@agent-native/core 0.49.27 → 0.50.0

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 (95) hide show
  1. package/dist/agent/harness/ai-sdk-adapter.d.ts +13 -0
  2. package/dist/agent/harness/ai-sdk-adapter.d.ts.map +1 -0
  3. package/dist/agent/harness/ai-sdk-adapter.js +232 -0
  4. package/dist/agent/harness/ai-sdk-adapter.js.map +1 -0
  5. package/dist/agent/harness/background.d.ts +15 -0
  6. package/dist/agent/harness/background.d.ts.map +1 -0
  7. package/dist/agent/harness/background.js +233 -0
  8. package/dist/agent/harness/background.js.map +1 -0
  9. package/dist/agent/harness/builtin.d.ts +2 -0
  10. package/dist/agent/harness/builtin.d.ts.map +1 -0
  11. package/dist/agent/harness/builtin.js +24 -0
  12. package/dist/agent/harness/builtin.js.map +1 -0
  13. package/dist/agent/harness/index.d.ts +9 -0
  14. package/dist/agent/harness/index.d.ts.map +1 -0
  15. package/dist/agent/harness/index.js +8 -0
  16. package/dist/agent/harness/index.js.map +1 -0
  17. package/dist/agent/harness/registry.d.ts +15 -0
  18. package/dist/agent/harness/registry.d.ts.map +1 -0
  19. package/dist/agent/harness/registry.js +70 -0
  20. package/dist/agent/harness/registry.js.map +1 -0
  21. package/dist/agent/harness/runner.d.ts +21 -0
  22. package/dist/agent/harness/runner.d.ts.map +1 -0
  23. package/dist/agent/harness/runner.js +86 -0
  24. package/dist/agent/harness/runner.js.map +1 -0
  25. package/dist/agent/harness/store.d.ts +46 -0
  26. package/dist/agent/harness/store.d.ts.map +1 -0
  27. package/dist/agent/harness/store.js +304 -0
  28. package/dist/agent/harness/store.js.map +1 -0
  29. package/dist/agent/harness/translate.d.ts +5 -0
  30. package/dist/agent/harness/translate.d.ts.map +1 -0
  31. package/dist/agent/harness/translate.js +120 -0
  32. package/dist/agent/harness/translate.js.map +1 -0
  33. package/dist/agent/harness/types.d.ts +127 -0
  34. package/dist/agent/harness/types.d.ts.map +1 -0
  35. package/dist/agent/harness/types.js +2 -0
  36. package/dist/agent/harness/types.js.map +1 -0
  37. package/dist/agent/production-agent.d.ts.map +1 -1
  38. package/dist/agent/production-agent.js +2 -0
  39. package/dist/agent/production-agent.js.map +1 -1
  40. package/dist/cli/create.d.ts.map +1 -1
  41. package/dist/cli/create.js +10 -1
  42. package/dist/cli/create.js.map +1 -1
  43. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  44. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  45. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  46. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  47. package/dist/cli/skills.d.ts +1 -1
  48. package/dist/cli/skills.d.ts.map +1 -1
  49. package/dist/cli/skills.js +8 -1
  50. package/dist/cli/skills.js.map +1 -1
  51. package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
  52. package/dist/client/blocks/library/wireframe.js +0 -1
  53. package/dist/client/blocks/library/wireframe.js.map +1 -1
  54. package/dist/client/resources/use-resources.d.ts.map +1 -1
  55. package/dist/client/resources/use-resources.js +4 -2
  56. package/dist/client/resources/use-resources.js.map +1 -1
  57. package/dist/code-agents/background-run.d.ts +6 -4
  58. package/dist/code-agents/background-run.d.ts.map +1 -1
  59. package/dist/code-agents/background-run.js.map +1 -1
  60. package/dist/coding-tools/run-code.js +6 -4
  61. package/dist/coding-tools/run-code.js.map +1 -1
  62. package/dist/provider-api/index.d.ts +20 -12
  63. package/dist/provider-api/index.d.ts.map +1 -1
  64. package/dist/provider-api/index.js +157 -37
  65. package/dist/provider-api/index.js.map +1 -1
  66. package/dist/provider-api/quota-governor.d.ts +53 -0
  67. package/dist/provider-api/quota-governor.d.ts.map +1 -0
  68. package/dist/provider-api/quota-governor.js +395 -0
  69. package/dist/provider-api/quota-governor.js.map +1 -0
  70. package/dist/provider-api/staging.d.ts.map +1 -1
  71. package/dist/provider-api/staging.js +16 -0
  72. package/dist/provider-api/staging.js.map +1 -1
  73. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  74. package/dist/server/agent-chat-plugin.js +34 -10
  75. package/dist/server/agent-chat-plugin.js.map +1 -1
  76. package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +98 -0
  77. package/dist/workspace-files/index.d.ts +0 -1
  78. package/dist/workspace-files/index.d.ts.map +1 -1
  79. package/dist/workspace-files/index.js +0 -1
  80. package/dist/workspace-files/index.js.map +1 -1
  81. package/dist/workspace-files/store.d.ts +14 -9
  82. package/dist/workspace-files/store.d.ts.map +1 -1
  83. package/dist/workspace-files/store.js +89 -164
  84. package/dist/workspace-files/store.js.map +1 -1
  85. package/dist/workspace-files/tool.d.ts +3 -4
  86. package/dist/workspace-files/tool.d.ts.map +1 -1
  87. package/dist/workspace-files/tool.js +8 -7
  88. package/dist/workspace-files/tool.js.map +1 -1
  89. package/docs/content/deployment.md +1 -1
  90. package/package.json +2 -1
  91. package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +98 -0
  92. package/dist/workspace-files/schema.d.ts +0 -195
  93. package/dist/workspace-files/schema.d.ts.map +0 -1
  94. package/dist/workspace-files/schema.js +0 -48
  95. package/dist/workspace-files/schema.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/harness/index.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,kCAAkC,EAClC,eAAe,IAAI,2BAA2B,GAC/C,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,8BAA8B,EAC9B,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,+BAA+B,EAC/B,sBAAsB,EACtB,6BAA6B,EAC7B,qCAAqC,EACrC,wBAAwB,EACxB,8BAA8B,EAC9B,uBAAuB,EACvB,yBAAyB,GAI1B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GAErB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAG1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,qCAAqC,EACrC,2CAA2C,EAC3C,4BAA4B,EAC5B,8BAA8B,EAC9B,0CAA0C,EAC1C,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC","sourcesContent":["export type {\n AgentHarnessAdapter,\n AgentHarnessApproval,\n AgentHarnessCapabilities,\n AgentHarnessContinueInput,\n AgentHarnessCreateSessionOptions,\n AgentHarnessEvent,\n AgentHarnessMessage,\n AgentHarnessPermissionMode,\n AgentHarnessSession,\n AgentHarnessTurnInput,\n} from \"./types.js\";\nexport {\n agentHarnessEventToAgentChatEvents,\n stringifyResult as stringifyAgentHarnessResult,\n} from \"./translate.js\";\nexport {\n getAgentHarnessEntry,\n isAgentHarnessPackageInstalled,\n listAgentHarnesses,\n registerAgentHarness,\n resolveAgentHarness,\n type AgentHarnessEntry,\n} from \"./registry.js\";\nexport {\n ensureAgentHarnessSessionTables,\n getAgentHarnessSession,\n getAgentHarnessSessionByRunId,\n getLatestAgentHarnessSessionForThread,\n listAgentHarnessSessions,\n markAgentHarnessSessionStopped,\n saveAgentHarnessSession,\n updateAgentHarnessSession,\n type AgentHarnessSessionStatus,\n type SaveAgentHarnessSessionInput,\n type StoredAgentHarnessSession,\n} from \"./store.js\";\nexport {\n sendAgentHarnessEvent,\n startAgentHarnessRun,\n type StartAgentHarnessRunOptions,\n} from \"./runner.js\";\nexport {\n aiSdkHarnessPartToEvents,\n createAiSdkHarnessAdapter,\n type AiSdkHarnessAdapterOptions,\n type AiSdkHarnessRuntime,\n} from \"./ai-sdk-adapter.js\";\nexport { registerBuiltinAgentHarnesses } from \"./builtin.js\";\nexport {\n agentHarnessBackgroundAgentController,\n createAgentHarnessBackgroundAgentController,\n getAgentHarnessBackgroundRun,\n listAgentHarnessBackgroundRuns,\n listAgentHarnessBackgroundTranscriptEvents,\n stopAgentHarnessBackgroundRun,\n} from \"./background.js\";\n"]}
@@ -0,0 +1,15 @@
1
+ import type { AgentHarnessAdapter } from "./types.js";
2
+ export interface AgentHarnessEntry {
3
+ name: string;
4
+ label: string;
5
+ description: string;
6
+ installPackage?: string;
7
+ capabilities: AgentHarnessAdapter["capabilities"];
8
+ create(config?: Record<string, unknown>): AgentHarnessAdapter;
9
+ }
10
+ export declare function registerAgentHarness(entry: AgentHarnessEntry): void;
11
+ export declare function getAgentHarnessEntry(name: string): AgentHarnessEntry | undefined;
12
+ export declare function listAgentHarnesses(): AgentHarnessEntry[];
13
+ export declare function resolveAgentHarness(name: string, config?: Record<string, unknown>): AgentHarnessAdapter;
14
+ export declare function isAgentHarnessPackageInstalled(entry: Pick<AgentHarnessEntry, "installPackage">): boolean;
15
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/agent/harness/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAItD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAAC;CAC/D;AAKD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAQnE;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,iBAAiB,GAAG,SAAS,CAE/B;AAED,wBAAgB,kBAAkB,IAAI,iBAAiB,EAAE,CAExD;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,mBAAmB,CAOrB;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,GAC/C,OAAO,CAOT"}
@@ -0,0 +1,70 @@
1
+ import { createRequire } from "node:module";
2
+ const require = createRequire(import.meta.url);
3
+ const registry = new Map();
4
+ const packageAvailabilityCache = new Map();
5
+ export function registerAgentHarness(entry) {
6
+ if (registry.has(entry.name) && process.env.NODE_ENV !== "test") {
7
+ console.warn(`[agent-harness] Harness "${entry.name}" is already registered. Skipping.`);
8
+ return;
9
+ }
10
+ registry.set(entry.name, entry);
11
+ }
12
+ export function getAgentHarnessEntry(name) {
13
+ return registry.get(name);
14
+ }
15
+ export function listAgentHarnesses() {
16
+ return Array.from(registry.values());
17
+ }
18
+ export function resolveAgentHarness(name, config) {
19
+ const entry = registry.get(name);
20
+ if (!entry) {
21
+ throw new Error(`[agent-harness] Unknown harness "${name}"`);
22
+ }
23
+ assertAgentHarnessPackagesInstalled(entry);
24
+ return entry.create(config);
25
+ }
26
+ export function isAgentHarnessPackageInstalled(entry) {
27
+ const packages = entry.installPackage
28
+ ?.split(/\s+/)
29
+ .map(packageNameFromInstallSpecifier)
30
+ .filter((name) => Boolean(name)) ?? [];
31
+ return packages.every(canResolvePackage);
32
+ }
33
+ function assertAgentHarnessPackagesInstalled(entry) {
34
+ if (isAgentHarnessPackageInstalled(entry))
35
+ return;
36
+ const hint = entry.installPackage
37
+ ? ` Run: pnpm add ${entry.installPackage}`
38
+ : "";
39
+ throw new Error(`[agent-harness] Harness "${entry.name}" requires optional packages that are not installed in this app.${hint}`);
40
+ }
41
+ function packageNameFromInstallSpecifier(specifier) {
42
+ const trimmed = specifier.trim();
43
+ if (!trimmed || trimmed.startsWith("-"))
44
+ return null;
45
+ if (trimmed.startsWith("@")) {
46
+ const slashIndex = trimmed.indexOf("/");
47
+ if (slashIndex === -1)
48
+ return trimmed;
49
+ const versionIndex = trimmed.indexOf("@", slashIndex + 1);
50
+ return versionIndex === -1 ? trimmed : trimmed.slice(0, versionIndex);
51
+ }
52
+ const versionIndex = trimmed.indexOf("@");
53
+ return versionIndex === -1 ? trimmed : trimmed.slice(0, versionIndex);
54
+ }
55
+ function canResolvePackage(packageName) {
56
+ const cached = packageAvailabilityCache.get(packageName);
57
+ if (cached !== undefined)
58
+ return cached;
59
+ let available = false;
60
+ try {
61
+ require.resolve(packageName);
62
+ available = true;
63
+ }
64
+ catch {
65
+ available = false;
66
+ }
67
+ packageAvailabilityCache.set(packageName, available);
68
+ return available;
69
+ }
70
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/agent/harness/registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\";\nimport type { AgentHarnessAdapter } from \"./types.js\";\n\nconst require = createRequire(import.meta.url);\n\nexport interface AgentHarnessEntry {\n name: string;\n label: string;\n description: string;\n installPackage?: string;\n capabilities: AgentHarnessAdapter[\"capabilities\"];\n create(config?: Record<string, unknown>): AgentHarnessAdapter;\n}\n\nconst registry = new Map<string, AgentHarnessEntry>();\nconst packageAvailabilityCache = new Map<string, boolean>();\n\nexport function registerAgentHarness(entry: AgentHarnessEntry): void {\n if (registry.has(entry.name) && process.env.NODE_ENV !== \"test\") {\n console.warn(\n `[agent-harness] Harness \"${entry.name}\" is already registered. Skipping.`,\n );\n return;\n }\n registry.set(entry.name, entry);\n}\n\nexport function getAgentHarnessEntry(\n name: string,\n): AgentHarnessEntry | undefined {\n return registry.get(name);\n}\n\nexport function listAgentHarnesses(): AgentHarnessEntry[] {\n return Array.from(registry.values());\n}\n\nexport function resolveAgentHarness(\n name: string,\n config?: Record<string, unknown>,\n): AgentHarnessAdapter {\n const entry = registry.get(name);\n if (!entry) {\n throw new Error(`[agent-harness] Unknown harness \"${name}\"`);\n }\n assertAgentHarnessPackagesInstalled(entry);\n return entry.create(config);\n}\n\nexport function isAgentHarnessPackageInstalled(\n entry: Pick<AgentHarnessEntry, \"installPackage\">,\n): boolean {\n const packages =\n entry.installPackage\n ?.split(/\\s+/)\n .map(packageNameFromInstallSpecifier)\n .filter((name): name is string => Boolean(name)) ?? [];\n return packages.every(canResolvePackage);\n}\n\nfunction assertAgentHarnessPackagesInstalled(entry: AgentHarnessEntry): void {\n if (isAgentHarnessPackageInstalled(entry)) return;\n const hint = entry.installPackage\n ? ` Run: pnpm add ${entry.installPackage}`\n : \"\";\n throw new Error(\n `[agent-harness] Harness \"${entry.name}\" requires optional packages that are not installed in this app.${hint}`,\n );\n}\n\nfunction packageNameFromInstallSpecifier(specifier: string): string | null {\n const trimmed = specifier.trim();\n if (!trimmed || trimmed.startsWith(\"-\")) return null;\n if (trimmed.startsWith(\"@\")) {\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex === -1) return trimmed;\n const versionIndex = trimmed.indexOf(\"@\", slashIndex + 1);\n return versionIndex === -1 ? trimmed : trimmed.slice(0, versionIndex);\n }\n const versionIndex = trimmed.indexOf(\"@\");\n return versionIndex === -1 ? trimmed : trimmed.slice(0, versionIndex);\n}\n\nfunction canResolvePackage(packageName: string): boolean {\n const cached = packageAvailabilityCache.get(packageName);\n if (cached !== undefined) return cached;\n let available = false;\n try {\n require.resolve(packageName);\n available = true;\n } catch {\n available = false;\n }\n packageAvailabilityCache.set(packageName, available);\n return available;\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import type { ActiveRun, StartRunOptions } from "../run-manager.js";
2
+ import type { AgentChatEvent } from "../types.js";
3
+ import type { AgentHarnessAdapter, AgentHarnessCreateSessionOptions, AgentHarnessEvent, AgentHarnessSession, AgentHarnessTurnInput } from "./types.js";
4
+ export interface StartAgentHarnessRunOptions {
5
+ runId: string;
6
+ threadId: string;
7
+ turnId?: string;
8
+ adapter: AgentHarnessAdapter;
9
+ input: AgentHarnessTurnInput;
10
+ session?: AgentHarnessSession;
11
+ createSession?: AgentHarnessCreateSessionOptions;
12
+ ownerEmail?: string | null;
13
+ orgId?: string | null;
14
+ detachOnComplete?: boolean;
15
+ runOptions?: StartRunOptions;
16
+ onHarnessEvent?: (event: AgentHarnessEvent) => void | Promise<void>;
17
+ onRunComplete?: (run: ActiveRun) => void | Promise<void>;
18
+ }
19
+ export declare function startAgentHarnessRun(opts: StartAgentHarnessRunOptions): ActiveRun;
20
+ export declare function sendAgentHarnessEvent(send: (event: AgentChatEvent) => void, event: AgentHarnessEvent): void;
21
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/agent/harness/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,OAAO,KAAK,EACV,mBAAmB,EACnB,gCAAgC,EAChC,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,KAAK,EAAE,qBAAqB,CAAC;IAC7B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,aAAa,CAAC,EAAE,gCAAgC,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,2BAA2B,GAChC,SAAS,CAwFX;AAaD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,EACrC,KAAK,EAAE,iBAAiB,GACvB,IAAI,CAIN"}
@@ -0,0 +1,86 @@
1
+ import { startRun } from "../run-manager.js";
2
+ import { markAgentHarnessSessionStopped, saveAgentHarnessSession, updateAgentHarnessSession, } from "./store.js";
3
+ import { agentHarnessEventToAgentChatEvents } from "./translate.js";
4
+ export function startAgentHarnessRun(opts) {
5
+ let harnessSession = opts.session;
6
+ const detachOnComplete = opts.detachOnComplete !== false;
7
+ return startRun(opts.runId, opts.threadId, async (send, signal) => {
8
+ send({
9
+ type: "activity",
10
+ label: `Starting ${opts.adapter.label}`,
11
+ tool: "harness",
12
+ });
13
+ harnessSession ??= await opts.adapter.createSession({
14
+ ...(opts.createSession ?? {}),
15
+ threadId: opts.threadId,
16
+ runId: opts.runId,
17
+ ownerEmail: opts.ownerEmail ?? opts.createSession?.ownerEmail ?? null,
18
+ orgId: opts.orgId ?? opts.createSession?.orgId ?? null,
19
+ signal,
20
+ });
21
+ await saveAgentHarnessSession({
22
+ id: opts.createSession?.sessionId ?? harnessSession.id,
23
+ harnessName: opts.adapter.name,
24
+ threadId: opts.threadId,
25
+ runId: opts.runId,
26
+ providerSessionId: harnessSession.id,
27
+ status: "running",
28
+ resumeState: opts.createSession?.resumeState,
29
+ ownerEmail: opts.ownerEmail ?? opts.createSession?.ownerEmail ?? null,
30
+ orgId: opts.orgId ?? opts.createSession?.orgId ?? null,
31
+ });
32
+ const input = {
33
+ ...opts.input,
34
+ abortSignal: signal,
35
+ };
36
+ for await (const event of harnessSession.streamTurn(input)) {
37
+ if (signal.aborted)
38
+ break;
39
+ await opts.onHarnessEvent?.(event);
40
+ if (event.type === "approval-request") {
41
+ await updateAgentHarnessSession(opts.createSession?.sessionId ?? harnessSession.id, {
42
+ status: "idle",
43
+ pendingApproval: event,
44
+ });
45
+ }
46
+ if (event.type === "error") {
47
+ throw new Error(event.error);
48
+ }
49
+ for (const chatEvent of agentHarnessEventToAgentChatEvents(event)) {
50
+ send(chatEvent);
51
+ }
52
+ }
53
+ if (signal.aborted) {
54
+ await stopHarnessSession(harnessSession);
55
+ await markAgentHarnessSessionStopped(opts.createSession?.sessionId ?? harnessSession.id, "stopped");
56
+ return;
57
+ }
58
+ let resumeState = opts.createSession?.resumeState;
59
+ if (detachOnComplete && harnessSession.detach) {
60
+ resumeState = await harnessSession.detach();
61
+ }
62
+ await updateAgentHarnessSession(opts.createSession?.sessionId ?? harnessSession.id, {
63
+ status: "idle",
64
+ resumeState,
65
+ pendingApproval: null,
66
+ });
67
+ }, opts.onRunComplete, {
68
+ ...(opts.runOptions ?? {}),
69
+ turnId: opts.turnId ?? opts.runOptions?.turnId,
70
+ });
71
+ }
72
+ async function stopHarnessSession(session) {
73
+ if (!session)
74
+ return;
75
+ if (session.stop) {
76
+ await session.stop();
77
+ return;
78
+ }
79
+ await session.destroy?.();
80
+ }
81
+ export function sendAgentHarnessEvent(send, event) {
82
+ for (const chatEvent of agentHarnessEventToAgentChatEvents(event)) {
83
+ send(chatEvent);
84
+ }
85
+ }
86
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/agent/harness/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActiveRun, StartRunOptions } from \"../run-manager.js\";\nimport { startRun } from \"../run-manager.js\";\nimport type { AgentChatEvent } from \"../types.js\";\nimport {\n markAgentHarnessSessionStopped,\n saveAgentHarnessSession,\n updateAgentHarnessSession,\n} from \"./store.js\";\nimport { agentHarnessEventToAgentChatEvents } from \"./translate.js\";\nimport type {\n AgentHarnessAdapter,\n AgentHarnessCreateSessionOptions,\n AgentHarnessEvent,\n AgentHarnessSession,\n AgentHarnessTurnInput,\n} from \"./types.js\";\n\nexport interface StartAgentHarnessRunOptions {\n runId: string;\n threadId: string;\n turnId?: string;\n adapter: AgentHarnessAdapter;\n input: AgentHarnessTurnInput;\n session?: AgentHarnessSession;\n createSession?: AgentHarnessCreateSessionOptions;\n ownerEmail?: string | null;\n orgId?: string | null;\n detachOnComplete?: boolean;\n runOptions?: StartRunOptions;\n onHarnessEvent?: (event: AgentHarnessEvent) => void | Promise<void>;\n onRunComplete?: (run: ActiveRun) => void | Promise<void>;\n}\n\nexport function startAgentHarnessRun(\n opts: StartAgentHarnessRunOptions,\n): ActiveRun {\n let harnessSession: AgentHarnessSession | undefined = opts.session;\n const detachOnComplete = opts.detachOnComplete !== false;\n\n return startRun(\n opts.runId,\n opts.threadId,\n async (send, signal) => {\n send({\n type: \"activity\",\n label: `Starting ${opts.adapter.label}`,\n tool: \"harness\",\n });\n\n harnessSession ??= await opts.adapter.createSession({\n ...(opts.createSession ?? {}),\n threadId: opts.threadId,\n runId: opts.runId,\n ownerEmail: opts.ownerEmail ?? opts.createSession?.ownerEmail ?? null,\n orgId: opts.orgId ?? opts.createSession?.orgId ?? null,\n signal,\n });\n\n await saveAgentHarnessSession({\n id: opts.createSession?.sessionId ?? harnessSession.id,\n harnessName: opts.adapter.name,\n threadId: opts.threadId,\n runId: opts.runId,\n providerSessionId: harnessSession.id,\n status: \"running\",\n resumeState: opts.createSession?.resumeState,\n ownerEmail: opts.ownerEmail ?? opts.createSession?.ownerEmail ?? null,\n orgId: opts.orgId ?? opts.createSession?.orgId ?? null,\n });\n\n const input: AgentHarnessTurnInput = {\n ...opts.input,\n abortSignal: signal,\n };\n\n for await (const event of harnessSession.streamTurn(input)) {\n if (signal.aborted) break;\n await opts.onHarnessEvent?.(event);\n if (event.type === \"approval-request\") {\n await updateAgentHarnessSession(\n opts.createSession?.sessionId ?? harnessSession.id,\n {\n status: \"idle\",\n pendingApproval: event,\n },\n );\n }\n if (event.type === \"error\") {\n throw new Error(event.error);\n }\n for (const chatEvent of agentHarnessEventToAgentChatEvents(event)) {\n send(chatEvent);\n }\n }\n\n if (signal.aborted) {\n await stopHarnessSession(harnessSession);\n await markAgentHarnessSessionStopped(\n opts.createSession?.sessionId ?? harnessSession.id,\n \"stopped\",\n );\n return;\n }\n\n let resumeState: unknown = opts.createSession?.resumeState;\n if (detachOnComplete && harnessSession.detach) {\n resumeState = await harnessSession.detach();\n }\n await updateAgentHarnessSession(\n opts.createSession?.sessionId ?? harnessSession.id,\n {\n status: \"idle\",\n resumeState,\n pendingApproval: null,\n },\n );\n },\n opts.onRunComplete,\n {\n ...(opts.runOptions ?? {}),\n turnId: opts.turnId ?? opts.runOptions?.turnId,\n },\n );\n}\n\nasync function stopHarnessSession(\n session: AgentHarnessSession | undefined,\n): Promise<void> {\n if (!session) return;\n if (session.stop) {\n await session.stop();\n return;\n }\n await session.destroy?.();\n}\n\nexport function sendAgentHarnessEvent(\n send: (event: AgentChatEvent) => void,\n event: AgentHarnessEvent,\n): void {\n for (const chatEvent of agentHarnessEventToAgentChatEvents(event)) {\n send(chatEvent);\n }\n}\n"]}
@@ -0,0 +1,46 @@
1
+ export type AgentHarnessSessionStatus = "running" | "idle" | "stopped" | "errored" | "destroyed";
2
+ export interface StoredAgentHarnessSession {
3
+ id: string;
4
+ harnessName: string;
5
+ threadId: string;
6
+ runId?: string | null;
7
+ providerSessionId?: string | null;
8
+ status: AgentHarnessSessionStatus;
9
+ resumeState?: unknown;
10
+ workspaceRef?: string | null;
11
+ pendingApproval?: unknown;
12
+ ownerEmail?: string | null;
13
+ orgId?: string | null;
14
+ createdAt: number;
15
+ updatedAt: number;
16
+ stoppedAt?: number | null;
17
+ }
18
+ export interface SaveAgentHarnessSessionInput {
19
+ id: string;
20
+ harnessName: string;
21
+ threadId: string;
22
+ runId?: string | null;
23
+ providerSessionId?: string | null;
24
+ status?: AgentHarnessSessionStatus;
25
+ resumeState?: unknown;
26
+ workspaceRef?: string | null;
27
+ pendingApproval?: unknown;
28
+ ownerEmail?: string | null;
29
+ orgId?: string | null;
30
+ stoppedAt?: number | null;
31
+ }
32
+ export declare function ensureAgentHarnessSessionTables(): Promise<void>;
33
+ export declare function saveAgentHarnessSession(input: SaveAgentHarnessSessionInput): Promise<StoredAgentHarnessSession>;
34
+ export declare function updateAgentHarnessSession(id: string, patch: Partial<Omit<SaveAgentHarnessSessionInput, "id">>): Promise<StoredAgentHarnessSession | null>;
35
+ export declare function getAgentHarnessSession(id: string): Promise<StoredAgentHarnessSession | null>;
36
+ export declare function getLatestAgentHarnessSessionForThread(threadId: string, harnessName?: string): Promise<StoredAgentHarnessSession | null>;
37
+ export declare function getAgentHarnessSessionByRunId(runId: string): Promise<StoredAgentHarnessSession | null>;
38
+ export declare function listAgentHarnessSessions(options?: {
39
+ status?: AgentHarnessSessionStatus;
40
+ threadId?: string;
41
+ ownerEmail?: string | null;
42
+ orgId?: string | null;
43
+ limit?: number;
44
+ }): Promise<StoredAgentHarnessSession[]>;
45
+ export declare function markAgentHarnessSessionStopped(id: string, status: Extract<AgentHarnessSessionStatus, "stopped" | "destroyed" | "errored">): Promise<StoredAgentHarnessSession | null>;
46
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/agent/harness/store.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,yBAAyB,GACjC,SAAS,GACT,MAAM,GACN,SAAS,GACT,SAAS,GACT,WAAW,CAAC;AAEhB,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,EAAE,yBAAyB,CAAC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID,wBAAsB,+BAA+B,IAAI,OAAO,CAAC,IAAI,CAAC,CAiFrE;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CAgEpC;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAC,GACvD,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAwB3C;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAQ3C;AAED,wBAAsB,qCAAqC,CACzD,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAiB3C;AAED,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAU3C;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,GACL,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAoDtC;AAED,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,OAAO,CACb,yBAAyB,EACzB,SAAS,GAAG,WAAW,GAAG,SAAS,CACpC,GACA,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAM3C"}
@@ -0,0 +1,304 @@
1
+ import { getDbExec, intType, isPostgres, retryOnDdlRace, } from "../../db/client.js";
2
+ let initPromise;
3
+ export async function ensureAgentHarnessSessionTables() {
4
+ if (!initPromise) {
5
+ initPromise = (async () => {
6
+ 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
+ `));
25
+ for (const col of [
26
+ "run_id",
27
+ "provider_session_id",
28
+ "resume_state",
29
+ "workspace_ref",
30
+ "pending_approval",
31
+ "owner_email",
32
+ "org_id",
33
+ ]) {
34
+ 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
+ }
41
+ }
42
+ catch {
43
+ // Column already exists.
44
+ }
45
+ }
46
+ 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
+ }
53
+ }
54
+ catch {
55
+ // Column already exists.
56
+ }
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)`));
60
+ })().catch((err) => {
61
+ initPromise = undefined;
62
+ throw err;
63
+ });
64
+ }
65
+ return initPromise;
66
+ }
67
+ export async function saveAgentHarnessSession(input) {
68
+ await ensureAgentHarnessSessionTables();
69
+ const now = Date.now();
70
+ const existing = await getAgentHarnessSession(input.id);
71
+ const record = {
72
+ id: input.id,
73
+ harnessName: input.harnessName,
74
+ threadId: input.threadId,
75
+ runId: input.runId ?? null,
76
+ providerSessionId: input.providerSessionId ?? null,
77
+ status: input.status ?? existing?.status ?? "idle",
78
+ resumeState: input.resumeState !== undefined
79
+ ? input.resumeState
80
+ : existing?.resumeState,
81
+ workspaceRef: input.workspaceRef ?? existing?.workspaceRef ?? null,
82
+ pendingApproval: input.pendingApproval !== undefined
83
+ ? input.pendingApproval
84
+ : existing?.pendingApproval,
85
+ ownerEmail: input.ownerEmail ?? existing?.ownerEmail ?? null,
86
+ orgId: input.orgId ?? existing?.orgId ?? null,
87
+ createdAt: existing?.createdAt ?? now,
88
+ updatedAt: now,
89
+ stoppedAt: input.stoppedAt ?? existing?.stoppedAt ?? null,
90
+ };
91
+ const client = getDbExec();
92
+ await client.execute({
93
+ sql: `INSERT INTO agent_harness_sessions (
94
+ id, harness_name, thread_id, run_id, provider_session_id, status,
95
+ resume_state, workspace_ref, pending_approval, owner_email, org_id,
96
+ created_at, updated_at, stopped_at
97
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
98
+ ON CONFLICT(id) DO UPDATE SET
99
+ harness_name = excluded.harness_name,
100
+ thread_id = excluded.thread_id,
101
+ run_id = excluded.run_id,
102
+ provider_session_id = excluded.provider_session_id,
103
+ status = excluded.status,
104
+ resume_state = excluded.resume_state,
105
+ workspace_ref = excluded.workspace_ref,
106
+ pending_approval = excluded.pending_approval,
107
+ owner_email = excluded.owner_email,
108
+ org_id = excluded.org_id,
109
+ updated_at = excluded.updated_at,
110
+ stopped_at = excluded.stopped_at`,
111
+ args: [
112
+ record.id,
113
+ record.harnessName,
114
+ record.threadId,
115
+ record.runId ?? null,
116
+ record.providerSessionId ?? null,
117
+ record.status,
118
+ serializeJson(record.resumeState),
119
+ record.workspaceRef ?? null,
120
+ serializeJson(record.pendingApproval),
121
+ record.ownerEmail ?? null,
122
+ record.orgId ?? null,
123
+ record.createdAt,
124
+ record.updatedAt,
125
+ record.stoppedAt ?? null,
126
+ ],
127
+ });
128
+ return record;
129
+ }
130
+ export async function updateAgentHarnessSession(id, patch) {
131
+ const existing = await getAgentHarnessSession(id);
132
+ if (!existing)
133
+ return null;
134
+ return saveAgentHarnessSession({
135
+ id,
136
+ harnessName: patch.harnessName ?? existing.harnessName,
137
+ threadId: patch.threadId ?? existing.threadId,
138
+ runId: patch.runId ?? existing.runId ?? null,
139
+ providerSessionId: patch.providerSessionId ?? existing.providerSessionId ?? null,
140
+ status: patch.status ?? existing.status,
141
+ resumeState: patch.resumeState !== undefined
142
+ ? patch.resumeState
143
+ : existing.resumeState,
144
+ workspaceRef: patch.workspaceRef ?? existing.workspaceRef ?? null,
145
+ pendingApproval: patch.pendingApproval !== undefined
146
+ ? patch.pendingApproval
147
+ : existing.pendingApproval,
148
+ ownerEmail: patch.ownerEmail ?? existing.ownerEmail ?? null,
149
+ orgId: patch.orgId ?? existing.orgId ?? null,
150
+ stoppedAt: patch.stoppedAt ?? existing.stoppedAt ?? null,
151
+ });
152
+ }
153
+ export async function getAgentHarnessSession(id) {
154
+ await ensureAgentHarnessSessionTables();
155
+ const client = getDbExec();
156
+ const { rows } = await client.execute({
157
+ sql: `SELECT * FROM agent_harness_sessions WHERE id = ?`,
158
+ args: [id],
159
+ });
160
+ return rowToHarnessSession(rows[0]);
161
+ }
162
+ export async function getLatestAgentHarnessSessionForThread(threadId, harnessName) {
163
+ await ensureAgentHarnessSessionTables();
164
+ const client = getDbExec();
165
+ const { rows } = harnessName
166
+ ? await client.execute({
167
+ sql: `SELECT * FROM agent_harness_sessions
168
+ WHERE thread_id = ? AND harness_name = ? AND status != 'destroyed'
169
+ ORDER BY updated_at DESC LIMIT 1`,
170
+ args: [threadId, harnessName],
171
+ })
172
+ : await client.execute({
173
+ sql: `SELECT * FROM agent_harness_sessions
174
+ WHERE thread_id = ? AND status != 'destroyed'
175
+ ORDER BY updated_at DESC LIMIT 1`,
176
+ args: [threadId],
177
+ });
178
+ return rowToHarnessSession(rows[0]);
179
+ }
180
+ export async function getAgentHarnessSessionByRunId(runId) {
181
+ await ensureAgentHarnessSessionTables();
182
+ const client = getDbExec();
183
+ const { rows } = await client.execute({
184
+ sql: `SELECT * FROM agent_harness_sessions
185
+ WHERE run_id = ?
186
+ ORDER BY updated_at DESC LIMIT 1`,
187
+ args: [runId],
188
+ });
189
+ return rowToHarnessSession(rows[0]);
190
+ }
191
+ export async function listAgentHarnessSessions(options = {}) {
192
+ await ensureAgentHarnessSessionTables();
193
+ const limit = Math.max(1, Math.min(200, options.limit ?? 50));
194
+ const client = getDbExec();
195
+ if (options.ownerEmail) {
196
+ const { rows } = await client.execute({
197
+ sql: `SELECT * FROM agent_harness_sessions
198
+ WHERE owner_email = ?
199
+ ORDER BY updated_at DESC LIMIT ?`,
200
+ args: [options.ownerEmail, limit],
201
+ });
202
+ const sessions = rows.map(rowToHarnessSession).filter(isStoredSession);
203
+ return sessions.filter((session) => (!options.threadId || session.threadId === options.threadId) &&
204
+ (!options.status || session.status === options.status) &&
205
+ (!options.orgId || session.orgId === options.orgId));
206
+ }
207
+ if (options.threadId && options.status) {
208
+ const { rows } = await client.execute({
209
+ sql: `SELECT * FROM agent_harness_sessions
210
+ WHERE thread_id = ? AND status = ?
211
+ ORDER BY updated_at DESC LIMIT ?`,
212
+ args: [options.threadId, options.status, limit],
213
+ });
214
+ return rows.map(rowToHarnessSession).filter(isStoredSession);
215
+ }
216
+ if (options.threadId) {
217
+ const { rows } = await client.execute({
218
+ sql: `SELECT * FROM agent_harness_sessions
219
+ WHERE thread_id = ?
220
+ ORDER BY updated_at DESC LIMIT ?`,
221
+ args: [options.threadId, limit],
222
+ });
223
+ return rows.map(rowToHarnessSession).filter(isStoredSession);
224
+ }
225
+ if (options.status) {
226
+ const { rows } = await client.execute({
227
+ sql: `SELECT * FROM agent_harness_sessions
228
+ WHERE status = ?
229
+ ORDER BY updated_at DESC LIMIT ?`,
230
+ args: [options.status, limit],
231
+ });
232
+ return rows.map(rowToHarnessSession).filter(isStoredSession);
233
+ }
234
+ const { rows } = await client.execute({
235
+ sql: `SELECT * FROM agent_harness_sessions
236
+ ORDER BY updated_at DESC LIMIT ?`,
237
+ args: [limit],
238
+ });
239
+ return rows.map(rowToHarnessSession).filter(isStoredSession);
240
+ }
241
+ export async function markAgentHarnessSessionStopped(id, status) {
242
+ return updateAgentHarnessSession(id, {
243
+ status,
244
+ stoppedAt: Date.now(),
245
+ pendingApproval: null,
246
+ });
247
+ }
248
+ function rowToHarnessSession(row) {
249
+ if (!row || typeof row !== "object")
250
+ return null;
251
+ const record = row;
252
+ return {
253
+ id: String(record.id),
254
+ harnessName: String(record.harness_name),
255
+ threadId: String(record.thread_id),
256
+ runId: stringOrNull(record.run_id),
257
+ providerSessionId: stringOrNull(record.provider_session_id),
258
+ status: normalizeStatus(record.status),
259
+ resumeState: parseJson(record.resume_state),
260
+ workspaceRef: stringOrNull(record.workspace_ref),
261
+ pendingApproval: parseJson(record.pending_approval),
262
+ ownerEmail: stringOrNull(record.owner_email),
263
+ orgId: stringOrNull(record.org_id),
264
+ createdAt: numberValue(record.created_at),
265
+ updatedAt: numberValue(record.updated_at),
266
+ stoppedAt: record.stopped_at === null || record.stopped_at === undefined
267
+ ? null
268
+ : numberValue(record.stopped_at),
269
+ };
270
+ }
271
+ function isStoredSession(session) {
272
+ return Boolean(session);
273
+ }
274
+ function normalizeStatus(value) {
275
+ return value === "running" ||
276
+ value === "idle" ||
277
+ value === "stopped" ||
278
+ value === "errored" ||
279
+ value === "destroyed"
280
+ ? value
281
+ : "idle";
282
+ }
283
+ function serializeJson(value) {
284
+ if (value === undefined || value === null)
285
+ return null;
286
+ return JSON.stringify(value);
287
+ }
288
+ function parseJson(value) {
289
+ if (typeof value !== "string" || !value)
290
+ return undefined;
291
+ try {
292
+ return JSON.parse(value);
293
+ }
294
+ catch {
295
+ return undefined;
296
+ }
297
+ }
298
+ function stringOrNull(value) {
299
+ return typeof value === "string" && value ? value : null;
300
+ }
301
+ function numberValue(value) {
302
+ return typeof value === "number" ? value : Number(value ?? 0);
303
+ }
304
+ //# sourceMappingURL=store.js.map
@@ -0,0 +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"]}