@songsid/agend 2.1.7-beta.4 → 2.1.7-beta.6

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.
Files changed (98) hide show
  1. package/README.md +2 -0
  2. package/README.zh-TW.md +2 -0
  3. package/dist/agent-cli-instructions.md +5 -0
  4. package/dist/agent-cli.js +13 -0
  5. package/dist/agent-cli.js.map +1 -1
  6. package/dist/agent-endpoint.js +1 -0
  7. package/dist/agent-endpoint.js.map +1 -1
  8. package/dist/backend/codex-session-lookup.d.ts +59 -0
  9. package/dist/backend/codex-session-lookup.js +139 -0
  10. package/dist/backend/codex-session-lookup.js.map +1 -0
  11. package/dist/backend/codex.d.ts +37 -9
  12. package/dist/backend/codex.js +204 -38
  13. package/dist/backend/codex.js.map +1 -1
  14. package/dist/backend/grok.js +51 -0
  15. package/dist/backend/grok.js.map +1 -1
  16. package/dist/backend/types.d.ts +12 -0
  17. package/dist/backend/types.js.map +1 -1
  18. package/dist/channel/mcp-tools.js +2 -0
  19. package/dist/channel/mcp-tools.js.map +1 -1
  20. package/dist/cli.js +137 -124
  21. package/dist/cli.js.map +1 -1
  22. package/dist/completion-install.d.ts +32 -0
  23. package/dist/completion-install.js +125 -1
  24. package/dist/completion-install.js.map +1 -1
  25. package/dist/config-validator.js +4 -0
  26. package/dist/config-validator.js.map +1 -1
  27. package/dist/daemon.d.ts +12 -1
  28. package/dist/daemon.js +186 -27
  29. package/dist/daemon.js.map +1 -1
  30. package/dist/delivery-outbox.d.ts +199 -6
  31. package/dist/delivery-outbox.js +602 -44
  32. package/dist/delivery-outbox.js.map +1 -1
  33. package/dist/delivery-outbox.test.js +268 -14
  34. package/dist/delivery-outbox.test.js.map +1 -1
  35. package/dist/delivery-queue-evidence.d.ts +15 -0
  36. package/dist/delivery-queue-evidence.js +35 -0
  37. package/dist/delivery-queue-evidence.js.map +1 -0
  38. package/dist/delivery-queue-evidence.test.d.ts +1 -0
  39. package/dist/delivery-queue-evidence.test.js +23 -0
  40. package/dist/delivery-queue-evidence.test.js.map +1 -0
  41. package/dist/delivery-reconciliation.d.ts +49 -0
  42. package/dist/delivery-reconciliation.js +296 -0
  43. package/dist/delivery-reconciliation.js.map +1 -0
  44. package/dist/delivery-reconciliation.test.d.ts +1 -0
  45. package/dist/delivery-reconciliation.test.js +411 -0
  46. package/dist/delivery-reconciliation.test.js.map +1 -0
  47. package/dist/fleet-manager.d.ts +10 -1
  48. package/dist/fleet-manager.js +109 -32
  49. package/dist/fleet-manager.js.map +1 -1
  50. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +10 -0
  51. package/dist/instance-lifecycle.d.ts +13 -0
  52. package/dist/instance-lifecycle.js +105 -21
  53. package/dist/instance-lifecycle.js.map +1 -1
  54. package/dist/instructions.d.ts +6 -0
  55. package/dist/instructions.js +9 -0
  56. package/dist/instructions.js.map +1 -1
  57. package/dist/locale.js +8 -0
  58. package/dist/locale.js.map +1 -1
  59. package/dist/ls-rows.d.ts +50 -0
  60. package/dist/ls-rows.js +152 -0
  61. package/dist/ls-rows.js.map +1 -0
  62. package/dist/outbound-handlers.d.ts +3 -0
  63. package/dist/outbound-handlers.js +38 -2
  64. package/dist/outbound-handlers.js.map +1 -1
  65. package/dist/outbound-schemas.d.ts +8 -0
  66. package/dist/outbound-schemas.js +15 -0
  67. package/dist/outbound-schemas.js.map +1 -1
  68. package/dist/pane-write-lock.d.ts +2 -0
  69. package/dist/pane-write-lock.js +19 -0
  70. package/dist/pane-write-lock.js.map +1 -1
  71. package/dist/quickstart.js +9 -3
  72. package/dist/quickstart.js.map +1 -1
  73. package/dist/remote-credential-check.d.ts +26 -7
  74. package/dist/remote-credential-check.js +157 -10
  75. package/dist/remote-credential-check.js.map +1 -1
  76. package/dist/scheduler/scheduler.d.ts +5 -1
  77. package/dist/scheduler/scheduler.js +60 -20
  78. package/dist/scheduler/scheduler.js.map +1 -1
  79. package/dist/scheduler/scheduler.test.js +41 -2
  80. package/dist/scheduler/scheduler.test.js.map +1 -1
  81. package/dist/scheduler/types.d.ts +1 -1
  82. package/dist/tmux-manager.d.ts +3 -3
  83. package/dist/tmux-manager.js +6 -6
  84. package/dist/tmux-manager.js.map +1 -1
  85. package/dist/tool-permissions.js +6 -6
  86. package/dist/tool-permissions.js.map +1 -1
  87. package/dist/transcript-monitor.d.ts +3 -1
  88. package/dist/transcript-monitor.js +15 -0
  89. package/dist/transcript-monitor.js.map +1 -1
  90. package/dist/transcript-sources.d.ts +9 -0
  91. package/dist/transcript-sources.js +14 -0
  92. package/dist/transcript-sources.js.map +1 -1
  93. package/dist/types.d.ts +6 -0
  94. package/dist/ui/dashboard.html +7 -5
  95. package/dist/ui/view.html +138 -45
  96. package/dist/usage/usage-api.js +30 -0
  97. package/dist/usage/usage-api.js.map +1 -1
  98. package/package.json +1 -1
@@ -1,14 +1,16 @@
1
1
  import { EventEmitter } from "node:events";
2
+ import type { QueueResumePolicy } from "./delivery-queue-evidence.js";
2
3
  export declare const DURABLE_DELIVERY_MAX_ATTEMPTS = 8;
3
4
  export declare const DURABLE_DELIVERY_MAX_AGE_MS: number;
4
5
  export declare const DURABLE_DELIVERY_ABORT_BACKOFF_MS = 5000;
5
6
  export interface DaemonDeliveryPort {
6
- begin(deliveryId: string, targetBootId: string, attemptNo: number): "begun" | "duplicate" | "stale";
7
+ begin(deliveryId: string, targetBootId: string, attemptNo: number, evidence?: DeliveryAttemptEvidence): "begun" | "duplicate" | "stale";
8
+ markEnterStarted(deliveryId: string, targetBootId: string, attemptNo: number): boolean;
7
9
  abort(deliveryId: string, targetBootId: string, attemptNo: number, reason: string): boolean;
8
10
  complete(deliveryId: string, targetBootId: string, attemptNo: number, outcome: "delivered" | "failed" | "uncertain", evidence?: string): boolean;
9
11
  retryBeforeBegin(deliveryId: string, targetBootId: string, attemptNo: number, reason: string, delayMs?: number): boolean;
10
12
  }
11
- export type OutboxState = "queued" | "delivering" | "submission_started" | "retry_wait" | "delivered" | "failed" | "uncertain" | "cancelled";
13
+ export type OutboxState = "queued" | "delivering" | "submission_started" | "reconciliation_pending" | "retry_wait" | "delivered" | "failed" | "uncertain" | "cancelled";
12
14
  export interface NewOutboxDelivery {
13
15
  operationId: string;
14
16
  sourceKey: string;
@@ -39,6 +41,143 @@ export interface OutboxDelivery {
39
41
  responseDeliveredAt: string | null;
40
42
  nextAttemptAt: string | null;
41
43
  lastError: string | null;
44
+ reconciliationPending: boolean;
45
+ }
46
+ export type DeliveryStatusSelector = {
47
+ deliveryId: string;
48
+ operationId?: never;
49
+ correlationId?: never;
50
+ messageId?: never;
51
+ limit?: never;
52
+ cursor?: never;
53
+ } | {
54
+ operationId: string;
55
+ deliveryId?: never;
56
+ correlationId?: never;
57
+ messageId?: never;
58
+ limit?: number;
59
+ cursor?: string;
60
+ } | {
61
+ correlationId: string;
62
+ deliveryId?: never;
63
+ operationId?: never;
64
+ messageId?: never;
65
+ limit?: number;
66
+ cursor?: string;
67
+ }
68
+ /**
69
+ * #856: the `message_id` a receiver sees in the envelope header. Lets an
70
+ * agent check that a peer message it is about to act on was really
71
+ * delivered by the fleet — a model can "see" one nobody sent.
72
+ */
73
+ | {
74
+ messageId: string;
75
+ deliveryId?: never;
76
+ operationId?: never;
77
+ correlationId?: never;
78
+ limit?: number;
79
+ cursor?: string;
80
+ };
81
+ /** The one mapping from validated tool/CLI arguments to a selector. */
82
+ export declare function deliveryStatusSelector(args: {
83
+ delivery_id?: string;
84
+ operation_id?: string;
85
+ correlation_id?: string;
86
+ message_id?: string;
87
+ limit?: number;
88
+ cursor?: string;
89
+ }): DeliveryStatusSelector;
90
+ /** sha256 of a delivered text, as hex. The same function hashes admission and paste. */
91
+ export declare function deliveryContentDigest(text: string): string;
92
+ /** #926 reminders and overdue notices; never themselves the subject of a failure notice. */
93
+ export declare const REPLY_OBLIGATION_NOTICE_KIND = "reply_obligation_notice";
94
+ export interface DeliveryStatusItem {
95
+ delivery_id: string;
96
+ operation_id: string;
97
+ correlation_id: string | null;
98
+ source_instance: string;
99
+ target_instance: string;
100
+ kind: string;
101
+ state: OutboxState;
102
+ attempt_no: number;
103
+ created_at: string;
104
+ updated_at: string;
105
+ status_summary: string;
106
+ error_summary: string | null;
107
+ safe_to_retry: boolean;
108
+ /** Fleet message ID of the delivered envelope, when it had one. */
109
+ message_id: string | null;
110
+ /** sha256 of the delivered text as admitted (#856). */
111
+ content_sha256: string | null;
112
+ /**
113
+ * The text as admitted — only on a `message_id` query by the row's own
114
+ * source or target: the caller already sent or received it, and verifying
115
+ * a value (a SHA, a PR number) needs the text, not just its digest. Every
116
+ * other query, and operator reads, stay redacted as before (#982).
117
+ */
118
+ content?: string | null;
119
+ /** #926: the reply this request is owed, when it asked for one. */
120
+ reply_obligation?: {
121
+ state: "open" | "answered";
122
+ opened_at: string;
123
+ last_asked_at: string;
124
+ nudged_at: string | null;
125
+ overdue_notified_at: string | null;
126
+ answered_at: string | null;
127
+ } | null;
128
+ }
129
+ /**
130
+ * #926: a peer asked with `requires_reply` and the owner has not answered it
131
+ * through the fleet yet. Terminal text is not an answer: only a message the
132
+ * owner sends back to the requester with the same correlation_id closes it.
133
+ */
134
+ export interface ReplyObligation {
135
+ correlationId: string;
136
+ requesterInstance: string;
137
+ ownerInstance: string;
138
+ requestDeliveryId: string;
139
+ openedAt: string;
140
+ lastAskedAt: string;
141
+ state: "open" | "answered";
142
+ nudgedAt: string | null;
143
+ overdueNotifiedAt: string | null;
144
+ answeredAt: string | null;
145
+ answeredDeliveryId: string | null;
146
+ }
147
+ export interface DeliveryStatusPage {
148
+ items: DeliveryStatusItem[];
149
+ next_cursor: string | null;
150
+ }
151
+ export type DurableSubmissionMode = "idle_submit" | "native_queue_handoff" | "steer" | "raw_paste";
152
+ /** Checkpoint committed with begin, before any pane paste can occur. */
153
+ export interface DeliveryAttemptEvidence {
154
+ backend: string;
155
+ backendVersion?: string | null;
156
+ windowId: string | null;
157
+ transcriptPath: string | null;
158
+ transcriptOffset: number | null;
159
+ transcriptSessionId: string | null;
160
+ submissionMode: DurableSubmissionMode;
161
+ queueResumePolicy?: QueueResumePolicy;
162
+ /** sha256 of the text the target daemon received, before formatting (#856). */
163
+ pastedContentSha256?: string | null;
164
+ /** sha256 of the exact string handed to the pane write (#856). */
165
+ pastedBytesSha256?: string | null;
166
+ }
167
+ export interface DeliveryReconciliationCandidate extends OutboxDelivery {
168
+ attempt: {
169
+ targetDaemonBootId: string;
170
+ attemptNo: number;
171
+ backend: string | null;
172
+ backendVersion: string | null;
173
+ windowId: string | null;
174
+ transcriptPath: string | null;
175
+ transcriptOffset: number | null;
176
+ transcriptSessionId: string | null;
177
+ submissionMode: DurableSubmissionMode | null;
178
+ queueResumePolicy: QueueResumePolicy | null;
179
+ enterStartedAt: string | null;
180
+ };
42
181
  }
43
182
  export interface ClaimedOutboxDelivery extends OutboxDelivery {
44
183
  targetDaemonBootId: string;
@@ -48,6 +187,45 @@ export declare class DeliveryOutbox extends EventEmitter {
48
187
  private readonly db;
49
188
  readonly managerBootId: string;
50
189
  constructor(dbPath: string, managerBootId?: string);
190
+ /**
191
+ * #926: a delivered `requires_reply` request opens (or, asked again,
192
+ * re-opens) the owner's obligation. Runs inside the delivered transition.
193
+ * An answer admitted before the request finished its submission proof —
194
+ * an owner can reply while the daemon is still confirming — counts.
195
+ */
196
+ private openReplyObligation;
197
+ /** The owner's message back to the requester on the same correlation_id answers it — at admission. */
198
+ private answerReplyObligation;
199
+ /**
200
+ * #926 safety net 1: remind an owner that has not answered. `turn-ended`
201
+ * reminds once per ask, after the grace (a reply seconds after the ask is
202
+ * normal); `restart` reminds once per restart, because the interrupted turn
203
+ * does not resume on its own. Marked in the same transaction as the notice.
204
+ */
205
+ remindReplyObligations(ownerInstance: string, opts: {
206
+ now?: Date;
207
+ graceMs: number;
208
+ reason: "turn-ended" | "restart";
209
+ since?: Date;
210
+ }): number;
211
+ /**
212
+ * #926 safety net 2 (poll-on-timeout, in code): tell the requester once when
213
+ * the owner is not working and nothing has come back for `overdueMs` since
214
+ * the last ask or reminder. A still-working owner is never reported.
215
+ */
216
+ notifyOverdueReplyObligations(opts: {
217
+ now?: Date;
218
+ overdueMs: number;
219
+ ownerIdle: (owner: string) => boolean;
220
+ }): number;
221
+ /** A system notice as a durable row, like #929's outcome notices; the key makes it idempotent. */
222
+ private insertReplyObligationNotice;
223
+ /** The owner's open obligations, oldest first (#926). */
224
+ openReplyObligations(ownerInstance: string): ReplyObligation[];
225
+ getReplyObligation(correlationId: string, requesterInstance: string, ownerInstance: string): ReplyObligation | undefined;
226
+ /** Rows admitted before #856 get the same message_id / digest a new row would. */
227
+ private backfillMessageEvidence;
228
+ private ensureColumn;
51
229
  /** Commit admission before returning success. Duplicate source keys return their original row. */
52
230
  admit(input: NewOutboxDelivery): {
53
231
  delivery: OutboxDelivery;
@@ -55,19 +233,29 @@ export declare class DeliveryOutbox extends EventEmitter {
55
233
  };
56
234
  get(deliveryId: string): OutboxDelivery | undefined;
57
235
  getByOperation(sourceInstance: string, operationId: string): OutboxDelivery[];
236
+ /**
237
+ * Query only rows owned by the authenticated instance as source or target.
238
+ * This method accepts caller identity separately from user arguments so a
239
+ * caller cannot widen its own visibility with a forged source name.
240
+ */
241
+ queryStatusForInstance(callerInstance: string, selector: DeliveryStatusSelector): DeliveryStatusPage;
242
+ /** Open the existing outbox without migrations or writes for the operator CLI. */
243
+ static queryStatusReadOnly(dbPath: string, selector: DeliveryStatusSelector): DeliveryStatusPage;
58
244
  listPending(): OutboxDelivery[];
59
245
  nextRetryAt(): string | null;
60
246
  /** Claim the earliest eligible target row; one caller owns each target lane. */
61
247
  claimNext(managerBootId: string, targetBootIdFor: (target: string) => string | null, blockedTargets: ReadonlySet<string>): ClaimedOutboxDelivery | undefined;
62
248
  /** Idempotent begin permit, committed immediately before the pane side effect. */
63
- begin(deliveryId: string, targetBootId: string, attemptNo: number): "begun" | "duplicate" | "stale";
249
+ begin(deliveryId: string, targetBootId: string, attemptNo: number, evidence?: DeliveryAttemptEvidence): "begun" | "duplicate" | "stale";
250
+ /** Write-ahead fence: commit before tmux is allowed to receive Enter. */
251
+ markEnterStarted(deliveryId: string, targetBootId: string, attemptNo: number): boolean;
64
252
  /** Safe only when the caller can prove no pane write occurred for this attempt. */
65
253
  abort(deliveryId: string, targetBootId: string, attemptNo: number, reason: string): boolean;
66
254
  complete(deliveryId: string, targetBootId: string, attemptNo: number, outcome: "delivered" | "failed" | "uncertain", evidence?: string): boolean;
67
255
  /** Transient pre-submit failure: state is retryable and the same row keeps its FIFO position. */
68
256
  retryBeforeBegin(deliveryId: string, targetBootId: string, attemptNo: number, reason: string, delayMs?: number): boolean;
69
257
  failBeforeBegin(deliveryId: string, reason: string): boolean;
70
- /** Expire unavailable/pre-submit rows instead of leaving them queued forever. */
258
+ /** Bound both unavailable rows and unresolved reconciliation without stealing a live lease. */
71
259
  expireStale(nowMs?: number, maxAgeMs?: number): number;
72
260
  /** Next queued/retry expiry for bounded maintenance scheduling. */
73
261
  nextExpiryAt(): string | null;
@@ -75,14 +263,19 @@ export declare class DeliveryOutbox extends EventEmitter {
75
263
  /** Old process leases are recoverable; an old submission attempt needs evidence reconciliation. */
76
264
  recoverForBoot(managerBootId: string): {
77
265
  queued: number;
78
- uncertain: number;
266
+ reconciliationPending: number;
79
267
  };
80
268
  /** Atomically create a post-restart notice for an accepted operation whose response was not recorded. */
81
269
  admitPostRestartOutcomeNotice(parent: OutboxDelivery, currentSourceBootId: string): OutboxDelivery | undefined;
82
270
  recoverTargetGeneration(targetInstance: string, currentTargetBootId: string): {
83
271
  queued: number;
84
- uncertain: number;
272
+ reconciliationPending: number;
85
273
  };
274
+ /** Fence in-flight writes before an in-process target stop begins. */
275
+ markTargetReconciliationPending(targetInstance: string, targetBootId: string): number;
276
+ getReconciliationCandidates(targetInstance: string): DeliveryReconciliationCandidate[];
277
+ /** Atomically settle one old attempt using only its boot/attempt fence. */
278
+ reconcileAttempt(deliveryId: string, targetBootId: string, attemptNo: number, outcome: "delivered" | "retry_wait" | "uncertain", evidence: string): boolean;
86
279
  getUnansweredAccepted(sourceInstance: string, currentBootId: string): OutboxDelivery[];
87
280
  close(): void;
88
281
  /** Must be called inside the same SQLite transaction as the terminal transition. */