agent-conveyor 0.1.20 → 0.1.22
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 +23 -3
- package/dist/cli/typescript-runtime.js +214 -7
- package/dist/cli/typescript-runtime.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/app-autonomy.js +4 -3
- package/dist/runtime/app-autonomy.js.map +1 -1
- package/dist/runtime/audit.d.ts +14 -1
- package/dist/runtime/audit.js +24 -0
- package/dist/runtime/audit.js.map +1 -1
- package/dist/runtime/notifications.d.ts +32 -0
- package/dist/runtime/notifications.js +94 -1
- package/dist/runtime/notifications.js.map +1 -1
- package/dist/runtime/replay.js +24 -0
- package/dist/runtime/replay.js.map +1 -1
- package/dist/state/schema-v23.js +18 -0
- package/dist/state/schema-v23.js.map +1 -1
- package/dist/state/sqlite-contract.d.ts +1 -1
- package/dist/state/sqlite-contract.js +4 -1
- package/dist/state/sqlite-contract.js.map +1 -1
- package/package.json +1 -1
- package/plugin/agent-conveyor/plugin.json +4 -2
- package/plugin/agent-conveyor/skills/conveyor-app-wake-relay/SKILL.md +122 -0
- package/plugin/agent-conveyor/skills/conveyor-check-status/SKILL.md +2 -0
- package/plugin/agent-conveyor/skills/conveyor-create-pair/SKILL.md +2 -0
- package/plugin/agent-conveyor/skills/conveyor-create-worker-set/SKILL.md +2 -0
- package/plugin/agent-conveyor/skills/conveyor-whats-next-nudger/SKILL.md +120 -0
package/README.md
CHANGED
|
@@ -168,8 +168,9 @@ conveyor plugin-status
|
|
|
168
168
|
|
|
169
169
|
The per-project default ledger for operator sessions is
|
|
170
170
|
`.codex-workers/workerctl.db`. The initial included skills are
|
|
171
|
-
`conveyor-
|
|
172
|
-
`conveyor-check-status
|
|
171
|
+
`conveyor-app-wake-relay`, `conveyor-create-pair`,
|
|
172
|
+
`conveyor-create-worker-set`, `conveyor-check-status`, and
|
|
173
|
+
`conveyor-whats-next-nudger`.
|
|
173
174
|
|
|
174
175
|
After install, the intended Codex app entry point is natural language. Open a
|
|
175
176
|
new Codex app session in the target repo and say:
|
|
@@ -204,6 +205,15 @@ print `CONVEYOR POLL`, `CONVEYOR RECEIVED`, `WORK`, `CONVEYOR SEND`, and
|
|
|
204
205
|
audit proof, not a replacement for the live session story. Idle polls may be a
|
|
205
206
|
single `CONVEYOR IDLE` line.
|
|
206
207
|
|
|
208
|
+
For bounded follow-up passes after the first worker result, use
|
|
209
|
+
`Use the conveyor-whats-next-nudger skill`.
|
|
210
|
+
|
|
211
|
+
For stale Codex app roles, use `Use the conveyor-app-wake-relay skill`. It
|
|
212
|
+
runs `app-wakeup-dispatch`, sends only prepared `send_ready=true` prompts with
|
|
213
|
+
Codex app thread tools, and records `sent`, `skipped`, or `blocked` delivery
|
|
214
|
+
receipts with `app-wakeup-record-delivery`. The app-thread prompt wakes the
|
|
215
|
+
session to poll; it is not durable task truth.
|
|
216
|
+
|
|
207
217
|
Dispatch is core infrastructure for supervised worker/manager pairs. The
|
|
208
218
|
`pair` workflow starts a detached Dispatch watch process by default so worker
|
|
209
219
|
completion is routed to the bound manager mechanically. For manually bound
|
|
@@ -512,7 +522,8 @@ stay out of receipts.
|
|
|
512
522
|
[--json]` — Record what the Codex app/operator layer did with a wake action.
|
|
513
523
|
`sent` is accepted only when the referenced `app-wakeup-dispatch` receipt has
|
|
514
524
|
a matching `ready_to_send` action with `send_ready=true` and the same thread
|
|
515
|
-
id; healthy
|
|
525
|
+
id; healthy roles must be recorded as `skipped`; missing-thread blockers and
|
|
526
|
+
failed app-thread sends must be recorded as `blocked` with a reason.
|
|
516
527
|
- `app-autopilot start|stop|status TASK [--dispatcher-id ID]
|
|
517
528
|
[--interval SECONDS] [--watch-iterations N] [--stale-after N]
|
|
518
529
|
[--quiet-after N] [--json]` —
|
|
@@ -804,6 +815,15 @@ stay out of receipts.
|
|
|
804
815
|
- `worker-inbox <task> [--consume-next] [--wait] [--timeout N] [--interval N]
|
|
805
816
|
[--limit N] [--json]` — Resolve the task's bound worker session and read its
|
|
806
817
|
dispatcher inbox.
|
|
818
|
+
- `inbox-ack <task> --notification-id N [--json]` — Read durable
|
|
819
|
+
role-authored acknowledgement history for one routed notification.
|
|
820
|
+
- `inbox-ack <task> --notification-id N --role manager|worker
|
|
821
|
+
--status received|accepted|blocked --from-stdin [--correlation-id C]
|
|
822
|
+
[--json]` — Record that the addressed role saw a delivered notification and
|
|
823
|
+
either received, accepted, or blocked on it. `received` requires delivery;
|
|
824
|
+
`accepted` and `blocked` require consumption. Use this after visible Codex app
|
|
825
|
+
sessions print `CONVEYOR RECEIVED`; do not use direct app-thread text as the
|
|
826
|
+
durable receipt.
|
|
807
827
|
|
|
808
828
|
### Actuation
|
|
809
829
|
|
|
@@ -18,7 +18,7 @@ import { executeDispatchCommandSync } from "../runtime/dispatch.js";
|
|
|
18
18
|
import { deregisterSessionSync, discoverRegistrySync, findRolloutPathForPid, listRegisteredSessionsSync, registerSessionSync, readSessionMeta, sessionRow, } from "../runtime/codex-session.js";
|
|
19
19
|
import { managerConfigPermissionAllowed, managerConfigSync } from "../runtime/manager-config.js";
|
|
20
20
|
import { canonicalManagerPermissionNames, flattenManagerPermissions, normalizeManagerPermissions, } from "../runtime/manager-permissions.js";
|
|
21
|
-
import { deferRoutedNotificationBeforeSideEffectSync, deliveryModeForTargetSessionSync, finishRoutedNotificationSync, insertRoutedNotificationSync, markRoutedNotificationSideEffectStartedSync, consumeNextSessionInboxItemSync, routedNotificationsSync, sessionInboxSync, } from "../runtime/notifications.js";
|
|
21
|
+
import { deferRoutedNotificationBeforeSideEffectSync, deliveryModeForTargetSessionSync, finishRoutedNotificationSync, insertRoutedNotificationSync, insertNotificationAcknowledgementSync, latestNotificationAcknowledgementSync, markRoutedNotificationSideEffectStartedSync, notificationAcknowledgementsSync, consumeNextSessionInboxItemSync, routedNotificationsSync, sessionInboxSync, } from "../runtime/notifications.js";
|
|
22
22
|
import { activeBindingForTaskSync, bindSessionsSync, createTaskSync, listTasksSync, unbindTaskSync, } from "../runtime/tasks.js";
|
|
23
23
|
import { captureTmuxTargetWithRunner, captureTranscriptTmuxTargetWithRunner, currentPaneIdWithRunner, killTmuxSessionWithRunner, sendEnterToTmuxSessionWithRunner, sendTextToSessionWithRunner, sessionExists, startTmuxSessionWithRunner, tmuxCommandFailureMessage, tmuxSession, tmuxSessionRunning, } from "../runtime/tmux.js";
|
|
24
24
|
import { captureMetaPath, configPath, defaultDbPath, eventsPath, loadJsonSync, stateRoot, statusPath, transcriptPath, validateWorkerName, workerDir, writeJsonSync, } from "../state/files.js";
|
|
@@ -261,6 +261,9 @@ export function runTypescriptRuntimeCommand(options) {
|
|
|
261
261
|
if (parsed.command === "manager-ack") {
|
|
262
262
|
return runTaskAckCommand(parsed, options, "manager");
|
|
263
263
|
}
|
|
264
|
+
if (parsed.command === "inbox-ack") {
|
|
265
|
+
return runInboxAckCommand(parsed, options);
|
|
266
|
+
}
|
|
264
267
|
if (parsed.command === "session-inbox") {
|
|
265
268
|
return runSessionInboxCommand(parsed, options, "session");
|
|
266
269
|
}
|
|
@@ -420,6 +423,15 @@ function commandHelpText(program, command) {
|
|
|
420
423
|
"Example JSON:",
|
|
421
424
|
` {"task":"my-task","manager_session":"mgr","supervision_contract":"I will supervise through Conveyor and verify criteria before finishing.","will_not_edit_project_files":true}`,
|
|
422
425
|
],
|
|
426
|
+
"inbox-ack": [
|
|
427
|
+
`usage: ${program} inbox-ack <task> --notification-id N --role manager|worker --status received|accepted|blocked --from-stdin ${path} [--json]`,
|
|
428
|
+
`usage: ${program} inbox-ack <task> --notification-id N --json ${path}`,
|
|
429
|
+
"",
|
|
430
|
+
"Record or read a notification-scoped manager/worker acknowledgement.",
|
|
431
|
+
"",
|
|
432
|
+
"Example JSON:",
|
|
433
|
+
` {"summary":"Received manager instruction and will run the bounded task.","evidence":[]}`,
|
|
434
|
+
],
|
|
423
435
|
nudge: [
|
|
424
436
|
`usage: ${program} nudge <worker-or-session> <message> ${path} [--dry-run]`,
|
|
425
437
|
`usage: ${program} session-nudge <session> <message> ${path} [--dry-run]`,
|
|
@@ -584,6 +596,7 @@ function parseRuntimeArgs(args, env) {
|
|
|
584
596
|
nextAction: null,
|
|
585
597
|
noFollowup: false,
|
|
586
598
|
nextSteps: [],
|
|
599
|
+
notificationId: null,
|
|
587
600
|
output: null,
|
|
588
601
|
path: null,
|
|
589
602
|
pid: null,
|
|
@@ -1502,7 +1515,7 @@ function parseRuntimeArgs(args, env) {
|
|
|
1502
1515
|
index += 1;
|
|
1503
1516
|
}
|
|
1504
1517
|
else if (arg === "--from-stdin") {
|
|
1505
|
-
if (command !== "criteria-plan" && command !== "continuation" && command !== "worker-ack" && command !== "manager-ack") {
|
|
1518
|
+
if (command !== "criteria-plan" && command !== "continuation" && command !== "worker-ack" && command !== "manager-ack" && command !== "inbox-ack") {
|
|
1506
1519
|
return { command, enabled, error: "Unsupported TypeScript runtime option: --from-stdin", explicit, flags, task };
|
|
1507
1520
|
}
|
|
1508
1521
|
flags.fromStdin = true;
|
|
@@ -2373,7 +2386,7 @@ function parseRuntimeArgs(args, env) {
|
|
|
2373
2386
|
flags.epilogueStatus = true;
|
|
2374
2387
|
continue;
|
|
2375
2388
|
}
|
|
2376
|
-
if (command !== "criteria" && command !== "runs" && command !== "loop-evidence" && command !== "campaign") {
|
|
2389
|
+
if (command !== "criteria" && command !== "runs" && command !== "loop-evidence" && command !== "campaign" && command !== "inbox-ack") {
|
|
2377
2390
|
return { command, enabled, error: "Unsupported TypeScript runtime option: --status", explicit, flags, task };
|
|
2378
2391
|
}
|
|
2379
2392
|
const parsedValue = valueAfter(queue, index, arg);
|
|
@@ -2383,11 +2396,29 @@ function parseRuntimeArgs(args, env) {
|
|
|
2383
2396
|
if (command === "criteria") {
|
|
2384
2397
|
flags.statuses.push(parsedValue.value);
|
|
2385
2398
|
}
|
|
2399
|
+
else if (command === "inbox-ack") {
|
|
2400
|
+
flags.statusState = parsedValue.value;
|
|
2401
|
+
}
|
|
2386
2402
|
else {
|
|
2387
2403
|
flags.statusState = parsedValue.value;
|
|
2388
2404
|
}
|
|
2389
2405
|
index += 1;
|
|
2390
2406
|
}
|
|
2407
|
+
else if (arg === "--notification-id") {
|
|
2408
|
+
if (command !== "inbox-ack") {
|
|
2409
|
+
return { command, enabled, error: "Unsupported TypeScript runtime option: --notification-id", explicit, flags, task };
|
|
2410
|
+
}
|
|
2411
|
+
const parsedValue = valueAfter(queue, index, arg);
|
|
2412
|
+
if (parsedValue.error) {
|
|
2413
|
+
return { command, enabled, error: parsedValue.error, explicit, flags, task };
|
|
2414
|
+
}
|
|
2415
|
+
const value = Number(parsedValue.value);
|
|
2416
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
2417
|
+
return { command, enabled, error: "--notification-id must be a positive integer.", explicit, flags, task };
|
|
2418
|
+
}
|
|
2419
|
+
flags.notificationId = value;
|
|
2420
|
+
index += 1;
|
|
2421
|
+
}
|
|
2391
2422
|
else if (arg === "--type") {
|
|
2392
2423
|
const value = valueAfter(queue, index, arg);
|
|
2393
2424
|
if (value.error) {
|
|
@@ -2537,6 +2568,7 @@ function parseRuntimeArgs(args, env) {
|
|
|
2537
2568
|
&& command !== "enqueue-continue-iteration"
|
|
2538
2569
|
&& command !== "worker-ack"
|
|
2539
2570
|
&& command !== "manager-ack"
|
|
2571
|
+
&& command !== "inbox-ack"
|
|
2540
2572
|
&& command !== "loop-evidence"
|
|
2541
2573
|
&& command !== "continuation"
|
|
2542
2574
|
&& command !== "continuation-reviewer"
|
|
@@ -3863,7 +3895,7 @@ function runAppWakeupRecordDeliveryCommand(parsed, options) {
|
|
|
3863
3895
|
if (!action) {
|
|
3864
3896
|
throw new Error(`Receipt ${source.id} has no ${role} wake action.`);
|
|
3865
3897
|
}
|
|
3866
|
-
validateAppWakeupDelivery({ action, deliveryStatus, role, threadId: parsed.flags.threadId });
|
|
3898
|
+
validateAppWakeupDelivery({ action, deliveryStatus, reason: parsed.flags.reason, role, threadId: parsed.flags.threadId });
|
|
3867
3899
|
const timestamp = nowIsoSeconds(options);
|
|
3868
3900
|
const eventId = emitTelemetrySync(database, {
|
|
3869
3901
|
actor: "manager",
|
|
@@ -4383,9 +4415,16 @@ function validateAppWakeupDelivery(options) {
|
|
|
4383
4415
|
}
|
|
4384
4416
|
return;
|
|
4385
4417
|
}
|
|
4386
|
-
if (sourceStatus
|
|
4387
|
-
|
|
4418
|
+
if (sourceStatus === "blocked_missing_thread") {
|
|
4419
|
+
return;
|
|
4420
|
+
}
|
|
4421
|
+
if (sourceStatus === "ready_to_send" && options.action.send_ready === true) {
|
|
4422
|
+
if (!options.reason?.trim()) {
|
|
4423
|
+
throw new Error(`Cannot record blocked wakeup for ${options.role}; ready-to-send source actions require --reason.`);
|
|
4424
|
+
}
|
|
4425
|
+
return;
|
|
4388
4426
|
}
|
|
4427
|
+
throw new Error(`Cannot record blocked wakeup for ${options.role}; source action is ${sourceStatus}.`);
|
|
4389
4428
|
}
|
|
4390
4429
|
function parseAppWakeupSourceActionStatus(value) {
|
|
4391
4430
|
if (value === "ready_to_send" || value === "skipped_healthy" || value === "blocked_missing_thread") {
|
|
@@ -6697,7 +6736,13 @@ function runInstallSkillsCommand(parsed, options) {
|
|
|
6697
6736
|
return { exitCode: 0, handled: true, stdout: `${lines.join("\n")}\n` };
|
|
6698
6737
|
}
|
|
6699
6738
|
const AGENT_CONVEYOR_PLUGIN_NAME = "agent-conveyor";
|
|
6700
|
-
const AGENT_CONVEYOR_PLUGIN_SKILLS = [
|
|
6739
|
+
const AGENT_CONVEYOR_PLUGIN_SKILLS = [
|
|
6740
|
+
"conveyor-app-wake-relay",
|
|
6741
|
+
"conveyor-create-pair",
|
|
6742
|
+
"conveyor-create-worker-set",
|
|
6743
|
+
"conveyor-check-status",
|
|
6744
|
+
"conveyor-whats-next-nudger",
|
|
6745
|
+
];
|
|
6701
6746
|
function resolveCodexHome(parsed, options) {
|
|
6702
6747
|
return resolve(expandUserPath(parsed.flags.codexHome ?? options.env?.CODEX_HOME ?? join(homedir(), ".codex")));
|
|
6703
6748
|
}
|
|
@@ -9087,6 +9132,94 @@ function runTaskAckCommand(parsed, options, role) {
|
|
|
9087
9132
|
database.close();
|
|
9088
9133
|
}
|
|
9089
9134
|
}
|
|
9135
|
+
function runInboxAckCommand(parsed, options) {
|
|
9136
|
+
const unsupported = unsupportedInboxAckOptions(parsed);
|
|
9137
|
+
if (unsupported) {
|
|
9138
|
+
return unsupportedRuntimeResult(parsed, unsupported);
|
|
9139
|
+
}
|
|
9140
|
+
const taskName = requireTask(parsed);
|
|
9141
|
+
const notificationId = parsed.flags.notificationId;
|
|
9142
|
+
if (notificationId === null) {
|
|
9143
|
+
return errorResult("inbox-ack requires --notification-id.");
|
|
9144
|
+
}
|
|
9145
|
+
const database = openRuntimeDatabase(parsed, options);
|
|
9146
|
+
try {
|
|
9147
|
+
const task = taskRowForLifecycle(database, taskName);
|
|
9148
|
+
if (task === null) {
|
|
9149
|
+
throw new Error(`Unknown task: ${taskName}`);
|
|
9150
|
+
}
|
|
9151
|
+
const binding = activeBindingForTaskSync(database, task.name);
|
|
9152
|
+
const notification = notificationForInboxAckSync(database, {
|
|
9153
|
+
notificationId,
|
|
9154
|
+
taskId: task.id,
|
|
9155
|
+
taskName: task.name,
|
|
9156
|
+
});
|
|
9157
|
+
if (notification.binding_id !== binding.binding_id) {
|
|
9158
|
+
throw new Error(`Notification ${notificationId} does not belong to the active binding for task ${task.name}.`);
|
|
9159
|
+
}
|
|
9160
|
+
if (!parsed.flags.fromStdin) {
|
|
9161
|
+
const acknowledgements = notificationAcknowledgementsSync(database, { notificationId, taskId: task.id });
|
|
9162
|
+
return jsonResult({
|
|
9163
|
+
acknowledgements,
|
|
9164
|
+
latest: latestNotificationAcknowledgementSync(database, { notificationId, taskId: task.id }),
|
|
9165
|
+
notification: inboxAckNotificationPayload(notification),
|
|
9166
|
+
task: { id: task.id, name: task.name },
|
|
9167
|
+
});
|
|
9168
|
+
}
|
|
9169
|
+
const role = parsed.flags.role;
|
|
9170
|
+
const status = parseNotificationAcknowledgementStatus(parsed.flags.statusState);
|
|
9171
|
+
if (status instanceof Error) {
|
|
9172
|
+
return errorResult(status.message);
|
|
9173
|
+
}
|
|
9174
|
+
validateInboxAcknowledgement({ notification, role, status });
|
|
9175
|
+
const payload = parseStdinJsonObject(options.stdin);
|
|
9176
|
+
const ack = insertNotificationAcknowledgementSync(database, {
|
|
9177
|
+
bindingId: notification.binding_id,
|
|
9178
|
+
correlationId: parsed.flags.correlationId,
|
|
9179
|
+
notificationId,
|
|
9180
|
+
now: nowIsoSeconds(options),
|
|
9181
|
+
payload,
|
|
9182
|
+
role,
|
|
9183
|
+
status,
|
|
9184
|
+
taskId: task.id,
|
|
9185
|
+
});
|
|
9186
|
+
const eventId = emitTelemetrySync(database, {
|
|
9187
|
+
actor: role,
|
|
9188
|
+
attributes: {
|
|
9189
|
+
binding_id: notification.binding_id,
|
|
9190
|
+
notification_id: notificationId,
|
|
9191
|
+
payload_keys: Object.keys(payload).sort(),
|
|
9192
|
+
role,
|
|
9193
|
+
signal_type: notification.signal_type,
|
|
9194
|
+
status,
|
|
9195
|
+
},
|
|
9196
|
+
correlation: {
|
|
9197
|
+
command: "inbox-ack",
|
|
9198
|
+
correlation_id: parsed.flags.correlationId,
|
|
9199
|
+
notification_id: notificationId,
|
|
9200
|
+
role,
|
|
9201
|
+
},
|
|
9202
|
+
eventType: "dispatch_inbox_ack_recorded",
|
|
9203
|
+
severity: status === "blocked" ? "warning" : "info",
|
|
9204
|
+
summary: `${role} recorded ${status} acknowledgement for notification ${notificationId}.`,
|
|
9205
|
+
taskId: task.id,
|
|
9206
|
+
timestamp: ack.created_at,
|
|
9207
|
+
});
|
|
9208
|
+
return jsonResult({
|
|
9209
|
+
acknowledgement: ack,
|
|
9210
|
+
notification: inboxAckNotificationPayload(notification),
|
|
9211
|
+
receipt: {
|
|
9212
|
+
event_id: eventId,
|
|
9213
|
+
event_type: "dispatch_inbox_ack_recorded",
|
|
9214
|
+
recorded_at: ack.created_at,
|
|
9215
|
+
},
|
|
9216
|
+
task: { id: task.id, name: task.name },
|
|
9217
|
+
});
|
|
9218
|
+
}
|
|
9219
|
+
finally {
|
|
9220
|
+
database.close();
|
|
9221
|
+
}
|
|
9222
|
+
}
|
|
9090
9223
|
function runSessionInboxCommand(parsed, options, kind) {
|
|
9091
9224
|
const unsupported = unsupportedSessionInboxOptions(parsed, kind);
|
|
9092
9225
|
if (unsupported) {
|
|
@@ -9336,6 +9469,59 @@ function latestTaskAcknowledgementSync(database, options) {
|
|
|
9336
9469
|
task_id: row.task_id,
|
|
9337
9470
|
};
|
|
9338
9471
|
}
|
|
9472
|
+
function notificationForInboxAckSync(database, options) {
|
|
9473
|
+
const row = database.prepare(`
|
|
9474
|
+
select rn.id, rn.task_id, rn.binding_id, rn.signal_type, rn.delivered_at,
|
|
9475
|
+
rn.consumed_at, rn.delivery_mode, rn.state, rn.target_session_id,
|
|
9476
|
+
ts.name as target_session_name, ts.role as target_session_role
|
|
9477
|
+
from routed_notifications rn
|
|
9478
|
+
join sessions ts on ts.id = rn.target_session_id
|
|
9479
|
+
where rn.id = ? and rn.task_id = ?
|
|
9480
|
+
limit 1
|
|
9481
|
+
`).get(options.notificationId, options.taskId);
|
|
9482
|
+
if (!row) {
|
|
9483
|
+
throw new Error(`Unknown routed notification for task ${options.taskName}: ${options.notificationId}`);
|
|
9484
|
+
}
|
|
9485
|
+
return row;
|
|
9486
|
+
}
|
|
9487
|
+
function inboxAckNotificationPayload(notification) {
|
|
9488
|
+
return {
|
|
9489
|
+
binding_id: notification.binding_id,
|
|
9490
|
+
consumed_at: notification.consumed_at,
|
|
9491
|
+
delivered_at: notification.delivered_at,
|
|
9492
|
+
delivery_mode: notification.delivery_mode,
|
|
9493
|
+
id: notification.id,
|
|
9494
|
+
signal_type: notification.signal_type,
|
|
9495
|
+
state: notification.state,
|
|
9496
|
+
target_session_id: notification.target_session_id,
|
|
9497
|
+
target_session_name: notification.target_session_name,
|
|
9498
|
+
target_session_role: notification.target_session_role,
|
|
9499
|
+
task_id: notification.task_id,
|
|
9500
|
+
};
|
|
9501
|
+
}
|
|
9502
|
+
function parseNotificationAcknowledgementStatus(value) {
|
|
9503
|
+
if (value === "received" || value === "accepted" || value === "blocked") {
|
|
9504
|
+
return value;
|
|
9505
|
+
}
|
|
9506
|
+
return new Error("inbox-ack --status must be received, accepted, or blocked.");
|
|
9507
|
+
}
|
|
9508
|
+
function validateInboxAcknowledgement(options) {
|
|
9509
|
+
if (options.notification.target_session_role !== options.role) {
|
|
9510
|
+
throw new Error(`Cannot record ${options.role} acknowledgement for notification ${options.notification.id}; target role is ${options.notification.target_session_role}.`);
|
|
9511
|
+
}
|
|
9512
|
+
if (options.notification.state !== "delivered") {
|
|
9513
|
+
throw new Error(`Cannot acknowledge notification ${options.notification.id}; state is ${options.notification.state}, expected delivered.`);
|
|
9514
|
+
}
|
|
9515
|
+
if (options.status === "received") {
|
|
9516
|
+
if (!options.notification.delivered_at) {
|
|
9517
|
+
throw new Error(`Cannot record received acknowledgement for notification ${options.notification.id}; it has no delivered_at receipt.`);
|
|
9518
|
+
}
|
|
9519
|
+
return;
|
|
9520
|
+
}
|
|
9521
|
+
if (!options.notification.consumed_at) {
|
|
9522
|
+
throw new Error(`Cannot record ${options.status} acknowledgement for notification ${options.notification.id}; it has not been consumed by the target session.`);
|
|
9523
|
+
}
|
|
9524
|
+
}
|
|
9339
9525
|
function sessionInboxResponse(database, options) {
|
|
9340
9526
|
if (options.timeoutSeconds < 0) {
|
|
9341
9527
|
throw new Error("--timeout must be non-negative");
|
|
@@ -15201,6 +15387,26 @@ function unsupportedTaskAckOptions(parsed) {
|
|
|
15201
15387
|
}
|
|
15202
15388
|
return null;
|
|
15203
15389
|
}
|
|
15390
|
+
function unsupportedInboxAckOptions(parsed) {
|
|
15391
|
+
if (!parsed.task) {
|
|
15392
|
+
return "inbox-ack requires a task.";
|
|
15393
|
+
}
|
|
15394
|
+
if (parsed.flags.notificationId === null) {
|
|
15395
|
+
return "inbox-ack requires --notification-id.";
|
|
15396
|
+
}
|
|
15397
|
+
if (!parsed.flags.fromStdin && !parsed.flags.json) {
|
|
15398
|
+
return "inbox-ack requires --from-stdin to write or --json to read.";
|
|
15399
|
+
}
|
|
15400
|
+
if (parsed.flags.fromStdin) {
|
|
15401
|
+
if (parsed.flags.role !== "manager" && parsed.flags.role !== "worker") {
|
|
15402
|
+
return "inbox-ack write requires --role manager|worker.";
|
|
15403
|
+
}
|
|
15404
|
+
if (parsed.flags.statusState === null) {
|
|
15405
|
+
return "inbox-ack write requires --status received|accepted|blocked.";
|
|
15406
|
+
}
|
|
15407
|
+
}
|
|
15408
|
+
return null;
|
|
15409
|
+
}
|
|
15204
15410
|
function unsupportedSessionInboxOptions(parsed, kind) {
|
|
15205
15411
|
if (!parsed.task) {
|
|
15206
15412
|
return kind === "session" ? "session-inbox requires a session name." : `${kind}-inbox requires a task.`;
|
|
@@ -15718,6 +15924,7 @@ function isDefaultRuntimeCommand(command) {
|
|
|
15718
15924
|
|| command === "nudge"
|
|
15719
15925
|
|| command === "worker-ack"
|
|
15720
15926
|
|| command === "manager-ack"
|
|
15927
|
+
|| command === "inbox-ack"
|
|
15721
15928
|
|| command === "session-inbox"
|
|
15722
15929
|
|| command === "manager-inbox"
|
|
15723
15930
|
|| command === "worker-inbox"
|