@oh-hai/cli 0.2.3 → 0.3.1
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/CHANGELOG.md +125 -0
- package/README.md +59 -29
- package/dist/commands/ask.js +71 -10
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/bridge.d.ts +2 -0
- package/dist/commands/bridge.js +502 -0
- package/dist/commands/bridge.js.map +1 -0
- package/dist/commands/context.d.ts +22 -0
- package/dist/commands/doctor.js +12 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/fleet.d.ts +2 -0
- package/dist/commands/fleet.js +164 -0
- package/dist/commands/fleet.js.map +1 -0
- package/dist/commands/handlers.js +8 -0
- package/dist/commands/handlers.js.map +1 -1
- package/dist/commands/messages.d.ts +2 -0
- package/dist/commands/messages.js +131 -0
- package/dist/commands/messages.js.map +1 -0
- package/dist/commands/messaging/build.d.ts +10 -1
- package/dist/commands/messaging/build.js +22 -4
- package/dist/commands/messaging/build.js.map +1 -1
- package/dist/commands/messaging/capability.d.ts +42 -0
- package/dist/commands/messaging/capability.js +164 -0
- package/dist/commands/messaging/capability.js.map +1 -0
- package/dist/commands/messaging/http.d.ts +28 -1
- package/dist/commands/messaging/http.js +234 -13
- package/dist/commands/messaging/http.js.map +1 -1
- package/dist/commands/messaging/inbox-entries.d.ts +83 -0
- package/dist/commands/messaging/inbox-entries.js +371 -0
- package/dist/commands/messaging/inbox-entries.js.map +1 -0
- package/dist/commands/messaging/inbox-stream.d.ts +37 -0
- package/dist/commands/messaging/inbox-stream.js +224 -0
- package/dist/commands/messaging/inbox-stream.js.map +1 -0
- package/dist/commands/messaging/session-drain.d.ts +50 -0
- package/dist/commands/messaging/session-drain.js +163 -0
- package/dist/commands/messaging/session-drain.js.map +1 -0
- package/dist/commands/messaging/session-scope.d.ts +93 -0
- package/dist/commands/messaging/session-scope.js +0 -0
- package/dist/commands/messaging/session-scope.js.map +1 -0
- package/dist/commands/messaging/sessions-http.d.ts +20 -0
- package/dist/commands/messaging/sessions-http.js +153 -0
- package/dist/commands/messaging/sessions-http.js.map +1 -0
- package/dist/commands/messaging/shared.d.ts +19 -1
- package/dist/commands/messaging/shared.js +69 -2
- package/dist/commands/messaging/shared.js.map +1 -1
- package/dist/commands/messaging/validate.d.ts +33 -1
- package/dist/commands/messaging/validate.js +78 -0
- package/dist/commands/messaging/validate.js.map +1 -1
- package/dist/commands/messaging/wire.d.ts +180 -3
- package/dist/commands/notify.js +47 -5
- package/dist/commands/notify.js.map +1 -1
- package/dist/commands/registry.js +128 -3
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/self-test.d.ts +17 -0
- package/dist/commands/self-test.js +472 -0
- package/dist/commands/self-test.js.map +1 -0
- package/dist/commands/session.d.ts +2 -0
- package/dist/commands/session.js +158 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.js +44 -0
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/task.js +61 -11
- package/dist/commands/task.js.map +1 -1
- package/dist/commands/teach.js +84 -4
- package/dist/commands/teach.js.map +1 -1
- package/dist/commands/whoami.js +14 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/exit-codes.d.ts +37 -1
- package/dist/exit-codes.js +42 -1
- package/dist/exit-codes.js.map +1 -1
- package/dist/help.js +5 -1
- package/dist/help.js.map +1 -1
- package/dist/watch-lock.js +7 -0
- package/dist/watch-lock.js.map +1 -1
- package/package.json +5 -4
|
@@ -10,11 +10,17 @@ export type Runtime = "github-actions" | "cli" | "cloud" | "desktop" | "openclaw
|
|
|
10
10
|
export type RequestMode = "select" | "input" | "confirm";
|
|
11
11
|
/** Hub-attested resolver identity: `<type>:<id>` (spec §9.1). */
|
|
12
12
|
export type Actor = `${"human" | "agent" | "system"}:${string}`;
|
|
13
|
+
/** A §4 destination address (v0.5): `agent:<id>` or `agent:<id>#<sess_…>`. The FIRST `#` is the
|
|
14
|
+
* separator, so a `#`-bearing agent id is inexpressible — matching the wire grammar exactly. */
|
|
15
|
+
export type AgentAddress = `agent:${string}`;
|
|
13
16
|
export interface AgentDescriptor {
|
|
14
17
|
id: string;
|
|
15
18
|
run_id: string;
|
|
16
19
|
runtime: Runtime;
|
|
17
20
|
project?: string;
|
|
21
|
+
/** v0.5 §4.1/§16.2: the submitter's own LIVE session. Binds the Caller mailbox for a response
|
|
22
|
+
* and is client-originated lease renewal. Only legal on an envelope declaring >= 0.5. */
|
|
23
|
+
session?: string;
|
|
18
24
|
}
|
|
19
25
|
export interface ResponseOption {
|
|
20
26
|
value: string;
|
|
@@ -44,8 +50,13 @@ export interface TaskAction {
|
|
|
44
50
|
allowed_resolvers?: Actor[];
|
|
45
51
|
callback?: Callback;
|
|
46
52
|
}
|
|
53
|
+
/** The wire versions this CLI composes. `0.3` is the unchanged human-inbox envelope; `0.5` is
|
|
54
|
+
* stamped ONLY on an envelope that carries v0.5 addressing vocabulary (`to` / `agent.session`) —
|
|
55
|
+
* the Hub routes schema validation by DECLARED minor and refuses either field on a pre-0.5
|
|
56
|
+
* envelope (`422 invalid_field`), so the declared version has to move with the fields. */
|
|
57
|
+
export type WireVersion = "0.3" | "0.5";
|
|
47
58
|
interface BaseEnvelope {
|
|
48
|
-
ma2h_version:
|
|
59
|
+
ma2h_version: WireVersion;
|
|
49
60
|
created_at: string;
|
|
50
61
|
agent: AgentDescriptor;
|
|
51
62
|
title: string;
|
|
@@ -55,6 +66,9 @@ interface BaseEnvelope {
|
|
|
55
66
|
/** Agent-owned, agent-integrity-sealed resume blob (`{ sealed: "MA2HSEALv1.…" }`, via `--state`).
|
|
56
67
|
* Opaque to the Hub (MUST NOT inspect/log — spec §9.3). Sealed by `state.ts` on submit. */
|
|
57
68
|
state?: JsonObject;
|
|
69
|
+
/** v0.5 §4: an optional agent destination (`--to`). Absent = the human inbox, unchanged. Only
|
|
70
|
+
* legal on an envelope declaring >= 0.5. */
|
|
71
|
+
to?: AgentAddress;
|
|
58
72
|
}
|
|
59
73
|
export interface NotifyMessage extends BaseEnvelope {
|
|
60
74
|
type: "notify";
|
|
@@ -74,7 +88,19 @@ export type A2hMessage = NotifyMessage | AskMessage | TaskMessage;
|
|
|
74
88
|
export type AskResolution = "answered" | "declined" | "cancelled" | "expired";
|
|
75
89
|
export type TaskResolution = "completed" | "dismissed" | "expired";
|
|
76
90
|
export type Resolution = AskResolution | TaskResolution;
|
|
77
|
-
|
|
91
|
+
/** The v0.5 §14.2 DELIVERY-track states, reachable only on an ADDRESSED message (`to` present):
|
|
92
|
+
* `queued` at accept, `acknowledged` once the addressee consumes the mailbox entry, `bounced`
|
|
93
|
+
* when the destination goes terminal before it does. Distinct from the §7 RESOLUTION track above —
|
|
94
|
+
* an addressed ask still reports `open` there, because `open` asserts nothing about delivery.
|
|
95
|
+
*
|
|
96
|
+
* This mirror is hand-maintained (see the file header on why the CLI re-declares the wire types),
|
|
97
|
+
* which is exactly why it was left behind when the server widened for v0.5 (#649 review residual):
|
|
98
|
+
* a mirror that is merely stale is invisible until the day the new values arrive on the wire, and
|
|
99
|
+
* addressed sends are the day. Un-widened, `messages list --status queued` would be rejected
|
|
100
|
+
* locally as an invalid filter for a state the Hub plainly reports, and `isValidTypeStatus`
|
|
101
|
+
* (http.ts) would reject a legitimate `queued` poll body as malformed. */
|
|
102
|
+
export type DeliveryStatus = "queued" | "acknowledged" | "bounced";
|
|
103
|
+
export type Status = "open" | "delivered" | DeliveryStatus | Resolution;
|
|
78
104
|
export interface ResponseDetail {
|
|
79
105
|
/** ask only: chosen option value (string) or the input object. Absent for task. */
|
|
80
106
|
value?: string | JsonObject;
|
|
@@ -91,11 +117,28 @@ export interface A2hResponse {
|
|
|
91
117
|
response?: ResponseDetail;
|
|
92
118
|
state?: JsonObject;
|
|
93
119
|
}
|
|
120
|
+
/** Presence states a Hub may report for a destination (spec §15). `unknown` is the honest "no
|
|
121
|
+
* visibility here" — never a claim of liveness — and MUST carry no `last_seen`. */
|
|
122
|
+
export type PresenceState = "online" | "offline" | "unknown";
|
|
123
|
+
/** The destination's §15 reachability at send time, REQUIRED on every addressed-submit ack
|
|
124
|
+
* (v0.5 §8.1). Its presence doubles as the sender's version-misroute detector: a pre-0.5 Hub
|
|
125
|
+
* cannot emit this object at all, so an addressed ack WITHOUT it proves the `to` was ignored and
|
|
126
|
+
* the message filed in a human inbox instead. */
|
|
127
|
+
export interface DestinationSnapshot {
|
|
128
|
+
state: PresenceState;
|
|
129
|
+
last_seen?: string;
|
|
130
|
+
}
|
|
94
131
|
export interface SubmitAck {
|
|
132
|
+
/** The verb's OWNING-track status (spec §8.1) — `open` for any ask/task, `delivered` for a
|
|
133
|
+
* human-inbox notify, `queued` for an ADDRESSED notify. An idempotent replay returns the track's
|
|
134
|
+
* CURRENT status, which for an addressed notify may already be `acknowledged` / `bounced` /
|
|
135
|
+
* `expired` — hence the full `Status` here rather than the accept-time trio. */
|
|
95
136
|
id: string;
|
|
96
|
-
status:
|
|
137
|
+
status: Status;
|
|
97
138
|
poll_url: string;
|
|
98
139
|
review_url?: string;
|
|
140
|
+
/** Present on every ADDRESSED submit ack (v0.5 §8.1); absent on the human-inbox path. */
|
|
141
|
+
destination?: DestinationSnapshot;
|
|
99
142
|
}
|
|
100
143
|
/** GET /v1/messages/:id — the stored envelope plus its lifecycle status and terminal Response. */
|
|
101
144
|
export type GetMessageBody = A2hMessage & {
|
|
@@ -130,4 +173,138 @@ export interface InboundDelivery {
|
|
|
130
173
|
export interface InboxAckResult {
|
|
131
174
|
acked: string[];
|
|
132
175
|
}
|
|
176
|
+
/** The delivered form of an addressed §4 envelope (spec §8.7.1). Hub-assigned `id`, Hub-attested
|
|
177
|
+
* `from` (session-qualified when the sender presented one), and `to` — the address whose principal
|
|
178
|
+
* AND session qualifier the §13.4 amendment makes the recipient check against its own identity. */
|
|
179
|
+
export interface InterAgentMessage {
|
|
180
|
+
ma2h_version: string;
|
|
181
|
+
type: "notify" | "ask" | "task";
|
|
182
|
+
id: string;
|
|
183
|
+
from: string;
|
|
184
|
+
to: string;
|
|
185
|
+
created_at: string;
|
|
186
|
+
title: string;
|
|
187
|
+
body?: string;
|
|
188
|
+
priority?: Priority;
|
|
189
|
+
tags?: string[];
|
|
190
|
+
context?: JsonValue[];
|
|
191
|
+
request?: JsonObject;
|
|
192
|
+
action?: JsonObject;
|
|
193
|
+
idempotency_key?: string;
|
|
194
|
+
}
|
|
195
|
+
/** A Hub-originated delivery-status notification to a SENDER (spec §8.7.1/§14.2); v0.5 uses it for
|
|
196
|
+
* the bounce. Its `id` (`rcpt_…`) is the §8.7.1 ack key. */
|
|
197
|
+
export interface ReceiptEntry {
|
|
198
|
+
ma2h_version: string;
|
|
199
|
+
type: "receipt";
|
|
200
|
+
id: string;
|
|
201
|
+
in_reply_to: string;
|
|
202
|
+
event: string;
|
|
203
|
+
prior: string;
|
|
204
|
+
at: string;
|
|
205
|
+
session: string;
|
|
206
|
+
to: string;
|
|
207
|
+
}
|
|
208
|
+
/** One drained (or streamed) §8.7.1 mailbox entry plus its detached `MA2H-Signature`. The kind is
|
|
209
|
+
* the discriminating KEY, not a `type` field — the wire union the Hub emits. */
|
|
210
|
+
export type InboxEntryDelivery = {
|
|
211
|
+
directive: InboundDirective;
|
|
212
|
+
signature: string;
|
|
213
|
+
} | {
|
|
214
|
+
message: InterAgentMessage;
|
|
215
|
+
signature: string;
|
|
216
|
+
} | {
|
|
217
|
+
response: A2hResponse;
|
|
218
|
+
signature: string;
|
|
219
|
+
} | {
|
|
220
|
+
receipt: ReceiptEntry;
|
|
221
|
+
signature: string;
|
|
222
|
+
};
|
|
223
|
+
/** The kinds above, as a discriminator a caller can switch on / print. */
|
|
224
|
+
export type InboxEntryKind = "directive" | "message" | "response" | "receipt";
|
|
225
|
+
/** `active → closed` (an explicit DELETE) or `active → expired` (the lease lapsed). Terminal states
|
|
226
|
+
* are immutable, and a lapsed lease READS `expired` to every reader before the reaper runs — so a
|
|
227
|
+
* client never has to model the reaper's schedule. */
|
|
228
|
+
export type SessionState = "active" | "closed" | "expired";
|
|
229
|
+
/** The session RESOURCE as the Hub returns it (spec §16.1). The id is Hub-minted, non-secret, and
|
|
230
|
+
* confers NOTHING on its own — every operation still requires the owning principal's credential,
|
|
231
|
+
* so this is safe to print, log, and pass around as an address. */
|
|
232
|
+
export interface Session {
|
|
233
|
+
id: string;
|
|
234
|
+
agent_id: string;
|
|
235
|
+
state: SessionState;
|
|
236
|
+
created_at: string;
|
|
237
|
+
/** Current lease expiry. Renewed only by client-originated activity (spec §16.2). */
|
|
238
|
+
expires_at: string;
|
|
239
|
+
last_seen?: string;
|
|
240
|
+
/** The §15.1 REACHABILITY conclusion the Hub states on the session resource (issue #654).
|
|
241
|
+
* Distinct from `state`: `state` says whether the LEASE is standing, reachability additionally
|
|
242
|
+
* requires client-originated activity inside the presence freshness window. Optional because a
|
|
243
|
+
* Hub of an earlier minor does not emit it — and because an ABSENT field must never be read as
|
|
244
|
+
* a claim either way. Read it, never re-derive it: the whole point of the Hub stating it once is
|
|
245
|
+
* that `fleet ls`, the §8.1 submit ack, the web UI and this CLI cannot drift apart. */
|
|
246
|
+
reachability?: DestinationSnapshot;
|
|
247
|
+
ttl_seconds?: number;
|
|
248
|
+
closed_at?: string;
|
|
249
|
+
/** Present and `true` ONLY when an account human closed this session — the §16.4 operator
|
|
250
|
+
* kill-switch (issue #683 §5). Absent for a lapsed lease and for the agent closing its own
|
|
251
|
+
* session, so an ABSENT field is "nobody stopped this", never "unknown".
|
|
252
|
+
*
|
|
253
|
+
* A supervised bridge branches on it: a lapse means "restart and register a fresh session", an
|
|
254
|
+
* operator close means "a human stopped you — stay down". Optional because an older Hub does not
|
|
255
|
+
* emit it, and falling back to the restart reading is the pre-#683 behaviour. */
|
|
256
|
+
closed_by_operator?: boolean;
|
|
257
|
+
run_id?: string;
|
|
258
|
+
label?: string;
|
|
259
|
+
kind?: string;
|
|
260
|
+
project?: string;
|
|
261
|
+
labels?: Record<string, string>;
|
|
262
|
+
}
|
|
263
|
+
/** `POST /v1/sessions` request body (spec §16.1). Every field is optional — the Hub owns the id,
|
|
264
|
+
* the state and the lease; `ttl_seconds` is a REQUEST it clamps two-sidedly into its bounds. */
|
|
265
|
+
export interface SessionRegisterRequest {
|
|
266
|
+
run_id?: string;
|
|
267
|
+
label?: string;
|
|
268
|
+
kind?: string;
|
|
269
|
+
project?: string;
|
|
270
|
+
labels?: Record<string, string>;
|
|
271
|
+
ttl_seconds?: number;
|
|
272
|
+
}
|
|
273
|
+
/** The subset of `GET /v1/capability` the CLI reads. Everything is optional: the document is
|
|
274
|
+
* served by Hubs of several minors, and an absent object means "this Hub does not say", never
|
|
275
|
+
* "disabled" — see `sessions.ts` on why an absent `inter_agent` in particular must not be read
|
|
276
|
+
* as a refusal. */
|
|
277
|
+
export interface HubCapability {
|
|
278
|
+
ma2h_version?: string;
|
|
279
|
+
/** The human→agent inbound leg (§8.0/§8.7). `oh-hai bridge` reads the v0.5 additions: whether the
|
|
280
|
+
* drain takes `?session=`, and — when the OPTIONAL §8.7.2 SSE binding is offered — where it lives
|
|
281
|
+
* and the ceiling on one hold. `stream_max_hold_seconds` is only the ADVERTISED ceiling: the
|
|
282
|
+
* per-hold bound arrives on the stream's own `open` event as `hold_ms` and may be shorter (it is
|
|
283
|
+
* the lesser of this and a margin before the presenting session's lease expiry), so anything
|
|
284
|
+
* scheduled against a hold uses `hold_ms`, never this. */
|
|
285
|
+
inbound?: {
|
|
286
|
+
enabled?: boolean;
|
|
287
|
+
session_param?: boolean;
|
|
288
|
+
stream_url?: string;
|
|
289
|
+
stream_max_hold_seconds?: number;
|
|
290
|
+
max_batch?: number;
|
|
291
|
+
visibility_timeout_seconds?: number;
|
|
292
|
+
};
|
|
293
|
+
/** The §9.7/§9.8 signature freshness window in seconds. `oh-hai bridge` enforces it on a drained
|
|
294
|
+
* entry's `t` before emitting anything (§13.4 step 1). */
|
|
295
|
+
replay_window_seconds?: number;
|
|
296
|
+
sessions?: {
|
|
297
|
+
enabled: boolean;
|
|
298
|
+
min_ttl_seconds?: number;
|
|
299
|
+
max_ttl_seconds?: number;
|
|
300
|
+
max_live_per_agent?: number;
|
|
301
|
+
agent_list_visibility?: boolean;
|
|
302
|
+
terminal_retention_seconds?: number;
|
|
303
|
+
};
|
|
304
|
+
inter_agent?: {
|
|
305
|
+
enabled: boolean;
|
|
306
|
+
entry_kinds?: string[];
|
|
307
|
+
sender_allowlists?: boolean;
|
|
308
|
+
};
|
|
309
|
+
}
|
|
133
310
|
export {};
|
package/dist/commands/notify.js
CHANGED
|
@@ -2,14 +2,20 @@
|
|
|
2
2
|
// digest). The productized sibling of `scripts/notify.ts`: the bearer is resolved account-aware
|
|
3
3
|
// (keychain/file/env, not raw env), output follows the `--json` envelope, and HTTP statuses map
|
|
4
4
|
// to §7 exit codes. No idempotency key — a notify must not be retried (a retry posts a duplicate).
|
|
5
|
+
//
|
|
6
|
+
// v0.5 (issue #657): `--to agent:<id>[#sess_…]` addresses ANOTHER AGENT instead of the human inbox.
|
|
7
|
+
// An addressed notify acks `queued`, never `delivered` — its lifecycle is the §14.2 delivery track,
|
|
8
|
+
// and the ack's `destination` snapshot is rendered verbatim rather than dressed up as liveness.
|
|
5
9
|
import { CliError, buildOk, serializeEnvelope } from "../envelope.js";
|
|
6
10
|
import { parseCommandArgs } from "./flags.js";
|
|
7
11
|
import { buildNotify } from "./messaging/build.js";
|
|
12
|
+
import { assertHubSpeaksAddressing } from "./messaging/capability.js";
|
|
8
13
|
import { submitEnvelope } from "./messaging/http.js";
|
|
9
14
|
import { resolveSubmitIdentity } from "./messaging/identity.js";
|
|
15
|
+
import { SESSION_OPTIONS, closeOwnedSession, explicitSession, releasingOwnedSessionOnFailure, resolveSessionScope, } from "./messaging/session-scope.js";
|
|
10
16
|
import { dryRunFlag, printDryRunEnvelope, printSubmitAck, resolveRunId, stringFlag } from "./messaging/shared.js";
|
|
11
17
|
import { resolveState } from "./messaging/state.js";
|
|
12
|
-
import { PRIORITIES, isPriority } from "./messaging/validate.js";
|
|
18
|
+
import { PRIORITIES, isPriority, parseDestination } from "./messaging/validate.js";
|
|
13
19
|
export async function notifyCommand(ctx) {
|
|
14
20
|
const { values } = parseCommandArgs(ctx.argv, {
|
|
15
21
|
title: { type: "string" },
|
|
@@ -18,6 +24,7 @@ export async function notifyCommand(ctx) {
|
|
|
18
24
|
tag: { type: "string", multiple: true },
|
|
19
25
|
"dry-run": { type: "boolean" },
|
|
20
26
|
state: { type: "string" },
|
|
27
|
+
...SESSION_OPTIONS,
|
|
21
28
|
});
|
|
22
29
|
// Seal an optional `--state` resume blob up front (requires MA2H_STATE_SEAL_KEY) so the
|
|
23
30
|
// preview under --dry-run shows the sealed envelope. notify has no await/open leg.
|
|
@@ -35,34 +42,69 @@ export async function notifyCommand(ctx) {
|
|
|
35
42
|
// Strict parse (not `=== true`): the `=`-form `--dry-run=true` still previews, and a malformed
|
|
36
43
|
// value like `--dry-run=treu` fails as usage rather than falling through to a LIVE submit.
|
|
37
44
|
const dryRun = dryRunFlag(values["dry-run"]);
|
|
45
|
+
// Parse `--to` BEFORE any credential work so a malformed address is a local usage error (exit 2),
|
|
46
|
+
// the same discipline `--priority` / `--resolver` follow. `--dry-run` previews it too.
|
|
47
|
+
const toRaw = stringFlag(values.to);
|
|
48
|
+
const destination = toRaw !== undefined ? parseDestination(toRaw) : undefined;
|
|
38
49
|
// Under --dry-run neither a token nor a resolved account is required — the envelope is only
|
|
39
50
|
// previewed. Use a placeholder agent id so the composed envelope stays inspectable. A real
|
|
40
51
|
// submit resolves the bearer + account up front (auth/usage errors before composing).
|
|
52
|
+
// ONE run id per invocation: the session registration and the envelope must agree, or the
|
|
53
|
+
// `fleet ls` correlation between a session and the message it sent silently breaks.
|
|
54
|
+
const runId = resolveRunId();
|
|
41
55
|
let agentId = ctx.config.account ?? "oh-hai/notify-bot";
|
|
42
56
|
let token = ""; // reassigned on the real path below; dry-run returns before it's used
|
|
57
|
+
// Resolve an EXPLICIT session (`--session` / `MA2H_SESSION_ID`) on BOTH paths — it is local, so a
|
|
58
|
+
// preview that dropped it would misrepresent the live send twice over: no `agent.session`, and a
|
|
59
|
+
// `ma2h_version` of 0.3 where the real submit says 0.5. A captured `--dry-run` envelope is meant
|
|
60
|
+
// to be replayable, so it has to match what a live invocation would post. Only the network-backed
|
|
61
|
+
// AUTO-MINT is suppressed under --dry-run (a preview must create no durable Hub state).
|
|
62
|
+
const attached = explicitSession(values);
|
|
63
|
+
let scope = attached !== undefined ? { ...attached, owned: false } : undefined;
|
|
43
64
|
if (!dryRun) {
|
|
65
|
+
// Gate BEFORE minting: a refused address must not leave a registered session behind. This is
|
|
66
|
+
// the same cached check `submitEnvelope` enforces as the un-forgettable backstop (one HTTP
|
|
67
|
+
// probe per process either way), run early so nothing durable is created for a send that
|
|
68
|
+
// cannot legally go.
|
|
69
|
+
if (destination !== undefined)
|
|
70
|
+
await assertHubSpeaksAddressing(ctx, destination.address);
|
|
44
71
|
const identity = await resolveSubmitIdentity(ctx);
|
|
45
72
|
agentId = identity.agentId;
|
|
46
73
|
token = identity.token;
|
|
74
|
+
scope = await resolveSessionScope(ctx, values, identity, destination !== undefined, runId);
|
|
47
75
|
}
|
|
48
76
|
const notify = buildNotify({
|
|
49
|
-
agent: { id: agentId, run_id:
|
|
77
|
+
agent: { id: agentId, run_id: runId, ...(scope !== undefined ? { session: scope.id } : {}) },
|
|
50
78
|
title,
|
|
79
|
+
...(destination !== undefined ? { to: destination.address } : {}),
|
|
51
80
|
...(body !== undefined ? { body } : {}),
|
|
52
81
|
...(priority !== undefined ? { priority } : {}),
|
|
53
82
|
...(tags.length > 0 ? { tags } : {}),
|
|
54
83
|
...(state !== undefined ? { state } : {}),
|
|
55
84
|
});
|
|
56
85
|
if (dryRun) {
|
|
86
|
+
// Say what the preview cannot show: a live addressed send with nothing attached would register a
|
|
87
|
+
// session and stamp it, so an envelope captured here is short exactly that field.
|
|
88
|
+
if (destination !== undefined && scope === undefined) {
|
|
89
|
+
ctx.io.err("note: a live --to send registers a session and adds `agent.session`; this preview cannot (it makes no Hub call).");
|
|
90
|
+
}
|
|
57
91
|
printDryRunEnvelope(ctx, "notify", notify);
|
|
58
92
|
return;
|
|
59
93
|
}
|
|
60
|
-
const ack = await submitEnvelope(ctx, token, notify
|
|
94
|
+
const ack = await releasingOwnedSessionOnFailure(ctx, token, scope, () => submitEnvelope(ctx, token, notify, {
|
|
95
|
+
...(destination !== undefined ? { addressedTo: destination.address } : {}),
|
|
96
|
+
}));
|
|
97
|
+
// A notify has no return leg — it carries no idempotency key and must never be retried — so a
|
|
98
|
+
// session THIS process minted for it has nothing left to receive, and closing it frees the
|
|
99
|
+
// §16.1 live-session slot immediately instead of holding it for the whole lease. An ATTACHED
|
|
100
|
+
// session is untouched: it belongs to whoever exported it.
|
|
101
|
+
if (scope?.owned === true)
|
|
102
|
+
await closeOwnedSession(ctx, token, scope.id);
|
|
61
103
|
if (ctx.json) {
|
|
62
|
-
ctx.io.log(serializeEnvelope(buildOk("notify", { id: ack.id })));
|
|
104
|
+
ctx.io.log(serializeEnvelope(buildOk("notify", { id: ack.id, status: ack.status, destination: ack.destination, to: destination?.address })));
|
|
63
105
|
}
|
|
64
106
|
else {
|
|
65
|
-
printSubmitAck(ctx, "notify posted", ack);
|
|
107
|
+
printSubmitAck(ctx, "notify posted", ack, false, destination !== undefined);
|
|
66
108
|
}
|
|
67
109
|
}
|
|
68
110
|
//# sourceMappingURL=notify.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/commands/notify.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,gGAAgG;AAChG,gGAAgG;AAChG,mGAAmG;
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/commands/notify.ts"],"names":[],"mappings":"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"}
|
|
@@ -96,9 +96,15 @@ export const COMMANDS = [
|
|
|
96
96
|
"oh-hai notify — fire-and-forget notification (status / FYI / digest).",
|
|
97
97
|
"",
|
|
98
98
|
"Usage: oh-hai notify --title <t> [--body <b>] [--priority <low|normal|high|urgent>]",
|
|
99
|
-
" [--tag <t>]... [--
|
|
99
|
+
" [--tag <t>]... [--to agent:<id>[#sess_…]] [--session <sess_…>]",
|
|
100
|
+
" [--no-session] [--dry-run]",
|
|
100
101
|
"",
|
|
101
102
|
"No idempotency key — a notify is fire-and-forget and must not be retried.",
|
|
103
|
+
"",
|
|
104
|
+
"--to addresses ANOTHER AGENT instead of the human inbox (v0.5 §4). Such a notify acks",
|
|
105
|
+
"`queued`, never `delivered` — it is sitting in a mailbox that may never be drained — and the",
|
|
106
|
+
"ack's destination reachability is printed exactly as the Hub reported it, including",
|
|
107
|
+
"'unknown', which means the Hub has no visibility and never that the addressee is down.",
|
|
102
108
|
].join("\n"),
|
|
103
109
|
},
|
|
104
110
|
{
|
|
@@ -111,10 +117,16 @@ export const COMMANDS = [
|
|
|
111
117
|
"",
|
|
112
118
|
"Usage: oh-hai ask submit --mode <select|input|confirm> --title <t>",
|
|
113
119
|
" [--resolver human:<id>]... [--option k:Label]... [--schema <json>]",
|
|
120
|
+
" [--to agent:<id>[#sess_…]] [--session <sess_…>] [--no-session]",
|
|
114
121
|
" oh-hai ask await --id <id> [--interval <ms>] [--await-timeout <ms>]",
|
|
115
122
|
"",
|
|
116
123
|
"Carries a REQUIRED idempotency key. --resolver is optional: with none, the account",
|
|
117
124
|
"owner can answer (it needn't be hand-typed). See cli spec §4.4.",
|
|
125
|
+
"",
|
|
126
|
+
"--to asks ANOTHER AGENT rather than a human (v0.5 §4). The answer routes back to your own",
|
|
127
|
+
"SESSION, so one is registered if you have not attached one — and left open afterwards, since",
|
|
128
|
+
"closing it is what would make the reply undeliverable. The id is printed with an export line",
|
|
129
|
+
"so the invocation that awaits the answer can present the same session.",
|
|
118
130
|
].join("\n"),
|
|
119
131
|
},
|
|
120
132
|
{
|
|
@@ -127,10 +139,14 @@ export const COMMANDS = [
|
|
|
127
139
|
"",
|
|
128
140
|
"Usage: oh-hai task submit --instructions <text> --title <t> [--resolver human:<id>]...",
|
|
129
141
|
" [--checklist <text>]... [--callback pull|push]",
|
|
142
|
+
" [--to agent:<id>[#sess_…]] [--session <sess_…>] [--no-session]",
|
|
130
143
|
" oh-hai task await --id <id> [--interval <ms>] [--await-timeout <ms>]",
|
|
131
144
|
"",
|
|
132
145
|
"Terminal by default. --resolver is optional: with none, the account owner can mark",
|
|
133
146
|
"it done. See cli spec §4.4.",
|
|
147
|
+
"",
|
|
148
|
+
"--to hands the action to ANOTHER AGENT rather than a human (v0.5 §4); as with ask, the",
|
|
149
|
+
"completion routes back to your session, which is registered if needed and left open.",
|
|
134
150
|
].join("\n"),
|
|
135
151
|
},
|
|
136
152
|
{
|
|
@@ -169,17 +185,123 @@ export const COMMANDS = [
|
|
|
169
185
|
"mailbox. See cli spec §4.7.",
|
|
170
186
|
].join("\n"),
|
|
171
187
|
},
|
|
188
|
+
{
|
|
189
|
+
name: "bridge",
|
|
190
|
+
summary: "supervised, loud-failure consumer of your session's mailbox (v0.5)",
|
|
191
|
+
issue: 658,
|
|
192
|
+
// `status` is the only subcommand; a bare `oh-hai bridge` RUNS the bridge, so the operand is
|
|
193
|
+
// optional and the handler parses it itself (parseSubcommandArgs would demand one).
|
|
194
|
+
subcommands: ["status"],
|
|
195
|
+
help: [
|
|
196
|
+
"oh-hai bridge — deliver your session's mail, or die saying why (cli spec §4.15).",
|
|
197
|
+
"",
|
|
198
|
+
"Usage: oh-hai bridge [--until-event | --stream] [--session <sess_…>] [--transport auto|sse|poll]",
|
|
199
|
+
" [--interval <ms>] [--max <n>] [--max-retries <n>]",
|
|
200
|
+
" [--allow-from agent:<id>[#sess_…] | any-in-account]... [--json]",
|
|
201
|
+
" oh-hai bridge status",
|
|
202
|
+
"",
|
|
203
|
+
"Drains the v0.5 session-scoped mailbox (§8.7.1) — directives PLUS the inter-agent entry",
|
|
204
|
+
"kinds — over SSE where the Hub offers it (§8.7.2), else long-poll. --until-event (the",
|
|
205
|
+
"default) holds until the first entry, hands it over, acks, and exits 0: the primitive a",
|
|
206
|
+
"harness re-invokes. --stream never exits on entries. Under --json each entry is one NDJSON",
|
|
207
|
+
"envelope, forwarded byte-verbatim with its signature.",
|
|
208
|
+
"",
|
|
209
|
+
"The Hub BOUNDS every stream hold and closes it on purpose — that close is not an error, and",
|
|
210
|
+
"reconnecting is what renews your session lease (§16.2). Backoff is reserved for real faults.",
|
|
211
|
+
"",
|
|
212
|
+
"§13.4 is enforced before anything is printed: signature freshness + replay, entry shape, and",
|
|
213
|
+
"the addressee check INCLUDING the session qualifier. Acting on an addressed ask/task needs an",
|
|
214
|
+
"EXPLICIT --allow-from policy — there is no permissive default, by spec.",
|
|
215
|
+
"",
|
|
216
|
+
"Fatal exits are distinct so a supervisor can branch: 3 auth (stop — a human fixes it),",
|
|
217
|
+
"11 session terminal (restart), 12 verification failure (stop), 13 retries exhausted (restart),",
|
|
218
|
+
"14 a human closed your session — the §16.4 operator kill-switch (STOP; do not restart, and do",
|
|
219
|
+
"not open a replacement session — restarting is what silently undoes the human's decision).",
|
|
220
|
+
"Do NOT use a blanket restart-on-any-nonzero policy: it defeats all five. Put the stop classes",
|
|
221
|
+
"in RestartPreventExitStatus (2 3 12 14). See docs/guides/bridge-supervision.md.",
|
|
222
|
+
].join("\n"),
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "session",
|
|
226
|
+
summary: "open / read / close this run's addressing scope (v0.5 sessions)",
|
|
227
|
+
issue: 657,
|
|
228
|
+
subcommands: ["start", "close", "status"],
|
|
229
|
+
help: [
|
|
230
|
+
"oh-hai session — the MA2H v0.5 §16 session: an addressing scope for ONE live run.",
|
|
231
|
+
"",
|
|
232
|
+
"Usage: oh-hai session start [--label <l>] [--kind <k>] [--project <p>] [--run-id <r>] [--ttl <seconds>]",
|
|
233
|
+
" oh-hai session status [--id <sess_…>]",
|
|
234
|
+
" oh-hai session close [--id <sess_…>]",
|
|
235
|
+
"",
|
|
236
|
+
"`agent.id` names a machine principal many concurrent runs can share, so on its own it cannot",
|
|
237
|
+
"say WHICH run you are talking to. A session can: it is Hub-minted, lease-bound, and is the",
|
|
238
|
+
"thing `--to agent:<id>#<sess_…>` addresses — and the thing an addressed ask routes its answer",
|
|
239
|
+
"back to. `start` prints the id plus the `export MA2H_SESSION_ID=…` line that attaches later",
|
|
240
|
+
"invocations (attaching also RENEWS the lease, so an agent that keeps working stays live with",
|
|
241
|
+
"no keep-alive of its own). `status`/`close` default to that attached session when --id is",
|
|
242
|
+
"omitted; `close` is idempotent. A session id is NOT a credential — it is non-secret and",
|
|
243
|
+
"confers nothing; every call still presents your token, which is never printed.",
|
|
244
|
+
].join("\n"),
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "fleet",
|
|
248
|
+
summary: "list the agent sessions you can address with --to",
|
|
249
|
+
issue: 657,
|
|
250
|
+
subcommands: ["ls"],
|
|
251
|
+
help: [
|
|
252
|
+
"oh-hai fleet — discover the sessions this credential can see (cli spec §4.13).",
|
|
253
|
+
"",
|
|
254
|
+
"Usage: oh-hai fleet ls [--all] [--limit <n>] [--offset <n>]",
|
|
255
|
+
"",
|
|
256
|
+
"Prints one row per session with the exact ADDRESS to copy into `--to`, plus state, age,",
|
|
257
|
+
"label, kind and project. Live sessions only by default; --all includes closed/expired ones,",
|
|
258
|
+
"which the Hub retains for a window. The SCOPE is not a flag — you always see your own",
|
|
259
|
+
"sessions, and other agents' only where the Hub permits same-account listing (§16.4, off by",
|
|
260
|
+
"default). The command says which one it printed rather than letting a narrowed list read as",
|
|
261
|
+
"'nobody else is running'.",
|
|
262
|
+
].join("\n"),
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "messages",
|
|
266
|
+
summary: "list the agent's own submitted messages (history / dedupe)",
|
|
267
|
+
issue: 572,
|
|
268
|
+
subcommands: ["list"],
|
|
269
|
+
help: [
|
|
270
|
+
"oh-hai messages — read the messages THIS agent has submitted (cli spec §4.11).",
|
|
271
|
+
"",
|
|
272
|
+
"Usage: oh-hai messages list [--limit <n>] [--offset <n>] [--status <s>] [--type <t>]",
|
|
273
|
+
"",
|
|
274
|
+
"Lists the agent's OWN submitted messages (bearer-scoped — never the human inbox), newest",
|
|
275
|
+
"first, for history review or to dedupe before resubmitting. Each row shows the message's",
|
|
276
|
+
"status but NOT the resolved answer body (the list is a pure index) — pull a specific answer",
|
|
277
|
+
"by its id. Paginated: --limit (default 50, the Hub clamps to 200) / --offset page one window",
|
|
278
|
+
"per call; when a full page comes back, re-run with the printed --offset to continue. Filter",
|
|
279
|
+
"with --status (open | delivered | answered | declined | cancelled | expired | completed |",
|
|
280
|
+
"dismissed) and/or --type (notify | ask | task). Under --json the ok-envelope carries",
|
|
281
|
+
"{ messages, count, has_more, next_offset }.",
|
|
282
|
+
].join("\n"),
|
|
283
|
+
},
|
|
172
284
|
{
|
|
173
285
|
name: "doctor",
|
|
174
|
-
summary: "config + keychain + connectivity
|
|
286
|
+
summary: "config + keychain + connectivity checks, and the end-to-end reachability self-test",
|
|
175
287
|
issue: 108,
|
|
176
288
|
subcommands: [],
|
|
177
289
|
help: [
|
|
178
290
|
"oh-hai doctor — diagnose setup (config, keychain, connectivity).",
|
|
179
291
|
"",
|
|
180
|
-
"Usage: oh-hai doctor [--test-notify]",
|
|
292
|
+
"Usage: oh-hai doctor [--test-notify] [--self-test]",
|
|
181
293
|
"",
|
|
182
294
|
"Local checks run offline; connectivity + --test-notify are network checks. See cli spec §4.6.",
|
|
295
|
+
"",
|
|
296
|
+
"--self-test proves the loop instead of a precondition: it registers a session, sends this agent a",
|
|
297
|
+
"message addressed to it, drains it back through the same §13.4 checks `oh-hai bridge` applies, acks",
|
|
298
|
+
"it, reports the reachability a human would see, and closes the session. Those steps are REQUIRED —",
|
|
299
|
+
"if the round trip does not complete, doctor exits non-zero. It sends real traffic, so it is opt-in.",
|
|
300
|
+
"",
|
|
301
|
+
"One side effect worth knowing: a session-scoped drain claims the PRINCIPAL's queued mail too",
|
|
302
|
+
"(first-claim-wins, §8.7.1), so on a busy agent the probe can briefly lease an entry meant for a",
|
|
303
|
+
"running bridge. It never acks those, so each returns to the queue when its lease lapses — delayed,",
|
|
304
|
+
"not lost — and the report names any it touched. Prefer running it when no bridge is mid-flight.",
|
|
183
305
|
].join("\n"),
|
|
184
306
|
},
|
|
185
307
|
{
|
|
@@ -195,6 +317,9 @@ export const COMMANDS = [
|
|
|
195
317
|
"Writes a vendor-neutral OH HAI snippet into the agent-instruction files this machine's",
|
|
196
318
|
"agents already read: the cross-vendor AGENTS.md (project-level by default; --global for",
|
|
197
319
|
"the user-level convention path) plus any detected vendor files (CLAUDE.md, GEMINI.md, …).",
|
|
320
|
+
"The snippet covers BOTH directions — when to notify/ask/task a human, and how to stay",
|
|
321
|
+
"REACHABLE (open a session, run `oh-hai bridge --until-event` as a background task, and branch",
|
|
322
|
+
"on its exit code rather than looping blindly) plus the `--to` addressing conventions.",
|
|
198
323
|
"Idempotent — a stable marked block it updates in place, never a duplicate; never a secret.",
|
|
199
324
|
"--dry-run previews what it would touch; --yes skips the confirm (required under --json).",
|
|
200
325
|
].join("\n"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/commands/registry.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,mFAAmF;AACnF,kFAAkF;AAClF,kGAAkG;AAelG,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,8DAA8D;QACvE,KAAK,EAAE,GAAG;QACV,WAAW,EAAE,EAAE;QACf,IAAI,EAAE;YACJ,gEAAgE;YAChE,EAAE;YACF,qBAAqB;YACrB,EAAE;YACF,mFAAmF;YACnF,oFAAoF;YACpF,sFAAsF;YACtF,uFAAuF;YACvF,mDAAmD;SACpD,CAAC,IAAI,CAAC,IAAI,CAAC;KACb;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,+CAA+C;QACxD,KAAK,EAAE,GAAG;QACV,WAAW,EAAE,EAAE;QACf,IAAI,EAAE;YACJ,iEAAiE;YACjE,EAAE;YACF,wCAAwC;YACxC,uEAAuE;YACvE,EAAE;YACF,mFAAmF;YACnF,mFAAmF;YACnF,yEAAyE;YACzE,mFAAmF;YACnF,qCAAqC;SACtC,CAAC,IAAI,CAAC,IAAI,CAAC;KACb;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,yBAAyB;QAClC,KAAK,EAAE,GAAG;QACV,WAAW,EAAE,EAAE;QACf,IAAI,EAAE;YACJ,kFAAkF;YAClF,EAAE;YACF,+CAA+C;YAC/C,EAAE;YACF,6DAA6D;SAC9D,CAAC,IAAI,CAAC,IAAI,CAAC;KACb;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,+EAA+E;QACxF,KAAK,EAAE,GAAG;QACV,WAAW,EAAE,EAAE;QACf,IAAI,EAAE;YACJ,0EAA0E;YAC1E,EAAE;YACF,gCAAgC;YAChC,EAAE;YACF,kFAAkF;YAClF,qFAAqF;YACrF,sFAAsF;YACtF,iDAAiD;SAClD,CAAC,IAAI,CAAC,IAAI,CAAC;KACb;IACD;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,+EAA+E;QACxF,KAAK,EAAE,GAAG;QACV,WAAW,EAAE,EAAE;QACf,IAAI,EAAE;YACJ,yEAAyE;YACzE,EAAE;YACF,8EAA8E;YAC9E,0DAA0D;YAC1D,8DAA8D;YAC9D,EAAE;YACF,kFAAkF;YAClF,uFAAuF;YACvF,sFAAsF;YACtF,8EAA8E;YAC9E,oFAAoF;YACpF,oDAAoD;SACrD,CAAC,IAAI,CAAC,IAAI,CAAC;KACb;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,uCAAuC;QAChD,KAAK,EAAE,GAAG;QACV,WAAW,EAAE,EAAE;QACf,IAAI,EAAE;YACJ,uEAAuE;YACvE,EAAE;YACF,qFAAqF;YACrF,iDAAiD;YACjD,EAAE;YACF,2EAA2E;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/commands/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CommandContext } from "./context.js";
|
|
2
|
+
/** One self-test step, shaped exactly like a `doctor` check so the two render through one reporter. */
|
|
3
|
+
export interface SelfTestStep {
|
|
4
|
+
name: string;
|
|
5
|
+
status: "pass" | "warn" | "fail";
|
|
6
|
+
detail: string;
|
|
7
|
+
/** Set on a `fail` only — the code `doctor` returns. Every self-test failure is REQUIRED. */
|
|
8
|
+
exitCode?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Run the end-to-end self-test and return its ordered steps.
|
|
12
|
+
*
|
|
13
|
+
* NEVER THROWS for a diagnosable failure: a self-test that threw would lose the steps that already
|
|
14
|
+
* passed, which are exactly what tells a human *where* the loop breaks. Every failure becomes a
|
|
15
|
+
* `fail` step carrying its exit code; the caller decides the process exit.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runSelfTest(ctx: CommandContext): Promise<SelfTestStep[]>;
|