@scotthuang/agent-knock-knock 0.13.3 → 0.13.4
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 +14 -0
- package/README.md +13 -5
- package/dist/src/callback-outbox-policy.js +27 -6
- package/dist/src/callback-outbox-policy.js.map +1 -1
- package/dist/src/callback-outbox-service.d.ts +4 -30
- package/dist/src/callback-outbox-service.js +21 -154
- package/dist/src/callback-outbox-service.js.map +1 -1
- package/dist/src/callback-outbox-settlement.js +13 -8
- package/dist/src/callback-outbox-settlement.js.map +1 -1
- package/dist/src/callback-route-service.d.ts +46 -0
- package/dist/src/callback-route-service.js +155 -0
- package/dist/src/callback-route-service.js.map +1 -0
- package/dist/src/codex-process-incarnation.d.ts +8 -0
- package/dist/src/codex-process-incarnation.js +36 -0
- package/dist/src/codex-process-incarnation.js.map +1 -0
- package/dist/src/deferred-foreground-conflict-policy.d.ts +22 -0
- package/dist/src/deferred-foreground-conflict-policy.js +52 -0
- package/dist/src/deferred-foreground-conflict-policy.js.map +1 -0
- package/dist/src/durable-notification-kernel.d.ts +94 -0
- package/dist/src/durable-notification-kernel.js +68 -0
- package/dist/src/durable-notification-kernel.js.map +1 -0
- package/dist/src/herdr-socket-transport.d.ts +43 -0
- package/dist/src/herdr-socket-transport.js +170 -0
- package/dist/src/herdr-socket-transport.js.map +1 -0
- package/dist/src/herdr-terminal-control-provider.d.ts +2 -45
- package/dist/src/herdr-terminal-control-provider.js +2 -172
- package/dist/src/herdr-terminal-control-provider.js.map +1 -1
- package/dist/src/host-adapter-capabilities.d.ts +35 -0
- package/dist/src/host-adapter-capabilities.js +146 -0
- package/dist/src/host-adapter-capabilities.js.map +1 -0
- package/dist/src/host-adapter.d.ts +9 -3
- package/dist/src/host-adapter.js +33 -9
- package/dist/src/host-adapter.js.map +1 -1
- package/dist/src/host-bridge-tools.d.ts +3 -4
- package/dist/src/host-bridge-tools.js +49 -92
- package/dist/src/host-bridge-tools.js.map +1 -1
- package/dist/src/host-bridge.js +5 -5
- package/dist/src/host-bridge.js.map +1 -1
- package/dist/src/host-monitor-reconciliation.d.ts +6 -0
- package/dist/src/host-monitor-reconciliation.js +96 -0
- package/dist/src/host-monitor-reconciliation.js.map +1 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.js +116 -60
- package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -1
- package/dist/src/openclaw-list-projection.d.ts +2 -0
- package/dist/src/openclaw-list-projection.js +3 -0
- package/dist/src/openclaw-list-projection.js.map +1 -0
- package/dist/src/openclaw-model-facing-field-policy.d.ts +2 -0
- package/dist/src/openclaw-model-facing-field-policy.js +3 -0
- package/dist/src/openclaw-model-facing-field-policy.js.map +1 -0
- package/dist/src/openclaw-plugin-command-adapter.d.ts +6 -29
- package/dist/src/openclaw-plugin-command-adapter.js +7 -2660
- package/dist/src/openclaw-plugin-command-adapter.js.map +1 -1
- package/dist/src/openclaw-plugin-helpers.d.ts +2 -148
- package/dist/src/openclaw-plugin-helpers.js +2 -1844
- package/dist/src/openclaw-plugin-helpers.js.map +1 -1
- package/dist/src/openclaw-plugin-schemas.d.ts +2 -563
- package/dist/src/openclaw-plugin-schemas.js +2 -572
- package/dist/src/openclaw-plugin-schemas.js.map +1 -1
- package/dist/src/openclaw-plugin-supervisor.d.ts +4 -5
- package/dist/src/openclaw-plugin-supervisor.js +5 -94
- package/dist/src/openclaw-plugin-supervisor.js.map +1 -1
- package/dist/src/openclaw-plugin-value-helpers.d.ts +2 -0
- package/dist/src/openclaw-plugin-value-helpers.js +3 -0
- package/dist/src/openclaw-plugin-value-helpers.js.map +1 -0
- package/dist/src/openclaw-private-authority-offers.d.ts +4 -39
- package/dist/src/openclaw-private-authority-offers.js +3 -258
- package/dist/src/openclaw-private-authority-offers.js.map +1 -1
- package/dist/src/semantic-private-authority-offers.d.ts +41 -0
- package/dist/src/semantic-private-authority-offers.js +261 -0
- package/dist/src/semantic-private-authority-offers.js.map +1 -0
- package/dist/src/semantic-tool-arguments.d.ts +9 -0
- package/dist/src/semantic-tool-arguments.js +64 -0
- package/dist/src/semantic-tool-arguments.js.map +1 -0
- package/dist/src/semantic-tool-catalog.d.ts +48 -0
- package/dist/src/semantic-tool-catalog.js +105 -0
- package/dist/src/semantic-tool-catalog.js.map +1 -0
- package/dist/src/semantic-tool-command-helpers.d.ts +145 -0
- package/dist/src/semantic-tool-command-helpers.js +1272 -0
- package/dist/src/semantic-tool-command-helpers.js.map +1 -0
- package/dist/src/semantic-tool-list-projection.d.ts +10 -0
- package/dist/src/semantic-tool-list-projection.js +497 -0
- package/dist/src/semantic-tool-list-projection.js.map +1 -0
- package/dist/src/semantic-tool-model-facing-field-policy.d.ts +3 -0
- package/dist/src/semantic-tool-model-facing-field-policy.js +66 -0
- package/dist/src/semantic-tool-model-facing-field-policy.js.map +1 -0
- package/dist/src/semantic-tool-presentation.d.ts +37 -0
- package/dist/src/semantic-tool-presentation.js +680 -0
- package/dist/src/semantic-tool-presentation.js.map +1 -0
- package/dist/src/semantic-tool-private-authority.d.ts +39 -0
- package/dist/src/semantic-tool-private-authority.js +602 -0
- package/dist/src/semantic-tool-private-authority.js.map +1 -0
- package/dist/src/semantic-tool-relay.d.ts +16 -0
- package/dist/src/semantic-tool-relay.js +175 -0
- package/dist/src/semantic-tool-relay.js.map +1 -0
- package/dist/src/semantic-tool-runtime.d.ts +10 -0
- package/dist/src/semantic-tool-runtime.js +1157 -0
- package/dist/src/semantic-tool-runtime.js.map +1 -0
- package/dist/src/semantic-tool-schemas.d.ts +563 -0
- package/dist/src/semantic-tool-schemas.js +573 -0
- package/dist/src/semantic-tool-schemas.js.map +1 -0
- package/dist/src/semantic-tool-value-helpers.d.ts +5 -0
- package/dist/src/semantic-tool-value-helpers.js +27 -0
- package/dist/src/semantic-tool-value-helpers.js.map +1 -0
- package/dist/src/store-event-presentation.d.ts +17 -0
- package/dist/src/store-event-presentation.js +33 -0
- package/dist/src/store-event-presentation.js.map +1 -0
- package/dist/src/store.d.ts +3 -16
- package/dist/src/store.js +2 -30
- package/dist/src/store.js.map +1 -1
- package/dist/src/terminal-action-projection.d.ts +2 -98
- package/dist/src/terminal-action-projection.js +13 -215
- package/dist/src/terminal-action-projection.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +14 -340
- package/dist/src/terminal-agent-bridge.js +155 -3226
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-approval-cli-adapter.d.ts +17 -0
- package/dist/src/terminal-approval-cli-adapter.js +921 -0
- package/dist/src/terminal-approval-cli-adapter.js.map +1 -0
- package/dist/src/terminal-command-cli-adapter.d.ts +2 -429
- package/dist/src/terminal-command-cli-adapter.js +344 -6061
- package/dist/src/terminal-command-cli-adapter.js.map +1 -1
- package/dist/src/terminal-command-cli-ports.d.ts +443 -0
- package/dist/src/terminal-command-cli-ports.js +2 -0
- package/dist/src/terminal-command-cli-ports.js.map +1 -0
- package/dist/src/terminal-command-dispatch-preparation.d.ts +81 -0
- package/dist/src/terminal-command-dispatch-preparation.js +209 -0
- package/dist/src/terminal-command-dispatch-preparation.js.map +1 -0
- package/dist/src/terminal-command-dispatch-transport.d.ts +35 -0
- package/dist/src/terminal-command-dispatch-transport.js +859 -0
- package/dist/src/terminal-command-dispatch-transport.js.map +1 -0
- package/dist/src/terminal-command-foreground-proof.d.ts +32 -0
- package/dist/src/terminal-command-foreground-proof.js +72 -0
- package/dist/src/terminal-command-foreground-proof.js.map +1 -0
- package/dist/src/terminal-command-send-preflight.d.ts +41 -0
- package/dist/src/terminal-command-send-preflight.js +86 -0
- package/dist/src/terminal-command-send-preflight.js.map +1 -0
- package/dist/src/terminal-composer-classifier.d.ts +55 -0
- package/dist/src/terminal-composer-classifier.js +638 -0
- package/dist/src/terminal-composer-classifier.js.map +1 -0
- package/dist/src/terminal-dispatch-recovery-authority.d.ts +56 -0
- package/dist/src/terminal-dispatch-recovery-authority.js +251 -0
- package/dist/src/terminal-dispatch-recovery-authority.js.map +1 -0
- package/dist/src/terminal-dispatch-recovery-cli-adapter.d.ts +1 -9
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js +5 -240
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -1
- package/dist/src/terminal-handoff-cli-adapter.d.ts +1 -11
- package/dist/src/terminal-handoff-cli-adapter.js +2 -39
- package/dist/src/terminal-handoff-cli-adapter.js.map +1 -1
- package/dist/src/terminal-human-explicit-send-cli-adapter.d.ts +25 -0
- package/dist/src/terminal-human-explicit-send-cli-adapter.js +903 -0
- package/dist/src/terminal-human-explicit-send-cli-adapter.js.map +1 -0
- package/dist/src/terminal-identity-authority-cli-adapter.d.ts +1 -6
- package/dist/src/terminal-identity-authority-cli-adapter.js +3 -33
- package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -1
- package/dist/src/terminal-interaction-cli-adapter.js +209 -210
- package/dist/src/terminal-interaction-cli-adapter.js.map +1 -1
- package/dist/src/terminal-interaction-core.d.ts +0 -2
- package/dist/src/terminal-interaction-core.js +4 -3
- package/dist/src/terminal-interaction-core.js.map +1 -1
- package/dist/src/terminal-interaction-protocol.d.ts +21 -0
- package/dist/src/terminal-interaction-protocol.js +74 -0
- package/dist/src/terminal-interaction-protocol.js.map +1 -1
- package/dist/src/terminal-interaction-response-bridge.d.ts +126 -0
- package/dist/src/terminal-interaction-response-bridge.js +579 -0
- package/dist/src/terminal-interaction-response-bridge.js.map +1 -0
- package/dist/src/terminal-interaction-response-transaction.d.ts +44 -0
- package/dist/src/terminal-interaction-response-transaction.js +56 -0
- package/dist/src/terminal-interaction-response-transaction.js.map +1 -0
- package/dist/src/terminal-list-action-policy.d.ts +43 -0
- package/dist/src/terminal-list-action-policy.js +164 -0
- package/dist/src/terminal-list-action-policy.js.map +1 -0
- package/dist/src/terminal-list-cli-adapter.d.ts +6 -36
- package/dist/src/terminal-list-cli-adapter.js +241 -1946
- package/dist/src/terminal-list-cli-adapter.js.map +1 -1
- package/dist/src/terminal-list-facts.d.ts +129 -0
- package/dist/src/terminal-list-facts.js +179 -0
- package/dist/src/terminal-list-facts.js.map +1 -0
- package/dist/src/terminal-list-inventory.d.ts +59 -0
- package/dist/src/terminal-list-inventory.js +194 -0
- package/dist/src/terminal-list-inventory.js.map +1 -0
- package/dist/src/terminal-list-ownership-service.d.ts +118 -0
- package/dist/src/terminal-list-ownership-service.js +1003 -0
- package/dist/src/terminal-list-ownership-service.js.map +1 -0
- package/dist/src/terminal-list-projection-service.d.ts +49 -0
- package/dist/src/terminal-list-projection-service.js +407 -0
- package/dist/src/terminal-list-projection-service.js.map +1 -0
- package/dist/src/terminal-list-renderer.d.ts +11 -11
- package/dist/src/terminal-list-renderer.js +168 -119
- package/dist/src/terminal-list-renderer.js.map +1 -1
- package/dist/src/terminal-managed-send-cli-adapter.d.ts +33 -0
- package/dist/src/terminal-managed-send-cli-adapter.js +994 -0
- package/dist/src/terminal-managed-send-cli-adapter.js.map +1 -0
- package/dist/src/terminal-managed-turn-list-action-policy.d.ts +47 -0
- package/dist/src/terminal-managed-turn-list-action-policy.js +64 -0
- package/dist/src/terminal-managed-turn-list-action-policy.js.map +1 -0
- package/dist/src/terminal-model-control-action-policy.d.ts +60 -0
- package/dist/src/terminal-model-control-action-policy.js +96 -0
- package/dist/src/terminal-model-control-action-policy.js.map +1 -0
- package/dist/src/terminal-model-control-availability.d.ts +68 -0
- package/dist/src/terminal-model-control-availability.js +157 -0
- package/dist/src/terminal-model-control-availability.js.map +1 -0
- package/dist/src/terminal-model-control-bridge.d.ts +48 -0
- package/dist/src/terminal-model-control-bridge.js +259 -0
- package/dist/src/terminal-model-control-bridge.js.map +1 -0
- package/dist/src/terminal-model-control-profile.d.ts +55 -0
- package/dist/src/terminal-model-control-profile.js +137 -0
- package/dist/src/terminal-model-control-profile.js.map +1 -0
- package/dist/src/terminal-model-control-subject.d.ts +34 -0
- package/dist/src/terminal-model-control-subject.js +58 -0
- package/dist/src/terminal-model-control-subject.js.map +1 -0
- package/dist/src/terminal-model-control-transaction.d.ts +19 -0
- package/dist/src/terminal-model-control-transaction.js +39 -0
- package/dist/src/terminal-model-control-transaction.js.map +1 -0
- package/dist/src/terminal-model-control.d.ts +37 -18
- package/dist/src/terminal-model-control.js +285 -194
- package/dist/src/terminal-model-control.js.map +1 -1
- package/dist/src/terminal-monitor-application-service.js +50 -17
- package/dist/src/terminal-monitor-application-service.js.map +1 -1
- package/dist/src/terminal-native-inspection-bridge.d.ts +211 -0
- package/dist/src/terminal-native-inspection-bridge.js +1127 -0
- package/dist/src/terminal-native-inspection-bridge.js.map +1 -0
- package/dist/src/terminal-runtime-cli-adapter.d.ts +2 -2
- package/dist/src/terminal-runtime-cli-adapter.js.map +1 -1
- package/dist/src/terminal-submission-retry-application.d.ts +24 -0
- package/dist/src/terminal-submission-retry-application.js +402 -0
- package/dist/src/terminal-submission-retry-application.js.map +1 -0
- package/dist/src/terminal-submission-retry-ports.d.ts +30 -0
- package/dist/src/terminal-submission-retry-ports.js +2 -0
- package/dist/src/terminal-submission-retry-ports.js.map +1 -0
- package/dist/src/terminal-submission-retry-reconciliation.d.ts +236 -0
- package/dist/src/terminal-submission-retry-reconciliation.js +1130 -0
- package/dist/src/terminal-submission-retry-reconciliation.js.map +1 -0
- package/dist/src/terminal-submission-retry-transport.d.ts +58 -0
- package/dist/src/terminal-submission-retry-transport.js +675 -0
- package/dist/src/terminal-submission-retry-transport.js.map +1 -0
- package/dist/src/terminal-text-submission-bridge.d.ts +200 -0
- package/dist/src/terminal-text-submission-bridge.js +632 -0
- package/dist/src/terminal-text-submission-bridge.js.map +1 -0
- package/dist/src/terminal-user-explicit-send-policy.d.ts +29 -0
- package/dist/src/terminal-user-explicit-send-policy.js +46 -0
- package/dist/src/terminal-user-explicit-send-policy.js.map +1 -0
- package/dist/src/terminal-watch-cli-adapter.js +91 -143
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-codec.d.ts +9 -0
- package/dist/src/terminal-watch-codec.js +1051 -0
- package/dist/src/terminal-watch-codec.js.map +1 -0
- package/dist/src/terminal-watch-interaction-response-store.d.ts +19 -0
- package/dist/src/terminal-watch-interaction-response-store.js +87 -0
- package/dist/src/terminal-watch-interaction-response-store.js.map +1 -0
- package/dist/src/terminal-watch-record.d.ts +319 -0
- package/dist/src/terminal-watch-record.js +742 -0
- package/dist/src/terminal-watch-record.js.map +1 -0
- package/dist/src/terminal-watch-service.js +48 -27
- package/dist/src/terminal-watch-service.js.map +1 -1
- package/dist/src/terminal-watch-store.d.ts +3 -279
- package/dist/src/terminal-watch-store.js +5 -1779
- package/dist/src/terminal-watch-store.js.map +1 -1
- package/package.json +7 -2
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isFinalDeferredForegroundTransferStatus } from "./deferred-foreground-transfer-policy.js";
|
|
2
|
+
import { listDeferredForegroundTransfers, loadDeferredForegroundTransfer } from "./deferred-foreground-transfer.js";
|
|
3
|
+
import { turnIdForConversation } from "./protocol.js";
|
|
4
|
+
import { terminalControlEvidenceMatches } from "./terminal-control-ref.js";
|
|
5
|
+
import { isRecord, nonBlankString as stringValue } from "./value-guards.js";
|
|
6
|
+
/**
|
|
7
|
+
* Keep a Turn immutable while it is reserved by a nonterminal deferred
|
|
8
|
+
* foreground transfer. This guard observes Store state only and never sends
|
|
9
|
+
* terminal input.
|
|
10
|
+
*/
|
|
11
|
+
export function assertConversationHasNoNonterminalDeferredForegroundTransfer({ storeDir, conversation, action }) {
|
|
12
|
+
const turnId = turnIdForConversation(conversation);
|
|
13
|
+
const sourceTransfer = listDeferredForegroundTransfers(storeDir).find((candidate) => candidate.version === 2 &&
|
|
14
|
+
candidate.source_kind === "candidate_rollout_quiescent" &&
|
|
15
|
+
!isFinalDeferredForegroundTransferStatus(candidate.status) &&
|
|
16
|
+
(candidate.source_turn_history ?? []).some((sourceTurn) => sourceTurn.turn_id === turnId));
|
|
17
|
+
if (sourceTransfer) {
|
|
18
|
+
throw new Error(`cannot ${action} Turn ${turnId} while deferred foreground transfer ` +
|
|
19
|
+
`${sourceTransfer.transfer_id} reserves it as immutable source ` +
|
|
20
|
+
`history in ${sourceTransfer.status}; dedicated transfer recovery ` +
|
|
21
|
+
"must finish first");
|
|
22
|
+
}
|
|
23
|
+
const takeover = isRecord(conversation.native_session_takeover)
|
|
24
|
+
? conversation.native_session_takeover
|
|
25
|
+
: undefined;
|
|
26
|
+
const transferId = stringValue(takeover?.deferred_foreground_transfer_id);
|
|
27
|
+
if (!transferId) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const transfer = loadDeferredForegroundTransfer(storeDir, transferId);
|
|
31
|
+
if (!isFinalDeferredForegroundTransferStatus(transfer.status)) {
|
|
32
|
+
throw new Error(`cannot ${action} Turn ${turnId} while deferred foreground transfer ` +
|
|
33
|
+
`${transfer.transfer_id} is ${transfer.status}; dedicated transfer ` +
|
|
34
|
+
"recovery must finish first");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Keep one exact physical terminal immutable while a deferred foreground
|
|
39
|
+
* transfer still owns its lifecycle boundary.
|
|
40
|
+
*/
|
|
41
|
+
export function assertTerminalHasNoNonterminalDeferredForegroundTransfer({ storeDir, pid, terminalControl, action }) {
|
|
42
|
+
const transfer = listDeferredForegroundTransfers(storeDir).find((candidate) => !isFinalDeferredForegroundTransferStatus(candidate.status) &&
|
|
43
|
+
candidate.process_pid === pid &&
|
|
44
|
+
terminalControlEvidenceMatches(candidate.terminal_endpoint, terminalControl));
|
|
45
|
+
if (!transfer) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`cannot ${action} terminal ${terminalControl.target} while deferred ` +
|
|
49
|
+
`foreground transfer ${transfer.transfer_id} is ${transfer.status}; ` +
|
|
50
|
+
"dedicated transfer recovery must finish first");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=deferred-foreground-conflict-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferred-foreground-conflict-policy.js","sourceRoot":"","sources":["../../src/deferred-foreground-conflict-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAChD,0CAA0C,CAAC;AAC7C,OAAO,EAAE,+BAA+B,EACtC,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAqB,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,cAAc,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE5E;;;;GAIG;AACH,MAAM,UAAU,4DAA4D,CAAC,EAC3E,QAAQ,EACR,YAAY,EACZ,MAAM,EAKP;IACC,MAAM,MAAM,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,+BAA+B,CAAC,QAAQ,CAAC,CAAC,IAAI,CACnE,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,OAAO,KAAK,CAAC;QACvB,SAAS,CAAC,WAAW,KAAK,6BAA6B;QACvD,CAAC,uCAAuC,CAAC,SAAS,CAAC,MAAM,CAAC;QAC1D,CAAC,SAAS,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,IAAI,CACxC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,KAAK,MAAM,CAC9C,CACJ,CAAC;IACF,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,SAAS,MAAM,sCAAsC;YACrE,GAAG,cAAc,CAAC,WAAW,mCAAmC;YAChE,cAAc,cAAc,CAAC,MAAM,gCAAgC;YACnE,mBAAmB,CACpB,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,uBAAuB,CAAC;QAC7D,CAAC,CAAC,YAAY,CAAC,uBAAuB;QACtC,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,UAAU,GAAG,WAAW,CAAC,QAAQ,EAAE,+BAA+B,CAAC,CAAC;IAC1E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAG,8BAA8B,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtE,IAAI,CAAC,uCAAuC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,SAAS,MAAM,sCAAsC;YACrE,GAAG,QAAQ,CAAC,WAAW,OAAO,QAAQ,CAAC,MAAM,uBAAuB;YACpE,4BAA4B,CAC7B,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wDAAwD,CAAC,EACvE,QAAQ,EACR,GAAG,EACH,eAAe,EACf,MAAM,EAMP;IACC,MAAM,QAAQ,GAAG,+BAA+B,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC7D,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,uCAAuC,CAAC,SAAS,CAAC,MAAM,CAAC;QAC1D,SAAS,CAAC,WAAW,KAAK,GAAG;QAC7B,8BAA8B,CAC5B,SAAS,CAAC,iBAAiB,EAC3B,eAAe,CAChB,CACJ,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IACD,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,aAAa,eAAe,CAAC,MAAM,kBAAkB;QACrE,uBAAuB,QAAQ,CAAC,WAAW,OAAO,QAAQ,CAAC,MAAM,IAAI;QACrE,+CAA+C,CAChD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { CallbackAttemptOutcome } from "./callback-transport.js";
|
|
2
|
+
/**
|
|
3
|
+
* Store-neutral claim metadata shared by durable callback and Watch outboxes.
|
|
4
|
+
* Persistence adapters deliberately choose their own status names and fields.
|
|
5
|
+
*/
|
|
6
|
+
export interface DurableNotificationLease {
|
|
7
|
+
attempt: number;
|
|
8
|
+
attemptId: string;
|
|
9
|
+
attemptedAt: string;
|
|
10
|
+
leaseExpiresAt: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function createDurableNotificationLease(input: {
|
|
13
|
+
previousAttempts: number;
|
|
14
|
+
attemptId: string;
|
|
15
|
+
attemptedAt: string;
|
|
16
|
+
leaseBaseMs: number;
|
|
17
|
+
leaseMs: number;
|
|
18
|
+
}): DurableNotificationLease;
|
|
19
|
+
export type DurableNotificationRetryDecision = {
|
|
20
|
+
state: "retryable";
|
|
21
|
+
attempt: number;
|
|
22
|
+
} | {
|
|
23
|
+
state: "waiting";
|
|
24
|
+
attempt: number;
|
|
25
|
+
retry_at?: string;
|
|
26
|
+
} | {
|
|
27
|
+
state: "in_flight";
|
|
28
|
+
attempt: number;
|
|
29
|
+
lease_expires_at?: string;
|
|
30
|
+
} | {
|
|
31
|
+
state: "non_retryable";
|
|
32
|
+
attempt: number;
|
|
33
|
+
} | {
|
|
34
|
+
state: "settled";
|
|
35
|
+
attempt: number;
|
|
36
|
+
} | {
|
|
37
|
+
state: "exhausted";
|
|
38
|
+
attempt: number;
|
|
39
|
+
};
|
|
40
|
+
export type DurableNotificationRetryFacts = {
|
|
41
|
+
phase: "ready";
|
|
42
|
+
attempt: number;
|
|
43
|
+
maxAttempts?: number;
|
|
44
|
+
} | {
|
|
45
|
+
phase: "retry_wait";
|
|
46
|
+
attempt: number;
|
|
47
|
+
nowMs: number;
|
|
48
|
+
retryAt?: string;
|
|
49
|
+
retryAuthorized: boolean;
|
|
50
|
+
maxAttempts?: number;
|
|
51
|
+
} | {
|
|
52
|
+
phase: "leased";
|
|
53
|
+
attempt: number;
|
|
54
|
+
nowMs: number;
|
|
55
|
+
leaseExpiresAt?: string;
|
|
56
|
+
maxAttempts?: number;
|
|
57
|
+
} | {
|
|
58
|
+
phase: "settled";
|
|
59
|
+
attempt: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Decide whether a durable notification attempt may be claimed. The caller
|
|
63
|
+
* supplies only persisted facts plus its clock observation; no I/O or Store
|
|
64
|
+
* shape is owned here.
|
|
65
|
+
*/
|
|
66
|
+
export declare function decideDurableNotificationRetry(facts: DurableNotificationRetryFacts): DurableNotificationRetryDecision;
|
|
67
|
+
export type DurableNotificationSettlement = {
|
|
68
|
+
state: "accepted";
|
|
69
|
+
outcome: Extract<CallbackAttemptOutcome, {
|
|
70
|
+
disposition: "accepted";
|
|
71
|
+
}>;
|
|
72
|
+
} | {
|
|
73
|
+
state: "superseded";
|
|
74
|
+
outcome: Exclude<CallbackAttemptOutcome, {
|
|
75
|
+
disposition: "accepted";
|
|
76
|
+
}>;
|
|
77
|
+
} | {
|
|
78
|
+
state: "failed";
|
|
79
|
+
outcome: Exclude<CallbackAttemptOutcome, {
|
|
80
|
+
disposition: "accepted";
|
|
81
|
+
}>;
|
|
82
|
+
retryAuthorized: boolean;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Reduce one authoritative transport outcome into a Store-neutral settlement.
|
|
86
|
+
* Conversation and Watch adapters retain their distinct status/error schemas.
|
|
87
|
+
*/
|
|
88
|
+
export declare function reduceDurableNotificationSettlement(input: {
|
|
89
|
+
attempt: number;
|
|
90
|
+
outcome: CallbackAttemptOutcome;
|
|
91
|
+
retryEnabled: boolean;
|
|
92
|
+
maxRetryAttempts?: number;
|
|
93
|
+
supersede?: boolean;
|
|
94
|
+
}): DurableNotificationSettlement;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export function createDurableNotificationLease(input) {
|
|
2
|
+
return {
|
|
3
|
+
attempt: input.previousAttempts + 1,
|
|
4
|
+
attemptId: input.attemptId,
|
|
5
|
+
attemptedAt: input.attemptedAt,
|
|
6
|
+
leaseExpiresAt: new Date(input.leaseBaseMs + input.leaseMs).toISOString()
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Decide whether a durable notification attempt may be claimed. The caller
|
|
11
|
+
* supplies only persisted facts plus its clock observation; no I/O or Store
|
|
12
|
+
* shape is owned here.
|
|
13
|
+
*/
|
|
14
|
+
export function decideDurableNotificationRetry(facts) {
|
|
15
|
+
if (facts.phase !== "settled" &&
|
|
16
|
+
facts.maxAttempts !== undefined &&
|
|
17
|
+
facts.attempt > facts.maxAttempts) {
|
|
18
|
+
return { state: "exhausted", attempt: facts.attempt };
|
|
19
|
+
}
|
|
20
|
+
if (facts.phase === "ready") {
|
|
21
|
+
return { state: "retryable", attempt: facts.attempt };
|
|
22
|
+
}
|
|
23
|
+
if (facts.phase === "retry_wait") {
|
|
24
|
+
if (!facts.retryAuthorized) {
|
|
25
|
+
return { state: "non_retryable", attempt: facts.attempt };
|
|
26
|
+
}
|
|
27
|
+
const retryAtMs = Date.parse(facts.retryAt ?? "");
|
|
28
|
+
return retryAtMs <= facts.nowMs
|
|
29
|
+
? { state: "retryable", attempt: facts.attempt }
|
|
30
|
+
: {
|
|
31
|
+
state: "waiting",
|
|
32
|
+
attempt: facts.attempt,
|
|
33
|
+
retry_at: facts.retryAt
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (facts.phase === "leased") {
|
|
37
|
+
const leaseExpiresAtMs = Date.parse(facts.leaseExpiresAt ?? "");
|
|
38
|
+
return leaseExpiresAtMs <= facts.nowMs
|
|
39
|
+
? { state: "retryable", attempt: facts.attempt }
|
|
40
|
+
: {
|
|
41
|
+
state: "in_flight",
|
|
42
|
+
attempt: facts.attempt,
|
|
43
|
+
lease_expires_at: facts.leaseExpiresAt
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { state: "settled", attempt: facts.attempt };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Reduce one authoritative transport outcome into a Store-neutral settlement.
|
|
50
|
+
* Conversation and Watch adapters retain their distinct status/error schemas.
|
|
51
|
+
*/
|
|
52
|
+
export function reduceDurableNotificationSettlement(input) {
|
|
53
|
+
if (input.outcome.disposition === "accepted") {
|
|
54
|
+
return { state: "accepted", outcome: input.outcome };
|
|
55
|
+
}
|
|
56
|
+
if (input.supersede === true) {
|
|
57
|
+
return { state: "superseded", outcome: input.outcome };
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
state: "failed",
|
|
61
|
+
outcome: input.outcome,
|
|
62
|
+
retryAuthorized: input.outcome.disposition === "retryable_failure" &&
|
|
63
|
+
input.retryEnabled &&
|
|
64
|
+
(input.maxRetryAttempts === undefined ||
|
|
65
|
+
input.attempt <= input.maxRetryAttempts)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=durable-notification-kernel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-notification-kernel.js","sourceRoot":"","sources":["../../src/durable-notification-kernel.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,8BAA8B,CAAC,KAM9C;IACC,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,gBAAgB,GAAG,CAAC;QACnC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,cAAc,EAAE,IAAI,IAAI,CACtB,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAClC,CAAC,WAAW,EAAE;KAChB,CAAC;AACJ,CAAC;AAoCD;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAC5C,KAAoC;IAEpC,IACE,KAAK,CAAC,KAAK,KAAK,SAAS;QACzB,KAAK,CAAC,WAAW,KAAK,SAAS;QAC/B,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,WAAW,EACjC,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAC3B,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5D,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAClD,OAAO,SAAS,IAAI,KAAK,CAAC,KAAK;YAC7B,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;YAChD,CAAC,CAAC;gBACE,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,QAAQ,EAAE,KAAK,CAAC,OAAO;aACxB,CAAC;IACR,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAChE,OAAO,gBAAgB,IAAI,KAAK,CAAC,KAAK;YACpC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;YAChD,CAAC,CAAC;gBACE,KAAK,EAAE,WAAW;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,gBAAgB,EAAE,KAAK,CAAC,cAAc;aACvC,CAAC;IACR,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;AACtD,CAAC;AAiBD;;;GAGG;AACH,MAAM,UAAU,mCAAmC,CAAC,KAMnD;IACC,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QAC7C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACvD,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACzD,CAAC;IACD,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW,KAAK,mBAAmB;YAChE,KAAK,CAAC,YAAY;YAClB,CACE,KAAK,CAAC,gBAAgB,KAAK,SAAS;gBACpC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,gBAAgB,CACxC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const HERDR_DEFAULT_TIMEOUT_MS = 5000;
|
|
2
|
+
export interface HerdrWireRequest {
|
|
3
|
+
id: string;
|
|
4
|
+
method: string;
|
|
5
|
+
params: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface HerdrSocketIdentity {
|
|
8
|
+
device: string;
|
|
9
|
+
inode: string;
|
|
10
|
+
ctimeNs: string;
|
|
11
|
+
ownerUid?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface HerdrRequestOptions {
|
|
14
|
+
expectedSocketIdentity?: HerdrSocketIdentity;
|
|
15
|
+
}
|
|
16
|
+
export type HerdrRequestFunction = (socketPath: string, request: HerdrWireRequest, options?: HerdrRequestOptions) => Promise<unknown>;
|
|
17
|
+
/** A structured Herdr API rejection received after a complete request. */
|
|
18
|
+
export declare class HerdrApiError extends Error {
|
|
19
|
+
readonly code: string;
|
|
20
|
+
readonly requestId: string;
|
|
21
|
+
constructor(code: string, message: string, requestId: string);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Raw socket failure with an explicit dispatch boundary.
|
|
25
|
+
*
|
|
26
|
+
* `definitelyNotSent` is true only when the Unix socket never connected or
|
|
27
|
+
* the request was rejected locally before any socket write was attempted.
|
|
28
|
+
*/
|
|
29
|
+
export declare class HerdrTransportError extends Error {
|
|
30
|
+
readonly definitelyNotSent: boolean;
|
|
31
|
+
constructor(message: string, definitelyNotSent: boolean, options?: {
|
|
32
|
+
cause?: unknown;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/** Send one newline-delimited JSON request over a Herdr Unix-domain socket. */
|
|
36
|
+
export declare function requestHerdrUnixSocket(socketPath: string, request: HerdrWireRequest, options?: {
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
maxResponseBytes?: number;
|
|
39
|
+
expectedSocketIdentity?: HerdrSocketIdentity;
|
|
40
|
+
}): Promise<unknown>;
|
|
41
|
+
/** Resolve immutable filesystem identity for one owner-local Herdr socket. */
|
|
42
|
+
export declare function readHerdrSocketIdentity(socketPath: string): HerdrSocketIdentity;
|
|
43
|
+
export declare function sameHerdrSocketIdentity(left: HerdrSocketIdentity, right: HerdrSocketIdentity): boolean;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { createConnection } from "node:net";
|
|
3
|
+
const HERDR_MAX_REQUEST_BYTES = 1024 * 1024;
|
|
4
|
+
const HERDR_MAX_RESPONSE_BYTES = 16 * 1024 * 1024;
|
|
5
|
+
export const HERDR_DEFAULT_TIMEOUT_MS = 5_000;
|
|
6
|
+
/** A structured Herdr API rejection received after a complete request. */
|
|
7
|
+
export class HerdrApiError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
requestId;
|
|
10
|
+
constructor(code, message, requestId) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.requestId = requestId;
|
|
14
|
+
this.name = "HerdrApiError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Raw socket failure with an explicit dispatch boundary.
|
|
19
|
+
*
|
|
20
|
+
* `definitelyNotSent` is true only when the Unix socket never connected or
|
|
21
|
+
* the request was rejected locally before any socket write was attempted.
|
|
22
|
+
*/
|
|
23
|
+
export class HerdrTransportError extends Error {
|
|
24
|
+
definitelyNotSent;
|
|
25
|
+
constructor(message, definitelyNotSent, options = {}) {
|
|
26
|
+
super(message, options);
|
|
27
|
+
this.definitelyNotSent = definitelyNotSent;
|
|
28
|
+
this.name = "HerdrTransportError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Send one newline-delimited JSON request over a Herdr Unix-domain socket. */
|
|
32
|
+
export function requestHerdrUnixSocket(socketPath, request, options = {}) {
|
|
33
|
+
let encoded;
|
|
34
|
+
try {
|
|
35
|
+
encoded = `${JSON.stringify(request)}\n`;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return Promise.reject(new HerdrTransportError(`failed to encode Herdr request: ${describeError(error)}`, true, { cause: error }));
|
|
39
|
+
}
|
|
40
|
+
if (Buffer.byteLength(encoded) > HERDR_MAX_REQUEST_BYTES) {
|
|
41
|
+
return Promise.reject(new HerdrTransportError(`Herdr request exceeds ${HERDR_MAX_REQUEST_BYTES} bytes`, true));
|
|
42
|
+
}
|
|
43
|
+
const timeoutMs = positiveInteger(options.timeoutMs) ?? HERDR_DEFAULT_TIMEOUT_MS;
|
|
44
|
+
const maxResponseBytes = positiveInteger(options.maxResponseBytes) ??
|
|
45
|
+
HERDR_MAX_RESPONSE_BYTES;
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
let connected = false;
|
|
48
|
+
let settled = false;
|
|
49
|
+
let response = "";
|
|
50
|
+
const socket = createConnection({ path: socketPath });
|
|
51
|
+
socket.setEncoding("utf8");
|
|
52
|
+
socket.setTimeout(timeoutMs);
|
|
53
|
+
const fail = (message, definitelyNotSent, cause) => {
|
|
54
|
+
if (settled)
|
|
55
|
+
return;
|
|
56
|
+
settled = true;
|
|
57
|
+
socket.destroy();
|
|
58
|
+
reject(new HerdrTransportError(message, definitelyNotSent, { cause }));
|
|
59
|
+
};
|
|
60
|
+
socket.once("connect", () => {
|
|
61
|
+
if (settled)
|
|
62
|
+
return;
|
|
63
|
+
connected = true;
|
|
64
|
+
if (options.expectedSocketIdentity) {
|
|
65
|
+
let liveSocketIdentity;
|
|
66
|
+
try {
|
|
67
|
+
liveSocketIdentity = readHerdrSocketIdentity(socketPath);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
fail(`failed to revalidate Herdr socket ${socketPath}: ${describeError(error)}`, true, error);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!sameHerdrSocketIdentity(options.expectedSocketIdentity, liveSocketIdentity)) {
|
|
74
|
+
fail(`Herdr socket ${socketPath} changed before request dispatch`, true);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
socket.write(encoded, (error) => {
|
|
80
|
+
if (error) {
|
|
81
|
+
fail(`failed to write Herdr request: ${error.message}`, false, error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
fail(`failed to write Herdr request: ${describeError(error)}`, false, error);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
socket.on("data", (chunk) => {
|
|
90
|
+
if (settled)
|
|
91
|
+
return;
|
|
92
|
+
response += String(chunk);
|
|
93
|
+
if (Buffer.byteLength(response) > maxResponseBytes) {
|
|
94
|
+
fail(`Herdr response exceeds ${maxResponseBytes} bytes`, false);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const newline = response.indexOf("\n");
|
|
98
|
+
if (newline < 0)
|
|
99
|
+
return;
|
|
100
|
+
const line = response.slice(0, newline).trim();
|
|
101
|
+
if (!line) {
|
|
102
|
+
fail("Herdr returned an empty response", false);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
let parsed;
|
|
106
|
+
try {
|
|
107
|
+
parsed = JSON.parse(line);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
fail(`Herdr returned invalid JSON: ${describeError(error)}`, false, error);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
settled = true;
|
|
114
|
+
socket.destroy();
|
|
115
|
+
resolve(parsed);
|
|
116
|
+
});
|
|
117
|
+
socket.once("timeout", () => {
|
|
118
|
+
fail(`timed out waiting for Herdr socket ${socketPath}`, !connected);
|
|
119
|
+
});
|
|
120
|
+
socket.once("error", (error) => {
|
|
121
|
+
fail(`Herdr socket ${socketPath} failed: ${error.message}`, !connected, error);
|
|
122
|
+
});
|
|
123
|
+
socket.once("end", () => {
|
|
124
|
+
if (!settled)
|
|
125
|
+
fail("Herdr closed the socket without a response", false);
|
|
126
|
+
});
|
|
127
|
+
socket.once("close", () => {
|
|
128
|
+
if (!settled)
|
|
129
|
+
fail("Herdr closed the socket without a response", !connected);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** Resolve immutable filesystem identity for one owner-local Herdr socket. */
|
|
134
|
+
export function readHerdrSocketIdentity(socketPath) {
|
|
135
|
+
const stats = fs.lstatSync(socketPath, { bigint: true });
|
|
136
|
+
if (stats.isSymbolicLink()) {
|
|
137
|
+
throw new Error(`Herdr endpoint must not be a symbolic link: ${socketPath}`);
|
|
138
|
+
}
|
|
139
|
+
if (!stats.isSocket()) {
|
|
140
|
+
throw new Error(`Herdr endpoint is not a Unix socket: ${socketPath}`);
|
|
141
|
+
}
|
|
142
|
+
const ownerUid = Number(stats.uid);
|
|
143
|
+
const currentUid = typeof process.getuid === "function"
|
|
144
|
+
? process.getuid()
|
|
145
|
+
: undefined;
|
|
146
|
+
if (currentUid !== undefined && ownerUid !== currentUid) {
|
|
147
|
+
throw new Error(`Herdr socket ${socketPath} is owned by uid ${ownerUid}, expected ${currentUid}`);
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
device: stats.dev.toString(),
|
|
151
|
+
inode: stats.ino.toString(),
|
|
152
|
+
ctimeNs: stats.ctimeNs.toString(),
|
|
153
|
+
ownerUid
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
export function sameHerdrSocketIdentity(left, right) {
|
|
157
|
+
return left.device === right.device &&
|
|
158
|
+
left.inode === right.inode &&
|
|
159
|
+
left.ctimeNs === right.ctimeNs &&
|
|
160
|
+
left.ownerUid === right.ownerUid;
|
|
161
|
+
}
|
|
162
|
+
function positiveInteger(value) {
|
|
163
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0
|
|
164
|
+
? value
|
|
165
|
+
: undefined;
|
|
166
|
+
}
|
|
167
|
+
function describeError(error) {
|
|
168
|
+
return error instanceof Error ? error.message : String(error);
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=herdr-socket-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"herdr-socket-transport.js","sourceRoot":"","sources":["../../src/herdr-socket-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { type CommandResult, type TerminalDiscoveryDiagnosticLog, type TerminalControlProvider, type TerminalViewport } from "./terminal-control-provider.js";
|
|
2
2
|
import { type TerminalControlCapability, type TerminalControlRef, type TerminalEndpointRef, type TerminalProviderCapability } from "./terminal-control-ref.js";
|
|
3
3
|
import type { TerminalProcessSnapshot } from "./terminal-agent-adapter.js";
|
|
4
|
+
import { type HerdrRequestFunction, type HerdrSocketIdentity } from "./herdr-socket-transport.js";
|
|
5
|
+
export { HerdrApiError, HerdrTransportError, readHerdrSocketIdentity, requestHerdrUnixSocket, type HerdrRequestFunction, type HerdrRequestOptions, type HerdrSocketIdentity, type HerdrWireRequest } from "./herdr-socket-transport.js";
|
|
4
6
|
export declare const HERDR_EXACT_VERSION = "0.8.0";
|
|
5
7
|
export declare const HERDR_EXACT_PROTOCOL = 19;
|
|
6
|
-
type JsonRecord = Record<string, unknown>;
|
|
7
|
-
export interface HerdrWireRequest {
|
|
8
|
-
id: string;
|
|
9
|
-
method: string;
|
|
10
|
-
params: JsonRecord;
|
|
11
|
-
}
|
|
12
|
-
export interface HerdrSocketIdentity {
|
|
13
|
-
device: string;
|
|
14
|
-
inode: string;
|
|
15
|
-
ctimeNs: string;
|
|
16
|
-
ownerUid?: number;
|
|
17
|
-
}
|
|
18
8
|
export interface HerdrTtyDeviceIdentity {
|
|
19
9
|
device: string;
|
|
20
10
|
inode: string;
|
|
@@ -31,10 +21,6 @@ export interface HerdrTtyViewportInspectionOptions {
|
|
|
31
21
|
currentUid?: number;
|
|
32
22
|
}
|
|
33
23
|
export type HerdrTtyViewportInspector = (shellPid: number) => TerminalViewport | undefined | Promise<TerminalViewport | undefined>;
|
|
34
|
-
export interface HerdrRequestOptions {
|
|
35
|
-
expectedSocketIdentity?: HerdrSocketIdentity;
|
|
36
|
-
}
|
|
37
|
-
export type HerdrRequestFunction = (socketPath: string, request: HerdrWireRequest, options?: HerdrRequestOptions) => Promise<unknown>;
|
|
38
24
|
export interface HerdrSessionInfo {
|
|
39
25
|
name: string;
|
|
40
26
|
default: boolean;
|
|
@@ -58,33 +44,6 @@ export interface HerdrTerminalControlDiagnostics {
|
|
|
58
44
|
}>;
|
|
59
45
|
terminalCount: number;
|
|
60
46
|
}
|
|
61
|
-
/** A structured Herdr API rejection received after a complete request. */
|
|
62
|
-
export declare class HerdrApiError extends Error {
|
|
63
|
-
readonly code: string;
|
|
64
|
-
readonly requestId: string;
|
|
65
|
-
constructor(code: string, message: string, requestId: string);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Raw socket failure with an explicit dispatch boundary.
|
|
69
|
-
*
|
|
70
|
-
* `definitelyNotSent` is true only when the Unix socket never connected or
|
|
71
|
-
* the request was rejected locally before any socket write was attempted.
|
|
72
|
-
*/
|
|
73
|
-
export declare class HerdrTransportError extends Error {
|
|
74
|
-
readonly definitelyNotSent: boolean;
|
|
75
|
-
constructor(message: string, definitelyNotSent: boolean, options?: {
|
|
76
|
-
cause?: unknown;
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Send one newline-delimited JSON request over a Herdr Unix-domain socket.
|
|
81
|
-
* Normal Herdr requests receive exactly one newline-delimited JSON response.
|
|
82
|
-
*/
|
|
83
|
-
export declare function requestHerdrUnixSocket(socketPath: string, request: HerdrWireRequest, options?: {
|
|
84
|
-
timeoutMs?: number;
|
|
85
|
-
maxResponseBytes?: number;
|
|
86
|
-
expectedSocketIdentity?: HerdrSocketIdentity;
|
|
87
|
-
}): Promise<unknown>;
|
|
88
47
|
export declare class HerdrTerminalControlProvider implements TerminalControlProvider {
|
|
89
48
|
readonly kind = "herdr";
|
|
90
49
|
readonly supportedCapabilities: readonly TerminalControlCapability[];
|
|
@@ -139,5 +98,3 @@ export declare function translateHerdrKey(value: string): string;
|
|
|
139
98
|
* resize the PTY without updating the layout rectangle that owns the pane.
|
|
140
99
|
*/
|
|
141
100
|
export declare function inspectHerdrTtyViewport(shellPid: number, options?: HerdrTtyViewportInspectionOptions): TerminalViewport | undefined;
|
|
142
|
-
export declare function readHerdrSocketIdentity(socketPath: string): HerdrSocketIdentity;
|
|
143
|
-
export {};
|