- `storebound console plan <form> [--json] [--lookup]`: read-only plan for an AI agent that drives the browser itself: start URL (deep links), ordered steps, answer sheet with the console's exact labels (certain / ask owner, curly quotes noted), never-press list, verified UI facts, driving guidance (in-page async loop + window.__log), verify instructions. All six forms. - `storebound console verify <form> [--from-text <file|->]`: App Privacy per-type summaries from page text, Play Create app from input states, content rating / target audience summaries, App Store record and age rating from the API; exit 1 on a mismatch. - MCP: console_plan, console_verify (read-only); console fill stays off MCP. - App Privacy (verified 2026-10-12): two information steps, unlabeled purpose checkboxes (nearest parent text), "Definitions and Examples" never pressed; fixture and engine follow. - Play Create app (verified 2026-10-12): /developers/<id>/create-new-app, App package name + read-only Check availability, material-radio inner [role=radio] click, app dashboard URL and play.appId, service account "Add app" as an owner step. - console-autofill skill rewritten agent-first; agents-core rule 10; README; pitfalls 12, 18 (confirmed sign-out), 19; CHANGELOG; play-first-release.
39 lines
2.7 KiB
TypeScript
39 lines
2.7 KiB
TypeScript
// The agent-first console mode: storebound supplies the knowledge, the calling AI agent drives the browser.
|
|
// storebound console plan lists the forms
|
|
// storebound console plan <form> [--json] [--lookup]
|
|
// Read-only. Offline by default: the start URL, the ordered steps, the answer sheet (each answer certain or "ask
|
|
// owner", with the console's own labels), the never-press list, the known UI facts and how to verify. Deep links use
|
|
// apple.appId / play.developerId / play.appId, the ids cached by earlier runs (.storebound/console-app-ids.json,
|
|
// ~/.storebound/console-accounts.json) and the workspace's account ids; --lookup also asks the App Store Connect API
|
|
// for the app id by bundle id (a GET; needs the API key). Pure logic in cli/lib/console-plan.ts. MCP: console_plan.
|
|
import type { Ctx } from '../lib/ctx';
|
|
import { FORM_IDS, formMeta, isForm } from '../lib/console-answers';
|
|
import { consolePlan, type PlanIds, planText } from '../lib/console-plan';
|
|
import { printJson } from '../lib/log';
|
|
|
|
export async function run(ctx: Ctx): Promise<void> {
|
|
const { config, root } = ctx.loaded;
|
|
const args = ctx.args, json = args.has('json');
|
|
const form = args._[0];
|
|
if (!form) {
|
|
const forms = FORM_IDS.map(id => { const m = formMeta(id, config); return { id, store: m.store, title: m.title, fillable: m.fillable }; });
|
|
if (json) return printJson({ forms });
|
|
console.log('storebound console plan <form> [--json] [--lookup] (then drive the page yourself; `storebound console verify <form>` checks it)\n');
|
|
for (const f of forms) console.log(` ${f.id.padEnd(22)} ${f.store.padEnd(6)} ${f.title}${f.fillable ? '' : ' (guide only)'}`);
|
|
return;
|
|
}
|
|
if (!isForm(form)) throw new Error(`console plan: unknown form "${form}" (one of ${FORM_IDS.join(', ')})`);
|
|
const { withAccountIds, readAccounts } = await import('./accounts');
|
|
const cfg = withAccountIds(config);
|
|
const pkg = cfg.play?.packageName;
|
|
const cached = pkg ? readAccounts().play[pkg] : undefined;
|
|
const ids: PlanIds = { playDeveloperId: cfg.play?.developerId ?? cached?.developerId ?? null, playAppId: cfg.play?.appId ?? cached?.appId ?? null };
|
|
if (form.startsWith('apple-') && !cfg.apple?.appId && cfg.apple?.bundleId) {
|
|
const { appleAppId } = await import('./app-id');
|
|
// without --lookup only the cache is read: the lookup refuses, so no request is made
|
|
ids.appleAppId = await appleAppId(root, cfg, { say: () => { /* the plan's start says what it found */ }, ...(args.has('lookup') ? {} : { lookup: async () => { throw new Error('offline (add --lookup to ask the API)'); } }) });
|
|
}
|
|
const plan = consolePlan(form, cfg, ids);
|
|
if (json) return printJson(plan);
|
|
console.log(planText(plan));
|
|
}
|