@myagentroam/node 0.9.8 → 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/dist/capabilities.js +2 -92
  2. package/dist/claude-agent-sdk.js +2 -330
  3. package/dist/claude-channel.js +2 -44
  4. package/dist/codex-app-server.js +2 -503
  5. package/dist/config.js +2 -56
  6. package/dist/connector/node-connector-options.js +2 -1
  7. package/dist/connector/node-operation-router.js +2 -22
  8. package/dist/connector.js +2 -841
  9. package/dist/control-outbound-scheduler.js +2 -154
  10. package/dist/database.js +2 -1418
  11. package/dist/event-buffer.js +2 -19
  12. package/dist/fake-runner.js +2 -129
  13. package/dist/health.js +2 -3
  14. package/dist/main.js +2 -54
  15. package/dist/migrations/v001.js +3 -144
  16. package/dist/migrations/v002.js +2 -143
  17. package/dist/migrations/v003.js +2 -44
  18. package/dist/migrations/v004.js +34 -30
  19. package/dist/native-jsonl-reader.js +2 -186
  20. package/dist/native-session-history.js +2 -1119
  21. package/dist/opencode-runtime.js +2 -80
  22. package/dist/opencode-server.js +2 -263
  23. package/dist/operational.js +2 -122
  24. package/dist/process-tree.js +2 -18
  25. package/dist/rotating-log.js +2 -67
  26. package/dist/runner/abstract-runner.js +2 -232
  27. package/dist/runner/claude/managed-run-controller.js +2 -345
  28. package/dist/runner/claude-code-runner.js +2 -303
  29. package/dist/runner/codex/composer-image-markers.js +2 -0
  30. package/dist/runner/codex/conversation-parser.js +2 -861
  31. package/dist/runner/codex/managed-run-controller.js +2 -460
  32. package/dist/runner/codex-runner.js +2 -628
  33. package/dist/runner/fake-test-runner.js +2 -47
  34. package/dist/runner/opencode/conversation-parser.js +2 -221
  35. package/dist/runner/opencode/managed-run-controller.js +2 -537
  36. package/dist/runner/opencode-runner.js +2 -448
  37. package/dist/runner/runner-registry.js +2 -90
  38. package/dist/runner-command-engine.js +2 -70
  39. package/dist/runner-profiles.js +2 -215
  40. package/dist/runner-usage.js +2 -190
  41. package/dist/runtime-command-detector.js +2 -73
  42. package/dist/runtime-state.js +2 -973
  43. package/dist/service/attachment-domain-state.js +2 -7
  44. package/dist/service/conversation-history-service.js +2 -457
  45. package/dist/service/conversation-segment-service.js +2 -162
  46. package/dist/service/external-session-resume-service.js +2 -118
  47. package/dist/service/fake-managed-run-service.js +2 -60
  48. package/dist/service/managed-runner-session-service.js +2 -35
  49. package/dist/service/mcp-installation-verifier.js +2 -87
  50. package/dist/service/mcp-node-operation-service.js +2 -90
  51. package/dist/service/mcp-package-installer.js +2 -136
  52. package/dist/service/native-session-projection-service.js +2 -280
  53. package/dist/service/native-session-watch-service.js +2 -383
  54. package/dist/service/node-connection-lifecycle-service.js +2 -83
  55. package/dist/service/node-control-channel.js +2 -85
  56. package/dist/service/node-control-message-service.js +2 -107
  57. package/dist/service/node-request-service.js +2 -52
  58. package/dist/service/node-run-event-bridge.js +2 -83
  59. package/dist/service/node-terminal-channel.js +2 -182
  60. package/dist/service/node-upgrade-coordinator.js +2 -137
  61. package/dist/service/node-workspace-coordinator.js +2 -70
  62. package/dist/service/recent-run-projection-service.js +2 -0
  63. package/dist/service/run-attachment-service.js +2 -194
  64. package/dist/service/run-domain-state.js +2 -4
  65. package/dist/service/run-event-service.js +2 -193
  66. package/dist/service/run-workbench-service.js +2 -104
  67. package/dist/service/runner-channel-message-service.js +2 -20
  68. package/dist/service/runner-interaction-service.js +2 -243
  69. package/dist/service/runner-service.js +2 -71
  70. package/dist/service/session-catalog-service.js +2 -224
  71. package/dist/service/session-command-service.js +2 -76
  72. package/dist/service/session-context-service.js +2 -101
  73. package/dist/service/session-domain-state.js +2 -9
  74. package/dist/service/session-identity-service.js +2 -86
  75. package/dist/service/session-lifecycle-service.js +2 -240
  76. package/dist/service/session-message-service.js +2 -173
  77. package/dist/service/session-presentation-service.js +2 -43
  78. package/dist/service/session-query-service.js +2 -82
  79. package/dist/service/skill-directory-service.js +2 -238
  80. package/dist/service/skill-install-service.js +2 -434
  81. package/dist/service/skill-node-operation-service.js +2 -206
  82. package/dist/service/terminal-relay-state.js +2 -3
  83. package/dist/service/terminal-service.js +2 -52
  84. package/dist/service/workbench-event-service.js +2 -19
  85. package/dist/service/workbench-manifest-service.js +2 -69
  86. package/dist/service/workspace-change-service.js +2 -86
  87. package/dist/service/workspace-content-search-service.js +2 -477
  88. package/dist/service/workspace-domain-state.js +2 -41
  89. package/dist/service/workspace-file-service.js +2 -122
  90. package/dist/service/workspace-git-exclude-service.js +2 -119
  91. package/dist/service/workspace-queue-workbench-service.js +2 -304
  92. package/dist/service/workspace-service.js +2 -69
  93. package/dist/service/workspace-session-service.js +2 -139
  94. package/dist/service/workspace-upload-service.js +2 -262
  95. package/dist/service/workspace-watch-service.js +2 -146
  96. package/dist/service/workspace-workbench-service.js +2 -405
  97. package/dist/service.js +2 -38
  98. package/dist/storage.js +2 -32
  99. package/dist/supervisor.js +2 -136
  100. package/dist/terminal.js +2 -416
  101. package/dist/util/node-operation-parsers.js +2 -382
  102. package/dist/util/personal-instructions.js +2 -31
  103. package/dist/util/runner-error.js +2 -52
  104. package/dist/util/runner-native-session-parsers.js +2 -490
  105. package/dist/util/safe-error.js +2 -5
  106. package/dist/util/secret-environment.js +2 -25
  107. package/dist/workspace.js +2 -1519
  108. package/package.json +3 -3
  109. package/dist/capabilities.d.ts +0 -12
  110. package/dist/claude-agent-sdk.d.ts +0 -92
  111. package/dist/claude-channel.d.ts +0 -28
  112. package/dist/codex-app-server.d.ts +0 -133
  113. package/dist/config.d.ts +0 -18
  114. package/dist/connector/node-connector-options.d.ts +0 -27
  115. package/dist/connector/node-operation-router.d.ts +0 -9
  116. package/dist/connector.d.ts +0 -93
  117. package/dist/control-outbound-scheduler.d.ts +0 -29
  118. package/dist/database.d.ts +0 -305
  119. package/dist/event-buffer.d.ts +0 -9
  120. package/dist/fake-runner.d.ts +0 -42
  121. package/dist/health.d.ts +0 -4
  122. package/dist/main.d.ts +0 -2
  123. package/dist/migrations/v001.d.ts +0 -3
  124. package/dist/migrations/v002.d.ts +0 -4
  125. package/dist/migrations/v003.d.ts +0 -4
  126. package/dist/migrations/v004.d.ts +0 -4
  127. package/dist/native-jsonl-reader.d.ts +0 -35
  128. package/dist/native-session-history.d.ts +0 -126
  129. package/dist/opencode-runtime.d.ts +0 -33
  130. package/dist/opencode-server.d.ts +0 -49
  131. package/dist/operational.d.ts +0 -39
  132. package/dist/process-tree.d.ts +0 -9
  133. package/dist/rotating-log.d.ts +0 -17
  134. package/dist/runner/abstract-runner.d.ts +0 -172
  135. package/dist/runner/claude/managed-run-controller.d.ts +0 -51
  136. package/dist/runner/claude-code-runner.d.ts +0 -72
  137. package/dist/runner/codex/conversation-parser.d.ts +0 -59
  138. package/dist/runner/codex/managed-run-controller.d.ts +0 -90
  139. package/dist/runner/codex-runner.d.ts +0 -103
  140. package/dist/runner/fake-test-runner.d.ts +0 -26
  141. package/dist/runner/opencode/conversation-parser.d.ts +0 -31
  142. package/dist/runner/opencode/managed-run-controller.d.ts +0 -82
  143. package/dist/runner/opencode-runner.d.ts +0 -71
  144. package/dist/runner/runner-registry.d.ts +0 -19
  145. package/dist/runner-command-engine.d.ts +0 -28
  146. package/dist/runner-profiles.d.ts +0 -15
  147. package/dist/runner-usage.d.ts +0 -33
  148. package/dist/runtime-command-detector.d.ts +0 -3
  149. package/dist/runtime-state.d.ts +0 -169
  150. package/dist/service/attachment-domain-state.d.ts +0 -7
  151. package/dist/service/conversation-history-service.d.ts +0 -43
  152. package/dist/service/conversation-segment-service.d.ts +0 -20
  153. package/dist/service/external-session-resume-service.d.ts +0 -34
  154. package/dist/service/fake-managed-run-service.d.ts +0 -28
  155. package/dist/service/managed-runner-session-service.d.ts +0 -12
  156. package/dist/service/mcp-installation-verifier.d.ts +0 -9
  157. package/dist/service/mcp-node-operation-service.d.ts +0 -11
  158. package/dist/service/mcp-package-installer.d.ts +0 -8
  159. package/dist/service/native-session-projection-service.d.ts +0 -52
  160. package/dist/service/native-session-watch-service.d.ts +0 -62
  161. package/dist/service/node-connection-lifecycle-service.d.ts +0 -35
  162. package/dist/service/node-control-channel.d.ts +0 -32
  163. package/dist/service/node-control-message-service.d.ts +0 -27
  164. package/dist/service/node-request-service.d.ts +0 -14
  165. package/dist/service/node-run-event-bridge.d.ts +0 -40
  166. package/dist/service/node-terminal-channel.d.ts +0 -29
  167. package/dist/service/node-upgrade-coordinator.d.ts +0 -29
  168. package/dist/service/node-workspace-coordinator.d.ts +0 -29
  169. package/dist/service/run-attachment-service.d.ts +0 -38
  170. package/dist/service/run-domain-state.d.ts +0 -4
  171. package/dist/service/run-event-service.d.ts +0 -33
  172. package/dist/service/run-workbench-service.d.ts +0 -25
  173. package/dist/service/runner-channel-message-service.d.ts +0 -13
  174. package/dist/service/runner-interaction-service.d.ts +0 -39
  175. package/dist/service/runner-service.d.ts +0 -46
  176. package/dist/service/session-catalog-service.d.ts +0 -45
  177. package/dist/service/session-command-service.d.ts +0 -24
  178. package/dist/service/session-context-service.d.ts +0 -35
  179. package/dist/service/session-domain-state.d.ts +0 -9
  180. package/dist/service/session-identity-service.d.ts +0 -24
  181. package/dist/service/session-lifecycle-service.d.ts +0 -31
  182. package/dist/service/session-message-service.d.ts +0 -33
  183. package/dist/service/session-presentation-service.d.ts +0 -34
  184. package/dist/service/session-query-service.d.ts +0 -35
  185. package/dist/service/skill-directory-service.d.ts +0 -20
  186. package/dist/service/skill-install-service.d.ts +0 -21
  187. package/dist/service/skill-node-operation-service.d.ts +0 -44
  188. package/dist/service/terminal-relay-state.d.ts +0 -6
  189. package/dist/service/terminal-service.d.ts +0 -12
  190. package/dist/service/workbench-event-service.d.ts +0 -9
  191. package/dist/service/workbench-manifest-service.d.ts +0 -90
  192. package/dist/service/workspace-change-service.d.ts +0 -9
  193. package/dist/service/workspace-content-search-service.d.ts +0 -14
  194. package/dist/service/workspace-domain-state.d.ts +0 -79
  195. package/dist/service/workspace-file-service.d.ts +0 -18
  196. package/dist/service/workspace-git-exclude-service.d.ts +0 -4
  197. package/dist/service/workspace-queue-workbench-service.d.ts +0 -86
  198. package/dist/service/workspace-service.d.ts +0 -15
  199. package/dist/service/workspace-session-service.d.ts +0 -23
  200. package/dist/service/workspace-upload-service.d.ts +0 -39
  201. package/dist/service/workspace-watch-service.d.ts +0 -23
  202. package/dist/service/workspace-workbench-service.d.ts +0 -58
  203. package/dist/service.d.ts +0 -4
  204. package/dist/storage.d.ts +0 -2
  205. package/dist/supervisor.d.ts +0 -1
  206. package/dist/terminal.d.ts +0 -133
  207. package/dist/util/node-operation-parsers.d.ts +0 -92
  208. package/dist/util/personal-instructions.d.ts +0 -2
  209. package/dist/util/runner-error.d.ts +0 -6
  210. package/dist/util/runner-native-session-parsers.d.ts +0 -74
  211. package/dist/util/safe-error.d.ts +0 -2
  212. package/dist/util/secret-environment.d.ts +0 -1
  213. package/dist/workspace.d.ts +0 -217
package/dist/database.js CHANGED
@@ -1,1418 +1,2 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { closeSync, existsSync, mkdirSync, openSync, rmSync } from 'node:fs';
3
- import { dirname } from 'node:path';
4
- import { DatabaseSync } from 'node:sqlite';
5
- import { runnerDefaultConfigurationSchema } from '@myagentroam/protocol';
6
- import { mcpCatalogEntrySchema, mcpInstallationConfigurationSchema, mcpRuntimeDescriptorSchema } from '@myagentroam/protocol';
7
- import { assertNodeSchema, NODE_SCHEMA_V1 } from './migrations/v001.js';
8
- import { assertNodeSchemaV2, migrateNodeSchemaV2 } from './migrations/v002.js';
9
- import { assertNodeSchemaV3, migrateNodeSchemaV3 } from './migrations/v003.js';
10
- import { assertNodeSchemaV4, migrateNodeSchemaV4, NODE_SCHEMA_VERSION_V4 } from './migrations/v004.js';
11
- const NODE_SCHEMA_VERSION = NODE_SCHEMA_VERSION_V4;
12
- export class NodeDatabase {
13
- now;
14
- activeWorkspaceLeaseCount() {
15
- const row = this.raw
16
- .prepare("SELECT COUNT(*) AS count FROM workspace_leases WHERE state IN ('ACTIVE', 'SUSPECT')")
17
- .get();
18
- return row.count;
19
- }
20
- raw;
21
- constructor(path, nodeId, now = Date.now) {
22
- this.now = now;
23
- this.nodeIdProvider = typeof nodeId === 'string' ? () => nodeId : nodeId;
24
- if (path !== ':memory:')
25
- mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
26
- const releaseMigrationLock = acquireNodeMigrationLock(path);
27
- try {
28
- this.raw = new DatabaseSync(path, {
29
- enableForeignKeyConstraints: true,
30
- timeout: 5_000,
31
- defensive: true
32
- });
33
- this.raw.exec('PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000;');
34
- migrate(this.raw);
35
- initializeEphemeralRuntimeTables(this.raw);
36
- }
37
- finally {
38
- releaseMigrationLock();
39
- }
40
- }
41
- close() {
42
- this.raw.close();
43
- }
44
- getRunnerDefaults() {
45
- const rows = this.raw
46
- .prepare('SELECT runner, model, effort, access FROM runner_defaults ORDER BY runner')
47
- .all();
48
- return rows.flatMap((row) => {
49
- const parsed = runnerDefaultConfigurationSchema.safeParse({
50
- runner: stringValue(row, 'runner'),
51
- model: stringValue(row, 'model'),
52
- effort: stringValue(row, 'effort'),
53
- access: stringValue(row, 'access')
54
- });
55
- return parsed.success ? [parsed.data] : [];
56
- });
57
- }
58
- saveRunnerDefaults(input) {
59
- this.raw
60
- .prepare(`INSERT INTO runner_defaults (runner, model, effort, access)
61
- VALUES (?, ?, ?, ?)
62
- ON CONFLICT(runner) DO UPDATE SET
63
- model = excluded.model, effort = excluded.effort,
64
- access = excluded.access`)
65
- .run(input.runner, input.model, input.effort, input.access);
66
- return input;
67
- }
68
- listMcpInstallations(targetKind, targetId = '') {
69
- const rows = this.raw
70
- .prepare(`SELECT target_kind,target_id,catalog_entry_id,server_name,display_name,version,
71
- enabled,runtime,configuration,installed_at
72
- FROM mcp_installations WHERE target_kind=? AND target_id=? ORDER BY display_name,server_name`)
73
- .all(targetKind, targetKind === 'NODE' ? '' : targetId);
74
- return rows.map(mcpInstallation);
75
- }
76
- saveMcpInstallation(input) {
77
- const entry = mcpCatalogEntrySchema.parse(input.entry);
78
- const configuration = mcpInstallationConfigurationSchema.parse(input.configuration);
79
- const targetId = input.targetKind === 'NODE' ? '' : (input.targetId ?? '');
80
- if (input.targetKind === 'WORKSPACE' && this.getWorkspace(targetId) === undefined)
81
- throw new Error('WORKSPACE_NOT_FOUND');
82
- const installedAt = this.now();
83
- this.raw
84
- .prepare(`INSERT INTO mcp_installations
85
- (target_kind,target_id,catalog_entry_id,server_name,display_name,version,enabled,runtime,configuration,installed_at)
86
- VALUES (?,?,?,?,?,?,?,?,?,?)
87
- ON CONFLICT(target_kind,target_id,server_name) DO UPDATE SET
88
- catalog_entry_id=excluded.catalog_entry_id,display_name=excluded.display_name,
89
- version=excluded.version,enabled=excluded.enabled,runtime=excluded.runtime,
90
- configuration=excluded.configuration,installed_at=excluded.installed_at`)
91
- .run(input.targetKind, targetId, entry.id, entry.serverName, entry.displayName, entry.version, input.enabled ? 1 : 0, JSON.stringify(entry.runtime), JSON.stringify(configuration), installedAt);
92
- return {
93
- targetKind: input.targetKind,
94
- targetId,
95
- catalogEntryId: entry.id,
96
- serverName: entry.serverName,
97
- displayName: entry.displayName,
98
- version: entry.version,
99
- enabled: input.enabled,
100
- runtime: entry.runtime,
101
- configuration,
102
- installedAt
103
- };
104
- }
105
- removeMcpInstallation(targetKind, targetId, serverName) {
106
- return (Number(this.raw
107
- .prepare('DELETE FROM mcp_installations WHERE target_kind=? AND target_id=? AND server_name=?')
108
- .run(targetKind, targetKind === 'NODE' ? '' : targetId, serverName).changes) > 0);
109
- }
110
- effectiveMcpInstallations(workspaceId) {
111
- const effective = new Map(this.listMcpInstallations('NODE').map((installation) => [
112
- installation.serverName,
113
- installation
114
- ]));
115
- for (const installation of this.listMcpInstallations('WORKSPACE', workspaceId))
116
- effective.set(installation.serverName, installation);
117
- return [...effective.values()].filter((installation) => installation.enabled);
118
- }
119
- /**
120
- * Stores only terminal lifecycle metadata. PTY input/output must remain in
121
- * the Node-local bounded replay buffer and must never be passed here.
122
- */
123
- saveTerminalSession(input) {
124
- this.raw
125
- .prepare(`INSERT INTO terminal_sessions
126
- (id, workspace_id, profile_id, state, exit_code, rows, cols, latest_sequence, created_at, updated_at)
127
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
128
- ON CONFLICT(id) DO UPDATE SET workspace_id = excluded.workspace_id, profile_id = excluded.profile_id, state = excluded.state,
129
- exit_code = excluded.exit_code, rows = excluded.rows, cols = excluded.cols,
130
- latest_sequence = excluded.latest_sequence, updated_at = excluded.updated_at`)
131
- .run(input.id, input.workspaceId, input.profileId, input.state, input.exitCode, input.rows, input.cols, input.latestSequence, input.createdAt, input.updatedAt);
132
- return this.getTerminalSession(input.id);
133
- }
134
- getTerminalSession(id) {
135
- const row = this.raw
136
- .prepare(`SELECT id, workspace_id, profile_id, state, exit_code, rows, cols, latest_sequence, created_at, updated_at
137
- FROM terminal_sessions WHERE id = ?`)
138
- .get(id);
139
- return row === undefined ? undefined : terminalSession(row);
140
- }
141
- listTerminalSessions() {
142
- return this.raw
143
- .prepare(`SELECT id, workspace_id, profile_id, state, exit_code, rows, cols, latest_sequence, created_at, updated_at
144
- FROM terminal_sessions WHERE state = 'RUNNING' ORDER BY created_at ASC, id ASC`)
145
- .all()
146
- .map((row) => terminalSession(row));
147
- }
148
- /** A restart cannot safely reattach an orphaned PTY, so record it as closed. */
149
- closeRunningTerminalSessions() {
150
- this.raw
151
- .prepare("UPDATE terminal_sessions SET state = 'CLOSED', updated_at = ? WHERE state = 'RUNNING'")
152
- .run(this.now());
153
- }
154
- saveWorkspace(input) {
155
- const current = this.raw.prepare('SELECT id FROM workspaces WHERE path = ?').get(input.path);
156
- const workspace = {
157
- id: current === undefined ? (input.id ?? randomUUID()) : stringValue(current, 'id'),
158
- path: input.path,
159
- kind: input.kind,
160
- gitSummary: input.gitSummary
161
- };
162
- const timestamp = this.now();
163
- this.raw
164
- .prepare(`INSERT INTO workspaces (id, path, kind, git_summary, created_at, updated_at)
165
- VALUES (?, ?, ?, ?, ?, ?)
166
- ON CONFLICT(path) DO UPDATE SET kind = excluded.kind,
167
- git_summary = excluded.git_summary, updated_at = excluded.updated_at`)
168
- .run(workspace.id, workspace.path, workspace.kind, workspace.gitSummary === null ? null : JSON.stringify(workspace.gitSummary), timestamp, timestamp);
169
- return workspace;
170
- }
171
- listWorkspaces() {
172
- return this.raw
173
- .prepare('SELECT id, path, kind, git_summary FROM workspaces ORDER BY created_at ASC')
174
- .all()
175
- .map((row) => workspace(row));
176
- }
177
- getWorkspace(id) {
178
- const row = this.raw
179
- .prepare('SELECT id, path, kind, git_summary FROM workspaces WHERE id = ?')
180
- .get(id);
181
- return row === undefined ? undefined : workspace(row);
182
- }
183
- /** Unregisters a Workspace registration without deleting its local directory. */
184
- removeWorkspace(id) {
185
- const current = this.getWorkspace(id);
186
- if (current === undefined)
187
- throw new Error('WORKSPACE_NOT_FOUND');
188
- this.raw.exec('BEGIN');
189
- try {
190
- // Session deletion cascades their runs, conversation and attachments. The workspace
191
- // record itself never represents a filesystem deletion.
192
- this.raw.prepare('DELETE FROM agent_sessions WHERE workspace_id = ?').run(id);
193
- this.raw.prepare('DELETE FROM legacy_agent_sessions WHERE workspace_id = ?').run(id);
194
- this.raw
195
- .prepare("DELETE FROM mcp_installations WHERE target_kind='WORKSPACE' AND target_id = ?")
196
- .run(id);
197
- this.raw.prepare('DELETE FROM workspaces WHERE id = ?').run(id);
198
- this.raw.exec('COMMIT');
199
- return current;
200
- }
201
- catch (error) {
202
- this.raw.exec('ROLLBACK');
203
- throw error;
204
- }
205
- }
206
- createAgentSession(input) {
207
- if (this.getWorkspace(input.workspaceId) === undefined)
208
- throw new Error('WORKSPACE_NOT_FOUND');
209
- const session = {
210
- id: randomUUID(),
211
- nodeId: this.nodeIdProvider(),
212
- workspaceId: input.workspaceId,
213
- runner: input.runner,
214
- externalSessionId: input.externalSessionId ?? null,
215
- nativeControl: input.externalSessionId === undefined ? 'MAR_MANAGED' : (input.nativeControl ?? 'EXTERNAL'),
216
- channelToken: null,
217
- cwd: input.cwd,
218
- model: optionValue(input.model),
219
- effort: optionValue(input.effort),
220
- access: optionValue(input.access),
221
- customTitle: null,
222
- runnerTitle: input.title?.trim().slice(0, 160) || null,
223
- pinnedAt: null,
224
- titleSource: input.title?.trim() ? 'RUNNER' : 'AUTO',
225
- lastActivityAt: this.now(),
226
- createdAt: this.now()
227
- };
228
- this.raw
229
- .prepare(`INSERT INTO legacy_agent_sessions
230
- (id, workspace_id, runner, external_session_id, native_control, channel_token, cwd, model, effort, access, custom_title, runner_title, pinned_at, title_source, last_activity_at, created_at, updated_at)
231
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
232
- .run(session.id, session.workspaceId, session.runner, session.externalSessionId, session.nativeControl, session.channelToken, session.cwd, session.model, session.effort, session.access, session.customTitle, session.runnerTitle, session.pinnedAt, session.titleSource, session.lastActivityAt, session.createdAt, session.createdAt);
233
- return session;
234
- }
235
- getAgentSession(id) {
236
- const row = this.raw
237
- .prepare('SELECT id, workspace_id, runner, external_session_id, native_control, channel_token, cwd, model, effort, access, custom_title, runner_title, pinned_at, title_source, last_activity_at, created_at FROM legacy_agent_sessions WHERE id = ?')
238
- .get(id);
239
- return row === undefined ? undefined : session(row, this.nodeIdProvider());
240
- }
241
- updateAgentSessionConfiguration(input) {
242
- const result = this.raw
243
- .prepare(`UPDATE legacy_agent_sessions
244
- SET model = ?, effort = ?, access = ?, updated_at = ?
245
- WHERE id = ?`)
246
- .run(input.model, input.effort, input.access, this.now(), input.sessionId);
247
- if (Number(result.changes) === 0)
248
- throw new Error('SESSION_NOT_FOUND');
249
- return this.getAgentSession(input.sessionId);
250
- }
251
- listAgentSessions() {
252
- return this.raw
253
- .prepare('SELECT id, workspace_id, runner, external_session_id, native_control, channel_token, cwd, model, effort, access, custom_title, runner_title, pinned_at, title_source, last_activity_at, created_at FROM legacy_agent_sessions ORDER BY pinned_at IS NULL, pinned_at DESC, last_activity_at DESC, id DESC')
254
- .all()
255
- .map((row) => session(row, this.nodeIdProvider()));
256
- }
257
- findAgentSessionByExternalSession(runner, externalSessionId) {
258
- const row = this.raw
259
- .prepare(`SELECT id, workspace_id, runner, external_session_id, native_control, channel_token, cwd, model, effort, access, custom_title, runner_title, pinned_at, title_source, last_activity_at, created_at
260
- FROM legacy_agent_sessions WHERE runner = ? AND external_session_id = ?`)
261
- .get(runner, externalSessionId);
262
- return row === undefined ? undefined : session(row, this.nodeIdProvider());
263
- }
264
- setNativeControl(sessionId, nativeControl) {
265
- const result = this.raw
266
- .prepare('UPDATE legacy_agent_sessions SET native_control = ?, updated_at = ? WHERE id = ?')
267
- .run(nativeControl, this.now(), sessionId);
268
- if (Number(result.changes) === 0)
269
- throw new Error('SESSION_NOT_FOUND');
270
- }
271
- setExternalSessionId(sessionId, externalSessionId) {
272
- if (externalSessionId.length === 0)
273
- throw new Error('SESSION_EXTERNAL_ID_INVALID');
274
- const result = this.raw
275
- .prepare("UPDATE legacy_agent_sessions SET external_session_id = ?, native_control = 'MAR_MANAGED', updated_at = ? WHERE id = ?")
276
- .run(externalSessionId, this.now(), sessionId);
277
- if (Number(result.changes) === 0)
278
- throw new Error('SESSION_NOT_FOUND');
279
- }
280
- setChannelToken(sessionId, token) {
281
- if (token.length < 16)
282
- throw new Error('SESSION_CHANNEL_TOKEN_INVALID');
283
- const result = this.raw
284
- .prepare('UPDATE legacy_agent_sessions SET channel_token = ?, updated_at = ? WHERE id = ?')
285
- .run(token, this.now(), sessionId);
286
- if (Number(result.changes) === 0)
287
- throw new Error('SESSION_NOT_FOUND');
288
- }
289
- updateSessionMetadata(input) {
290
- const current = this.getAgentSession(input.sessionId);
291
- if (current === undefined)
292
- throw new Error('SESSION_NOT_FOUND');
293
- const title = input.customTitle === undefined ? current.customTitle : input.customTitle?.trim() || null;
294
- if (title !== null && title.length > 160)
295
- throw new Error('SESSION_TITLE_INVALID');
296
- const pinnedAt = input.pinned === undefined ? current.pinnedAt : input.pinned ? this.now() : null;
297
- const titleSource = title === null ? 'AUTO' : 'CUSTOM';
298
- this.raw
299
- .prepare('UPDATE legacy_agent_sessions SET custom_title = ?, pinned_at = ?, title_source = ?, updated_at = ? WHERE id = ?')
300
- .run(title, pinnedAt, titleSource, this.now(), input.sessionId);
301
- return this.getAgentSession(input.sessionId);
302
- }
303
- getNativeSessionMetadata(runner, externalSessionId, workspaceId) {
304
- const row = this.raw
305
- .prepare('SELECT pin_order, metadata FROM agent_sessions WHERE id = ? AND runner = ? AND workspace_id = ?')
306
- .get(externalSessionId, runner, workspaceId);
307
- if (row === undefined)
308
- return undefined;
309
- return {
310
- ...sessionMetadata(row),
311
- pinnedAt: row['pin_order'] === null ? null : 1,
312
- pinOrder: nullableNumber(row, 'pin_order')
313
- };
314
- }
315
- saveNativeSessionMetadata(input) {
316
- const current = this.getNativeSessionMetadata(input.runner, input.externalSessionId, input.workspaceId);
317
- const customTitle = input.customTitle === undefined
318
- ? (current?.customTitle ?? null)
319
- : input.customTitle?.trim() || null;
320
- const runnerTitle = input.runnerTitle === undefined
321
- ? (current?.runnerTitle ?? null)
322
- : input.runnerTitle?.trim() || null;
323
- const runnerTitlePending = input.runnerTitlePending === undefined
324
- ? (current?.runnerTitlePending ?? false)
325
- : input.runnerTitlePending;
326
- if (customTitle !== null && customTitle.length > 160)
327
- throw new Error('SESSION_TITLE_INVALID');
328
- if (runnerTitle !== null && runnerTitle.length > 160)
329
- throw new Error('SESSION_TITLE_INVALID');
330
- let pinOrder = current?.pinOrder ?? null;
331
- const pinAtTop = input.pinned === true && pinOrder === null;
332
- if (pinAtTop)
333
- pinOrder = 0;
334
- else if (input.pinned === false)
335
- pinOrder = null;
336
- const model = input.model === undefined ? (current?.model ?? null) : input.model;
337
- const effort = input.effort === undefined ? (current?.effort ?? null) : input.effort;
338
- const access = input.access === undefined ? (current?.access ?? null) : input.access;
339
- const metadata = JSON.stringify({
340
- version: 1,
341
- customTitle,
342
- runnerTitle,
343
- runnerTitlePending,
344
- model,
345
- effort,
346
- access
347
- });
348
- this.raw.exec('BEGIN IMMEDIATE');
349
- try {
350
- if (pinAtTop)
351
- this.raw
352
- .prepare('UPDATE agent_sessions SET pin_order = pin_order + 1 WHERE workspace_id = ? AND pin_order IS NOT NULL')
353
- .run(input.workspaceId);
354
- this.raw
355
- .prepare(`INSERT INTO agent_sessions (id, workspace_id, runner, pin_order, metadata)
356
- VALUES (?, ?, ?, ?, ?)
357
- ON CONFLICT(id) DO UPDATE SET workspace_id = excluded.workspace_id,
358
- runner = excluded.runner, pin_order = excluded.pin_order, metadata = excluded.metadata`)
359
- .run(input.externalSessionId, input.workspaceId, input.runner, pinOrder, metadata);
360
- this.raw.exec('COMMIT');
361
- }
362
- catch (error) {
363
- this.raw.exec('ROLLBACK');
364
- throw error;
365
- }
366
- return {
367
- customTitle,
368
- runnerTitle,
369
- runnerTitlePending,
370
- pinnedAt: pinOrder === null ? null : 1,
371
- pinOrder,
372
- model,
373
- effort,
374
- access
375
- };
376
- }
377
- listSessionRecords(workspaceId) {
378
- return this.raw
379
- .prepare('SELECT id, workspace_id, runner, pin_order, metadata FROM agent_sessions WHERE workspace_id = ? ORDER BY pin_order IS NULL, pin_order, id')
380
- .all(workspaceId).map((row) => ({
381
- id: stringValue(row, 'id'),
382
- workspaceId: stringValue(row, 'workspace_id'),
383
- runner: stringValue(row, 'runner'),
384
- pinOrder: nullableNumber(row, 'pin_order'),
385
- metadata: {
386
- ...sessionMetadata(row),
387
- pinnedAt: row['pin_order'] === null ? null : 1,
388
- pinOrder: nullableNumber(row, 'pin_order')
389
- }
390
- }));
391
- }
392
- movePinnedSession(sessionId, direction) {
393
- const current = this.raw
394
- .prepare('SELECT workspace_id, pin_order FROM agent_sessions WHERE id = ?')
395
- .get(sessionId);
396
- if (current === undefined || current['pin_order'] === null)
397
- throw new Error('SESSION_NOT_PINNED');
398
- const order = numberValue(current, 'pin_order');
399
- const adjacent = this.raw
400
- .prepare(direction === 'up'
401
- ? 'SELECT id, pin_order FROM agent_sessions WHERE workspace_id = ? AND pin_order < ? ORDER BY pin_order DESC LIMIT 1'
402
- : 'SELECT id, pin_order FROM agent_sessions WHERE workspace_id = ? AND pin_order > ? ORDER BY pin_order ASC LIMIT 1')
403
- .get(stringValue(current, 'workspace_id'), order);
404
- if (adjacent === undefined)
405
- return;
406
- this.raw.exec('BEGIN IMMEDIATE');
407
- try {
408
- this.raw
409
- .prepare('UPDATE agent_sessions SET pin_order = ? WHERE id = ?')
410
- .run(order, stringValue(adjacent, 'id'));
411
- this.raw
412
- .prepare('UPDATE agent_sessions SET pin_order = ? WHERE id = ?')
413
- .run(numberValue(adjacent, 'pin_order'), sessionId);
414
- this.raw.exec('COMMIT');
415
- }
416
- catch (error) {
417
- this.raw.exec('ROLLBACK');
418
- throw error;
419
- }
420
- }
421
- deleteSessionRecord(sessionId) {
422
- return (Number(this.raw.prepare('DELETE FROM agent_sessions WHERE id = ?').run(sessionId).changes) > 0);
423
- }
424
- /**
425
- * Replaces only transcript-derived, run-less history. Managed Run turns are
426
- * never touched by a vendor file scan.
427
- */
428
- syncNativeTranscript(sessionId, history) {
429
- const current = this.getAgentSession(sessionId);
430
- if (current === undefined)
431
- throw new Error('SESSION_NOT_FOUND');
432
- const checkpoint = this.raw
433
- .prepare('SELECT digest FROM native_session_checkpoints WHERE session_id = ?')
434
- .get(sessionId);
435
- if (checkpoint !== undefined && stringValue(checkpoint, 'digest') === history.digest)
436
- return false;
437
- const now = this.now();
438
- this.raw.exec('BEGIN IMMEDIATE');
439
- try {
440
- this.raw
441
- .prepare('DELETE FROM conversation_turns WHERE session_id = ? AND run_id IS NULL')
442
- .run(sessionId);
443
- for (const [index, item] of history.items.entries()) {
444
- if (item.kind !== 'message')
445
- continue;
446
- const turnId = randomUUID();
447
- const itemId = randomUUID();
448
- const createdAt = item.createdAt ?? now + index;
449
- this.raw
450
- .prepare(`INSERT INTO conversation_turns
451
- (id, session_id, run_id, user_item_id, status, started_at, completed_at, created_at, updated_at)
452
- VALUES (?, ?, NULL, ?, 'SUCCEEDED', ?, ?, ?, ?)`)
453
- .run(turnId, sessionId, item.role === 'USER' ? itemId : null, createdAt, createdAt, createdAt, now);
454
- this.raw
455
- .prepare(`INSERT INTO conversation_items
456
- (id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at, created_at, updated_at)
457
- VALUES (?, ?, ?, NULL, NULL, ?, 0, ?, 'COMPLETED', ?, ?, ?, ?, ?)`)
458
- .run(itemId, sessionId, turnId, index, item.role === 'USER' ? 'user_message' : 'assistant_message', JSON.stringify({ text: item.text, format: 'markdown', source: 'native-file' }), createdAt, createdAt, createdAt, now);
459
- this.recordConversationItemChange(sessionId, itemId, 0);
460
- }
461
- const runnerTitle = history.title?.trim().slice(0, 160) || current.runnerTitle;
462
- this.raw
463
- .prepare(`UPDATE legacy_agent_sessions
464
- SET runner_title = ?, title_source = CASE WHEN custom_title IS NULL THEN 'RUNNER' ELSE title_source END,
465
- last_activity_at = CASE WHEN ? > last_activity_at THEN ? ELSE last_activity_at END, updated_at = ?
466
- WHERE id = ?`)
467
- .run(runnerTitle, now, now, now, sessionId);
468
- this.raw
469
- .prepare(`INSERT INTO native_session_checkpoints (session_id, digest, updated_at)
470
- VALUES (?, ?, ?)
471
- ON CONFLICT(session_id) DO UPDATE SET digest = excluded.digest, updated_at = excluded.updated_at`)
472
- .run(sessionId, history.digest, now);
473
- this.raw.exec('COMMIT');
474
- return true;
475
- }
476
- catch (error) {
477
- this.raw.exec('ROLLBACK');
478
- throw error;
479
- }
480
- }
481
- createMessageRun(input) {
482
- const existing = this.raw
483
- .prepare(`SELECT r.id, r.session_id, r.workspace_id, r.runner, r.status, r.recovery_state, r.version,
484
- m.client_message_id, r.created_at, r.updated_at
485
- FROM agent_runs r JOIN session_messages m ON m.id = r.message_id
486
- WHERE m.session_id = ? AND m.client_message_id = ?`)
487
- .get(input.sessionId, input.clientMessageId);
488
- if (existing !== undefined)
489
- return { run: run(existing, this.nodeIdProvider()), created: false };
490
- const agentSession = this.getAgentSession(input.sessionId);
491
- if (agentSession === undefined)
492
- throw new Error('SESSION_NOT_FOUND');
493
- const attachments = normalizeAttachments(input.attachments ?? []);
494
- const value = {
495
- id: randomUUID(),
496
- sessionId: agentSession.id,
497
- nodeId: this.nodeIdProvider(),
498
- workspaceId: agentSession.workspaceId,
499
- runner: agentSession.runner,
500
- status: 'QUEUED',
501
- recoveryState: 'ACTIVE',
502
- version: 0,
503
- clientMessageId: input.clientMessageId,
504
- createdAt: this.now(),
505
- updatedAt: this.now()
506
- };
507
- this.raw.exec('BEGIN IMMEDIATE');
508
- try {
509
- const messageId = randomUUID();
510
- this.raw
511
- .prepare(`INSERT INTO session_messages (id, session_id, client_message_id, role, content, created_at)
512
- VALUES (?, ?, ?, 'USER', ?, ?)`)
513
- .run(messageId, input.sessionId, input.clientMessageId, input.content, value.createdAt);
514
- for (const attachment of attachments) {
515
- this.raw
516
- .prepare(`INSERT INTO message_attachments (id, message_id, name, mime, byte_size, data, created_at)
517
- VALUES (?, ?, ?, ?, ?, ?, ?)`)
518
- .run(randomUUID(), messageId, attachment.name, attachment.mime, attachment.data.length, attachment.data, value.createdAt);
519
- }
520
- this.raw
521
- .prepare(`INSERT INTO agent_runs
522
- (id, session_id, message_id, workspace_id, runner, status, recovery_state, version, created_at, updated_at)
523
- VALUES (?, ?, ?, ?, ?, ?, 'ACTIVE', 0, ?, ?)`)
524
- .run(value.id, value.sessionId, messageId, value.workspaceId, value.runner, value.status, value.createdAt, value.updatedAt);
525
- this.raw
526
- .prepare(`INSERT INTO workspace_leases (id, workspace_id, run_id, state, created_at, updated_at)
527
- VALUES (?, ?, ?, 'ACTIVE', ?, ?)`)
528
- .run(randomUUID(), value.workspaceId, value.id, value.createdAt, value.createdAt);
529
- const turnId = randomUUID();
530
- const userItemId = randomUUID();
531
- this.raw
532
- .prepare(`INSERT INTO conversation_turns
533
- (id, session_id, run_id, user_item_id, status, model, effort, access, started_at, created_at, updated_at)
534
- VALUES (?, ?, ?, ?, 'QUEUED', ?, ?, ?, NULL, ?, ?)`)
535
- .run(turnId, value.sessionId, value.id, userItemId, agentSession.model, agentSession.effort, agentSession.access, value.createdAt, value.createdAt);
536
- this.raw
537
- .prepare(`INSERT INTO conversation_items
538
- (id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at, created_at, updated_at)
539
- VALUES (?, ?, ?, ?, NULL, NULL, 0, 'user_message', 'COMPLETED', ?, ?, ?, ?, ?)`)
540
- .run(userItemId, value.sessionId, turnId, value.id, JSON.stringify({
541
- clientMessageId: input.clientMessageId,
542
- text: input.content,
543
- contexts: [],
544
- attachments: attachments.map(({ name, mime, data }) => ({
545
- name,
546
- mime,
547
- byteSize: data.length
548
- })),
549
- delivery: 'ACCEPTED'
550
- }), value.createdAt, value.createdAt, value.createdAt, value.createdAt);
551
- this.recordConversationItemChange(value.sessionId, userItemId, 0);
552
- this.raw
553
- .prepare('UPDATE legacy_agent_sessions SET last_activity_at = ?, updated_at = ? WHERE id = ?')
554
- .run(value.createdAt, value.createdAt, value.sessionId);
555
- this.raw.exec('COMMIT');
556
- return { run: value, created: true };
557
- }
558
- catch (error) {
559
- this.raw.exec('ROLLBACK');
560
- if (isConstraint(error))
561
- throw new Error('WORKSPACE_BUSY');
562
- throw error;
563
- }
564
- }
565
- getRun(id) {
566
- const row = this.raw
567
- .prepare(`SELECT r.id, r.session_id, r.workspace_id, r.runner, r.status, r.recovery_state, r.version,
568
- m.client_message_id, r.created_at, r.updated_at
569
- FROM agent_runs r JOIN session_messages m ON m.id = r.message_id WHERE r.id = ?`)
570
- .get(id);
571
- return row === undefined ? undefined : run(row, this.nodeIdProvider());
572
- }
573
- listRunsForSession(sessionId) {
574
- if (this.getAgentSession(sessionId) === undefined)
575
- throw new Error('SESSION_NOT_FOUND');
576
- return this.raw
577
- .prepare(`SELECT r.id, r.session_id, r.workspace_id, r.runner, r.status, r.recovery_state, r.version,
578
- m.client_message_id, r.created_at, r.updated_at
579
- FROM agent_runs r JOIN session_messages m ON m.id = r.message_id
580
- WHERE r.session_id = ? ORDER BY r.created_at DESC, r.id DESC`)
581
- .all(sessionId)
582
- .map((row) => run(row, this.nodeIdProvider()));
583
- }
584
- getRunInput(id) {
585
- const row = this.raw
586
- .prepare('SELECT m.content FROM session_messages m JOIN agent_runs r ON r.message_id = m.id WHERE r.id = ?')
587
- .get(id);
588
- return row === undefined ? undefined : stringValue(row, 'content');
589
- }
590
- transitionRun(runId, next) {
591
- const current = this.getRun(runId);
592
- if (current === undefined)
593
- throw new Error('RUN_NOT_FOUND');
594
- if (current.recoveryState === 'LOST')
595
- throw new Error('RUN_LOST');
596
- if (!transitionAllowed(current.status, next))
597
- throw new Error('RUN_STATE_INVALID');
598
- const changed = this.raw
599
- .prepare('UPDATE agent_runs SET status = ?, version = version + 1, updated_at = ? WHERE id = ? AND version = ?')
600
- .run(next, this.now(), runId, current.version);
601
- if (Number(changed.changes) === 0)
602
- throw new Error('RUN_VERSION_CONFLICT');
603
- if (terminal(next))
604
- this.releaseLease(runId);
605
- return this.getRun(runId);
606
- }
607
- appendRunEvent(input) {
608
- if (this.getRun(input.runId) === undefined)
609
- throw new Error('RUN_NOT_FOUND');
610
- const row = this.raw
611
- .prepare('SELECT MAX(sequence) AS sequence FROM run_events WHERE run_id = ?')
612
- .get(input.runId);
613
- const lastSequence = row['sequence'] === null ? 0 : numberValue(row, 'sequence');
614
- if (input.sequence > lastSequence + 1)
615
- throw new Error('EVENT_SEQUENCE_GAP');
616
- const timestamp = this.now();
617
- const result = this.raw
618
- .prepare(`INSERT INTO run_events (run_id, sequence, event_type, payload, created_at)
619
- VALUES (?, ?, ?, ?, ?) ON CONFLICT(run_id, sequence) DO NOTHING`)
620
- .run(input.runId, input.sequence, input.eventType, JSON.stringify(input.payload ?? null), timestamp);
621
- if (Number(result.changes) === 0)
622
- return undefined;
623
- if (input.status !== undefined)
624
- this.transitionRun(input.runId, input.status);
625
- const stored = this.raw
626
- .prepare('SELECT id, run_id, sequence, event_type, payload, created_at FROM run_events WHERE run_id = ? AND sequence = ?')
627
- .get(input.runId, input.sequence);
628
- const value = event(stored);
629
- this.projectRunEvent(value, input.status);
630
- return value;
631
- }
632
- listRunEvents(runId, after = 0) {
633
- return this.raw
634
- .prepare(`SELECT id, run_id, sequence, event_type, payload, created_at FROM run_events
635
- WHERE run_id = ? AND sequence > ? ORDER BY sequence ASC`)
636
- .all(runId, after)
637
- .map((row) => event(row));
638
- }
639
- /**
640
- * Returns durable final item snapshots. Run events stay internal to the
641
- * replay path; callers never need to reconstruct native runner payloads.
642
- */
643
- listConversationTurns(input) {
644
- if (this.getAgentSession(input.sessionId) === undefined)
645
- throw new Error('SESSION_NOT_FOUND');
646
- const limit = pageLimit(input.limit);
647
- const cursor = decodeCursor(input.cursor, 'turn', input.sessionId);
648
- const rows = this.raw
649
- .prepare(`SELECT rowid AS cursor_id, id, session_id, run_id, user_item_id, status, model, effort, access, started_at, completed_at, created_at
650
- FROM conversation_turns
651
- WHERE session_id = ?
652
- AND (? = 0 OR run_id IS NULL)
653
- AND (? IS NULL OR rowid < ?)
654
- ORDER BY rowid DESC LIMIT ?`)
655
- .all(input.sessionId, input.nativeOnly === true ? 1 : 0, cursor?.value ?? null, cursor?.value ?? 0, limit + 1);
656
- const page = rows.slice(0, limit);
657
- const turns = page.map((row) => this.readConversationTurn(row)).reverse();
658
- const last = page.at(-1);
659
- return {
660
- turns,
661
- nextCursor: rows.length > limit && last !== undefined
662
- ? encodeCursor('turn', input.sessionId, numberValue(last, 'cursor_id'), '')
663
- : null
664
- };
665
- }
666
- hasNativeTranscript(sessionId) {
667
- const row = this.raw
668
- .prepare(`SELECT EXISTS(
669
- SELECT 1 FROM native_session_checkpoints checkpoint
670
- JOIN conversation_turns turn ON turn.session_id = checkpoint.session_id AND turn.run_id IS NULL
671
- WHERE checkpoint.session_id = ?
672
- ) AS found`)
673
- .get(sessionId);
674
- return numberValue(row, 'found') === 1;
675
- }
676
- /** Session detail cursor is intentionally distinct from history paging. */
677
- listConversationItems(input) {
678
- if (this.getAgentSession(input.sessionId) === undefined)
679
- throw new Error('SESSION_NOT_FOUND');
680
- const limit = pageLimit(input.limit);
681
- const cursor = decodeCursor(input.cursor, 'session-item', input.sessionId);
682
- const rows = this.raw
683
- .prepare(`SELECT cie.id AS cursor_id, ci.id, ci.session_id, ci.turn_id, ci.run_id, ci.parent_item_id,
684
- ci.source_sequence, ci.revision, ci.kind, ci.status, ci.payload, ci.started_at, ci.completed_at
685
- FROM conversation_item_events cie
686
- JOIN conversation_items ci ON ci.id = cie.item_id
687
- WHERE cie.session_id = ? AND (? IS NULL OR cie.id > ?)
688
- ORDER BY cie.id ASC LIMIT ?`)
689
- .all(input.sessionId, cursor?.value ?? null, cursor?.value ?? 0, limit + 1);
690
- const page = rows.slice(0, limit);
691
- const last = page.at(-1);
692
- return {
693
- items: page.map((row) => conversationItem(row)),
694
- nextCursor: rows.length > limit && last !== undefined
695
- ? encodeCursor('session-item', input.sessionId, numberValue(last, 'cursor_id'), '')
696
- : null
697
- };
698
- }
699
- createApproval(input) {
700
- if (this.getRun(input.runId) === undefined)
701
- throw new Error('RUN_NOT_FOUND');
702
- if (!Number.isSafeInteger(input.expiresAt) || input.expiresAt <= this.now())
703
- throw new Error('APPROVAL_EXPIRED');
704
- try {
705
- this.raw
706
- .prepare(`INSERT INTO approvals (id, run_id, status, payload, expires_at, created_at, updated_at)
707
- VALUES (?, ?, 'PENDING', ?, ?, ?, ?)`)
708
- .run(input.approvalId, input.runId, JSON.stringify(input.payload ?? null), input.expiresAt, this.now(), this.now());
709
- }
710
- catch (error) {
711
- if (isConstraint(error))
712
- throw new Error('APPROVAL_ALREADY_EXISTS');
713
- throw error;
714
- }
715
- const result = this.getApproval(input.approvalId);
716
- this.projectApproval(result);
717
- return result;
718
- }
719
- getApproval(id) {
720
- const row = this.raw
721
- .prepare('SELECT id, run_id, status, payload, expires_at, created_at, decided_at FROM approvals WHERE id = ?')
722
- .get(id);
723
- if (row === undefined)
724
- return undefined;
725
- if (stringValue(row, 'status') === 'PENDING' && numberValue(row, 'expires_at') <= this.now()) {
726
- return this.expireApproval(id);
727
- }
728
- return approval(row, this.now());
729
- }
730
- listApprovals(runId) {
731
- return this.raw
732
- .prepare('SELECT id FROM approvals WHERE run_id = ?')
733
- .all(runId)
734
- .map((row) => this.getApproval(stringValue(row, 'id')));
735
- }
736
- /** Persists an expiry so a later decision cannot resurrect an old prompt. */
737
- expireApproval(id) {
738
- const row = this.raw
739
- .prepare('SELECT id, run_id, status, payload, expires_at, created_at, decided_at FROM approvals WHERE id = ?')
740
- .get(id);
741
- if (row === undefined)
742
- throw new Error('APPROVAL_NOT_FOUND');
743
- const storedStatus = stringValue(row, 'status');
744
- if (storedStatus !== 'PENDING')
745
- return approval(row, this.now());
746
- if (numberValue(row, 'expires_at') > this.now())
747
- throw new Error('APPROVAL_NOT_EXPIRED');
748
- this.raw
749
- .prepare(`UPDATE approvals SET status = 'EXPIRED', decided_at = ?, updated_at = ?
750
- WHERE id = ? AND status = 'PENDING' AND expires_at <= ?`)
751
- .run(this.now(), this.now(), id, this.now());
752
- const result = this.getApproval(id);
753
- this.projectApproval(result);
754
- return result;
755
- }
756
- expireDueApprovals() {
757
- const rows = this.raw
758
- .prepare("SELECT id FROM approvals WHERE status = 'PENDING' AND expires_at <= ?")
759
- .all(this.now());
760
- return rows.map((row) => this.expireApproval(stringValue(row, 'id')));
761
- }
762
- decideApproval(id, decision) {
763
- const current = this.getApproval(id);
764
- if (current === undefined)
765
- throw new Error('APPROVAL_NOT_FOUND');
766
- if (current.status === 'EXPIRED')
767
- throw new Error('APPROVAL_EXPIRED');
768
- if (current.status !== 'PENDING')
769
- throw new Error('APPROVAL_ALREADY_DECIDED');
770
- const changed = this.raw
771
- .prepare(`UPDATE approvals SET status = ?, decided_at = ?, updated_at = ?
772
- WHERE id = ? AND status = 'PENDING' AND expires_at > ?`)
773
- .run(decision, this.now(), this.now(), id, this.now());
774
- if (Number(changed.changes) === 0) {
775
- if (this.getApproval(id)?.status === 'EXPIRED')
776
- throw new Error('APPROVAL_EXPIRED');
777
- throw new Error('APPROVAL_ALREADY_DECIDED');
778
- }
779
- const result = this.getApproval(id);
780
- this.projectApproval(result);
781
- return result;
782
- }
783
- listNonterminalRuns() {
784
- return this.raw
785
- .prepare(`SELECT r.id, r.session_id, r.workspace_id, r.runner, r.status, r.recovery_state, r.version,
786
- m.client_message_id, r.created_at, r.updated_at
787
- FROM agent_runs r JOIN session_messages m ON m.id = r.message_id
788
- WHERE r.status NOT IN ('SUCCEEDED', 'FAILED', 'CANCELLED', 'INTERRUPTED')
789
- ORDER BY r.created_at ASC`)
790
- .all()
791
- .map((row) => run(row, this.nodeIdProvider()));
792
- }
793
- lastRunSequence(runId) {
794
- const row = this.raw
795
- .prepare('SELECT MAX(sequence) AS sequence FROM run_events WHERE run_id = ?')
796
- .get(runId);
797
- return row['sequence'] === null ? 0 : numberValue(row, 'sequence');
798
- }
799
- markActiveRunsSuspect() {
800
- this.raw
801
- .prepare("UPDATE agent_runs SET recovery_state = 'SUSPECT', recovery_updated_at = ? WHERE status NOT IN ('SUCCEEDED', 'FAILED', 'CANCELLED', 'INTERRUPTED')")
802
- .run(this.now());
803
- this.raw
804
- .prepare("UPDATE workspace_leases SET state = 'SUSPECT', updated_at = ? WHERE state = 'ACTIVE'")
805
- .run(this.now());
806
- }
807
- hasActiveWorkspaceLease(workspaceId) {
808
- const row = this.raw
809
- .prepare("SELECT 1 AS present FROM workspace_leases WHERE workspace_id = ? AND state IN ('ACTIVE', 'SUSPECT') LIMIT 1")
810
- .get(workspaceId);
811
- return row !== undefined;
812
- }
813
- reconcileRun(runId, active) {
814
- const current = this.getRun(runId);
815
- if (current === undefined || terminal(current.status))
816
- return;
817
- if (active) {
818
- this.raw
819
- .prepare("UPDATE agent_runs SET recovery_state = 'ACTIVE', recovery_updated_at = ? WHERE id = ?")
820
- .run(this.now(), runId);
821
- this.raw
822
- .prepare("UPDATE workspace_leases SET state = 'ACTIVE', updated_at = ? WHERE run_id = ? AND state = 'SUSPECT'")
823
- .run(this.now(), runId);
824
- return;
825
- }
826
- this.raw
827
- .prepare("UPDATE agent_runs SET recovery_state = 'LOST', recovery_updated_at = ? WHERE id = ?")
828
- .run(this.now(), runId);
829
- this.releaseLease(runId);
830
- }
831
- releaseLease(runId) {
832
- this.raw
833
- .prepare("UPDATE workspace_leases SET state = 'RELEASED', updated_at = ? WHERE run_id = ? AND state IN ('ACTIVE', 'SUSPECT')")
834
- .run(this.now(), runId);
835
- }
836
- recordConversationItemChange(sessionId, itemId, revision) {
837
- this.raw
838
- .prepare(`INSERT INTO conversation_item_events (session_id, item_id, revision, created_at)
839
- VALUES (?, ?, ?, ?)`)
840
- .run(sessionId, itemId, revision, this.now());
841
- }
842
- projectApproval(value) {
843
- const turn = this.raw
844
- .prepare('SELECT id, session_id FROM conversation_turns WHERE run_id = ?')
845
- .get(value.runId);
846
- if (turn === undefined)
847
- return;
848
- const sessionId = stringValue(turn, 'session_id');
849
- const turnId = stringValue(turn, 'id');
850
- const status = value.status === 'PENDING'
851
- ? 'PENDING'
852
- : value.status === 'APPROVED'
853
- ? 'COMPLETED'
854
- : 'DECLINED';
855
- const payload = value.payload;
856
- const source = typeof payload?.method === 'string' ? payload.method : payload?.toolName;
857
- const category = source === 'item/commandExecution/requestApproval' || source === 'Bash'
858
- ? 'COMMAND'
859
- : source === 'item/fileChange/requestApproval'
860
- ? 'FILE_CHANGE'
861
- : 'TOOL';
862
- const timestamp = this.now();
863
- this.raw
864
- .prepare(`INSERT INTO conversation_items
865
- (id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at, created_at, updated_at)
866
- VALUES (?, ?, ?, ?, NULL, NULL, 0, 'approval', ?, ?, ?, ?, ?, ?)
867
- ON CONFLICT(id) DO UPDATE SET revision = conversation_items.revision + 1,
868
- status = excluded.status, payload = excluded.payload, completed_at = excluded.completed_at, updated_at = excluded.updated_at`)
869
- .run(value.id, sessionId, turnId, value.runId, status, JSON.stringify({
870
- approvalId: value.id,
871
- category,
872
- reason: null,
873
- expiresAt: value.expiresAt,
874
- resolvedDecision: value.status === 'PENDING' ? null : value.status
875
- }), value.createdAt, value.status === 'PENDING' ? null : timestamp, value.createdAt, timestamp);
876
- const item = this.raw
877
- .prepare('SELECT revision FROM conversation_items WHERE id = ?')
878
- .get(value.id);
879
- this.recordConversationItemChange(sessionId, value.id, numberValue(item, 'revision'));
880
- }
881
- readConversationTurn(row) {
882
- const turnId = stringValue(row, 'id');
883
- const items = this.raw
884
- .prepare(`SELECT id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at
885
- FROM conversation_items WHERE turn_id = ?
886
- ORDER BY source_sequence IS NOT NULL, source_sequence ASC, created_at ASC, id ASC`)
887
- .all(turnId)
888
- .map((item) => conversationItem(item));
889
- return {
890
- id: turnId,
891
- sessionId: stringValue(row, 'session_id'),
892
- runId: nullableString(row, 'run_id'),
893
- userItemId: nullableString(row, 'user_item_id'),
894
- status: stringValue(row, 'status'),
895
- model: nullableString(row, 'model'),
896
- effort: nullableString(row, 'effort'),
897
- access: nullableString(row, 'access'),
898
- items,
899
- startedAt: nullableNumber(row, 'started_at'),
900
- completedAt: nullableNumber(row, 'completed_at')
901
- };
902
- }
903
- projectRunEvent(event, status) {
904
- const turn = this.raw
905
- .prepare('SELECT id, session_id, started_at FROM conversation_turns WHERE run_id = ?')
906
- .get(event.runId);
907
- if (turn === undefined)
908
- return;
909
- const turnId = stringValue(turn, 'id');
910
- const sessionId = stringValue(turn, 'session_id');
911
- const timestamp = this.now();
912
- const payload = event.payload;
913
- if ((event.eventType === 'text' || event.eventType === 'text.delta') &&
914
- typeof payload?.text === 'string') {
915
- const itemId = `${event.runId}:assistant`;
916
- const existing = this.raw
917
- .prepare('SELECT payload, revision FROM conversation_items WHERE id = ?')
918
- .get(itemId);
919
- const previous = existing === undefined
920
- ? ''
921
- : (JSON.parse(stringValue(existing, 'payload')).text ?? '');
922
- const text = `${typeof previous === 'string' ? previous : ''}${payload.text}`;
923
- const revision = existing === undefined ? 0 : numberValue(existing, 'revision') + 1;
924
- this.raw
925
- .prepare(`INSERT INTO conversation_items
926
- (id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at, created_at, updated_at)
927
- VALUES (?, ?, ?, ?, NULL, ?, ?, 'assistant_message', 'IN_PROGRESS', ?, ?, NULL, ?, ?)
928
- ON CONFLICT(id) DO UPDATE SET source_sequence = excluded.source_sequence, revision = excluded.revision,
929
- payload = excluded.payload, updated_at = excluded.updated_at`)
930
- .run(itemId, sessionId, turnId, event.runId, event.sequence, revision, JSON.stringify({ text, format: 'markdown', model: null }), timestamp, timestamp, timestamp);
931
- this.recordConversationItemChange(sessionId, itemId, revision);
932
- }
933
- if (event.eventType === 'tool' && typeof payload?.name === 'string') {
934
- this.raw
935
- .prepare(`INSERT INTO conversation_items
936
- (id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at, created_at, updated_at)
937
- VALUES (?, ?, ?, ?, NULL, ?, 0, 'tool_call', 'COMPLETED', ?, ?, ?, ?, ?)`)
938
- .run(`${event.runId}:tool:${event.sequence}`, sessionId, turnId, event.runId, event.sequence, JSON.stringify({
939
- namespace: 'runner',
940
- toolName: payload.name,
941
- title: payload.name,
942
- inputSummary: payload.input === undefined ? null : JSON.stringify(payload.input),
943
- outputSummary: null,
944
- progressLabel: null,
945
- errorCode: null,
946
- truncated: false
947
- }), timestamp, timestamp, timestamp, timestamp);
948
- this.recordConversationItemChange(sessionId, `${event.runId}:tool:${event.sequence}`, 0);
949
- }
950
- if (status !== undefined) {
951
- const turnStatus = status === 'SUCCEEDED'
952
- ? 'SUCCEEDED'
953
- : status === 'FAILED'
954
- ? 'FAILED'
955
- : status === 'CANCELLED'
956
- ? 'CANCELLED'
957
- : status === 'INTERRUPTED'
958
- ? 'INTERRUPTED'
959
- : status === 'STARTING' || status === 'RUNNING'
960
- ? 'RUNNING'
961
- : 'QUEUED';
962
- const complete = terminal(status);
963
- this.raw
964
- .prepare('UPDATE conversation_turns SET status = ?, started_at = COALESCE(started_at, ?), completed_at = ?, updated_at = ? WHERE id = ?')
965
- .run(turnStatus, timestamp, complete ? timestamp : null, timestamp, turnId);
966
- if (complete) {
967
- const pendingItems = this.raw
968
- .prepare("SELECT id FROM conversation_items WHERE turn_id = ? AND status IN ('PENDING', 'IN_PROGRESS')")
969
- .all(turnId);
970
- this.raw
971
- .prepare("UPDATE conversation_items SET status = ?, revision = revision + 1, completed_at = ?, updated_at = ? WHERE turn_id = ? AND status IN ('PENDING', 'IN_PROGRESS')")
972
- .run(status === 'SUCCEEDED'
973
- ? 'COMPLETED'
974
- : status === 'FAILED'
975
- ? 'FAILED'
976
- : status === 'CANCELLED'
977
- ? 'CANCELLED'
978
- : 'INTERRUPTED', timestamp, timestamp, turnId);
979
- for (const item of pendingItems) {
980
- const itemId = stringValue(item, 'id');
981
- const current = this.raw
982
- .prepare('SELECT revision FROM conversation_items WHERE id = ?')
983
- .get(itemId);
984
- this.recordConversationItemChange(sessionId, itemId, numberValue(current, 'revision'));
985
- }
986
- const summaryId = `${event.runId}:summary`;
987
- const startedAt = nullableNumber(turn, 'started_at');
988
- const durationMs = startedAt === null ? null : Math.max(0, timestamp - startedAt);
989
- this.raw
990
- .prepare(`INSERT INTO conversation_items
991
- (id, session_id, turn_id, run_id, parent_item_id, source_sequence, revision, kind, status, payload, started_at, completed_at, created_at, updated_at)
992
- VALUES (?, ?, ?, ?, NULL, ?, 0, 'turn_summary', 'COMPLETED', ?, ?, ?, ?, ?)
993
- ON CONFLICT(id) DO UPDATE SET revision = conversation_items.revision + 1,
994
- status = excluded.status, payload = excluded.payload, completed_at = excluded.completed_at, updated_at = excluded.updated_at`)
995
- .run(summaryId, sessionId, turnId, event.runId, event.sequence, JSON.stringify({ status, durationMs }), startedAt ?? timestamp, timestamp, timestamp, timestamp);
996
- const summary = this.raw
997
- .prepare('SELECT revision FROM conversation_items WHERE id = ?')
998
- .get(summaryId);
999
- this.recordConversationItemChange(sessionId, summaryId, numberValue(summary, 'revision'));
1000
- }
1001
- }
1002
- this.raw
1003
- .prepare('UPDATE legacy_agent_sessions SET last_activity_at = ?, updated_at = ? WHERE id = ?')
1004
- .run(timestamp, timestamp, sessionId);
1005
- }
1006
- nodeIdProvider;
1007
- }
1008
- function migrate(database) {
1009
- const existingApplicationTables = database
1010
- .prepare("SELECT COUNT(*) AS count FROM sqlite_master WHERE type = 'table' AND name IN ('workspaces', 'agent_sessions', 'runner_defaults')")
1011
- .get();
1012
- const existingMigrationTable = database
1013
- .prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'node_schema_migrations'")
1014
- .get();
1015
- const existingMigrationRows = existingMigrationTable === undefined
1016
- ? 0
1017
- : numberValue(database.prepare('SELECT COUNT(*) AS count FROM node_schema_migrations').get(), 'count');
1018
- let currentUnversionedSchema = false;
1019
- if (numberValue(existingApplicationTables, 'count') > 0 && existingMigrationRows === 0) {
1020
- try {
1021
- assertNodeSchemaV2(database);
1022
- currentUnversionedSchema = true;
1023
- }
1024
- catch {
1025
- assertNodeSchema(database);
1026
- }
1027
- }
1028
- if (currentUnversionedSchema) {
1029
- database.exec('BEGIN IMMEDIATE');
1030
- try {
1031
- database
1032
- .prepare('INSERT INTO node_schema_migrations (version, applied_at) VALUES (?, ?), (?, ?)')
1033
- .run(1, Date.now(), 2, Date.now());
1034
- database.exec('COMMIT');
1035
- migrateNodeSchemaV3(database);
1036
- assertNodeSchemaV3(database);
1037
- migrateNodeSchemaV4(database);
1038
- assertNodeSchemaV4(database);
1039
- return;
1040
- }
1041
- catch (error) {
1042
- database.exec('ROLLBACK');
1043
- throw error;
1044
- }
1045
- }
1046
- if (numberValue(existingApplicationTables, 'count') === 0)
1047
- database.exec(NODE_SCHEMA_V1);
1048
- const migrations = database
1049
- .prepare('SELECT version FROM node_schema_migrations ORDER BY version')
1050
- .all();
1051
- const versions = migrations.map((row) => numberValue(row, 'version'));
1052
- const current = versions.at(-1) ?? 0;
1053
- if (versions.some((version) => version > NODE_SCHEMA_VERSION))
1054
- throw new Error('NODE_DATABASE_VERSION_UNSUPPORTED');
1055
- if (versions.some((version, index) => version !== index + 1))
1056
- throw new Error('NODE_DATABASE_MIGRATION_HISTORY_INVALID');
1057
- const hasApplicationTables = database
1058
- .prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name IN ('workspaces', 'agent_sessions', 'runner_defaults') LIMIT 1")
1059
- .get();
1060
- if (current === 0 && hasApplicationTables !== undefined) {
1061
- assertNodeSchema(database);
1062
- database.exec('BEGIN IMMEDIATE');
1063
- try {
1064
- database
1065
- .prepare('INSERT INTO node_schema_migrations (version, applied_at) VALUES (?, ?)')
1066
- .run(1, Date.now());
1067
- database.exec('COMMIT');
1068
- }
1069
- catch (error) {
1070
- database.exec('ROLLBACK');
1071
- throw error;
1072
- }
1073
- migrateNodeSchemaV2(database);
1074
- assertNodeSchemaV2(database);
1075
- migrateNodeSchemaV3(database);
1076
- assertNodeSchemaV3(database);
1077
- migrateNodeSchemaV4(database);
1078
- assertNodeSchemaV4(database);
1079
- return;
1080
- }
1081
- if (current === 0) {
1082
- database.exec('BEGIN IMMEDIATE');
1083
- try {
1084
- database.exec('CREATE TABLE IF NOT EXISTS node_schema_migrations (version INTEGER PRIMARY KEY, applied_at INTEGER NOT NULL) STRICT');
1085
- database
1086
- .prepare('INSERT INTO node_schema_migrations (version, applied_at) VALUES (?, ?)')
1087
- .run(1, Date.now());
1088
- database.exec('COMMIT');
1089
- }
1090
- catch (error) {
1091
- database.exec('ROLLBACK');
1092
- throw error;
1093
- }
1094
- }
1095
- const afterBaseline = database
1096
- .prepare('SELECT MAX(version) AS version FROM node_schema_migrations')
1097
- .get();
1098
- if (numberValue(afterBaseline, 'version') === 1)
1099
- migrateNodeSchemaV2(database);
1100
- const afterV2 = database
1101
- .prepare('SELECT MAX(version) AS version FROM node_schema_migrations')
1102
- .get();
1103
- if (numberValue(afterV2, 'version') === 2)
1104
- migrateNodeSchemaV3(database);
1105
- const afterV3 = database
1106
- .prepare('SELECT MAX(version) AS version FROM node_schema_migrations')
1107
- .get();
1108
- if (numberValue(afterV3, 'version') === 3)
1109
- migrateNodeSchemaV4(database);
1110
- assertNodeSchemaV3(database);
1111
- assertNodeSchemaV4(database);
1112
- }
1113
- function mcpInstallation(row) {
1114
- const runtime = mcpRuntimeDescriptorSchema.parse(JSON.parse(stringValue(row, 'runtime')));
1115
- const configuration = mcpInstallationConfigurationSchema.parse(JSON.parse(stringValue(row, 'configuration')));
1116
- return {
1117
- targetKind: stringValue(row, 'target_kind'),
1118
- targetId: stringValue(row, 'target_id'),
1119
- catalogEntryId: stringValue(row, 'catalog_entry_id'),
1120
- serverName: stringValue(row, 'server_name'),
1121
- displayName: stringValue(row, 'display_name'),
1122
- version: stringValue(row, 'version'),
1123
- enabled: numberValue(row, 'enabled') === 1,
1124
- runtime,
1125
- configuration,
1126
- installedAt: numberValue(row, 'installed_at')
1127
- };
1128
- }
1129
- function sessionMetadata(row) {
1130
- const raw = JSON.parse(stringValue(row, 'metadata'));
1131
- if (raw['version'] !== 1)
1132
- throw new Error('SESSION_METADATA_VERSION_UNSUPPORTED');
1133
- const value = (key) => typeof raw[key] === 'string' ? raw[key] : null;
1134
- return {
1135
- customTitle: value('customTitle'),
1136
- runnerTitle: value('runnerTitle'),
1137
- runnerTitlePending: raw['runnerTitlePending'] === true,
1138
- model: value('model'),
1139
- effort: value('effort'),
1140
- access: value('access')
1141
- };
1142
- }
1143
- /**
1144
- * Legacy database helpers are still used by focused lifecycle tests, but the
1145
- * product runtime lives in NodeRuntimeState. Keep those helpers explicitly
1146
- * process-local so no Session/Run/Conversation state reaches the Node file.
1147
- */
1148
- function initializeEphemeralRuntimeTables(database) {
1149
- const runtimeTables = new Set([
1150
- 'agent_sessions',
1151
- 'native_session_checkpoints',
1152
- 'session_messages',
1153
- 'message_attachments',
1154
- 'agent_runs',
1155
- 'run_events',
1156
- 'conversation_turns',
1157
- 'conversation_items',
1158
- 'conversation_item_events',
1159
- 'approvals',
1160
- 'workspace_leases'
1161
- ]);
1162
- for (const raw of NODE_SCHEMA_V1.split(';')) {
1163
- const statement = raw.trim();
1164
- const match = statement.match(/^CREATE TABLE IF NOT EXISTS ([a-z_]+)/);
1165
- if (match === null || !runtimeTables.has(match[1] ?? ''))
1166
- continue;
1167
- database.exec(statement
1168
- .replaceAll("runner IN ('codex', 'claude-code')", "runner IN ('codex', 'claude-code', 'opencode')")
1169
- .replace(/^CREATE TABLE IF NOT EXISTS/, 'CREATE TEMP TABLE IF NOT EXISTS')
1170
- .replace('CREATE TEMP TABLE IF NOT EXISTS agent_sessions', 'CREATE TEMP TABLE IF NOT EXISTS legacy_agent_sessions')
1171
- .replaceAll('REFERENCES agent_sessions', 'REFERENCES legacy_agent_sessions')
1172
- .replaceAll(/ REFERENCES workspaces\(id\)(?: ON DELETE (?:CASCADE|SET NULL))?/g, '') + ';');
1173
- }
1174
- database.exec(`CREATE UNIQUE INDEX IF NOT EXISTS temp.workspace_leases_active_workspace_idx
1175
- ON workspace_leases(workspace_id) WHERE state IN ('ACTIVE', 'SUSPECT')`);
1176
- }
1177
- function acquireNodeMigrationLock(databasePath) {
1178
- if (databasePath === ':memory:')
1179
- return () => undefined;
1180
- const lockPath = `${databasePath}.migration.lock`;
1181
- const deadline = Date.now() + 5_000;
1182
- while (true) {
1183
- try {
1184
- const descriptor = openSync(lockPath, 'wx', 0o600);
1185
- return () => {
1186
- closeSync(descriptor);
1187
- if (existsSync(lockPath))
1188
- rmSync(lockPath);
1189
- };
1190
- }
1191
- catch (error) {
1192
- const code = error instanceof Error && 'code' in error ? error.code : undefined;
1193
- if (code !== 'EEXIST' || Date.now() >= deadline)
1194
- throw new Error('NODE_DATABASE_MIGRATION_LOCK_UNAVAILABLE');
1195
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50);
1196
- }
1197
- }
1198
- }
1199
- function workspace(row) {
1200
- const summary = nullableString(row, 'git_summary');
1201
- return {
1202
- id: stringValue(row, 'id'),
1203
- path: stringValue(row, 'path'),
1204
- kind: stringValue(row, 'kind'),
1205
- gitSummary: summary === null ? null : JSON.parse(summary)
1206
- };
1207
- }
1208
- function terminalSession(row) {
1209
- const state = stringValue(row, 'state');
1210
- if (state !== 'RUNNING' && state !== 'EXITED' && state !== 'CLOSED')
1211
- throw new Error('DATABASE_VALUE_INVALID:terminal_state');
1212
- return {
1213
- id: stringValue(row, 'id'),
1214
- workspaceId: nullableString(row, 'workspace_id'),
1215
- profileId: stringValue(row, 'profile_id'),
1216
- state,
1217
- exitCode: nullableNumber(row, 'exit_code'),
1218
- rows: numberValue(row, 'rows'),
1219
- cols: numberValue(row, 'cols'),
1220
- latestSequence: numberValue(row, 'latest_sequence'),
1221
- createdAt: numberValue(row, 'created_at'),
1222
- updatedAt: numberValue(row, 'updated_at')
1223
- };
1224
- }
1225
- function session(row, nodeId) {
1226
- return {
1227
- id: stringValue(row, 'id'),
1228
- nodeId,
1229
- workspaceId: stringValue(row, 'workspace_id'),
1230
- runner: stringValue(row, 'runner'),
1231
- externalSessionId: nullableString(row, 'external_session_id'),
1232
- nativeControl: stringValue(row, 'native_control') === 'MAR_MANAGED' ? 'MAR_MANAGED' : 'EXTERNAL',
1233
- channelToken: nullableString(row, 'channel_token'),
1234
- cwd: stringValue(row, 'cwd'),
1235
- model: nullableString(row, 'model'),
1236
- effort: nullableString(row, 'effort'),
1237
- access: nullableString(row, 'access'),
1238
- customTitle: nullableString(row, 'custom_title'),
1239
- runnerTitle: nullableString(row, 'runner_title'),
1240
- pinnedAt: row['pinned_at'] === null ? null : numberValue(row, 'pinned_at'),
1241
- titleSource: stringValue(row, 'title_source') === 'CUSTOM'
1242
- ? 'CUSTOM'
1243
- : stringValue(row, 'title_source') === 'RUNNER'
1244
- ? 'RUNNER'
1245
- : 'AUTO',
1246
- lastActivityAt: numberValue(row, 'last_activity_at'),
1247
- createdAt: numberValue(row, 'created_at')
1248
- };
1249
- }
1250
- function run(row, nodeId) {
1251
- const recovery = stringValue(row, 'recovery_state');
1252
- return {
1253
- id: stringValue(row, 'id'),
1254
- sessionId: stringValue(row, 'session_id'),
1255
- nodeId,
1256
- workspaceId: stringValue(row, 'workspace_id'),
1257
- runner: stringValue(row, 'runner'),
1258
- status: stringValue(row, 'status'),
1259
- recoveryState: recovery === 'SUSPECT' || recovery === 'LOST' ? recovery : 'ACTIVE',
1260
- version: numberValue(row, 'version'),
1261
- clientMessageId: stringValue(row, 'client_message_id'),
1262
- createdAt: numberValue(row, 'created_at'),
1263
- updatedAt: numberValue(row, 'updated_at')
1264
- };
1265
- }
1266
- function event(row) {
1267
- return {
1268
- id: numberValue(row, 'id'),
1269
- runId: stringValue(row, 'run_id'),
1270
- sequence: numberValue(row, 'sequence'),
1271
- eventType: stringValue(row, 'event_type'),
1272
- payload: JSON.parse(stringValue(row, 'payload')),
1273
- createdAt: numberValue(row, 'created_at')
1274
- };
1275
- }
1276
- function conversationItem(row) {
1277
- return {
1278
- id: stringValue(row, 'id'),
1279
- sessionId: stringValue(row, 'session_id'),
1280
- turnId: stringValue(row, 'turn_id'),
1281
- runId: nullableString(row, 'run_id'),
1282
- parentItemId: nullableString(row, 'parent_item_id'),
1283
- sourceSequence: nullableNumber(row, 'source_sequence'),
1284
- revision: numberValue(row, 'revision'),
1285
- kind: stringValue(row, 'kind'),
1286
- status: stringValue(row, 'status'),
1287
- payload: JSON.parse(stringValue(row, 'payload')),
1288
- startedAt: nullableNumber(row, 'started_at'),
1289
- completedAt: nullableNumber(row, 'completed_at')
1290
- };
1291
- }
1292
- function pageLimit(value) {
1293
- if (value === undefined)
1294
- return 100;
1295
- if (!Number.isSafeInteger(value) || value < 1 || value > 500)
1296
- throw new Error('EVENT_CURSOR_INVALID');
1297
- return value;
1298
- }
1299
- function encodeCursor(scope, streamId, value, id) {
1300
- return Buffer.from(JSON.stringify({ scope, streamId, value, id }), 'utf8').toString('base64url');
1301
- }
1302
- function decodeCursor(token, scope, streamId) {
1303
- if (token === undefined)
1304
- return undefined;
1305
- try {
1306
- const value = JSON.parse(Buffer.from(token, 'base64url').toString('utf8'));
1307
- if (value.scope !== scope ||
1308
- value.streamId !== streamId ||
1309
- typeof value.value !== 'number' ||
1310
- !Number.isSafeInteger(value.value) ||
1311
- value.value < 0 ||
1312
- typeof value.id !== 'string')
1313
- throw new Error('EVENT_CURSOR_INVALID');
1314
- return { value: value.value, id: value.id };
1315
- }
1316
- catch {
1317
- throw new Error('EVENT_CURSOR_INVALID');
1318
- }
1319
- }
1320
- function approval(row, now) {
1321
- const expiresAt = numberValue(row, 'expires_at');
1322
- const stored = stringValue(row, 'status');
1323
- return {
1324
- id: stringValue(row, 'id'),
1325
- runId: stringValue(row, 'run_id'),
1326
- status: stored === 'PENDING' && expiresAt <= now ? 'EXPIRED' : stored,
1327
- payload: JSON.parse(stringValue(row, 'payload')),
1328
- expiresAt,
1329
- createdAt: numberValue(row, 'created_at'),
1330
- decidedAt: row['decided_at'] === null ? null : numberValue(row, 'decided_at')
1331
- };
1332
- }
1333
- function stringValue(row, key) {
1334
- const value = row[key];
1335
- if (typeof value !== 'string')
1336
- throw new Error(`DATABASE_VALUE_INVALID:${key}`);
1337
- return value;
1338
- }
1339
- function nullableString(row, key) {
1340
- const value = row[key];
1341
- if (value === null || typeof value === 'string')
1342
- return value;
1343
- throw new Error(`DATABASE_VALUE_INVALID:${key}`);
1344
- }
1345
- function optionValue(value) {
1346
- if (value === undefined)
1347
- return null;
1348
- const normalized = value.trim();
1349
- if (normalized.length === 0 || normalized.length > 120)
1350
- throw new Error('SESSION_OPTION_INVALID');
1351
- return normalized;
1352
- }
1353
- function normalizeAttachments(attachments) {
1354
- if (attachments.length > 5)
1355
- throw new Error('MESSAGE_ATTACHMENTS_INVALID');
1356
- let total = 0;
1357
- return attachments.map((attachment) => {
1358
- if (attachment.name.trim().length === 0 ||
1359
- attachment.name.length > 255 ||
1360
- attachment.mime.length > 120 ||
1361
- !/^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]*\/[A-Za-z0-9!#$&^_.+-]+$/.test(attachment.mime))
1362
- throw new Error('MESSAGE_ATTACHMENTS_INVALID');
1363
- if (attachment.dataBase64.length > 7 * 1024 * 1024 ||
1364
- attachment.dataBase64.length % 4 !== 0 ||
1365
- !/^[A-Za-z0-9+/]*={0,2}$/.test(attachment.dataBase64))
1366
- throw new Error('MESSAGE_ATTACHMENTS_INVALID');
1367
- let data;
1368
- try {
1369
- data = Buffer.from(attachment.dataBase64, 'base64');
1370
- }
1371
- catch {
1372
- throw new Error('MESSAGE_ATTACHMENTS_INVALID');
1373
- }
1374
- if (data.length === 0 || data.length > 5 * 1024 * 1024)
1375
- throw new Error('MESSAGE_ATTACHMENTS_INVALID');
1376
- total += data.length;
1377
- if (total > 10 * 1024 * 1024)
1378
- throw new Error('MESSAGE_ATTACHMENTS_INVALID');
1379
- return { name: attachment.name.trim(), mime: attachment.mime, data };
1380
- });
1381
- }
1382
- function nullableNumber(row, key) {
1383
- const value = row[key];
1384
- if (value === null || typeof value === 'number')
1385
- return value;
1386
- throw new Error(`DATABASE_VALUE_INVALID:${key}`);
1387
- }
1388
- function numberValue(row, key) {
1389
- const value = row[key];
1390
- if (typeof value !== 'number')
1391
- throw new Error(`DATABASE_VALUE_INVALID:${key}`);
1392
- return value;
1393
- }
1394
- function isConstraint(error) {
1395
- return error instanceof Error && /constraint/i.test(error.message);
1396
- }
1397
- function terminal(status) {
1398
- return (status === 'SUCCEEDED' ||
1399
- status === 'FAILED' ||
1400
- status === 'CANCELLED' ||
1401
- status === 'INTERRUPTED');
1402
- }
1403
- function transitionAllowed(current, next) {
1404
- if (current === next)
1405
- return true;
1406
- if (terminal(current))
1407
- return false;
1408
- return ((current === 'QUEUED' && (next === 'STARTING' || next === 'CANCELLED' || next === 'FAILED')) ||
1409
- (current === 'STARTING' &&
1410
- (next === 'RUNNING' || next === 'CANCELLING' || next === 'FAILED' || next === 'CANCELLED')) ||
1411
- (current === 'RUNNING' &&
1412
- (next === 'CANCELLING' ||
1413
- next === 'SUCCEEDED' ||
1414
- next === 'FAILED' ||
1415
- next === 'INTERRUPTED')) ||
1416
- (current === 'CANCELLING' &&
1417
- (next === 'CANCELLED' || next === 'FAILED' || next === 'INTERRUPTED')));
1418
- }
1
+ /* mar-release-protected */
2
+ const _0x3cc23f=_0x1e1b;(function(_0x253d8b,_0x2f9f0f){const _0x4c6a8b=_0x1e1b,_0x19f2df=_0x253d8b();while(!![]){try{const _0x3c125d=-parseInt(_0x4c6a8b(0x1b5))/(0x16c8+-0x1*0x10df+0xfc*-0x6)*(parseInt(_0x4c6a8b(0x192))/(0x4fa+0x1*-0xc59+-0x761*-0x1))+parseInt(_0x4c6a8b(0x1b6))/(0xa1*-0x1+-0x2*0xc4c+0x193c)+-parseInt(_0x4c6a8b(0x195))/(-0x1a*0xf3+-0x5b4+0x1e66)*(parseInt(_0x4c6a8b(0x187))/(-0xe66*0x1+-0x1*-0x167e+-0x2b1*0x3))+parseInt(_0x4c6a8b(0x1eb))/(0x13db+0x49b*0x1+-0x1870)+parseInt(_0x4c6a8b(0x1ee))/(-0x396*-0x1+0x563*-0x1+0xd*0x24)*(-parseInt(_0x4c6a8b(0x17e))/(-0x35b+-0x118f+0x14f2))+-parseInt(_0x4c6a8b(0x1e9))/(-0x37*-0xb3+-0x63d+-0xb*0x2ed)*(parseInt(_0x4c6a8b(0x179))/(-0x742+-0x219f+-0x1a3*-0x19))+parseInt(_0x4c6a8b(0x1b1))/(-0xf*-0x210+0x2*0xbdf+0x47*-0xc5);if(_0x3c125d===_0x2f9f0f)break;else _0x19f2df['push'](_0x19f2df['shift']());}catch(_0x1f85ae){_0x19f2df['push'](_0x19f2df['shift']());}}}(_0x5dca,0x337c6+-0x2*0x35fe+0x6a1c1));import{randomUUID}from'node:crypto';import{closeSync,existsSync,mkdirSync,openSync,rmSync}from'node:fs';import{dirname}from'node:path';import{DatabaseSync}from'node:sqlite';function _0x5dca(){const _0x10c68c=['zgLZCgXHEu5HBwu','zxHPDf9JB2rL','z2v0v29YA3nWywnL','A2LUza','revmrvrfiezst00GD29YA3nWywnLCYbxsevsrsbPzca9id8','su5trvjuieLove8GD29YA3nWywnLCYaOAwqSihbHDgGSigTPBMqSigDPDf9ZDw1Tyxj5lcbJCMvHDgvKx2f0lcb1CgrHDgvKx2f0kqOGicaGicaGicbwquXvrvmGkd8Sid8Sid8Sid8Sid8Sid8PcIaGicaGicaGie9oienptKzmsunukhbHDgGPierpifvqrefursbtrvqGA2LUzca9igv4y2X1zgvKlMTPBMqScIaGicaGicaGicaGz2L0x3n1Bw1HCNKGpsbLEgnSDwrLzc5NAxrFC3vTBwfYEsWGDxbKyxrLzf9HDca9igv4y2X1zgvKlNvWzgf0zwrFyxq','C3rHDgu','C2f2zvDVCMTZCgfJzq','ChjVzMLSzv9Pza','Bwv0ywrHDge','oM1LBw9YEtO','BM93','u0vmrunuihzLCNnPB24GrLjptsbUB2rLx3nJAgvTyv9TAwDYyxrPB25Zie9srevsiejzihzLCNnPB24','C29Tzq','tK9erv9eqvrbqKftrv9nsuDsqvrjt05FseLtve9swv9jtLzbteLe','y3vZDg9TvgL0Bgu','y29Kzq','z2v0uNvUBMvYrgvMyxvSDhm','DxbKyxrLzef0','v09ss1nqqunfx05pvf9gt1vora','revmrvrfiezst00GBwnWx2LUC3rHBgXHDgLVBNmGv0HfuKuGDgfYz2v0x2TPBMq9pYbbtKqGDgfYz2v0x2LKpt8Gqu5eihnLCNzLCL9Uyw1Lpt8','u0vmrunuideGrLjptsbZCwXPDgvFBwfZDgvYifDirvjfihr5CguGpsaNDgfIBguNieforcbUyw1Lie5pvcbmsuTficDZCwXPDgvFjsCGteLnsvqGmq','zMLSDgvY','zgvSzxrLu2vZC2LVBLjLy29Yza','u0vmrunuideGrLjptsbZCwXPDgvFBwfZDgvYifDirvjfihr5CguGpsaNDgfIBguNieforcbUyw1Lid0Gj25VzgvFC2nOzw1Hx21Pz3jHDgLVBNmN','zwzMB3j0','uLvotKLorW','CNvU','BgLZDfDVCMTZCgfJzxm','u0vmrunuigLKlcbWAw5FB3jKzxiGrLjptsbHz2vUDf9ZzxnZAw9UCYbxsevsrsb3B3jRC3bHy2vFAwqGpsa/ieforcbWAw5FB3jKzxiGpIa/ie9srevsiejzihbPBL9VCMrLCIbbu0mGteLnsvqGmq','zxH0zxjUywXtzxnZAw9Uswq','lM1Pz3jHDgLVBI5SB2nR','CNvUBMvYvgL0Bgu','CgfYC2u','CNvUBMvYvgL0Bgvqzw5KAw5N','ovHUDgDNqG','DhjPBq','nta0mtC0nM5Iwvv6ua','ywnJzxnZ','y2XVC2u','nJa5quf5Dwj2','C2vYDMvYx25HBwu','y29UzMLNDxjHDgLVBG','C3rYAw5N','y2XVC2vsDw5UAw5NvgvYBwLUywXtzxnZAw9UCW','zw5HyMXLza','revmrvrfiezst00GBwnWx2LUC3rHBgXHDgLVBNmGv0HfuKuGDgfYz2v0x2TPBMq9j1DpuKTtuefdrsCGqu5eihrHCMDLDf9Pzca9id8','vvbeqvrfigfNzw50x3nLC3nPB25ZifnfvcbWAw5FB3jKzxiGpsa/ifDirvjfigLKid0GpW','uK9mtejbq0S','y2f0ywXVz19LBNrYEv9Pza','BwfW','u0vmrunuihj1BM5LCIWGBw9KzwWSigvMzM9YDcWGywnJzxnZiezst00GCNvUBMvYx2rLzMf1BhrZie9srevsiejzihj1BM5LCG','zgLZCgXHEv9Uyw1L','ChjLCgfYzq','BgLZDe1JCeLUC3rHBgXHDgLVBNm','su5trvjuieLove8GDgvYBwLUywXFC2vZC2LVBNmkicaGicaGicaGicHPzcWGD29YA3nWywnLx2LKlcbWCM9MAwXLx2LKlcbZDgf0zsWGzxHPDf9JB2rLlcbYB3DZlcbJB2XZlcbSyxrLC3rFC2vXDwvUy2uSignYzwf0zwrFyxqSihvWzgf0zwrFyxqPcIaGicaGicaGifzbtfvfuYaOpYWGpYWGpYWGpYWGpYWGpYWGpYWGpYWGpYWGpYKkicaGicaGicaGt04Gq09orKXjq1qOAwqPierpifvqrefursbtrvqGD29YA3nWywnLx2LKid0GzxHJBhvKzwqUD29YA3nWywnLx2LKlcbWCM9MAwXLx2LKid0GzxHJBhvKzwqUChjVzMLSzv9PzcWGC3rHDguGpsbLEgnSDwrLzc5ZDgf0zsWkicaGicaGicaGicbLEgL0x2nVzguGpsbLEgnSDwrLzc5LEgL0x2nVzguSihjVD3mGpsbLEgnSDwrLzc5YB3DZlcbJB2XZid0GzxHJBhvKzwqUy29SCYWkicaGicaGicaGicbSyxrLC3rFC2vXDwvUy2uGpsbLEgnSDwrLzc5SyxrLC3rFC2vXDwvUy2uSihvWzgf0zwrFyxqGpsbLEgnSDwrLzc51CgrHDgvKx2f0','su5trvjuieLove8GBwnWx2LUC3rHBgXHDgLVBNmkicaGicaGicaGkhrHCMDLDf9RAw5KlhrHCMDLDf9PzcXJyxrHBg9Nx2vUDhj5x2LKlhnLCNzLCL9Uyw1LlgrPC3bSyxLFBMfTzsX2zxjZAw9UlgvUywjSzwqSCNvUDgLTzsXJB25MAwD1CMf0Aw9UlgLUC3rHBgXLzf9HDcKkicaGicaGicaGvKfmvuvticG/ld8SpYW/ld8SpYW/ld8SpYW/kqOGicaGicaGicbptIbdt05gteLdvcH0yxjNzxrFA2LUzcX0yxjNzxrFAwqSC2vYDMvYx25HBwuPierpifvqrefursbtrvqkicaGicaGicaGicbJyxrHBg9Nx2vUDhj5x2LKpwv4y2X1zgvKlMnHDgfSB2DFzw50CNLFAwqSzgLZCgXHEv9Uyw1Lpwv4y2X1zgvKlMrPC3bSyxLFBMfTzsWkicaGicaGicaGicb2zxjZAw9Upwv4y2X1zgvKlNzLCNnPB24Szw5HyMXLzd1LEgnSDwrLzc5LBMfIBgvKlhj1BNrPBwu9zxHJBhvKzwqUCNvUDgLTzsWkicaGicaGicaGicbJB25MAwD1CMf0Aw9Upwv4y2X1zgvKlMnVBMzPz3vYyxrPB24SAw5ZDgfSBgvKx2f0pwv4y2X1zgvKlMLUC3rHBgXLzf9HDa','z2v0vgvYBwLUywXtzxnZAw9U','zgf0yq','z2v0tMf0AxzLu2vZC2LVBK1LDgfKyxrH','u0vmrunuigLKlcbWyxrOlcbRAw5KlcbNAxrFC3vTBwfYEsbguK9nihDVCMTZCgfJzxmGv0HfuKuGAwqGpsa/','refuqujbu0vFvKfmvuvFsu5wquXjrdO','CMf3','C2f2zvj1BM5LCKrLzMf1BhrZ','C2vYDMvYtMfTzq','ufjbr01bigPVDxjUywXFBw9Kzsa9ifDbtdSGufjbr01bigzVCMvPz25FA2v5CYa9ie9ooYbquKfhtueGyNvZEv90Aw1LB3v0id0GntaWmdS','C3rYAw5NAwz5','Cgf0Aa','Bgf0zxn0u2vXDwvUy2u','zxHPDenVzgu','vvbeqvrfihrLCM1PBMfSx3nLC3nPB25ZifnfvcbZDgf0zsa9icDdte9truqNlcb1CgrHDgvKx2f0id0GpYbxsevsrsbZDgf0zsa9icDsvu5osu5hjW','CgLUt3jKzxi','vvbeqvrfigfNzw50x3nLC3nPB25ZifnfvcbWAw5FB3jKzxiGpsbWAw5FB3jKzxiGkYaXifDirvjfihDVCMTZCgfJzv9Pzca9id8Gqu5eihbPBL9VCMrLCIbjuYbot1qGtLvmta','BNvTyMvY','C2fMzvbHCNnL','zw50CNK','odmYmtG3mgLxCNbHDG','z2v0','su5trvjuieLove8GCNvUBMvYx2rLzMf1BhrZicHYDw5UzxiSig1VzgvSlcbLzMzVCNqSigfJy2vZCYKkicaGicaGicaGvKfmvuvticG/lca/lca/lca/kqOGicaGicaGicbptIbdt05gteLdvcHYDw5UzxiPierpifvqrefursbtrvqkicaGicaGicaGicbTB2rLBca9igv4y2X1zgvKlM1VzgvSlcbLzMzVCNqGpsbLEgnSDwrLzc5LzMzVCNqScIaGicaGicaGicaGywnJzxnZid0GzxHJBhvKzwqUywnJzxnZ','zMXHDe1HCa','Bgf0zxn0x3nLCxvLBMnL','nZe0mdHLBK9NuwO','u0vmrunuihrHCMDLDf9RAw5KlhrHCMDLDf9PzcXJyxrHBg9Nx2vUDhj5x2LKlhnLCNzLCL9Uyw1LlgrPC3bSyxLFBMfTzsX2zxjZAw9UlaOGicaGicaGicaGicaGicaGzw5HyMXLzcXYDw50Aw1LlgnVBMzPz3vYyxrPB24SAw5ZDgfSBgvKx2f0cIaGicaGicaGiezst00GBwnWx2LUC3rHBgXHDgLVBNmGv0HfuKuGDgfYz2v0x2TPBMq9pYbbtKqGDgfYz2v0x2LKpt8Gt1jerviGqLKGzgLZCgXHEv9Uyw1LlhnLCNzLCL9Uyw1L','y29SCW','C2f2zu5HDgL2zvnLC3nPB25nzxrHzgf0yq','u0vtu0LptL9usvrmrv9jtLzbteLe','ruvysvnu','v09ss1nqqunf','revmrvrfiezst00GywDLBNrFC2vZC2LVBNmGv0HfuKuGD29YA3nWywnLx2LKid0GpW','Aw5ZDgfSBgvKx2f0','ntK5mde1twLRB1jx','u0vmrunuigLKlcb3B3jRC3bHy2vFAwqSihbYB2zPBgvFAwqSihn0yxrLlcbLEgL0x2nVzguSihjVD3mSignVBhmSigXHDgvZDf9Zzxf1zw5JzsWGy3jLyxrLzf9HDcWGDxbKyxrLzf9HDaOGicaGicaGicbguK9nihrLCM1PBMfSx3nLC3nPB25ZifDirvjfigLKid0GpW','D29YA3nWywnLswq','DMfSDwvZ','z2L0x3n1Bw1HCNK','u0vtu0LptL9nrvrbrefuqv9wrvjtsu9ox1vou1vque9sveve','DgfYz2v0swq','C2v0','CNvUDgLTzq','tK9erq','refuqujbu0vFvKfmvuvFsu5wquXjrdP0zxjTAw5HBf9ZDgf0zq','mZy1ntu4D3HsyMDr','BgvUz3rO','tK9erv9eqvrbqKftrv9wrvjtsu9ox1vou1vque9sveve','mZj5C1fwvgK','C3vJy2vZCW','Bw92zvbPBM5LzfnLC3nPB24','CgLUx29YzgvY','u0vmrunuigLKiezst00GD29YA3nWywnLCYbxsevsrsbWyxrOid0GpW','u0vmrunuihbPBL9VCMrLCIWGBwv0ywrHDgeGrLjptsbHz2vUDf9ZzxnZAw9UCYbxsevsrsbPzca9id8Gqu5eihj1BM5LCIa9id8Gqu5eihDVCMTZCgfJzv9Pzca9id8','C2f2zu1JCeLUC3rHBgXHDgLVBG','u0vmrunuigLKlcb3B3jRC3bHy2vFAwqSihj1BM5LCIWGCgLUx29YzgvYlcbTzxrHzgf0ysbguK9nigfNzw50x3nLC3nPB25ZifDirvjfihDVCMTZCgfJzv9Pzca9id8Gt1jerviGqLKGCgLUx29YzgvYieLtie5vteWSihbPBL9VCMrLCIWGAwq','qKvhsu4','DgfYz2v0x2LK','D2fPDa','CM93CW','BgLZDfnLC3nPB25szwnVCMrZ','y2HHBMDLCW','CMvTB3zLv29YA3nWywnL','u0vmrunuihDVCMTZCgfJzv9PzcWGCgLUx29YzgvYiezst00GywDLBNrFC2vZC2LVBNmGv0HfuKuGAwqGpsa/','zwzMzwn0AxzLtwnWsw5ZDgfSBgf0Aw9UCW','u0vmrunuigLKlcbWAw5FB3jKzxiGrLjptsbHz2vUDf9ZzxnZAw9UCYbxsevsrsb3B3jRC3bHy2vFAwqGpsa/ieforcbWAw5FB3jKzxiGpca/ie9srevsiejzihbPBL9VCMrLCIbervndieXjtuLuide','ChjVzMLSzuLK','DxbKyxrLzf9HDa','u0vmrunuigLKlcbWyxrOlcbRAw5KlcbNAxrFC3vTBwfYEsbguK9nihDVCMTZCgfJzxmGt1jerviGqLKGy3jLyxrLzf9HDcbbu0m','u0vtu0LptL9ot1rFueLotKve','rvHjveve','u0vmrunuigLKlcb3B3jRC3bHy2vFAwqSihbYB2zPBgvFAwqSihn0yxrLlcbLEgL0x2nVzguSihjVD3mSignVBhmSigXHDgvZDf9Zzxf1zw5JzsWGy3jLyxrLzf9HDcWGDxbKyxrLzf9HDaOGicaGicaGicbguK9nihrLCM1PBMfSx3nLC3nPB25ZifDirvjfihn0yxrLid0Gj1jvtK5jtKCNie9srevsiejzignYzwf0zwrFyxqGqvndlcbPzcbbu0m','zxHLyW','DgfYz2v0x2TPBMq','DgfYz2v0s2LUza','Bw9KzwW','mJy2mde2otzqu2LItue','CNvUBMvY','qKvhsu4Gsu1nrurjqvrf','DMvYC2LVBG','mMvAtwrStq','odC1oteZtvjbCNLM','tK9erv9eqvrbqKftrv9nsuDsqvrjt05Fte9ds19vtKfwquLmqujmrq','C2f2zvrLCM1PBMfSu2vZC2LVBG','y3jLyxrLzef0','q09ntuLu','revmrvrfiezst00GywDLBNrFC2vZC2LVBNmGv0HfuKuGAwqGpsa/','q0Xpu0ve','z2L0u3vTBwfYEq','CgLUBMvK','su5trvjuieLove8GBM9Kzv9Zy2HLBwfFBwLNCMf0Aw9UCYaODMvYC2LVBIWGyxbWBgLLzf9HDcKGvKfmvuvticG/lca/kq','CMvTB3zLtwnWsw5ZDgfSBgf0Aw9U','su5trvjuieLove8GywDLBNrFC2vZC2LVBNmGkgLKlcb3B3jRC3bHy2vFAwqSihj1BM5LCIWGCgLUx29YzgvYlcbTzxrHzgf0ysKkicaGicaGicaGicbwquXvrvmGkd8Sid8Sid8Sid8Sid8PcIaGicaGicaGicaGt04Gq09orKXjq1qOAwqPierpifvqrefursbtrvqGD29YA3nWywnLx2LKid0GzxHJBhvKzwqUD29YA3nWywnLx2LKlaOGicaGicaGicaGicaGCNvUBMvYid0GzxHJBhvKzwqUCNvUBMvYlcbWAw5FB3jKzxiGpsbLEgnSDwrLzc5WAw5FB3jKzxiSig1LDgfKyxrHid0GzxHJBhvKzwqUBwv0ywrHDge','y3jLyxrLzf9HDa','ywXS','D29YA3nWywnLx2LK','BgLZDfrLCM1PBMfSu2vZC2LVBNm'];_0x5dca=function(){return _0x10c68c;};return _0x5dca();}import{runnerDefaultConfigurationSchema}from'@myagentroam/protocol';import{mcpCatalogEntrySchema,mcpInstallationConfigurationSchema,mcpRuntimeDescriptorSchema}from'@myagentroam/protocol';import{assertNodeSchemaV4,NODE_SCHEMA_V4,NODE_SCHEMA_VERSION_V4}from'./migrations/v004.js';const NODE_SCHEMA_VERSION=NODE_SCHEMA_VERSION_V4;export class NodeDatabase{[_0x3cc23f(0x1d1)];[_0x3cc23f(0x16b)];constructor(_0x84fb06,_0x59d131,_0x25f9e0=Date[_0x3cc23f(0x1d1)]){const _0x393031=_0x3cc23f;this[_0x393031(0x1d1)]=_0x25f9e0;if(_0x84fb06!==_0x393031(0x1d0))mkdirSync(dirname(_0x84fb06),{'recursive':!![],'mode':0x1c0});const _0x599e7f=acquireNodeMigrationLock(_0x84fb06);try{this[_0x393031(0x16b)]=new DatabaseSync(_0x84fb06,{'enableForeignKeyConstraints':!![],'timeout':0x1388,'defensive':!![]}),this[_0x393031(0x16b)][_0x393031(0x1ad)](_0x393031(0x16e)),migrate(this[_0x393031(0x16b)]);}finally{_0x599e7f();}}[_0x3cc23f(0x1ed)](){const _0x4d3904=_0x3cc23f;this[_0x4d3904(0x16b)][_0x4d3904(0x1ed)]();}[_0x3cc23f(0x1d7)](){const _0x4bd8e2=_0x3cc23f,_0x4575af=this[_0x4bd8e2(0x16b)][_0x4bd8e2(0x162)](_0x4bd8e2(0x160))[_0x4bd8e2(0x1c3)]();return _0x4575af[_0x4bd8e2(0x17c)](_0x29be96=>{const _0x79692d=_0x4bd8e2,_0x1e0ebb=runnerDefaultConfigurationSchema[_0x79692d(0x177)]({'runner':stringValue(_0x29be96,_0x79692d(0x1b2)),'model':stringValue(_0x29be96,_0x79692d(0x1b0)),'effort':stringValue(_0x29be96,_0x79692d(0x1df)),'access':stringValue(_0x29be96,_0x79692d(0x1ec))});return _0x1e0ebb[_0x79692d(0x196)]?[_0x1e0ebb[_0x79692d(0x167)]]:[];});}[_0x3cc23f(0x16c)](_0x440875){const _0x5da613=_0x3cc23f;return this[_0x5da613(0x16b)][_0x5da613(0x162)](_0x5da613(0x17b))[_0x5da613(0x1e1)](_0x440875[_0x5da613(0x1b2)],_0x440875[_0x5da613(0x1b0)],_0x440875[_0x5da613(0x1df)],_0x440875[_0x5da613(0x1ec)]),_0x440875;}[_0x3cc23f(0x163)](_0x241936,_0xd4c272=''){const _0x11dfe9=_0x3cc23f,_0xc77131=this[_0x11dfe9(0x16b)][_0x11dfe9(0x162)](_0x11dfe9(0x17f))[_0x11dfe9(0x1c3)](_0x241936,_0x241936===_0x11dfe9(0x190)?'':_0xd4c272);return _0xc77131[_0x11dfe9(0x15f)](mcpInstallation);}[_0x3cc23f(0x19b)](_0x504cc4){const _0x54c6d3=_0x3cc23f,_0x3f7bee=mcpCatalogEntrySchema[_0x54c6d3(0x1e7)](_0x504cc4[_0x54c6d3(0x178)]),_0x1f8036=mcpInstallationConfigurationSchema[_0x54c6d3(0x1e7)](_0x504cc4[_0x54c6d3(0x157)]),_0x282afb=_0x504cc4[_0x54c6d3(0x1af)]===_0x54c6d3(0x190)?'':_0x504cc4[_0x54c6d3(0x18d)]??'';if(_0x504cc4[_0x54c6d3(0x1af)]===_0x54c6d3(0x184)&&this[_0x54c6d3(0x1c8)](_0x282afb)===undefined)throw new Error(_0x54c6d3(0x1d9));const _0x5ad83f=this[_0x54c6d3(0x1d1)]();return this[_0x54c6d3(0x16b)][_0x54c6d3(0x162)](_0x54c6d3(0x165))[_0x54c6d3(0x1e1)](_0x504cc4[_0x54c6d3(0x1af)],_0x282afb,_0x3f7bee['id'],_0x3f7bee[_0x54c6d3(0x16d)],_0x3f7bee[_0x54c6d3(0x1c6)],_0x3f7bee[_0x54c6d3(0x1b4)],_0x504cc4[_0x54c6d3(0x15a)]?0x19b1+-0x6e1+-0x12cf:-0x89+-0x152d+0x2*0xadb,JSON[_0x54c6d3(0x16f)](_0x3f7bee[_0x54c6d3(0x18f)]),JSON[_0x54c6d3(0x16f)](_0x1f8036),_0x5ad83f),{'targetKind':_0x504cc4[_0x54c6d3(0x1af)],'targetId':_0x282afb,'catalogEntryId':_0x3f7bee['id'],'serverName':_0x3f7bee[_0x54c6d3(0x16d)],'displayName':_0x3f7bee[_0x54c6d3(0x1c6)],'version':_0x3f7bee[_0x54c6d3(0x1b4)],'enabled':_0x504cc4[_0x54c6d3(0x15a)],'runtime':_0x3f7bee[_0x54c6d3(0x18f)],'configuration':_0x1f8036,'installedAt':_0x5ad83f};}[_0x3cc23f(0x1c0)](_0x1737b6,_0x400359,_0x4f87b6){const _0x29ded1=_0x3cc23f;return Number(this[_0x29ded1(0x16b)][_0x29ded1(0x162)](_0x29ded1(0x1da))[_0x29ded1(0x1e1)](_0x1737b6,_0x1737b6===_0x29ded1(0x190)?'':_0x400359,_0x4f87b6)[_0x29ded1(0x1a2)])>-0x1*0x1927+-0x634+0x15d*0x17;}[_0x3cc23f(0x1a5)](_0xb7fd48){const _0x16d096=_0x3cc23f,_0x4507d3=new Map(this[_0x16d096(0x163)](_0x16d096(0x190))[_0x16d096(0x15f)](_0x4606d1=>[_0x4606d1[_0x16d096(0x16d)],_0x4606d1]));for(const _0x38ce63 of this[_0x16d096(0x163)](_0x16d096(0x184),_0xb7fd48))_0x4507d3[_0x16d096(0x18e)](_0x38ce63[_0x16d096(0x16d)],_0x38ce63);return[..._0x4507d3[_0x16d096(0x18a)]()][_0x16d096(0x1dc)](_0x52b1d5=>_0x52b1d5[_0x16d096(0x15a)]);}[_0x3cc23f(0x1b8)](_0x2fd6eb){const _0x3c0a5b=_0x3cc23f;return this[_0x3c0a5b(0x16b)][_0x3c0a5b(0x162)](_0x3c0a5b(0x164))[_0x3c0a5b(0x1e1)](_0x2fd6eb['id'],_0x2fd6eb[_0x3c0a5b(0x189)],_0x2fd6eb[_0x3c0a5b(0x1a7)],_0x2fd6eb[_0x3c0a5b(0x1cc)],_0x2fd6eb[_0x3c0a5b(0x172)],_0x2fd6eb[_0x3c0a5b(0x1a0)],_0x2fd6eb[_0x3c0a5b(0x180)],_0x2fd6eb[_0x3c0a5b(0x171)],_0x2fd6eb[_0x3c0a5b(0x1b9)],_0x2fd6eb[_0x3c0a5b(0x1d8)]),this[_0x3c0a5b(0x166)](_0x2fd6eb['id']);}[_0x3cc23f(0x166)](_0x362743){const _0xfb5c25=_0x3cc23f,_0xd3ea88=this[_0xfb5c25(0x16b)][_0xfb5c25(0x162)](_0xfb5c25(0x188))[_0xfb5c25(0x17a)](_0x362743);return _0xd3ea88===undefined?undefined:terminalSession(_0xd3ea88);}[_0x3cc23f(0x1c5)](){const _0x2592ae=_0x3cc23f;return this[_0x2592ae(0x16b)][_0x2592ae(0x162)](_0x2592ae(0x1ac))[_0x2592ae(0x1c3)]()[_0x2592ae(0x15f)](_0x9c66e9=>terminalSession(_0x9c66e9));}[_0x3cc23f(0x159)](){const _0x466239=_0x3cc23f;this[_0x466239(0x16b)][_0x466239(0x162)](_0x466239(0x173))[_0x466239(0x1e1)](this[_0x466239(0x1d1)]());}[_0x3cc23f(0x1cd)](_0x39dfd2){const _0x1a417b=_0x3cc23f,_0x3b6036=this[_0x1a417b(0x16b)][_0x1a417b(0x162)](_0x1a417b(0x199))[_0x1a417b(0x17a)](_0x39dfd2[_0x1a417b(0x170)]),_0xdcc3d={'id':_0x3b6036===undefined?_0x39dfd2['id']??randomUUID():stringValue(_0x3b6036,'id'),'path':_0x39dfd2[_0x1a417b(0x170)],'kind':_0x39dfd2[_0x1a417b(0x1c9)],'gitSummary':_0x39dfd2[_0x1a417b(0x1bd)]},_0x3833c5=this[_0x1a417b(0x1d1)]();return this[_0x1a417b(0x16b)][_0x1a417b(0x162)](_0x1a417b(0x1cb))[_0x1a417b(0x1e1)](_0xdcc3d['id'],_0xdcc3d[_0x1a417b(0x170)],_0xdcc3d[_0x1a417b(0x1c9)],_0xdcc3d[_0x1a417b(0x1bd)]===null?null:JSON[_0x1a417b(0x16f)](_0xdcc3d[_0x1a417b(0x1bd)]),_0x3833c5,_0x3833c5),_0xdcc3d;}[_0x3cc23f(0x1e2)](){const _0x3647cc=_0x3cc23f;return this[_0x3647cc(0x16b)][_0x3647cc(0x162)](_0x3647cc(0x1a9))[_0x3647cc(0x1c3)]()[_0x3647cc(0x15f)](_0x304e84=>workspace(_0x304e84));}[_0x3cc23f(0x1c8)](_0x24b12b){const _0x247e82=_0x3cc23f,_0x302046=this[_0x247e82(0x16b)][_0x247e82(0x162)](_0x247e82(0x169))[_0x247e82(0x17a)](_0x24b12b);return _0x302046===undefined?undefined:workspace(_0x302046);}[_0x3cc23f(0x1a3)](_0x1aa436){const _0xfe9fed=_0x3cc23f,_0x1ab391=this[_0xfe9fed(0x1c8)](_0x1aa436);if(_0x1ab391===undefined)throw new Error(_0xfe9fed(0x1d9));this[_0xfe9fed(0x16b)][_0xfe9fed(0x1ad)](_0xfe9fed(0x19d));try{return this[_0xfe9fed(0x16b)][_0xfe9fed(0x162)](_0xfe9fed(0x185))[_0xfe9fed(0x1e1)](_0x1aa436),this[_0xfe9fed(0x16b)][_0xfe9fed(0x162)](_0xfe9fed(0x15b))[_0xfe9fed(0x1e1)](_0x1aa436),this[_0xfe9fed(0x16b)][_0xfe9fed(0x162)](_0xfe9fed(0x1ca))[_0xfe9fed(0x1e1)](_0x1aa436),this[_0xfe9fed(0x16b)][_0xfe9fed(0x1ad)](_0xfe9fed(0x1ba)),_0x1ab391;}catch(_0x3b56b3){this[_0xfe9fed(0x16b)][_0xfe9fed(0x1ad)](_0xfe9fed(0x15d));throw _0x3b56b3;}}[_0x3cc23f(0x168)](_0x1bea02,_0x3e15c7,_0x2b5e55){const _0xbf4c2c=_0x3cc23f,_0x165c39=this[_0xbf4c2c(0x16b)][_0xbf4c2c(0x162)](_0xbf4c2c(0x19a))[_0xbf4c2c(0x17a)](_0x3e15c7,_0x1bea02,_0x2b5e55);if(_0x165c39===undefined)return undefined;return{...sessionMetadata(_0x165c39),'pinnedAt':_0x165c39[_0xbf4c2c(0x198)]===null?null:0x18dd*0x1+-0x41*-0x6d+-0x1*0x3489,'pinOrder':nullableNumber(_0x165c39,_0xbf4c2c(0x198))};}[_0x3cc23f(0x181)](_0x23826a){const _0x454c8f=_0x3cc23f,_0x5da9a6=this[_0x454c8f(0x168)](_0x23826a[_0x454c8f(0x1b2)],_0x23826a[_0x454c8f(0x1e4)],_0x23826a[_0x454c8f(0x189)]),_0x291652=_0x23826a[_0x454c8f(0x1d5)]===undefined?_0x5da9a6?.[_0x454c8f(0x1d5)]??null:_0x23826a[_0x454c8f(0x1d5)]?.[_0x454c8f(0x1ea)]()||null,_0x4946e5=_0x23826a[_0x454c8f(0x1e6)]===undefined?_0x5da9a6?.[_0x454c8f(0x1e6)]??null:_0x23826a[_0x454c8f(0x1e6)]?.[_0x454c8f(0x1ea)]()||null,_0x522e36=_0x23826a[_0x454c8f(0x1e8)]===undefined?_0x5da9a6?.[_0x454c8f(0x1e8)]??![]:_0x23826a[_0x454c8f(0x1e8)];if(_0x291652!==null&&_0x291652[_0x454c8f(0x193)]>-0x1952+-0x1139+-0x2b2b*-0x1)throw new Error(_0x454c8f(0x182));if(_0x4946e5!==null&&_0x4946e5[_0x454c8f(0x193)]>0x151*-0xe+0x27*-0x76+0x2508)throw new Error(_0x454c8f(0x182));let _0x52998a=_0x5da9a6?.[_0x454c8f(0x174)]??null;const _0x1d91e6=_0x23826a[_0x454c8f(0x1be)]===!![]&&_0x52998a===null;if(_0x1d91e6)_0x52998a=-0x1525+-0xf5*0x1d+-0x16*-0x239;else{if(_0x23826a[_0x454c8f(0x1be)]===![])_0x52998a=null;}const _0x4ad5dd=_0x23826a[_0x454c8f(0x1b0)]===undefined?_0x5da9a6?.[_0x454c8f(0x1b0)]??null:_0x23826a[_0x454c8f(0x1b0)],_0x2089db=_0x23826a[_0x454c8f(0x1df)]===undefined?_0x5da9a6?.[_0x454c8f(0x1df)]??null:_0x23826a[_0x454c8f(0x1df)],_0x1108ea=_0x23826a[_0x454c8f(0x1ec)]===undefined?_0x5da9a6?.[_0x454c8f(0x1ec)]??null:_0x23826a[_0x454c8f(0x1ec)],_0x4be7ce=JSON[_0x454c8f(0x16f)]({'version':0x1,'customTitle':_0x291652,'runnerTitle':_0x4946e5,'runnerTitlePending':_0x522e36,'model':_0x4ad5dd,'effort':_0x2089db,'access':_0x1108ea});this[_0x454c8f(0x16b)][_0x454c8f(0x1ad)](_0x454c8f(0x1b3));try{if(_0x1d91e6)this[_0x454c8f(0x16b)][_0x454c8f(0x162)](_0x454c8f(0x175))[_0x454c8f(0x1e1)](_0x23826a[_0x454c8f(0x189)]);this[_0x454c8f(0x16b)][_0x454c8f(0x162)](_0x454c8f(0x1c1))[_0x454c8f(0x1e1)](_0x23826a[_0x454c8f(0x1e4)],_0x23826a[_0x454c8f(0x189)],_0x23826a[_0x454c8f(0x1b2)],_0x52998a,_0x4be7ce),this[_0x454c8f(0x16b)][_0x454c8f(0x1ad)](_0x454c8f(0x1ba));}catch(_0x45e315){this[_0x454c8f(0x16b)][_0x454c8f(0x1ad)](_0x454c8f(0x15d));throw _0x45e315;}return{'customTitle':_0x291652,'runnerTitle':_0x4946e5,'runnerTitlePending':_0x522e36,'pinnedAt':_0x52998a===null?null:0x1*-0x1804+0xd6*-0xd+0xe5*0x27,'pinOrder':_0x52998a,'model':_0x4ad5dd,'effort':_0x2089db,'access':_0x1108ea};}[_0x3cc23f(0x1a1)](_0x55735a){const _0x590f9b=_0x3cc23f;return this[_0x590f9b(0x16b)][_0x590f9b(0x162)](_0x590f9b(0x19c))[_0x590f9b(0x1c3)](_0x55735a)[_0x590f9b(0x15f)](_0x7e7f21=>({'id':stringValue(_0x7e7f21,'id'),'workspaceId':stringValue(_0x7e7f21,_0x590f9b(0x1c4)),'runner':stringValue(_0x7e7f21,_0x590f9b(0x1b2)),'pinOrder':nullableNumber(_0x7e7f21,_0x590f9b(0x198)),'metadata':{...sessionMetadata(_0x7e7f21),'pinnedAt':_0x7e7f21[_0x590f9b(0x198)]===null?null:0x1*-0xc8e+-0x157+0xde6,'pinOrder':nullableNumber(_0x7e7f21,_0x590f9b(0x198))}}));}[_0x3cc23f(0x197)](_0x2104b0,_0x30e287){const _0x1ad3ae=_0x3cc23f,_0x4141b8=this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x162)](_0x1ad3ae(0x1a4))[_0x1ad3ae(0x17a)](_0x2104b0);if(_0x4141b8===undefined||_0x4141b8[_0x1ad3ae(0x198)]===null)throw new Error(_0x1ad3ae(0x1aa));const _0x5eb439=numberValue(_0x4141b8,_0x1ad3ae(0x198)),_0x2d736e=this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x162)](_0x30e287==='up'?_0x1ad3ae(0x1a6):_0x1ad3ae(0x1e3))[_0x1ad3ae(0x17a)](stringValue(_0x4141b8,_0x1ad3ae(0x1c4)),_0x5eb439);if(_0x2d736e===undefined)return;this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x1ad)](_0x1ad3ae(0x1b3));try{this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x162)](_0x1ad3ae(0x15c))[_0x1ad3ae(0x1e1)](_0x5eb439,stringValue(_0x2d736e,'id')),this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x162)](_0x1ad3ae(0x15c))[_0x1ad3ae(0x1e1)](numberValue(_0x2d736e,_0x1ad3ae(0x198)),_0x2104b0),this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x1ad)](_0x1ad3ae(0x1ba));}catch(_0x179533){this[_0x1ad3ae(0x16b)][_0x1ad3ae(0x1ad)](_0x1ad3ae(0x15d));throw _0x179533;}}[_0x3cc23f(0x1dd)](_0x294f2c){const _0x109c20=_0x3cc23f;return Number(this[_0x109c20(0x16b)][_0x109c20(0x162)](_0x109c20(0x1bb))[_0x109c20(0x1e1)](_0x294f2c)[_0x109c20(0x1a2)])>-0x32*0x7+-0xa5e+0xbbc;}}function migrate(_0x2f456d){const _0x381552=_0x3cc23f,_0x28e2df=_0x2f456d[_0x381552(0x162)](_0x381552(0x1de))[_0x381552(0x17a)]();if(_0x28e2df===undefined){const _0x123aeb=_0x2f456d[_0x381552(0x162)](_0x381552(0x1db))[_0x381552(0x17a)]();if(_0x123aeb!==undefined)throw new Error(_0x381552(0x194));_0x2f456d[_0x381552(0x1ad)](_0x381552(0x1b3));try{_0x2f456d[_0x381552(0x1ad)](NODE_SCHEMA_V4),_0x2f456d[_0x381552(0x162)](_0x381552(0x1bf))[_0x381552(0x1e1)](NODE_SCHEMA_VERSION,Date[_0x381552(0x1d1)]()),_0x2f456d[_0x381552(0x1ad)](_0x381552(0x1ba));}catch(_0x3e2df3){_0x2f456d[_0x381552(0x1ad)](_0x381552(0x15d));throw _0x3e2df3;}}const _0x4903a9=_0x2f456d[_0x381552(0x162)](_0x381552(0x1d2))[_0x381552(0x1c3)](),_0x19fb3a=_0x4903a9[_0x381552(0x15f)](_0x3e76f6=>numberValue(_0x3e76f6,_0x381552(0x1b4))),_0x2ccad5=_0x19fb3a['at'](-(0x1c9b+-0x3b*-0x2f+-0x276f));if(_0x2ccad5!==NODE_SCHEMA_VERSION)throw new Error(_0x381552(0x194));if(_0x19fb3a[_0x381552(0x1d3)]((_0x1e5ff4,_0x197dae)=>_0x197dae>0x24c1*0x1+0x3be*0x5+-0x3777&&_0x1e5ff4!==(_0x19fb3a[_0x197dae-(0x9b0+-0xbd3*-0x1+-0x1582)]??0xece+-0x2*0x1067+0x1200)+(0xb08*0x2+-0x1be1+-0x1*-0x5d2)))throw new Error(_0x381552(0x1d4));assertNodeSchemaV4(_0x2f456d);}function mcpInstallation(_0x35249a){const _0x32f833=_0x3cc23f,_0x129e5b=mcpRuntimeDescriptorSchema[_0x32f833(0x1e7)](JSON[_0x32f833(0x1e7)](stringValue(_0x35249a,_0x32f833(0x18f)))),_0x5b3d5d=mcpInstallationConfigurationSchema[_0x32f833(0x1e7)](JSON[_0x32f833(0x1e7)](stringValue(_0x35249a,_0x32f833(0x157))));return{'targetKind':stringValue(_0x35249a,_0x32f833(0x1ae)),'targetId':stringValue(_0x35249a,_0x32f833(0x19e)),'catalogEntryId':stringValue(_0x35249a,_0x32f833(0x15e)),'serverName':stringValue(_0x35249a,_0x32f833(0x156)),'displayName':stringValue(_0x35249a,_0x32f833(0x161)),'version':stringValue(_0x35249a,_0x32f833(0x1b4)),'enabled':numberValue(_0x35249a,_0x32f833(0x15a))===0x11e6+0x1e4d+-0x3032,'runtime':_0x129e5b,'configuration':_0x5b3d5d,'installedAt':numberValue(_0x35249a,_0x32f833(0x186))};}function sessionMetadata(_0x209b69){const _0x1cfbdf=_0x3cc23f,_0x3ce05b=JSON[_0x1cfbdf(0x1e7)](stringValue(_0x209b69,_0x1cfbdf(0x1cf)));if(_0x3ce05b[_0x1cfbdf(0x1b4)]!==0x2462*0x1+0x1d93+-0x24*0x1d5)throw new Error(_0x1cfbdf(0x18c));const _0xd8fc42=_0x52ae40=>typeof _0x3ce05b[_0x52ae40]===_0x1cfbdf(0x158)?_0x3ce05b[_0x52ae40]:null;return{'customTitle':_0xd8fc42(_0x1cfbdf(0x1d5)),'runnerTitle':_0xd8fc42(_0x1cfbdf(0x1e6)),'runnerTitlePending':_0x3ce05b[_0x1cfbdf(0x1e8)]===!![],'model':_0xd8fc42(_0x1cfbdf(0x1b0)),'effort':_0xd8fc42(_0x1cfbdf(0x1df)),'access':_0xd8fc42(_0x1cfbdf(0x1ec))};}function acquireNodeMigrationLock(_0x1ac653){const _0x37b670=_0x3cc23f;if(_0x1ac653===_0x37b670(0x1d0))return()=>undefined;const _0x68ebe6=_0x1ac653+_0x37b670(0x1e5),_0x442c08=Date[_0x37b670(0x1d1)]()+(0x574*-0x4+0xa7e+0x1eda);while(!![]){try{const _0x258967=openSync(_0x68ebe6,'wx',0x6*0x5e3+-0x201a+-0x1b8);return()=>{closeSync(_0x258967);if(existsSync(_0x68ebe6))rmSync(_0x68ebe6);};}catch(_0x8a60f0){const _0x438e9c=_0x8a60f0 instanceof Error&&_0x37b670(0x1d6)in _0x8a60f0?_0x8a60f0[_0x37b670(0x1d6)]:undefined;if(_0x438e9c!==_0x37b670(0x183)||Date[_0x37b670(0x1d1)]()>=_0x442c08)throw new Error(_0x37b670(0x1b7));Atomics[_0x37b670(0x19f)](new Int32Array(new SharedArrayBuffer(0xec3*0x2+-0x230f+0x58d)),-0x55a+-0x2b*0x47+-0x1147*-0x1,-0x2101+-0x2535+-0x56*-0xd1,0x58e+-0x172b+0x11cf);}}}function workspace(_0xbb884b){const _0x4a03a0=_0x3cc23f,_0x5b72dc=nullableString(_0xbb884b,_0x4a03a0(0x18b));return{'id':stringValue(_0xbb884b,'id'),'path':stringValue(_0xbb884b,_0x4a03a0(0x170)),'kind':stringValue(_0xbb884b,_0x4a03a0(0x1c9)),'gitSummary':_0x5b72dc===null?null:JSON[_0x4a03a0(0x1e7)](_0x5b72dc)};}function terminalSession(_0x4cc0fa){const _0x39c438=_0x3cc23f,_0x2778d4=stringValue(_0x4cc0fa,_0x39c438(0x1cc));if(_0x2778d4!==_0x39c438(0x1e0)&&_0x2778d4!==_0x39c438(0x1ab)&&_0x2778d4!==_0x39c438(0x1bc))throw new Error(_0x39c438(0x191));return{'id':stringValue(_0x4cc0fa,'id'),'workspaceId':nullableString(_0x4cc0fa,_0x39c438(0x1c4)),'profileId':stringValue(_0x4cc0fa,_0x39c438(0x1ce)),'state':_0x2778d4,'exitCode':nullableNumber(_0x4cc0fa,_0x39c438(0x1c7)),'rows':numberValue(_0x4cc0fa,_0x39c438(0x1a0)),'cols':numberValue(_0x4cc0fa,_0x39c438(0x180)),'latestSequence':numberValue(_0x4cc0fa,_0x39c438(0x17d)),'createdAt':numberValue(_0x4cc0fa,_0x39c438(0x1c2)),'updatedAt':numberValue(_0x4cc0fa,_0x39c438(0x1a8))};}function _0x1e1b(_0x3b836d,_0x3e1f18){_0x3b836d=_0x3b836d-(-0x1*-0x1cb7+-0x839+-0x1*0x1328);const _0xa06a18=_0x5dca();let _0x4df826=_0xa06a18[_0x3b836d];if(_0x1e1b['UUwACN']===undefined){var _0xa167ce=function(_0x7a64a1){const _0x17b45b='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x37d479='',_0x2c692d='';for(let _0x22d3c7=0x59*0x43+0xcac+-0x23f7,_0x4a9d48,_0xda9c1a,_0x395909=-0x1065+-0xb07+0x1b6c;_0xda9c1a=_0x7a64a1['charAt'](_0x395909++);~_0xda9c1a&&(_0x4a9d48=_0x22d3c7%(-0x10f*0x1+0x205e+-0x1*0x1f4b)?_0x4a9d48*(0x9e*-0x19+0x5*0x609+0x4d5*-0x3)+_0xda9c1a:_0xda9c1a,_0x22d3c7++%(-0x1043+0x2398+-0x1351))?_0x37d479+=String['fromCharCode'](-0xa0*0x8+-0x2404+0x2a03&_0x4a9d48>>(-(0x2d*0xb1+0x15ee+-0x3509)*_0x22d3c7&-0xf5*0x1d+-0x9*0x3fa+0x3f91)):0x1*-0xade+0x1a5c*0x1+-0x3*0x52a){_0xda9c1a=_0x17b45b['indexOf'](_0xda9c1a);}for(let _0x57a79c=-0x1*0x157+0x164e+-0x14f7,_0x2a4942=_0x37d479['length'];_0x57a79c<_0x2a4942;_0x57a79c++){_0x2c692d+='%'+('00'+_0x37d479['charCodeAt'](_0x57a79c)['toString'](-0xa5e+0x1bb6+-0x1148))['slice'](-(0x1c9b+-0x3b*-0x2f+-0x276e));}return decodeURIComponent(_0x2c692d);};_0x1e1b['glsSLy']=_0xa167ce,_0x1e1b['JsaIwz']={},_0x1e1b['UUwACN']=!![];}const _0x1fe41e=_0xa06a18[0x24c1*0x1+0x3be*0x5+-0x3777];_0x1e1b['asTROt']!==_0x1fe41e&&(_0x1e1b['JsaIwz']={},_0x1e1b['asTROt']=_0x1fe41e);const _0x41c23c=_0x1e1b['JsaIwz'][_0x3b836d];return _0x41c23c===undefined?(_0x4df826=_0x1e1b['glsSLy'](_0x4df826),_0x1e1b['JsaIwz'][_0x3b836d]=_0x4df826):_0x4df826=_0x41c23c,_0x4df826;}function stringValue(_0x108e4f,_0xbd714){const _0x2a605e=_0x3cc23f,_0x54efa3=_0x108e4f[_0xbd714];if(typeof _0x54efa3!==_0x2a605e(0x158))throw new Error(_0x2a605e(0x16a)+_0xbd714);return _0x54efa3;}function nullableString(_0x3fb152,_0x86f41d){const _0x3c503d=_0x3cc23f,_0x1d7a6d=_0x3fb152[_0x86f41d];if(_0x1d7a6d===null||typeof _0x1d7a6d===_0x3c503d(0x158))return _0x1d7a6d;throw new Error(_0x3c503d(0x16a)+_0x86f41d);}function nullableNumber(_0x303d5b,_0x46f8c1){const _0x13dde4=_0x3cc23f,_0x28d4ea=_0x303d5b[_0x46f8c1];if(_0x28d4ea===null||typeof _0x28d4ea===_0x13dde4(0x176))return _0x28d4ea;throw new Error(_0x13dde4(0x16a)+_0x46f8c1);}function numberValue(_0x128f9f,_0x102524){const _0x32e669=_0x3cc23f,_0x161ac1=_0x128f9f[_0x102524];if(typeof _0x161ac1!==_0x32e669(0x176))throw new Error(_0x32e669(0x16a)+_0x102524);return _0x161ac1;}