@myagentroam/node 0.9.62 → 0.9.65
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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/dist/capabilities.js +110 -2
- package/dist/claude-agent-sdk.js +330 -2
- package/dist/claude-channel.js +44 -2
- package/dist/codex-app-server.js +510 -2
- package/dist/config.js +106 -2
- package/dist/connector/node-connector-options.js +1 -2
- package/dist/connector/node-operation-router.js +22 -2
- package/dist/connector.js +1736 -2
- package/dist/control-outbound-scheduler.js +153 -2
- package/dist/database.js +639 -2
- package/dist/fake-runner.js +129 -2
- package/dist/git-askpass.js +12 -0
- package/dist/git-execution-helper.js +266 -0
- package/dist/health.js +3 -2
- package/dist/main.js +57 -2
- package/dist/mcp-installation-model.js +1 -2
- package/dist/migrations/v004.js +55 -3
- package/dist/migrations/v005.js +13 -3
- package/dist/migrations/v006.js +90 -3
- package/dist/migrations/v007.js +22 -3
- package/dist/migrations/v008.js +18 -3
- package/dist/migrations/v009.js +70 -4
- package/dist/migrations/v010.js +43 -3
- package/dist/migrations/v011.js +20 -3
- package/dist/migrations/v012.js +8 -0
- package/dist/native-jsonl-reader.js +186 -2
- package/dist/native-session-history.js +1143 -2
- package/dist/opencode-runtime.js +80 -2
- package/dist/opencode-server.js +259 -2
- package/dist/operational.js +122 -2
- package/dist/process-tree.js +18 -2
- package/dist/ripgrep-binary.js +31 -2
- package/dist/rotating-log.js +67 -2
- package/dist/runner/abstract-runner.js +260 -2
- package/dist/runner/claude/managed-run-controller.js +355 -2
- package/dist/runner/claude/tool-normalizer.js +120 -2
- package/dist/runner/claude-code-runner.js +303 -2
- package/dist/runner/codex/composer-image-markers.js +8 -2
- package/dist/runner/codex/conversation-parser.js +913 -2
- package/dist/runner/codex/managed-run-controller.js +494 -2
- package/dist/runner/codex/tool-normalizer.js +214 -2
- package/dist/runner/codex-runner.js +585 -2
- package/dist/runner/fake-test-runner.js +47 -2
- package/dist/runner/mar-agent/conversation-normalizer.js +644 -2
- package/dist/runner/mar-agent/executor-stdio-client-transport.js +139 -2
- package/dist/runner/mar-agent/generated-images.js +41 -2
- package/dist/runner/mar-agent/history-projection.js +106 -2
- package/dist/runner/mar-agent/hosted-conversation-runtime.js +446 -2
- package/dist/runner/mar-agent/managed-run-controller.js +785 -2
- package/dist/runner/mar-agent/mcp-client-pool.js +233 -2
- package/dist/runner/mar-agent/runtime-model-factory.js +326 -2
- package/dist/runner/mar-agent-runner.js +458 -2
- package/dist/runner/opencode/conversation-parser.js +221 -2
- package/dist/runner/opencode/managed-run-controller.js +588 -2
- package/dist/runner/opencode/tool-normalizer.js +80 -2
- package/dist/runner/opencode-runner.js +426 -2
- package/dist/runner/runner-registry.js +87 -2
- package/dist/runner-command-engine.js +71 -2
- package/dist/runner-profiles.js +323 -2
- package/dist/runner-usage.js +190 -2
- package/dist/runtime-command-detector.js +73 -2
- package/dist/runtime-model.js +1 -2
- package/dist/runtime-state.js +1509 -2
- package/dist/service/attachment-domain-state.js +7 -2
- package/dist/service/bubblewrap-sandbox-executor.js +543 -2
- package/dist/service/continuous-run-coordinator.js +425 -2
- package/dist/service/conversation-history-service.js +552 -2
- package/dist/service/conversation-hosting-capability-service.js +61 -2
- package/dist/service/conversation-hosting-enablement-service.js +91 -2
- package/dist/service/conversation-hosting-maintenance-service.js +174 -2
- package/dist/service/conversation-segment-service.js +162 -2
- package/dist/service/conversation-template-node-service.js +992 -2
- package/dist/service/external-session-resume-service.js +152 -2
- package/dist/service/fake-managed-run-service.js +60 -2
- package/dist/service/git-execution-service.js +418 -0
- package/dist/service/git-operation-service.js +57 -0
- package/dist/service/hosted-conversation-node-service.js +1982 -2
- package/dist/service/hosted-conversation-store.js +1405 -2
- package/dist/service/managed-runner-session-service.js +35 -2
- package/dist/service/mar-agent-model-transport-test-service.js +88 -2
- package/dist/service/mcp-installation-verifier.js +87 -2
- package/dist/service/mcp-node-operation-service.js +90 -2
- package/dist/service/mission-mcp-server.js +124 -2
- package/dist/service/mission-mcp-stdio.js +40 -2
- package/dist/service/mission-runtime.js +142 -2
- package/dist/service/native-session-projection-service.js +274 -2
- package/dist/service/native-session-watch-service.js +683 -2
- package/dist/service/node-connection-lifecycle-service.js +88 -2
- package/dist/service/node-control-channel.js +85 -2
- package/dist/service/node-control-message-service.js +109 -2
- package/dist/service/node-request-service.js +62 -2
- package/dist/service/node-run-event-bridge.js +88 -2
- package/dist/service/node-terminal-channel.js +202 -2
- package/dist/service/node-upgrade-coordinator.js +137 -2
- package/dist/service/node-workspace-coordinator.js +97 -2
- package/dist/service/recent-run-projection-service.js +99 -2
- package/dist/service/run-attachment-service.js +321 -2
- package/dist/service/run-domain-state.js +4 -2
- package/dist/service/run-event-service.js +246 -2
- package/dist/service/run-ownership-policy.js +22 -2
- package/dist/service/run-workbench-service.js +120 -2
- package/dist/service/runner-channel-message-service.js +20 -2
- package/dist/service/runner-interaction-service.js +243 -2
- package/dist/service/runner-service.js +69 -2
- package/dist/service/runtime-credential-control-service.js +95 -2
- package/dist/service/session-catalog-service.js +404 -2
- package/dist/service/session-command-service.js +125 -2
- package/dist/service/session-context-service.js +128 -2
- package/dist/service/session-domain-state.js +9 -2
- package/dist/service/session-identity-service.js +86 -2
- package/dist/service/session-lifecycle-service.js +248 -2
- package/dist/service/session-message-service.js +270 -2
- package/dist/service/session-presentation-service.js +43 -2
- package/dist/service/session-query-service.js +82 -2
- package/dist/service/session-watch-slot-coordinator.js +21 -2
- package/dist/service/skill-directory-service.js +238 -2
- package/dist/service/skill-install-service.js +434 -2
- package/dist/service/skill-node-operation-service.js +206 -2
- package/dist/service/terminal-relay-state.js +3 -2
- package/dist/service/terminal-service.js +90 -2
- package/dist/service/web-search-error.js +40 -2
- package/dist/service/workbench-event-service.js +21 -2
- package/dist/service/workbench-manifest-service.js +69 -2
- package/dist/service/workspace-change-service.js +290 -2
- package/dist/service/workspace-content-search-service.js +457 -2
- package/dist/service/workspace-domain-state.js +41 -2
- package/dist/service/workspace-file-service.js +150 -2
- package/dist/service/workspace-git-exclude-service.js +119 -2
- package/dist/service/workspace-queue-workbench-service.js +176 -2
- package/dist/service/workspace-service.js +92 -2
- package/dist/service/workspace-session-service.js +154 -2
- package/dist/service/workspace-upload-service.js +262 -2
- package/dist/service/workspace-watch-controller.js +68 -2
- package/dist/service/workspace-watch-service.js +170 -2
- package/dist/service/workspace-watch-snapshot-service.js +218 -2
- package/dist/service/workspace-workbench-service.js +239 -2
- package/dist/service.js +91 -2
- package/dist/storage.js +32 -2
- package/dist/supervisor.js +136 -2
- package/dist/terminal.js +496 -2
- package/dist/util/git-credential-client.js +32 -0
- package/dist/util/node-operation-data.js +9 -2
- package/dist/util/node-operation-parsers.js +382 -2
- package/dist/util/personal-instructions.js +34 -2
- package/dist/util/runner-error.js +70 -2
- package/dist/util/runner-native-session-parsers.js +510 -2
- package/dist/util/safe-error.js +8 -2
- package/dist/util/secret-environment.js +25 -2
- package/dist/workspace.js +1793 -2
- package/package.json +11 -8
- package/vendor/ripgrep/darwin-arm64/rg +0 -0
- package/vendor/ripgrep/darwin-x64/rg +0 -0
- package/vendor/ripgrep/manifest.json +12 -0
- package/README.md +0 -42
- package/dist/event-buffer.js +0 -2
- package/dist/migrations/v001.js +0 -107
- package/dist/migrations/v002.js +0 -2
- package/dist/migrations/v003.js +0 -2
- package/dist/service/mcp-package-installer.js +0 -2
|
@@ -1,2 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
import { createEnvelope, runtimeCredentialResolveRequestSchema, runtimeCredentialResolveResponseSchema } from '@myagentroam/protocol';
|
|
2
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
3
|
+
/** Correlates the closed runtime-credential exchange on the authenticated control connection. */
|
|
4
|
+
export class RuntimeCredentialControlService {
|
|
5
|
+
options;
|
|
6
|
+
#pending = new Map();
|
|
7
|
+
#timeoutMs;
|
|
8
|
+
#generation = 0;
|
|
9
|
+
#connected = false;
|
|
10
|
+
#closed = false;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
14
|
+
}
|
|
15
|
+
connected() {
|
|
16
|
+
this.#rejectPending('MAR_AGENT_RUNTIME_CREDENTIAL_CONNECTION_INVALID');
|
|
17
|
+
this.#generation++;
|
|
18
|
+
this.#connected = true;
|
|
19
|
+
}
|
|
20
|
+
disconnected() {
|
|
21
|
+
this.#connected = false;
|
|
22
|
+
this.#generation++;
|
|
23
|
+
this.#rejectPending('MAR_AGENT_RUNTIME_CREDENTIAL_CONNECTION_INVALID');
|
|
24
|
+
}
|
|
25
|
+
handle(envelope) {
|
|
26
|
+
if (envelope.type !== 'credential.response')
|
|
27
|
+
return false;
|
|
28
|
+
if (envelope.replyTo === undefined)
|
|
29
|
+
return true;
|
|
30
|
+
const pending = this.#pending.get(envelope.replyTo);
|
|
31
|
+
if (pending === undefined || pending.generation !== this.#generation)
|
|
32
|
+
return true;
|
|
33
|
+
const parsed = runtimeCredentialResolveResponseSchema.safeParse(envelope.payload);
|
|
34
|
+
if (!parsed.success) {
|
|
35
|
+
pending.reject(new Error('MAR_AGENT_RUNTIME_CREDENTIAL_RESPONSE_INVALID'));
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
pending.resolve(parsed.data);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
resolve(request, signal) {
|
|
42
|
+
if (this.#closed)
|
|
43
|
+
return Promise.reject(new Error('MAR_AGENT_RUNTIME_CREDENTIAL_CONTROL_CLOSED'));
|
|
44
|
+
if (!this.#connected)
|
|
45
|
+
return Promise.reject(new Error('MAR_AGENT_RUNTIME_CREDENTIAL_CONNECTION_INVALID'));
|
|
46
|
+
const parsed = runtimeCredentialResolveRequestSchema.parse(request);
|
|
47
|
+
const envelope = createEnvelope('credential.resolve', parsed);
|
|
48
|
+
const generation = this.#generation;
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const settle = (action, value) => {
|
|
51
|
+
const pending = this.#pending.get(envelope.id);
|
|
52
|
+
if (pending === undefined)
|
|
53
|
+
return;
|
|
54
|
+
this.#pending.delete(envelope.id);
|
|
55
|
+
clearTimeout(pending.timer);
|
|
56
|
+
pending.cleanup();
|
|
57
|
+
action(value);
|
|
58
|
+
};
|
|
59
|
+
const abort = () => settle((error) => reject(error), new Error('MAR_AGENT_RUNTIME_CREDENTIAL_PROVIDER_CLOSED'));
|
|
60
|
+
const timer = setTimeout(() => settle((error) => reject(error), new Error('MAR_AGENT_RUNTIME_CREDENTIAL_REQUEST_TIMEOUT')), this.#timeoutMs);
|
|
61
|
+
timer.unref();
|
|
62
|
+
this.#pending.set(envelope.id, {
|
|
63
|
+
generation,
|
|
64
|
+
resolve: (response) => settle((value) => resolve(value), response),
|
|
65
|
+
reject: (error) => settle((value) => reject(value), error),
|
|
66
|
+
timer,
|
|
67
|
+
cleanup: () => signal?.removeEventListener('abort', abort)
|
|
68
|
+
});
|
|
69
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
70
|
+
if (signal?.aborted)
|
|
71
|
+
abort();
|
|
72
|
+
else
|
|
73
|
+
try {
|
|
74
|
+
this.options.send(envelope);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
settle((cause) => reject(cause), error instanceof Error
|
|
78
|
+
? error
|
|
79
|
+
: new Error('MAR_AGENT_RUNTIME_CREDENTIAL_REQUEST_SEND_FAILED'));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
close() {
|
|
84
|
+
if (this.#closed)
|
|
85
|
+
return;
|
|
86
|
+
this.#closed = true;
|
|
87
|
+
this.#connected = false;
|
|
88
|
+
this.#generation++;
|
|
89
|
+
this.#rejectPending('MAR_AGENT_RUNTIME_CREDENTIAL_CONTROL_CLOSED');
|
|
90
|
+
}
|
|
91
|
+
#rejectPending(code) {
|
|
92
|
+
for (const pending of [...this.#pending.values()])
|
|
93
|
+
pending.reject(new Error(code));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,2 +1,404 @@
|
|
|
1
|
-
|
|
2
|
-
function _0x1973(){const _0x43e6dd=['CMvTzw1Izxi','oeHcqKzbBG','uKvtvu1bqKXf','BgLZDa','u0vtu0LptL9srvDjtKrFvefsr0vux0LovKfmsuq','BMv4Den1CNnVCG','Cg9ZAxrPB24','u0vtu0LptL9st0XmqKfds19jtLzbteLe','u0vtu0LptL9srvDjtKrFveLutevFvu5bvKfjtefcteu','nZiWndjKqvzvseW','zw1PDfnLC3nPB24','tufsx01btKfhruq','CMvTB3zL','BM9YBwfSAxPL','vw50AxrSzwqGC2vZC2LVBG','CMvZB2X2zq','Aw52ywXPzgf0zvDVCMTZCgfJzvnLC3nPB25Z','C2v0','mJmXnJu5mu95A0rSzq','CNvUBMvYvgL0Bgu','CNvUDgLTzq','C3rHDhvZ','Aw5JBhvKzxm','Aw5Hy3rPDMveyxLZ','mJuZCMXfs1fU','CMvTB3zLuMvZB2X2zwq','zgvSzxrLza','C2XPy2u','BNvTyMvY','uLvotKvs','B2jQzwn0','ywz0zxi','Aw52ywXPzgf0zuHPC3rVCNK','DxnLCL9TzxnZywDL','CMvZzxrbz2vUDfnLC3nPB25iAxn0B3j5','nJa1ntbpsM9fwhm','u0vtu0LptL9rvuvvrv9ot1rFru1qvfK','A2LUza','zMLUza','BgLZDefNzw50u2vZC2LVBNm','B3bLCMf0Aw9UCW','DhvYBNm','q09nueXfveve','mZi5mdy2nxnAven1vG','zgvSAxzLCNK','AxnbCNjHEq','v09ss1nqqunfx1nfu1njt05Fq0Xfqu5vuf9jtLzbteLe','CgLUt3jKzxi','quzurvi','CMvZDw1L','C3rYAw5N','y2fJAgvKtMf0AxzL','BwvZC2fNzq','DhvYBKLK','BgLZDfnLC3nPB25szwnVCMrZ','z2v0qwDLBNrtzxnZAw9U','DgL0BgvtB3vYy2u','zM9Yz2v0','z2v0v29YA3nWywnL','AxnxyxrJAgLUzW','q1vtve9n','CM9SBgjHy2ToyxrPDMu','CgLUBMvKqxq','tKzlqW','u0vtu0LptL9bq1rjvKu','v09ss1nqqunfx05pvf9gt1vora','C2TPChbLza','mZLQt0z6Ew0','CNvUBMvY','CMvMCMvZAefJDgL2Axr5','y2fJAgvKv29YA3nWywnL','y29Kzq','q0foq0vmteve','CMvTzw1Izxjnyw5Hz2vKtMf0AxzL','u0vtu0LptL9srvDjtKrFvu5bvKfjtefcteu','u0vtu0LptL9st0XmqKfds19vtKfwquLmqujmrq','BM9KzuLK','BwfW','ntC2odHIvgfMwxO','BgLZDfj1BNngB3jtzxnZAw9U','zgvSzxrLu2vZC2LVBLjLy29Yza','u0vtu0LptL9xqvrdseLorW','CMvTB3zLtMf0AxzL','CMvWBgfJzq','Bwv0ywrHDge','te9tva','DgHLBG','u0vtu0LptL9srvnvtuvFuKvkrunuruq','AxngAw5PDgu','ywnJzxnZ','CM9SBgjHy2S','CNvUBMvYCW','u0vtu0LptL9srvDjtKrFsu5wquXjra','BMf0AxzLq29UDhjVBa','qvvutW','CMv3Aw5KuxvLDwu','AgfZ','BgvUz3rO','u0vtu0LptL9ot1rFrK9vtKq','yM91BMrHCNK','zM9YA05HDgL2zq','BwvYz2vqzxjZAxn0zwq','D29YA3nWywnLlNnLC3nPB24Uy2XLyw51Cc5MywLSzwq','tKfusvzfx1rsqu5tq1jjufrFvu5bvKfjtefcteu','yMvNAw5tzxnZAw9UsgLZDg9YEu11Dgf0Aw9U','Dg9mB2nHBgvmB3DLCKnHC2u','rvHurvjoquXFqunusvzf','zMXHDe1HCa','zMLUzfr1CM4','BwfYlwfNzw50','rKfjteve','rvHurvjoquW','yMvMB3jL','zMLSDgvY','D29YA3nWywnLswq','y2XLyw51CenHBMrPzgf0zq','zgLZy292zxjxB3jRC3bHy2u','AxrLBuLKCW','qKvgt1jf','ogjuqu5Quq','Bw9KzwW','zMfPBhvYzq','BMf0AxzLswrZ','Cgf0Aa','y3DK','zxH0zxjUywXby3rPDML0Eq','u0vtu0LptL9jtLzbteLe','icHdB3b5ia','nta2odGZnMjgveDlqq','B3b0Aw9UCW','C2vZC2LVBLf1zxvL','AxrLBxm','zwzMB3j0','zw5XDwv1zu11Dgf0Aw9U','C29Tzq','CxvLCNK','zgf0ywjHC2u','ChjVAMvJDgLVBKzVCK5HDgL2zq','zxH0zxjUywXeAxnJB3zLCMvK','ChjLC2vUDa','AgLZDg9YEq','y2XLyw51CfDVCMTZCgfJzvnLC3nPB25Z','y3jLyxrLqwDLBNrtzxnZAw9U','y3vZDg9TvgL0Bgu','v09ss1nqqunfx1nfu1njt05Fq0Xfqu5vuf9eruXfvevFrKfjteve','DMfSDwvZ','BM93','u1vdq0vfreve','C2vZC2LVBKLK','BgfZDefJDgL2Axr5qxq','tufyx1nbrKvFsu5uruDfuG','CMv3Aw5K','AxnjBNrLz2vY','C2v0uNvUBMvYvgL0BgvgCM9TtMf0AxzL','CMvXDwLYzq','DhjPBq','ChjVAMvJDgLVBG','su5urvjsvvburuq','u0vtu0LptL9st0XmqKfds19uqvjhrvrFsu5wquXjra','mtjruuXgs3m','uKvkrunuruq','zxH0zxjUywXtzxnZAw9Uswq','nte3nJG1wwrpqMjM'];_0x1973=function(){return _0x43e6dd;};return _0x1973();}const _0x419e16=_0x3127;(function(_0x362f7d,_0x1b8c50){const _0x217922=_0x3127,_0x436324=_0x362f7d();while(!![]){try{const _0x5330c0=-parseInt(_0x217922(0x1e6))/(-0x19ac+-0xc9a+-0x2647*-0x1)*(-parseInt(_0x217922(0x1de))/(-0xc0b+-0x926+0x3*0x711))+-parseInt(_0x217922(0x220))/(0x5e5+-0x20b*0xb+-0x1*-0x1097)*(parseInt(_0x217922(0x22b))/(0xcbf*0x1+-0x1a49+0xd8e))+parseInt(_0x217922(0x1dc))/(0x1*0x55e+-0x155b+-0x1002*-0x1)*(-parseInt(_0x217922(0x1d9))/(0x1211+-0x3b9*-0x7+0x2c1a*-0x1))+-parseInt(_0x217922(0x208))/(0xa9*-0xf+0x20cd+-0x16df)+parseInt(_0x217922(0x1b1))/(0x1*-0xb8d+-0x51+0x5f3*0x2)*(parseInt(_0x217922(0x1ef))/(-0x1c6*-0x13+0x16cb+-0x3874))+-parseInt(_0x217922(0x200))/(-0x3f*0x59+0x7a+0x1577)*(-parseInt(_0x217922(0x1f5))/(0x211b+0x2677+-0x4787))+parseInt(_0x217922(0x1ba))/(-0x2fb*-0xd+-0x336*0x3+-0x7*0x427);if(_0x5330c0===_0x1b8c50)break;else _0x436324['push'](_0x436324['shift']());}catch(_0x1e3802){_0x436324['push'](_0x436324['shift']());}}}(_0x1973,0xca99+-0x398f8+0x681f3));import{removeNativeSession}from'../native-session-history.js';import{nodeLog}from'../operational.js';import{isTerminalRunStatus,sessionPage}from'../util/node-operation-parsers.js';import{latestSessionActivityAt}from'./session-presentation-service.js';export class SessionCatalogService{[_0x419e16(0x1bb)];[_0x419e16(0x199)]=Promise[_0x419e16(0x1ec)]();constructor(_0x23ea64){const _0x482c5c=_0x419e16;this[_0x482c5c(0x1bb)]=_0x23ea64;}[_0x419e16(0x205)](){const _0x510aec=_0x419e16;return{'session.list':_0x402094=>this[_0x510aec(0x1e0)](record(_0x402094)),'session.resume':_0x540375=>this[_0x510aec(0x20e)](record(_0x540375)),'session.remove':_0x526ae7=>this[_0x510aec(0x1bf)](()=>this[_0x510aec(0x1e9)](record(_0x526ae7))),'workspace.sessions.cleanup':_0x5b0213=>this[_0x510aec(0x1bf)](()=>this[_0x510aec(0x1c7)](record(_0x5b0213))),'session.rewind':_0x72d670=>this[_0x510aec(0x1bf)](()=>this[_0x510aec(0x1d1)](record(_0x72d670))),'session.rollback':_0x3a7122=>this[_0x510aec(0x1bf)](()=>this[_0x510aec(0x194)](record(_0x3a7122)))};}async[_0x419e16(0x1e0)](_0x268c74){const _0x1d6f45=_0x419e16,_0x2f89ad=typeof _0x268c74[_0x1d6f45(0x1ac)]===_0x1d6f45(0x20f)?_0x268c74[_0x1d6f45(0x1ac)]:undefined,_0x206fe5=typeof _0x268c74[_0x1d6f45(0x1c1)]===_0x1d6f45(0x20f)&&_0x268c74[_0x1d6f45(0x1c1)][_0x1d6f45(0x1d5)]()[_0x1d6f45(0x19b)]>0x1*0x174a+0xfd3*-0x1+-0x777?_0x268c74[_0x1d6f45(0x1c1)][_0x1d6f45(0x1d5)]()[_0x1d6f45(0x1ea)](_0x1d6f45(0x21c))[_0x1d6f45(0x1a3)]():undefined,_0x212595=_0x2f89ad===undefined?this[_0x1d6f45(0x1bb)][_0x1d6f45(0x210)]():_0x206fe5===undefined?await this[_0x1d6f45(0x1bb)][_0x1d6f45(0x223)](_0x2f89ad):await this[_0x1d6f45(0x1bb)][_0x1d6f45(0x1ae)](_0x2f89ad),_0x2ae49f=_0x212595[_0x1d6f45(0x22a)](_0x1c0766=>this[_0x1d6f45(0x1bb)][_0x1d6f45(0x1c5)]({..._0x1c0766,'externalDiscovered':!![]})),_0x56a4dd=this[_0x1d6f45(0x1bb)][_0x1d6f45(0x1f1)][_0x1d6f45(0x204)]()[_0x1d6f45(0x1ab)](_0x25c485=>_0x25c485[_0x1d6f45(0x197)]===_0x1d6f45(0x1e8)||_0x25c485[_0x1d6f45(0x197)]===_0x1d6f45(0x1a9)&&_0x25c485[_0x1d6f45(0x1db)]!==null)[_0x1d6f45(0x22a)](_0x3259c9=>{const _0x324dac=_0x1d6f45,_0x46d7ed=_0x2ae49f[_0x324dac(0x203)](_0x2b4d71=>this[_0x324dac(0x1bb)][_0x324dac(0x1c3)](_0x2b4d71)?.['id']===_0x3259c9['id']),_0x4bfb37=_0x3259c9[_0x324dac(0x215)]!==_0x324dac(0x198)||_0x46d7ed?.[_0x324dac(0x1f0)]===undefined||_0x46d7ed[_0x324dac(0x1f0)]===null?_0x3259c9:this[_0x324dac(0x1bb)][_0x324dac(0x1f1)][_0x324dac(0x1d3)](_0x3259c9['id'],_0x46d7ed[_0x324dac(0x1f0)]);return this[_0x324dac(0x1bb)][_0x324dac(0x1c5)](_0x46d7ed===undefined?_0x4bfb37:{..._0x4bfb37,'pinnedAt':_0x46d7ed[_0x324dac(0x21b)],'pinOrder':_0x46d7ed[_0x324dac(0x20c)]??null,'externalDiscovered':!![],'lastActivityAt':latestSessionActivityAt(_0x4bfb37[_0x324dac(0x1cf)],_0x46d7ed[_0x324dac(0x1cf)])});}),_0x2205e0=new Map([..._0x56a4dd,..._0x2ae49f[_0x1d6f45(0x1ab)](_0x4fb55a=>_0x4fb55a[_0x1d6f45(0x1db)]===null||this[_0x1d6f45(0x1bb)][_0x1d6f45(0x1c3)](_0x4fb55a)===undefined)][_0x1d6f45(0x22a)](_0x527406=>[_0x527406['id'],_0x527406]));if(_0x2f89ad!==undefined)this[_0x1d6f45(0x19f)](_0x2205e0,_0x2f89ad);const _0x51d750=[..._0x2205e0[_0x1d6f45(0x1cb)]()][_0x1d6f45(0x1ab)](_0x263711=>{const _0x14a187=_0x1d6f45;if(_0x206fe5===undefined)return!![];const _0x3b9014=(_0x263711[_0x14a187(0x1c9)]??_0x263711[_0x14a187(0x1f0)]??'')[_0x14a187(0x1ea)](_0x14a187(0x21c))[_0x14a187(0x1a3)]();return _0x3b9014[_0x14a187(0x1f3)](_0x206fe5);});return sessionPage(_0x2f89ad===undefined?_0x51d750:_0x51d750[_0x1d6f45(0x1ab)](_0x47c258=>_0x47c258[_0x1d6f45(0x1ac)]===_0x2f89ad),_0x268c74);}[_0x419e16(0x19f)](_0x5d38a0,_0x29a19e){const _0x499b41=_0x419e16,_0x219944=this[_0x499b41(0x1bb)][_0x499b41(0x1c2)](),_0x125168=_0x219944[_0x499b41(0x217)](_0x29a19e);if(_0x125168===undefined)throw new Error(_0x499b41(0x21e));for(const _0x1b1fd7 of _0x219944[_0x499b41(0x213)](_0x29a19e)){if(_0x5d38a0[_0x499b41(0x19a)](_0x1b1fd7['id']))continue;_0x5d38a0[_0x499b41(0x1ee)](_0x1b1fd7['id'],this[_0x499b41(0x1bb)][_0x499b41(0x1c5)]({'id':_0x1b1fd7['id'],'nodeId':this[_0x499b41(0x1bb)][_0x499b41(0x229)](),'workspaceId':_0x29a19e,'runner':_0x1b1fd7[_0x499b41(0x221)],'externalSessionId':_0x1b1fd7['id'],'nativeControl':_0x499b41(0x1a9),'channelToken':null,'cwd':_0x125168[_0x499b41(0x1b5)],'model':_0x1b1fd7[_0x499b41(0x18e)][_0x499b41(0x1b2)],'effort':_0x1b1fd7[_0x499b41(0x18e)][_0x499b41(0x1be)],'access':_0x1b1fd7[_0x499b41(0x18e)][_0x499b41(0x193)],'customTitle':_0x1b1fd7[_0x499b41(0x18e)][_0x499b41(0x1c9)],'runnerTitle':_0x1b1fd7[_0x499b41(0x18e)][_0x499b41(0x1f0)],'pinnedAt':_0x1b1fd7[_0x499b41(0x20c)]===null?null:-0x1*-0xc4d+0x1*-0x1c13+-0x241*-0x7,'pinOrder':_0x1b1fd7[_0x499b41(0x20c)],'externalDiscovered':![],'titleSource':_0x1b1fd7[_0x499b41(0x18e)][_0x499b41(0x1c9)]===null?_0x499b41(0x1fa):_0x499b41(0x219),'lastActivityAt':0x0,'createdAt':0x0}));}}async[_0x419e16(0x20e)](_0x5b8e68){const _0x2c5b54=_0x419e16;if(typeof _0x5b8e68[_0x2c5b54(0x1ce)]!==_0x2c5b54(0x20f))throw new Error(_0x2c5b54(0x1b8));const _0x409846=this[_0x2c5b54(0x1bb)][_0x2c5b54(0x1f1)][_0x2c5b54(0x214)](_0x5b8e68[_0x2c5b54(0x1ce)])??await this[_0x2c5b54(0x1bb)][_0x2c5b54(0x1d6)][_0x2c5b54(0x1ec)](_0x5b8e68[_0x2c5b54(0x1ce)]);if(_0x409846===undefined)throw new Error(_0x2c5b54(0x19c));if(_0x409846[_0x2c5b54(0x197)]!==_0x2c5b54(0x1a9))return{'session':this[_0x2c5b54(0x1bb)][_0x2c5b54(0x1c5)](_0x409846),'delivery':this[_0x2c5b54(0x1bb)][_0x2c5b54(0x20e)][_0x2c5b54(0x209)](_0x409846)};const _0x86d902=await this[_0x2c5b54(0x1bb)][_0x2c5b54(0x20e)][_0x2c5b54(0x20e)](_0x409846),_0x10e52c=_0x86d902===undefined?this[_0x2c5b54(0x1bb)][_0x2c5b54(0x20e)][_0x2c5b54(0x1b3)](_0x409846['id']):undefined;return{'session':this[_0x2c5b54(0x1bb)][_0x2c5b54(0x1c5)](_0x86d902??_0x409846),'delivery':_0x86d902===undefined?_0x2c5b54(0x1da):_0x2c5b54(0x1df),..._0x86d902===undefined?{'reasonCode':_0x10e52c?.[_0x2c5b54(0x224)]??_0x2c5b54(0x191)}:{}};}[_0x419e16(0x1bf)](_0x38a45c){const _0x2be5dd=_0x419e16,_0x35f083=this[_0x2be5dd(0x199)][_0x2be5dd(0x190)](_0x38a45c);return this[_0x2be5dd(0x199)]=_0x35f083[_0x2be5dd(0x190)](()=>undefined,()=>undefined),_0x35f083;}async[_0x419e16(0x194)](_0x4575e9){const _0x5087c5=_0x419e16;if(!validRewindId(_0x4575e9[_0x5087c5(0x1ce)],0x8a3+0xa*-0x2b+-0x675)||!validRewindId(_0x4575e9[_0x5087c5(0x212)],0x1a2*0x2+-0x2*-0x106a+-0x218*0x11)||_0x4575e9[_0x5087c5(0x19d)]!==null&&!validRewindId(_0x4575e9[_0x5087c5(0x19d)],-0x2281+0xa1*0x27+0xafa))throw new Error(_0x5087c5(0x1e4));const _0x354f8c=this[_0x5087c5(0x1bb)][_0x5087c5(0x1f1)][_0x5087c5(0x214)](_0x4575e9[_0x5087c5(0x1ce)])??await this[_0x5087c5(0x1bb)][_0x5087c5(0x1d6)][_0x5087c5(0x1ec)](_0x4575e9[_0x5087c5(0x1ce)]);if(_0x354f8c===undefined)throw new Error(_0x5087c5(0x19c));if(_0x354f8c[_0x5087c5(0x221)]!==_0x5087c5(0x1a7)||_0x354f8c[_0x5087c5(0x1db)]===null)throw new Error(_0x5087c5(0x228));if(this[_0x5087c5(0x1bb)][_0x5087c5(0x1f1)][_0x5087c5(0x22c)](_0x354f8c['id'])[_0x5087c5(0x1c0)](_0x40d32f=>!isTerminalRunStatus(_0x40d32f[_0x5087c5(0x1f2)])))throw new Error(_0x5087c5(0x21d));if(this[_0x5087c5(0x1bb)][_0x5087c5(0x1f1)][_0x5087c5(0x1bc)](_0x354f8c['id'])[_0x5087c5(0x1af)][_0x5087c5(0x19b)]>-0x15eb*-0x1+0x11*-0x10d+-0x1*0x40e)throw new Error(_0x5087c5(0x201));const _0x1ec8b2=await this[_0x5087c5(0x1a6)](_0x354f8c,_0x4575e9[_0x5087c5(0x212)]),_0xb7b334=_0x1ec8b2?.[_0x5087c5(0x1bd)][_0x5087c5(0x203)](_0x9ed1fd=>_0x9ed1fd[_0x5087c5(0x202)]===_0x5087c5(0x1fe)&&_0x9ed1fd[_0x5087c5(0x1f2)]===_0x5087c5(0x207));if(_0x1ec8b2===undefined||!terminalConversationStatus(_0x1ec8b2[_0x5087c5(0x1f2)])||_0xb7b334===undefined||_0x1ec8b2[_0x5087c5(0x1d1)]?.[_0x5087c5(0x1aa)]!==_0x4575e9[_0x5087c5(0x19d)])throw new Error(_0x5087c5(0x1d8));const _0x11df7b=this[_0x5087c5(0x1bb)][_0x5087c5(0x1f1)][_0x5087c5(0x1a2)](_0x354f8c['id']);try{const _0x27fc3a=await this[_0x5087c5(0x1bb)][_0x5087c5(0x195)][_0x5087c5(0x1d4)](_0x354f8c[_0x5087c5(0x221)])[_0x5087c5(0x21a)](_0x354f8c,_0x4575e9[_0x5087c5(0x19d)]),_0x1d0dde=this[_0x5087c5(0x1bb)][_0x5087c5(0x1f1)][_0x5087c5(0x214)](_0x354f8c['id']),_0x2f2d33=_0x1d0dde===undefined?{..._0x354f8c,'lastActivityAt':_0x27fc3a}:this[_0x5087c5(0x1bb)][_0x5087c5(0x1f1)][_0x5087c5(0x1ff)](_0x1d0dde['id'],_0x27fc3a);return this[_0x5087c5(0x1bb)][_0x5087c5(0x1d6)][_0x5087c5(0x1dd)]([_0x2f2d33]),this[_0x5087c5(0x1bb)][_0x5087c5(0x1fd)](_0x2f2d33['id']),this[_0x5087c5(0x1bb)][_0x5087c5(0x1ed)](_0x2f2d33[_0x5087c5(0x1ac)]),this[_0x5087c5(0x1bb)][_0x5087c5(0x1e7)](_0x2f2d33),{'session':this[_0x5087c5(0x1bb)][_0x5087c5(0x1c5)](_0x2f2d33)};}finally{_0x11df7b();}}async[_0x419e16(0x1d1)](_0x29d560){const _0x49d8ba=_0x419e16;if(!validRewindId(_0x29d560[_0x49d8ba(0x1ce)],-0x1ba4+-0x24f7*-0x1+-0x8d3*0x1)||!validRewindId(_0x29d560[_0x49d8ba(0x212)],0x1*0x84b+0x422*-0x3+0x189*0x3)||_0x29d560[_0x49d8ba(0x1e3)]!==_0x49d8ba(0x1b0)&&_0x29d560[_0x49d8ba(0x1e3)]!==_0x49d8ba(0x20d)||_0x29d560[_0x49d8ba(0x19d)]!==null&&!validRewindId(_0x29d560[_0x49d8ba(0x19d)],-0xf7*0x28+-0x3*-0x448+-0xd60*-0x2))throw new Error(_0x49d8ba(0x196));const _0x14ecc4=this[_0x49d8ba(0x1bb)][_0x49d8ba(0x1f1)][_0x49d8ba(0x214)](_0x29d560[_0x49d8ba(0x1ce)])??await this[_0x49d8ba(0x1bb)][_0x49d8ba(0x1d6)][_0x49d8ba(0x1ec)](_0x29d560[_0x49d8ba(0x1ce)]);if(_0x14ecc4===undefined)throw new Error(_0x49d8ba(0x19c));if(_0x14ecc4[_0x49d8ba(0x1db)]===null)throw new Error(_0x49d8ba(0x227));const _0x962148=await this[_0x49d8ba(0x1a6)](_0x14ecc4,_0x29d560[_0x49d8ba(0x212)]),_0x4e9ec5=_0x29d560[_0x49d8ba(0x1e3)]===_0x49d8ba(0x1b0)?_0x962148?.[_0x49d8ba(0x1d1)]?.[_0x49d8ba(0x1aa)]:_0x962148?.[_0x49d8ba(0x1d1)]?.[_0x49d8ba(0x1fc)];if(_0x962148===undefined||_0x4e9ec5!==_0x29d560[_0x49d8ba(0x19d)])throw new Error(_0x49d8ba(0x1e1));const _0x1d0097=rewindTitle(_0x14ecc4[_0x49d8ba(0x1c9)]??_0x14ecc4[_0x49d8ba(0x1f0)]??_0x49d8ba(0x1eb),this[_0x49d8ba(0x1bb)][_0x49d8ba(0x1f1)][_0x49d8ba(0x204)]()[_0x49d8ba(0x1a5)](_0x412caf=>[_0x412caf[_0x49d8ba(0x1c9)]??_0x412caf[_0x49d8ba(0x1f0)]][_0x49d8ba(0x1ab)](isString))),_0x42c460=this[_0x49d8ba(0x1bb)][_0x49d8ba(0x195)][_0x49d8ba(0x1d4)](_0x14ecc4[_0x49d8ba(0x221)]),_0x33b444=await _0x42c460[_0x49d8ba(0x19e)](_0x14ecc4,_0x29d560[_0x49d8ba(0x19d)],_0x1d0097),_0x6e98df=this[_0x49d8ba(0x1bb)][_0x49d8ba(0x1f1)][_0x49d8ba(0x1c8)]({'workspaceId':_0x14ecc4[_0x49d8ba(0x1ac)],'runner':_0x14ecc4[_0x49d8ba(0x221)],'cwd':_0x14ecc4[_0x49d8ba(0x1b6)],'nativeControl':_0x49d8ba(0x1e8),..._0x33b444===null?{}:{'externalSessionId':_0x33b444},..._0x14ecc4[_0x49d8ba(0x1b2)]===null?{}:{'model':_0x14ecc4[_0x49d8ba(0x1b2)]},..._0x14ecc4[_0x49d8ba(0x1be)]===null?{}:{'effort':_0x14ecc4[_0x49d8ba(0x1be)]},..._0x14ecc4[_0x49d8ba(0x193)]===null?{}:{'access':_0x14ecc4[_0x49d8ba(0x193)]},'title':_0x1d0097});if(_0x33b444!==null)_0x42c460[_0x49d8ba(0x226)](_0x6e98df,_0x33b444);return this[_0x49d8ba(0x1bb)][_0x49d8ba(0x1e7)](_0x6e98df),{'session':this[_0x49d8ba(0x1bb)][_0x49d8ba(0x1c5)](_0x6e98df)};}async[_0x419e16(0x1a6)](_0xf2bc0b,_0x19fc4d){const _0x6eb70b=_0x419e16;let _0x11140b;for(let _0x39f977=-0x127*-0x1c+-0x2687+0x643;_0x39f977<0x6*-0x2fc+0x225c+0x101*-0x10;_0x39f977+=0x249+0x5*0x7b7+-0x28db){const _0x86ef44=await this[_0x6eb70b(0x1bb)][_0x6eb70b(0x1c6)](_0xf2bc0b,{..._0x11140b===undefined?{}:{'cursor':_0x11140b},'limit':0x64}),_0x222e3b=_0x86ef44[_0x6eb70b(0x206)][_0x6eb70b(0x203)](_0x2c84ae=>_0x2c84ae['id']===_0x19fc4d);if(_0x222e3b!==undefined||_0x86ef44[_0x6eb70b(0x1e2)]===null)return _0x222e3b;_0x11140b=_0x86ef44[_0x6eb70b(0x1e2)];}throw new Error(_0x6eb70b(0x1e1));}async[_0x419e16(0x1e9)](_0x4f5a2e){const _0xadf042=_0x419e16;if(typeof _0x4f5a2e[_0xadf042(0x1ce)]!==_0xadf042(0x20f))throw new Error(_0xadf042(0x1b8));const _0x7f4aec=this[_0xadf042(0x1bb)][_0xadf042(0x1f1)][_0xadf042(0x214)](_0x4f5a2e[_0xadf042(0x1ce)])??await this[_0xadf042(0x1bb)][_0xadf042(0x1d6)][_0xadf042(0x1ec)](_0x4f5a2e[_0xadf042(0x1ce)]);if(_0x7f4aec===undefined)throw new Error(_0xadf042(0x19c));return await this[_0xadf042(0x1f6)](_0x7f4aec),{'deleted':!![]};}async[_0x419e16(0x1c7)](_0x3adeab){const _0x45581c=_0x419e16,_0x2f25d3=_0x3adeab[_0x45581c(0x1f4)];if(typeof _0x3adeab[_0x45581c(0x1ac)]!==_0x45581c(0x20f)||typeof _0x2f25d3!==_0x45581c(0x1f9)||!Number[_0x45581c(0x1d2)](_0x2f25d3)||_0x2f25d3<0x409*0x1+-0xc*-0x186+-0xa8*0x22||_0x2f25d3>0x2c5*-0x3+-0xc1d+0x15d9)throw new Error(_0x45581c(0x20b));if(this[_0x45581c(0x1bb)][_0x45581c(0x1c2)]()[_0x45581c(0x217)](_0x3adeab[_0x45581c(0x1ac)])===undefined)throw new Error(_0x45581c(0x21e));const _0x163149=Date[_0x45581c(0x1cc)]()-_0x2f25d3*(0x516+-0x24b*-0x1+-0x175*0x5)*(0x1f*-0x47+0x2cb*0x8+-0xd83)*(0x935*0x1+0x1580+0x10d*-0x1d)*(-0x200b*-0x1+0x6*-0x12a+-0x1527),_0x842387=await this[_0x45581c(0x1bb)][_0x45581c(0x1ae)](_0x3adeab[_0x45581c(0x1ac)]);let _0xeeae1f=0x229c+0x8b8+-0x2b54,_0xdfbf8a=0x17*0x18a+-0x301*0x4+0x52*-0x49,_0x2561cd=0x19*0xf9+-0x6e5*-0x1+-0x1f36;const _0x13387c={};for(const _0x5953aa of deduplicateNativeSessions(_0x842387)){if(_0x5953aa[_0x45581c(0x1ac)]!==_0x3adeab[_0x45581c(0x1ac)])continue;const _0x6c393a=this[_0x45581c(0x1ad)](_0x5953aa);if(_0x6c393a[_0x45581c(0x1db)]===null||!Number[_0x45581c(0x192)](_0x6c393a[_0x45581c(0x1cf)])||_0x6c393a[_0x45581c(0x1cf)]<=-0x52f+-0xc1e+0x1*0x114d||_0x6c393a[_0x45581c(0x1cf)]>=_0x163149||_0x6c393a[_0x45581c(0x20c)]!==null&&_0x6c393a[_0x45581c(0x20c)]!==undefined||this[_0x45581c(0x1bb)][_0x45581c(0x218)](_0x6c393a['id'])||this[_0x45581c(0x1bb)][_0x45581c(0x1f1)][_0x45581c(0x1bc)](_0x6c393a['id'])[_0x45581c(0x1af)][_0x45581c(0x19b)]>0x176+-0x1cb1+0x1b3b||this[_0x45581c(0x1bb)][_0x45581c(0x1f1)][_0x45581c(0x22c)](_0x6c393a['id'])[_0x45581c(0x1c0)](_0x5012af=>!isTerminalRunStatus(_0x5012af[_0x45581c(0x1f2)]))||this[_0x45581c(0x1bb)][_0x45581c(0x1b7)](_0x6c393a['id'])===_0x45581c(0x1a4)){_0xdfbf8a+=0x744+0x3df*-0x2+0x29*0x3;continue;}try{if(await this[_0x45581c(0x1f6)](_0x6c393a,!![])===_0x45581c(0x1f7))_0xeeae1f+=-0x5ff+0x370+0x29*0x10,_0x13387c[_0x6c393a[_0x45581c(0x221)]]=(_0x13387c[_0x6c393a[_0x45581c(0x221)]]??0x61d+-0x1*-0x26fc+-0x2d19)+(0xb95*-0x1+-0x1*0xe0d+0x19a3);else _0xdfbf8a+=0x985+-0x84*-0x2c+-0x2034;}catch(_0x5b1432){if(isCleanupSkip(_0x5b1432))_0xdfbf8a+=-0x1*-0x1846+-0x21*-0x73+0x9*-0x458;else _0x2561cd+=0x1ae1+0xb*-0x215+-0x3f9,nodeLog(_0x45581c(0x1a0),{'workspaceId':_0x3adeab[_0x45581c(0x1ac)],'sessionId':_0x6c393a['id'],'runner':_0x6c393a[_0x45581c(0x221)],...cleanupFailureDiagnostic(_0x5b1432)});}}return this[_0x45581c(0x1bb)][_0x45581c(0x1ed)](_0x3adeab[_0x45581c(0x1ac)]),{'deleted':_0xeeae1f,'skipped':_0xdfbf8a,'failed':_0x2561cd,'deletedByRunner':_0x13387c};}[_0x419e16(0x1ad)](_0x5c2142){const _0x373c99=_0x419e16,_0x4747e1=this[_0x373c99(0x1bb)][_0x373c99(0x1c3)](_0x5c2142);if(_0x4747e1===undefined)return _0x5c2142;return{..._0x4747e1,'pinnedAt':_0x5c2142[_0x373c99(0x21b)]??_0x4747e1[_0x373c99(0x21b)],'pinOrder':_0x5c2142[_0x373c99(0x20c)]??_0x4747e1[_0x373c99(0x20c)]??null,'externalDiscovered':_0x5c2142[_0x373c99(0x1c4)]??!![],'lastActivityAt':latestSessionActivityAt(_0x4747e1[_0x373c99(0x1cf)],_0x5c2142[_0x373c99(0x1cf)])};}async[_0x419e16(0x1f6)](_0x3da372,_0x2679f0=![]){const _0x136b3b=_0x419e16;if(_0x3da372[_0x136b3b(0x1db)]===null)throw new Error(_0x136b3b(0x1a1));const _0x5e0317=_0x2679f0?this[_0x136b3b(0x1bb)][_0x136b3b(0x1f1)][_0x136b3b(0x1a2)](_0x3da372['id']):undefined;try{if(this[_0x136b3b(0x1bb)][_0x136b3b(0x1f1)][_0x136b3b(0x22c)](_0x3da372['id'])[_0x136b3b(0x1c0)](_0x350dba=>!isTerminalRunStatus(_0x350dba[_0x136b3b(0x1f2)])))throw new Error(_0x136b3b(0x21d));if(_0x3da372[_0x136b3b(0x197)]===_0x136b3b(0x1a9)){await this[_0x136b3b(0x1bb)][_0x136b3b(0x222)](_0x3da372);if(this[_0x136b3b(0x1bb)][_0x136b3b(0x1b7)](_0x3da372['id'])===_0x136b3b(0x1a4))throw new Error(_0x136b3b(0x21d));}if(_0x2679f0){if(this[_0x136b3b(0x1bb)][_0x136b3b(0x218)](_0x3da372['id']))throw new Error(_0x136b3b(0x22e));if(this[_0x136b3b(0x1bb)][_0x136b3b(0x1f1)][_0x136b3b(0x1bc)](_0x3da372['id'])[_0x136b3b(0x1af)][_0x136b3b(0x19b)]>0x1*-0x1576+-0x4ac+0x2*0xd11)throw new Error(_0x136b3b(0x201));if(this[_0x136b3b(0x1bb)][_0x136b3b(0x1f1)][_0x136b3b(0x22c)](_0x3da372['id'])[_0x136b3b(0x1c0)](_0x56c95b=>!isTerminalRunStatus(_0x56c95b[_0x136b3b(0x1f2)])))throw new Error(_0x136b3b(0x21d));}const _0x12ff65=this[_0x136b3b(0x1bb)][_0x136b3b(0x1b4)](_0x3da372),_0x11f8d0=this[_0x136b3b(0x1bb)][_0x136b3b(0x195)][_0x136b3b(0x1d4)](_0x3da372[_0x136b3b(0x221)]);let _0x34891c=![];for(const _0x566804 of _0x12ff65){try{const _0x429539=await _0x11f8d0[_0x136b3b(0x18c)](_0x3da372,_0x566804);if(_0x429539===!![])_0x34891c=!![];else _0x429539===![]&&(await removeNativeSession(_0x3da372[_0x136b3b(0x221)],_0x3da372[_0x136b3b(0x1b6)],_0x566804),_0x34891c=!![]);}catch(_0x1f959a){if(!(_0x1f959a instanceof Error)||_0x1f959a[_0x136b3b(0x211)]!==_0x136b3b(0x1a1))throw _0x1f959a;}}return this[_0x136b3b(0x1bb)][_0x136b3b(0x1c2)]()[_0x136b3b(0x22d)](_0x3da372['id']),this[_0x136b3b(0x1bb)][_0x136b3b(0x216)](_0x3da372,_0x12ff65),_0x34891c?_0x136b3b(0x1f7):_0x136b3b(0x21f);}finally{_0x5e0317?.();}}}export function rewindTitle(_0x3e93c6,_0x37450f=[]){const _0x16edd0=_0x419e16,_0xb87a59=_0x3e93c6[_0x16edd0(0x18d)](/ \(Copy \d+\)$/u,''),_0x37f0ae=new Set(_0x37450f);for(let _0x5ed751=0x15d*0x8+0x1*0xcd+0x2*-0x5da;_0x5ed751<Number[_0x16edd0(0x1d0)];_0x5ed751+=-0x1237*-0x2+0x255c*-0x1+0x1*0xef){const _0x1cf7eb=_0x16edd0(0x1b9)+_0x5ed751+')',_0x5b9769=''+_0xb87a59[_0x16edd0(0x1f8)](-0x1f29+0xc93*0x1+-0xb7*-0x1a,-0xa6*-0x2+0x1b07+-0x7*0x3f5-_0x1cf7eb[_0x16edd0(0x19b)])+_0x1cf7eb;if(!_0x37f0ae[_0x16edd0(0x19a)](_0x5b9769))return _0x5b9769;}throw new Error(_0x16edd0(0x1e5));}function validRewindId(_0x4d8bd5,_0x2452fe){const _0x3e0f33=_0x419e16;return typeof _0x4d8bd5===_0x3e0f33(0x20f)&&_0x4d8bd5[_0x3e0f33(0x19b)]>0x1*0xdd2+0x6*-0x3a1+0x1*0x7f4&&_0x4d8bd5[_0x3e0f33(0x19b)]<=_0x2452fe;}function _0x3127(_0x333797,_0x25da74){_0x333797=_0x333797-(0x1e88+0x1*-0xad+-0x1*0x1c4f);const _0x4f8c2e=_0x1973();let _0x11acd3=_0x4f8c2e[_0x333797];if(_0x3127['lHViEq']===undefined){var _0x258ca3=function(_0x4a99bf){const _0x12f511='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x174a29='',_0x35e574='';for(let _0x327d3c=0xad*0xd+-0x2d+0x1*-0x89c,_0x2f0ec8,_0x45d0b9,_0xc5f33a=0x1d96+-0xc9d*-0x2+-0x1*0x36d0;_0x45d0b9=_0x4a99bf['charAt'](_0xc5f33a++);~_0x45d0b9&&(_0x2f0ec8=_0x327d3c%(-0x55*-0x37+-0x1*-0x5c2+-0x1801)?_0x2f0ec8*(0x207d+0x797*0x2+0x2f6b*-0x1)+_0x45d0b9:_0x45d0b9,_0x327d3c++%(-0x6aa*-0x5+-0x34c+-0x14e*0x17))?_0x174a29+=String['fromCharCode'](0x1fdb+-0x21*-0xad+-0x3529*0x1&_0x2f0ec8>>(-(-0x1*-0x1666+0x1270+-0x27*0x10c)*_0x327d3c&-0x5fd*-0x1+-0x1*0x16eb+0xa*0x1b2)):0x574*0x7+0x1e2f+0x445b*-0x1){_0x45d0b9=_0x12f511['indexOf'](_0x45d0b9);}for(let _0x3fde0a=-0x1896+-0x216*-0x1+-0x1680*-0x1,_0x15b212=_0x174a29['length'];_0x3fde0a<_0x15b212;_0x3fde0a++){_0x35e574+='%'+('00'+_0x174a29['charCodeAt'](_0x3fde0a)['toString'](0x14e0+-0x188d+0x3bd))['slice'](-(-0x1*-0x225c+0x4f*0xe+0x26ac*-0x1));}return decodeURIComponent(_0x35e574);};_0x3127['tnnOUp']=_0x258ca3,_0x3127['hBipvi']={},_0x3127['lHViEq']=!![];}const _0x20e7aa=_0x4f8c2e[-0x474*0x5+0x5*0x32b+0xeb*0x7];_0x3127['txgglk']!==_0x20e7aa&&(_0x3127['hBipvi']={},_0x3127['txgglk']=_0x20e7aa);const _0x3f0772=_0x3127['hBipvi'][_0x333797];return _0x3f0772===undefined?(_0x11acd3=_0x3127['tnnOUp'](_0x11acd3),_0x3127['hBipvi'][_0x333797]=_0x11acd3):_0x11acd3=_0x3f0772,_0x11acd3;}function terminalConversationStatus(_0x188604){const _0x46b11e=_0x419e16;return[_0x46b11e(0x1cd),_0x46b11e(0x1a8),_0x46b11e(0x225),_0x46b11e(0x1d7),_0x46b11e(0x18f)][_0x46b11e(0x1f3)](_0x188604);}function isString(_0x546f25){return _0x546f25!==null;}function record(_0x2444c9){const _0x2f3af0=_0x419e16;if(_0x2444c9===null||typeof _0x2444c9!==_0x2f3af0(0x1fb)||Array[_0x2f3af0(0x20a)](_0x2444c9))return{};return _0x2444c9;}function deduplicateNativeSessions(_0x3ebcef){const _0x2944db=_0x419e16;return[...new Map(_0x3ebcef[_0x2944db(0x22a)](_0x1915d3=>[_0x1915d3['id'],_0x1915d3]))[_0x2944db(0x1cb)]()];}function isCleanupSkip(_0x58d5ea){const _0x2bf3af=_0x419e16;return _0x58d5ea instanceof Error&&(_0x58d5ea[_0x2bf3af(0x211)]===_0x2bf3af(0x21d)||_0x58d5ea[_0x2bf3af(0x211)]===_0x2bf3af(0x19c)||_0x58d5ea[_0x2bf3af(0x211)]===_0x2bf3af(0x201)||_0x58d5ea[_0x2bf3af(0x211)]===_0x2bf3af(0x22e)||_0x58d5ea[_0x2bf3af(0x211)]===_0x2bf3af(0x1a1));}function cleanupFailureDiagnostic(_0x14bcc3){const _0x2d48fb=_0x419e16,_0x1edf31=_0x14bcc3!==null&&typeof _0x14bcc3===_0x2d48fb(0x1fb)?_0x14bcc3:{},_0x1a0adf=typeof _0x1edf31[_0x2d48fb(0x224)]===_0x2d48fb(0x20f)?_0x1edf31[_0x2d48fb(0x224)]:undefined,_0x363fd5=_0x14bcc3 instanceof Error?_0x14bcc3[_0x2d48fb(0x211)]:String(_0x14bcc3);return{'errorCode':(_0x1a0adf??_0x2d48fb(0x1ca))[_0x2d48fb(0x1f8)](-0x2e*-0x59+0x266f+-0x366d,-0x15d*-0x17+-0x24e*0xa+-0x7ff),'error':_0x363fd5[_0x2d48fb(0x1f8)](-0x1d3*-0x2+-0x2*0xefe+-0x2*-0xd2b,-0x1e5d*0x1+-0x6db+-0x272c*-0x1)};}
|
|
1
|
+
import { removeNativeSession } from '../native-session-history.js';
|
|
2
|
+
import { nodeLog } from '../operational.js';
|
|
3
|
+
import { isTerminalRunStatus, sessionPage } from '../util/node-operation-parsers.js';
|
|
4
|
+
import { latestSessionActivityAt } from './session-presentation-service.js';
|
|
5
|
+
export class SessionCatalogService {
|
|
6
|
+
options;
|
|
7
|
+
rewindQueue = Promise.resolve();
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
}
|
|
11
|
+
operations() {
|
|
12
|
+
return {
|
|
13
|
+
'session.list': (data) => this.list(record(data)),
|
|
14
|
+
'session.resume': (data) => this.resume(record(data)),
|
|
15
|
+
'session.remove': (data) => this.enqueueMutation(() => this.remove(record(data))),
|
|
16
|
+
'workspace.sessions.cleanup': (data) => this.enqueueMutation(() => this.cleanupWorkspaceSessions(record(data))),
|
|
17
|
+
'session.rewind': (data) => this.enqueueMutation(() => this.rewind(record(data))),
|
|
18
|
+
'session.rollback': (data) => this.enqueueMutation(() => this.rollback(record(data)))
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async list(input) {
|
|
22
|
+
const workspaceId = typeof input.workspaceId === 'string' ? input.workspaceId : undefined;
|
|
23
|
+
const query = typeof input.query === 'string' && input.query.trim().length > 0
|
|
24
|
+
? input.query.trim().normalize('NFKC').toLocaleLowerCase()
|
|
25
|
+
: undefined;
|
|
26
|
+
const nativeSessions = workspaceId === undefined
|
|
27
|
+
? this.options.cachedNative()
|
|
28
|
+
: query === undefined
|
|
29
|
+
? await this.options.cachedWorkspace(workspaceId)
|
|
30
|
+
: await this.options.discoverWorkspace(workspaceId);
|
|
31
|
+
const native = nativeSessions.map((session) => this.options.present({ ...session, externalDiscovered: true }));
|
|
32
|
+
const projected = this.options.runtime
|
|
33
|
+
.listAgentSessions()
|
|
34
|
+
.filter((session) => session.nativeControl === 'MAR_MANAGED' ||
|
|
35
|
+
(session.nativeControl === 'EXTERNAL' && session.externalSessionId !== null))
|
|
36
|
+
.map((session) => {
|
|
37
|
+
const source = native.find((candidate) => this.options.projectionForNative(candidate)?.id === session.id);
|
|
38
|
+
const synchronized = session.titleSource !== 'AUTO' ||
|
|
39
|
+
source?.runnerTitle === undefined ||
|
|
40
|
+
source.runnerTitle === null
|
|
41
|
+
? session
|
|
42
|
+
: this.options.runtime.setRunnerTitleFromNative(session.id, source.runnerTitle);
|
|
43
|
+
return this.options.present(source === undefined
|
|
44
|
+
? synchronized
|
|
45
|
+
: {
|
|
46
|
+
...synchronized,
|
|
47
|
+
pinnedAt: source.pinnedAt,
|
|
48
|
+
pinOrder: source.pinOrder ?? null,
|
|
49
|
+
externalDiscovered: true,
|
|
50
|
+
lastActivityAt: latestSessionActivityAt(synchronized.lastActivityAt, source.lastActivityAt)
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const merged = new Map([
|
|
54
|
+
...projected,
|
|
55
|
+
...native.filter((candidate) => candidate.externalSessionId === null ||
|
|
56
|
+
this.options.projectionForNative(candidate) === undefined)
|
|
57
|
+
].map((session) => [session.id, session]));
|
|
58
|
+
if (workspaceId !== undefined)
|
|
59
|
+
this.mergePersisted(merged, workspaceId);
|
|
60
|
+
const sessions = [...merged.values()].filter((session) => {
|
|
61
|
+
if (query === undefined)
|
|
62
|
+
return true;
|
|
63
|
+
const title = (session.customTitle ?? session.runnerTitle ?? '')
|
|
64
|
+
.normalize('NFKC')
|
|
65
|
+
.toLocaleLowerCase();
|
|
66
|
+
return title.includes(query);
|
|
67
|
+
});
|
|
68
|
+
return sessionPage(workspaceId === undefined
|
|
69
|
+
? sessions
|
|
70
|
+
: sessions.filter((session) => session.workspaceId === workspaceId), input);
|
|
71
|
+
}
|
|
72
|
+
mergePersisted(merged, workspaceId) {
|
|
73
|
+
const database = this.options.database();
|
|
74
|
+
const workspace = database.getWorkspace(workspaceId);
|
|
75
|
+
if (workspace === undefined)
|
|
76
|
+
throw new Error('WORKSPACE_NOT_FOUND');
|
|
77
|
+
for (const persisted of database.listSessionRecords(workspaceId)) {
|
|
78
|
+
if (merged.has(persisted.id))
|
|
79
|
+
continue;
|
|
80
|
+
merged.set(persisted.id, this.options.present({
|
|
81
|
+
id: persisted.id,
|
|
82
|
+
nodeId: this.options.nodeId(),
|
|
83
|
+
workspaceId,
|
|
84
|
+
runner: persisted.runner,
|
|
85
|
+
externalSessionId: persisted.id,
|
|
86
|
+
nativeControl: 'EXTERNAL',
|
|
87
|
+
channelToken: null,
|
|
88
|
+
cwd: workspace.path,
|
|
89
|
+
model: persisted.metadata.model,
|
|
90
|
+
effort: persisted.metadata.effort,
|
|
91
|
+
access: persisted.metadata.access,
|
|
92
|
+
customTitle: persisted.metadata.customTitle,
|
|
93
|
+
runnerTitle: persisted.metadata.runnerTitle,
|
|
94
|
+
pinnedAt: persisted.pinOrder === null ? null : 1,
|
|
95
|
+
pinOrder: persisted.pinOrder,
|
|
96
|
+
externalDiscovered: false,
|
|
97
|
+
titleSource: persisted.metadata.customTitle === null ? 'RUNNER' : 'CUSTOM',
|
|
98
|
+
lastActivityAt: 0,
|
|
99
|
+
createdAt: 0
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async resume(input) {
|
|
104
|
+
if (typeof input.sessionId !== 'string')
|
|
105
|
+
throw new Error('SESSION_INVALID');
|
|
106
|
+
const value = this.options.runtime.getAgentSession(input.sessionId) ??
|
|
107
|
+
(await this.options.projection.resolve(input.sessionId));
|
|
108
|
+
if (value === undefined)
|
|
109
|
+
throw new Error('SESSION_NOT_FOUND');
|
|
110
|
+
if (value.nativeControl !== 'EXTERNAL')
|
|
111
|
+
return {
|
|
112
|
+
session: this.options.present(value),
|
|
113
|
+
delivery: this.options.resume.delivery(value)
|
|
114
|
+
};
|
|
115
|
+
const resumed = await this.options.resume.resume(value);
|
|
116
|
+
const failure = resumed === undefined ? this.options.resume.failure(value.id) : undefined;
|
|
117
|
+
return {
|
|
118
|
+
session: this.options.present(resumed ?? value),
|
|
119
|
+
delivery: resumed === undefined ? 'REJECTED' : 'RESUMABLE',
|
|
120
|
+
...(resumed === undefined
|
|
121
|
+
? {
|
|
122
|
+
reasonCode: failure?.code ?? 'SESSION_RESUME_REJECTED'
|
|
123
|
+
}
|
|
124
|
+
: {})
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
enqueueMutation(operation) {
|
|
128
|
+
const result = this.rewindQueue.then(operation);
|
|
129
|
+
this.rewindQueue = result.then(() => undefined, () => undefined);
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
async rollback(input) {
|
|
133
|
+
if (!validRewindId(input.sessionId, 128) ||
|
|
134
|
+
!validRewindId(input.turnId, 128) ||
|
|
135
|
+
(input.boundary !== null && !validRewindId(input.boundary, 256)))
|
|
136
|
+
throw new Error('SESSION_ROLLBACK_INVALID');
|
|
137
|
+
const source = this.options.runtime.getAgentSession(input.sessionId) ??
|
|
138
|
+
(await this.options.projection.resolve(input.sessionId));
|
|
139
|
+
if (source === undefined)
|
|
140
|
+
throw new Error('SESSION_NOT_FOUND');
|
|
141
|
+
if (source.runner !== 'mar-agent' || source.externalSessionId === null)
|
|
142
|
+
throw new Error('SESSION_ROLLBACK_UNAVAILABLE');
|
|
143
|
+
if (this.options.runtime
|
|
144
|
+
.listRunsForSession(source.id)
|
|
145
|
+
.some((run) => !isTerminalRunStatus(run.status)))
|
|
146
|
+
throw new Error('SESSION_ACTIVE');
|
|
147
|
+
if (this.options.runtime.sessionQueue(source.id).itemIds.length > 0)
|
|
148
|
+
throw new Error('SESSION_QUEUE_NOT_EMPTY');
|
|
149
|
+
const turn = await this.findTurn(source, input.turnId);
|
|
150
|
+
const userMessage = turn?.items.find((item) => item.kind === 'user_message' && item.status === 'COMPLETED');
|
|
151
|
+
if (turn === undefined ||
|
|
152
|
+
!terminalConversationStatus(turn.status) ||
|
|
153
|
+
userMessage === undefined ||
|
|
154
|
+
turn.rewind?.before !== input.boundary)
|
|
155
|
+
throw new Error('SESSION_ROLLBACK_TARGET_INVALID');
|
|
156
|
+
const releaseMutation = this.options.runtime.beginSessionHistoryMutation(source.id);
|
|
157
|
+
try {
|
|
158
|
+
const lastActivityAt = await this.options.runners
|
|
159
|
+
.require(source.runner)
|
|
160
|
+
.rollbackNative(source, input.boundary);
|
|
161
|
+
const runtimeSession = this.options.runtime.getAgentSession(source.id);
|
|
162
|
+
const session = runtimeSession === undefined
|
|
163
|
+
? { ...source, lastActivityAt }
|
|
164
|
+
: this.options.runtime.resetAgentSessionHistory(runtimeSession.id, lastActivityAt);
|
|
165
|
+
this.options.projection.remember([session]);
|
|
166
|
+
this.options.invalidateHistory(session.id);
|
|
167
|
+
this.options.invalidateWorkspaceSessions(session.workspaceId);
|
|
168
|
+
this.options.emitSession(session);
|
|
169
|
+
return { session: this.options.present(session) };
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
releaseMutation();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async rewind(input) {
|
|
176
|
+
if (!validRewindId(input.sessionId, 128) ||
|
|
177
|
+
!validRewindId(input.turnId, 128) ||
|
|
178
|
+
(input.position !== 'BEFORE' && input.position !== 'AFTER') ||
|
|
179
|
+
(input.boundary !== null && !validRewindId(input.boundary, 256)))
|
|
180
|
+
throw new Error('SESSION_REWIND_INVALID');
|
|
181
|
+
const source = this.options.runtime.getAgentSession(input.sessionId) ??
|
|
182
|
+
(await this.options.projection.resolve(input.sessionId));
|
|
183
|
+
if (source === undefined)
|
|
184
|
+
throw new Error('SESSION_NOT_FOUND');
|
|
185
|
+
if (source.externalSessionId === null)
|
|
186
|
+
throw new Error('SESSION_REWIND_UNAVAILABLE');
|
|
187
|
+
const turn = await this.findTurn(source, input.turnId);
|
|
188
|
+
const expected = input.position === 'BEFORE' ? turn?.rewind?.before : turn?.rewind?.after;
|
|
189
|
+
if (turn === undefined || expected !== input.boundary)
|
|
190
|
+
throw new Error('SESSION_REWIND_TARGET_INVALID');
|
|
191
|
+
const title = rewindTitle(source.customTitle ?? source.runnerTitle ?? 'Untitled session', this.options.runtime
|
|
192
|
+
.listAgentSessions()
|
|
193
|
+
.flatMap((candidate) => [candidate.customTitle ?? candidate.runnerTitle].filter(isString)));
|
|
194
|
+
const runner = this.options.runners.require(source.runner);
|
|
195
|
+
const nativeId = await runner.forkNative(source, input.boundary, title);
|
|
196
|
+
const session = this.options.runtime.createAgentSession({
|
|
197
|
+
workspaceId: source.workspaceId,
|
|
198
|
+
runner: source.runner,
|
|
199
|
+
cwd: source.cwd,
|
|
200
|
+
nativeControl: 'MAR_MANAGED',
|
|
201
|
+
...(nativeId === null ? {} : { externalSessionId: nativeId }),
|
|
202
|
+
...(source.model === null ? {} : { model: source.model }),
|
|
203
|
+
...(source.effort === null ? {} : { effort: source.effort }),
|
|
204
|
+
...(source.access === null ? {} : { access: source.access }),
|
|
205
|
+
title
|
|
206
|
+
});
|
|
207
|
+
if (nativeId !== null)
|
|
208
|
+
runner.rememberManagedNative(session, nativeId);
|
|
209
|
+
this.options.emitSession(session);
|
|
210
|
+
return { session: this.options.present(session) };
|
|
211
|
+
}
|
|
212
|
+
async findTurn(session, turnId) {
|
|
213
|
+
let cursor;
|
|
214
|
+
for (let pageIndex = 0; pageIndex < 100; pageIndex += 1) {
|
|
215
|
+
const page = await this.options.history(session, {
|
|
216
|
+
...(cursor === undefined ? {} : { cursor }),
|
|
217
|
+
limit: 100
|
|
218
|
+
});
|
|
219
|
+
const turn = page.turns.find((candidate) => candidate.id === turnId);
|
|
220
|
+
if (turn !== undefined || page.nextCursor === null)
|
|
221
|
+
return turn;
|
|
222
|
+
cursor = page.nextCursor;
|
|
223
|
+
}
|
|
224
|
+
throw new Error('SESSION_REWIND_TARGET_INVALID');
|
|
225
|
+
}
|
|
226
|
+
async remove(input) {
|
|
227
|
+
if (typeof input.sessionId !== 'string')
|
|
228
|
+
throw new Error('SESSION_INVALID');
|
|
229
|
+
const session = this.options.runtime.getAgentSession(input.sessionId) ??
|
|
230
|
+
(await this.options.projection.resolve(input.sessionId));
|
|
231
|
+
if (session === undefined)
|
|
232
|
+
throw new Error('SESSION_NOT_FOUND');
|
|
233
|
+
await this.removeResolved(session);
|
|
234
|
+
return { deleted: true };
|
|
235
|
+
}
|
|
236
|
+
async cleanupWorkspaceSessions(input) {
|
|
237
|
+
const inactiveDays = input.inactiveDays;
|
|
238
|
+
if (typeof input.workspaceId !== 'string' ||
|
|
239
|
+
typeof inactiveDays !== 'number' ||
|
|
240
|
+
!Number.isInteger(inactiveDays) ||
|
|
241
|
+
inactiveDays < 1 ||
|
|
242
|
+
inactiveDays > 365)
|
|
243
|
+
throw new Error('WORKSPACE_SESSION_CLEANUP_INVALID');
|
|
244
|
+
if (this.options.database().getWorkspace(input.workspaceId) === undefined)
|
|
245
|
+
throw new Error('WORKSPACE_NOT_FOUND');
|
|
246
|
+
const cutoff = Date.now() - inactiveDays * 24 * 60 * 60 * 1000;
|
|
247
|
+
const nativeSessions = await this.options.discoverWorkspace(input.workspaceId);
|
|
248
|
+
let deleted = 0;
|
|
249
|
+
let skipped = 0;
|
|
250
|
+
let failed = 0;
|
|
251
|
+
const deletedByRunner = {};
|
|
252
|
+
for (const native of deduplicateNativeSessions(nativeSessions)) {
|
|
253
|
+
if (native.workspaceId !== input.workspaceId)
|
|
254
|
+
continue;
|
|
255
|
+
const session = this.cleanupCandidate(native);
|
|
256
|
+
if (session.externalSessionId === null ||
|
|
257
|
+
!Number.isFinite(session.lastActivityAt) ||
|
|
258
|
+
session.lastActivityAt <= 0 ||
|
|
259
|
+
session.lastActivityAt >= cutoff ||
|
|
260
|
+
(session.pinOrder !== null && session.pinOrder !== undefined) ||
|
|
261
|
+
this.options.isWatching(session.id) ||
|
|
262
|
+
this.options.runtime.sessionQueue(session.id).itemIds.length > 0 ||
|
|
263
|
+
this.options.runtime
|
|
264
|
+
.listRunsForSession(session.id)
|
|
265
|
+
.some((run) => !isTerminalRunStatus(run.status)) ||
|
|
266
|
+
this.options.externalActivity(session.id) === 'EXTERNAL_ACTIVE') {
|
|
267
|
+
skipped += 1;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
if ((await this.removeResolved(session, true)) === 'deleted') {
|
|
272
|
+
deleted += 1;
|
|
273
|
+
deletedByRunner[session.runner] = (deletedByRunner[session.runner] ?? 0) + 1;
|
|
274
|
+
}
|
|
275
|
+
else
|
|
276
|
+
skipped += 1;
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (isCleanupSkip(error))
|
|
280
|
+
skipped += 1;
|
|
281
|
+
else {
|
|
282
|
+
failed += 1;
|
|
283
|
+
nodeLog('workspace.session.cleanup.failed', {
|
|
284
|
+
workspaceId: input.workspaceId,
|
|
285
|
+
sessionId: session.id,
|
|
286
|
+
runner: session.runner,
|
|
287
|
+
...cleanupFailureDiagnostic(error)
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
this.options.invalidateWorkspaceSessions(input.workspaceId);
|
|
293
|
+
return { deleted, skipped, failed, deletedByRunner };
|
|
294
|
+
}
|
|
295
|
+
cleanupCandidate(native) {
|
|
296
|
+
const projected = this.options.projectionForNative(native);
|
|
297
|
+
if (projected === undefined)
|
|
298
|
+
return native;
|
|
299
|
+
return {
|
|
300
|
+
...projected,
|
|
301
|
+
pinnedAt: native.pinnedAt ?? projected.pinnedAt,
|
|
302
|
+
pinOrder: native.pinOrder ?? projected.pinOrder ?? null,
|
|
303
|
+
externalDiscovered: native.externalDiscovered ?? true,
|
|
304
|
+
lastActivityAt: latestSessionActivityAt(projected.lastActivityAt, native.lastActivityAt)
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
async removeResolved(session, requireCleanupSafety = false) {
|
|
308
|
+
if (session.externalSessionId === null)
|
|
309
|
+
throw new Error('NATIVE_TRANSCRIPT_UNAVAILABLE');
|
|
310
|
+
const releaseMutation = requireCleanupSafety
|
|
311
|
+
? this.options.runtime.beginSessionHistoryMutation(session.id)
|
|
312
|
+
: undefined;
|
|
313
|
+
try {
|
|
314
|
+
if (this.options.runtime
|
|
315
|
+
.listRunsForSession(session.id)
|
|
316
|
+
.some((run) => !isTerminalRunStatus(run.status)))
|
|
317
|
+
throw new Error('SESSION_ACTIVE');
|
|
318
|
+
if (session.nativeControl === 'EXTERNAL') {
|
|
319
|
+
await this.options.refreshActivity(session);
|
|
320
|
+
if (this.options.externalActivity(session.id) === 'EXTERNAL_ACTIVE')
|
|
321
|
+
throw new Error('SESSION_ACTIVE');
|
|
322
|
+
}
|
|
323
|
+
if (requireCleanupSafety) {
|
|
324
|
+
if (this.options.isWatching(session.id))
|
|
325
|
+
throw new Error('SESSION_WATCHING');
|
|
326
|
+
if (this.options.runtime.sessionQueue(session.id).itemIds.length > 0)
|
|
327
|
+
throw new Error('SESSION_QUEUE_NOT_EMPTY');
|
|
328
|
+
if (this.options.runtime
|
|
329
|
+
.listRunsForSession(session.id)
|
|
330
|
+
.some((run) => !isTerminalRunStatus(run.status)))
|
|
331
|
+
throw new Error('SESSION_ACTIVE');
|
|
332
|
+
}
|
|
333
|
+
const nativeIds = this.options.nativeIds(session);
|
|
334
|
+
const runner = this.options.runners.require(session.runner);
|
|
335
|
+
let deleted = false;
|
|
336
|
+
for (const externalSessionId of nativeIds) {
|
|
337
|
+
try {
|
|
338
|
+
const result = await runner.removeNative(session, externalSessionId);
|
|
339
|
+
if (result === true)
|
|
340
|
+
deleted = true;
|
|
341
|
+
else if (result === false) {
|
|
342
|
+
await removeNativeSession(session.runner, session.cwd, externalSessionId);
|
|
343
|
+
deleted = true;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
if (!(error instanceof Error) || error.message !== 'NATIVE_TRANSCRIPT_UNAVAILABLE')
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
this.options.database().deleteSessionRecord(session.id);
|
|
352
|
+
this.options.forget(session, nativeIds);
|
|
353
|
+
return deleted ? 'deleted' : 'skipped';
|
|
354
|
+
}
|
|
355
|
+
finally {
|
|
356
|
+
releaseMutation?.();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
export function rewindTitle(sourceTitle, existingTitles = []) {
|
|
361
|
+
const base = sourceTitle.replace(/ \(Copy \d+\)$/u, '');
|
|
362
|
+
const existing = new Set(existingTitles);
|
|
363
|
+
for (let sequence = 1; sequence < Number.MAX_SAFE_INTEGER; sequence += 1) {
|
|
364
|
+
const suffix = ` (Copy ${sequence})`;
|
|
365
|
+
const candidate = `${base.slice(0, 160 - suffix.length)}${suffix}`;
|
|
366
|
+
if (!existing.has(candidate))
|
|
367
|
+
return candidate;
|
|
368
|
+
}
|
|
369
|
+
throw new Error('SESSION_REWIND_TITLE_UNAVAILABLE');
|
|
370
|
+
}
|
|
371
|
+
function validRewindId(value, maximum) {
|
|
372
|
+
return typeof value === 'string' && value.length > 0 && value.length <= maximum;
|
|
373
|
+
}
|
|
374
|
+
function terminalConversationStatus(value) {
|
|
375
|
+
return ['SUCCEEDED', 'FAILED', 'CANCELLED', 'INTERRUPTED', 'LOST'].includes(value);
|
|
376
|
+
}
|
|
377
|
+
function isString(value) {
|
|
378
|
+
return value !== null;
|
|
379
|
+
}
|
|
380
|
+
function record(value) {
|
|
381
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
382
|
+
return {};
|
|
383
|
+
return value;
|
|
384
|
+
}
|
|
385
|
+
function deduplicateNativeSessions(sessions) {
|
|
386
|
+
return [...new Map(sessions.map((session) => [session.id, session])).values()];
|
|
387
|
+
}
|
|
388
|
+
function isCleanupSkip(error) {
|
|
389
|
+
return (error instanceof Error &&
|
|
390
|
+
(error.message === 'SESSION_ACTIVE' ||
|
|
391
|
+
error.message === 'SESSION_NOT_FOUND' ||
|
|
392
|
+
error.message === 'SESSION_QUEUE_NOT_EMPTY' ||
|
|
393
|
+
error.message === 'SESSION_WATCHING' ||
|
|
394
|
+
error.message === 'NATIVE_TRANSCRIPT_UNAVAILABLE'));
|
|
395
|
+
}
|
|
396
|
+
function cleanupFailureDiagnostic(error) {
|
|
397
|
+
const record = error !== null && typeof error === 'object' ? error : {};
|
|
398
|
+
const code = typeof record.code === 'string' ? record.code : undefined;
|
|
399
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
400
|
+
return {
|
|
401
|
+
errorCode: (code ?? 'WORKSPACE_SESSION_CLEANUP_DELETE_FAILED').slice(0, 80),
|
|
402
|
+
error: message.slice(0, 500)
|
|
403
|
+
};
|
|
404
|
+
}
|