@oh-hai/cli 0.1.0-beta.0
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 +154 -0
- package/dist/auth/file-backend.d.ts +16 -0
- package/dist/auth/file-backend.js +98 -0
- package/dist/auth/file-backend.js.map +1 -0
- package/dist/auth/keychain.d.ts +54 -0
- package/dist/auth/keychain.js +232 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/auth/resolve-token.d.ts +34 -0
- package/dist/auth/resolve-token.js +91 -0
- package/dist/auth/resolve-token.js.map +1 -0
- package/dist/auth/secure-write.d.ts +2 -0
- package/dist/auth/secure-write.js +30 -0
- package/dist/auth/secure-write.js.map +1 -0
- package/dist/auth/token-store.d.ts +104 -0
- package/dist/auth/token-store.js +208 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +238 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/agents.d.ts +2 -0
- package/dist/commands/agents.js +370 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/ask.d.ts +2 -0
- package/dist/commands/ask.js +246 -0
- package/dist/commands/ask.js.map +1 -0
- package/dist/commands/context.d.ts +72 -0
- package/dist/commands/context.js +7 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +237 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/flags.d.ts +25 -0
- package/dist/commands/flags.js +100 -0
- package/dist/commands/flags.js.map +1 -0
- package/dist/commands/handlers.d.ts +2 -0
- package/dist/commands/handlers.js +26 -0
- package/dist/commands/handlers.js.map +1 -0
- package/dist/commands/http.d.ts +8 -0
- package/dist/commands/http.js +19 -0
- package/dist/commands/http.js.map +1 -0
- package/dist/commands/inbox.d.ts +2 -0
- package/dist/commands/inbox.js +111 -0
- package/dist/commands/inbox.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +272 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.js +35 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/messaging/await.d.ts +43 -0
- package/dist/commands/messaging/await.js +125 -0
- package/dist/commands/messaging/await.js.map +1 -0
- package/dist/commands/messaging/build.d.ts +46 -0
- package/dist/commands/messaging/build.js +66 -0
- package/dist/commands/messaging/build.js.map +1 -0
- package/dist/commands/messaging/http.d.ts +22 -0
- package/dist/commands/messaging/http.js +270 -0
- package/dist/commands/messaging/http.js.map +1 -0
- package/dist/commands/messaging/identity.d.ts +29 -0
- package/dist/commands/messaging/identity.js +63 -0
- package/dist/commands/messaging/identity.js.map +1 -0
- package/dist/commands/messaging/shared.d.ts +53 -0
- package/dist/commands/messaging/shared.js +135 -0
- package/dist/commands/messaging/shared.js.map +1 -0
- package/dist/commands/messaging/state.d.ts +26 -0
- package/dist/commands/messaging/state.js +82 -0
- package/dist/commands/messaging/state.js.map +1 -0
- package/dist/commands/messaging/validate.d.ts +40 -0
- package/dist/commands/messaging/validate.js +193 -0
- package/dist/commands/messaging/validate.js.map +1 -0
- package/dist/commands/messaging/wire.d.ts +133 -0
- package/dist/commands/messaging/wire.js +16 -0
- package/dist/commands/messaging/wire.js.map +1 -0
- package/dist/commands/notify.d.ts +2 -0
- package/dist/commands/notify.js +68 -0
- package/dist/commands/notify.js.map +1 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/commands/registry.js +144 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/stub.d.ts +1 -0
- package/dist/commands/stub.js +9 -0
- package/dist/commands/stub.js.map +1 -0
- package/dist/commands/task.d.ts +2 -0
- package/dist/commands/task.js +223 -0
- package/dist/commands/task.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.js +90 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/config-file.d.ts +38 -0
- package/dist/config-file.js +233 -0
- package/dist/config-file.js.map +1 -0
- package/dist/config.d.ts +64 -0
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -0
- package/dist/envelope.d.ts +25 -0
- package/dist/envelope.js +41 -0
- package/dist/envelope.js.map +1 -0
- package/dist/exit-codes.d.ts +51 -0
- package/dist/exit-codes.js +57 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/help.d.ts +1 -0
- package/dist/help.js +17 -0
- package/dist/help.js.map +1 -0
- package/dist/terminal.d.ts +5 -0
- package/dist/terminal.js +18 -0
- package/dist/terminal.js.map +1 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// `oh-hai ask` (docs/specs/cli.md §4.4) — request a human decision. Subcommands `submit` +
|
|
2
|
+
// `await`. Productized from `scripts/ask.ts`: account-aware bearer, `--json` envelope, §7 exit
|
|
3
|
+
// codes, injectable fetch. `submit` composes + POSTs an ask (REQUIRED idempotency key, ≥1
|
|
4
|
+
// `human:` resolver for a real submit) or replays a captured envelope (§4.8); `await` pull-polls
|
|
5
|
+
// to the terminal resolution.
|
|
6
|
+
import { CliError, buildOk, serializeEnvelope } from "../envelope.js";
|
|
7
|
+
import { parseSubcommandArgs } from "./flags.js";
|
|
8
|
+
import { awaitResolution, printResolution, resolveAwaitTiming } from "./messaging/await.js";
|
|
9
|
+
import { buildAsk } from "./messaging/build.js";
|
|
10
|
+
import { submitEnvelope } from "./messaging/http.js";
|
|
11
|
+
import { requireReplayToken, requireToken, resolveSubmitIdentity } from "./messaging/identity.js";
|
|
12
|
+
import { assertNoForeignFlags, dryRunFlag, printDryRunEnvelope, printSubmitAck, requireNonEmpty, resolveRunId, resumeRoutingSuffix, sanitizeForTerminal, stringFlag } from "./messaging/shared.js";
|
|
13
|
+
import { openResumeState, resolveState } from "./messaging/state.js";
|
|
14
|
+
import { REQUEST_MODES, assertAskEnvelope, hasConcreteHumanResolver, hasHumanResolver, isActor, isCallbackMode, isRequestMode, normalizePushUrl, parseOption, readEnvelopeArg, replayResolvers, } from "./messaging/validate.js";
|
|
15
|
+
const SUBCOMMANDS = ["submit", "await"];
|
|
16
|
+
const ASK_SUBMIT_OPTIONS = {
|
|
17
|
+
title: { type: "string" },
|
|
18
|
+
body: { type: "string" },
|
|
19
|
+
mode: { type: "string" },
|
|
20
|
+
option: { type: "string", multiple: true },
|
|
21
|
+
schema: { type: "string" },
|
|
22
|
+
resolver: { type: "string", multiple: true },
|
|
23
|
+
callback: { type: "string" },
|
|
24
|
+
"callback-url": { type: "string" },
|
|
25
|
+
"idempotency-key": { type: "string" },
|
|
26
|
+
"created-at": { type: "string" },
|
|
27
|
+
"dry-run": { type: "boolean" },
|
|
28
|
+
envelope: { type: "string" },
|
|
29
|
+
state: { type: "string" },
|
|
30
|
+
};
|
|
31
|
+
const ASK_AWAIT_OPTIONS = {
|
|
32
|
+
id: { type: "string" },
|
|
33
|
+
interval: { type: "string" },
|
|
34
|
+
"await-timeout": { type: "string" },
|
|
35
|
+
};
|
|
36
|
+
// The union so the shared parser recognizes every ask flag; each subcommand then rejects the
|
|
37
|
+
// other's exclusive flags (loud-fail, not silent-ignore).
|
|
38
|
+
const ASK_OPTIONS = { ...ASK_SUBMIT_OPTIONS, ...ASK_AWAIT_OPTIONS };
|
|
39
|
+
const AWAIT_ONLY = ["id", "interval", "await-timeout"];
|
|
40
|
+
const SUBMIT_ONLY = Object.keys(ASK_SUBMIT_OPTIONS);
|
|
41
|
+
export async function askCommand(ctx) {
|
|
42
|
+
const { values, subcommand } = parseSubcommandArgs(ctx.argv, SUBCOMMANDS, ASK_OPTIONS);
|
|
43
|
+
const flags = values;
|
|
44
|
+
if (subcommand === "submit") {
|
|
45
|
+
assertNoForeignFlags(flags, AWAIT_ONLY, "ask submit");
|
|
46
|
+
await askSubmit(ctx, flags);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
assertNoForeignFlags(flags, SUBMIT_ONLY, "ask await");
|
|
50
|
+
await askAwait(ctx, flags);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function askSubmit(ctx, flags) {
|
|
54
|
+
// Strict parse: `--dry-run=true` still previews; a malformed `--dry-run=treu` fails as usage
|
|
55
|
+
// rather than silently performing a LIVE submit.
|
|
56
|
+
const dryRun = dryRunFlag(flags["dry-run"]);
|
|
57
|
+
const envelopeRaw = stringFlag(flags.envelope);
|
|
58
|
+
if (envelopeRaw !== undefined) {
|
|
59
|
+
await askReplay(ctx, envelopeRaw, flags, dryRun);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const title = stringFlag(flags.title);
|
|
63
|
+
if (title === undefined || title.trim() === "") {
|
|
64
|
+
throw new CliError("usage", "missing required flag: --title (must be non-empty).");
|
|
65
|
+
}
|
|
66
|
+
const modeRaw = stringFlag(flags.mode);
|
|
67
|
+
if (modeRaw === undefined)
|
|
68
|
+
throw new CliError("usage", "missing required flag: --mode.");
|
|
69
|
+
if (!isRequestMode(modeRaw)) {
|
|
70
|
+
throw new CliError("usage", `invalid --mode "${modeRaw}" (expected one of: ${REQUEST_MODES.join(", ")}).`);
|
|
71
|
+
}
|
|
72
|
+
const mode = modeRaw;
|
|
73
|
+
const callback = resolveCallback(flags);
|
|
74
|
+
const options = resolveOptions(flags, mode);
|
|
75
|
+
const schema = mode === "input" ? resolveSchema(flags) : undefined;
|
|
76
|
+
const resolvers = resolveResolvers(flags, dryRun, ctx);
|
|
77
|
+
const request = { mode, callback };
|
|
78
|
+
if (options.length > 0)
|
|
79
|
+
request.options = options;
|
|
80
|
+
if (schema !== undefined)
|
|
81
|
+
request.schema = schema;
|
|
82
|
+
if (resolvers.length > 0)
|
|
83
|
+
request.allowed_resolvers = resolvers;
|
|
84
|
+
const idempotencyKey = requireNonEmpty(flags, "idempotency-key");
|
|
85
|
+
const createdAt = requireNonEmpty(flags, "created-at");
|
|
86
|
+
const body = stringFlag(flags.body);
|
|
87
|
+
// Seal an optional `--state` resume blob (requires MA2H_STATE_SEAL_KEY) before the dry-run
|
|
88
|
+
// branch so the preview shows the sealed envelope; `ask await` opens it on resolution.
|
|
89
|
+
const state = resolveState(stringFlag(flags.state));
|
|
90
|
+
let agentId = ctx.config.account ?? "oh-hai/ask-bot";
|
|
91
|
+
let token = "";
|
|
92
|
+
if (!dryRun) {
|
|
93
|
+
const identity = await resolveSubmitIdentity(ctx);
|
|
94
|
+
agentId = identity.agentId;
|
|
95
|
+
token = identity.token;
|
|
96
|
+
}
|
|
97
|
+
const ask = buildAsk({
|
|
98
|
+
agent: { id: agentId, run_id: resolveRunId() },
|
|
99
|
+
title,
|
|
100
|
+
request,
|
|
101
|
+
...(body !== undefined ? { body } : {}),
|
|
102
|
+
...(idempotencyKey !== undefined ? { idempotency_key: idempotencyKey } : {}),
|
|
103
|
+
...(createdAt !== undefined ? { created_at: createdAt } : {}),
|
|
104
|
+
...(state !== undefined ? { state } : {}),
|
|
105
|
+
});
|
|
106
|
+
if (dryRun) {
|
|
107
|
+
printDryRunEnvelope(ctx, "ask.submit", ask);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const ack = await submitEnvelope(ctx, token, ask);
|
|
111
|
+
if (ctx.json) {
|
|
112
|
+
ctx.io.log(serializeEnvelope(buildOk("ask.submit", { id: ack.id, poll_url: ack.poll_url, review_url: ack.review_url })));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
printSubmitAck(ctx, "ask submitted", ack, true);
|
|
116
|
+
ctx.io.log(`\nResume (pull): oh-hai ask await --id ${sanitizeForTerminal(ack.id)}${resumeRoutingSuffix(ctx)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Replay a captured ask envelope verbatim (§4.8) — the supported idempotent retry for a lost
|
|
120
|
+
* 202. Extends the human-resolver guard the task replay already enforces to ask replay too. */
|
|
121
|
+
async function askReplay(ctx, envelopeRaw, flags, dryRun) {
|
|
122
|
+
const conflicts = ["title", "body", "mode", "option", "schema", "resolver", "callback", "callback-url", "idempotency-key", "created-at", "state"].filter((k) => flags[k] !== undefined);
|
|
123
|
+
if (conflicts.length > 0) {
|
|
124
|
+
throw new CliError("usage", `--envelope replays a captured envelope verbatim and cannot be combined with composition flags (${conflicts.map((k) => `--${k}`).join(", ")}).`);
|
|
125
|
+
}
|
|
126
|
+
// readEnvelopeArg may throw a usage CliError (missing @file); only the JSON.parse is wrapped, so
|
|
127
|
+
// a truncated/invalid captured envelope is a usage error (exit 2), not the generic error path.
|
|
128
|
+
const raw = await readEnvelopeArg(envelopeRaw, ctx.runtime.readStdin);
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = JSON.parse(raw);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
throw new CliError("usage", `--envelope is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
135
|
+
}
|
|
136
|
+
const envelope = assertAskEnvelope(parsed);
|
|
137
|
+
if (!hasConcreteHumanResolver(replayResolvers(envelope))) {
|
|
138
|
+
if (!dryRun) {
|
|
139
|
+
throw new CliError("usage", "--envelope ask has no concrete human:<id> resolver in request.allowed_resolvers (a wildcard can " +
|
|
140
|
+
"never match): the resolve route is human-only, so it could never be answered and would sit open " +
|
|
141
|
+
"until expiry. Capture the envelope with a concrete human resolver. (Use --dry-run to preview anyway.)");
|
|
142
|
+
}
|
|
143
|
+
ctx.io.err("⚠ --envelope ask has no concrete human:<id> resolver: this previewed replay would be UNANSWERABLE.");
|
|
144
|
+
}
|
|
145
|
+
if (dryRun) {
|
|
146
|
+
printDryRunEnvelope(ctx, "ask.submit", envelope);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const token = await requireReplayToken(ctx, envelope.agent.id);
|
|
150
|
+
const ack = await submitEnvelope(ctx, token, envelope);
|
|
151
|
+
if (ctx.json) {
|
|
152
|
+
ctx.io.log(serializeEnvelope(buildOk("ask.submit", { id: ack.id, poll_url: ack.poll_url, review_url: ack.review_url })));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
printSubmitAck(ctx, "ask submitted (replayed envelope)", ack, true);
|
|
156
|
+
ctx.io.log(`\nResume (pull): oh-hai ask await --id ${sanitizeForTerminal(ack.id)}${resumeRoutingSuffix(ctx)}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function askAwait(ctx, flags) {
|
|
160
|
+
const id = stringFlag(flags.id);
|
|
161
|
+
if (id === undefined || id.trim() === "")
|
|
162
|
+
throw new CliError("usage", "missing required flag: --id.");
|
|
163
|
+
const { intervalMs, budgetMs, perRequestMs } = resolveAwaitTiming(ctx, stringFlag(flags.interval), stringFlag(flags["await-timeout"]), stringFlag(flags.timeout));
|
|
164
|
+
const token = await requireToken(ctx);
|
|
165
|
+
const body = await awaitResolution(ctx, { token, id, expectedType: "ask", intervalMs, budgetMs, perRequestMs });
|
|
166
|
+
// Open the agent-owned sealed `state` when MA2H_STATE_SEAL_KEY is set (undefined otherwise).
|
|
167
|
+
const openedState = openResumeState(body);
|
|
168
|
+
printResolution(ctx, body, true, openedState);
|
|
169
|
+
}
|
|
170
|
+
// --- composition helpers ---
|
|
171
|
+
function resolveCallback(flags) {
|
|
172
|
+
const callbackRaw = stringFlag(flags.callback) ?? "pull";
|
|
173
|
+
if (!isCallbackMode(callbackRaw)) {
|
|
174
|
+
throw new CliError("usage", `invalid --callback "${callbackRaw}" (expected one of: pull, push).`);
|
|
175
|
+
}
|
|
176
|
+
const callbackUrl = stringFlag(flags["callback-url"]);
|
|
177
|
+
if (callbackRaw === "push") {
|
|
178
|
+
if (callbackUrl === undefined || callbackUrl.trim() === "") {
|
|
179
|
+
throw new CliError("usage", "--callback push requires --callback-url.");
|
|
180
|
+
}
|
|
181
|
+
return { mode: "push", url: normalizePushUrl(callbackUrl) };
|
|
182
|
+
}
|
|
183
|
+
// Reject a stray --callback-url in pull mode rather than silently dropping it — an agent
|
|
184
|
+
// expecting a push re-invoke would otherwise wait forever for a callback never enqueued.
|
|
185
|
+
if (callbackUrl !== undefined) {
|
|
186
|
+
throw new CliError("usage", `--callback-url is only valid with --callback push (got --callback ${callbackRaw}).`);
|
|
187
|
+
}
|
|
188
|
+
return { mode: "pull" };
|
|
189
|
+
}
|
|
190
|
+
function resolveOptions(flags, mode) {
|
|
191
|
+
const raw = Array.isArray(flags.option) ? flags.option.filter((o) => typeof o === "string") : [];
|
|
192
|
+
let options = raw.map(parseOption);
|
|
193
|
+
// Mirror the Hub's per-mode option rules so a shape mistake fails locally, not as a remote 422.
|
|
194
|
+
if (mode === "confirm" && options.length === 0) {
|
|
195
|
+
options = [
|
|
196
|
+
{ value: "yes", label: "Yes" },
|
|
197
|
+
{ value: "no", label: "No" },
|
|
198
|
+
];
|
|
199
|
+
}
|
|
200
|
+
if (mode === "confirm" && options.length !== 2) {
|
|
201
|
+
throw new CliError("usage", "--mode confirm requires exactly two --option value:label choices.");
|
|
202
|
+
}
|
|
203
|
+
if (mode === "select" && options.length < 2) {
|
|
204
|
+
throw new CliError("usage", "--mode select requires at least two --option value:label choices.");
|
|
205
|
+
}
|
|
206
|
+
return options;
|
|
207
|
+
}
|
|
208
|
+
function resolveSchema(flags) {
|
|
209
|
+
const schemaRaw = stringFlag(flags.schema);
|
|
210
|
+
if (schemaRaw === undefined)
|
|
211
|
+
throw new CliError("usage", "--mode input requires --schema <json>.");
|
|
212
|
+
let parsed;
|
|
213
|
+
try {
|
|
214
|
+
parsed = JSON.parse(schemaRaw);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
throw new CliError("usage", "--schema must be valid JSON.");
|
|
218
|
+
}
|
|
219
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
220
|
+
throw new CliError("usage", "--schema must be a JSON object.");
|
|
221
|
+
}
|
|
222
|
+
return parsed;
|
|
223
|
+
}
|
|
224
|
+
function resolveResolvers(flags, dryRun, ctx) {
|
|
225
|
+
const raw = Array.isArray(flags.resolver) ? flags.resolver.filter((r) => typeof r === "string") : [];
|
|
226
|
+
const resolvers = [];
|
|
227
|
+
for (const r of raw) {
|
|
228
|
+
if (!isActor(r))
|
|
229
|
+
throw new CliError("usage", `invalid --resolver "${r}" (expected <human|agent|system>:<id>).`);
|
|
230
|
+
// The Hub matches allowed_resolvers literally — a `*` id can never equal a concrete resolver,
|
|
231
|
+
// making the ask unanswerable. Reject it locally rather than letting it sit open until expiry.
|
|
232
|
+
if (r.slice(r.indexOf(":") + 1).includes("*")) {
|
|
233
|
+
throw new CliError("usage", `invalid --resolver "${r}": wildcards are not supported — name a concrete actor like human:owner.`);
|
|
234
|
+
}
|
|
235
|
+
resolvers.push(r);
|
|
236
|
+
}
|
|
237
|
+
if (!hasHumanResolver(resolvers)) {
|
|
238
|
+
if (!dryRun) {
|
|
239
|
+
throw new CliError("usage", "an ask needs at least one --resolver human:<id> — the resolve route is human-only and fails closed, " +
|
|
240
|
+
"so an ask with no human resolver can never be answered. (Use --dry-run to preview without one.)");
|
|
241
|
+
}
|
|
242
|
+
ctx.io.err("⚠ no --resolver human:<id> given: this previewed ask would be UNANSWERABLE (resolve is human-only).");
|
|
243
|
+
}
|
|
244
|
+
return resolvers;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { ResolvedConfig } from "../config.js";
|
|
2
|
+
import type { LoadedConfigFiles } from "../config-file.js";
|
|
3
|
+
import type { CredentialStore, OpenStoreOptions } from "../auth/token-store.js";
|
|
4
|
+
/** Output sink — the same shape `cli.ts` uses, so tests capture stdout/stderr in-process. */
|
|
5
|
+
export interface Io {
|
|
6
|
+
log(line: string): void;
|
|
7
|
+
err(line: string): void;
|
|
8
|
+
}
|
|
9
|
+
/** A minimal structural view of an HTTP response. `status` is always consulted; `json` is read
|
|
10
|
+
* only by callers that need the body (the device-code flow, §4.3). It is OPTIONAL so a
|
|
11
|
+
* status-only fake (`{ status: 404 }`, as `whoami --check` uses) still satisfies the type — the
|
|
12
|
+
* DOM `Response` provides both, so the production `fetch` is structurally assignable either way. */
|
|
13
|
+
export interface HttpResponse {
|
|
14
|
+
status: number;
|
|
15
|
+
json?(): Promise<unknown>;
|
|
16
|
+
/** Response headers — only `Retry-After` on a 429 is read (by the device-code poll's back-off).
|
|
17
|
+
* Optional so a status-only fake (`{ status: 404 }`) still satisfies the type; the DOM
|
|
18
|
+
* `Response.headers` (a `Headers`) is structurally assignable to `{ get(name): string | null }`. */
|
|
19
|
+
headers?: {
|
|
20
|
+
get(name: string): string | null;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** The subset of `fetch` the CLI uses. `body` carries a JSON request payload (the device-code
|
|
24
|
+
* POSTs); it's optional so a bodyless GET (`whoami --check`) is unaffected. Real `fetch`'s return
|
|
25
|
+
* type is structurally assignable. */
|
|
26
|
+
export type FetchLike = (url: string, init: {
|
|
27
|
+
method: string;
|
|
28
|
+
headers: Record<string, string>;
|
|
29
|
+
body?: string;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}) => Promise<HttpResponse>;
|
|
32
|
+
/** Side-effecting dependencies, injected so command tests stay hermetic. */
|
|
33
|
+
export interface RuntimeDeps {
|
|
34
|
+
/** Open the credential store (selects keychain vs `0600` file fallback). */
|
|
35
|
+
openStore: (options?: OpenStoreOptions) => Promise<CredentialStore>;
|
|
36
|
+
/** Read all of stdin as a UTF-8 string (used by `login --token-stdin`). */
|
|
37
|
+
readStdin: () => Promise<string>;
|
|
38
|
+
/** Read a SINGLE line from stdin, for interactive prompts (the `agents revoke` confirm). Distinct
|
|
39
|
+
* from `readStdin`: a TTY prompt must resolve on Enter, not block until EOF. Optional — a caller
|
|
40
|
+
* that omits it falls back to `readStdin` (fine for the piped/hermetic paths). */
|
|
41
|
+
readLine?: () => Promise<string>;
|
|
42
|
+
/** HTTP client (used by `whoami --check` and the `login` device-code flow). */
|
|
43
|
+
fetchImpl: FetchLike;
|
|
44
|
+
/** Load the user-global + per-project config files (§6). Injected so tests never read real disk. */
|
|
45
|
+
loadConfigFiles: () => LoadedConfigFiles;
|
|
46
|
+
/** Sleep `ms` milliseconds between device-code polls (§4.3). Injected so tests don't actually
|
|
47
|
+
* wait — a no-op keeps the happy path instant, and a recording sleep lets a test assert the
|
|
48
|
+
* `slow_down` backoff grew the interval. */
|
|
49
|
+
sleep: (ms: number) => Promise<void>;
|
|
50
|
+
/** Await any buffered stdout being flushed to the consumer (`inbox watch` calls this before acking a
|
|
51
|
+
* drained batch, so the emit-then-ack handoff stays at-least-once under pipe backpressure). Optional
|
|
52
|
+
* — a caller that omits it (and every hermetic test) skips the wait, since in-memory IO never
|
|
53
|
+
* backpressures. Production awaits `process.stdout` drain. */
|
|
54
|
+
flushOutput?: () => Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
export interface CommandContext {
|
|
57
|
+
io: Io;
|
|
58
|
+
/** True when `--json` selected the machine envelope (§8). */
|
|
59
|
+
json: boolean;
|
|
60
|
+
config: ResolvedConfig;
|
|
61
|
+
runtime: RuntimeDeps;
|
|
62
|
+
/** The full argv passed to `run()`, for per-command flag parsing (§4.2). */
|
|
63
|
+
argv: string[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A command handler. Most handlers return `void` (the entrypoint then uses `ExitCode.SUCCESS`);
|
|
67
|
+
* a handler MAY instead resolve to a numeric exit code when it has already printed its own
|
|
68
|
+
* output but must still signal a non-zero exit — `doctor` (§4.6) does this so it can emit its
|
|
69
|
+
* full checks report (human table or the `--json` `data.checks` envelope) AND exit non-zero on a
|
|
70
|
+
* failed required check, which a thrown `CliError` can't do without clobbering the envelope.
|
|
71
|
+
*/
|
|
72
|
+
export type CommandHandler = (ctx: CommandContext) => Promise<void | number>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Shared command-execution context (docs/specs/cli.md §4). A command handler receives the
|
|
2
|
+
// resolved config, an injectable IO sink, and a small bundle of runtime dependencies (the
|
|
3
|
+
// credential store opener, a stdin reader, and an HTTP client). Everything a handler touches
|
|
4
|
+
// that has a side effect is injected here so tests never open the real OS keychain, read the
|
|
5
|
+
// real stdin, or hit a live Hub.
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,0FAA0F;AAC1F,6FAA6F;AAC7F,6FAA6F;AAC7F,iCAAiC"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// `oh-hai doctor` (docs/specs/cli.md §4.6) — diagnose setup. Runs a series of checks and reports
|
|
2
|
+
// each pass/fail. REQUIRED checks (a failure → non-zero exit): config resolution and token
|
|
3
|
+
// presence. Keychain availability is required ONLY when the token actually resolved from the
|
|
4
|
+
// keychain; ADVISORY when it came from MA2H_AGENT_TOKEN (env/CI) or the 0600 file fallback — both
|
|
5
|
+
// valid headless setups with no working keychain (§5.2/§5.3). ADVISORY checks (reported, never
|
|
6
|
+
// fail the exit code): Hub connectivity and the opt-in --test-notify, which sends a real
|
|
7
|
+
// low-priority notify to confirm the end-to-end path (the onboarding "aha"). Local checks work
|
|
8
|
+
// offline; connectivity/test-notify are network checks (§9). The token is never printed (§5.4).
|
|
9
|
+
// `--json` → data: { checks: [{ name, status, detail }] }.
|
|
10
|
+
//
|
|
11
|
+
// A handler can normally only influence the exit code by THROWING, but a throw under --json yields
|
|
12
|
+
// a buildErr envelope (data: null), which would drop the checks array exactly when the caller
|
|
13
|
+
// needs it. So doctor RETURNS its exit code (CommandHandler resolves to `void | number`): it prints
|
|
14
|
+
// the full report either way, then returns the first failing REQUIRED check's exit code, or `void`
|
|
15
|
+
// (exit 0) when every required check passed.
|
|
16
|
+
import { resolveIdentity } from "../auth/resolve-token.js";
|
|
17
|
+
import { buildOk, serializeEnvelope } from "../envelope.js";
|
|
18
|
+
import { ExitCode } from "../exit-codes.js";
|
|
19
|
+
import { sanitizeForTerminal } from "../terminal.js";
|
|
20
|
+
import { flagOn, parseCommandArgs } from "./flags.js";
|
|
21
|
+
import { buildNotify } from "./messaging/build.js";
|
|
22
|
+
import { submitEnvelope } from "./messaging/http.js";
|
|
23
|
+
import { resolveSubmitIdentity } from "./messaging/identity.js";
|
|
24
|
+
import { resolveRunId } from "./messaging/shared.js";
|
|
25
|
+
/** Default per-request bound for the network probes when no --timeout/MA2H_TIMEOUT_MS is set —
|
|
26
|
+
* §9 promises offline is an explicit state, never a silent hang. Mirrors whoami's checkToken. */
|
|
27
|
+
const DEFAULT_PROBE_TIMEOUT_MS = 10_000;
|
|
28
|
+
/** Node's setTimeout/AbortSignal.timeout ceiling — a larger delay throws a RangeError (>2^32-1) or
|
|
29
|
+
* overflows to ~immediate (>2^31-1). Mirrors messaging/http.ts. */
|
|
30
|
+
const MAX_TIMER_MS = 2_147_483_647;
|
|
31
|
+
const STATUS_MARK = { pass: "✔", warn: "!", fail: "✖" };
|
|
32
|
+
/** The per-request bound for the connectivity probe: `config.timeoutMs` (from --timeout /
|
|
33
|
+
* MA2H_TIMEOUT_MS / config, §6), defaulted on absent/0/negative and clamped to the timer ceiling.
|
|
34
|
+
* Without the clamp an oversized value would throw a RangeError out of `AbortSignal.timeout` (which
|
|
35
|
+
* is built before the fetch try, so it would crash doctor report-less); without the `>0` guard a
|
|
36
|
+
* configured `0` would abort immediately and falsely report the Hub unreachable. Mirrors
|
|
37
|
+
* messaging/http.ts's requestTimeoutMs so doctor and the messaging commands agree. */
|
|
38
|
+
function probeTimeoutMs(ctx) {
|
|
39
|
+
const t = ctx.config.timeoutMs;
|
|
40
|
+
return Math.min(t !== undefined && t > 0 ? t : DEFAULT_PROBE_TIMEOUT_MS, MAX_TIMER_MS);
|
|
41
|
+
}
|
|
42
|
+
/** Probe the Hub for reachability with a side-effect-free GET of a nonexistent message id (a GET
|
|
43
|
+
* creates nothing). With a bearer this doubles as a validity check — the Hub authenticates BEFORE
|
|
44
|
+
* looking the id up, so `404` proves the presented token authenticated (whoami --check parity).
|
|
45
|
+
* Purely advisory: every outcome is `pass` (reachable + healthy) or `warn` (unreachable, or
|
|
46
|
+
* reachable-but-off); it never fails doctor's exit code (§4.6). */
|
|
47
|
+
async function probeConnectivity(ctx, token) {
|
|
48
|
+
const url = `${ctx.config.baseUrl}/v1/messages/oh-hai-doctor-connectivity-probe`;
|
|
49
|
+
const init = {
|
|
50
|
+
method: "GET",
|
|
51
|
+
headers: token !== undefined ? { Authorization: `Bearer ${token}` } : {},
|
|
52
|
+
signal: AbortSignal.timeout(probeTimeoutMs(ctx)),
|
|
53
|
+
};
|
|
54
|
+
let status;
|
|
55
|
+
try {
|
|
56
|
+
status = (await ctx.runtime.fetchImpl(url, init)).status;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Any transport failure (DNS, connection refused, timeout) → the Hub is unreachable (§9).
|
|
60
|
+
return { name: "connectivity", status: "warn", detail: `Hub unreachable at ${ctx.config.baseUrl}` };
|
|
61
|
+
}
|
|
62
|
+
// Without a bearer we can only assert reachability — any HTTP response proves the Hub answered.
|
|
63
|
+
if (token === undefined) {
|
|
64
|
+
return { name: "connectivity", status: "pass", detail: `Hub reachable (HTTP ${status}); no token to validate` };
|
|
65
|
+
}
|
|
66
|
+
// With a bearer, interpret the status like whoami --check.
|
|
67
|
+
if (status === 404) {
|
|
68
|
+
return { name: "connectivity", status: "pass", detail: "Hub reachable; token valid" };
|
|
69
|
+
}
|
|
70
|
+
if (status === 401 || status === 403) {
|
|
71
|
+
return { name: "connectivity", status: "warn", detail: `Hub reachable but token was rejected (HTTP ${status}); run \`oh-hai login\`` };
|
|
72
|
+
}
|
|
73
|
+
if (status >= 500) {
|
|
74
|
+
return { name: "connectivity", status: "warn", detail: `Hub reachable but returned ${status}; token validity unconfirmed` };
|
|
75
|
+
}
|
|
76
|
+
return { name: "connectivity", status: "warn", detail: `Hub reachable but returned an unexpected ${status}; check --base-url` };
|
|
77
|
+
}
|
|
78
|
+
/** Send a real low-priority notify through the same account-aware path as `oh-hai notify`, to
|
|
79
|
+
* confirm the end-to-end flow lands in the human's inbox (the onboarding "aha", §4.6). Advisory:
|
|
80
|
+
* submitEnvelope throws a CliError on any non-202 (its message is already token-redacted and
|
|
81
|
+
* control-char-sanitized) — caught here and turned into a `warn`, never failing doctor's exit. */
|
|
82
|
+
async function testNotifyCheck(ctx) {
|
|
83
|
+
try {
|
|
84
|
+
const { token, agentId } = await resolveSubmitIdentity(ctx);
|
|
85
|
+
const notify = buildNotify({
|
|
86
|
+
agent: { id: agentId, run_id: resolveRunId() },
|
|
87
|
+
title: "oh-hai doctor test notification",
|
|
88
|
+
body: "Sent by `oh-hai doctor --test-notify` to confirm the end-to-end path.",
|
|
89
|
+
priority: "low",
|
|
90
|
+
});
|
|
91
|
+
const ack = await submitEnvelope(ctx, token, notify);
|
|
92
|
+
return { name: "test-notify", status: "pass", detail: `posted (id ${ack.id})` };
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
96
|
+
return { name: "test-notify", status: "warn", detail: `could not send test notify — ${message}` };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Emit the collected checks: the uniform --json envelope (data.checks, exactly name/status/detail),
|
|
100
|
+
* or a human table with a per-status marker. Details are sanitized on BOTH paths (§5.4): some carry
|
|
101
|
+
* Hub-supplied strings (a device-code-login discovered agent id, a --test-notify ack id), and
|
|
102
|
+
* `JSON.stringify` does NOT escape C1 (U+0080–009F) or DEL — so relying on it for --json would echo
|
|
103
|
+
* those raw into a consumer's terminal. `exitCode` is internal and never serialized. */
|
|
104
|
+
function emitReport(ctx, checks) {
|
|
105
|
+
if (ctx.json) {
|
|
106
|
+
ctx.io.log(serializeEnvelope(buildOk("doctor", {
|
|
107
|
+
checks: checks.map(({ name, status, detail }) => ({ name, status, detail: sanitizeForTerminal(detail) })),
|
|
108
|
+
})));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
ctx.io.log("oh-hai doctor");
|
|
112
|
+
for (const check of checks) {
|
|
113
|
+
ctx.io.log(` ${STATUS_MARK[check.status]} ${check.name.padEnd(12)} ${sanitizeForTerminal(check.detail)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export async function doctorCommand(ctx) {
|
|
117
|
+
const { values } = parseCommandArgs(ctx.argv, { "test-notify": { type: "boolean" } });
|
|
118
|
+
const testNotify = flagOn(values["test-notify"]);
|
|
119
|
+
// Open the store once and reuse it for BOTH the keychain-availability signal and identity
|
|
120
|
+
// resolution. Unlike whoami (which skips the store for an env token), doctor opens it even for an
|
|
121
|
+
// env token — reporting keychain status is the point of a diagnostic, and openStore()'s probe is
|
|
122
|
+
// already timeout-bounded so this is safe headless. A diagnostic must SURVIVE a broken store: a
|
|
123
|
+
// keychain read error (KeychainBackend throws on an "error" status) would otherwise crash doctor
|
|
124
|
+
// before it prints anything, so a store/identity failure degrades into a reported check.
|
|
125
|
+
let keychainAvailable = false;
|
|
126
|
+
let account;
|
|
127
|
+
let token;
|
|
128
|
+
let source = "none";
|
|
129
|
+
let storeError;
|
|
130
|
+
try {
|
|
131
|
+
const store = await ctx.runtime.openStore();
|
|
132
|
+
keychainAvailable = store.backendName === "keychain";
|
|
133
|
+
({ account, token, source } = await resolveIdentity(ctx.config, store));
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
storeError = error instanceof Error ? error.message : String(error);
|
|
137
|
+
}
|
|
138
|
+
const checks = [];
|
|
139
|
+
// 1. config resolution (REQUIRED). resolveConfig already ran in cli.ts; the checks doctor can
|
|
140
|
+
// still make are: (a) the resolved base URL is a usable HTTP(S) URL — a bad --base-url passes
|
|
141
|
+
// resolveConfig verbatim and would otherwise only fail at fetch time (and `new URL()` alone is
|
|
142
|
+
// too weak: it accepts a non-http scheme and parses a scheme-less `localhost:8787` as protocol
|
|
143
|
+
// `localhost:`), and (b) an authenticated caller has a resolvable agent id — a token with no
|
|
144
|
+
// account can't submit notify/ask/task (resolveSubmitIdentity requires the id), so it's a
|
|
145
|
+
// config failure, not a clean pass. When there's NO token, the token check below carries the
|
|
146
|
+
// failure (a fresh user needs `oh-hai login`, not `--account`), so the missing account isn't
|
|
147
|
+
// re-flagged here.
|
|
148
|
+
let baseUrlScheme;
|
|
149
|
+
try {
|
|
150
|
+
baseUrlScheme = new URL(ctx.config.baseUrl).protocol;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
baseUrlScheme = undefined;
|
|
154
|
+
}
|
|
155
|
+
if (baseUrlScheme !== "http:" && baseUrlScheme !== "https:") {
|
|
156
|
+
checks.push({
|
|
157
|
+
name: "config",
|
|
158
|
+
status: "fail",
|
|
159
|
+
detail: `base URL must be an http(s) URL: ${ctx.config.baseUrl}`,
|
|
160
|
+
exitCode: ExitCode.USAGE,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
else if (token !== undefined && account === undefined) {
|
|
164
|
+
checks.push({
|
|
165
|
+
name: "config",
|
|
166
|
+
status: "fail",
|
|
167
|
+
detail: "authenticated but no agent id resolved — set --account/MA2H_AGENT_ID (notify/ask/task can't submit without it)",
|
|
168
|
+
exitCode: ExitCode.USAGE,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const accountPart = account !== undefined
|
|
173
|
+
? `account ${account}`
|
|
174
|
+
: "no account resolved (pass --account, or log in so a single stored identity is discovered)";
|
|
175
|
+
checks.push({ name: "config", status: "pass", detail: `base URL ${ctx.config.baseUrl} · ${accountPart}` });
|
|
176
|
+
}
|
|
177
|
+
// 2. token presence (REQUIRED). A store read failure is reported here (no usable token → exit
|
|
178
|
+
// AUTH), distinct from a clean "no stored token".
|
|
179
|
+
if (storeError !== undefined) {
|
|
180
|
+
checks.push({
|
|
181
|
+
name: "token",
|
|
182
|
+
status: "fail",
|
|
183
|
+
detail: `could not read the credential store — ${storeError}`,
|
|
184
|
+
exitCode: ExitCode.AUTH,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else if (token !== undefined) {
|
|
188
|
+
checks.push({ name: "token", status: "pass", detail: `present [${source}]` });
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
checks.push({
|
|
192
|
+
name: "token",
|
|
193
|
+
status: "fail",
|
|
194
|
+
detail: "no stored token — run `oh-hai login`, or set MA2H_AGENT_TOKEN",
|
|
195
|
+
exitCode: ExitCode.AUTH,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
// 3. keychain availability (ADVISORY except when the token came from the keychain, where it is
|
|
199
|
+
// necessarily available → pass). A token that resolved from the UNENCRYPTED 0600 file
|
|
200
|
+
// (`source === "file"`) is always a warn — even when the keychain IS available, because that
|
|
201
|
+
// means a stale plaintext copy (written during a past keychain outage) is being used and the
|
|
202
|
+
// keychain-`pass` line would hide it (§5.2). An env token / no token with an available keychain
|
|
203
|
+
// is a clean pass; an unavailable keychain (env / none) warns that the file fallback is in play.
|
|
204
|
+
if (storeError !== undefined) {
|
|
205
|
+
checks.push({ name: "keychain", status: "warn", detail: `could not probe the OS keychain — ${storeError}` });
|
|
206
|
+
}
|
|
207
|
+
else if (source === "file") {
|
|
208
|
+
checks.push({
|
|
209
|
+
name: "keychain",
|
|
210
|
+
status: "warn",
|
|
211
|
+
detail: keychainAvailable
|
|
212
|
+
? "token resolved from the 0600 file fallback though the OS keychain is available — re-run `oh-hai login` to move it into the keychain (§5.2)"
|
|
213
|
+
: "OS keychain unavailable — token stored in the 0600 file fallback (§5.2)",
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else if (keychainAvailable) {
|
|
217
|
+
checks.push({ name: "keychain", status: "pass", detail: "OS keychain available" });
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const detail = source === "env"
|
|
221
|
+
? "OS keychain unavailable — using MA2H_AGENT_TOKEN (headless/CI, §5.3)"
|
|
222
|
+
: "OS keychain unavailable — the 0600 file fallback would be used (§5.2)";
|
|
223
|
+
checks.push({ name: "keychain", status: "warn", detail });
|
|
224
|
+
}
|
|
225
|
+
// 4. Hub connectivity (ADVISORY).
|
|
226
|
+
checks.push(await probeConnectivity(ctx, token));
|
|
227
|
+
// 5. test-notify (ADVISORY, opt-in).
|
|
228
|
+
if (testNotify) {
|
|
229
|
+
checks.push(await testNotifyCheck(ctx));
|
|
230
|
+
}
|
|
231
|
+
emitReport(ctx, checks);
|
|
232
|
+
// Exit code = the first failing REQUIRED check's code (config is checked before token, so a bad
|
|
233
|
+
// base URL wins over a missing token); undefined (→ exit 0) when every required check passed.
|
|
234
|
+
const failed = checks.find((check) => check.status === "fail");
|
|
235
|
+
return failed !== undefined ? failed.exitCode ?? ExitCode.ERROR : undefined;
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=doctor.js.map
|