openryoko 2026.7.1 → 2026.7.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/dist/package.json +1 -1
- package/dist/src/connectors/slack/__tests__/triage-prompt.test.js +43 -1
- package/dist/src/connectors/slack/__tests__/triage-prompt.test.js.map +1 -1
- package/dist/src/connectors/slack/index.d.ts.map +1 -1
- package/dist/src/connectors/slack/index.js +33 -11
- package/dist/src/connectors/slack/index.js.map +1 -1
- package/dist/src/connectors/slack/triage-prompt.d.ts +16 -0
- package/dist/src/connectors/slack/triage-prompt.d.ts.map +1 -1
- package/dist/src/connectors/slack/triage-prompt.js +42 -4
- package/dist/src/connectors/slack/triage-prompt.js.map +1 -1
- package/dist/src/engines/__tests__/claude-interactive-transcript-recovery.test.d.ts +2 -0
- package/dist/src/engines/__tests__/claude-interactive-transcript-recovery.test.d.ts.map +1 -0
- package/dist/src/engines/__tests__/claude-interactive-transcript-recovery.test.js +84 -0
- package/dist/src/engines/__tests__/claude-interactive-transcript-recovery.test.js.map +1 -0
- package/dist/src/engines/__tests__/claude-interactive.test.js +107 -1
- package/dist/src/engines/__tests__/claude-interactive.test.js.map +1 -1
- package/dist/src/engines/__tests__/pty-lifecycle.test.js +33 -0
- package/dist/src/engines/__tests__/pty-lifecycle.test.js.map +1 -1
- package/dist/src/engines/__tests__/sse-pty-proxy-busy.test.d.ts +2 -0
- package/dist/src/engines/__tests__/sse-pty-proxy-busy.test.d.ts.map +1 -0
- package/dist/src/engines/__tests__/sse-pty-proxy-busy.test.js +67 -0
- package/dist/src/engines/__tests__/sse-pty-proxy-busy.test.js.map +1 -0
- package/dist/src/engines/claude-interactive.d.ts +59 -0
- package/dist/src/engines/claude-interactive.d.ts.map +1 -1
- package/dist/src/engines/claude-interactive.js +335 -17
- package/dist/src/engines/claude-interactive.js.map +1 -1
- package/dist/src/engines/pty-lifecycle.d.ts +9 -0
- package/dist/src/engines/pty-lifecycle.d.ts.map +1 -1
- package/dist/src/engines/pty-lifecycle.js +13 -0
- package/dist/src/engines/pty-lifecycle.js.map +1 -1
- package/dist/src/engines/sse-pty-proxy.d.ts +15 -0
- package/dist/src/engines/sse-pty-proxy.d.ts.map +1 -1
- package/dist/src/engines/sse-pty-proxy.js +34 -0
- package/dist/src/engines/sse-pty-proxy.js.map +1 -1
- package/dist/src/gateway/__tests__/hook-registry.test.js +50 -0
- package/dist/src/gateway/__tests__/hook-registry.test.js.map +1 -1
- package/dist/src/gateway/__tests__/status-reconciler.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/status-reconciler.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/status-reconciler.test.js +100 -0
- package/dist/src/gateway/__tests__/status-reconciler.test.js.map +1 -0
- package/dist/src/gateway/hook-registry.d.ts +12 -0
- package/dist/src/gateway/hook-registry.d.ts.map +1 -1
- package/dist/src/gateway/hook-registry.js +26 -0
- package/dist/src/gateway/hook-registry.js.map +1 -1
- package/dist/src/gateway/server.d.ts.map +1 -1
- package/dist/src/gateway/server.js +20 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/status-reconciler.d.ts +32 -0
- package/dist/src/gateway/status-reconciler.d.ts.map +1 -0
- package/dist/src/gateway/status-reconciler.js +74 -0
- package/dist/src/gateway/status-reconciler.js.map +1 -0
- package/dist/src/sessions/manager.d.ts +15 -0
- package/dist/src/sessions/manager.d.ts.map +1 -1
- package/dist/src/sessions/manager.js +120 -2
- package/dist/src/sessions/manager.js.map +1 -1
- package/dist/src/shared/__tests__/rateLimit.test.js +21 -1
- package/dist/src/shared/__tests__/rateLimit.test.js.map +1 -1
- package/dist/src/shared/rateLimit.d.ts +1 -0
- package/dist/src/shared/rateLimit.d.ts.map +1 -1
- package/dist/src/shared/rateLimit.js +17 -0
- package/dist/src/shared/rateLimit.js.map +1 -1
- package/dist/src/shared/types.d.ts +9 -0
- package/dist/src/shared/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import { describe, it, expect, vi } from "vitest";
|
|
|
5
5
|
// pure-JS class with zero PTY dependency, so mocking the module keeps the test
|
|
6
6
|
// focused and CI-portable.
|
|
7
7
|
vi.mock("node-pty", () => ({ spawn: vi.fn() }));
|
|
8
|
-
import { TurnResolver } from "../claude-interactive.js";
|
|
8
|
+
import { TurnResolver, isNativeClaudeCommand } from "../claude-interactive.js";
|
|
9
9
|
describe("TurnResolver", () => {
|
|
10
10
|
it("resolves only after BOTH SessionStart and Stop", async () => {
|
|
11
11
|
const r = new TurnResolver({ fallbackSessionId: "old" });
|
|
@@ -51,4 +51,110 @@ describe("TurnResolver", () => {
|
|
|
51
51
|
expect(r.stopFailure?.error).toBe("rate_limit");
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
|
+
describe("TurnResolver — StopFailure grace window (upstream port)", () => {
|
|
55
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
56
|
+
it("holds a server_error StopFailure in grace and settles with the error after expiry", async () => {
|
|
57
|
+
const r = new TurnResolver({ fallbackSessionId: "s", stopFailureGraceMs: 20 });
|
|
58
|
+
let resolved;
|
|
59
|
+
r.promise.then((v) => { resolved = v; });
|
|
60
|
+
r.onHook({ hook_event_name: "StopFailure", error: "server_error" });
|
|
61
|
+
await sleep(5);
|
|
62
|
+
expect(resolved).toBeUndefined(); // held in grace, not settled yet
|
|
63
|
+
await sleep(40);
|
|
64
|
+
expect(resolved?.error).toMatch(/server_error/);
|
|
65
|
+
expect(resolved?.numTurns).toBe(1);
|
|
66
|
+
});
|
|
67
|
+
it("a later Stop supersedes the graced failure — the CLI retried and finished", async () => {
|
|
68
|
+
const r = new TurnResolver({ fallbackSessionId: "s", assumeStarted: true, stopFailureGraceMs: 50 });
|
|
69
|
+
r.onHook({ hook_event_name: "StopFailure", error: "server_error" });
|
|
70
|
+
await sleep(5);
|
|
71
|
+
r.onHook({ hook_event_name: "Stop", last_assistant_message: "recovered answer" });
|
|
72
|
+
const v = await r.promise;
|
|
73
|
+
expect(v.error).toBeUndefined();
|
|
74
|
+
expect(v.result).toBe("recovered answer");
|
|
75
|
+
expect(r.stopFailure).toBeUndefined(); // superseded, not exposed
|
|
76
|
+
});
|
|
77
|
+
it("tool-hook activity re-arms the grace window", async () => {
|
|
78
|
+
const r = new TurnResolver({ fallbackSessionId: "s", stopFailureGraceMs: 30 });
|
|
79
|
+
let resolved;
|
|
80
|
+
r.promise.then((v) => { resolved = v; });
|
|
81
|
+
r.onHook({ hook_event_name: "StopFailure", error: "server_error" });
|
|
82
|
+
// Keep feeding activity past the original 30ms window.
|
|
83
|
+
for (let i = 0; i < 4; i++) {
|
|
84
|
+
await sleep(15);
|
|
85
|
+
r.onHook({ hook_event_name: "PostToolUse", tool_name: "Bash" });
|
|
86
|
+
}
|
|
87
|
+
expect(resolved).toBeUndefined(); // still alive well past 30ms
|
|
88
|
+
await sleep(60); // quiet — grace finally expires
|
|
89
|
+
expect(resolved?.error).toMatch(/server_error/);
|
|
90
|
+
});
|
|
91
|
+
it("defers settling while shouldDeferStopFailure reports in-flight work", async () => {
|
|
92
|
+
let busy = true;
|
|
93
|
+
const r = new TurnResolver({ fallbackSessionId: "s", stopFailureGraceMs: 10, shouldDeferStopFailure: () => busy });
|
|
94
|
+
let resolved;
|
|
95
|
+
r.promise.then((v) => { resolved = v; });
|
|
96
|
+
r.onHook({ hook_event_name: "StopFailure", error: "server_error" });
|
|
97
|
+
await sleep(40);
|
|
98
|
+
expect(resolved).toBeUndefined(); // deferred — sub-agent still streaming
|
|
99
|
+
busy = false;
|
|
100
|
+
await sleep(30);
|
|
101
|
+
expect(resolved?.error).toMatch(/server_error/);
|
|
102
|
+
});
|
|
103
|
+
it("rate_limit / authentication_failed still settle immediately", async () => {
|
|
104
|
+
for (const error of ["rate_limit", "authentication_failed", "billing_error", "max_output_tokens"]) {
|
|
105
|
+
const r = new TurnResolver({ fallbackSessionId: "s", stopFailureGraceMs: 10_000 });
|
|
106
|
+
r.onHook({ hook_event_name: "StopFailure", error });
|
|
107
|
+
const v = await r.promise; // resolves without waiting for any grace
|
|
108
|
+
expect(v.error).toContain(error);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
it("PTY death with a pending graced failure reports the API error, not 'process exited'", async () => {
|
|
112
|
+
const r = new TurnResolver({ fallbackSessionId: "s", stopFailureGraceMs: 10_000 });
|
|
113
|
+
r.onHook({ hook_event_name: "StopFailure", error: "server_error" });
|
|
114
|
+
r.interrupt("Interrupted: claude process exited");
|
|
115
|
+
const v = await r.promise;
|
|
116
|
+
expect(v.error).toMatch(/server_error/);
|
|
117
|
+
});
|
|
118
|
+
it("strips leaked thinking blocks from Stop hook assistant text", async () => {
|
|
119
|
+
const r = new TurnResolver({ fallbackSessionId: "warm-sid", assumeStarted: true });
|
|
120
|
+
r.onHook({
|
|
121
|
+
hook_event_name: "Stop",
|
|
122
|
+
last_assistant_message: "<thinking>private reasoning</thinking>\n\nVisible answer.",
|
|
123
|
+
});
|
|
124
|
+
const v = await r.promise;
|
|
125
|
+
expect(v.result).toBe("Visible answer.");
|
|
126
|
+
});
|
|
127
|
+
it("can recover-complete a turn when the Stop hook is missing", async () => {
|
|
128
|
+
const r = new TurnResolver({ fallbackSessionId: "old" });
|
|
129
|
+
r.onHook({ hook_event_name: "SessionStart", session_id: "c1" });
|
|
130
|
+
r.completeRecovered("transcript final", "c1");
|
|
131
|
+
const v = await r.promise;
|
|
132
|
+
expect(v.result).toBe("transcript final");
|
|
133
|
+
expect(v.sessionId).toBe("c1");
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe("native Claude command handling (upstream port)", () => {
|
|
137
|
+
it("classifies native local commands", () => {
|
|
138
|
+
expect(isNativeClaudeCommand("/compact")).toBe(true);
|
|
139
|
+
expect(isNativeClaudeCommand("/usage")).toBe(true);
|
|
140
|
+
expect(isNativeClaudeCommand(" /model opus")).toBe(true);
|
|
141
|
+
expect(isNativeClaudeCommand("/init")).toBe(false); // real-turn command
|
|
142
|
+
expect(isNativeClaudeCommand("hello /compact")).toBe(false);
|
|
143
|
+
expect(isNativeClaudeCommand("")).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
it("a native turn's Stop settles EMPTY — stale last_assistant_message is not persisted", async () => {
|
|
146
|
+
const r = new TurnResolver({ fallbackSessionId: "warm-sid", assumeStarted: true, native: true });
|
|
147
|
+
r.onHook({ hook_event_name: "Stop", last_assistant_message: "PREVIOUS turn's text" });
|
|
148
|
+
const v = await r.promise;
|
|
149
|
+
expect(v.result).toBe("");
|
|
150
|
+
expect(v.error).toBeUndefined();
|
|
151
|
+
});
|
|
152
|
+
it("completeNativeCommand settles empty (context mutators fire no Stop at all)", async () => {
|
|
153
|
+
const r = new TurnResolver({ fallbackSessionId: "warm-sid", assumeStarted: true, native: true });
|
|
154
|
+
r.completeNativeCommand();
|
|
155
|
+
const v = await r.promise;
|
|
156
|
+
expect(v.result).toBe("");
|
|
157
|
+
expect(v.numTurns).toBe(1);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
54
160
|
//# sourceMappingURL=claude-interactive.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-interactive.test.js","sourceRoot":"","sources":["../../../../src/engines/__tests__/claude-interactive.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,+EAA+E;AAC/E,2BAA2B;AAC3B,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-interactive.test.js","sourceRoot":"","sources":["../../../../src/engines/__tests__/claude-interactive.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,39 @@ describe("PtyLifecycleManager", () => {
|
|
|
56
56
|
m.adopt("b", fakeHandle());
|
|
57
57
|
expect(m.isAtCapacity()).toBe(true);
|
|
58
58
|
});
|
|
59
|
+
it("sweep does not release a PTY the isBusy probe reports as working", () => {
|
|
60
|
+
let busy = true;
|
|
61
|
+
const m = new PtyLifecycleManager({ maxLivePtys: 8, isBusy: () => busy });
|
|
62
|
+
const h = fakeHandle();
|
|
63
|
+
m.adopt("busy-1", h);
|
|
64
|
+
// Freshly adopted, no turn/viewer → shouldStayAlive is false, so only the
|
|
65
|
+
// busy probe keeps it alive.
|
|
66
|
+
m.sweep();
|
|
67
|
+
expect(h.killed).toBe(false);
|
|
68
|
+
busy = false;
|
|
69
|
+
m.sweep();
|
|
70
|
+
expect(h.killed).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
it("touch restarts the keep-warm grace window for out-of-turn activity", () => {
|
|
73
|
+
const m = new PtyLifecycleManager({ maxLivePtys: 8 });
|
|
74
|
+
const h = fakeHandle();
|
|
75
|
+
m.adopt("touch-1", h);
|
|
76
|
+
// Without touch, a fresh adopt (no turn, no viewer) is sweep-eligible.
|
|
77
|
+
m.touch("touch-1");
|
|
78
|
+
m.sweep();
|
|
79
|
+
expect(h.killed).toBe(false); // touched → inside the grace window
|
|
80
|
+
});
|
|
81
|
+
it("LRU eviction at capacity skips a busy PTY", () => {
|
|
82
|
+
const busyIds = new Set(["victim-candidate"]);
|
|
83
|
+
const m = new PtyLifecycleManager({ maxLivePtys: 2, isBusy: (id) => busyIds.has(id) });
|
|
84
|
+
const a = fakeHandle(), b = fakeHandle(), c = fakeHandle();
|
|
85
|
+
m.adopt("victim-candidate", a); // busy — must survive
|
|
86
|
+
m.adopt("idle-one", b); // idle — must be evicted instead
|
|
87
|
+
m.adopt("newcomer", c);
|
|
88
|
+
expect(a.killed).toBe(false);
|
|
89
|
+
expect(b.killed).toBe(true);
|
|
90
|
+
expect(m.getWarm("newcomer")).toBe(c);
|
|
91
|
+
});
|
|
59
92
|
it("killAll kills every live PTY", () => {
|
|
60
93
|
const m = new PtyLifecycleManager({ maxLivePtys: 8 });
|
|
61
94
|
const a = fakeHandle(), b = fakeHandle();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-lifecycle.test.js","sourceRoot":"","sources":["../../../../src/engines/__tests__/pty-lifecycle.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pty-lifecycle.test.js","sourceRoot":"","sources":["../../../../src/engines/__tests__/pty-lifecycle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-pty-proxy-busy.test.d.ts","sourceRoot":"","sources":["../../../../src/engines/__tests__/sse-pty-proxy-busy.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
import { SsePtyProxy } from "../sse-pty-proxy.js";
|
|
4
|
+
/** Upstream that holds every response open until release() is called. */
|
|
5
|
+
function startHoldingUpstream() {
|
|
6
|
+
const pending = [];
|
|
7
|
+
const server = http.createServer((req, res) => {
|
|
8
|
+
req.resume();
|
|
9
|
+
pending.push(res);
|
|
10
|
+
});
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
server.listen(0, "127.0.0.1", () => {
|
|
13
|
+
resolve({
|
|
14
|
+
port: server.address().port,
|
|
15
|
+
release: () => {
|
|
16
|
+
for (const res of pending.splice(0)) {
|
|
17
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
18
|
+
res.end("{}");
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
close: () => new Promise((r) => server.close(() => r())),
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function callProxy(port) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const req = http.request({ hostname: "127.0.0.1", port, path: "/v1/messages", method: "POST", agent: false }, (res) => {
|
|
29
|
+
res.resume();
|
|
30
|
+
res.on("end", () => resolve({ status: res.statusCode || 0 }));
|
|
31
|
+
});
|
|
32
|
+
req.on("error", reject);
|
|
33
|
+
req.end('{"messages":[]}');
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
37
|
+
describe("SsePtyProxy.isBusy (background-work liveness for the PTY reaper)", () => {
|
|
38
|
+
const proxies = [];
|
|
39
|
+
const upstreams = [];
|
|
40
|
+
afterEach(async () => {
|
|
41
|
+
while (proxies.length > 0)
|
|
42
|
+
proxies.pop().stop();
|
|
43
|
+
while (upstreams.length > 0)
|
|
44
|
+
await upstreams.pop().close();
|
|
45
|
+
});
|
|
46
|
+
it("is false before any request, true while one is in flight, and false once the window elapses", async () => {
|
|
47
|
+
const up = await startHoldingUpstream();
|
|
48
|
+
upstreams.push(up);
|
|
49
|
+
const proxy = new SsePtyProxy("busy-test", () => { }, {
|
|
50
|
+
requestFn: http.request,
|
|
51
|
+
upstream: { hostname: "127.0.0.1", port: up.port },
|
|
52
|
+
primaryAgent: false,
|
|
53
|
+
});
|
|
54
|
+
proxies.push(proxy);
|
|
55
|
+
const port = await proxy.start();
|
|
56
|
+
expect(proxy.isBusy(60_000)).toBe(false); // nothing has happened yet
|
|
57
|
+
const call = callProxy(port);
|
|
58
|
+
await sleep(50); // request reaches the upstream and is held open
|
|
59
|
+
expect(proxy.isBusy(60_000)).toBe(true); // in flight → busy regardless of window
|
|
60
|
+
up.release();
|
|
61
|
+
await call;
|
|
62
|
+
await sleep(30);
|
|
63
|
+
expect(proxy.isBusy(60_000)).toBe(true); // finished recently → inside window
|
|
64
|
+
expect(proxy.isBusy(1)).toBe(false); // window elapsed → idle
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=sse-pty-proxy-busy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-pty-proxy-busy.test.js","sourceRoot":"","sources":["../../../../src/engines/__tests__/sse-pty-proxy-busy.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAalD,yEAAyE;AACzE,SAAS,oBAAoB;IAC3B,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC5C,GAAG,CAAC,MAAM,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;YACjC,OAAO,CAAC;gBACN,IAAI,EAAG,MAAM,CAAC,OAAO,EAAkB,CAAC,IAAI;gBAC5C,OAAO,EAAE,GAAG,EAAE;oBACZ,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;wBACpC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;wBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC;gBACD,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACzD,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EACnF,CAAC,GAAG,EAAE,EAAE;YACN,GAAG,CAAC,MAAM,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpE,QAAQ,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAChF,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,EAAG,CAAC,IAAI,EAAE,CAAC;QACjD,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,SAAS,CAAC,GAAG,EAAG,CAAC,KAAK,EAAE,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6FAA6F,EAAE,KAAK,IAAI,EAAE;QAC3G,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;QACxC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE;YACnD,SAAS,EAAE,IAAI,CAAC,OAAO;YACvB,QAAQ,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;YAClD,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QAEjC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,2BAA2B;QAErE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,gDAAgD;QACjE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,wCAAwC;QAEjF,EAAE,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,CAAC;QACX,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,oCAAoC;QAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,wBAAwB;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -4,6 +4,21 @@ import type { PtyControlEvent, PtyViewEngine, PtyIdleSpawnOpts } from "./pty-vie
|
|
|
4
4
|
import type { HookRegistry, HookPayload } from "../gateway/hook-registry.js";
|
|
5
5
|
import { type SseDataEvent } from "./sse-pty-proxy.js";
|
|
6
6
|
export type { PtyControlEvent } from "./pty-view-engine.js";
|
|
7
|
+
/** Claude Code stores per-project transcripts at
|
|
8
|
+
* ~/.claude/projects/<cwd-slug>/<claudeSessionId>.jsonl, where the slug is the
|
|
9
|
+
* cwd with every "/" and "." replaced by "-". Derive that path; fall back to a
|
|
10
|
+
* scan across project dirs if the slug heuristic misses (defensive). Exported
|
|
11
|
+
* for the transcript-recovery unit test. (Ported from upstream jinn.) */
|
|
12
|
+
export declare function findTranscriptForSession(claudeSessionId: string, homeDir?: string, projectsDir?: string): string | undefined;
|
|
13
|
+
/** Last assistant text block from a Claude transcript — the turn's final
|
|
14
|
+
* message. Used to recover result text when the Stop hook (which normally
|
|
15
|
+
* carries last_assistant_message) was lost (gateway restart deleting
|
|
16
|
+
* gateway.json mid-turn, PTY crash, or relay drop), so the reply shows real
|
|
17
|
+
* output instead of "(no output)". Exported for tests. */
|
|
18
|
+
export declare function lastAssistantTextFromTranscript(transcriptPath: string, afterMs?: number): string | undefined;
|
|
19
|
+
/** Strip model reasoning blocks that occasionally leak into
|
|
20
|
+
* last_assistant_message / transcript text — they are never user-facing. */
|
|
21
|
+
export declare function stripReasoningBlocks(text: string): string;
|
|
7
22
|
/**
|
|
8
23
|
* Translate one parsed Anthropic SSE `data:` event into StreamDeltas. This is the
|
|
9
24
|
* live streaming source (replacing the old transcript tailer): word-by-word text
|
|
@@ -23,6 +38,15 @@ export interface TurnResolverOpts {
|
|
|
23
38
|
* SessionStart (it already fired once at process start) and pre-fills the
|
|
24
39
|
* Claude session id from fallbackSessionId. */
|
|
25
40
|
assumeStarted?: boolean;
|
|
41
|
+
/** Test override for the StopFailure grace window (default 20s). */
|
|
42
|
+
stopFailureGraceMs?: number;
|
|
43
|
+
/** While true, a graced StopFailure keeps waiting instead of settling. */
|
|
44
|
+
shouldDeferStopFailure?: () => boolean;
|
|
45
|
+
/** This turn is a Claude-native local command (see isNativeClaudeCommand). Such
|
|
46
|
+
* commands produce no new assistant message, so a Stop hook's
|
|
47
|
+
* last_assistant_message is the PREVIOUS turn's stale text — maybeComplete must
|
|
48
|
+
* settle empty rather than re-persist it as a duplicate. */
|
|
49
|
+
native?: boolean;
|
|
26
50
|
}
|
|
27
51
|
/** State machine for one interactive turn: resolves after BOTH SessionStart + Stop, or on StopFailure/interrupt. */
|
|
28
52
|
export declare class TurnResolver {
|
|
@@ -34,18 +58,31 @@ export declare class TurnResolver {
|
|
|
34
58
|
private gotSessionStart;
|
|
35
59
|
private stopPayload;
|
|
36
60
|
private stopFailurePayload;
|
|
61
|
+
private graceTimer;
|
|
37
62
|
constructor(opts: TurnResolverOpts);
|
|
38
63
|
onHook(h: HookPayload): void;
|
|
39
64
|
/** Claude session id learned so far (for engineSessionId persistence on warm-PTY turns). */
|
|
40
65
|
get sessionId(): string | undefined;
|
|
66
|
+
get isSettled(): boolean;
|
|
41
67
|
/** The StopFailure payload, if the turn ended in an API error (Task 5.3 maps it to rateLimit). */
|
|
42
68
|
get stopFailure(): HookPayload | undefined;
|
|
43
69
|
/** transcript_path from whichever hook carried it. */
|
|
44
70
|
get transcriptPath(): string | undefined;
|
|
45
71
|
private maybeComplete;
|
|
46
72
|
interrupt(reason: string): void;
|
|
73
|
+
/** Settle a native local command (no Stop hook fires for context mutators). */
|
|
74
|
+
completeNativeCommand(): void;
|
|
75
|
+
/** Settle with text recovered from the transcript (the Stop hook was lost). */
|
|
76
|
+
completeRecovered(text: string, sessionId?: string): void;
|
|
77
|
+
/** Proof of life (SSE delta / tool hook) while a StopFailure is pending —
|
|
78
|
+
* re-arms the grace window. No-op when no failure is pending. */
|
|
79
|
+
noteActivity(): void;
|
|
80
|
+
private armGrace;
|
|
81
|
+
private clearGrace;
|
|
82
|
+
private settleWithFailure;
|
|
47
83
|
private settle;
|
|
48
84
|
}
|
|
85
|
+
export declare function isNativeClaudeCommand(prompt: string): boolean;
|
|
49
86
|
export declare class InteractiveClaudeEngine implements InterruptibleEngine, PtyViewEngine {
|
|
50
87
|
private lifecycle;
|
|
51
88
|
private hookRegistry;
|
|
@@ -69,6 +106,9 @@ export declare class InteractiveClaudeEngine implements InterruptibleEngine, Pty
|
|
|
69
106
|
* `onStream` is the current turn's delta callback; the per-PTY SSE proxy routes
|
|
70
107
|
* parsed events here (a PTY outlives its turn, so the proxy looks this up live). */
|
|
71
108
|
private active;
|
|
109
|
+
/** Epoch ms of the most recent PTY output per session — the quiet-window
|
|
110
|
+
* signal for native-command settle and lost-Stop recovery. */
|
|
111
|
+
private lastOutputAt;
|
|
72
112
|
/** Sessions with an in-flight async idle-spawn (proxy.start awaited) — prevents
|
|
73
113
|
* a second ensureIdleSpawn from racing in a duplicate PTY during that gap. */
|
|
74
114
|
private idleSpawning;
|
|
@@ -164,6 +204,25 @@ export declare class InteractiveClaudeEngine implements InterruptibleEngine, Pty
|
|
|
164
204
|
killAll(): void;
|
|
165
205
|
/** True only while a turn is in flight (distinct from "PTY is warm"). */
|
|
166
206
|
isTurnRunning(sessionId: string): boolean;
|
|
207
|
+
/** Grace bridging local tool executions between API calls: the PTY counts as
|
|
208
|
+
* busy this long after the last upstream activity even with nothing in flight. */
|
|
209
|
+
private static readonly BUSY_ACTIVITY_WINDOW_MS;
|
|
210
|
+
/** True while the warm PTY's claude is demonstrably working OUTSIDE a managed
|
|
211
|
+
* turn (autonomous background continuation): an API request is streaming
|
|
212
|
+
* through its SSE proxy, or did so within the activity window. Wired into
|
|
213
|
+
* PtyLifecycleManager.isBusy so the keep-warm reaper / LRU eviction never
|
|
214
|
+
* kills a PTY mid-work. */
|
|
215
|
+
isEngineBusy(sessionId: string): boolean;
|
|
216
|
+
/** True while an upstream API request is streaming through the session's SSE
|
|
217
|
+
* proxy RIGHT NOW (no recency window — strictly in-flight). Used to defer a
|
|
218
|
+
* graced StopFailure (a sub-agent error while the main agent still works)
|
|
219
|
+
* and to hold lost-Stop recovery while the model is mid-request. */
|
|
220
|
+
private hasInflightUpstream;
|
|
221
|
+
/** Out-of-turn engine activity observed via an orphan hook (a background
|
|
222
|
+
* continuation firing PreToolUse/PostToolUse/Stop after its turn settled).
|
|
223
|
+
* Restarts the PTY keep-warm grace window so active background work — which
|
|
224
|
+
* the lifecycle can't see as a turn — isn't reaped mid-flight. */
|
|
225
|
+
noteBackgroundActivity(sessionId: string): void;
|
|
167
226
|
/** True iff a warm PTY exists for this session (in the lifecycle manager). */
|
|
168
227
|
hasWarmPty(sessionId: string): boolean;
|
|
169
228
|
/** Track viewing state from the frontend. Called by pty-ws on `viewing` messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-interactive.d.ts","sourceRoot":"","sources":["../../../src/engines/claude-interactive.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude-interactive.d.ts","sourceRoot":"","sources":["../../../src/engines/claude-interactive.ts"],"names":[],"mappings":"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"}
|