@rosthq/cli 0.7.123 → 0.7.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/dist/commands/onboarding.d.ts +24 -2
- package/dist/commands/onboarding.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +829 -525
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -52051,7 +52051,7 @@ var referenceDocuments = [
|
|
|
52051
52051
|
order: 10,
|
|
52052
52052
|
title: "{{brand}} implementation method",
|
|
52053
52053
|
summary: "The staged operating-system setup path used by humans, CLI sessions, MCP clients, and in-app agents.",
|
|
52054
|
-
version: "2026-07-
|
|
52054
|
+
version: "2026-07-30.1",
|
|
52055
52055
|
public: true,
|
|
52056
52056
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
52057
52057
|
stages: ["company_setup", "graph_design", "charter_design", "staffing", "operating_rhythm"],
|
|
@@ -52180,6 +52180,8 @@ The Compass is drafted, then activated by a human through supersession.
|
|
|
52180
52180
|
|
|
52181
52181
|
\`onboarding.setup\`, \`onboarding.finish\`, \`compass.approve_version\`, \`compass.reject_draft\`, and \`compass.set\` are \`human_required\`. \`onboarding.source_ingest\` is a bootstrap-safe \`none\` prerequisite that retains bounded source bytes encrypted under the exact tenant/run, computes its digest and canonical parser manifest server-side, and remains permanently outside Trusted and Full Operator. \`onboarding.setup\` is the one-approval composite apply: it freezes the complete plan and live proof at staging, then rechecks them and applies Compass, cycle, Responsibility Graph, Charters, staffing, goals, Signals/readings, Frictions, tasks, and Sync scope in one transaction. A failure rolls back the entire application and leaves the confirmation pending.
|
|
52182
52182
|
|
|
52183
|
+
The whole composite flow has first-class CLI verbs: \`{{cli}} onboard source-ingest --file <path> ...\` for each allowed local source, \`{{cli}} onboard setup --input-file <plan.json>\` to stage the one owner approval (it prints the confirmation id and exact approval URL), \`{{cli}} onboard setup-status --input-file <plan.json>\` to discover the applied receipt by idempotent re-submission of the identical plan, then \`{{cli}} onboard rehearse\` and \`{{cli}} onboard activate\`. Each authenticates with the implementation-bootstrap credential first and falls back to the user session; the generic \`{{cli}} command <id> --json\` path and the generated MCP tools expose the same schemas.
|
|
52184
|
+
|
|
52183
52185
|
After setup succeeds, call \`onboarding.rehearse\` with the exact setup application, expected setup digest/revision, and a caller idempotency key. This is the implementation principal's one bounded \`execute\` exception: it is ungated because it can run only the setup receipt's exact agents in the sandbox, with no schedule arming, go-live transition, credential access, source mutation, or external communication. It rechecks the current Charter manifest, pinned published Skill versions and content hashes, schedule, execution lane, and canonical configuration digest under the same tenant/run boundary. A complete batch returns an immutable terminal batch receipt plus one immutable per-agent receipt with nonzero checked counts, runtime run ids, bounded tool previews/manifest holds/errors, and \`passed\` or \`failed\` status. Same-key/same-configuration retry returns that terminal evidence; a changed configuration conflicts instead of silently reusing it. The rehearsal never returns an approval URL and never stages activation. The later, separate \`onboarding.activate\` command consumes that exact terminal batch and the unique run/configuration evidence for the setup receipt's complete agent set. It stages one owner approval whose durable card shows every agent, Seat, Charter/configuration digest, rehearsal run, effective lane/model, permissions, schedule, warnings, and the onboarding-completion effect. Approval rechecks the full projection, records one composite human decision, makes every agent live, arms eligible schedules, and completes onboarding atomically. Any stale or failed member rolls the transaction back; same-key retry returns the committed receipt without duplicating effects.
|
|
52184
52186
|
|
|
52185
52187
|
\`onboarding.advance_step\`, \`onboarding.create_invite\`, \`onboarding.attach_reference\`, \`compass.answer_gap\`, and drafting a Compass are \`none\` \u2014 none of them returns a pending confirmation. \`none\` is not the same as "agent-callable", though: \`onboarding.create_invite\` and \`compass.answer_gap\` record the human who ran them, so they run as a person, not from an agent session, while advancing a step, attaching a reference, drafting a Compass, and exact-run source ingestion are safe for the bootstrap agent. Approving a version (a supersession) is a human act. The agent drafts and surfaces the approve link. See the confirmations guide.
|
|
@@ -53320,7 +53322,7 @@ External connectors are being rolled out provider by provider, conservatively (r
|
|
|
53320
53322
|
order: 48,
|
|
53321
53323
|
title: "CLI and MCP installation guide",
|
|
53322
53324
|
summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
|
|
53323
|
-
version: "2026-07-
|
|
53325
|
+
version: "2026-07-30.1",
|
|
53324
53326
|
public: true,
|
|
53325
53327
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
53326
53328
|
stages: ["company_setup", "staffing"],
|
|
@@ -53844,11 +53846,28 @@ These are the security posture rules for operating after install \u2014 a checkl
|
|
|
53844
53846
|
|
|
53845
53847
|
### Onboarding
|
|
53846
53848
|
|
|
53849
|
+
\`\`\`text
|
|
53850
|
+
{{cli}} onboard status
|
|
53851
|
+
{{cli}} onboard resume
|
|
53852
|
+
{{cli}} onboard run
|
|
53853
|
+
{{cli}} onboard source-ingest --file <path> --source-key <key> --kind <kind> --title <title> [--json]
|
|
53854
|
+
{{cli}} onboard setup --input '<json-plan>' | --input-file <path> [--json]
|
|
53855
|
+
{{cli}} onboard setup-status --input '<json-plan>' | --input-file <path> [--json]
|
|
53856
|
+
{{cli}} onboard rehearse|activate --setup-application-id <uuid> ... [--json]
|
|
53857
|
+
\`\`\`
|
|
53858
|
+
|
|
53859
|
+
Every tenant-scoped \`onboard\` verb (\`status\`, \`resume\`, \`source-ingest\`, \`setup\`, \`setup-status\`, \`rehearse\`, \`activate\` \u2014 \`onboard run\` is an offline public print) authenticates with an existing implementation-bootstrap credential first and falls back to the user session, so the agent-led composite flow works without a personal login. \`onboard source-ingest\` reads one local business file client-side, base64-encodes it, and calls \`onboarding.source_ingest\`; the server computes the digest and family manifest and returns the opaque \`source_ref\` to reference from the setup plan's \`sources[]\` (paths and client digests are rejected). The server's 1 MiB command-body cap is authoritative, and base64 expands content by 4/3, so the largest file reachable through this command today is about 780 KB \u2014 the CLI pre-checks and names the exact fitting size; split a larger export. \`onboard setup\` submits the complete declarative plan to \`onboarding.setup\`: staging succeeds with exit code 0 and prints the pending confirmation id plus the exact approval URL (with \`--json\`, the full pending-confirmation object). \`onboard setup-status\` re-submits the identical plan to discover state through the command's idempotent contract: after approval it returns the immutable applied receipt (application id, receipt revision, input digest) without staging anything; while approval is still pending it returns the current approval card \u2014 an identical still-valid card is reused with the same confirmation id and URL, and only a changed server-derived projection supersedes the stale card and mints a fresh one. After application, a same-key re-submission with a different plan digest is a typed conflict.
|
|
53860
|
+
|
|
53847
53861
|
| Command | Purpose | Scope | Safe example |
|
|
53848
53862
|
|---|---|---|---|
|
|
53849
53863
|
| \`{{cli}} onboard status\` | Return onboarding progress, graph summary, and next actions. | Tenant | \`{{cli}} onboard status\` |
|
|
53850
53864
|
| \`{{cli}} onboard resume\` | Resume the guided onboarding flow where it left off. | Tenant | \`{{cli}} onboard resume\` |
|
|
53851
53865
|
| \`{{cli}} onboard run\` | Print the deterministic agent onboarding prompt. | Public reference | \`{{cli}} onboard run\` |
|
|
53866
|
+
| \`{{cli}} onboard source-ingest\` | Retain one bounded local business source (encrypted, tenant/run-bound) via \`onboarding.source_ingest\` and print the opaque \`source_ref\` for the setup plan. | Tenant (implementation bootstrap or owner) | \`{{cli}} onboard source-ingest --file org-chart.csv --source-key org-chart --kind org_chart --title "Org chart" --json\` |
|
|
53867
|
+
| \`{{cli}} onboard setup\` | Stage the one-approval composite onboarding setup via \`onboarding.setup\`; prints the pending confirmation id and exact approval URL, or the applied receipt on an identical re-submission. | Tenant (implementation bootstrap or owner) | \`{{cli}} onboard setup --input-file setup-plan.json --json\` |
|
|
53868
|
+
| \`{{cli}} onboard setup-status\` | Discover the setup application state by idempotent re-submission of the identical plan: applied receipt after approval; while pending, the current approval card (an identical card is reused, same id and URL). | Tenant (implementation bootstrap or owner) | \`{{cli}} onboard setup-status --input-file setup-plan.json --json\` |
|
|
53869
|
+
| \`{{cli}} onboard rehearse\` | Run the applied setup receipt's agents through the resumable sandbox-only rehearsal batch via \`onboarding.rehearse\`; returns immutable terminal evidence, never an activation approval URL. | Tenant (implementation bootstrap or owner) | \`{{cli}} onboard rehearse --setup-application-id <uuid> --expected-input-digest <sha256:digest> --expected-receipt-revision 1 --idempotency-key rehearse-1 --json\` |
|
|
53870
|
+
| \`{{cli}} onboard activate\` | Stage the one post-rehearsal owner approval via \`onboarding.activate\` with the exact unique-agent-ID rehearsal and configuration evidence arrays; it alone stages the activation URL. | Tenant (implementation bootstrap or owner) | \`{{cli}} onboard activate --setup-application-id <uuid> --expected-input-digest <sha256:digest> --expected-receipt-revision 1 --terminal-rehearsal-batch-receipt-id <uuid> --rehearsal-runs '[...]' --configuration-digests '[...]' --idempotency-key activate-1 --json\` |
|
|
53852
53871
|
| \`{{cli}} init [--client claude-code|codex|cursor] (defaults --scope tenant-admin)\` | Log in when needed, install MCP, and print the onboarding prompt. As the first-run helper it defaults to a tenant-admin token (no seats exist yet); pass \`--scope seat --seat-id <id>\` to scope it narrower. | User plus tenant | \`{{cli}} init --client codex\` |
|
|
53853
53872
|
| \`{{cli}} init --tenant <tenant> --client <client>\` | Select a tenant before MCP install. | User plus tenant | \`{{cli}} init --tenant acme-ops --client cursor\` |
|
|
53854
53873
|
|
|
@@ -53890,7 +53909,7 @@ These ergonomic wrappers (including the \`{{cli}} agent\` group) require **{{cli
|
|
|
53890
53909
|
|
|
53891
53910
|
**Generated verbs (0.6.0+).** Every registry command now has a first-class \`{{cli}} <namespace> <action>\` verb, projected directly from the command's input schema \u2014 so namespaces that previously had no ergonomic wrapper (for example \`{{cli}} measurable create\`, \`{{cli}} work_order enqueue\`, \`{{cli}} mcp_token create\`) are usable without dropping to the raw \`command <id>\` path. Flags follow the schema field names (\`--seat-id\`, \`--name\`, \u2026); read a command's exact input offline with \`{{cli}} <namespace> <action> --schema\` before calling it, and pass a nested payload with \`--input '<json>'\` when a field is a complex object. \`--json\` still selects machine output, \`--seat <id>\` still sets seat scope, and \`{{cli}} command <id> --json '<body>'\` remains the universal fallback.
|
|
53892
53911
|
|
|
53893
|
-
For a complete Seat, inspect \`{{cli}} seat create-complete --schema\`, then pass the strict nested request with \`{{cli}} seat create-complete --input '<json>' --json\`. The generic \`{{cli}} command seat.create_complete --json '<json>'\` path and the generated MCP tool \`rost_create_complete_seat\` expose the same registry schema and server-side command.
|
|
53912
|
+
For a complete Seat, inspect \`{{cli}} seat create-complete --schema\`, then pass the strict nested request with \`{{cli}} seat create-complete --input '<json>' --json\`. The generic \`{{cli}} command seat.create_complete --json '<json>'\` path and the generated MCP tool \`rost_create_complete_seat\` expose the same registry schema and server-side command. \`seat create-complete\` authenticates with an existing implementation-bootstrap credential first (it is one of the vetted bootstrap staging primitives) and falls back to the user session. Staging surfaces as the CLI's confirmation-required envelope: a \`COMMAND_CONFIRMATION_REQUIRED\` JSON object on stderr, exit code 3, whose \`details\` carry the pending confirmation id and the exact approval URL (\`details.approveVia.webUrl\`) \u2014 read the URL from there; the command has done its job at that point. The human owner reviews one card covering the Seat, canonical Charter and permission manifest, disclosed staffing, effective agent lane/readiness, exact pinned Skill versions and dependency state, and schedule. Approval applies the proposal in one transaction and returns its application and receipt ids. Any failure rolls back the whole proposal. An optional agent remains in \`dry_run\`; this command never approves go-live. Direct calls use existing parent and Steward Seat ids\u2014logical references are reserved for the later composite onboarding flow. Retained source ingestion is not available on this direct command yet, so \`sources\` and every \`source_uses\` collection must be empty and planned staffing must omit \`source_ref\`; the command rejects source-backed provenance instead of accepting an unverified upload id or caller-supplied digest.
|
|
53894
53913
|
|
|
53895
53914
|
The signed-in app exposes the same Skill command surface at **Skills**, linked from the Agents page (the nav collapse moved it out of the primary sidebar). Use \`/skills\` to filter the tenant library, \`/skills/new\` to build canonical \`SKILL.md\` frontmatter with \`tool.catalog\` dependencies, \`/skills/import\` for bounded GitHub or upload imports, and each Skill detail page to review validation, publish, check Seat dependencies, and assign a published version. During \`/agents/new\`, \`agent_setup.get\` can return \`next_action: "choose_skills"\`; selected Skills are proposed immutable-version assignments and required Skill tools block sign-off/go-live until tool configuration is ready.
|
|
53896
53915
|
|
|
@@ -57245,6 +57264,19 @@ function renderImplementationAccessNote() {
|
|
|
57245
57264
|
`${cliBrand.binName} onboard resume`,
|
|
57246
57265
|
"```",
|
|
57247
57266
|
"",
|
|
57267
|
+
"The agent-led composite setup flow has first-class verbs that authenticate with this credential first and fall back to the user session:",
|
|
57268
|
+
"",
|
|
57269
|
+
"```bash",
|
|
57270
|
+
`${cliBrand.binName} onboard source-ingest --file <path> --source-key <key> --kind <kind> --title <title> --json`,
|
|
57271
|
+
`${cliBrand.binName} onboard setup --input-file <plan.json> --json`,
|
|
57272
|
+
`${cliBrand.binName} onboard setup-status --input-file <plan.json> --json`,
|
|
57273
|
+
`${cliBrand.binName} onboard rehearse --setup-application-id <uuid> --expected-input-digest <sha256:digest> --expected-receipt-revision <n> --idempotency-key <key> --json`,
|
|
57274
|
+
`${cliBrand.binName} onboard activate --setup-application-id <uuid> ... --json`,
|
|
57275
|
+
`${cliBrand.binName} seat create-complete --input '<json>' --json`,
|
|
57276
|
+
"```",
|
|
57277
|
+
"",
|
|
57278
|
+
"`onboard setup` staging succeeds with exit code 0 and prints the pending confirmation id plus the exact approval URL; `onboard setup-status` re-submits the identical plan and returns the immutable applied receipt once the owner has approved.",
|
|
57279
|
+
"",
|
|
57248
57280
|
"Register the same bearer with an MCP client through `implementation access install-mcp`:",
|
|
57249
57281
|
"",
|
|
57250
57282
|
"```bash",
|
|
@@ -57989,508 +58021,7 @@ function parseSemver(value) {
|
|
|
57989
58021
|
}
|
|
57990
58022
|
|
|
57991
58023
|
// src/commands/onboarding.ts
|
|
57992
|
-
|
|
57993
|
-
var ACTIVATE_USAGE = `${cliBrand.binName} onboard activate --setup-application-id <uuid> --expected-input-digest <sha256:digest> --expected-receipt-revision <integer> --terminal-rehearsal-batch-receipt-id <uuid> --rehearsal-runs '<json-array>' --configuration-digests '<json-array>' --idempotency-key <key> [--json]`;
|
|
57994
|
-
var OnboardingUsageError = class extends Error {
|
|
57995
|
-
constructor(message) {
|
|
57996
|
-
super(message);
|
|
57997
|
-
this.name = "OnboardingUsageError";
|
|
57998
|
-
}
|
|
57999
|
-
};
|
|
58000
|
-
async function runOnboarding(args, io, deps) {
|
|
58001
|
-
let invocation;
|
|
58002
|
-
try {
|
|
58003
|
-
invocation = parseOnboardingInvocation(args);
|
|
58004
|
-
} catch (error51) {
|
|
58005
|
-
if (!(error51 instanceof OnboardingUsageError)) {
|
|
58006
|
-
throw error51;
|
|
58007
|
-
}
|
|
58008
|
-
io.stderr.write(`${error51.message}
|
|
58009
|
-
${onboardingUsage()}
|
|
58010
|
-
`);
|
|
58011
|
-
return 1;
|
|
58012
|
-
}
|
|
58013
|
-
const client = await deps.makeClient();
|
|
58014
|
-
try {
|
|
58015
|
-
const result = await client.execute(invocation.commandId, invocation.body);
|
|
58016
|
-
const rendered = invocation.json ? JSON.stringify(result.output, null, 2) : formatOnboardingOutput(invocation.action, result.output);
|
|
58017
|
-
io.stdout.write(`${rendered}
|
|
58018
|
-
`);
|
|
58019
|
-
return 0;
|
|
58020
|
-
} catch (error51) {
|
|
58021
|
-
return printCommandError(io, error51);
|
|
58022
|
-
}
|
|
58023
|
-
}
|
|
58024
|
-
function parseOnboardingInvocation(args) {
|
|
58025
|
-
const action = args[0];
|
|
58026
|
-
if (action === "status" || action === "resume") {
|
|
58027
|
-
return {
|
|
58028
|
-
commandId: action === "status" ? "onboarding.status" : "onboarding.resume",
|
|
58029
|
-
body: {},
|
|
58030
|
-
json: args.includes("--json"),
|
|
58031
|
-
action
|
|
58032
|
-
};
|
|
58033
|
-
}
|
|
58034
|
-
if (action !== "rehearse" && action !== "activate") {
|
|
58035
|
-
throw new OnboardingUsageError(`Unknown onboard action: ${action ?? "(missing)"}`);
|
|
58036
|
-
}
|
|
58037
|
-
const allowed = /* @__PURE__ */ new Set([
|
|
58038
|
-
"setup-application-id",
|
|
58039
|
-
"expected-input-digest",
|
|
58040
|
-
"expected-receipt-revision",
|
|
58041
|
-
"idempotency-key",
|
|
58042
|
-
...action === "activate" ? [
|
|
58043
|
-
"terminal-rehearsal-batch-receipt-id",
|
|
58044
|
-
"rehearsal-runs",
|
|
58045
|
-
"configuration-digests"
|
|
58046
|
-
] : []
|
|
58047
|
-
]);
|
|
58048
|
-
const values = /* @__PURE__ */ new Map();
|
|
58049
|
-
let json2 = false;
|
|
58050
|
-
for (let index = 1; index < args.length; index += 1) {
|
|
58051
|
-
const argument = args[index];
|
|
58052
|
-
if (argument === "--json") {
|
|
58053
|
-
if (json2) {
|
|
58054
|
-
throw new OnboardingUsageError("Duplicate --json flag.");
|
|
58055
|
-
}
|
|
58056
|
-
json2 = true;
|
|
58057
|
-
continue;
|
|
58058
|
-
}
|
|
58059
|
-
if (argument === void 0 || !argument.startsWith("--")) {
|
|
58060
|
-
throw new OnboardingUsageError(`Unexpected argument: ${argument ?? "(missing)"}`);
|
|
58061
|
-
}
|
|
58062
|
-
const key = argument.slice(2);
|
|
58063
|
-
if (!allowed.has(key)) {
|
|
58064
|
-
throw new OnboardingUsageError(`Unknown flag: --${key}`);
|
|
58065
|
-
}
|
|
58066
|
-
if (values.has(key)) {
|
|
58067
|
-
throw new OnboardingUsageError(`Duplicate --${key} flag.`);
|
|
58068
|
-
}
|
|
58069
|
-
const value = args[index + 1];
|
|
58070
|
-
if (value === void 0 || value.startsWith("--")) {
|
|
58071
|
-
throw new OnboardingUsageError(`Missing required --${key} value.`);
|
|
58072
|
-
}
|
|
58073
|
-
values.set(key, value);
|
|
58074
|
-
index += 1;
|
|
58075
|
-
}
|
|
58076
|
-
const requiredValue2 = (key) => {
|
|
58077
|
-
const value = values.get(key);
|
|
58078
|
-
if (value === void 0 || value.length === 0) {
|
|
58079
|
-
throw new OnboardingUsageError(`Missing required --${key} value.`);
|
|
58080
|
-
}
|
|
58081
|
-
return value;
|
|
58082
|
-
};
|
|
58083
|
-
const setupApplicationId = requiredValue2("setup-application-id");
|
|
58084
|
-
const expectedInputDigest = requiredValue2("expected-input-digest");
|
|
58085
|
-
const revisionRaw = requiredValue2("expected-receipt-revision");
|
|
58086
|
-
const idempotencyKey = requiredValue2("idempotency-key");
|
|
58087
|
-
const expectedReceiptRevision = Number(revisionRaw);
|
|
58088
|
-
if (!Number.isSafeInteger(expectedReceiptRevision) || expectedReceiptRevision <= 0) {
|
|
58089
|
-
throw new OnboardingUsageError("--expected-receipt-revision must be a positive integer.");
|
|
58090
|
-
}
|
|
58091
|
-
const sharedBody = {
|
|
58092
|
-
setup_application_id: setupApplicationId,
|
|
58093
|
-
expected_input_digest: expectedInputDigest,
|
|
58094
|
-
expected_receipt_revision: expectedReceiptRevision,
|
|
58095
|
-
idempotency_key: idempotencyKey
|
|
58096
|
-
};
|
|
58097
|
-
if (action === "activate") {
|
|
58098
|
-
return {
|
|
58099
|
-
commandId: "onboarding.activate",
|
|
58100
|
-
body: {
|
|
58101
|
-
...sharedBody,
|
|
58102
|
-
terminal_rehearsal_batch_receipt_id: requiredValue2(
|
|
58103
|
-
"terminal-rehearsal-batch-receipt-id"
|
|
58104
|
-
),
|
|
58105
|
-
rehearsal_runs: parseJsonArrayFlag(
|
|
58106
|
-
"rehearsal-runs",
|
|
58107
|
-
requiredValue2("rehearsal-runs")
|
|
58108
|
-
),
|
|
58109
|
-
configuration_digests: parseJsonArrayFlag(
|
|
58110
|
-
"configuration-digests",
|
|
58111
|
-
requiredValue2("configuration-digests")
|
|
58112
|
-
)
|
|
58113
|
-
},
|
|
58114
|
-
json: json2,
|
|
58115
|
-
action
|
|
58116
|
-
};
|
|
58117
|
-
}
|
|
58118
|
-
return {
|
|
58119
|
-
commandId: "onboarding.rehearse",
|
|
58120
|
-
body: sharedBody,
|
|
58121
|
-
json: json2,
|
|
58122
|
-
action
|
|
58123
|
-
};
|
|
58124
|
-
}
|
|
58125
|
-
function onboardingUsage() {
|
|
58126
|
-
return [
|
|
58127
|
-
`Usage: ${cliBrand.binName} onboard status|resume [--json]`,
|
|
58128
|
-
` ${REHEARSE_USAGE}`,
|
|
58129
|
-
` ${ACTIVATE_USAGE}`
|
|
58130
|
-
].join("\n");
|
|
58131
|
-
}
|
|
58132
|
-
function formatOnboardingOutput(action, output) {
|
|
58133
|
-
if (action === "rehearse") {
|
|
58134
|
-
return formatRehearsalOutput(output);
|
|
58135
|
-
}
|
|
58136
|
-
if (action === "activate") {
|
|
58137
|
-
return formatActivationOutput(output);
|
|
58138
|
-
}
|
|
58139
|
-
const record2 = typeof output === "object" && output !== null ? output : {};
|
|
58140
|
-
if (typeof record2.summary === "string") {
|
|
58141
|
-
return record2.summary;
|
|
58142
|
-
}
|
|
58143
|
-
return JSON.stringify(output, null, 2);
|
|
58144
|
-
}
|
|
58145
|
-
function parseJsonArrayFlag(flag, value) {
|
|
58146
|
-
try {
|
|
58147
|
-
const parsed = JSON.parse(value);
|
|
58148
|
-
if (!Array.isArray(parsed)) {
|
|
58149
|
-
throw new Error("not an array");
|
|
58150
|
-
}
|
|
58151
|
-
return parsed;
|
|
58152
|
-
} catch {
|
|
58153
|
-
throw new OnboardingUsageError(`--${flag} must be a valid JSON array.`);
|
|
58154
|
-
}
|
|
58155
|
-
}
|
|
58156
|
-
function formatActivationOutput(output) {
|
|
58157
|
-
const record2 = asRecord(output);
|
|
58158
|
-
const approveVia = asRecord(record2.approveVia);
|
|
58159
|
-
if (typeof approveVia.webUrl === "string") {
|
|
58160
|
-
return [
|
|
58161
|
-
"Onboarding activation approval is ready.",
|
|
58162
|
-
`Approve once: ${approveVia.webUrl}`
|
|
58163
|
-
].join("\n");
|
|
58164
|
-
}
|
|
58165
|
-
const receipt = asRecord(record2.receipt);
|
|
58166
|
-
const agents = Array.isArray(receipt.agents) ? receipt.agents : [];
|
|
58167
|
-
if (record2.status === "activated") {
|
|
58168
|
-
return [
|
|
58169
|
-
"Onboarding activation completed.",
|
|
58170
|
-
`Activation receipt: ${field(receipt, "activation_receipt_id")}`,
|
|
58171
|
-
`Agents live: ${agents.length} of ${agents.length}`,
|
|
58172
|
-
`Onboarding completed: ${field(receipt, "onboarding_completed_at")}`
|
|
58173
|
-
].join("\n");
|
|
58174
|
-
}
|
|
58175
|
-
return JSON.stringify(output, null, 2);
|
|
58176
|
-
}
|
|
58177
|
-
function formatRehearsalOutput(output) {
|
|
58178
|
-
const record2 = asRecord(output);
|
|
58179
|
-
if (record2.status === "in_progress") {
|
|
58180
|
-
const batch = asRecord(record2.batch);
|
|
58181
|
-
const checkpoints = Array.isArray(record2.checkpoints) ? record2.checkpoints : [];
|
|
58182
|
-
const completed = checkpoints.filter((checkpoint) => {
|
|
58183
|
-
const status = asRecord(checkpoint).status;
|
|
58184
|
-
return status === "passed" || status === "failed";
|
|
58185
|
-
}).length;
|
|
58186
|
-
return [
|
|
58187
|
-
"Onboarding rehearsal is in progress.",
|
|
58188
|
-
`Batch: ${field(batch, "batch_id")}`,
|
|
58189
|
-
`Checkpoints complete: ${completed} of ${checkpoints.length}`,
|
|
58190
|
-
...checkpoints.map((checkpoint) => {
|
|
58191
|
-
const item = asRecord(checkpoint);
|
|
58192
|
-
return `- Agent ${field(item, "agent_id")} / Seat ${field(item, "seat_id")}: ${field(item, "status")}`;
|
|
58193
|
-
}),
|
|
58194
|
-
"Retry with the same idempotency key to continue this batch."
|
|
58195
|
-
].join("\n");
|
|
58196
|
-
}
|
|
58197
|
-
if (record2.status === "passed" || record2.status === "failed") {
|
|
58198
|
-
return [
|
|
58199
|
-
`Onboarding rehearsal ${record2.status}.`,
|
|
58200
|
-
"Immutable batch receipt:",
|
|
58201
|
-
JSON.stringify(record2.batch_receipt, null, 2),
|
|
58202
|
-
"Immutable agent receipts:",
|
|
58203
|
-
JSON.stringify(record2.agent_receipts, null, 2)
|
|
58204
|
-
].join("\n");
|
|
58205
|
-
}
|
|
58206
|
-
return JSON.stringify(output, null, 2);
|
|
58207
|
-
}
|
|
58208
|
-
function asRecord(value) {
|
|
58209
|
-
return typeof value === "object" && value !== null ? value : {};
|
|
58210
|
-
}
|
|
58211
|
-
function field(record2, key) {
|
|
58212
|
-
const value = record2[key];
|
|
58213
|
-
return typeof value === "string" || typeof value === "number" ? String(value) : "\u2014";
|
|
58214
|
-
}
|
|
58215
|
-
function printCommandError(io, error51) {
|
|
58216
|
-
if (error51 instanceof CommandClientError && error51.response && !error51.response.ok) {
|
|
58217
|
-
const help = error51.response.error.help;
|
|
58218
|
-
const requestId = error51.response.requestId;
|
|
58219
|
-
io.stderr.write(redactForLog({
|
|
58220
|
-
code: error51.response.error.code,
|
|
58221
|
-
message: error51.response.error.message,
|
|
58222
|
-
...error51.response.error.details === void 0 ? {} : { details: error51.response.error.details },
|
|
58223
|
-
...help === void 0 ? {} : { help },
|
|
58224
|
-
...requestId === void 0 ? {} : { requestId }
|
|
58225
|
-
}));
|
|
58226
|
-
io.stderr.write("\n");
|
|
58227
|
-
if (help !== void 0) {
|
|
58228
|
-
io.stderr.write(`\u2192 try: ${redactForLog(help)}
|
|
58229
|
-
`);
|
|
58230
|
-
}
|
|
58231
|
-
if (error51.status === 409) {
|
|
58232
|
-
return 3;
|
|
58233
|
-
}
|
|
58234
|
-
return error51.status >= 400 && error51.status < 500 ? 1 : 2;
|
|
58235
|
-
}
|
|
58236
|
-
throw error51;
|
|
58237
|
-
}
|
|
58238
|
-
|
|
58239
|
-
// src/commands/implementation-access.ts
|
|
58240
|
-
var implementationCredentialSchema = external_exports.object({
|
|
58241
|
-
token: external_exports.string().regex(/^rost_impl_[A-Za-z0-9_-]+$/),
|
|
58242
|
-
token_id: external_exports.string().uuid(),
|
|
58243
|
-
tenant_id: external_exports.string().uuid(),
|
|
58244
|
-
implementation_run_id: external_exports.string().uuid(),
|
|
58245
|
-
scope: external_exports.literal("implementation_bootstrap"),
|
|
58246
|
-
expires_at: external_exports.string().datetime({ offset: true })
|
|
58247
|
-
}).strict();
|
|
58248
|
-
var ImplementationAccessError = class extends Error {
|
|
58249
|
-
constructor(message) {
|
|
58250
|
-
super(message);
|
|
58251
|
-
this.name = "ImplementationAccessError";
|
|
58252
|
-
}
|
|
58253
|
-
};
|
|
58254
|
-
var DEFAULT_SOURCE_CLIENT = "external-agent";
|
|
58255
|
-
var SOURCE_CLIENT_MAX_LENGTH = 80;
|
|
58256
|
-
async function runImplementationAccess(args, io, deps) {
|
|
58257
|
-
const json2 = args.includes("--json");
|
|
58258
|
-
const action = parseAction(args[0]);
|
|
58259
|
-
if (action === null) {
|
|
58260
|
-
io.stderr.write(
|
|
58261
|
-
`Usage: ${cliBrand.binName} implementation access start|status|complete|abandon [--json]
|
|
58262
|
-
`
|
|
58263
|
-
);
|
|
58264
|
-
return 1;
|
|
58265
|
-
}
|
|
58266
|
-
if (action === "start") {
|
|
58267
|
-
const sourceClient = parseSourceClient(args.slice(1), DEFAULT_SOURCE_CLIENT);
|
|
58268
|
-
return runStart(io, deps, sourceClient, json2);
|
|
58269
|
-
}
|
|
58270
|
-
const store = deps.createImplementationStore();
|
|
58271
|
-
const credential = await store.read();
|
|
58272
|
-
if (!credential) {
|
|
58273
|
-
io.stderr.write("No implementation credential. Run rost implementation access start.\n");
|
|
58274
|
-
return 1;
|
|
58275
|
-
}
|
|
58276
|
-
if (action === "status") {
|
|
58277
|
-
return runStatus(io, deps, credential, json2);
|
|
58278
|
-
}
|
|
58279
|
-
if (action === "complete") {
|
|
58280
|
-
return runComplete(io, deps, credential, store, json2);
|
|
58281
|
-
}
|
|
58282
|
-
return runAbandon(io, deps, credential, store, json2);
|
|
58283
|
-
}
|
|
58284
|
-
function parseAction(value) {
|
|
58285
|
-
if (value === "start" || value === "status" || value === "complete" || value === "abandon") {
|
|
58286
|
-
return value;
|
|
58287
|
-
}
|
|
58288
|
-
return null;
|
|
58289
|
-
}
|
|
58290
|
-
function parseSourceClient(args, defaultValue) {
|
|
58291
|
-
let sourceClient;
|
|
58292
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
58293
|
-
const arg = args[index];
|
|
58294
|
-
if (arg === "--source-client") {
|
|
58295
|
-
sourceClient = args[index + 1];
|
|
58296
|
-
if (sourceClient === void 0) {
|
|
58297
|
-
throw new ImplementationAccessError("--source-client requires a value.");
|
|
58298
|
-
}
|
|
58299
|
-
index += 1;
|
|
58300
|
-
}
|
|
58301
|
-
}
|
|
58302
|
-
const value = (sourceClient ?? defaultValue).trim();
|
|
58303
|
-
if (value.length === 0) {
|
|
58304
|
-
throw new ImplementationAccessError("--source-client cannot be blank.");
|
|
58305
|
-
}
|
|
58306
|
-
if (value.length > SOURCE_CLIENT_MAX_LENGTH) {
|
|
58307
|
-
throw new ImplementationAccessError(`--source-client must be ${SOURCE_CLIENT_MAX_LENGTH} characters or fewer.`);
|
|
58308
|
-
}
|
|
58309
|
-
return value;
|
|
58310
|
-
}
|
|
58311
|
-
function minimalConfig(appUrl2) {
|
|
58312
|
-
return {
|
|
58313
|
-
appUrl: appUrl2,
|
|
58314
|
-
supabaseUrl: "https://unused.example.test",
|
|
58315
|
-
supabaseAnonKey: "unused"
|
|
58316
|
-
};
|
|
58317
|
-
}
|
|
58318
|
-
async function runStart(io, deps, sourceClient, json2) {
|
|
58319
|
-
const store = deps.createImplementationStore();
|
|
58320
|
-
const credential = await deps.pollDeviceAuthorizationHandoff(
|
|
58321
|
-
minimalConfig(deps.appUrl),
|
|
58322
|
-
io,
|
|
58323
|
-
{
|
|
58324
|
-
purpose: "implementation_bootstrap",
|
|
58325
|
-
sourceClient,
|
|
58326
|
-
// DER-2158 (U3b) C3: `silent: json` still suppresses the poller's own
|
|
58327
|
-
// stdout print + browser open in --json mode, so stdout stays pure JSON
|
|
58328
|
-
// for a machine caller. But without a replacement, --json mode never
|
|
58329
|
-
// shows the verification URL/code at all — the command blocks until
|
|
58330
|
-
// approval and nobody ever saw the code to approve it, so it always
|
|
58331
|
-
// times out. `onStart` fires unconditionally (even when silent), so use
|
|
58332
|
-
// it to surface the same URL/code on STDERR instead. Never write the
|
|
58333
|
-
// bearer token here — the pre-approval StartSession doesn't carry one.
|
|
58334
|
-
silent: json2,
|
|
58335
|
-
...json2 ? { onStart: (session) => writeJsonStartPrompt(io, session) } : {}
|
|
58336
|
-
},
|
|
58337
|
-
{},
|
|
58338
|
-
(approved) => mapApprovedToCredential(approved)
|
|
58339
|
-
);
|
|
58340
|
-
await store.write(credential);
|
|
58341
|
-
if (json2) {
|
|
58342
|
-
io.stdout.write(
|
|
58343
|
-
`${JSON.stringify({
|
|
58344
|
-
status: "started",
|
|
58345
|
-
run_id: credential.implementation_run_id,
|
|
58346
|
-
tenant_id: credential.tenant_id,
|
|
58347
|
-
scope: credential.scope,
|
|
58348
|
-
expires_at: credential.expires_at,
|
|
58349
|
-
stored_in: store.describe()
|
|
58350
|
-
})}
|
|
58351
|
-
`
|
|
58352
|
-
);
|
|
58353
|
-
} else {
|
|
58354
|
-
io.stdout.write(
|
|
58355
|
-
`The implementation credential is stored in ${store.describe()} and expires at ${credential.expires_at}.
|
|
58356
|
-
`
|
|
58357
|
-
);
|
|
58358
|
-
}
|
|
58359
|
-
return 0;
|
|
58360
|
-
}
|
|
58361
|
-
function writeJsonStartPrompt(io, session) {
|
|
58362
|
-
io.stderr.write(
|
|
58363
|
-
[
|
|
58364
|
-
"To sign in, open this URL in any browser and approve the code:",
|
|
58365
|
-
` ${session.verification_uri}`,
|
|
58366
|
-
"",
|
|
58367
|
-
` Code: ${session.user_code}`,
|
|
58368
|
-
"",
|
|
58369
|
-
"Waiting for approval\u2026",
|
|
58370
|
-
""
|
|
58371
|
-
].join("\n")
|
|
58372
|
-
);
|
|
58373
|
-
}
|
|
58374
|
-
function mapApprovedToCredential(approved) {
|
|
58375
|
-
const raw = approved;
|
|
58376
|
-
const parsed = implementationCredentialSchema.safeParse({
|
|
58377
|
-
token: raw.token,
|
|
58378
|
-
token_id: raw.token_id,
|
|
58379
|
-
tenant_id: raw.tenant_id,
|
|
58380
|
-
implementation_run_id: raw.implementation_run_id,
|
|
58381
|
-
scope: raw.scope,
|
|
58382
|
-
expires_at: raw.expires_at
|
|
58383
|
-
});
|
|
58384
|
-
if (!parsed.success) {
|
|
58385
|
-
return null;
|
|
58386
|
-
}
|
|
58387
|
-
return parsed.data;
|
|
58388
|
-
}
|
|
58389
|
-
function createImplementationClient(deps, credential) {
|
|
58390
|
-
return new deps.CommandClient({
|
|
58391
|
-
appUrl: deps.appUrl,
|
|
58392
|
-
token: credential.token,
|
|
58393
|
-
credentialKind: "implementation_bootstrap"
|
|
58394
|
-
});
|
|
58395
|
-
}
|
|
58396
|
-
function isDeadRunError(error51) {
|
|
58397
|
-
if (!(error51 instanceof CommandClientError) || !error51.response || error51.response.ok) {
|
|
58398
|
-
return false;
|
|
58399
|
-
}
|
|
58400
|
-
if (error51.status === 401) {
|
|
58401
|
-
return true;
|
|
58402
|
-
}
|
|
58403
|
-
const code = error51.response.error.code;
|
|
58404
|
-
return code === "COMMAND_AUTHORIZATION" || code === "COMMAND_UNAUTHENTICATED" || /expired/i.test(error51.response.error.message);
|
|
58405
|
-
}
|
|
58406
|
-
async function runStatus(io, deps, credential, json2) {
|
|
58407
|
-
const client = createImplementationClient(deps, credential);
|
|
58408
|
-
try {
|
|
58409
|
-
const result = await client.execute("implementation_access.status", {});
|
|
58410
|
-
if (json2) {
|
|
58411
|
-
io.stdout.write(`${JSON.stringify(result.output)}
|
|
58412
|
-
`);
|
|
58413
|
-
} else {
|
|
58414
|
-
io.stdout.write(`${redactForLog(formatStatusSummary(result.output))}
|
|
58415
|
-
`);
|
|
58416
|
-
}
|
|
58417
|
-
return 0;
|
|
58418
|
-
} catch (error51) {
|
|
58419
|
-
if (isDeadRunError(error51)) {
|
|
58420
|
-
io.stderr.write(
|
|
58421
|
-
"The implementation run is no longer active. Start a new one: rost implementation access start\n"
|
|
58422
|
-
);
|
|
58423
|
-
return 1;
|
|
58424
|
-
}
|
|
58425
|
-
io.stderr.write(`${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
|
|
58426
|
-
`);
|
|
58427
|
-
return 1;
|
|
58428
|
-
}
|
|
58429
|
-
}
|
|
58430
|
-
function formatStatusSummary(output) {
|
|
58431
|
-
const record2 = typeof output === "object" && output !== null ? output : {};
|
|
58432
|
-
const status = typeof record2.status === "string" ? record2.status : "unknown";
|
|
58433
|
-
const runId = typeof record2.run_id === "string" ? record2.run_id : "unknown";
|
|
58434
|
-
return `Implementation run ${runId} status: ${status}.`;
|
|
58435
|
-
}
|
|
58436
|
-
async function runComplete(io, deps, credential, store, json2) {
|
|
58437
|
-
const client = createImplementationClient(deps, credential);
|
|
58438
|
-
try {
|
|
58439
|
-
const result = await client.execute("implementation_access.complete", {});
|
|
58440
|
-
await store.clear();
|
|
58441
|
-
if (json2) {
|
|
58442
|
-
io.stdout.write(
|
|
58443
|
-
`${JSON.stringify({
|
|
58444
|
-
status: "completed",
|
|
58445
|
-
run_id: credential.implementation_run_id,
|
|
58446
|
-
already_closed: result.output?.already_closed ?? false
|
|
58447
|
-
})}
|
|
58448
|
-
`
|
|
58449
|
-
);
|
|
58450
|
-
} else {
|
|
58451
|
-
io.stdout.write("Implementation run completed and the local credential was cleared.\n");
|
|
58452
|
-
}
|
|
58453
|
-
return 0;
|
|
58454
|
-
} catch (error51) {
|
|
58455
|
-
io.stderr.write(`${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
|
|
58456
|
-
`);
|
|
58457
|
-
io.stderr.write("The credential was kept. Retry with: rost implementation access complete\n");
|
|
58458
|
-
return 1;
|
|
58459
|
-
}
|
|
58460
|
-
}
|
|
58461
|
-
async function runAbandon(io, deps, credential, store, json2) {
|
|
58462
|
-
const client = createImplementationClient(deps, credential);
|
|
58463
|
-
try {
|
|
58464
|
-
const result = await client.execute("implementation_access.abandon", {});
|
|
58465
|
-
await store.clear();
|
|
58466
|
-
if (json2) {
|
|
58467
|
-
io.stdout.write(
|
|
58468
|
-
`${JSON.stringify({
|
|
58469
|
-
status: "abandoned",
|
|
58470
|
-
run_id: credential.implementation_run_id,
|
|
58471
|
-
already_closed: result.output?.already_closed ?? false
|
|
58472
|
-
})}
|
|
58473
|
-
`
|
|
58474
|
-
);
|
|
58475
|
-
} else {
|
|
58476
|
-
io.stdout.write("Implementation run abandoned and the local credential was cleared.\n");
|
|
58477
|
-
}
|
|
58478
|
-
return 0;
|
|
58479
|
-
} catch (error51) {
|
|
58480
|
-
io.stderr.write(`${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
|
|
58481
|
-
`);
|
|
58482
|
-
io.stderr.write("The credential was kept. Retry with: rost implementation access abandon\n");
|
|
58483
|
-
return 1;
|
|
58484
|
-
}
|
|
58485
|
-
}
|
|
58486
|
-
function defaultImplementationAccessDeps(appUrl2) {
|
|
58487
|
-
return {
|
|
58488
|
-
appUrl: appUrl2,
|
|
58489
|
-
createImplementationStore: createImplementationCredentialStore,
|
|
58490
|
-
pollDeviceAuthorizationHandoff,
|
|
58491
|
-
CommandClient
|
|
58492
|
-
};
|
|
58493
|
-
}
|
|
58024
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
58494
58025
|
|
|
58495
58026
|
// src/generated/command-manifest.ts
|
|
58496
58027
|
var COMMAND_MANIFEST = [
|
|
@@ -58791,6 +58322,738 @@ var COMMAND_MANIFEST = [
|
|
|
58791
58322
|
{ "id": "work.record", "namespace": "work", "action": "record", "title": "Record work", "description": "Append one or more structured business-activity records to the agent work ledger for the acting seat. Batch-accepting, append-only, secret-redacted, and idempotent on dedup_key. Corrections are superseding records.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": true, "help": "Append structured business-activity records (verb + entity refs + outcome + evidence) to the seat's work ledger, in a batch, right after each action succeeds." }
|
|
58792
58323
|
];
|
|
58793
58324
|
|
|
58325
|
+
// src/commands/onboarding.ts
|
|
58326
|
+
var REHEARSE_USAGE = `${cliBrand.binName} onboard rehearse --setup-application-id <uuid> --expected-input-digest <sha256:digest> --expected-receipt-revision <integer> --idempotency-key <key> [--json]`;
|
|
58327
|
+
var ACTIVATE_USAGE = `${cliBrand.binName} onboard activate --setup-application-id <uuid> --expected-input-digest <sha256:digest> --expected-receipt-revision <integer> --terminal-rehearsal-batch-receipt-id <uuid> --rehearsal-runs '<json-array>' --configuration-digests '<json-array>' --idempotency-key <key> [--json]`;
|
|
58328
|
+
var SOURCE_INGEST_USAGE = `${cliBrand.binName} onboard source-ingest --file <path> --source-key <key> --kind <kind> --title <title> [--json]`;
|
|
58329
|
+
var SERVER_COMMAND_BODY_CAP_BYTES = 1048576;
|
|
58330
|
+
var COMMAND_BODY_SAFETY_MARGIN_BYTES = 4096;
|
|
58331
|
+
var SETUP_USAGE = `${cliBrand.binName} onboard setup --input '<json-plan>' | --input-file <path> [--json]`;
|
|
58332
|
+
var SETUP_STATUS_USAGE = `${cliBrand.binName} onboard setup-status --input '<json-plan>' | --input-file <path> [--json]`;
|
|
58333
|
+
function sourceIngestKinds() {
|
|
58334
|
+
const entry = COMMAND_MANIFEST.find((candidate) => candidate.id === "onboarding.source_ingest");
|
|
58335
|
+
const kinds = entry?.fields.find((field4) => field4.name === "kind")?.enumValues;
|
|
58336
|
+
if (!kinds || kinds.length === 0) {
|
|
58337
|
+
throw new Error("The command manifest is missing onboarding.source_ingest kind values.");
|
|
58338
|
+
}
|
|
58339
|
+
return kinds;
|
|
58340
|
+
}
|
|
58341
|
+
var OnboardingUsageError = class extends Error {
|
|
58342
|
+
constructor(message) {
|
|
58343
|
+
super(message);
|
|
58344
|
+
this.name = "OnboardingUsageError";
|
|
58345
|
+
}
|
|
58346
|
+
};
|
|
58347
|
+
async function runOnboarding(args, io, deps) {
|
|
58348
|
+
let invocation;
|
|
58349
|
+
try {
|
|
58350
|
+
invocation = parseOnboardingInvocation(args);
|
|
58351
|
+
await resolveOnboardingInvocationFiles(invocation, deps.readFile ?? readFile5);
|
|
58352
|
+
} catch (error51) {
|
|
58353
|
+
if (!(error51 instanceof OnboardingUsageError)) {
|
|
58354
|
+
throw error51;
|
|
58355
|
+
}
|
|
58356
|
+
io.stderr.write(`${error51.message}
|
|
58357
|
+
${onboardingUsage()}
|
|
58358
|
+
`);
|
|
58359
|
+
return 1;
|
|
58360
|
+
}
|
|
58361
|
+
const client = await deps.makeClient();
|
|
58362
|
+
return executeOnboardingInvocation(invocation, io, client);
|
|
58363
|
+
}
|
|
58364
|
+
async function executeOnboardingInvocation(invocation, io, client, options = {}) {
|
|
58365
|
+
try {
|
|
58366
|
+
const result = await client.execute(invocation.commandId, invocation.body);
|
|
58367
|
+
const rendered = invocation.json ? JSON.stringify(result.output, null, 2) : formatOnboardingOutput(invocation.action, result.output);
|
|
58368
|
+
io.stdout.write(`${rendered}
|
|
58369
|
+
`);
|
|
58370
|
+
return 0;
|
|
58371
|
+
} catch (error51) {
|
|
58372
|
+
const staged = stagedSetupConfirmationFromError(invocation, error51);
|
|
58373
|
+
if (staged !== null) {
|
|
58374
|
+
io.stdout.write(`${invocation.json ? JSON.stringify(staged, null, 2) : formatStagedSetupConfirmation(invocation.action, staged)}
|
|
58375
|
+
`);
|
|
58376
|
+
return 0;
|
|
58377
|
+
}
|
|
58378
|
+
if (options.onError && options.onError(error51) === "handled") {
|
|
58379
|
+
return "fall-through";
|
|
58380
|
+
}
|
|
58381
|
+
return printCommandError(io, error51);
|
|
58382
|
+
}
|
|
58383
|
+
}
|
|
58384
|
+
async function resolveOnboardingInvocationFiles(invocation, readFileImpl = readFile5) {
|
|
58385
|
+
if (invocation.sourceFile !== void 0) {
|
|
58386
|
+
let bytes;
|
|
58387
|
+
try {
|
|
58388
|
+
bytes = await readFileImpl(invocation.sourceFile);
|
|
58389
|
+
} catch (error51) {
|
|
58390
|
+
throw new OnboardingUsageError(
|
|
58391
|
+
`Could not read --file ${invocation.sourceFile}: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
58392
|
+
);
|
|
58393
|
+
}
|
|
58394
|
+
if (bytes.length === 0) {
|
|
58395
|
+
throw new OnboardingUsageError(`--file ${invocation.sourceFile} is empty.`);
|
|
58396
|
+
}
|
|
58397
|
+
const contentBase64 = bytes.toString("base64");
|
|
58398
|
+
invocation.body.content_base64 = contentBase64;
|
|
58399
|
+
const bodyBytes = Buffer.byteLength(JSON.stringify(invocation.body), "utf8");
|
|
58400
|
+
const preflightCap = SERVER_COMMAND_BODY_CAP_BYTES - COMMAND_BODY_SAFETY_MARGIN_BYTES;
|
|
58401
|
+
if (bodyBytes > preflightCap) {
|
|
58402
|
+
const overheadBytes = bodyBytes - contentBase64.length;
|
|
58403
|
+
const effectiveMaxFileBytes = Math.floor((preflightCap - overheadBytes) / 4) * 3;
|
|
58404
|
+
throw new OnboardingUsageError(
|
|
58405
|
+
`--file ${invocation.sourceFile} is ${bytes.length} bytes; base64-encoded it makes a ${bodyBytes}-byte command body, over the server's authoritative ${SERVER_COMMAND_BODY_CAP_BYTES}-byte command-transport cap (this check stops ${COMMAND_BODY_SAFETY_MARGIN_BYTES} bytes early on purpose). The largest file this invocation can send is about ${effectiveMaxFileBytes} bytes. The onboarding.source_ingest protocol documents sources up to 5,000,000 bytes; reaching that range needs the server-side transport follow-up. Split the export or trim rows/columns to fit.`
|
|
58406
|
+
);
|
|
58407
|
+
}
|
|
58408
|
+
delete invocation.sourceFile;
|
|
58409
|
+
}
|
|
58410
|
+
if (invocation.inputFile !== void 0) {
|
|
58411
|
+
let text;
|
|
58412
|
+
try {
|
|
58413
|
+
text = (await readFileImpl(invocation.inputFile)).toString("utf8");
|
|
58414
|
+
} catch (error51) {
|
|
58415
|
+
throw new OnboardingUsageError(
|
|
58416
|
+
`Could not read --input-file ${invocation.inputFile}: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
58417
|
+
);
|
|
58418
|
+
}
|
|
58419
|
+
invocation.body = parseSetupPlanJson(text, "--input-file");
|
|
58420
|
+
delete invocation.inputFile;
|
|
58421
|
+
}
|
|
58422
|
+
}
|
|
58423
|
+
function stagedSetupConfirmationFromError(invocation, error51) {
|
|
58424
|
+
if (invocation.action !== "setup" && invocation.action !== "setup-status") {
|
|
58425
|
+
return null;
|
|
58426
|
+
}
|
|
58427
|
+
if (!(error51 instanceof CommandClientError) || !error51.response || error51.response.ok || error51.response.error.code !== "COMMAND_CONFIRMATION_REQUIRED") {
|
|
58428
|
+
return null;
|
|
58429
|
+
}
|
|
58430
|
+
const details = error51.response.error.details;
|
|
58431
|
+
if (typeof details !== "object" || details === null) {
|
|
58432
|
+
return null;
|
|
58433
|
+
}
|
|
58434
|
+
const record2 = details;
|
|
58435
|
+
return record2.commandId === invocation.commandId ? record2 : null;
|
|
58436
|
+
}
|
|
58437
|
+
function formatStagedSetupConfirmation(action, details) {
|
|
58438
|
+
const approveVia = asRecord(details.approveVia);
|
|
58439
|
+
const lines = [
|
|
58440
|
+
action === "setup-status" ? "Onboarding setup approval is pending. The URL below is the current card: an identical still-valid card is reused as-is; if live state moved, the stale card was superseded and this fresh one minted." : "Onboarding setup approval is ready.",
|
|
58441
|
+
`Confirmation: ${field(details, "confirmationId")}`
|
|
58442
|
+
];
|
|
58443
|
+
if (typeof approveVia.webUrl === "string") {
|
|
58444
|
+
lines.push(`Approve once: ${approveVia.webUrl}`);
|
|
58445
|
+
}
|
|
58446
|
+
lines.push(
|
|
58447
|
+
"After the owner approves, re-run this command with the identical plan to read the immutable setup receipt."
|
|
58448
|
+
);
|
|
58449
|
+
return lines.join("\n");
|
|
58450
|
+
}
|
|
58451
|
+
function parseSetupPlanJson(text, flag) {
|
|
58452
|
+
let parsed;
|
|
58453
|
+
try {
|
|
58454
|
+
parsed = JSON.parse(text);
|
|
58455
|
+
} catch {
|
|
58456
|
+
throw new OnboardingUsageError(`${flag} must be valid JSON.`);
|
|
58457
|
+
}
|
|
58458
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
58459
|
+
throw new OnboardingUsageError(`${flag} must be a JSON object (the complete onboarding setup plan).`);
|
|
58460
|
+
}
|
|
58461
|
+
return parsed;
|
|
58462
|
+
}
|
|
58463
|
+
function parseOnboardingInvocation(args) {
|
|
58464
|
+
const action = args[0];
|
|
58465
|
+
if (action === "status" || action === "resume") {
|
|
58466
|
+
return {
|
|
58467
|
+
commandId: action === "status" ? "onboarding.status" : "onboarding.resume",
|
|
58468
|
+
body: {},
|
|
58469
|
+
json: args.includes("--json"),
|
|
58470
|
+
action
|
|
58471
|
+
};
|
|
58472
|
+
}
|
|
58473
|
+
if (action === "source-ingest") {
|
|
58474
|
+
return parseSourceIngestInvocation(args.slice(1));
|
|
58475
|
+
}
|
|
58476
|
+
if (action === "setup" || action === "setup-status") {
|
|
58477
|
+
return parseSetupInvocation(action, args.slice(1));
|
|
58478
|
+
}
|
|
58479
|
+
if (action !== "rehearse" && action !== "activate") {
|
|
58480
|
+
throw new OnboardingUsageError(`Unknown onboard action: ${action ?? "(missing)"}`);
|
|
58481
|
+
}
|
|
58482
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
58483
|
+
"setup-application-id",
|
|
58484
|
+
"expected-input-digest",
|
|
58485
|
+
"expected-receipt-revision",
|
|
58486
|
+
"idempotency-key",
|
|
58487
|
+
...action === "activate" ? [
|
|
58488
|
+
"terminal-rehearsal-batch-receipt-id",
|
|
58489
|
+
"rehearsal-runs",
|
|
58490
|
+
"configuration-digests"
|
|
58491
|
+
] : []
|
|
58492
|
+
]);
|
|
58493
|
+
const values = /* @__PURE__ */ new Map();
|
|
58494
|
+
let json2 = false;
|
|
58495
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
58496
|
+
const argument = args[index];
|
|
58497
|
+
if (argument === "--json") {
|
|
58498
|
+
if (json2) {
|
|
58499
|
+
throw new OnboardingUsageError("Duplicate --json flag.");
|
|
58500
|
+
}
|
|
58501
|
+
json2 = true;
|
|
58502
|
+
continue;
|
|
58503
|
+
}
|
|
58504
|
+
if (argument === void 0 || !argument.startsWith("--")) {
|
|
58505
|
+
throw new OnboardingUsageError(`Unexpected argument: ${argument ?? "(missing)"}`);
|
|
58506
|
+
}
|
|
58507
|
+
const key = argument.slice(2);
|
|
58508
|
+
if (!allowed.has(key)) {
|
|
58509
|
+
throw new OnboardingUsageError(`Unknown flag: --${key}`);
|
|
58510
|
+
}
|
|
58511
|
+
if (values.has(key)) {
|
|
58512
|
+
throw new OnboardingUsageError(`Duplicate --${key} flag.`);
|
|
58513
|
+
}
|
|
58514
|
+
const value = args[index + 1];
|
|
58515
|
+
if (value === void 0 || value.startsWith("--")) {
|
|
58516
|
+
throw new OnboardingUsageError(`Missing required --${key} value.`);
|
|
58517
|
+
}
|
|
58518
|
+
values.set(key, value);
|
|
58519
|
+
index += 1;
|
|
58520
|
+
}
|
|
58521
|
+
const requiredValue2 = (key) => {
|
|
58522
|
+
const value = values.get(key);
|
|
58523
|
+
if (value === void 0 || value.length === 0) {
|
|
58524
|
+
throw new OnboardingUsageError(`Missing required --${key} value.`);
|
|
58525
|
+
}
|
|
58526
|
+
return value;
|
|
58527
|
+
};
|
|
58528
|
+
const setupApplicationId = requiredValue2("setup-application-id");
|
|
58529
|
+
const expectedInputDigest = requiredValue2("expected-input-digest");
|
|
58530
|
+
const revisionRaw = requiredValue2("expected-receipt-revision");
|
|
58531
|
+
const idempotencyKey = requiredValue2("idempotency-key");
|
|
58532
|
+
const expectedReceiptRevision = Number(revisionRaw);
|
|
58533
|
+
if (!Number.isSafeInteger(expectedReceiptRevision) || expectedReceiptRevision <= 0) {
|
|
58534
|
+
throw new OnboardingUsageError("--expected-receipt-revision must be a positive integer.");
|
|
58535
|
+
}
|
|
58536
|
+
const sharedBody = {
|
|
58537
|
+
setup_application_id: setupApplicationId,
|
|
58538
|
+
expected_input_digest: expectedInputDigest,
|
|
58539
|
+
expected_receipt_revision: expectedReceiptRevision,
|
|
58540
|
+
idempotency_key: idempotencyKey
|
|
58541
|
+
};
|
|
58542
|
+
if (action === "activate") {
|
|
58543
|
+
return {
|
|
58544
|
+
commandId: "onboarding.activate",
|
|
58545
|
+
body: {
|
|
58546
|
+
...sharedBody,
|
|
58547
|
+
terminal_rehearsal_batch_receipt_id: requiredValue2(
|
|
58548
|
+
"terminal-rehearsal-batch-receipt-id"
|
|
58549
|
+
),
|
|
58550
|
+
rehearsal_runs: parseJsonArrayFlag(
|
|
58551
|
+
"rehearsal-runs",
|
|
58552
|
+
requiredValue2("rehearsal-runs")
|
|
58553
|
+
),
|
|
58554
|
+
configuration_digests: parseJsonArrayFlag(
|
|
58555
|
+
"configuration-digests",
|
|
58556
|
+
requiredValue2("configuration-digests")
|
|
58557
|
+
)
|
|
58558
|
+
},
|
|
58559
|
+
json: json2,
|
|
58560
|
+
action
|
|
58561
|
+
};
|
|
58562
|
+
}
|
|
58563
|
+
return {
|
|
58564
|
+
commandId: "onboarding.rehearse",
|
|
58565
|
+
body: sharedBody,
|
|
58566
|
+
json: json2,
|
|
58567
|
+
action
|
|
58568
|
+
};
|
|
58569
|
+
}
|
|
58570
|
+
function collectFlagValues(args, allowed) {
|
|
58571
|
+
const values = /* @__PURE__ */ new Map();
|
|
58572
|
+
let json2 = false;
|
|
58573
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
58574
|
+
const argument = args[index];
|
|
58575
|
+
if (argument === "--json") {
|
|
58576
|
+
if (json2) {
|
|
58577
|
+
throw new OnboardingUsageError("Duplicate --json flag.");
|
|
58578
|
+
}
|
|
58579
|
+
json2 = true;
|
|
58580
|
+
continue;
|
|
58581
|
+
}
|
|
58582
|
+
if (argument === void 0 || !argument.startsWith("--")) {
|
|
58583
|
+
throw new OnboardingUsageError(`Unexpected argument: ${argument ?? "(missing)"}`);
|
|
58584
|
+
}
|
|
58585
|
+
const key = argument.slice(2);
|
|
58586
|
+
if (!allowed.has(key)) {
|
|
58587
|
+
throw new OnboardingUsageError(`Unknown flag: --${key}`);
|
|
58588
|
+
}
|
|
58589
|
+
if (values.has(key)) {
|
|
58590
|
+
throw new OnboardingUsageError(`Duplicate --${key} flag.`);
|
|
58591
|
+
}
|
|
58592
|
+
const value = args[index + 1];
|
|
58593
|
+
if (value === void 0 || value.startsWith("--")) {
|
|
58594
|
+
throw new OnboardingUsageError(`Missing required --${key} value.`);
|
|
58595
|
+
}
|
|
58596
|
+
values.set(key, value);
|
|
58597
|
+
index += 1;
|
|
58598
|
+
}
|
|
58599
|
+
return { values, json: json2 };
|
|
58600
|
+
}
|
|
58601
|
+
function parseSourceIngestInvocation(args) {
|
|
58602
|
+
const { values, json: json2 } = collectFlagValues(
|
|
58603
|
+
args,
|
|
58604
|
+
/* @__PURE__ */ new Set(["file", "source-key", "kind", "title"])
|
|
58605
|
+
);
|
|
58606
|
+
const required2 = (key) => {
|
|
58607
|
+
const value = values.get(key);
|
|
58608
|
+
if (value === void 0 || value.length === 0) {
|
|
58609
|
+
throw new OnboardingUsageError(`Missing required --${key} value.`);
|
|
58610
|
+
}
|
|
58611
|
+
return value;
|
|
58612
|
+
};
|
|
58613
|
+
const kind = required2("kind");
|
|
58614
|
+
const kinds = sourceIngestKinds();
|
|
58615
|
+
if (!kinds.includes(kind)) {
|
|
58616
|
+
throw new OnboardingUsageError(`--kind must be one of: ${kinds.join(", ")}`);
|
|
58617
|
+
}
|
|
58618
|
+
return {
|
|
58619
|
+
commandId: "onboarding.source_ingest",
|
|
58620
|
+
body: {
|
|
58621
|
+
source_key: required2("source-key"),
|
|
58622
|
+
kind,
|
|
58623
|
+
title: required2("title")
|
|
58624
|
+
},
|
|
58625
|
+
json: json2,
|
|
58626
|
+
action: "source-ingest",
|
|
58627
|
+
sourceFile: required2("file")
|
|
58628
|
+
};
|
|
58629
|
+
}
|
|
58630
|
+
function parseSetupInvocation(action, args) {
|
|
58631
|
+
const { values, json: json2 } = collectFlagValues(args, /* @__PURE__ */ new Set(["input", "input-file"]));
|
|
58632
|
+
const input = values.get("input");
|
|
58633
|
+
const inputFile = values.get("input-file");
|
|
58634
|
+
if (input === void 0 === (inputFile === void 0)) {
|
|
58635
|
+
throw new OnboardingUsageError(
|
|
58636
|
+
`onboard ${action} requires exactly one of --input '<json-plan>' or --input-file <path>.`
|
|
58637
|
+
);
|
|
58638
|
+
}
|
|
58639
|
+
return {
|
|
58640
|
+
commandId: "onboarding.setup",
|
|
58641
|
+
body: input === void 0 ? {} : parseSetupPlanJson(input, "--input"),
|
|
58642
|
+
json: json2,
|
|
58643
|
+
action,
|
|
58644
|
+
...inputFile === void 0 ? {} : { inputFile }
|
|
58645
|
+
};
|
|
58646
|
+
}
|
|
58647
|
+
function onboardingUsage() {
|
|
58648
|
+
return [
|
|
58649
|
+
`Usage: ${cliBrand.binName} onboard status|resume [--json]`,
|
|
58650
|
+
` ${SOURCE_INGEST_USAGE}`,
|
|
58651
|
+
` ${SETUP_USAGE}`,
|
|
58652
|
+
` ${SETUP_STATUS_USAGE}`,
|
|
58653
|
+
` ${REHEARSE_USAGE}`,
|
|
58654
|
+
` ${ACTIVATE_USAGE}`
|
|
58655
|
+
].join("\n");
|
|
58656
|
+
}
|
|
58657
|
+
function formatOnboardingOutput(action, output) {
|
|
58658
|
+
if (action === "rehearse") {
|
|
58659
|
+
return formatRehearsalOutput(output);
|
|
58660
|
+
}
|
|
58661
|
+
if (action === "activate") {
|
|
58662
|
+
return formatActivationOutput(output);
|
|
58663
|
+
}
|
|
58664
|
+
if (action === "source-ingest") {
|
|
58665
|
+
return formatSourceIngestOutput(output);
|
|
58666
|
+
}
|
|
58667
|
+
if (action === "setup" || action === "setup-status") {
|
|
58668
|
+
return formatAppliedSetupOutput(output);
|
|
58669
|
+
}
|
|
58670
|
+
const record2 = typeof output === "object" && output !== null ? output : {};
|
|
58671
|
+
if (typeof record2.summary === "string") {
|
|
58672
|
+
return record2.summary;
|
|
58673
|
+
}
|
|
58674
|
+
return JSON.stringify(output, null, 2);
|
|
58675
|
+
}
|
|
58676
|
+
function parseJsonArrayFlag(flag, value) {
|
|
58677
|
+
try {
|
|
58678
|
+
const parsed = JSON.parse(value);
|
|
58679
|
+
if (!Array.isArray(parsed)) {
|
|
58680
|
+
throw new Error("not an array");
|
|
58681
|
+
}
|
|
58682
|
+
return parsed;
|
|
58683
|
+
} catch {
|
|
58684
|
+
throw new OnboardingUsageError(`--${flag} must be a valid JSON array.`);
|
|
58685
|
+
}
|
|
58686
|
+
}
|
|
58687
|
+
function formatActivationOutput(output) {
|
|
58688
|
+
const record2 = asRecord(output);
|
|
58689
|
+
const approveVia = asRecord(record2.approveVia);
|
|
58690
|
+
if (typeof approveVia.webUrl === "string") {
|
|
58691
|
+
return [
|
|
58692
|
+
"Onboarding activation approval is ready.",
|
|
58693
|
+
`Approve once: ${approveVia.webUrl}`
|
|
58694
|
+
].join("\n");
|
|
58695
|
+
}
|
|
58696
|
+
const receipt = asRecord(record2.receipt);
|
|
58697
|
+
const agents = Array.isArray(receipt.agents) ? receipt.agents : [];
|
|
58698
|
+
if (record2.status === "activated") {
|
|
58699
|
+
return [
|
|
58700
|
+
"Onboarding activation completed.",
|
|
58701
|
+
`Activation receipt: ${field(receipt, "activation_receipt_id")}`,
|
|
58702
|
+
`Agents live: ${agents.length} of ${agents.length}`,
|
|
58703
|
+
`Onboarding completed: ${field(receipt, "onboarding_completed_at")}`
|
|
58704
|
+
].join("\n");
|
|
58705
|
+
}
|
|
58706
|
+
return JSON.stringify(output, null, 2);
|
|
58707
|
+
}
|
|
58708
|
+
function formatSourceIngestOutput(output) {
|
|
58709
|
+
const record2 = asRecord(output);
|
|
58710
|
+
const descriptor = asRecord(record2.descriptor);
|
|
58711
|
+
const families = Array.isArray(descriptor.family_manifest) ? descriptor.family_manifest : [];
|
|
58712
|
+
return [
|
|
58713
|
+
"Source retained for this run.",
|
|
58714
|
+
`Upload: ${field(record2, "source_upload_id")}`,
|
|
58715
|
+
`SHA-256: ${field(descriptor, "sha256")}`,
|
|
58716
|
+
`Bytes: ${field(descriptor, "byte_count")}`,
|
|
58717
|
+
...families.map((entry) => {
|
|
58718
|
+
const item = asRecord(entry);
|
|
58719
|
+
return `- ${field(item, "family")}: ${field(item, "input_count")} rows`;
|
|
58720
|
+
}),
|
|
58721
|
+
"Reference it from the setup plan's sources[] via the returned source_ref (run with --json to capture it verbatim)."
|
|
58722
|
+
].join("\n");
|
|
58723
|
+
}
|
|
58724
|
+
function formatAppliedSetupOutput(output) {
|
|
58725
|
+
const record2 = asRecord(output);
|
|
58726
|
+
if (typeof record2.application_id !== "string") {
|
|
58727
|
+
return JSON.stringify(output, null, 2);
|
|
58728
|
+
}
|
|
58729
|
+
const receipt = asRecord(record2.receipt);
|
|
58730
|
+
const digests = asRecord(receipt.digests);
|
|
58731
|
+
return [
|
|
58732
|
+
"Onboarding setup is applied.",
|
|
58733
|
+
`Setup application: ${field(record2, "application_id")}`,
|
|
58734
|
+
`Receipt revision: ${field(receipt, "receipt_revision")}`,
|
|
58735
|
+
`Input digest: ${field(digests, "input")}`,
|
|
58736
|
+
`Next: ${cliBrand.binName} onboard rehearse --setup-application-id ${field(record2, "application_id")} --expected-input-digest ${field(digests, "input")} --expected-receipt-revision ${field(receipt, "receipt_revision")} --idempotency-key <stable-key> --json`
|
|
58737
|
+
].join("\n");
|
|
58738
|
+
}
|
|
58739
|
+
function formatRehearsalOutput(output) {
|
|
58740
|
+
const record2 = asRecord(output);
|
|
58741
|
+
if (record2.status === "in_progress") {
|
|
58742
|
+
const batch = asRecord(record2.batch);
|
|
58743
|
+
const checkpoints = Array.isArray(record2.checkpoints) ? record2.checkpoints : [];
|
|
58744
|
+
const completed = checkpoints.filter((checkpoint) => {
|
|
58745
|
+
const status = asRecord(checkpoint).status;
|
|
58746
|
+
return status === "passed" || status === "failed";
|
|
58747
|
+
}).length;
|
|
58748
|
+
return [
|
|
58749
|
+
"Onboarding rehearsal is in progress.",
|
|
58750
|
+
`Batch: ${field(batch, "batch_id")}`,
|
|
58751
|
+
`Checkpoints complete: ${completed} of ${checkpoints.length}`,
|
|
58752
|
+
...checkpoints.map((checkpoint) => {
|
|
58753
|
+
const item = asRecord(checkpoint);
|
|
58754
|
+
return `- Agent ${field(item, "agent_id")} / Seat ${field(item, "seat_id")}: ${field(item, "status")}`;
|
|
58755
|
+
}),
|
|
58756
|
+
"Retry with the same idempotency key to continue this batch."
|
|
58757
|
+
].join("\n");
|
|
58758
|
+
}
|
|
58759
|
+
if (record2.status === "passed" || record2.status === "failed") {
|
|
58760
|
+
return [
|
|
58761
|
+
`Onboarding rehearsal ${record2.status}.`,
|
|
58762
|
+
"Immutable batch receipt:",
|
|
58763
|
+
JSON.stringify(record2.batch_receipt, null, 2),
|
|
58764
|
+
"Immutable agent receipts:",
|
|
58765
|
+
JSON.stringify(record2.agent_receipts, null, 2)
|
|
58766
|
+
].join("\n");
|
|
58767
|
+
}
|
|
58768
|
+
return JSON.stringify(output, null, 2);
|
|
58769
|
+
}
|
|
58770
|
+
function asRecord(value) {
|
|
58771
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
58772
|
+
}
|
|
58773
|
+
function field(record2, key) {
|
|
58774
|
+
const value = record2[key];
|
|
58775
|
+
return typeof value === "string" || typeof value === "number" ? String(value) : "\u2014";
|
|
58776
|
+
}
|
|
58777
|
+
function printCommandError(io, error51) {
|
|
58778
|
+
if (error51 instanceof CommandClientError && error51.response && !error51.response.ok) {
|
|
58779
|
+
const help = error51.response.error.help;
|
|
58780
|
+
const requestId = error51.response.requestId;
|
|
58781
|
+
io.stderr.write(redactForLog({
|
|
58782
|
+
code: error51.response.error.code,
|
|
58783
|
+
message: error51.response.error.message,
|
|
58784
|
+
...error51.response.error.details === void 0 ? {} : { details: error51.response.error.details },
|
|
58785
|
+
...help === void 0 ? {} : { help },
|
|
58786
|
+
...requestId === void 0 ? {} : { requestId }
|
|
58787
|
+
}));
|
|
58788
|
+
io.stderr.write("\n");
|
|
58789
|
+
if (help !== void 0) {
|
|
58790
|
+
io.stderr.write(`\u2192 try: ${redactForLog(help)}
|
|
58791
|
+
`);
|
|
58792
|
+
}
|
|
58793
|
+
if (error51.status === 409) {
|
|
58794
|
+
return 3;
|
|
58795
|
+
}
|
|
58796
|
+
return error51.status >= 400 && error51.status < 500 ? 1 : 2;
|
|
58797
|
+
}
|
|
58798
|
+
throw error51;
|
|
58799
|
+
}
|
|
58800
|
+
|
|
58801
|
+
// src/commands/implementation-access.ts
|
|
58802
|
+
var implementationCredentialSchema = external_exports.object({
|
|
58803
|
+
token: external_exports.string().regex(/^rost_impl_[A-Za-z0-9_-]+$/),
|
|
58804
|
+
token_id: external_exports.string().uuid(),
|
|
58805
|
+
tenant_id: external_exports.string().uuid(),
|
|
58806
|
+
implementation_run_id: external_exports.string().uuid(),
|
|
58807
|
+
scope: external_exports.literal("implementation_bootstrap"),
|
|
58808
|
+
expires_at: external_exports.string().datetime({ offset: true })
|
|
58809
|
+
}).strict();
|
|
58810
|
+
var ImplementationAccessError = class extends Error {
|
|
58811
|
+
constructor(message) {
|
|
58812
|
+
super(message);
|
|
58813
|
+
this.name = "ImplementationAccessError";
|
|
58814
|
+
}
|
|
58815
|
+
};
|
|
58816
|
+
var DEFAULT_SOURCE_CLIENT = "external-agent";
|
|
58817
|
+
var SOURCE_CLIENT_MAX_LENGTH = 80;
|
|
58818
|
+
async function runImplementationAccess(args, io, deps) {
|
|
58819
|
+
const json2 = args.includes("--json");
|
|
58820
|
+
const action = parseAction(args[0]);
|
|
58821
|
+
if (action === null) {
|
|
58822
|
+
io.stderr.write(
|
|
58823
|
+
`Usage: ${cliBrand.binName} implementation access start|status|complete|abandon [--json]
|
|
58824
|
+
`
|
|
58825
|
+
);
|
|
58826
|
+
return 1;
|
|
58827
|
+
}
|
|
58828
|
+
if (action === "start") {
|
|
58829
|
+
const sourceClient = parseSourceClient(args.slice(1), DEFAULT_SOURCE_CLIENT);
|
|
58830
|
+
return runStart(io, deps, sourceClient, json2);
|
|
58831
|
+
}
|
|
58832
|
+
const store = deps.createImplementationStore();
|
|
58833
|
+
const credential = await store.read();
|
|
58834
|
+
if (!credential) {
|
|
58835
|
+
io.stderr.write("No implementation credential. Run rost implementation access start.\n");
|
|
58836
|
+
return 1;
|
|
58837
|
+
}
|
|
58838
|
+
if (action === "status") {
|
|
58839
|
+
return runStatus(io, deps, credential, json2);
|
|
58840
|
+
}
|
|
58841
|
+
if (action === "complete") {
|
|
58842
|
+
return runComplete(io, deps, credential, store, json2);
|
|
58843
|
+
}
|
|
58844
|
+
return runAbandon(io, deps, credential, store, json2);
|
|
58845
|
+
}
|
|
58846
|
+
function parseAction(value) {
|
|
58847
|
+
if (value === "start" || value === "status" || value === "complete" || value === "abandon") {
|
|
58848
|
+
return value;
|
|
58849
|
+
}
|
|
58850
|
+
return null;
|
|
58851
|
+
}
|
|
58852
|
+
function parseSourceClient(args, defaultValue) {
|
|
58853
|
+
let sourceClient;
|
|
58854
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
58855
|
+
const arg = args[index];
|
|
58856
|
+
if (arg === "--source-client") {
|
|
58857
|
+
sourceClient = args[index + 1];
|
|
58858
|
+
if (sourceClient === void 0) {
|
|
58859
|
+
throw new ImplementationAccessError("--source-client requires a value.");
|
|
58860
|
+
}
|
|
58861
|
+
index += 1;
|
|
58862
|
+
}
|
|
58863
|
+
}
|
|
58864
|
+
const value = (sourceClient ?? defaultValue).trim();
|
|
58865
|
+
if (value.length === 0) {
|
|
58866
|
+
throw new ImplementationAccessError("--source-client cannot be blank.");
|
|
58867
|
+
}
|
|
58868
|
+
if (value.length > SOURCE_CLIENT_MAX_LENGTH) {
|
|
58869
|
+
throw new ImplementationAccessError(`--source-client must be ${SOURCE_CLIENT_MAX_LENGTH} characters or fewer.`);
|
|
58870
|
+
}
|
|
58871
|
+
return value;
|
|
58872
|
+
}
|
|
58873
|
+
function minimalConfig(appUrl2) {
|
|
58874
|
+
return {
|
|
58875
|
+
appUrl: appUrl2,
|
|
58876
|
+
supabaseUrl: "https://unused.example.test",
|
|
58877
|
+
supabaseAnonKey: "unused"
|
|
58878
|
+
};
|
|
58879
|
+
}
|
|
58880
|
+
async function runStart(io, deps, sourceClient, json2) {
|
|
58881
|
+
const store = deps.createImplementationStore();
|
|
58882
|
+
const credential = await deps.pollDeviceAuthorizationHandoff(
|
|
58883
|
+
minimalConfig(deps.appUrl),
|
|
58884
|
+
io,
|
|
58885
|
+
{
|
|
58886
|
+
purpose: "implementation_bootstrap",
|
|
58887
|
+
sourceClient,
|
|
58888
|
+
// DER-2158 (U3b) C3: `silent: json` still suppresses the poller's own
|
|
58889
|
+
// stdout print + browser open in --json mode, so stdout stays pure JSON
|
|
58890
|
+
// for a machine caller. But without a replacement, --json mode never
|
|
58891
|
+
// shows the verification URL/code at all — the command blocks until
|
|
58892
|
+
// approval and nobody ever saw the code to approve it, so it always
|
|
58893
|
+
// times out. `onStart` fires unconditionally (even when silent), so use
|
|
58894
|
+
// it to surface the same URL/code on STDERR instead. Never write the
|
|
58895
|
+
// bearer token here — the pre-approval StartSession doesn't carry one.
|
|
58896
|
+
silent: json2,
|
|
58897
|
+
...json2 ? { onStart: (session) => writeJsonStartPrompt(io, session) } : {}
|
|
58898
|
+
},
|
|
58899
|
+
{},
|
|
58900
|
+
(approved) => mapApprovedToCredential(approved)
|
|
58901
|
+
);
|
|
58902
|
+
await store.write(credential);
|
|
58903
|
+
if (json2) {
|
|
58904
|
+
io.stdout.write(
|
|
58905
|
+
`${JSON.stringify({
|
|
58906
|
+
status: "started",
|
|
58907
|
+
run_id: credential.implementation_run_id,
|
|
58908
|
+
tenant_id: credential.tenant_id,
|
|
58909
|
+
scope: credential.scope,
|
|
58910
|
+
expires_at: credential.expires_at,
|
|
58911
|
+
stored_in: store.describe()
|
|
58912
|
+
})}
|
|
58913
|
+
`
|
|
58914
|
+
);
|
|
58915
|
+
} else {
|
|
58916
|
+
io.stdout.write(
|
|
58917
|
+
`The implementation credential is stored in ${store.describe()} and expires at ${credential.expires_at}.
|
|
58918
|
+
`
|
|
58919
|
+
);
|
|
58920
|
+
}
|
|
58921
|
+
return 0;
|
|
58922
|
+
}
|
|
58923
|
+
function writeJsonStartPrompt(io, session) {
|
|
58924
|
+
io.stderr.write(
|
|
58925
|
+
[
|
|
58926
|
+
"To sign in, open this URL in any browser and approve the code:",
|
|
58927
|
+
` ${session.verification_uri}`,
|
|
58928
|
+
"",
|
|
58929
|
+
` Code: ${session.user_code}`,
|
|
58930
|
+
"",
|
|
58931
|
+
"Waiting for approval\u2026",
|
|
58932
|
+
""
|
|
58933
|
+
].join("\n")
|
|
58934
|
+
);
|
|
58935
|
+
}
|
|
58936
|
+
function mapApprovedToCredential(approved) {
|
|
58937
|
+
const raw = approved;
|
|
58938
|
+
const parsed = implementationCredentialSchema.safeParse({
|
|
58939
|
+
token: raw.token,
|
|
58940
|
+
token_id: raw.token_id,
|
|
58941
|
+
tenant_id: raw.tenant_id,
|
|
58942
|
+
implementation_run_id: raw.implementation_run_id,
|
|
58943
|
+
scope: raw.scope,
|
|
58944
|
+
expires_at: raw.expires_at
|
|
58945
|
+
});
|
|
58946
|
+
if (!parsed.success) {
|
|
58947
|
+
return null;
|
|
58948
|
+
}
|
|
58949
|
+
return parsed.data;
|
|
58950
|
+
}
|
|
58951
|
+
function createImplementationClient(deps, credential) {
|
|
58952
|
+
return new deps.CommandClient({
|
|
58953
|
+
appUrl: deps.appUrl,
|
|
58954
|
+
token: credential.token,
|
|
58955
|
+
credentialKind: "implementation_bootstrap"
|
|
58956
|
+
});
|
|
58957
|
+
}
|
|
58958
|
+
function isDeadRunError(error51) {
|
|
58959
|
+
if (!(error51 instanceof CommandClientError) || !error51.response || error51.response.ok) {
|
|
58960
|
+
return false;
|
|
58961
|
+
}
|
|
58962
|
+
if (error51.status === 401) {
|
|
58963
|
+
return true;
|
|
58964
|
+
}
|
|
58965
|
+
const code = error51.response.error.code;
|
|
58966
|
+
return code === "COMMAND_AUTHORIZATION" || code === "COMMAND_UNAUTHENTICATED" || /expired/i.test(error51.response.error.message);
|
|
58967
|
+
}
|
|
58968
|
+
async function runStatus(io, deps, credential, json2) {
|
|
58969
|
+
const client = createImplementationClient(deps, credential);
|
|
58970
|
+
try {
|
|
58971
|
+
const result = await client.execute("implementation_access.status", {});
|
|
58972
|
+
if (json2) {
|
|
58973
|
+
io.stdout.write(`${JSON.stringify(result.output)}
|
|
58974
|
+
`);
|
|
58975
|
+
} else {
|
|
58976
|
+
io.stdout.write(`${redactForLog(formatStatusSummary(result.output))}
|
|
58977
|
+
`);
|
|
58978
|
+
}
|
|
58979
|
+
return 0;
|
|
58980
|
+
} catch (error51) {
|
|
58981
|
+
if (isDeadRunError(error51)) {
|
|
58982
|
+
io.stderr.write(
|
|
58983
|
+
"The implementation run is no longer active. Start a new one: rost implementation access start\n"
|
|
58984
|
+
);
|
|
58985
|
+
return 1;
|
|
58986
|
+
}
|
|
58987
|
+
io.stderr.write(`${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
|
|
58988
|
+
`);
|
|
58989
|
+
return 1;
|
|
58990
|
+
}
|
|
58991
|
+
}
|
|
58992
|
+
function formatStatusSummary(output) {
|
|
58993
|
+
const record2 = typeof output === "object" && output !== null ? output : {};
|
|
58994
|
+
const status = typeof record2.status === "string" ? record2.status : "unknown";
|
|
58995
|
+
const runId = typeof record2.run_id === "string" ? record2.run_id : "unknown";
|
|
58996
|
+
return `Implementation run ${runId} status: ${status}.`;
|
|
58997
|
+
}
|
|
58998
|
+
async function runComplete(io, deps, credential, store, json2) {
|
|
58999
|
+
const client = createImplementationClient(deps, credential);
|
|
59000
|
+
try {
|
|
59001
|
+
const result = await client.execute("implementation_access.complete", {});
|
|
59002
|
+
await store.clear();
|
|
59003
|
+
if (json2) {
|
|
59004
|
+
io.stdout.write(
|
|
59005
|
+
`${JSON.stringify({
|
|
59006
|
+
status: "completed",
|
|
59007
|
+
run_id: credential.implementation_run_id,
|
|
59008
|
+
already_closed: result.output?.already_closed ?? false
|
|
59009
|
+
})}
|
|
59010
|
+
`
|
|
59011
|
+
);
|
|
59012
|
+
} else {
|
|
59013
|
+
io.stdout.write("Implementation run completed and the local credential was cleared.\n");
|
|
59014
|
+
}
|
|
59015
|
+
return 0;
|
|
59016
|
+
} catch (error51) {
|
|
59017
|
+
io.stderr.write(`${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
|
|
59018
|
+
`);
|
|
59019
|
+
io.stderr.write("The credential was kept. Retry with: rost implementation access complete\n");
|
|
59020
|
+
return 1;
|
|
59021
|
+
}
|
|
59022
|
+
}
|
|
59023
|
+
async function runAbandon(io, deps, credential, store, json2) {
|
|
59024
|
+
const client = createImplementationClient(deps, credential);
|
|
59025
|
+
try {
|
|
59026
|
+
const result = await client.execute("implementation_access.abandon", {});
|
|
59027
|
+
await store.clear();
|
|
59028
|
+
if (json2) {
|
|
59029
|
+
io.stdout.write(
|
|
59030
|
+
`${JSON.stringify({
|
|
59031
|
+
status: "abandoned",
|
|
59032
|
+
run_id: credential.implementation_run_id,
|
|
59033
|
+
already_closed: result.output?.already_closed ?? false
|
|
59034
|
+
})}
|
|
59035
|
+
`
|
|
59036
|
+
);
|
|
59037
|
+
} else {
|
|
59038
|
+
io.stdout.write("Implementation run abandoned and the local credential was cleared.\n");
|
|
59039
|
+
}
|
|
59040
|
+
return 0;
|
|
59041
|
+
} catch (error51) {
|
|
59042
|
+
io.stderr.write(`${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
|
|
59043
|
+
`);
|
|
59044
|
+
io.stderr.write("The credential was kept. Retry with: rost implementation access abandon\n");
|
|
59045
|
+
return 1;
|
|
59046
|
+
}
|
|
59047
|
+
}
|
|
59048
|
+
function defaultImplementationAccessDeps(appUrl2) {
|
|
59049
|
+
return {
|
|
59050
|
+
appUrl: appUrl2,
|
|
59051
|
+
createImplementationStore: createImplementationCredentialStore,
|
|
59052
|
+
pollDeviceAuthorizationHandoff,
|
|
59053
|
+
CommandClient
|
|
59054
|
+
};
|
|
59055
|
+
}
|
|
59056
|
+
|
|
58794
59057
|
// src/generator/groups.ts
|
|
58795
59058
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
58796
59059
|
|
|
@@ -62676,7 +62939,7 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
|
|
|
62676
62939
|
// src/runner-service.ts
|
|
62677
62940
|
import { execFile as execFileCallback2 } from "node:child_process";
|
|
62678
62941
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
62679
|
-
import { access, mkdir as mkdir4, readFile as
|
|
62942
|
+
import { access, mkdir as mkdir4, readFile as readFile6, readdir as readdir2, rm as rm4, writeFile as writeFile4 } from "node:fs/promises";
|
|
62680
62943
|
import { homedir as homedir4 } from "node:os";
|
|
62681
62944
|
import path7 from "node:path";
|
|
62682
62945
|
import { promisify as promisify2 } from "node:util";
|
|
@@ -63090,7 +63353,7 @@ async function inspectRunnerService(options) {
|
|
|
63090
63353
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
63091
63354
|
const label = serviceLabel(safeName);
|
|
63092
63355
|
const installed = await fileExists(paths.launchAgentPath);
|
|
63093
|
-
const plist = installed ? await
|
|
63356
|
+
const plist = installed ? await readFile6(paths.launchAgentPath, "utf8").catch(() => null) : null;
|
|
63094
63357
|
const programArgs = plist ? extractProgramArguments(plist) : [];
|
|
63095
63358
|
const appUrl2 = plist ? extractPlistEnvironmentValue(plist, `${cliBrand.envPrefix}_APP_URL`) : null;
|
|
63096
63359
|
const urlPolicyEnv = extractPlistEnvironmentValue(plist ?? "", allowInsecureAppUrlEnv) === "1" ? "set" : "unset";
|
|
@@ -63358,7 +63621,7 @@ async function fileExists(file2) {
|
|
|
63358
63621
|
}
|
|
63359
63622
|
async function readTail(file2, maxBytes) {
|
|
63360
63623
|
try {
|
|
63361
|
-
const content = await
|
|
63624
|
+
const content = await readFile6(file2, "utf8");
|
|
63362
63625
|
return content.length > maxBytes ? content.slice(content.length - maxBytes) : content;
|
|
63363
63626
|
} catch {
|
|
63364
63627
|
return null;
|
|
@@ -63506,7 +63769,7 @@ function parseSemver2(value) {
|
|
|
63506
63769
|
import { execFile as execFileCallback5, spawn } from "node:child_process";
|
|
63507
63770
|
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
63508
63771
|
import { constants as fsConstants4 } from "node:fs";
|
|
63509
|
-
import { access as access3, chmod as chmod2, lstat as lstat2, mkdir as mkdir6, open as open2, readFile as
|
|
63772
|
+
import { access as access3, chmod as chmod2, lstat as lstat2, mkdir as mkdir6, open as open2, readFile as readFile8, rename as rename2, rm as rm6, statfs, writeFile as writeFile6 } from "node:fs/promises";
|
|
63510
63773
|
import { cpus, homedir as homedir5, hostname as hostname3, platform, totalmem, tmpdir as tmpdir2 } from "node:os";
|
|
63511
63774
|
import path10 from "node:path";
|
|
63512
63775
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
@@ -63516,7 +63779,7 @@ import { promisify as promisify5 } from "node:util";
|
|
|
63516
63779
|
import { execFile as execFileCallback4 } from "node:child_process";
|
|
63517
63780
|
import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
63518
63781
|
import { constants as fsConstants3 } from "node:fs";
|
|
63519
|
-
import { chmod, link, lstat, mkdir as mkdir5, mkdtemp, open, readdir as readdir3, readFile as
|
|
63782
|
+
import { chmod, link, lstat, mkdir as mkdir5, mkdtemp, open, readdir as readdir3, readFile as readFile7, realpath, rename, rm as rm5, stat as stat4, writeFile as writeFile5 } from "node:fs/promises";
|
|
63520
63783
|
import os3 from "node:os";
|
|
63521
63784
|
import path8 from "node:path";
|
|
63522
63785
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
@@ -63628,7 +63891,7 @@ async function provisionIsolatedClaudeConfigDir(base, configDir, onRepair) {
|
|
|
63628
63891
|
const source = resolveSourceClaudeConfigDir(base);
|
|
63629
63892
|
for (const file2 of CLAUDE_CONFIG_AUTH_FILES) {
|
|
63630
63893
|
try {
|
|
63631
|
-
const data = await
|
|
63894
|
+
const data = await readFile7(path8.join(source, file2));
|
|
63632
63895
|
await writeFileAtomicNoFollow(path8.join(configDir, file2), data, { mode: 384 });
|
|
63633
63896
|
} catch {
|
|
63634
63897
|
}
|
|
@@ -63831,7 +64094,7 @@ trust_level = "untrusted"
|
|
|
63831
64094
|
await rm5(dest, { recursive: true, force: true });
|
|
63832
64095
|
}
|
|
63833
64096
|
const source = resolveSourceCodexHomeDir(base);
|
|
63834
|
-
const data = await
|
|
64097
|
+
const data = await readFile7(path8.join(source, CODEX_HOME_AUTH_FILE)).catch(() => null);
|
|
63835
64098
|
if (data === null) {
|
|
63836
64099
|
return homeDir;
|
|
63837
64100
|
}
|
|
@@ -63914,7 +64177,7 @@ async function acquireCodexHomeLock(homeDir, options = {}) {
|
|
|
63914
64177
|
ino = String((await handle.stat()).ino);
|
|
63915
64178
|
} catch (error51) {
|
|
63916
64179
|
await handle.close().catch(() => void 0);
|
|
63917
|
-
const stillOurs = await
|
|
64180
|
+
const stillOurs = await readFile7(lockPath, "utf8").then((raw) => JSON.parse(raw).nonce === nonce).catch(() => false);
|
|
63918
64181
|
if (stillOurs) {
|
|
63919
64182
|
await rm5(lockPath, { force: true }).catch(() => void 0);
|
|
63920
64183
|
}
|
|
@@ -63957,7 +64220,7 @@ async function breakCodexHomeLock(lockPath, expected) {
|
|
|
63957
64220
|
}
|
|
63958
64221
|
let raw;
|
|
63959
64222
|
try {
|
|
63960
|
-
raw = await
|
|
64223
|
+
raw = await readFile7(lockPath, "utf8");
|
|
63961
64224
|
} catch {
|
|
63962
64225
|
return;
|
|
63963
64226
|
}
|
|
@@ -63974,7 +64237,7 @@ async function judgeCodexHomeLock(lockPath, staleMs) {
|
|
|
63974
64237
|
}
|
|
63975
64238
|
let raw;
|
|
63976
64239
|
try {
|
|
63977
|
-
raw = await
|
|
64240
|
+
raw = await readFile7(lockPath, "utf8");
|
|
63978
64241
|
} catch (error51) {
|
|
63979
64242
|
if (error51.code === "ENOENT") {
|
|
63980
64243
|
return { stale: false, identity: null };
|
|
@@ -65537,7 +65800,7 @@ async function migrateOneLegacyCodexHome(legacyHome, newHome, io) {
|
|
|
65537
65800
|
}
|
|
65538
65801
|
async function loadState(filePath, expectedTenantId) {
|
|
65539
65802
|
try {
|
|
65540
|
-
const parsed = JSON.parse(await
|
|
65803
|
+
const parsed = JSON.parse(await readFile8(filePath, "utf8"));
|
|
65541
65804
|
if (typeof parsed.runner_id === "string" && typeof parsed.runner_secret === "string") {
|
|
65542
65805
|
if (expectedTenantId && parsed.tenant_id !== expectedTenantId) {
|
|
65543
65806
|
return null;
|
|
@@ -67335,7 +67598,7 @@ async function reconcileOrphanedInFlightWorkOrders(deps) {
|
|
|
67335
67598
|
const transcriptPath = await findClaudeTranscriptPath(entry.claude_config_dir, entry.claude_session_id);
|
|
67336
67599
|
if (transcriptPath) {
|
|
67337
67600
|
try {
|
|
67338
|
-
const content = await
|
|
67601
|
+
const content = await readFile8(transcriptPath, "utf8");
|
|
67339
67602
|
verdict = classifyClaudeTranscript(content);
|
|
67340
67603
|
} catch {
|
|
67341
67604
|
verdict = { kind: "missing" };
|
|
@@ -67734,7 +67997,7 @@ async function main(argv = process.argv.slice(2), options = {}) {
|
|
|
67734
67997
|
allowDevelopmentAppUrl: process.env[allowInsecureAppUrlEnv] === "1"
|
|
67735
67998
|
});
|
|
67736
67999
|
}
|
|
67737
|
-
if (command === "onboard" && (args[0] === "status" || args[0] === "resume" || args[0] === "rehearse" || args[0] === "activate")) {
|
|
68000
|
+
if (command === "onboard" && (args[0] === "status" || args[0] === "resume" || args[0] === "rehearse" || args[0] === "activate" || args[0] === "source-ingest" || args[0] === "setup" || args[0] === "setup-status")) {
|
|
67738
68001
|
let implCredential = null;
|
|
67739
68002
|
try {
|
|
67740
68003
|
implCredential = await createImplementationCredentialStore().read();
|
|
@@ -67745,6 +68008,7 @@ async function main(argv = process.argv.slice(2), options = {}) {
|
|
|
67745
68008
|
let invocation;
|
|
67746
68009
|
try {
|
|
67747
68010
|
invocation = parseOnboardingInvocation(args);
|
|
68011
|
+
await resolveOnboardingInvocationFiles(invocation);
|
|
67748
68012
|
} catch (error51) {
|
|
67749
68013
|
if (!(error51 instanceof OnboardingUsageError)) {
|
|
67750
68014
|
throw error51;
|
|
@@ -67760,15 +68024,51 @@ ${onboardingUsage()}
|
|
|
67760
68024
|
token: implCredential.token,
|
|
67761
68025
|
credentialKind: "implementation_bootstrap"
|
|
67762
68026
|
});
|
|
67763
|
-
|
|
67764
|
-
|
|
67765
|
-
|
|
68027
|
+
const exit = await executeOnboardingInvocation(invocation, io, implClient, {
|
|
68028
|
+
onError: (error51) => isDeadRunError(error51) ? "handled" : "print"
|
|
68029
|
+
});
|
|
68030
|
+
if (exit !== "fall-through") {
|
|
68031
|
+
return exit;
|
|
68032
|
+
}
|
|
68033
|
+
}
|
|
68034
|
+
}
|
|
68035
|
+
if (command === "seat" && args[0] === "create-complete") {
|
|
68036
|
+
let implCredential = null;
|
|
68037
|
+
try {
|
|
68038
|
+
implCredential = await createImplementationCredentialStore().read();
|
|
68039
|
+
} catch {
|
|
68040
|
+
implCredential = null;
|
|
68041
|
+
}
|
|
68042
|
+
if (implCredential) {
|
|
68043
|
+
const CommandClientCtor2 = options.commandClient ?? CommandClient;
|
|
68044
|
+
const implClient = new CommandClientCtor2({
|
|
68045
|
+
appUrl: config2.appUrl,
|
|
68046
|
+
token: implCredential.token,
|
|
68047
|
+
credentialKind: "implementation_bootstrap"
|
|
68048
|
+
});
|
|
68049
|
+
let deadRun = false;
|
|
68050
|
+
const exit = await runOperation("seat", args, {
|
|
68051
|
+
io,
|
|
68052
|
+
client: implClient,
|
|
68053
|
+
binName: cliBrand.binName,
|
|
68054
|
+
run: async (wrapperClient, commandId, body, format, runOptions) => {
|
|
68055
|
+
try {
|
|
68056
|
+
const result = await wrapperClient.execute(commandId, body, runOptions ?? {});
|
|
68057
|
+
const rendered = format ? format(result.output) : JSON.stringify(result.output, null, 2);
|
|
68058
|
+
io.stdout.write(`${rendered}
|
|
67766
68059
|
`);
|
|
67767
|
-
|
|
67768
|
-
|
|
67769
|
-
|
|
67770
|
-
|
|
68060
|
+
return 0;
|
|
68061
|
+
} catch (error51) {
|
|
68062
|
+
if (isDeadRunError(error51)) {
|
|
68063
|
+
deadRun = true;
|
|
68064
|
+
return 1;
|
|
68065
|
+
}
|
|
68066
|
+
return printCommandError3(io, error51);
|
|
68067
|
+
}
|
|
67771
68068
|
}
|
|
68069
|
+
});
|
|
68070
|
+
if (!deadRun) {
|
|
68071
|
+
return exit;
|
|
67772
68072
|
}
|
|
67773
68073
|
}
|
|
67774
68074
|
}
|
|
@@ -68268,6 +68568,10 @@ function printUsage(io) {
|
|
|
68268
68568
|
`${cliBrand.binName} onboard status`,
|
|
68269
68569
|
`${cliBrand.binName} onboard resume`,
|
|
68270
68570
|
`${cliBrand.binName} onboard run`,
|
|
68571
|
+
`${cliBrand.binName} onboard source-ingest --file <path> --source-key <key> --kind <kind> --title <title> [--json]`,
|
|
68572
|
+
`${cliBrand.binName} onboard setup --input '<json-plan>' | --input-file <path> [--json]`,
|
|
68573
|
+
`${cliBrand.binName} onboard setup-status --input '<json-plan>' | --input-file <path> [--json]`,
|
|
68574
|
+
`${cliBrand.binName} onboard rehearse|activate --setup-application-id <uuid> ... [--json]`,
|
|
68271
68575
|
`${cliBrand.binName} mcp install --client claude-code|codex|cursor --scope tenant-admin|seat [--seat-id <id>] [--expires-in <days>|--no-expiry]`,
|
|
68272
68576
|
`${cliBrand.binName} mcp install --client claude-code|codex|cursor --rotate <old-token-id> (inherits the old token's scope; no --scope)`,
|
|
68273
68577
|
`${cliBrand.binName} implementation access start|status|complete|abandon [--json]`,
|