@agent-native/core 0.77.8 → 0.77.11

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 (216) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +35 -0
  3. package/corpus/core/package.json +3 -3
  4. package/corpus/core/src/a2a/task-store.ts +25 -3
  5. package/corpus/core/src/agent/harness/store.ts +89 -55
  6. package/corpus/core/src/agent/observational-memory/store.ts +40 -14
  7. package/corpus/core/src/agent/run-store.ts +116 -59
  8. package/corpus/core/src/application-state/store.ts +36 -2
  9. package/corpus/core/src/audit/store.ts +37 -6
  10. package/corpus/core/src/browser-sessions/store.ts +31 -12
  11. package/corpus/core/src/chat-threads/store.ts +67 -3
  12. package/corpus/core/src/checkpoints/store.ts +14 -3
  13. package/corpus/core/src/cli/create.ts +9 -0
  14. package/corpus/core/src/collab/awareness.ts +12 -9
  15. package/corpus/core/src/collab/client.ts +4 -2
  16. package/corpus/core/src/collab/storage.ts +20 -2
  17. package/corpus/core/src/db/ddl-guard.ts +112 -0
  18. package/corpus/core/src/extensions/store.ts +76 -3
  19. package/corpus/core/src/integrations/a2a-continuations-store.ts +69 -26
  20. package/corpus/core/src/integrations/config-store.ts +19 -18
  21. package/corpus/core/src/integrations/pending-tasks-store.ts +40 -16
  22. package/corpus/core/src/integrations/remote-commands-store.ts +37 -23
  23. package/corpus/core/src/integrations/remote-devices-store.ts +64 -20
  24. package/corpus/core/src/integrations/remote-push-store.ts +75 -35
  25. package/corpus/core/src/integrations/remote-run-events-store.ts +38 -12
  26. package/corpus/core/src/integrations/thread-mapping-store.ts +11 -2
  27. package/corpus/core/src/mcp/connect-store.ts +53 -16
  28. package/corpus/core/src/mcp/oauth-store.ts +32 -7
  29. package/corpus/core/src/notifications/store.ts +20 -4
  30. package/corpus/core/src/oauth-tokens/store.ts +45 -2
  31. package/corpus/core/src/observability/store.ts +154 -47
  32. package/corpus/core/src/progress/store.ts +36 -21
  33. package/corpus/core/src/provider-api/corpus-jobs-store.ts +25 -5
  34. package/corpus/core/src/provider-api/custom-registry.ts +15 -4
  35. package/corpus/core/src/provider-api/quota-governor.ts +15 -3
  36. package/corpus/core/src/provider-api/staged-datasets-store.ts +22 -5
  37. package/corpus/core/src/resources/store.ts +66 -31
  38. package/corpus/core/src/secrets/storage.ts +18 -22
  39. package/corpus/core/src/server/agent-teams-run-queue.ts +22 -10
  40. package/corpus/core/src/server/auth.ts +22 -4
  41. package/corpus/core/src/server/better-auth-instance.ts +49 -15
  42. package/corpus/core/src/server/embed-session.ts +19 -4
  43. package/corpus/core/src/server/identity-sso-store.ts +40 -11
  44. package/corpus/core/src/server/recap-image-store.ts +28 -9
  45. package/corpus/core/src/settings/store.ts +14 -19
  46. package/corpus/core/src/usage/store.ts +51 -16
  47. package/corpus/core/src/workspace-connections/store.ts +200 -22
  48. package/corpus/templates/calendar/changelog/2026-06-25-booking-link-previews-now-show-the-content-directly-on-the-g.md +6 -0
  49. package/corpus/templates/calendar/server/lib/booking-og-image.ts +0 -2
  50. package/corpus/templates/clips/chrome-extension/package.json +1 -1
  51. package/corpus/templates/content/actions/list-trashed-content-databases.ts +36 -2
  52. package/corpus/templates/content/actions/move-document.ts +79 -33
  53. package/corpus/templates/content/actions/restore-content-database.ts +40 -3
  54. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +84 -2
  55. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +177 -49
  56. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +393 -219
  57. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +632 -467
  58. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +114 -14
  59. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +56 -15
  60. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +6 -5
  61. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +12 -4
  62. package/corpus/templates/content/app/global.css +9 -0
  63. package/corpus/templates/content/app/hooks/use-create-page.ts +36 -7
  64. package/corpus/templates/content/app/i18n-data.ts +140 -10
  65. package/corpus/templates/content/changelog/2026-06-25-comment-cards-now-track-their-highlighted-text-while-scrolli.md +6 -0
  66. package/corpus/templates/content/changelog/2026-06-25-comments-now-scroll-with-the-document-and-stay-below-the-pag.md +6 -0
  67. package/corpus/templates/content/changelog/2026-06-25-creating-a-database-from-the-slash-menu-no-longer-leaves-sta.md +6 -0
  68. package/corpus/templates/content/changelog/2026-06-25-sidebar-hover-controls-no-longer-leave-a-lingering-fade-when.md +6 -0
  69. package/corpus/templates/content/changelog/2026-06-25-sidebar-page-actions-are-now-easier-to-see-when-hovering-ina.md +6 -0
  70. package/corpus/templates/content/changelog/2026-06-25-text-selections-in-the-editor-no-longer-show-white-gaps-when.md +6 -0
  71. package/corpus/templates/content/changelog/2026-06-25-the-editor-toolbar-now-has-a-one-click-page-link-copy-button.md +6 -0
  72. package/corpus/templates/content/changelog/2026-06-25-the-editor-toolbar-now-shows-page-breadcrumbs-and-the-latest.md +6 -0
  73. package/corpus/templates/content/changelog/2026-06-25-the-page-command-now-leaves-a-notion-style-page-reference-an.md +6 -0
  74. package/corpus/templates/content/shared/nfm.ts +16 -0
  75. package/corpus/templates/forms/changelog/2026-06-25-form-previews-now-show-the-content-directly-on-the-grid-back.md +6 -0
  76. package/corpus/templates/forms/server/lib/form-og-image.ts +0 -2
  77. package/corpus/templates/plan/app/global.css +6 -11
  78. package/corpus/templates/plan/app/pages/PlansPage.tsx +12 -10
  79. package/corpus/templates/plan/changelog/2026-06-25-plan-access-request-pages-stay-visible-during-background-ref.md +6 -0
  80. package/corpus/templates/plan/changelog/2026-06-25-plan-documents-keep-their-full-reading-width-below-1200px-an.md +6 -0
  81. package/dist/a2a/task-store.d.ts.map +1 -1
  82. package/dist/a2a/task-store.js +19 -3
  83. package/dist/a2a/task-store.js.map +1 -1
  84. package/dist/agent/harness/store.d.ts.map +1 -1
  85. package/dist/agent/harness/store.js +63 -34
  86. package/dist/agent/harness/store.js.map +1 -1
  87. package/dist/agent/observational-memory/store.d.ts.map +1 -1
  88. package/dist/agent/observational-memory/store.js +30 -8
  89. package/dist/agent/observational-memory/store.js.map +1 -1
  90. package/dist/agent/run-store.d.ts.map +1 -1
  91. package/dist/agent/run-store.js +103 -46
  92. package/dist/agent/run-store.js.map +1 -1
  93. package/dist/application-state/store.d.ts.map +1 -1
  94. package/dist/application-state/store.js +28 -2
  95. package/dist/application-state/store.js.map +1 -1
  96. package/dist/audit/store.d.ts.map +1 -1
  97. package/dist/audit/store.js +18 -3
  98. package/dist/audit/store.js.map +1 -1
  99. package/dist/browser-sessions/store.d.ts.map +1 -1
  100. package/dist/browser-sessions/store.js +22 -7
  101. package/dist/browser-sessions/store.js.map +1 -1
  102. package/dist/chat-threads/store.d.ts.map +1 -1
  103. package/dist/chat-threads/store.js +51 -3
  104. package/dist/chat-threads/store.js.map +1 -1
  105. package/dist/checkpoints/store.d.ts.map +1 -1
  106. package/dist/checkpoints/store.js +12 -3
  107. package/dist/checkpoints/store.js.map +1 -1
  108. package/dist/cli/create.d.ts.map +1 -1
  109. package/dist/cli/create.js +9 -0
  110. package/dist/cli/create.js.map +1 -1
  111. package/dist/collab/awareness.d.ts +1 -1
  112. package/dist/collab/awareness.d.ts.map +1 -1
  113. package/dist/collab/awareness.js +12 -8
  114. package/dist/collab/awareness.js.map +1 -1
  115. package/dist/collab/client.d.ts.map +1 -1
  116. package/dist/collab/client.js +4 -3
  117. package/dist/collab/client.js.map +1 -1
  118. package/dist/collab/routes.d.ts +1 -1
  119. package/dist/collab/storage.d.ts.map +1 -1
  120. package/dist/collab/storage.js +14 -2
  121. package/dist/collab/storage.js.map +1 -1
  122. package/dist/db/ddl-guard.d.ts +63 -0
  123. package/dist/db/ddl-guard.d.ts.map +1 -1
  124. package/dist/db/ddl-guard.js +85 -0
  125. package/dist/db/ddl-guard.js.map +1 -1
  126. package/dist/extensions/store.d.ts.map +1 -1
  127. package/dist/extensions/store.js +32 -3
  128. package/dist/extensions/store.js.map +1 -1
  129. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
  130. package/dist/integrations/a2a-continuations-store.js +44 -24
  131. package/dist/integrations/a2a-continuations-store.js.map +1 -1
  132. package/dist/integrations/config-store.d.ts.map +1 -1
  133. package/dist/integrations/config-store.js +17 -11
  134. package/dist/integrations/config-store.js.map +1 -1
  135. package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
  136. package/dist/integrations/pending-tasks-store.js +24 -16
  137. package/dist/integrations/pending-tasks-store.js.map +1 -1
  138. package/dist/integrations/remote-commands-store.d.ts.map +1 -1
  139. package/dist/integrations/remote-commands-store.js +29 -21
  140. package/dist/integrations/remote-commands-store.js.map +1 -1
  141. package/dist/integrations/remote-devices-store.d.ts.map +1 -1
  142. package/dist/integrations/remote-devices-store.js +33 -18
  143. package/dist/integrations/remote-devices-store.js.map +1 -1
  144. package/dist/integrations/remote-push-store.d.ts.map +1 -1
  145. package/dist/integrations/remote-push-store.js +53 -31
  146. package/dist/integrations/remote-push-store.js.map +1 -1
  147. package/dist/integrations/remote-run-events-store.d.ts.map +1 -1
  148. package/dist/integrations/remote-run-events-store.js +26 -10
  149. package/dist/integrations/remote-run-events-store.js.map +1 -1
  150. package/dist/integrations/thread-mapping-store.d.ts.map +1 -1
  151. package/dist/integrations/thread-mapping-store.js +10 -2
  152. package/dist/integrations/thread-mapping-store.js.map +1 -1
  153. package/dist/mcp/connect-store.d.ts.map +1 -1
  154. package/dist/mcp/connect-store.js +34 -16
  155. package/dist/mcp/connect-store.js.map +1 -1
  156. package/dist/mcp/oauth-store.d.ts.map +1 -1
  157. package/dist/mcp/oauth-store.js +22 -7
  158. package/dist/mcp/oauth-store.js.map +1 -1
  159. package/dist/notifications/store.d.ts.map +1 -1
  160. package/dist/notifications/store.js +15 -3
  161. package/dist/notifications/store.js.map +1 -1
  162. package/dist/oauth-tokens/store.d.ts.map +1 -1
  163. package/dist/oauth-tokens/store.js +33 -2
  164. package/dist/oauth-tokens/store.js.map +1 -1
  165. package/dist/observability/store.d.ts.map +1 -1
  166. package/dist/observability/store.js +72 -29
  167. package/dist/observability/store.js.map +1 -1
  168. package/dist/progress/store.d.ts.map +1 -1
  169. package/dist/progress/store.js +31 -16
  170. package/dist/progress/store.js.map +1 -1
  171. package/dist/provider-api/corpus-jobs-store.d.ts.map +1 -1
  172. package/dist/provider-api/corpus-jobs-store.js +16 -5
  173. package/dist/provider-api/corpus-jobs-store.js.map +1 -1
  174. package/dist/provider-api/custom-registry.d.ts.map +1 -1
  175. package/dist/provider-api/custom-registry.js +14 -4
  176. package/dist/provider-api/custom-registry.js.map +1 -1
  177. package/dist/provider-api/quota-governor.d.ts.map +1 -1
  178. package/dist/provider-api/quota-governor.js +12 -3
  179. package/dist/provider-api/quota-governor.js.map +1 -1
  180. package/dist/provider-api/staged-datasets-store.d.ts.map +1 -1
  181. package/dist/provider-api/staged-datasets-store.js +16 -5
  182. package/dist/provider-api/staged-datasets-store.js.map +1 -1
  183. package/dist/resources/store.d.ts.map +1 -1
  184. package/dist/resources/store.js +56 -25
  185. package/dist/resources/store.js.map +1 -1
  186. package/dist/secrets/storage.d.ts.map +1 -1
  187. package/dist/secrets/storage.js +10 -14
  188. package/dist/secrets/storage.js.map +1 -1
  189. package/dist/server/agent-teams-run-queue.d.ts.map +1 -1
  190. package/dist/server/agent-teams-run-queue.js +15 -4
  191. package/dist/server/agent-teams-run-queue.js.map +1 -1
  192. package/dist/server/auth.d.ts.map +1 -1
  193. package/dist/server/auth.js +16 -2
  194. package/dist/server/auth.js.map +1 -1
  195. package/dist/server/better-auth-instance.d.ts.map +1 -1
  196. package/dist/server/better-auth-instance.js +55 -21
  197. package/dist/server/better-auth-instance.js.map +1 -1
  198. package/dist/server/embed-session.d.ts.map +1 -1
  199. package/dist/server/embed-session.js +15 -4
  200. package/dist/server/embed-session.js.map +1 -1
  201. package/dist/server/identity-sso-store.d.ts.map +1 -1
  202. package/dist/server/identity-sso-store.js +30 -11
  203. package/dist/server/identity-sso-store.js.map +1 -1
  204. package/dist/server/recap-image-store.d.ts.map +1 -1
  205. package/dist/server/recap-image-store.js +21 -7
  206. package/dist/server/recap-image-store.js.map +1 -1
  207. package/dist/settings/store.d.ts.map +1 -1
  208. package/dist/settings/store.js +11 -13
  209. package/dist/settings/store.js.map +1 -1
  210. package/dist/usage/store.d.ts.map +1 -1
  211. package/dist/usage/store.js +36 -11
  212. package/dist/usage/store.js.map +1 -1
  213. package/dist/workspace-connections/store.d.ts.map +1 -1
  214. package/dist/workspace-connections/store.js +57 -7
  215. package/dist/workspace-connections/store.js.map +1 -1
  216. package/package.json +3 -3
@@ -1,27 +1,51 @@
1
- import { getDbExec, intType, isPostgres, retryOnDdlRace, } from "../../db/client.js";
1
+ import { getDbExec, intType, isPostgres } from "../../db/client.js";
2
+ import { ensureColumnExists, ensureIndexExists, ensureTableExists, } from "../../db/ddl-guard.js";
2
3
  let initPromise;
3
4
  export async function ensureAgentHarnessSessionTables() {
4
5
  if (!initPromise) {
5
6
  initPromise = (async () => {
6
7
  const client = getDbExec();
7
- await retryOnDdlRace(() => client.execute(`
8
- CREATE TABLE IF NOT EXISTS agent_harness_sessions (
9
- id TEXT PRIMARY KEY,
10
- harness_name TEXT NOT NULL,
11
- thread_id TEXT NOT NULL,
12
- run_id TEXT,
13
- provider_session_id TEXT,
14
- status TEXT NOT NULL DEFAULT 'idle',
15
- resume_state TEXT,
16
- workspace_ref TEXT,
17
- pending_approval TEXT,
18
- owner_email TEXT,
19
- org_id TEXT,
20
- created_at ${intType()} NOT NULL,
21
- updated_at ${intType()} NOT NULL,
22
- stopped_at ${intType()}
23
- )
24
- `));
8
+ const createSql = `
9
+ CREATE TABLE IF NOT EXISTS agent_harness_sessions (
10
+ id TEXT PRIMARY KEY,
11
+ harness_name TEXT NOT NULL,
12
+ thread_id TEXT NOT NULL,
13
+ run_id TEXT,
14
+ provider_session_id TEXT,
15
+ status TEXT NOT NULL DEFAULT 'idle',
16
+ resume_state TEXT,
17
+ workspace_ref TEXT,
18
+ pending_approval TEXT,
19
+ owner_email TEXT,
20
+ org_id TEXT,
21
+ created_at ${intType()} NOT NULL,
22
+ updated_at ${intType()} NOT NULL,
23
+ stopped_at ${intType()}
24
+ )
25
+ `;
26
+ if (isPostgres()) {
27
+ // PG-guard: probe information_schema / pg_indexes before issuing DDL to
28
+ // avoid ACCESS EXCLUSIVE lock contention in fresh background-worker processes.
29
+ await ensureTableExists("agent_harness_sessions", createSql);
30
+ for (const col of [
31
+ "run_id",
32
+ "provider_session_id",
33
+ "resume_state",
34
+ "workspace_ref",
35
+ "pending_approval",
36
+ "owner_email",
37
+ "org_id",
38
+ ]) {
39
+ await ensureColumnExists("agent_harness_sessions", col, `ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS ${col} TEXT`);
40
+ }
41
+ await ensureColumnExists("agent_harness_sessions", "stopped_at", `ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS stopped_at ${intType()}`);
42
+ await ensureIndexExists("idx_agent_harness_sessions_thread", `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`);
43
+ await ensureIndexExists("idx_agent_harness_sessions_status", `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`);
44
+ await ensureIndexExists("idx_agent_harness_sessions_owner", `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`);
45
+ return;
46
+ }
47
+ // SQLite (local dev): no lock problem — keep the original behaviour.
48
+ await client.execute(createSql);
25
49
  for (const col of [
26
50
  "run_id",
27
51
  "provider_session_id",
@@ -32,31 +56,36 @@ export async function ensureAgentHarnessSessionTables() {
32
56
  "org_id",
33
57
  ]) {
34
58
  try {
35
- if (isPostgres()) {
36
- await client.execute(`ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS ${col} TEXT`);
37
- }
38
- else {
39
- await client.execute(`ALTER TABLE agent_harness_sessions ADD COLUMN ${col} TEXT`);
40
- }
59
+ await client.execute(`ALTER TABLE agent_harness_sessions ADD COLUMN ${col} TEXT`);
41
60
  }
42
61
  catch {
43
62
  // Column already exists.
44
63
  }
45
64
  }
46
65
  try {
47
- if (isPostgres()) {
48
- await client.execute(`ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS stopped_at ${intType()}`);
49
- }
50
- else {
51
- await client.execute(`ALTER TABLE agent_harness_sessions ADD COLUMN stopped_at ${intType()}`);
52
- }
66
+ await client.execute(`ALTER TABLE agent_harness_sessions ADD COLUMN stopped_at ${intType()}`);
53
67
  }
54
68
  catch {
55
69
  // Column already exists.
56
70
  }
57
- await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`));
58
- await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`));
59
- await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`));
71
+ try {
72
+ await client.execute(`CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`);
73
+ }
74
+ catch {
75
+ // Index already exists.
76
+ }
77
+ try {
78
+ await client.execute(`CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`);
79
+ }
80
+ catch {
81
+ // Index already exists.
82
+ }
83
+ try {
84
+ await client.execute(`CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`);
85
+ }
86
+ catch {
87
+ // Index already exists.
88
+ }
60
89
  })().catch((err) => {
61
90
  initPromise = undefined;
62
91
  throw err;
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/agent/harness/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n intType,\n isPostgres,\n retryOnDdlRace,\n} from \"../../db/client.js\";\n\nexport type AgentHarnessSessionStatus =\n | \"running\"\n | \"idle\"\n | \"stopped\"\n | \"errored\"\n | \"destroyed\";\n\nexport interface StoredAgentHarnessSession {\n id: string;\n harnessName: string;\n threadId: string;\n runId?: string | null;\n providerSessionId?: string | null;\n status: AgentHarnessSessionStatus;\n resumeState?: unknown;\n workspaceRef?: string | null;\n pendingApproval?: unknown;\n ownerEmail?: string | null;\n orgId?: string | null;\n createdAt: number;\n updatedAt: number;\n stoppedAt?: number | null;\n}\n\nexport interface SaveAgentHarnessSessionInput {\n id: string;\n harnessName: string;\n threadId: string;\n runId?: string | null;\n providerSessionId?: string | null;\n status?: AgentHarnessSessionStatus;\n resumeState?: unknown;\n workspaceRef?: string | null;\n pendingApproval?: unknown;\n ownerEmail?: string | null;\n orgId?: string | null;\n stoppedAt?: number | null;\n}\n\nlet initPromise: Promise<void> | undefined;\n\nexport async function ensureAgentHarnessSessionTables(): Promise<void> {\n if (!initPromise) {\n initPromise = (async () => {\n const client = getDbExec();\n await retryOnDdlRace(() =>\n client.execute(`\n CREATE TABLE IF NOT EXISTS agent_harness_sessions (\n id TEXT PRIMARY KEY,\n harness_name TEXT NOT NULL,\n thread_id TEXT NOT NULL,\n run_id TEXT,\n provider_session_id TEXT,\n status TEXT NOT NULL DEFAULT 'idle',\n resume_state TEXT,\n workspace_ref TEXT,\n pending_approval TEXT,\n owner_email TEXT,\n org_id TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n stopped_at ${intType()}\n )\n `),\n );\n for (const col of [\n \"run_id\",\n \"provider_session_id\",\n \"resume_state\",\n \"workspace_ref\",\n \"pending_approval\",\n \"owner_email\",\n \"org_id\",\n ] as const) {\n try {\n if (isPostgres()) {\n await client.execute(\n `ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS ${col} TEXT`,\n );\n } else {\n await client.execute(\n `ALTER TABLE agent_harness_sessions ADD COLUMN ${col} TEXT`,\n );\n }\n } catch {\n // Column already exists.\n }\n }\n try {\n if (isPostgres()) {\n await client.execute(\n `ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS stopped_at ${intType()}`,\n );\n } else {\n await client.execute(\n `ALTER TABLE agent_harness_sessions ADD COLUMN stopped_at ${intType()}`,\n );\n }\n } catch {\n // Column already exists.\n }\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`,\n ),\n );\n })().catch((err) => {\n initPromise = undefined;\n throw err;\n });\n }\n return initPromise;\n}\n\nexport async function saveAgentHarnessSession(\n input: SaveAgentHarnessSessionInput,\n): Promise<StoredAgentHarnessSession> {\n await ensureAgentHarnessSessionTables();\n const now = Date.now();\n const existing = await getAgentHarnessSession(input.id);\n const record: StoredAgentHarnessSession = {\n id: input.id,\n harnessName: input.harnessName,\n threadId: input.threadId,\n runId: input.runId ?? null,\n providerSessionId: input.providerSessionId ?? null,\n status: input.status ?? existing?.status ?? \"idle\",\n resumeState:\n input.resumeState !== undefined\n ? input.resumeState\n : existing?.resumeState,\n workspaceRef: input.workspaceRef ?? existing?.workspaceRef ?? null,\n pendingApproval:\n input.pendingApproval !== undefined\n ? input.pendingApproval\n : existing?.pendingApproval,\n ownerEmail: input.ownerEmail ?? existing?.ownerEmail ?? null,\n orgId: input.orgId ?? existing?.orgId ?? null,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n stoppedAt: input.stoppedAt ?? existing?.stoppedAt ?? null,\n };\n const client = getDbExec();\n await client.execute({\n sql: `INSERT INTO agent_harness_sessions (\n id, harness_name, thread_id, run_id, provider_session_id, status,\n resume_state, workspace_ref, pending_approval, owner_email, org_id,\n created_at, updated_at, stopped_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n harness_name = excluded.harness_name,\n thread_id = excluded.thread_id,\n run_id = excluded.run_id,\n provider_session_id = excluded.provider_session_id,\n status = excluded.status,\n resume_state = excluded.resume_state,\n workspace_ref = excluded.workspace_ref,\n pending_approval = excluded.pending_approval,\n owner_email = excluded.owner_email,\n org_id = excluded.org_id,\n updated_at = excluded.updated_at,\n stopped_at = excluded.stopped_at`,\n args: [\n record.id,\n record.harnessName,\n record.threadId,\n record.runId ?? null,\n record.providerSessionId ?? null,\n record.status,\n serializeJson(record.resumeState),\n record.workspaceRef ?? null,\n serializeJson(record.pendingApproval),\n record.ownerEmail ?? null,\n record.orgId ?? null,\n record.createdAt,\n record.updatedAt,\n record.stoppedAt ?? null,\n ],\n });\n return record;\n}\n\nexport async function updateAgentHarnessSession(\n id: string,\n patch: Partial<Omit<SaveAgentHarnessSessionInput, \"id\">>,\n): Promise<StoredAgentHarnessSession | null> {\n const existing = await getAgentHarnessSession(id);\n if (!existing) return null;\n return saveAgentHarnessSession({\n id,\n harnessName: patch.harnessName ?? existing.harnessName,\n threadId: patch.threadId ?? existing.threadId,\n runId: patch.runId ?? existing.runId ?? null,\n providerSessionId:\n patch.providerSessionId ?? existing.providerSessionId ?? null,\n status: patch.status ?? existing.status,\n resumeState:\n patch.resumeState !== undefined\n ? patch.resumeState\n : existing.resumeState,\n workspaceRef: patch.workspaceRef ?? existing.workspaceRef ?? null,\n pendingApproval:\n patch.pendingApproval !== undefined\n ? patch.pendingApproval\n : existing.pendingApproval,\n ownerEmail: patch.ownerEmail ?? existing.ownerEmail ?? null,\n orgId: patch.orgId ?? existing.orgId ?? null,\n stoppedAt: patch.stoppedAt ?? existing.stoppedAt ?? null,\n });\n}\n\nexport async function getAgentHarnessSession(\n id: string,\n): Promise<StoredAgentHarnessSession | null> {\n await ensureAgentHarnessSessionTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions WHERE id = ?`,\n args: [id],\n });\n return rowToHarnessSession(rows[0]);\n}\n\nexport async function getLatestAgentHarnessSessionForThread(\n threadId: string,\n harnessName?: string,\n): Promise<StoredAgentHarnessSession | null> {\n await ensureAgentHarnessSessionTables();\n const client = getDbExec();\n const { rows } = harnessName\n ? await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ? AND harness_name = ? AND status != 'destroyed'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [threadId, harnessName],\n })\n : await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ? AND status != 'destroyed'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [threadId],\n });\n return rowToHarnessSession(rows[0]);\n}\n\nexport async function getAgentHarnessSessionByRunId(\n runId: string,\n): Promise<StoredAgentHarnessSession | null> {\n await ensureAgentHarnessSessionTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE run_id = ?\n ORDER BY updated_at DESC LIMIT 1`,\n args: [runId],\n });\n return rowToHarnessSession(rows[0]);\n}\n\nexport async function listAgentHarnessSessions(\n options: {\n status?: AgentHarnessSessionStatus;\n threadId?: string;\n ownerEmail?: string | null;\n orgId?: string | null;\n limit?: number;\n } = {},\n): Promise<StoredAgentHarnessSession[]> {\n await ensureAgentHarnessSessionTables();\n const limit = Math.max(1, Math.min(200, options.limit ?? 50));\n const client = getDbExec();\n if (options.ownerEmail) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE owner_email = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.ownerEmail, limit],\n });\n const sessions = rows.map(rowToHarnessSession).filter(isStoredSession);\n return sessions.filter(\n (session) =>\n (!options.threadId || session.threadId === options.threadId) &&\n (!options.status || session.status === options.status) &&\n (!options.orgId || session.orgId === options.orgId),\n );\n }\n if (options.threadId && options.status) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ? AND status = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.threadId, options.status, limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n }\n if (options.threadId) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.threadId, limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n }\n if (options.status) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE status = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.status, limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n }\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n ORDER BY updated_at DESC LIMIT ?`,\n args: [limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n}\n\nexport async function markAgentHarnessSessionStopped(\n id: string,\n status: Extract<\n AgentHarnessSessionStatus,\n \"stopped\" | \"destroyed\" | \"errored\"\n >,\n): Promise<StoredAgentHarnessSession | null> {\n return updateAgentHarnessSession(id, {\n status,\n stoppedAt: Date.now(),\n pendingApproval: null,\n });\n}\n\nfunction rowToHarnessSession(row: unknown): StoredAgentHarnessSession | null {\n if (!row || typeof row !== \"object\") return null;\n const record = row as Record<string, unknown>;\n return {\n id: String(record.id),\n harnessName: String(record.harness_name),\n threadId: String(record.thread_id),\n runId: stringOrNull(record.run_id),\n providerSessionId: stringOrNull(record.provider_session_id),\n status: normalizeStatus(record.status),\n resumeState: parseJson(record.resume_state),\n workspaceRef: stringOrNull(record.workspace_ref),\n pendingApproval: parseJson(record.pending_approval),\n ownerEmail: stringOrNull(record.owner_email),\n orgId: stringOrNull(record.org_id),\n createdAt: numberValue(record.created_at),\n updatedAt: numberValue(record.updated_at),\n stoppedAt:\n record.stopped_at === null || record.stopped_at === undefined\n ? null\n : numberValue(record.stopped_at),\n };\n}\n\nfunction isStoredSession(\n session: StoredAgentHarnessSession | null,\n): session is StoredAgentHarnessSession {\n return Boolean(session);\n}\n\nfunction normalizeStatus(value: unknown): AgentHarnessSessionStatus {\n return value === \"running\" ||\n value === \"idle\" ||\n value === \"stopped\" ||\n value === \"errored\" ||\n value === \"destroyed\"\n ? value\n : \"idle\";\n}\n\nfunction serializeJson(value: unknown): string | null {\n if (value === undefined || value === null) return null;\n return JSON.stringify(value);\n}\n\nfunction parseJson(value: unknown): unknown {\n if (typeof value !== \"string\" || !value) return undefined;\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nfunction stringOrNull(value: unknown): string | null {\n return typeof value === \"string\" && value ? value : null;\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" ? value : Number(value ?? 0);\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/agent/harness/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec, intType, isPostgres } from \"../../db/client.js\";\nimport {\n ensureColumnExists,\n ensureIndexExists,\n ensureTableExists,\n} from \"../../db/ddl-guard.js\";\n\nexport type AgentHarnessSessionStatus =\n | \"running\"\n | \"idle\"\n | \"stopped\"\n | \"errored\"\n | \"destroyed\";\n\nexport interface StoredAgentHarnessSession {\n id: string;\n harnessName: string;\n threadId: string;\n runId?: string | null;\n providerSessionId?: string | null;\n status: AgentHarnessSessionStatus;\n resumeState?: unknown;\n workspaceRef?: string | null;\n pendingApproval?: unknown;\n ownerEmail?: string | null;\n orgId?: string | null;\n createdAt: number;\n updatedAt: number;\n stoppedAt?: number | null;\n}\n\nexport interface SaveAgentHarnessSessionInput {\n id: string;\n harnessName: string;\n threadId: string;\n runId?: string | null;\n providerSessionId?: string | null;\n status?: AgentHarnessSessionStatus;\n resumeState?: unknown;\n workspaceRef?: string | null;\n pendingApproval?: unknown;\n ownerEmail?: string | null;\n orgId?: string | null;\n stoppedAt?: number | null;\n}\n\nlet initPromise: Promise<void> | undefined;\n\nexport async function ensureAgentHarnessSessionTables(): Promise<void> {\n if (!initPromise) {\n initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS agent_harness_sessions (\n id TEXT PRIMARY KEY,\n harness_name TEXT NOT NULL,\n thread_id TEXT NOT NULL,\n run_id TEXT,\n provider_session_id TEXT,\n status TEXT NOT NULL DEFAULT 'idle',\n resume_state TEXT,\n workspace_ref TEXT,\n pending_approval TEXT,\n owner_email TEXT,\n org_id TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n stopped_at ${intType()}\n )\n `;\n\n if (isPostgres()) {\n // PG-guard: probe information_schema / pg_indexes before issuing DDL to\n // avoid ACCESS EXCLUSIVE lock contention in fresh background-worker processes.\n await ensureTableExists(\"agent_harness_sessions\", createSql);\n for (const col of [\n \"run_id\",\n \"provider_session_id\",\n \"resume_state\",\n \"workspace_ref\",\n \"pending_approval\",\n \"owner_email\",\n \"org_id\",\n ] as const) {\n await ensureColumnExists(\n \"agent_harness_sessions\",\n col,\n `ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS ${col} TEXT`,\n );\n }\n await ensureColumnExists(\n \"agent_harness_sessions\",\n \"stopped_at\",\n `ALTER TABLE agent_harness_sessions ADD COLUMN IF NOT EXISTS stopped_at ${intType()}`,\n );\n await ensureIndexExists(\n \"idx_agent_harness_sessions_thread\",\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`,\n );\n await ensureIndexExists(\n \"idx_agent_harness_sessions_status\",\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`,\n );\n await ensureIndexExists(\n \"idx_agent_harness_sessions_owner\",\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n for (const col of [\n \"run_id\",\n \"provider_session_id\",\n \"resume_state\",\n \"workspace_ref\",\n \"pending_approval\",\n \"owner_email\",\n \"org_id\",\n ] as const) {\n try {\n await client.execute(\n `ALTER TABLE agent_harness_sessions ADD COLUMN ${col} TEXT`,\n );\n } catch {\n // Column already exists.\n }\n }\n try {\n await client.execute(\n `ALTER TABLE agent_harness_sessions ADD COLUMN stopped_at ${intType()}`,\n );\n } catch {\n // Column already exists.\n }\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`,\n );\n } catch {\n // Index already exists.\n }\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`,\n );\n } catch {\n // Index already exists.\n }\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`,\n );\n } catch {\n // Index already exists.\n }\n })().catch((err) => {\n initPromise = undefined;\n throw err;\n });\n }\n return initPromise;\n}\n\nexport async function saveAgentHarnessSession(\n input: SaveAgentHarnessSessionInput,\n): Promise<StoredAgentHarnessSession> {\n await ensureAgentHarnessSessionTables();\n const now = Date.now();\n const existing = await getAgentHarnessSession(input.id);\n const record: StoredAgentHarnessSession = {\n id: input.id,\n harnessName: input.harnessName,\n threadId: input.threadId,\n runId: input.runId ?? null,\n providerSessionId: input.providerSessionId ?? null,\n status: input.status ?? existing?.status ?? \"idle\",\n resumeState:\n input.resumeState !== undefined\n ? input.resumeState\n : existing?.resumeState,\n workspaceRef: input.workspaceRef ?? existing?.workspaceRef ?? null,\n pendingApproval:\n input.pendingApproval !== undefined\n ? input.pendingApproval\n : existing?.pendingApproval,\n ownerEmail: input.ownerEmail ?? existing?.ownerEmail ?? null,\n orgId: input.orgId ?? existing?.orgId ?? null,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n stoppedAt: input.stoppedAt ?? existing?.stoppedAt ?? null,\n };\n const client = getDbExec();\n await client.execute({\n sql: `INSERT INTO agent_harness_sessions (\n id, harness_name, thread_id, run_id, provider_session_id, status,\n resume_state, workspace_ref, pending_approval, owner_email, org_id,\n created_at, updated_at, stopped_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n harness_name = excluded.harness_name,\n thread_id = excluded.thread_id,\n run_id = excluded.run_id,\n provider_session_id = excluded.provider_session_id,\n status = excluded.status,\n resume_state = excluded.resume_state,\n workspace_ref = excluded.workspace_ref,\n pending_approval = excluded.pending_approval,\n owner_email = excluded.owner_email,\n org_id = excluded.org_id,\n updated_at = excluded.updated_at,\n stopped_at = excluded.stopped_at`,\n args: [\n record.id,\n record.harnessName,\n record.threadId,\n record.runId ?? null,\n record.providerSessionId ?? null,\n record.status,\n serializeJson(record.resumeState),\n record.workspaceRef ?? null,\n serializeJson(record.pendingApproval),\n record.ownerEmail ?? null,\n record.orgId ?? null,\n record.createdAt,\n record.updatedAt,\n record.stoppedAt ?? null,\n ],\n });\n return record;\n}\n\nexport async function updateAgentHarnessSession(\n id: string,\n patch: Partial<Omit<SaveAgentHarnessSessionInput, \"id\">>,\n): Promise<StoredAgentHarnessSession | null> {\n const existing = await getAgentHarnessSession(id);\n if (!existing) return null;\n return saveAgentHarnessSession({\n id,\n harnessName: patch.harnessName ?? existing.harnessName,\n threadId: patch.threadId ?? existing.threadId,\n runId: patch.runId ?? existing.runId ?? null,\n providerSessionId:\n patch.providerSessionId ?? existing.providerSessionId ?? null,\n status: patch.status ?? existing.status,\n resumeState:\n patch.resumeState !== undefined\n ? patch.resumeState\n : existing.resumeState,\n workspaceRef: patch.workspaceRef ?? existing.workspaceRef ?? null,\n pendingApproval:\n patch.pendingApproval !== undefined\n ? patch.pendingApproval\n : existing.pendingApproval,\n ownerEmail: patch.ownerEmail ?? existing.ownerEmail ?? null,\n orgId: patch.orgId ?? existing.orgId ?? null,\n stoppedAt: patch.stoppedAt ?? existing.stoppedAt ?? null,\n });\n}\n\nexport async function getAgentHarnessSession(\n id: string,\n): Promise<StoredAgentHarnessSession | null> {\n await ensureAgentHarnessSessionTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions WHERE id = ?`,\n args: [id],\n });\n return rowToHarnessSession(rows[0]);\n}\n\nexport async function getLatestAgentHarnessSessionForThread(\n threadId: string,\n harnessName?: string,\n): Promise<StoredAgentHarnessSession | null> {\n await ensureAgentHarnessSessionTables();\n const client = getDbExec();\n const { rows } = harnessName\n ? await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ? AND harness_name = ? AND status != 'destroyed'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [threadId, harnessName],\n })\n : await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ? AND status != 'destroyed'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [threadId],\n });\n return rowToHarnessSession(rows[0]);\n}\n\nexport async function getAgentHarnessSessionByRunId(\n runId: string,\n): Promise<StoredAgentHarnessSession | null> {\n await ensureAgentHarnessSessionTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE run_id = ?\n ORDER BY updated_at DESC LIMIT 1`,\n args: [runId],\n });\n return rowToHarnessSession(rows[0]);\n}\n\nexport async function listAgentHarnessSessions(\n options: {\n status?: AgentHarnessSessionStatus;\n threadId?: string;\n ownerEmail?: string | null;\n orgId?: string | null;\n limit?: number;\n } = {},\n): Promise<StoredAgentHarnessSession[]> {\n await ensureAgentHarnessSessionTables();\n const limit = Math.max(1, Math.min(200, options.limit ?? 50));\n const client = getDbExec();\n if (options.ownerEmail) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE owner_email = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.ownerEmail, limit],\n });\n const sessions = rows.map(rowToHarnessSession).filter(isStoredSession);\n return sessions.filter(\n (session) =>\n (!options.threadId || session.threadId === options.threadId) &&\n (!options.status || session.status === options.status) &&\n (!options.orgId || session.orgId === options.orgId),\n );\n }\n if (options.threadId && options.status) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ? AND status = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.threadId, options.status, limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n }\n if (options.threadId) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE thread_id = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.threadId, limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n }\n if (options.status) {\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n WHERE status = ?\n ORDER BY updated_at DESC LIMIT ?`,\n args: [options.status, limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n }\n const { rows } = await client.execute({\n sql: `SELECT * FROM agent_harness_sessions\n ORDER BY updated_at DESC LIMIT ?`,\n args: [limit],\n });\n return rows.map(rowToHarnessSession).filter(isStoredSession);\n}\n\nexport async function markAgentHarnessSessionStopped(\n id: string,\n status: Extract<\n AgentHarnessSessionStatus,\n \"stopped\" | \"destroyed\" | \"errored\"\n >,\n): Promise<StoredAgentHarnessSession | null> {\n return updateAgentHarnessSession(id, {\n status,\n stoppedAt: Date.now(),\n pendingApproval: null,\n });\n}\n\nfunction rowToHarnessSession(row: unknown): StoredAgentHarnessSession | null {\n if (!row || typeof row !== \"object\") return null;\n const record = row as Record<string, unknown>;\n return {\n id: String(record.id),\n harnessName: String(record.harness_name),\n threadId: String(record.thread_id),\n runId: stringOrNull(record.run_id),\n providerSessionId: stringOrNull(record.provider_session_id),\n status: normalizeStatus(record.status),\n resumeState: parseJson(record.resume_state),\n workspaceRef: stringOrNull(record.workspace_ref),\n pendingApproval: parseJson(record.pending_approval),\n ownerEmail: stringOrNull(record.owner_email),\n orgId: stringOrNull(record.org_id),\n createdAt: numberValue(record.created_at),\n updatedAt: numberValue(record.updated_at),\n stoppedAt:\n record.stopped_at === null || record.stopped_at === undefined\n ? null\n : numberValue(record.stopped_at),\n };\n}\n\nfunction isStoredSession(\n session: StoredAgentHarnessSession | null,\n): session is StoredAgentHarnessSession {\n return Boolean(session);\n}\n\nfunction normalizeStatus(value: unknown): AgentHarnessSessionStatus {\n return value === \"running\" ||\n value === \"idle\" ||\n value === \"stopped\" ||\n value === \"errored\" ||\n value === \"destroyed\"\n ? value\n : \"idle\";\n}\n\nfunction serializeJson(value: unknown): string | null {\n if (value === undefined || value === null) return null;\n return JSON.stringify(value);\n}\n\nfunction parseJson(value: unknown): unknown {\n if (typeof value !== \"string\" || !value) return undefined;\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nfunction stringOrNull(value: unknown): string | null {\n return typeof value === \"string\" && value ? value : null;\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" ? value : Number(value ?? 0);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/agent/observational-memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AA0CpB,6DAA6D;AAC7D,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D;AAqDD,MAAM,WAAW,8BAA+B,SAAQ,wBAAwB;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;CAC3C;AAED,wDAAwD;AACxD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,CAAC,CAyCnC;AAED,MAAM,WAAW,8BAA+B,SAAQ,wBAAwB;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,IAAI,CAAC,EAAE,uBAAuB,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAiBrC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,8EAA8E;AAC9E,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAcjB"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/agent/observational-memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAoEpB,6DAA6D;AAC7D,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D;AAqDD,MAAM,WAAW,8BAA+B,SAAQ,wBAAwB;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;CAC3C;AAED,wDAAwD;AACxD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,CAAC,CAyCnC;AAED,MAAM,WAAW,8BAA+B,SAAQ,wBAAwB;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,IAAI,CAAC,EAAE,uBAAuB,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAiBrC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,8EAA8E;AAC9E,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAcjB"}
@@ -11,8 +11,8 @@
11
11
  * suspenders pattern as `chat-threads/store.ts`), so OM works in tests and at
12
12
  * runtime even before the migration plugin is registered.
13
13
  */
14
- import { getDbExec } from "../../db/client.js";
15
- import { isPostgres } from "../../db/client.js";
14
+ import { getDbExec, isPostgres } from "../../db/client.js";
15
+ import { ensureTableExists, ensureIndexExists } from "../../db/ddl-guard.js";
16
16
  let tableReady = null;
17
17
  async function ensureTable() {
18
18
  if (tableReady)
@@ -20,7 +20,7 @@ async function ensureTable() {
20
20
  tableReady = (async () => {
21
21
  const client = getDbExec();
22
22
  const intType = isPostgres() ? "BIGINT" : "INTEGER";
23
- await client.execute(`CREATE TABLE IF NOT EXISTS observational_memory (
23
+ const createSql = `CREATE TABLE IF NOT EXISTS observational_memory (
24
24
  id TEXT PRIMARY KEY,
25
25
  thread_id TEXT NOT NULL,
26
26
  tier TEXT NOT NULL,
@@ -34,11 +34,33 @@ async function ensureTable() {
34
34
  owner_email TEXT NOT NULL,
35
35
  org_id TEXT,
36
36
  visibility TEXT NOT NULL DEFAULT 'private'
37
- )`);
38
- await client.execute(`CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx
39
- ON observational_memory(thread_id, tier, created_at)`);
40
- await client.execute(`CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx
41
- ON observational_memory(thread_id, owner_email)`);
37
+ )`;
38
+ if (isPostgres()) {
39
+ // PG-guard: probe information_schema / pg_indexes before issuing DDL to
40
+ // avoid ACCESS EXCLUSIVE lock contention in fresh background-worker processes.
41
+ await ensureTableExists("observational_memory", createSql);
42
+ await ensureIndexExists("observational_memory_thread_tier_idx", `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx
43
+ ON observational_memory(thread_id, tier, created_at)`);
44
+ await ensureIndexExists("observational_memory_thread_owner_idx", `CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx
45
+ ON observational_memory(thread_id, owner_email)`);
46
+ return;
47
+ }
48
+ // SQLite (local dev): no lock problem — keep the original behaviour.
49
+ await client.execute(createSql);
50
+ try {
51
+ await client.execute(`CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx
52
+ ON observational_memory(thread_id, tier, created_at)`);
53
+ }
54
+ catch {
55
+ // Index already exists.
56
+ }
57
+ try {
58
+ await client.execute(`CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx
59
+ ON observational_memory(thread_id, owner_email)`);
60
+ }
61
+ catch {
62
+ // Index already exists.
63
+ }
42
64
  })().catch((err) => {
43
65
  // Reset so a transient failure (e.g. SQLITE_BUSY on HMR) can retry.
44
66
  tableReady = null;
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/agent/observational-memory/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Persistence for Observational Memory entries.\n *\n * Owner-scoped throughout: every read and write takes an `ownerEmail` and the\n * SQL always filters by it, so the ownable table is never read or written\n * cross-owner (per the `security` skill). Dialect-agnostic — only `getDbExec()`\n * and parameterized SQL, never raw SQLite/Postgres types or string interpolation\n * of user data.\n *\n * `ensureTable()` lazily creates the table on first use (the same belt-and-\n * suspenders pattern as `chat-threads/store.ts`), so OM works in tests and at\n * runtime even before the migration plugin is registered.\n */\n\nimport { getDbExec } from \"../../db/client.js\";\nimport { isPostgres } from \"../../db/client.js\";\nimport type {\n ObservationalMemoryEntry,\n ObservationalMemoryOwner,\n ObservationalMemoryTier,\n} from \"./types.js\";\n\nlet tableReady: Promise<void> | null = null;\n\nasync function ensureTable(): Promise<void> {\n if (tableReady) return tableReady;\n tableReady = (async () => {\n const client = getDbExec();\n const intType = isPostgres() ? \"BIGINT\" : \"INTEGER\";\n await client.execute(\n `CREATE TABLE IF NOT EXISTS observational_memory (\n id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n tier TEXT NOT NULL,\n text TEXT NOT NULL,\n token_estimate ${intType} NOT NULL DEFAULT 0,\n source_start_index ${intType},\n source_end_index ${intType},\n source_message_count ${intType} NOT NULL DEFAULT 0,\n created_at ${intType} NOT NULL,\n updated_at ${intType} NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n )`,\n );\n await client.execute(\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx\n ON observational_memory(thread_id, tier, created_at)`,\n );\n await client.execute(\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx\n ON observational_memory(thread_id, owner_email)`,\n );\n })().catch((err) => {\n // Reset so a transient failure (e.g. SQLITE_BUSY on HMR) can retry.\n tableReady = null;\n throw err;\n });\n return tableReady;\n}\n\n/** Reset the cached ensureTable promise — test-only seam. */\nexport function __resetObservationalMemoryTableCache(): void {\n tableReady = null;\n}\n\nfunction entryId(): string {\n return `om-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction numOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null;\n const n = Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction rowToEntry(row: Record<string, unknown>): ObservationalMemoryEntry {\n const ownerEmail =\n typeof row.owner_email === \"string\" && row.owner_email.trim()\n ? row.owner_email\n : null;\n if (!ownerEmail) {\n throw new Error(\"Observational memory row is missing owner_email.\");\n }\n return {\n id: String(row.id),\n threadId: String(row.thread_id),\n tier: row.tier as ObservationalMemoryTier,\n text: typeof row.text === \"string\" ? row.text : \"\",\n tokenEstimate: Number(row.token_estimate) || 0,\n sourceStartIndex: numOrNull(row.source_start_index),\n sourceEndIndex: numOrNull(row.source_end_index),\n sourceMessageCount: Number(row.source_message_count) || 0,\n createdAt: Number(row.created_at) || 0,\n updatedAt: Number(row.updated_at) || 0,\n ownerEmail,\n orgId: typeof row.org_id === \"string\" ? row.org_id : null,\n visibility:\n (row.visibility as ObservationalMemoryEntry[\"visibility\"]) ?? \"private\",\n };\n}\n\nfunction addOwnerScope(\n clauses: string[],\n args: unknown[],\n owner: ObservationalMemoryOwner,\n): void {\n clauses.push(\"owner_email = ?\");\n args.push(owner.ownerEmail);\n if (owner.orgId == null) {\n clauses.push(\"org_id IS NULL\");\n } else {\n clauses.push(\"org_id = ?\");\n args.push(owner.orgId);\n }\n}\n\nexport interface InsertObservationalMemoryInput extends ObservationalMemoryOwner {\n threadId: string;\n tier: ObservationalMemoryTier;\n text: string;\n tokenEstimate: number;\n sourceStartIndex?: number | null;\n sourceEndIndex?: number | null;\n sourceMessageCount?: number;\n visibility?: \"private\" | \"org\" | \"public\";\n}\n\n/** Insert one OM entry, returning the persisted row. */\nexport async function insertObservationalMemory(\n input: InsertObservationalMemoryInput,\n): Promise<ObservationalMemoryEntry> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = entryId();\n const entry: ObservationalMemoryEntry = {\n id,\n threadId: input.threadId,\n tier: input.tier,\n text: input.text,\n tokenEstimate: input.tokenEstimate,\n sourceStartIndex: input.sourceStartIndex ?? null,\n sourceEndIndex: input.sourceEndIndex ?? null,\n sourceMessageCount: input.sourceMessageCount ?? 0,\n createdAt: now,\n updatedAt: now,\n ownerEmail: input.ownerEmail,\n orgId: input.orgId ?? null,\n visibility: input.visibility ?? \"private\",\n };\n await client.execute({\n sql: `INSERT INTO observational_memory\n (id, thread_id, tier, text, token_estimate, source_start_index, source_end_index, source_message_count, created_at, updated_at, owner_email, org_id, visibility)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n entry.id,\n entry.threadId,\n entry.tier,\n entry.text,\n entry.tokenEstimate,\n entry.sourceStartIndex,\n entry.sourceEndIndex,\n entry.sourceMessageCount,\n entry.createdAt,\n entry.updatedAt,\n entry.ownerEmail,\n entry.orgId,\n entry.visibility,\n ],\n });\n return entry;\n}\n\nexport interface ListObservationalMemoryOptions extends ObservationalMemoryOwner {\n threadId: string;\n /** When set, only entries of this tier are returned. */\n tier?: ObservationalMemoryTier;\n}\n\n/**\n * List a thread's OM entries for an owner, oldest → newest. Always\n * owner-scoped; `org_id` is matched too when supplied so org-visible rows\n * don't leak across orgs.\n */\nexport async function listObservationalMemory(\n options: ListObservationalMemoryOptions,\n): Promise<ObservationalMemoryEntry[]> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n if (options.tier) {\n clauses.push(\"tier = ?\");\n args.push(options.tier);\n }\n const result = await client.execute({\n sql: `SELECT * FROM observational_memory WHERE ${clauses.join(\n \" AND \",\n )} ORDER BY created_at ASC, id ASC`,\n args,\n });\n return (result.rows as Record<string, unknown>[]).map(rowToEntry);\n}\n\n/**\n * The highest source-message index already folded into an observation for this\n * thread/owner, or -1 if none. The Observer uses this to know which messages\n * are still unobserved.\n */\nexport async function getObservedThroughIndex(\n options: ObservationalMemoryOwner & { threadId: string },\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\", \"tier = 'observation'\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n const result = await client.execute({\n sql: `SELECT MAX(source_end_index) AS max_idx\n FROM observational_memory\n WHERE ${clauses.join(\" AND \")}`,\n args,\n });\n const row = (result.rows as Record<string, unknown>[])[0];\n const max = numOrNull(row?.max_idx);\n return max == null ? -1 : max;\n}\n\n/** Sum the token estimates of a thread's observation entries for an owner. */\nexport async function getObservationLogTokens(\n options: ObservationalMemoryOwner & { threadId: string },\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\", \"tier = 'observation'\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n const result = await client.execute({\n sql: `SELECT COALESCE(SUM(token_estimate), 0) AS total\n FROM observational_memory\n WHERE ${clauses.join(\" AND \")}`,\n args,\n });\n const row = (result.rows as Record<string, unknown>[])[0];\n return Number(row?.total) || 0;\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/agent/observational-memory/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Persistence for Observational Memory entries.\n *\n * Owner-scoped throughout: every read and write takes an `ownerEmail` and the\n * SQL always filters by it, so the ownable table is never read or written\n * cross-owner (per the `security` skill). Dialect-agnostic — only `getDbExec()`\n * and parameterized SQL, never raw SQLite/Postgres types or string interpolation\n * of user data.\n *\n * `ensureTable()` lazily creates the table on first use (the same belt-and-\n * suspenders pattern as `chat-threads/store.ts`), so OM works in tests and at\n * runtime even before the migration plugin is registered.\n */\n\nimport { getDbExec, isPostgres } from \"../../db/client.js\";\nimport { ensureTableExists, ensureIndexExists } from \"../../db/ddl-guard.js\";\nimport type {\n ObservationalMemoryEntry,\n ObservationalMemoryOwner,\n ObservationalMemoryTier,\n} from \"./types.js\";\n\nlet tableReady: Promise<void> | null = null;\n\nasync function ensureTable(): Promise<void> {\n if (tableReady) return tableReady;\n tableReady = (async () => {\n const client = getDbExec();\n const intType = isPostgres() ? \"BIGINT\" : \"INTEGER\";\n const createSql = `CREATE TABLE IF NOT EXISTS observational_memory (\n id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n tier TEXT NOT NULL,\n text TEXT NOT NULL,\n token_estimate ${intType} NOT NULL DEFAULT 0,\n source_start_index ${intType},\n source_end_index ${intType},\n source_message_count ${intType} NOT NULL DEFAULT 0,\n created_at ${intType} NOT NULL,\n updated_at ${intType} NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n )`;\n\n if (isPostgres()) {\n // PG-guard: probe information_schema / pg_indexes before issuing DDL to\n // avoid ACCESS EXCLUSIVE lock contention in fresh background-worker processes.\n await ensureTableExists(\"observational_memory\", createSql);\n await ensureIndexExists(\n \"observational_memory_thread_tier_idx\",\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx\n ON observational_memory(thread_id, tier, created_at)`,\n );\n await ensureIndexExists(\n \"observational_memory_thread_owner_idx\",\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx\n ON observational_memory(thread_id, owner_email)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx\n ON observational_memory(thread_id, tier, created_at)`,\n );\n } catch {\n // Index already exists.\n }\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx\n ON observational_memory(thread_id, owner_email)`,\n );\n } catch {\n // Index already exists.\n }\n })().catch((err) => {\n // Reset so a transient failure (e.g. SQLITE_BUSY on HMR) can retry.\n tableReady = null;\n throw err;\n });\n return tableReady;\n}\n\n/** Reset the cached ensureTable promise — test-only seam. */\nexport function __resetObservationalMemoryTableCache(): void {\n tableReady = null;\n}\n\nfunction entryId(): string {\n return `om-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction numOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null;\n const n = Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction rowToEntry(row: Record<string, unknown>): ObservationalMemoryEntry {\n const ownerEmail =\n typeof row.owner_email === \"string\" && row.owner_email.trim()\n ? row.owner_email\n : null;\n if (!ownerEmail) {\n throw new Error(\"Observational memory row is missing owner_email.\");\n }\n return {\n id: String(row.id),\n threadId: String(row.thread_id),\n tier: row.tier as ObservationalMemoryTier,\n text: typeof row.text === \"string\" ? row.text : \"\",\n tokenEstimate: Number(row.token_estimate) || 0,\n sourceStartIndex: numOrNull(row.source_start_index),\n sourceEndIndex: numOrNull(row.source_end_index),\n sourceMessageCount: Number(row.source_message_count) || 0,\n createdAt: Number(row.created_at) || 0,\n updatedAt: Number(row.updated_at) || 0,\n ownerEmail,\n orgId: typeof row.org_id === \"string\" ? row.org_id : null,\n visibility:\n (row.visibility as ObservationalMemoryEntry[\"visibility\"]) ?? \"private\",\n };\n}\n\nfunction addOwnerScope(\n clauses: string[],\n args: unknown[],\n owner: ObservationalMemoryOwner,\n): void {\n clauses.push(\"owner_email = ?\");\n args.push(owner.ownerEmail);\n if (owner.orgId == null) {\n clauses.push(\"org_id IS NULL\");\n } else {\n clauses.push(\"org_id = ?\");\n args.push(owner.orgId);\n }\n}\n\nexport interface InsertObservationalMemoryInput extends ObservationalMemoryOwner {\n threadId: string;\n tier: ObservationalMemoryTier;\n text: string;\n tokenEstimate: number;\n sourceStartIndex?: number | null;\n sourceEndIndex?: number | null;\n sourceMessageCount?: number;\n visibility?: \"private\" | \"org\" | \"public\";\n}\n\n/** Insert one OM entry, returning the persisted row. */\nexport async function insertObservationalMemory(\n input: InsertObservationalMemoryInput,\n): Promise<ObservationalMemoryEntry> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = entryId();\n const entry: ObservationalMemoryEntry = {\n id,\n threadId: input.threadId,\n tier: input.tier,\n text: input.text,\n tokenEstimate: input.tokenEstimate,\n sourceStartIndex: input.sourceStartIndex ?? null,\n sourceEndIndex: input.sourceEndIndex ?? null,\n sourceMessageCount: input.sourceMessageCount ?? 0,\n createdAt: now,\n updatedAt: now,\n ownerEmail: input.ownerEmail,\n orgId: input.orgId ?? null,\n visibility: input.visibility ?? \"private\",\n };\n await client.execute({\n sql: `INSERT INTO observational_memory\n (id, thread_id, tier, text, token_estimate, source_start_index, source_end_index, source_message_count, created_at, updated_at, owner_email, org_id, visibility)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n entry.id,\n entry.threadId,\n entry.tier,\n entry.text,\n entry.tokenEstimate,\n entry.sourceStartIndex,\n entry.sourceEndIndex,\n entry.sourceMessageCount,\n entry.createdAt,\n entry.updatedAt,\n entry.ownerEmail,\n entry.orgId,\n entry.visibility,\n ],\n });\n return entry;\n}\n\nexport interface ListObservationalMemoryOptions extends ObservationalMemoryOwner {\n threadId: string;\n /** When set, only entries of this tier are returned. */\n tier?: ObservationalMemoryTier;\n}\n\n/**\n * List a thread's OM entries for an owner, oldest → newest. Always\n * owner-scoped; `org_id` is matched too when supplied so org-visible rows\n * don't leak across orgs.\n */\nexport async function listObservationalMemory(\n options: ListObservationalMemoryOptions,\n): Promise<ObservationalMemoryEntry[]> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n if (options.tier) {\n clauses.push(\"tier = ?\");\n args.push(options.tier);\n }\n const result = await client.execute({\n sql: `SELECT * FROM observational_memory WHERE ${clauses.join(\n \" AND \",\n )} ORDER BY created_at ASC, id ASC`,\n args,\n });\n return (result.rows as Record<string, unknown>[]).map(rowToEntry);\n}\n\n/**\n * The highest source-message index already folded into an observation for this\n * thread/owner, or -1 if none. The Observer uses this to know which messages\n * are still unobserved.\n */\nexport async function getObservedThroughIndex(\n options: ObservationalMemoryOwner & { threadId: string },\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\", \"tier = 'observation'\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n const result = await client.execute({\n sql: `SELECT MAX(source_end_index) AS max_idx\n FROM observational_memory\n WHERE ${clauses.join(\" AND \")}`,\n args,\n });\n const row = (result.rows as Record<string, unknown>[])[0];\n const max = numOrNull(row?.max_idx);\n return max == null ? -1 : max;\n}\n\n/** Sum the token estimates of a thread's observation entries for an owner. */\nexport async function getObservationLogTokens(\n options: ObservationalMemoryOwner & { threadId: string },\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\", \"tier = 'observation'\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n const result = await client.execute({\n sql: `SELECT COALESCE(SUM(token_estimate), 0) AS total\n FROM observational_memory\n WHERE ${clauses.join(\" AND \")}`,\n args,\n });\n const row = (result.rows as Record<string, unknown>[])[0];\n return Number(row?.total) || 0;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@
4
4
  * reliable reconnection after page refreshes.
5
5
  */
6
6
  import { getDbExec, intType, isPostgres } from "../db/client.js";
7
+ import { ensureColumnExists, ensureTableExists } from "../db/ddl-guard.js";
7
8
  import { widenIntColumnsToBigInt } from "../db/widen-columns.js";
8
9
  import { captureError } from "../server/capture-error.js";
9
10
  let _initPromise;
@@ -70,7 +71,9 @@ async function ensureRunTables() {
70
71
  if (!_initPromise) {
71
72
  _initPromise = (async () => {
72
73
  const client = getDbExec();
73
- await client.execute(`
74
+ // Shared CREATE SQL strings — referenced by both the Postgres and SQLite
75
+ // branches so the column definitions stay in one place.
76
+ const agentRunsCreateSql = `
74
77
  CREATE TABLE IF NOT EXISTS agent_runs (
75
78
  id TEXT PRIMARY KEY,
76
79
  thread_id TEXT NOT NULL,
@@ -86,24 +89,108 @@ async function ensureRunTables() {
86
89
  dispatch_mode TEXT,
87
90
  diag_stage TEXT
88
91
  )
89
- `);
92
+ `;
93
+ const agentRunEventsCreateSql = `
94
+ CREATE TABLE IF NOT EXISTS agent_run_events (
95
+ run_id TEXT NOT NULL,
96
+ seq ${intType()} NOT NULL,
97
+ event_data TEXT NOT NULL,
98
+ PRIMARY KEY (run_id, seq)
99
+ )
100
+ `;
101
+ // Tool-call result ledger: persists the outcome of write tool calls that
102
+ // completed AFTER their chunk was abandoned (zombie completions). A
103
+ // resumed continuation can recover the real result by matching
104
+ // thread_id + tool_key (name:stableInputHash) instead of re-executing
105
+ // the side effect. Entries are scoped to the thread and expire with it.
106
+ const agentToolLedgerCreateSql = `
107
+ CREATE TABLE IF NOT EXISTS agent_tool_ledger (
108
+ thread_id TEXT NOT NULL,
109
+ tool_key TEXT NOT NULL,
110
+ result_summary TEXT NOT NULL,
111
+ completed_at ${intType()} NOT NULL,
112
+ PRIMARY KEY (thread_id, tool_key)
113
+ )
114
+ `;
115
+ if (isPostgres()) {
116
+ // Hot path: in production the tables and all additive columns are
117
+ // virtually always already present. Issuing `CREATE TABLE`/`ALTER TABLE
118
+ // ADD COLUMN` still takes an ACCESS EXCLUSIVE lock — which, in a fresh
119
+ // background-worker process behind a concurrent connection on the shared
120
+ // Neon DB, can block ~indefinitely. So check `information_schema` first
121
+ // (plain reads, no lock) and run DDL ONLY for what is actually missing.
122
+ // The `ensureTableExists` / `ensureColumnExists` wrappers probe →
123
+ // guarded-DDL (bounded `lock_timeout`) → re-probe, and THROW if the
124
+ // schema is still missing after a swallowed lock-timeout so a poisoned
125
+ // init never memoizes success against absent schema (the `_initPromise`
126
+ // rejects and the next call retries).
127
+ await ensureTableExists("agent_runs", agentRunsCreateSql);
128
+ // Additive columns — all listed in the CREATE TABLE above, so on a
129
+ // fresh DB they already exist after the CREATE and these checks are
130
+ // instant short-circuits. On an older deployment that predates a
131
+ // column, the wrapper issues one bounded ALTER.
132
+ //
133
+ // Backfill heartbeat_at on older deployments.
134
+ // heartbeat_at = "the producer process is alive" (bumped on a timer).
135
+ // last_progress_at = "the agent is actually emitting events" (bumped on
136
+ // each emit). The gap between them is the stuck-detector signal.
137
+ for (const [col, colType] of [
138
+ ["heartbeat_at", intType()],
139
+ ["abort_reason", "TEXT"],
140
+ ["last_progress_at", intType()],
141
+ // Backfill turn_id / error_code / error_detail.
142
+ // turn_id = stable identity for one logical assistant turn that may
143
+ // span several continuation runs, so the durable record
144
+ // can be folded across runs instead of dropped per-run.
145
+ // error_code / error_detail = terminal failure classification captured
146
+ // at completion so errored/cut-off runs are queryable for
147
+ // pattern analysis (see listErroredRuns).
148
+ // dispatch_mode marks how a run was started: NULL/"foreground" for the
149
+ // normal synchronous path, "background" for a run dispatched into a
150
+ // Netlify background function. The reaper/claim widen the stale window
151
+ // for background rows so a slow cold-start isn't falsely reaped.
152
+ // diag_stage records the last reached pipeline stage (+ any error) for a
153
+ // background-dispatched run so a silent worker death is DIAGNOSABLE from
154
+ // the client (/runs/active surfaces it) without reading the unreadable
155
+ // Netlify background-function logs. See recordRunDiagnostic.
156
+ ["turn_id", "TEXT"],
157
+ ["error_code", "TEXT"],
158
+ ["error_detail", "TEXT"],
159
+ ["dispatch_mode", "TEXT"],
160
+ ["diag_stage", "TEXT"],
161
+ ]) {
162
+ await ensureColumnExists("agent_runs", col, `ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS ${col} ${colType}`);
163
+ }
164
+ await ensureTableExists("agent_run_events", agentRunEventsCreateSql);
165
+ await ensureTableExists("agent_tool_ledger", agentToolLedgerCreateSql);
166
+ // Widen millisecond-timestamp columns that older deployments created as
167
+ // 32-bit `INTEGER`. `insertRun()` writes `Date.now()` into `started_at`
168
+ // on every turn, so an int4 column makes every agent prompt fail on
169
+ // Postgres with "value … is out of range for type integer". No-op once
170
+ // widened (and on fresh DBs that already use BIGINT). See
171
+ // widenIntColumnsToBigInt.
172
+ await widenIntColumnsToBigInt("agent_runs", [
173
+ "started_at",
174
+ "completed_at",
175
+ "heartbeat_at",
176
+ "last_progress_at",
177
+ ]);
178
+ await widenIntColumnsToBigInt("agent_tool_ledger", ["completed_at"]);
179
+ return;
180
+ }
181
+ // SQLite (local dev): no ACCESS EXCLUSIVE lock problem — keep the
182
+ // original create-then-additive-alter behaviour. SQLite has no
183
+ // `ADD COLUMN IF NOT EXISTS`, so the ALTERs stay wrapped in try/catch.
184
+ await client.execute(agentRunsCreateSql);
90
185
  // Backfill heartbeat_at on older deployments.
91
186
  try {
92
- if (isPostgres()) {
93
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS heartbeat_at ${intType()}`);
94
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS abort_reason TEXT`);
95
- }
96
- else {
97
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN heartbeat_at ${intType()}`);
98
- }
187
+ await client.execute(`ALTER TABLE agent_runs ADD COLUMN heartbeat_at ${intType()}`);
99
188
  }
100
189
  catch {
101
190
  // Column already exists — ignore
102
191
  }
103
192
  try {
104
- if (!isPostgres()) {
105
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN abort_reason TEXT`);
106
- }
193
+ await client.execute(`ALTER TABLE agent_runs ADD COLUMN abort_reason TEXT`);
107
194
  }
108
195
  catch {
109
196
  // Column already exists — ignore
@@ -113,12 +200,7 @@ async function ensureRunTables() {
113
200
  // last_progress_at = "the agent is actually emitting events" (bumped on
114
201
  // each emit). The gap between them is the stuck-detector signal.
115
202
  try {
116
- if (isPostgres()) {
117
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS last_progress_at ${intType()}`);
118
- }
119
- else {
120
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN last_progress_at ${intType()}`);
121
- }
203
+ await client.execute(`ALTER TABLE agent_runs ADD COLUMN last_progress_at ${intType()}`);
122
204
  }
123
205
  catch {
124
206
  // Column already exists — ignore
@@ -146,39 +228,14 @@ async function ensureRunTables() {
146
228
  "diag_stage",
147
229
  ]) {
148
230
  try {
149
- if (isPostgres()) {
150
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS ${col} TEXT`);
151
- }
152
- else {
153
- await client.execute(`ALTER TABLE agent_runs ADD COLUMN ${col} TEXT`);
154
- }
231
+ await client.execute(`ALTER TABLE agent_runs ADD COLUMN ${col} TEXT`);
155
232
  }
156
233
  catch {
157
234
  // Column already exists — ignore
158
235
  }
159
236
  }
160
- await client.execute(`
161
- CREATE TABLE IF NOT EXISTS agent_run_events (
162
- run_id TEXT NOT NULL,
163
- seq ${intType()} NOT NULL,
164
- event_data TEXT NOT NULL,
165
- PRIMARY KEY (run_id, seq)
166
- )
167
- `);
168
- // Tool-call result ledger: persists the outcome of write tool calls that
169
- // completed AFTER their chunk was abandoned (zombie completions). A
170
- // resumed continuation can recover the real result by matching
171
- // thread_id + tool_key (name:stableInputHash) instead of re-executing
172
- // the side effect. Entries are scoped to the thread and expire with it.
173
- await client.execute(`
174
- CREATE TABLE IF NOT EXISTS agent_tool_ledger (
175
- thread_id TEXT NOT NULL,
176
- tool_key TEXT NOT NULL,
177
- result_summary TEXT NOT NULL,
178
- completed_at ${intType()} NOT NULL,
179
- PRIMARY KEY (thread_id, tool_key)
180
- )
181
- `);
237
+ await client.execute(agentRunEventsCreateSql);
238
+ await client.execute(agentToolLedgerCreateSql);
182
239
  // Widen millisecond-timestamp columns that older deployments created as
183
240
  // 32-bit `INTEGER`. `insertRun()` writes `Date.now()` into `started_at`
184
241
  // on every turn, so an int4 column makes every agent prompt fail on