agent-conveyor 0.1.21 → 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 +20 -3
- package/dist/cli/typescript-runtime.js +208 -6
- 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 +2 -1
- 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 +4 -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-
|
|
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:
|
|
@@ -207,6 +208,12 @@ single `CONVEYOR IDLE` line.
|
|
|
207
208
|
For bounded follow-up passes after the first worker result, use
|
|
208
209
|
`Use the conveyor-whats-next-nudger skill`.
|
|
209
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
|
+
|
|
210
217
|
Dispatch is core infrastructure for supervised worker/manager pairs. The
|
|
211
218
|
`pair` workflow starts a detached Dispatch watch process by default so worker
|
|
212
219
|
completion is routed to the bound manager mechanically. For manually bound
|
|
@@ -515,7 +522,8 @@ stay out of receipts.
|
|
|
515
522
|
[--json]` — Record what the Codex app/operator layer did with a wake action.
|
|
516
523
|
`sent` is accepted only when the referenced `app-wakeup-dispatch` receipt has
|
|
517
524
|
a matching `ready_to_send` action with `send_ready=true` and the same thread
|
|
518
|
-
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.
|
|
519
527
|
- `app-autopilot start|stop|status TASK [--dispatcher-id ID]
|
|
520
528
|
[--interval SECONDS] [--watch-iterations N] [--stale-after N]
|
|
521
529
|
[--quiet-after N] [--json]` —
|
|
@@ -807,6 +815,15 @@ stay out of receipts.
|
|
|
807
815
|
- `worker-inbox <task> [--consume-next] [--wait] [--timeout N] [--interval N]
|
|
808
816
|
[--limit N] [--json]` — Resolve the task's bound worker session and read its
|
|
809
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.
|
|
810
827
|
|
|
811
828
|
### Actuation
|
|
812
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") {
|
|
@@ -6698,6 +6737,7 @@ function runInstallSkillsCommand(parsed, options) {
|
|
|
6698
6737
|
}
|
|
6699
6738
|
const AGENT_CONVEYOR_PLUGIN_NAME = "agent-conveyor";
|
|
6700
6739
|
const AGENT_CONVEYOR_PLUGIN_SKILLS = [
|
|
6740
|
+
"conveyor-app-wake-relay",
|
|
6701
6741
|
"conveyor-create-pair",
|
|
6702
6742
|
"conveyor-create-worker-set",
|
|
6703
6743
|
"conveyor-check-status",
|
|
@@ -9092,6 +9132,94 @@ function runTaskAckCommand(parsed, options, role) {
|
|
|
9092
9132
|
database.close();
|
|
9093
9133
|
}
|
|
9094
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
|
+
}
|
|
9095
9223
|
function runSessionInboxCommand(parsed, options, kind) {
|
|
9096
9224
|
const unsupported = unsupportedSessionInboxOptions(parsed, kind);
|
|
9097
9225
|
if (unsupported) {
|
|
@@ -9341,6 +9469,59 @@ function latestTaskAcknowledgementSync(database, options) {
|
|
|
9341
9469
|
task_id: row.task_id,
|
|
9342
9470
|
};
|
|
9343
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
|
+
}
|
|
9344
9525
|
function sessionInboxResponse(database, options) {
|
|
9345
9526
|
if (options.timeoutSeconds < 0) {
|
|
9346
9527
|
throw new Error("--timeout must be non-negative");
|
|
@@ -15206,6 +15387,26 @@ function unsupportedTaskAckOptions(parsed) {
|
|
|
15206
15387
|
}
|
|
15207
15388
|
return null;
|
|
15208
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
|
+
}
|
|
15209
15410
|
function unsupportedSessionInboxOptions(parsed, kind) {
|
|
15210
15411
|
if (!parsed.task) {
|
|
15211
15412
|
return kind === "session" ? "session-inbox requires a session name." : `${kind}-inbox requires a task.`;
|
|
@@ -15723,6 +15924,7 @@ function isDefaultRuntimeCommand(command) {
|
|
|
15723
15924
|
|| command === "nudge"
|
|
15724
15925
|
|| command === "worker-ack"
|
|
15725
15926
|
|| command === "manager-ack"
|
|
15927
|
+
|| command === "inbox-ack"
|
|
15726
15928
|
|| command === "session-inbox"
|
|
15727
15929
|
|| command === "manager-inbox"
|
|
15728
15930
|
|| command === "worker-inbox"
|