@scotthuang/agent-knock-knock 0.12.13 → 0.12.15
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 +44 -0
- package/README.md +13 -13
- package/dist/src/callback-cli-adapter.d.ts +9 -6
- package/dist/src/callback-cli-adapter.js +119 -30
- package/dist/src/callback-cli-adapter.js.map +1 -1
- package/dist/src/callback-outbox-policy.d.ts +39 -0
- package/dist/src/callback-outbox-policy.js +163 -6
- package/dist/src/callback-outbox-policy.js.map +1 -1
- package/dist/src/callback-outbox-service.d.ts +28 -1
- package/dist/src/callback-outbox-service.js +413 -82
- package/dist/src/callback-outbox-service.js.map +1 -1
- package/dist/src/callback-outbox-settlement.d.ts +14 -1
- package/dist/src/callback-outbox-settlement.js +151 -30
- package/dist/src/callback-outbox-settlement.js.map +1 -1
- package/dist/src/callback-route-authority.d.ts +59 -0
- package/dist/src/callback-route-authority.js +123 -0
- package/dist/src/callback-route-authority.js.map +1 -0
- package/dist/src/callback-transport.d.ts +134 -0
- package/dist/src/callback-transport.js +256 -0
- package/dist/src/callback-transport.js.map +1 -0
- package/dist/src/cli-core.js +56 -18
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/cli-runtime-context.d.ts +2 -0
- package/dist/src/cli-runtime-context.js.map +1 -1
- package/dist/src/codex-lifecycle-compatibility.js +2 -1
- package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
- package/dist/src/deferred-foreground-application-service.d.ts +18 -0
- package/dist/src/deferred-foreground-application-service.js +72 -0
- package/dist/src/deferred-foreground-application-service.js.map +1 -1
- package/dist/src/deferred-foreground-authority-cli-adapter.js +10 -1
- package/dist/src/deferred-foreground-authority-cli-adapter.js.map +1 -1
- package/dist/src/deferred-foreground-recovery-cli-adapter.d.ts +1 -1
- package/dist/src/deferred-foreground-recovery-cli-adapter.js +108 -37
- package/dist/src/deferred-foreground-recovery-cli-adapter.js.map +1 -1
- package/dist/src/deferred-foreground-recovery-service.d.ts +1 -1
- package/dist/src/deferred-foreground-recovery-service.js +10 -3
- package/dist/src/deferred-foreground-recovery-service.js.map +1 -1
- package/dist/src/deferred-foreground-transfer-policy.d.ts +1 -1
- package/dist/src/deferred-foreground-transfer-policy.js +3 -2
- package/dist/src/deferred-foreground-transfer-policy.js.map +1 -1
- package/dist/src/deferred-foreground-transfer.d.ts +17 -1
- package/dist/src/deferred-foreground-transfer.js +244 -35
- package/dist/src/deferred-foreground-transfer.js.map +1 -1
- package/dist/src/deferred-foreground-user-close.d.ts +18 -0
- package/dist/src/deferred-foreground-user-close.js +180 -0
- package/dist/src/deferred-foreground-user-close.js.map +1 -0
- package/dist/src/install-doctor-command-adapter.js +1 -1
- package/dist/src/install-doctor-command-adapter.js.map +1 -1
- package/dist/src/openclaw-callback-transport.d.ts +4 -1
- package/dist/src/openclaw-callback-transport.js +403 -10
- package/dist/src/openclaw-callback-transport.js.map +1 -1
- package/dist/src/openclaw-doctor.js +16 -2
- package/dist/src/openclaw-doctor.js.map +1 -1
- package/dist/src/openclaw-managed-callback-cli-adapter.d.ts +23 -0
- package/dist/src/openclaw-managed-callback-cli-adapter.js +77 -0
- package/dist/src/openclaw-managed-callback-cli-adapter.js.map +1 -0
- package/dist/src/openclaw-plugin-command-adapter.js +93 -39
- package/dist/src/openclaw-plugin-command-adapter.js.map +1 -1
- package/dist/src/openclaw-plugin-helpers.d.ts +1 -0
- package/dist/src/openclaw-plugin-helpers.js +9 -1
- package/dist/src/openclaw-plugin-helpers.js.map +1 -1
- package/dist/src/openclaw-plugin-schemas.d.ts +20 -1
- package/dist/src/openclaw-plugin-schemas.js +27 -3
- package/dist/src/openclaw-plugin-schemas.js.map +1 -1
- package/dist/src/protocol.d.ts +3 -0
- package/dist/src/protocol.js +4 -0
- package/dist/src/protocol.js.map +1 -1
- package/dist/src/store.d.ts +12 -1
- package/dist/src/store.js +81 -3
- package/dist/src/store.js.map +1 -1
- package/dist/src/terminal-acceptance-cli-adapter.d.ts +2 -0
- package/dist/src/terminal-acceptance-cli-adapter.js +62 -12
- package/dist/src/terminal-acceptance-cli-adapter.js.map +1 -1
- package/dist/src/terminal-action-projection.d.ts +31 -3
- package/dist/src/terminal-action-projection.js +64 -9
- package/dist/src/terminal-action-projection.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +82 -0
- package/dist/src/terminal-agent-bridge.js +553 -109
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-command-cli-adapter.d.ts +26 -2
- package/dist/src/terminal-command-cli-adapter.js +3162 -214
- package/dist/src/terminal-command-cli-adapter.js.map +1 -1
- package/dist/src/terminal-delegate-cli-adapter.d.ts +4 -22
- package/dist/src/terminal-delegate-cli-adapter.js +239 -192
- package/dist/src/terminal-delegate-cli-adapter.js.map +1 -1
- package/dist/src/terminal-delegate-send-binding.d.ts +63 -0
- package/dist/src/terminal-delegate-send-binding.js +360 -0
- package/dist/src/terminal-delegate-send-binding.js.map +1 -0
- package/dist/src/terminal-dispatch-application.d.ts +4 -1
- package/dist/src/terminal-dispatch-application.js +11 -2
- package/dist/src/terminal-dispatch-application.js.map +1 -1
- package/dist/src/terminal-dispatch-composition.d.ts +5 -0
- package/dist/src/terminal-dispatch-execution.js +3 -1
- package/dist/src/terminal-dispatch-execution.js.map +1 -1
- package/dist/src/terminal-dispatch-ledger-codec.d.ts +3 -0
- package/dist/src/terminal-dispatch-ledger-codec.js +46 -19
- package/dist/src/terminal-dispatch-ledger-codec.js.map +1 -1
- package/dist/src/terminal-dispatch-presenter.js +5 -3
- package/dist/src/terminal-dispatch-presenter.js.map +1 -1
- package/dist/src/terminal-dispatch-receipt.d.ts +3 -0
- package/dist/src/terminal-dispatch-receipt.js +15 -1
- package/dist/src/terminal-dispatch-receipt.js.map +1 -1
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js +68 -7
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -1
- package/dist/src/terminal-dispatch-recovery-service.d.ts +2 -0
- package/dist/src/terminal-dispatch-recovery-service.js +9 -0
- package/dist/src/terminal-dispatch-recovery-service.js.map +1 -1
- package/dist/src/terminal-dispatch-repository-cli-adapter.d.ts +4 -2
- package/dist/src/terminal-dispatch-repository-cli-adapter.js +10 -3
- package/dist/src/terminal-dispatch-repository-cli-adapter.js.map +1 -1
- package/dist/src/terminal-identity-authority-cli-adapter.d.ts +2 -0
- package/dist/src/terminal-identity-authority-cli-adapter.js +34 -27
- package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -1
- package/dist/src/terminal-list-cli-adapter.d.ts +6 -0
- package/dist/src/terminal-list-cli-adapter.js +391 -177
- package/dist/src/terminal-list-cli-adapter.js.map +1 -1
- package/dist/src/terminal-list-renderer.d.ts +9 -1
- package/dist/src/terminal-list-renderer.js +226 -104
- package/dist/src/terminal-list-renderer.js.map +1 -1
- package/dist/src/terminal-maintenance-cli-adapter.js +253 -326
- package/dist/src/terminal-maintenance-cli-adapter.js.map +1 -1
- package/dist/src/terminal-monitor-application-service.d.ts +5 -0
- package/dist/src/terminal-monitor-application-service.js +5 -0
- package/dist/src/terminal-monitor-application-service.js.map +1 -1
- package/dist/src/terminal-monitor-cli-adapter.d.ts +25 -1
- package/dist/src/terminal-monitor-cli-adapter.js +170 -27
- package/dist/src/terminal-monitor-cli-adapter.js.map +1 -1
- package/dist/src/terminal-monitor-reconciliation-eligibility.d.ts +1 -1
- package/dist/src/terminal-monitor-reconciliation-eligibility.js +220 -32
- package/dist/src/terminal-monitor-reconciliation-eligibility.js.map +1 -1
- package/dist/src/terminal-monitor-state-cli-adapter.d.ts +1 -1
- package/dist/src/terminal-monitor-state-cli-adapter.js +808 -147
- package/dist/src/terminal-monitor-state-cli-adapter.js.map +1 -1
- package/dist/src/terminal-monitor-state-reconciliation-service.d.ts +2 -1
- package/dist/src/terminal-monitor-state-reconciliation-service.js +12 -0
- package/dist/src/terminal-monitor-state-reconciliation-service.js.map +1 -1
- package/dist/src/terminal-monitor-supervision-cli-adapter.d.ts +2 -0
- package/dist/src/terminal-monitor-supervision-cli-adapter.js +31 -11
- package/dist/src/terminal-monitor-supervision-cli-adapter.js.map +1 -1
- package/dist/src/terminal-process-source.d.ts +13 -0
- package/dist/src/terminal-process-source.js +37 -0
- package/dist/src/terminal-process-source.js.map +1 -1
- package/dist/src/terminal-runtime-cli-adapter.js +14 -2
- package/dist/src/terminal-runtime-cli-adapter.js.map +1 -1
- package/dist/src/terminal-status-cli-adapter.d.ts +1 -0
- package/dist/src/terminal-status-cli-adapter.js +30 -28
- package/dist/src/terminal-status-cli-adapter.js.map +1 -1
- package/dist/src/terminal-submission-acceptance.js +78 -25
- package/dist/src/terminal-submission-acceptance.js.map +1 -1
- package/dist/src/terminal-submission-retry-service.d.ts +114 -0
- package/dist/src/terminal-submission-retry-service.js +589 -0
- package/dist/src/terminal-submission-retry-service.js.map +1 -0
- package/dist/src/terminal-user-send-intent.d.ts +65 -0
- package/dist/src/terminal-user-send-intent.js +317 -0
- package/dist/src/terminal-user-send-intent.js.map +1 -0
- package/dist/src/terminal-watch-callback-cli-adapter.d.ts +10 -2
- package/dist/src/terminal-watch-callback-cli-adapter.js +76 -37
- package/dist/src/terminal-watch-callback-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-cli-adapter.js +41 -17
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-service.d.ts +11 -6
- package/dist/src/terminal-watch-service.js +210 -41
- package/dist/src/terminal-watch-service.js.map +1 -1
- package/dist/src/terminal-watch-store.d.ts +23 -0
- package/dist/src/terminal-watch-store.js +162 -4
- package/dist/src/terminal-watch-store.js.map +1 -1
- package/docs/quickstart-herdr.md +1 -1
- package/docs/quickstart-tmux.md +3 -3
- package/package.json +1 -1
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +14 -11
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { atomicSaveJsonFile } from "./durable-json-file.js";
|
|
2
|
+
export declare const TERMINAL_USER_SEND_INTENT_SCHEMA = "agent-knock-knock/terminal-user-send-intent";
|
|
3
|
+
export declare const TERMINAL_USER_SEND_INTENT_VERSION = 1;
|
|
4
|
+
export declare const TERMINAL_USER_SEND_INTENTS_DIRECTORY = "terminal-user-send-intents";
|
|
5
|
+
export type TerminalUserSendIntentStage = "reserved" | "zero_input_cancelled" | "enter_dispatched";
|
|
6
|
+
export type TerminalUserSendDeliveryMode = "managed" | "unmanaged";
|
|
7
|
+
export declare class TerminalUserSendIntentBoundaryConflictError extends Error {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class TerminalUserSendIntentUncertainError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export interface TerminalUserSendIntentBoundary {
|
|
14
|
+
terminalRuntimeKey: string;
|
|
15
|
+
physicalToken: string;
|
|
16
|
+
messageId: string;
|
|
17
|
+
requestHash: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TerminalUserSendIntent {
|
|
20
|
+
schema: typeof TERMINAL_USER_SEND_INTENT_SCHEMA;
|
|
21
|
+
version: typeof TERMINAL_USER_SEND_INTENT_VERSION;
|
|
22
|
+
terminal_runtime_key: string;
|
|
23
|
+
physical_token: string;
|
|
24
|
+
message_id: string;
|
|
25
|
+
request_hash: string;
|
|
26
|
+
stage: TerminalUserSendIntentStage;
|
|
27
|
+
reserved_at: string;
|
|
28
|
+
zero_input_cancelled_at?: string;
|
|
29
|
+
enter_dispatched_at?: string;
|
|
30
|
+
delivery_mode?: TerminalUserSendDeliveryMode;
|
|
31
|
+
}
|
|
32
|
+
export type TerminalUserSendIntentReserveResult = {
|
|
33
|
+
outcome: "reserved";
|
|
34
|
+
intent: TerminalUserSendIntent;
|
|
35
|
+
} | {
|
|
36
|
+
outcome: "replay" | "uncertain";
|
|
37
|
+
stage: TerminalUserSendIntentStage;
|
|
38
|
+
intent: TerminalUserSendIntent;
|
|
39
|
+
};
|
|
40
|
+
export interface TerminalUserSendIntentRepository {
|
|
41
|
+
pathFor(input: Pick<TerminalUserSendIntentBoundary, "messageId">): string;
|
|
42
|
+
load(input: TerminalUserSendIntentBoundary): TerminalUserSendIntent | undefined;
|
|
43
|
+
reserve(input: TerminalUserSendIntentBoundary): TerminalUserSendIntentReserveResult;
|
|
44
|
+
cancelProvenZeroInput(input: TerminalUserSendIntentBoundary): boolean;
|
|
45
|
+
complete(input: TerminalUserSendIntentBoundary, deliveryMode: TerminalUserSendDeliveryMode): TerminalUserSendIntent;
|
|
46
|
+
}
|
|
47
|
+
interface TerminalUserSendIntentRepositoryOptions {
|
|
48
|
+
runtimeDir: string;
|
|
49
|
+
now?: () => Date;
|
|
50
|
+
ensureDirectory?: (directoryPath: string) => void;
|
|
51
|
+
acquireLock?: (lockPath: string) => () => void;
|
|
52
|
+
saveJson?: typeof atomicSaveJsonFile;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Store-independent global idempotency for one explicit physical-terminal
|
|
56
|
+
* Send. The path is keyed only by host message id, so the same id cannot move
|
|
57
|
+
* between explicit, delegated, or differently targeted terminal entry points.
|
|
58
|
+
*
|
|
59
|
+
* The caller owns the physical-terminal lock. A reserved record means the
|
|
60
|
+
* previous managed or unmanaged attempt may have started input; only a
|
|
61
|
+
* completed record is safe to replay as success. The request body is never
|
|
62
|
+
* stored.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createTerminalUserSendIntentRepository(options: TerminalUserSendIntentRepositoryOptions): TerminalUserSendIntentRepository;
|
|
65
|
+
export {};
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstatSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { atomicSaveJsonFile, isNodeError, readJsonFileNoFollow } from "./durable-json-file.js";
|
|
6
|
+
import { ensureDir } from "./store.js";
|
|
7
|
+
import { createFileLockCliAdapter } from "./file-lock-cli-adapter.js";
|
|
8
|
+
export const TERMINAL_USER_SEND_INTENT_SCHEMA = "agent-knock-knock/terminal-user-send-intent";
|
|
9
|
+
export const TERMINAL_USER_SEND_INTENT_VERSION = 1;
|
|
10
|
+
export const TERMINAL_USER_SEND_INTENTS_DIRECTORY = "terminal-user-send-intents";
|
|
11
|
+
export class TerminalUserSendIntentBoundaryConflictError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "TerminalUserSendIntentBoundaryConflictError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class TerminalUserSendIntentUncertainError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "TerminalUserSendIntentUncertainError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const ALLOWED_KEYS = new Set([
|
|
24
|
+
"schema",
|
|
25
|
+
"version",
|
|
26
|
+
"terminal_runtime_key",
|
|
27
|
+
"physical_token",
|
|
28
|
+
"message_id",
|
|
29
|
+
"request_hash",
|
|
30
|
+
"stage",
|
|
31
|
+
"reserved_at",
|
|
32
|
+
"zero_input_cancelled_at",
|
|
33
|
+
"enter_dispatched_at",
|
|
34
|
+
"delivery_mode"
|
|
35
|
+
]);
|
|
36
|
+
function digest(value) {
|
|
37
|
+
return createHash("sha256").update(value, "utf8").digest("hex");
|
|
38
|
+
}
|
|
39
|
+
function requiredString(value, label) {
|
|
40
|
+
if (typeof value !== "string" || value.length === 0 || value.includes("\0")) {
|
|
41
|
+
throw new Error(`${label} must be a non-empty string without NUL bytes`);
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
function canonicalTimestamp(value, label) {
|
|
46
|
+
const timestamp = requiredString(value, label);
|
|
47
|
+
if (Number.isNaN(Date.parse(timestamp)) ||
|
|
48
|
+
new Date(timestamp).toISOString() !== timestamp) {
|
|
49
|
+
throw new Error(`${label} must be a canonical ISO timestamp`);
|
|
50
|
+
}
|
|
51
|
+
return timestamp;
|
|
52
|
+
}
|
|
53
|
+
function isRecord(value) {
|
|
54
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
55
|
+
}
|
|
56
|
+
function parseIntent(value) {
|
|
57
|
+
if (!isRecord(value)) {
|
|
58
|
+
throw new Error("terminal user-send intent must contain a JSON object");
|
|
59
|
+
}
|
|
60
|
+
for (const key of Object.keys(value)) {
|
|
61
|
+
if (!ALLOWED_KEYS.has(key)) {
|
|
62
|
+
throw new Error(`terminal user-send intent contains unsupported field ${key}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (value.schema !== TERMINAL_USER_SEND_INTENT_SCHEMA ||
|
|
66
|
+
value.version !== TERMINAL_USER_SEND_INTENT_VERSION) {
|
|
67
|
+
throw new Error("terminal user-send intent has an unsupported schema");
|
|
68
|
+
}
|
|
69
|
+
const stage = value.stage;
|
|
70
|
+
if (stage !== "reserved" &&
|
|
71
|
+
stage !== "zero_input_cancelled" &&
|
|
72
|
+
stage !== "enter_dispatched") {
|
|
73
|
+
throw new Error("terminal user-send intent stage is invalid");
|
|
74
|
+
}
|
|
75
|
+
requiredString(value.terminal_runtime_key, "terminal_runtime_key");
|
|
76
|
+
requiredString(value.physical_token, "physical_token");
|
|
77
|
+
requiredString(value.message_id, "message_id");
|
|
78
|
+
requiredString(value.request_hash, "request_hash");
|
|
79
|
+
canonicalTimestamp(value.reserved_at, "reserved_at");
|
|
80
|
+
if (stage === "enter_dispatched") {
|
|
81
|
+
canonicalTimestamp(value.enter_dispatched_at, "enter_dispatched_at");
|
|
82
|
+
if (value.delivery_mode !== "managed" && value.delivery_mode !== "unmanaged") {
|
|
83
|
+
throw new Error("a completed terminal user-send intent needs a delivery mode");
|
|
84
|
+
}
|
|
85
|
+
if (value.zero_input_cancelled_at !== undefined) {
|
|
86
|
+
throw new Error("a completed terminal user-send intent cannot claim zero-input cancellation");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (stage === "zero_input_cancelled") {
|
|
90
|
+
canonicalTimestamp(value.zero_input_cancelled_at, "zero_input_cancelled_at");
|
|
91
|
+
if (value.enter_dispatched_at !== undefined ||
|
|
92
|
+
value.delivery_mode !== undefined) {
|
|
93
|
+
throw new Error("a zero-input terminal user-send intent cannot claim delivery");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (value.zero_input_cancelled_at !== undefined ||
|
|
97
|
+
value.enter_dispatched_at !== undefined ||
|
|
98
|
+
value.delivery_mode !== undefined) {
|
|
99
|
+
throw new Error("a reserved terminal user-send intent cannot claim delivery");
|
|
100
|
+
}
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
function assertBoundaryMatches(intent, input) {
|
|
104
|
+
if (intent.terminal_runtime_key !== input.terminalRuntimeKey ||
|
|
105
|
+
intent.message_id !== input.messageId) {
|
|
106
|
+
throw new TerminalUserSendIntentBoundaryConflictError("terminal user-send intent identity does not match");
|
|
107
|
+
}
|
|
108
|
+
if (intent.physical_token !== input.physicalToken) {
|
|
109
|
+
throw new TerminalUserSendIntentBoundaryConflictError("messageId is already reserved for a different physical terminal");
|
|
110
|
+
}
|
|
111
|
+
if (intent.request_hash !== input.requestHash) {
|
|
112
|
+
throw new TerminalUserSendIntentBoundaryConflictError("messageId is already reserved for a different request hash");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function nowTimestamp(now) {
|
|
116
|
+
const value = now();
|
|
117
|
+
if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
|
|
118
|
+
throw new Error("now() must return a valid Date");
|
|
119
|
+
}
|
|
120
|
+
return value.toISOString();
|
|
121
|
+
}
|
|
122
|
+
function requiredDeliveryMode(value) {
|
|
123
|
+
if (value !== "managed" && value !== "unmanaged") {
|
|
124
|
+
throw new Error("terminal user-send delivery mode is invalid");
|
|
125
|
+
}
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
function syncSleep(milliseconds) {
|
|
129
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
|
|
130
|
+
}
|
|
131
|
+
function finalIntentPathDefinitelyAbsent(filePath) {
|
|
132
|
+
try {
|
|
133
|
+
lstatSync(filePath);
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (isNodeError(error, "ENOENT") || isNodeError(error, "ENOTDIR")) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function classifyIntentStorageError(error, filePath) {
|
|
144
|
+
const definitelyAbsent = finalIntentPathDefinitelyAbsent(filePath);
|
|
145
|
+
if (definitelyAbsent === true)
|
|
146
|
+
return error;
|
|
147
|
+
return new TerminalUserSendIntentUncertainError(`${definitelyAbsent === false ? "existing" : "possibly existing"} ` +
|
|
148
|
+
`same-id terminal user-Send intent cannot be verified: ${error instanceof Error ? error.message : String(error)}`);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Store-independent global idempotency for one explicit physical-terminal
|
|
152
|
+
* Send. The path is keyed only by host message id, so the same id cannot move
|
|
153
|
+
* between explicit, delegated, or differently targeted terminal entry points.
|
|
154
|
+
*
|
|
155
|
+
* The caller owns the physical-terminal lock. A reserved record means the
|
|
156
|
+
* previous managed or unmanaged attempt may have started input; only a
|
|
157
|
+
* completed record is safe to replay as success. The request body is never
|
|
158
|
+
* stored.
|
|
159
|
+
*/
|
|
160
|
+
export function createTerminalUserSendIntentRepository(options) {
|
|
161
|
+
const runtimeDir = path.resolve(options.runtimeDir);
|
|
162
|
+
const intentsDir = path.join(runtimeDir, TERMINAL_USER_SEND_INTENTS_DIRECTORY);
|
|
163
|
+
const now = options.now ?? (() => new Date());
|
|
164
|
+
const ensureDirectory = options.ensureDirectory ?? ensureDir;
|
|
165
|
+
const saveJson = options.saveJson ?? atomicSaveJsonFile;
|
|
166
|
+
const fileLock = createFileLockCliAdapter({
|
|
167
|
+
now: () => new Date(),
|
|
168
|
+
nowMs: Date.now,
|
|
169
|
+
pid: () => process.pid,
|
|
170
|
+
sleepSync: syncSleep
|
|
171
|
+
});
|
|
172
|
+
const acquireLock = options.acquireLock ?? ((lockPath) => fileLock.acquire(lockPath));
|
|
173
|
+
const heldMessages = new Set();
|
|
174
|
+
function pathFor(input) {
|
|
175
|
+
const messageId = requiredString(input.messageId, "messageId");
|
|
176
|
+
return path.join(intentsDir, `terminal-user-send-intent-${digest(messageId)}.json`);
|
|
177
|
+
}
|
|
178
|
+
function withMessageLock(messageId, operation) {
|
|
179
|
+
const messageKey = digest(requiredString(messageId, "messageId"));
|
|
180
|
+
if (heldMessages.has(messageKey)) {
|
|
181
|
+
throw new TerminalUserSendIntentUncertainError("terminal user-Send intent lock is already held");
|
|
182
|
+
}
|
|
183
|
+
const filePath = pathFor({ messageId });
|
|
184
|
+
let release;
|
|
185
|
+
let operationStarted = false;
|
|
186
|
+
try {
|
|
187
|
+
ensureDirectory(path.dirname(filePath));
|
|
188
|
+
release = acquireLock(`${filePath}.lock`);
|
|
189
|
+
heldMessages.add(messageKey);
|
|
190
|
+
operationStarted = true;
|
|
191
|
+
return operation();
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
if (error instanceof TerminalUserSendIntentBoundaryConflictError ||
|
|
195
|
+
error instanceof TerminalUserSendIntentUncertainError) {
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
if (isRecord(error) && error.code === "LOCK_TIMEOUT") {
|
|
199
|
+
throw new TerminalUserSendIntentUncertainError(`terminal user-Send intent lock is busy: ${error instanceof Error ? error.message : String(error)}`);
|
|
200
|
+
}
|
|
201
|
+
if (operationStarted)
|
|
202
|
+
throw error;
|
|
203
|
+
throw classifyIntentStorageError(error, filePath);
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
heldMessages.delete(messageKey);
|
|
207
|
+
try {
|
|
208
|
+
release?.();
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Releasing a completed lock is cleanup, not Send authority. A stale
|
|
212
|
+
// file is reclaimed by the normal owner/age protocol on a later call.
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function load(input) {
|
|
217
|
+
const filePath = pathFor(input);
|
|
218
|
+
try {
|
|
219
|
+
const intent = parseIntent(readJsonFileNoFollow(filePath, "terminal user-send intent"));
|
|
220
|
+
assertBoundaryMatches(intent, input);
|
|
221
|
+
return intent;
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
if (isNodeError(error, "ENOENT"))
|
|
225
|
+
return undefined;
|
|
226
|
+
if (error instanceof TerminalUserSendIntentBoundaryConflictError ||
|
|
227
|
+
error instanceof TerminalUserSendIntentUncertainError) {
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
230
|
+
throw classifyIntentStorageError(error, filePath);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function save(intent) {
|
|
234
|
+
saveJson(pathFor({ messageId: intent.message_id }), intent, {
|
|
235
|
+
rootLabel: "terminal user-send intent root",
|
|
236
|
+
directoryLabel: "terminal user-send intent directory",
|
|
237
|
+
fileLabel: "terminal user-send intent",
|
|
238
|
+
ensureDirectory,
|
|
239
|
+
fsyncNewRootParent: true,
|
|
240
|
+
fsyncNewDirectoryParent: true
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function reserve(input) {
|
|
244
|
+
return withMessageLock(input.messageId, () => {
|
|
245
|
+
const existing = load(input);
|
|
246
|
+
if (existing?.stage === "enter_dispatched") {
|
|
247
|
+
return {
|
|
248
|
+
outcome: "replay",
|
|
249
|
+
stage: existing.stage,
|
|
250
|
+
intent: existing
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
if (existing?.stage === "reserved") {
|
|
254
|
+
return {
|
|
255
|
+
outcome: "uncertain",
|
|
256
|
+
stage: existing.stage,
|
|
257
|
+
intent: existing
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const intent = {
|
|
261
|
+
schema: TERMINAL_USER_SEND_INTENT_SCHEMA,
|
|
262
|
+
version: TERMINAL_USER_SEND_INTENT_VERSION,
|
|
263
|
+
terminal_runtime_key: requiredString(input.terminalRuntimeKey, "terminalRuntimeKey"),
|
|
264
|
+
physical_token: requiredString(input.physicalToken, "physicalToken"),
|
|
265
|
+
message_id: requiredString(input.messageId, "messageId"),
|
|
266
|
+
request_hash: requiredString(input.requestHash, "requestHash"),
|
|
267
|
+
stage: "reserved",
|
|
268
|
+
reserved_at: nowTimestamp(now)
|
|
269
|
+
};
|
|
270
|
+
save(intent);
|
|
271
|
+
return { outcome: "reserved", intent };
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function complete(input, deliveryMode) {
|
|
275
|
+
return withMessageLock(input.messageId, () => {
|
|
276
|
+
const mode = requiredDeliveryMode(deliveryMode);
|
|
277
|
+
const existing = load(input);
|
|
278
|
+
if (!existing) {
|
|
279
|
+
throw new Error("terminal user-send intent must be reserved before completion");
|
|
280
|
+
}
|
|
281
|
+
if (existing.stage === "enter_dispatched") {
|
|
282
|
+
if (existing.delivery_mode !== mode) {
|
|
283
|
+
throw new Error("terminal user-send intent already completed in another mode");
|
|
284
|
+
}
|
|
285
|
+
return existing;
|
|
286
|
+
}
|
|
287
|
+
const completed = {
|
|
288
|
+
...existing,
|
|
289
|
+
stage: "enter_dispatched",
|
|
290
|
+
enter_dispatched_at: nowTimestamp(now),
|
|
291
|
+
delivery_mode: mode
|
|
292
|
+
};
|
|
293
|
+
save(completed);
|
|
294
|
+
return completed;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
function cancelProvenZeroInput(input) {
|
|
298
|
+
return withMessageLock(input.messageId, () => {
|
|
299
|
+
const existing = load(input);
|
|
300
|
+
if (!existing)
|
|
301
|
+
return false;
|
|
302
|
+
if (existing.stage === "zero_input_cancelled")
|
|
303
|
+
return false;
|
|
304
|
+
if (existing.stage === "enter_dispatched") {
|
|
305
|
+
throw new Error("a completed terminal user-send intent cannot be cancelled");
|
|
306
|
+
}
|
|
307
|
+
save({
|
|
308
|
+
...existing,
|
|
309
|
+
stage: "zero_input_cancelled",
|
|
310
|
+
zero_input_cancelled_at: nowTimestamp(now)
|
|
311
|
+
});
|
|
312
|
+
return true;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
return { pathFor, load, reserve, cancelProvenZeroInput, complete };
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=terminal-user-send-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-user-send-intent.js","sourceRoot":"","sources":["../../src/terminal-user-send-intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
import type { CallbackSpawnSync } from "./openclaw-callback-transport.js";
|
|
2
|
-
|
|
2
|
+
import { type CallbackAttemptOutcome, type CallbackRouteV1, type CallbackTransportContextV1, type CallbackTransportDeliverInput } from "./callback-transport.js";
|
|
3
|
+
import { type TerminalWatchCallbackEvent as TerminalWatchCallbackEventType, type TerminalWatchCallbackResolution } from "./terminal-watch-service.js";
|
|
4
|
+
import type { TerminalWatch } from "./terminal-watch-store.js";
|
|
5
|
+
export type TerminalWatchCallbackEvent = TerminalWatchCallbackEventType;
|
|
3
6
|
export interface TerminalWatchCallbackInput {
|
|
4
7
|
watchId: string;
|
|
5
8
|
idempotencyKey: string;
|
|
6
9
|
event: TerminalWatchCallbackEvent;
|
|
7
10
|
agent: "codex" | "claude";
|
|
8
11
|
terminalId: string;
|
|
9
|
-
openclawSession
|
|
12
|
+
openclawSession?: string;
|
|
10
13
|
openclawBin?: string;
|
|
11
14
|
detail?: string;
|
|
12
15
|
completionText?: string;
|
|
13
16
|
}
|
|
17
|
+
export type TerminalWatchTransportDeliveryInput = CallbackTransportDeliverInput;
|
|
14
18
|
export interface TerminalWatchCallbackCliAdapter {
|
|
15
19
|
deliver(input: TerminalWatchCallbackInput): void;
|
|
20
|
+
deliverTransport?(input: TerminalWatchTransportDeliveryInput): CallbackAttemptOutcome;
|
|
16
21
|
}
|
|
22
|
+
export declare function resolveTerminalWatchOpenClawCallback(watch: Pick<TerminalWatch, "openclaw_session" | "openclaw_bin">): TerminalWatchCallbackResolution;
|
|
23
|
+
export declare function resolveTerminalWatchOpenClawCallbackContext(watch: Pick<TerminalWatch, "openclaw_session" | "openclaw_bin">, _route?: CallbackRouteV1): CallbackTransportContextV1;
|
|
17
24
|
export declare function createTerminalWatchCallbackCliAdapter(options?: {
|
|
18
25
|
environment?: () => NodeJS.ProcessEnv;
|
|
26
|
+
now?: () => Date;
|
|
19
27
|
spawnSync?: CallbackSpawnSync;
|
|
20
28
|
}): TerminalWatchCallbackCliAdapter;
|
|
@@ -1,7 +1,32 @@
|
|
|
1
|
+
import { createLegacyOpenClawCallbackRoute } from "./callback-transport.js";
|
|
1
2
|
import { createOpenClawCallbackTransport, parseChatSendAcknowledgement } from "./openclaw-callback-transport.js";
|
|
3
|
+
import { terminalWatchCallbackMessage } from "./terminal-watch-service.js";
|
|
4
|
+
export function resolveTerminalWatchOpenClawCallback(watch) {
|
|
5
|
+
return {
|
|
6
|
+
route: {
|
|
7
|
+
...createLegacyOpenClawCallbackRoute({
|
|
8
|
+
controllerSessionId: watch.openclaw_session,
|
|
9
|
+
gatewayMethod: "chat.send",
|
|
10
|
+
openclawBin: watch.openclaw_bin
|
|
11
|
+
}),
|
|
12
|
+
capabilities: { wake: true, respond: false }
|
|
13
|
+
},
|
|
14
|
+
context: resolveTerminalWatchOpenClawCallbackContext(watch)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function resolveTerminalWatchOpenClawCallbackContext(watch, _route) {
|
|
18
|
+
return {
|
|
19
|
+
legacyOptions: {
|
|
20
|
+
gatewayMethod: "chat.send",
|
|
21
|
+
gatewaySession: watch.openclaw_session,
|
|
22
|
+
openclawBin: watch.openclaw_bin
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
2
26
|
export function createTerminalWatchCallbackCliAdapter(options = {}) {
|
|
27
|
+
const now = options.now ?? (() => new Date());
|
|
3
28
|
const transport = createOpenClawCallbackTransport({
|
|
4
|
-
now
|
|
29
|
+
now,
|
|
5
30
|
environment: options.environment ?? (() => process.env),
|
|
6
31
|
redactConversation: () => ({}),
|
|
7
32
|
recordCallbackProcessDelivery: () => { },
|
|
@@ -9,47 +34,61 @@ export function createTerminalWatchCallbackCliAdapter(options = {}) {
|
|
|
9
34
|
});
|
|
10
35
|
return Object.freeze({
|
|
11
36
|
deliver(input) {
|
|
12
|
-
const
|
|
37
|
+
const attempt = attemptOpenClawCallback({
|
|
13
38
|
openclawBin: input.openclawBin,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
idempotencyKey: input.idempotencyKey,
|
|
18
|
-
deliver: true
|
|
19
|
-
}
|
|
39
|
+
sessionKey: requiredString(input.openclawSession, "Terminal Watch OpenClaw session"),
|
|
40
|
+
message: terminalWatchCallbackMessage(input),
|
|
41
|
+
idempotencyKey: input.idempotencyKey
|
|
20
42
|
});
|
|
21
|
-
if (
|
|
22
|
-
throw new Error(
|
|
23
|
-
`Terminal Watch callback failed with status ${delivery.status}`);
|
|
24
|
-
}
|
|
25
|
-
const acknowledgement = parseChatSendAcknowledgement(delivery.stdout, input.idempotencyKey);
|
|
26
|
-
if (acknowledgement.status === "error" ||
|
|
27
|
-
acknowledgement.status === "timeout") {
|
|
28
|
-
throw new Error(`Terminal Watch chat.send was not accepted: ${acknowledgement.status}`);
|
|
43
|
+
if (attempt.disposition !== "accepted") {
|
|
44
|
+
throw new Error(attempt.errorMessage);
|
|
29
45
|
}
|
|
46
|
+
},
|
|
47
|
+
deliverTransport(input) {
|
|
48
|
+
return transport.deliver(input);
|
|
30
49
|
}
|
|
31
50
|
});
|
|
51
|
+
function attemptOpenClawCallback(input) {
|
|
52
|
+
const delivery = transport.deliverChatSend({
|
|
53
|
+
openclawBin: input.openclawBin,
|
|
54
|
+
params: {
|
|
55
|
+
sessionKey: input.sessionKey,
|
|
56
|
+
message: input.message,
|
|
57
|
+
idempotencyKey: input.idempotencyKey,
|
|
58
|
+
deliver: true
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (delivery.status !== 0) {
|
|
62
|
+
return {
|
|
63
|
+
disposition: "retryable_failure",
|
|
64
|
+
errorMessage: delivery.stderr || delivery.stdout ||
|
|
65
|
+
`Terminal Watch callback failed with status ${delivery.status}`
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
let acknowledgement;
|
|
69
|
+
try {
|
|
70
|
+
acknowledgement = parseChatSendAcknowledgement(delivery.stdout, input.idempotencyKey);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
return {
|
|
74
|
+
disposition: "uncertain",
|
|
75
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (acknowledgement.status === "error" ||
|
|
79
|
+
acknowledgement.status === "timeout") {
|
|
80
|
+
return {
|
|
81
|
+
disposition: "retryable_failure",
|
|
82
|
+
errorMessage: `Terminal Watch chat.send was not accepted: ${acknowledgement.status}`
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return { disposition: "accepted", acknowledgement };
|
|
86
|
+
}
|
|
32
87
|
}
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
: "Tell the user that Terminal Watch stopped without a verified successful completion and explain the exact reason below.";
|
|
39
|
-
return [
|
|
40
|
-
"Continue this OpenClaw conversation from the Agent Knock Knock Terminal Watch event below.",
|
|
41
|
-
"This is an observation of a task started by the human directly in Codex or Claude Code. It is not an AKK Turn and AKK did not send terminal input.",
|
|
42
|
-
eventInstruction,
|
|
43
|
-
"Do not poll files, processes, terminal panes, stdout, or stderr. Use only this structured event.",
|
|
44
|
-
"",
|
|
45
|
-
`[AKK Terminal Watch: ${input.event}]`,
|
|
46
|
-
`Watch: ${input.watchId}`,
|
|
47
|
-
`Terminal: ${input.terminalId}`,
|
|
48
|
-
`Agent: ${input.agent}`,
|
|
49
|
-
...(input.detail ? [`Detail: ${input.detail}`] : []),
|
|
50
|
-
...(input.completionText
|
|
51
|
-
? ["", "Bounded completion text:", input.completionText]
|
|
52
|
-
: [])
|
|
53
|
-
].join("\n");
|
|
88
|
+
function requiredString(value, label) {
|
|
89
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
90
|
+
throw new Error(`${label} is required`);
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
54
93
|
}
|
|
55
94
|
//# sourceMappingURL=terminal-watch-callback-cli-adapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-watch-callback-cli-adapter.js","sourceRoot":"","sources":["../../src/terminal-watch-callback-cli-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"terminal-watch-callback-cli-adapter.js","sourceRoot":"","sources":["../../src/terminal-watch-callback-cli-adapter.ts"],"names":[],"mappings":"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"}
|