@pasko70/pibo 1.16.5 → 2.0.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 (146) hide show
  1. package/dist/agent-runtime/auth.js +28 -0
  2. package/dist/agent-runtime/capabilities.js +221 -0
  3. package/dist/agent-runtime/context-build.js +313 -0
  4. package/dist/agent-runtime/contract.js +45 -0
  5. package/dist/agent-runtime/errors.js +57 -0
  6. package/dist/agent-runtime/events.js +1 -0
  7. package/dist/agent-runtime/history.js +1 -0
  8. package/dist/agent-runtime/profile-validation.js +109 -0
  9. package/dist/agent-runtime/registry.js +608 -0
  10. package/dist/agent-runtime/resource-files.js +87 -0
  11. package/dist/agent-runtime/resource-service.js +635 -0
  12. package/dist/agent-runtime/resources.js +1 -0
  13. package/dist/agent-runtime/routed-session.js +931 -0
  14. package/dist/agent-runtime/testing/contract.js +51 -0
  15. package/dist/agent-runtime/testing/fake-adapter.js +192 -0
  16. package/dist/agent-runtime/types.js +3 -0
  17. package/dist/agent-runtimes/codex-native/adapter.js +905 -0
  18. package/dist/agent-runtimes/codex-native/auth.js +476 -0
  19. package/dist/agent-runtimes/codex-native/client.js +734 -0
  20. package/dist/agent-runtimes/codex-native/config.js +152 -0
  21. package/dist/agent-runtimes/codex-native/history.js +283 -0
  22. package/dist/agent-runtimes/codex-native/mcp-stdio-launcher.js +89 -0
  23. package/dist/agent-runtimes/codex-native/models.js +581 -0
  24. package/dist/agent-runtimes/codex-native/process.js +459 -0
  25. package/dist/agent-runtimes/codex-native/protocol-types.js +1 -0
  26. package/dist/agent-runtimes/codex-native/protocol-version.js +7 -0
  27. package/dist/agent-runtimes/codex-native/redaction.js +31 -0
  28. package/dist/agent-runtimes/codex-native/requests.js +378 -0
  29. package/dist/agent-runtimes/codex-native/resource-delivery.js +445 -0
  30. package/dist/agent-runtimes/codex-native/thread.js +388 -0
  31. package/dist/agent-runtimes/codex-native/turn.js +849 -0
  32. package/dist/agent-runtimes/pi/adapter.js +653 -0
  33. package/dist/agent-runtimes/pi/auth.js +455 -0
  34. package/dist/agent-runtimes/pi/history.js +640 -0
  35. package/dist/agent-runtimes/pi/model-catalog.js +87 -0
  36. package/dist/agent-runtimes/pi/routed-session.js +1464 -0
  37. package/dist/agent-runtimes/pi/runtime.js +534 -0
  38. package/dist/agent-runtimes/pi/tool-compiler.js +69 -0
  39. package/dist/apps/chat/agent-profiles.js +40 -23
  40. package/dist/apps/chat/agent-store.js +111 -64
  41. package/dist/apps/chat/chat-api-routes.js +1 -1
  42. package/dist/apps/chat/chat-request-normalizers.js +47 -0
  43. package/dist/apps/chat/data/chat-data-mappers.js +25 -9
  44. package/dist/apps/chat/data/history-query-service.js +108 -0
  45. package/dist/apps/chat/data/session-query-service.js +24 -3
  46. package/dist/apps/chat/data/timeline-query-service.js +3 -3
  47. package/dist/apps/chat/model-catalog.js +1 -55
  48. package/dist/apps/chat/provider-auth-actions.js +171 -23
  49. package/dist/apps/chat/stream.js +12 -0
  50. package/dist/apps/chat/trace-v2.js +1 -0
  51. package/dist/apps/chat/trace.js +126 -415
  52. package/dist/apps/chat/web-app.js +582 -157
  53. package/dist/apps/chat-ui/assets/{dist-QXwINWYY.js → dist-9v2ZXT6V.js} +1 -1
  54. package/dist/apps/chat-ui/assets/{dist-CvZNkkOi.js → dist-B1LVAytl.js} +1 -1
  55. package/dist/apps/chat-ui/assets/{dist-_SP-MjLq.js → dist-C6LPDFXU.js} +1 -1
  56. package/dist/apps/chat-ui/assets/{dist-Bad4Yz4P.js → dist-DVtXxfHc.js} +1 -1
  57. package/dist/apps/chat-ui/assets/{dist-xy-zomwl.js → dist-DW4Qrfbd.js} +1 -1
  58. package/dist/apps/chat-ui/assets/{dist-DI4i80O2.js → dist-DmbsHdMC.js} +1 -1
  59. package/dist/apps/chat-ui/assets/{dist-D17yAUqp.js → dist-DyvwuSFO.js} +1 -1
  60. package/dist/apps/chat-ui/assets/{dist-Bc3Vbgjh.js → dist-I26VB0QO.js} +1 -1
  61. package/dist/apps/chat-ui/assets/{dist-BzqH7w58.js → dist-RtHbJRPV.js} +1 -1
  62. package/dist/apps/chat-ui/assets/{dist-CMDJ-WZm.js → dist-sZgJkWZb.js} +1 -1
  63. package/dist/apps/chat-ui/assets/index-BPbNvcZe.css +1 -0
  64. package/dist/apps/chat-ui/assets/index-CIOf2uL2.js +237 -0
  65. package/dist/apps/chat-ui/index.html +2 -2
  66. package/dist/apps/chat-vscode-web/assets/index-1ivRyjFs.js +41 -0
  67. package/dist/apps/chat-vscode-web/index.html +1 -1
  68. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  69. package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.0.0.vsix +0 -0
  70. package/dist/auth/login-actions.js +5 -251
  71. package/dist/cli-session/localSessionSource.js +8 -1
  72. package/dist/core/context-build.js +124 -20
  73. package/dist/core/default-profile.js +8 -0
  74. package/dist/core/profiles.js +30 -3
  75. package/dist/core/routed-session.js +5 -1446
  76. package/dist/core/runtime.js +5 -561
  77. package/dist/core/session-router.js +637 -83
  78. package/dist/data/cli.js +20 -3
  79. package/dist/data/schema.js +104 -1
  80. package/dist/data/session-store.js +24 -1
  81. package/dist/debug/events.js +25 -10
  82. package/dist/debug/failures.js +23 -3
  83. package/dist/debug/index.js +24 -6
  84. package/dist/debug/messages.js +87 -7
  85. package/dist/debug/persisted-payloads.js +31 -0
  86. package/dist/debug/pty.js +7 -6
  87. package/dist/debug/runtime-binding.js +29 -0
  88. package/dist/debug/session.js +137 -0
  89. package/dist/debug/summary.js +12 -0
  90. package/dist/debug/telemetry.js +28 -0
  91. package/dist/debug/tools.js +12 -2
  92. package/dist/debug/trace.js +154 -76
  93. package/dist/gateway/server.js +87 -2
  94. package/dist/gateway/tool.js +5 -5
  95. package/dist/index.js +21 -2
  96. package/dist/loops/tools.js +13 -12
  97. package/dist/mcp/agent-context.js +13 -4
  98. package/dist/mcp/client.js +10 -6
  99. package/dist/mcp/config.js +5 -2
  100. package/dist/mcp/runtime-session.js +166 -0
  101. package/dist/plugins/builtin.js +191 -53
  102. package/dist/plugins/codex-native.js +29 -0
  103. package/dist/plugins/registry.js +66 -2
  104. package/dist/runs/tools.js +26 -25
  105. package/dist/session-ui/terminalRows.js +2 -2
  106. package/dist/sessions/pibo-data-store.js +125 -16
  107. package/dist/sessions/runtime-binding.js +107 -0
  108. package/dist/sessions/sqlite-store.js +239 -18
  109. package/dist/sessions/store.js +86 -7
  110. package/dist/shared/trace-engine.js +18 -9
  111. package/dist/shared/trace-event-projection.js +29 -11
  112. package/dist/shared/{trace-transcript.js → trace-history.js} +193 -195
  113. package/dist/shared/trace-order.js +9 -4
  114. package/dist/shared/trace-page-merge.js +1 -1
  115. package/dist/signals/projector.js +20 -2
  116. package/dist/signals/registry.js +11 -0
  117. package/dist/subagents/tool.js +8 -6
  118. package/dist/tools/codex-browser.js +20 -19
  119. package/dist/tools/codex-compat.js +10 -9
  120. package/dist/tools/codex-image-generation.js +8 -6
  121. package/dist/tools/contract.js +45 -0
  122. package/dist/tools/credential-registry.js +182 -0
  123. package/dist/tools/mcp-bridge.js +511 -0
  124. package/dist/tools/payload-writer.js +17 -0
  125. package/dist/tools/runtime/tool.js +10 -9
  126. package/dist/tools/schema.js +9 -0
  127. package/dist/tools/session-service.js +193 -0
  128. package/dist/tools/session-tool-set.js +85 -0
  129. package/dist/web-annotations/tools.js +17 -16
  130. package/docs/README.md +11 -0
  131. package/package.json +3 -2
  132. package/skills/builtin/pibo-agent-runtime-adapter/SKILL.md +183 -0
  133. package/skills/builtin/pibo-agent-runtime-adapter/evals/README.md +10 -0
  134. package/skills/builtin/pibo-agent-runtime-adapter/evals/evals.json +45 -0
  135. package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/orion-full-harness.md +60 -0
  136. package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/relay-partial-harness.md +52 -0
  137. package/skills/builtin/pibo-agent-runtime-adapter/references/capabilities-and-designer.md +194 -0
  138. package/skills/builtin/pibo-agent-runtime-adapter/references/history-debug-and-security.md +213 -0
  139. package/skills/builtin/pibo-agent-runtime-adapter/references/interfaces-and-registration.md +214 -0
  140. package/skills/builtin/pibo-agent-runtime-adapter/references/lifecycle-bindings-and-events.md +193 -0
  141. package/skills/builtin/pibo-agent-runtime-adapter/references/portable-delivery-and-native-behavior.md +226 -0
  142. package/skills/builtin/pibo-agent-runtime-adapter/references/testing-migration-and-validation.md +256 -0
  143. package/dist/apps/chat-ui/assets/index-C45B0rw7.js +0 -237
  144. package/dist/apps/chat-ui/assets/index-E0RmuCkY.css +0 -1
  145. package/dist/apps/chat-vscode-web/assets/index-D-tSsXLG.js +0 -41
  146. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.16.5.vsix +0 -0
@@ -3,10 +3,75 @@ import { mkdirSync } from "node:fs";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { piboHomePath } from "../../core/pibo-home.js";
5
5
  import { DatabaseSync } from "node:sqlite";
6
- import { DEFAULT_BUILTIN_TOOL_NAMES } from "../../core/profiles.js";
6
+ import { DEFAULT_AGENT_RUNTIME_INSTANCE_ID, DEFAULT_BUILTIN_TOOL_NAMES } from "../../core/profiles.js";
7
7
  import { isPiboThinkingLevel } from "../../core/thinking.js";
8
8
  import { findPiPackage } from "../../pi-packages/store.js";
9
9
  const CUSTOM_AGENT_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
10
+ export function previewCustomAgentCreate(input, options = {}) {
11
+ const now = options.now ?? new Date().toISOString();
12
+ const id = options.id ?? `agent_${randomUUID()}`;
13
+ return {
14
+ id,
15
+ profileName: input.displayName,
16
+ displayName: input.displayName,
17
+ profileAliases: [],
18
+ description: input.description,
19
+ runtimeInstanceId: sanitizeRuntimeInstanceId(input.runtimeInstanceId),
20
+ runtimeOptions: cloneRuntimeOptions(input.runtimeOptions),
21
+ nativeTools: [...(input.nativeTools ?? [])],
22
+ skills: [...(input.skills ?? [])],
23
+ contextFiles: [...(input.contextFiles ?? [])],
24
+ subagents: sanitizeSubagents(input.subagents ?? []),
25
+ mcpServers: uniqueStrings(input.mcpServers ?? []),
26
+ piPackages: sanitizePiPackages(input.piPackages ?? []),
27
+ mainModel: sanitizeModelProfile(input.mainModel),
28
+ subagentModel: sanitizeModelProfile(input.subagentModel),
29
+ thinkingLevel: sanitizeThinkingLevel(input.thinkingLevel),
30
+ mainThinkingLevel: sanitizeThinkingLevel(input.mainThinkingLevel),
31
+ subagentThinkingLevel: sanitizeThinkingLevel(input.subagentThinkingLevel),
32
+ fast: sanitizeBoolean(input.fast),
33
+ mainFast: sanitizeBoolean(input.mainFast),
34
+ subagentFast: sanitizeBoolean(input.subagentFast),
35
+ builtinTools: input.builtinTools ?? "default",
36
+ builtinToolNames: sanitizeBuiltinToolNames(input.builtinToolNames),
37
+ autoContextFiles: input.autoContextFiles ?? true,
38
+ runControl: input.runControl ?? false,
39
+ goalControl: input.goalControl ?? true,
40
+ createdAt: now,
41
+ updatedAt: now,
42
+ };
43
+ }
44
+ export function previewCustomAgentUpdate(existing, input, options = {}) {
45
+ const profileName = input.displayName ?? existing.displayName;
46
+ return {
47
+ ...existing,
48
+ profileName,
49
+ displayName: input.displayName ?? existing.displayName,
50
+ description: input.description === undefined ? existing.description : input.description,
51
+ runtimeInstanceId: input.runtimeInstanceId === undefined ? existing.runtimeInstanceId : sanitizeRuntimeInstanceId(input.runtimeInstanceId),
52
+ runtimeOptions: input.runtimeOptions === undefined ? existing.runtimeOptions : cloneRuntimeOptions(input.runtimeOptions),
53
+ nativeTools: input.nativeTools ? [...input.nativeTools] : existing.nativeTools,
54
+ skills: input.skills ? [...input.skills] : existing.skills,
55
+ contextFiles: input.contextFiles ? [...input.contextFiles] : existing.contextFiles,
56
+ subagents: input.subagents ? sanitizeSubagents(input.subagents) : existing.subagents,
57
+ mcpServers: input.mcpServers ? uniqueStrings(input.mcpServers) : existing.mcpServers,
58
+ piPackages: input.piPackages ? sanitizePiPackages(input.piPackages) : existing.piPackages,
59
+ mainModel: input.mainModel === undefined ? existing.mainModel : sanitizeModelProfile(input.mainModel),
60
+ subagentModel: input.subagentModel === undefined ? existing.subagentModel : sanitizeModelProfile(input.subagentModel),
61
+ thinkingLevel: input.thinkingLevel === undefined ? existing.thinkingLevel : sanitizeThinkingLevel(input.thinkingLevel),
62
+ mainThinkingLevel: input.mainThinkingLevel === undefined ? existing.mainThinkingLevel : sanitizeThinkingLevel(input.mainThinkingLevel),
63
+ subagentThinkingLevel: input.subagentThinkingLevel === undefined ? existing.subagentThinkingLevel : sanitizeThinkingLevel(input.subagentThinkingLevel),
64
+ fast: input.fast === undefined ? existing.fast : sanitizeBoolean(input.fast),
65
+ mainFast: input.mainFast === undefined ? existing.mainFast : sanitizeBoolean(input.mainFast),
66
+ subagentFast: input.subagentFast === undefined ? existing.subagentFast : sanitizeBoolean(input.subagentFast),
67
+ builtinTools: input.builtinTools ?? existing.builtinTools,
68
+ builtinToolNames: input.builtinToolNames ? sanitizeBuiltinToolNames(input.builtinToolNames) : existing.builtinToolNames,
69
+ autoContextFiles: input.autoContextFiles ?? existing.autoContextFiles,
70
+ runControl: input.runControl ?? existing.runControl,
71
+ goalControl: input.goalControl ?? existing.goalControl,
72
+ updatedAt: options.now ?? new Date().toISOString(),
73
+ };
74
+ }
10
75
  export class CustomAgentStore {
11
76
  db;
12
77
  constructor(path) {
@@ -24,6 +89,8 @@ export class CustomAgentStore {
24
89
  profile_name TEXT NOT NULL UNIQUE,
25
90
  display_name TEXT NOT NULL,
26
91
  description TEXT,
92
+ runtime_instance_id TEXT NOT NULL DEFAULT 'pi',
93
+ runtime_options_json TEXT NOT NULL DEFAULT '{}',
27
94
  native_tools_json TEXT NOT NULL,
28
95
  skills_json TEXT NOT NULL,
29
96
  context_files_json TEXT NOT NULL,
@@ -53,6 +120,7 @@ export class CustomAgentStore {
53
120
  this.migrateArchivedAtColumn();
54
121
  this.migrateAutoContextFilesColumn();
55
122
  this.migrateMcpServersColumn();
123
+ this.migrateRuntimeColumns();
56
124
  this.migratePiPackagesColumn();
57
125
  this.migrateModelColumns();
58
126
  this.migrateThinkingLevelColumn();
@@ -78,42 +146,12 @@ export class CustomAgentStore {
78
146
  }
79
147
  create(input) {
80
148
  this.migrateLegacyProfileNames();
81
- const now = new Date().toISOString();
82
- const id = `agent_${randomUUID()}`;
83
- const profileName = input.displayName;
84
- this.requireProfileNameAvailable(profileName);
85
- const agent = {
86
- id,
87
- profileName,
88
- displayName: input.displayName,
89
- profileAliases: [],
90
- description: input.description,
91
- nativeTools: [...(input.nativeTools ?? [])],
92
- skills: [...(input.skills ?? [])],
93
- contextFiles: [...(input.contextFiles ?? [])],
94
- subagents: sanitizeSubagents(input.subagents ?? []),
95
- mcpServers: uniqueStrings(input.mcpServers ?? []),
96
- piPackages: sanitizePiPackages(input.piPackages ?? []),
97
- mainModel: sanitizeModelProfile(input.mainModel),
98
- subagentModel: sanitizeModelProfile(input.subagentModel),
99
- thinkingLevel: sanitizeThinkingLevel(input.thinkingLevel),
100
- mainThinkingLevel: sanitizeThinkingLevel(input.mainThinkingLevel),
101
- subagentThinkingLevel: sanitizeThinkingLevel(input.subagentThinkingLevel),
102
- fast: sanitizeBoolean(input.fast),
103
- mainFast: sanitizeBoolean(input.mainFast),
104
- subagentFast: sanitizeBoolean(input.subagentFast),
105
- builtinTools: input.builtinTools ?? "default",
106
- builtinToolNames: sanitizeBuiltinToolNames(input.builtinToolNames),
107
- autoContextFiles: input.autoContextFiles ?? true,
108
- runControl: input.runControl ?? false,
109
- goalControl: input.goalControl ?? true,
110
- createdAt: now,
111
- updatedAt: now,
112
- };
149
+ this.requireProfileNameAvailable(input.displayName);
150
+ const agent = previewCustomAgentCreate(input);
113
151
  this.insert(agent);
114
- const created = this.get(id);
152
+ const created = this.get(agent.id);
115
153
  if (!created)
116
- throw new Error(`Failed to create custom agent "${id}"`);
154
+ throw new Error(`Failed to create custom agent "${agent.id}"`);
117
155
  return created;
118
156
  }
119
157
  update(id, input) {
@@ -123,38 +161,15 @@ export class CustomAgentStore {
123
161
  return undefined;
124
162
  const profileName = input.displayName ?? existing.displayName;
125
163
  this.requireProfileNameAvailable(profileName, id);
126
- const updated = {
127
- ...existing,
128
- profileName,
129
- displayName: input.displayName ?? existing.displayName,
130
- description: input.description === undefined ? existing.description : input.description,
131
- nativeTools: input.nativeTools ? [...input.nativeTools] : existing.nativeTools,
132
- skills: input.skills ? [...input.skills] : existing.skills,
133
- contextFiles: input.contextFiles ? [...input.contextFiles] : existing.contextFiles,
134
- subagents: input.subagents ? sanitizeSubagents(input.subagents) : existing.subagents,
135
- mcpServers: input.mcpServers ? uniqueStrings(input.mcpServers) : existing.mcpServers,
136
- piPackages: input.piPackages ? sanitizePiPackages(input.piPackages) : existing.piPackages,
137
- mainModel: input.mainModel === undefined ? existing.mainModel : sanitizeModelProfile(input.mainModel),
138
- subagentModel: input.subagentModel === undefined ? existing.subagentModel : sanitizeModelProfile(input.subagentModel),
139
- thinkingLevel: input.thinkingLevel === undefined ? existing.thinkingLevel : sanitizeThinkingLevel(input.thinkingLevel),
140
- mainThinkingLevel: input.mainThinkingLevel === undefined ? existing.mainThinkingLevel : sanitizeThinkingLevel(input.mainThinkingLevel),
141
- subagentThinkingLevel: input.subagentThinkingLevel === undefined ? existing.subagentThinkingLevel : sanitizeThinkingLevel(input.subagentThinkingLevel),
142
- fast: input.fast === undefined ? existing.fast : sanitizeBoolean(input.fast),
143
- mainFast: input.mainFast === undefined ? existing.mainFast : sanitizeBoolean(input.mainFast),
144
- subagentFast: input.subagentFast === undefined ? existing.subagentFast : sanitizeBoolean(input.subagentFast),
145
- builtinTools: input.builtinTools ?? existing.builtinTools,
146
- builtinToolNames: input.builtinToolNames ? sanitizeBuiltinToolNames(input.builtinToolNames) : existing.builtinToolNames,
147
- autoContextFiles: input.autoContextFiles ?? existing.autoContextFiles,
148
- runControl: input.runControl ?? existing.runControl,
149
- goalControl: input.goalControl ?? existing.goalControl,
150
- updatedAt: new Date().toISOString(),
151
- };
164
+ const updated = previewCustomAgentUpdate(existing, input);
152
165
  this.db
153
166
  .prepare(`
154
167
  UPDATE chat_agents SET
155
168
  profile_name = ?,
156
169
  display_name = ?,
157
170
  description = ?,
171
+ runtime_instance_id = ?,
172
+ runtime_options_json = ?,
158
173
  native_tools_json = ?,
159
174
  skills_json = ?,
160
175
  context_files_json = ?,
@@ -177,7 +192,7 @@ export class CustomAgentStore {
177
192
  updated_at = ?
178
193
  WHERE id = ?
179
194
  `)
180
- .run(updated.profileName, updated.displayName, updated.description ?? null, JSON.stringify(updated.nativeTools), JSON.stringify(updated.skills), JSON.stringify(updated.contextFiles), JSON.stringify(sanitizeSubagents(updated.subagents)), JSON.stringify(updated.mcpServers), JSON.stringify(updated.piPackages), updated.mainModel ? JSON.stringify(updated.mainModel) : null, updated.subagentModel ? JSON.stringify(updated.subagentModel) : null, updated.thinkingLevel ?? null, updated.mainThinkingLevel ?? null, updated.subagentThinkingLevel ?? null, serializeBoolean(updated.fast), serializeBoolean(updated.mainFast), serializeBoolean(updated.subagentFast), updated.builtinTools, JSON.stringify(updated.builtinToolNames), updated.autoContextFiles ? 1 : 0, updated.runControl ? 1 : 0, updated.goalControl ? 1 : 0, updated.updatedAt, id);
195
+ .run(updated.profileName, updated.displayName, updated.description ?? null, updated.runtimeInstanceId, JSON.stringify(updated.runtimeOptions), JSON.stringify(updated.nativeTools), JSON.stringify(updated.skills), JSON.stringify(updated.contextFiles), JSON.stringify(sanitizeSubagents(updated.subagents)), JSON.stringify(updated.mcpServers), JSON.stringify(updated.piPackages), updated.mainModel ? JSON.stringify(updated.mainModel) : null, updated.subagentModel ? JSON.stringify(updated.subagentModel) : null, updated.thinkingLevel ?? null, updated.mainThinkingLevel ?? null, updated.subagentThinkingLevel ?? null, serializeBoolean(updated.fast), serializeBoolean(updated.mainFast), serializeBoolean(updated.subagentFast), updated.builtinTools, JSON.stringify(updated.builtinToolNames), updated.autoContextFiles ? 1 : 0, updated.runControl ? 1 : 0, updated.goalControl ? 1 : 0, updated.updatedAt, id);
181
196
  return this.get(id);
182
197
  }
183
198
  setArchived(id, archived) {
@@ -207,6 +222,8 @@ export class CustomAgentStore {
207
222
  profile_name,
208
223
  display_name,
209
224
  description,
225
+ runtime_instance_id,
226
+ runtime_options_json,
210
227
  native_tools_json,
211
228
  skills_json,
212
229
  context_files_json,
@@ -229,9 +246,9 @@ export class CustomAgentStore {
229
246
  created_at,
230
247
  updated_at,
231
248
  archived_at
232
- ) VALUES (${Array.from({ length: 26 }, () => "?").join(", ")})
249
+ ) VALUES (${Array.from({ length: 28 }, () => "?").join(", ")})
233
250
  `)
234
- .run(agent.id, agent.profileName, agent.displayName, agent.description ?? null, JSON.stringify(agent.nativeTools), JSON.stringify(agent.skills), JSON.stringify(agent.contextFiles), JSON.stringify(sanitizeSubagents(agent.subagents)), JSON.stringify(agent.mcpServers), JSON.stringify(agent.piPackages), agent.mainModel ? JSON.stringify(agent.mainModel) : null, agent.subagentModel ? JSON.stringify(agent.subagentModel) : null, agent.thinkingLevel ?? null, agent.mainThinkingLevel ?? null, agent.subagentThinkingLevel ?? null, serializeBoolean(agent.fast), serializeBoolean(agent.mainFast), serializeBoolean(agent.subagentFast), agent.builtinTools, JSON.stringify(agent.builtinToolNames), agent.autoContextFiles ? 1 : 0, agent.runControl ? 1 : 0, agent.goalControl ? 1 : 0, agent.createdAt, agent.updatedAt, agent.archivedAt ?? null);
251
+ .run(agent.id, agent.profileName, agent.displayName, agent.description ?? null, agent.runtimeInstanceId, JSON.stringify(agent.runtimeOptions), JSON.stringify(agent.nativeTools), JSON.stringify(agent.skills), JSON.stringify(agent.contextFiles), JSON.stringify(sanitizeSubagents(agent.subagents)), JSON.stringify(agent.mcpServers), JSON.stringify(agent.piPackages), agent.mainModel ? JSON.stringify(agent.mainModel) : null, agent.subagentModel ? JSON.stringify(agent.subagentModel) : null, agent.thinkingLevel ?? null, agent.mainThinkingLevel ?? null, agent.subagentThinkingLevel ?? null, serializeBoolean(agent.fast), serializeBoolean(agent.mainFast), serializeBoolean(agent.subagentFast), agent.builtinTools, JSON.stringify(agent.builtinToolNames), agent.autoContextFiles ? 1 : 0, agent.runControl ? 1 : 0, agent.goalControl ? 1 : 0, agent.createdAt, agent.updatedAt, agent.archivedAt ?? null);
235
252
  }
236
253
  requireProfileNameAvailable(profileName, currentId) {
237
254
  const row = this.db.prepare("SELECT id FROM chat_agents WHERE profile_name = ?").get(profileName);
@@ -341,6 +358,15 @@ export class CustomAgentStore {
341
358
  this.db.prepare("ALTER TABLE chat_agents ADD COLUMN mcp_servers_json TEXT NOT NULL DEFAULT '[]'").run();
342
359
  }
343
360
  }
361
+ migrateRuntimeColumns() {
362
+ const columns = this.tableColumns();
363
+ if (!columns.has("runtime_instance_id")) {
364
+ this.db.prepare(`ALTER TABLE chat_agents ADD COLUMN runtime_instance_id TEXT NOT NULL DEFAULT '${DEFAULT_AGENT_RUNTIME_INSTANCE_ID}'`).run();
365
+ }
366
+ if (!columns.has("runtime_options_json")) {
367
+ this.db.prepare("ALTER TABLE chat_agents ADD COLUMN runtime_options_json TEXT NOT NULL DEFAULT '{}'").run();
368
+ }
369
+ }
344
370
  migratePiPackagesColumn() {
345
371
  const columns = new Set(this.db.prepare("PRAGMA table_info(chat_agents)").all().map((column) => column.name));
346
372
  if (!columns.has("pi_packages_json")) {
@@ -536,6 +562,8 @@ function agentFromRow(row, profileAliases) {
536
562
  displayName: row.display_name,
537
563
  profileAliases: profileAliases.filter((alias) => alias !== row.profile_name),
538
564
  description: row.description ?? undefined,
565
+ runtimeInstanceId: sanitizeRuntimeInstanceId(row.runtime_instance_id),
566
+ runtimeOptions: parseRuntimeOptions(row.runtime_options_json),
539
567
  nativeTools: parseStringArray(row.native_tools_json),
540
568
  skills: parseStringArray(row.skills_json),
541
569
  contextFiles: parseStringArray(row.context_files_json),
@@ -572,6 +600,25 @@ function parseStringArray(value) {
572
600
  function uniqueStrings(value) {
573
601
  return [...new Set(value.filter((item) => typeof item === "string" && item.trim()).map((item) => item.trim()))];
574
602
  }
603
+ function sanitizeRuntimeInstanceId(value) {
604
+ if (typeof value !== "string" || !value.trim())
605
+ return DEFAULT_AGENT_RUNTIME_INSTANCE_ID;
606
+ return value.trim();
607
+ }
608
+ function cloneRuntimeOptions(value) {
609
+ return structuredClone(value ?? {});
610
+ }
611
+ function parseRuntimeOptions(value) {
612
+ try {
613
+ const parsed = JSON.parse(value);
614
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
615
+ ? structuredClone(parsed)
616
+ : {};
617
+ }
618
+ catch {
619
+ return {};
620
+ }
621
+ }
575
622
  function sanitizePiPackages(value) {
576
623
  const packages = uniqueStrings(value);
577
624
  for (const pkg of packages) {
@@ -300,7 +300,7 @@ export function sessionActionResource(pathname) {
300
300
  if (parts.length !== 2 || !parts[0])
301
301
  return undefined;
302
302
  const action = parts[1];
303
- if (action !== "read" && action !== "kill" && action !== "kill-all")
303
+ if (action !== "read" && action !== "kill" && action !== "kill-all" && action !== "runtime-binding")
304
304
  return undefined;
305
305
  try {
306
306
  return { piboSessionId: decodeURIComponent(parts[0]), action };
@@ -1,6 +1,7 @@
1
1
  import { existsSync, statSync } from "node:fs";
2
2
  import { isAbsolute, resolve } from "node:path";
3
3
  import { savePiboModelDefaults } from "../../core/model-defaults.js";
4
+ import { DEFAULT_AGENT_RUNTIME_INSTANCE_ID } from "../../core/profiles.js";
4
5
  import { isPiboThinkingLevel } from "../../core/thinking.js";
5
6
  import { PiboWebHttpError } from "../../web/http.js";
6
7
  import { listPiPackages } from "../../pi-packages/store.js";
@@ -127,6 +128,46 @@ export function normalizeAgentDescription(value) {
127
128
  throw new PiboWebHttpError("Agent description is too long", 400);
128
129
  return description;
129
130
  }
131
+ export function normalizeAgentRuntimeInstanceId(value) {
132
+ if (value === undefined)
133
+ return DEFAULT_AGENT_RUNTIME_INSTANCE_ID;
134
+ if (typeof value !== "string" || !value.trim()) {
135
+ throw new PiboWebHttpError("runtimeInstanceId must be a non-empty string", 400);
136
+ }
137
+ const instanceId = value.trim();
138
+ if (!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/.test(instanceId)) {
139
+ throw new PiboWebHttpError("runtimeInstanceId is invalid", 400);
140
+ }
141
+ return instanceId;
142
+ }
143
+ export function normalizeAgentRuntimeOptions(value) {
144
+ if (value === undefined || value === null)
145
+ return {};
146
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
147
+ throw new PiboWebHttpError("runtimeOptions must be a JSON object", 400);
148
+ }
149
+ return normalizeAgentRuntimeJsonObject(value, "runtimeOptions", 0);
150
+ }
151
+ function normalizeAgentRuntimeJsonObject(value, path, depth) {
152
+ if (depth > 20)
153
+ throw new PiboWebHttpError(`${path} exceeds the maximum nesting depth`, 400);
154
+ const normalized = {};
155
+ for (const [key, item] of Object.entries(value)) {
156
+ normalized[key] = normalizeAgentRuntimeJsonValue(item, `${path}.${key}`, depth + 1);
157
+ }
158
+ return normalized;
159
+ }
160
+ function normalizeAgentRuntimeJsonValue(value, path, depth) {
161
+ if (value === null || typeof value === "string" || typeof value === "boolean")
162
+ return value;
163
+ if (typeof value === "number" && Number.isFinite(value))
164
+ return value;
165
+ if (Array.isArray(value))
166
+ return value.map((item, index) => normalizeAgentRuntimeJsonValue(item, `${path}[${index}]`, depth + 1));
167
+ if (value && typeof value === "object")
168
+ return normalizeAgentRuntimeJsonObject(value, path, depth + 1);
169
+ throw new PiboWebHttpError(`${path} must contain JSON values only`, 400);
170
+ }
130
171
  export function normalizeNameArray(value, label) {
131
172
  if (value === undefined)
132
173
  return [];
@@ -607,6 +648,8 @@ export function createAgentInput(body) {
607
648
  return {
608
649
  displayName: normalizeAgentDisplayName(body.displayName),
609
650
  description: normalizeAgentDescription(body.description),
651
+ runtimeInstanceId: normalizeAgentRuntimeInstanceId(body.runtimeInstanceId),
652
+ runtimeOptions: normalizeAgentRuntimeOptions(body.runtimeOptions),
610
653
  nativeTools: normalizeNameArray(body.nativeTools, "nativeTools"),
611
654
  skills: normalizeNameArray(body.skills, "skills"),
612
655
  contextFiles: normalizeNameArray(body.contextFiles, "contextFiles"),
@@ -634,6 +677,10 @@ export function createAgentUpdate(body) {
634
677
  update.displayName = normalizeAgentDisplayName(body.displayName);
635
678
  if (body.description !== undefined)
636
679
  update.description = normalizeAgentDescription(body.description);
680
+ if (body.runtimeInstanceId !== undefined)
681
+ update.runtimeInstanceId = normalizeAgentRuntimeInstanceId(body.runtimeInstanceId);
682
+ if (body.runtimeOptions !== undefined)
683
+ update.runtimeOptions = normalizeAgentRuntimeOptions(body.runtimeOptions);
637
684
  if (body.nativeTools !== undefined)
638
685
  update.nativeTools = normalizeNameArray(body.nativeTools, "nativeTools");
639
686
  if (body.skills !== undefined)
@@ -1,18 +1,18 @@
1
1
  import { normalizeSessionErrorDetails } from "../../../core/session-errors.js";
2
2
  import { roomWorkspaceFromMetadata } from "../types/rooms.js";
3
- export function storedPiboEventFromV2Row(row) {
3
+ export function storedPiboEventFromV2Row(row, payloadStore) {
4
4
  const attributes = parseJsonObject(row.attributes_json);
5
- const payload = outputPayloadFromV2Row(row, attributes);
5
+ const payload = outputPayloadFromV2Row(row, attributes, readPersistedPayload(row, payloadStore));
6
6
  if (!payload)
7
7
  return undefined;
8
8
  return { id: String(row.stream_id), piboSessionId: row.session_id ?? undefined, eventSequence: row.session_sequence ?? undefined, eventId: row.event_id ?? undefined, streamId: row.stream_id, type: row.type, createdAt: row.created_at, payload };
9
9
  }
10
- export function storedChatEventFromV2Row(row) {
10
+ export function storedChatEventFromV2Row(row, payloadStore) {
11
11
  const attributes = parseJsonObject(row.attributes_json);
12
- return { streamId: row.stream_id, roomId: row.room_id ?? undefined, piboSessionId: row.session_id ?? undefined, eventId: row.event_id ?? `evt_${row.stream_id}`, eventType: row.type, actorType: actorTypeValue(row.actor_type), actorId: row.actor_id ?? undefined, clientTxnId: typeof attributes.clientTxnId === "string" ? attributes.clientTxnId : undefined, createdAt: row.created_at, retentionClass: retentionClassValue(row.retention_class), payload: (outputPayloadFromV2Row(row, attributes) ?? null) };
12
+ return { streamId: row.stream_id, roomId: row.room_id ?? undefined, piboSessionId: row.session_id ?? undefined, eventId: row.event_id ?? `evt_${row.stream_id}`, eventType: row.type, actorType: actorTypeValue(row.actor_type), actorId: row.actor_id ?? undefined, clientTxnId: typeof attributes.clientTxnId === "string" ? attributes.clientTxnId : undefined, createdAt: row.created_at, retentionClass: retentionClassValue(row.retention_class), payload: (outputPayloadFromV2Row(row, attributes, readPersistedPayload(row, payloadStore)) ?? null) };
13
13
  }
14
- function outputPayloadFromV2Row(row, attributes) {
15
- const inlinePayload = attributes.inlinePayload;
14
+ function outputPayloadFromV2Row(row, attributes, persistedPayload) {
15
+ const inlinePayload = attributes.inlinePayload ?? persistedPayload;
16
16
  if (inlinePayload && typeof inlinePayload === "object" && !Array.isArray(inlinePayload) && typeof inlinePayload.type === "string")
17
17
  return inlinePayload;
18
18
  const piboSessionId = row.session_id;
@@ -25,7 +25,7 @@ function outputPayloadFromV2Row(row, attributes) {
25
25
  type: row.type,
26
26
  assistantIndex: numberAttribute(attributes, "assistantIndex"),
27
27
  contentIndex: numberAttribute(attributes, "contentIndex"),
28
- text: row.preview_text ?? "",
28
+ text: typeof inlinePayload === "string" ? inlinePayload : row.preview_text ?? "",
29
29
  });
30
30
  }
31
31
  if (row.type === "message_queued")
@@ -42,7 +42,7 @@ function outputPayloadFromV2Row(row, attributes) {
42
42
  type: row.type,
43
43
  thinkingIndex: numberAttribute(attributes, "thinkingIndex"),
44
44
  contentIndex: numberAttribute(attributes, "contentIndex"),
45
- ...(row.type === "thinking_started" ? {} : { text: row.preview_text ?? "" }),
45
+ ...(row.type === "thinking_started" ? {} : { text: typeof inlinePayload === "string" ? inlinePayload : row.preview_text ?? "" }),
46
46
  });
47
47
  }
48
48
  if (row.type === "tool_call")
@@ -71,7 +71,22 @@ function outputPayloadFromV2Row(row, attributes) {
71
71
  return { type: "user.message.accepted", piboSessionId, roomId: row.room_id ?? undefined, text: stringAttribute(attributes, "inlineText") ?? row.preview_text ?? "", clientTxnId: stringAttribute(attributes, "clientTxnId") };
72
72
  return { ...base, type: row.type };
73
73
  }
74
- export function sessionFromRow(row) { return { piboSessionId: row.id, piSessionId: row.pi_session_id ?? row.id, parentId: row.parent_id ?? undefined, profile: row.profile, channel: row.channel, kind: row.kind, createdAt: row.created_at, updatedAt: row.updated_at, lastActivityAt: row.last_activity_at, status: row.status === "running" || row.status === "error" ? row.status : "idle" }; }
74
+ function readPersistedPayload(row, payloadStore) {
75
+ if (!row.payload_ref || !payloadStore)
76
+ return undefined;
77
+ try {
78
+ const metadata = payloadStore.getPayload(row.payload_ref);
79
+ if (!metadata)
80
+ return undefined;
81
+ return metadata.contentType.includes("json")
82
+ ? payloadStore.readPayloadJson(row.payload_ref)
83
+ : payloadStore.readPayloadText(row.payload_ref);
84
+ }
85
+ catch {
86
+ return undefined;
87
+ }
88
+ }
89
+ export function sessionFromRow(row) { return { piboSessionId: row.id, piSessionId: row.pi_session_id ?? "", runtimeInstanceId: row.runtime_instance_id ?? undefined, runtimeAdapterId: row.runtime_adapter_id ?? undefined, runtimeBindingState: isRuntimeBindingState(row.binding_state) ? row.binding_state : undefined, nativeSessionId: row.native_session_id ?? undefined, parentId: row.parent_id ?? undefined, profile: row.profile, channel: row.channel, kind: row.kind, createdAt: row.created_at, updatedAt: row.updated_at, lastActivityAt: row.last_activity_at, status: row.status === "running" || row.status === "error" ? row.status : "idle" }; }
75
90
  export function roomFromRow(row) { const metadata = parseJsonObject(row.metadata_json); return { id: row.id, name: row.name, topic: row.topic ?? undefined, workspace: row.workspace ?? roomWorkspaceFromMetadata(metadata), type: row.type, parentRoomId: row.parent_room_id ?? undefined, createdAt: row.created_at, updatedAt: row.updated_at, retentionPolicyId: row.retention_policy_id ?? undefined, metadata }; }
76
91
  export function parseJsonObject(value) { try {
77
92
  const parsed = JSON.parse(value);
@@ -92,5 +107,6 @@ export function previewForPayload(payload) { if (typeof payload === "object" &&
92
107
  export function statusFromOutputEvent(event) { if (event.type === "session_error")
93
108
  return "error"; if (event.type === "message_finished")
94
109
  return "idle"; return "running"; }
110
+ function isRuntimeBindingState(value) { return value === "unbound" || value === "bound" || value === "missing" || value === "error"; }
95
111
  function actorTypeValue(value) { return value === "user" || value === "assistant" || value === "system" || value === "agent" ? value : undefined; }
96
112
  function retentionClassValue(value) { return value === "live_delta" || value === "chat_message" || value === "audit_event" ? value : "trace_event"; }
@@ -0,0 +1,108 @@
1
+ export class ChatHistoryQueryService {
2
+ store;
3
+ constructor(store) {
4
+ this.store = store;
5
+ }
6
+ listProductHistoryEntries(input) {
7
+ const limit = Math.max(1, Math.min(input.limit ?? 200, 1000));
8
+ const clauses = ["m.session_id = ?", "m.role IN ('user', 'assistant', 'system')"];
9
+ const values = [input.piboSessionId];
10
+ if (input.beforeSequence !== undefined) {
11
+ clauses.push("COALESCE(e.session_sequence, m.sequence) < ?");
12
+ values.push(input.beforeSequence);
13
+ }
14
+ const rows = this.store.db.prepare(`
15
+ SELECT m.*, e.session_sequence AS event_sequence
16
+ FROM chat_messages m
17
+ LEFT JOIN event_log e ON e.stream_id = m.source_stream_id
18
+ WHERE ${clauses.join(" AND ")}
19
+ ORDER BY m.sequence DESC
20
+ LIMIT ?
21
+ `).all(...values, limit);
22
+ return rows.reverse().flatMap((row) => {
23
+ const role = historyRole(row.role);
24
+ if (!role)
25
+ return [];
26
+ const attributes = parseObject(row.attributes_json);
27
+ const text = this.readMessageText(row, attributes);
28
+ return [{
29
+ id: `product:${row.id}`,
30
+ type: "message",
31
+ source: "product",
32
+ createdAt: row.created_at,
33
+ sequence: row.event_sequence ?? row.sequence,
34
+ turnId: row.turn_id ?? undefined,
35
+ role,
36
+ content: text,
37
+ assistantIndex: numberValue(attributes.assistantIndex),
38
+ contentIndex: numberValue(attributes.contentIndex),
39
+ status: historyStatus(row.status),
40
+ metadata: compactObject({
41
+ messageId: row.id,
42
+ sourceStreamId: row.source_stream_id ?? undefined,
43
+ completedAt: row.completed_at ?? undefined,
44
+ payloadRef: row.content_payload_ref ?? undefined,
45
+ }),
46
+ }];
47
+ });
48
+ }
49
+ getProductHistoryCoverage(piboSessionId) {
50
+ const row = this.store.db.prepare(`
51
+ SELECT
52
+ COUNT(*) AS message_count,
53
+ MIN(e.session_sequence) AS first_event_sequence,
54
+ MAX(e.session_sequence) AS last_event_sequence,
55
+ MIN(m.created_at) AS first_created_at,
56
+ MAX(m.created_at) AS last_created_at
57
+ FROM chat_messages m
58
+ LEFT JOIN event_log e ON e.stream_id = m.source_stream_id
59
+ WHERE m.session_id = ?
60
+ `).get(piboSessionId);
61
+ return {
62
+ messageCount: Number(row.message_count ?? 0),
63
+ firstEventSequence: row.first_event_sequence ?? undefined,
64
+ lastEventSequence: row.last_event_sequence ?? undefined,
65
+ firstCreatedAt: row.first_created_at ?? undefined,
66
+ lastCreatedAt: row.last_created_at ?? undefined,
67
+ };
68
+ }
69
+ readMessageText(row, attributes) {
70
+ if (row.content_payload_ref) {
71
+ try {
72
+ return this.store.payloads.readPayloadText(row.content_payload_ref);
73
+ }
74
+ catch {
75
+ // Retain the durable preview if the external payload was removed or corrupted.
76
+ }
77
+ }
78
+ if (typeof attributes.inlineText === "string")
79
+ return attributes.inlineText;
80
+ return row.content_preview ?? "";
81
+ }
82
+ }
83
+ function historyRole(role) {
84
+ return role === "user" || role === "assistant" || role === "system" ? role : undefined;
85
+ }
86
+ function historyStatus(status) {
87
+ if (status === "running" || status === "streaming" || status === "in_progress")
88
+ return "running";
89
+ if (status === "error" || status === "failed")
90
+ return "error";
91
+ return "complete";
92
+ }
93
+ function parseObject(value) {
94
+ try {
95
+ const parsed = JSON.parse(value);
96
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
97
+ }
98
+ catch {
99
+ return {};
100
+ }
101
+ }
102
+ function numberValue(value) {
103
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
104
+ }
105
+ function compactObject(value) {
106
+ const compact = Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
107
+ return Object.keys(compact).length ? compact : undefined;
108
+ }
@@ -30,11 +30,22 @@ export class ChatSessionQueryService {
30
30
  return undefined;
31
31
  }
32
32
  listSessions() {
33
- const rows = this.store.db.prepare("SELECT * FROM sessions WHERE deleted_at IS NULL ORDER BY last_activity_at DESC, created_at DESC").all();
33
+ const rows = this.store.db.prepare(`
34
+ SELECT s.*, b.runtime_instance_id, b.runtime_adapter_id, b.native_session_id, b.binding_state
35
+ FROM sessions s
36
+ LEFT JOIN session_runtime_bindings b ON b.pibo_session_id = s.id
37
+ WHERE s.deleted_at IS NULL
38
+ ORDER BY s.last_activity_at DESC, s.created_at DESC
39
+ `).all();
34
40
  return rows.map(sessionFromRow);
35
41
  }
36
42
  getSession(piboSessionId) {
37
- const row = this.store.db.prepare("SELECT * FROM sessions WHERE id = ? AND deleted_at IS NULL").get(piboSessionId);
43
+ const row = this.store.db.prepare(`
44
+ SELECT s.*, b.runtime_instance_id, b.runtime_adapter_id, b.native_session_id, b.binding_state
45
+ FROM sessions s
46
+ LEFT JOIN session_runtime_bindings b ON b.pibo_session_id = s.id
47
+ WHERE s.id = ? AND s.deleted_at IS NULL
48
+ `).get(piboSessionId);
38
49
  return row ? sessionFromRow(row) : undefined;
39
50
  }
40
51
  hasSessionActivity(piboSessionId) {
@@ -76,17 +87,27 @@ export class ChatSessionQueryService {
76
87
  s.created_at,
77
88
  s.updated_at,
78
89
  s.last_activity_at,
90
+ b.runtime_instance_id,
91
+ b.runtime_adapter_id,
92
+ b.native_session_id,
93
+ b.binding_state,
79
94
  n.status AS navigation_status,
80
95
  n.title AS navigation_title,
81
96
  n.sort_key AS navigation_sort_key,
82
97
  n.updated_at AS navigation_updated_at
83
98
  FROM sessions s
99
+ LEFT JOIN session_runtime_bindings b ON b.pibo_session_id = s.id
84
100
  LEFT JOIN session_navigation n ON n.session_id = s.id
85
101
  WHERE s.id = ? AND s.deleted_at IS NULL
86
102
  `).get(session.id);
87
103
  if (!row)
88
104
  return false;
89
- return row.pi_session_id === session.piSessionId
105
+ const binding = session.runtimeBinding;
106
+ return row.pi_session_id === (session.piSessionId || null)
107
+ && row.runtime_instance_id === (binding?.runtimeInstanceId ?? "pi")
108
+ && row.runtime_adapter_id === (binding?.adapterId ?? "pi")
109
+ && row.native_session_id === (binding?.nativeSessionId ?? (session.piSessionId || null))
110
+ && row.binding_state === (binding?.state ?? (session.piSessionId ? "bound" : "unbound"))
90
111
  && row.room_id === roomId
91
112
  && row.root_session_id === rootSessionId(session)
92
113
  && row.parent_id === (session.parentId ?? null)
@@ -23,7 +23,7 @@ export class ChatTimelineQueryService {
23
23
  const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
24
24
  const limit = Math.max(1, Math.min(input.limit ?? 1000, 5000));
25
25
  const rows = this.store.db.prepare(`SELECT * FROM event_log ${where} ORDER BY stream_id ASC LIMIT ?`).all(...values, limit);
26
- return rows.map(storedChatEventFromV2Row);
26
+ return rows.map((row) => storedChatEventFromV2Row(row, this.store.payloads));
27
27
  }
28
28
  listSessionEvents(piboSessionId, limit = 1000) {
29
29
  return this.listTraceEvents({ piboSessionId, limit, includeLive: true });
@@ -38,7 +38,7 @@ export class ChatTimelineQueryService {
38
38
  AND type IN ('message_queued', 'message_steered', 'message_started', 'message_finished', 'session_error', 'thinking_finished', 'assistant_message')
39
39
  ORDER BY session_sequence ASC, stream_id ASC
40
40
  `).all(piboSessionId);
41
- const events = rows.map(storedPiboEventFromV2Row).filter((event) => event !== undefined);
41
+ const events = rows.map((row) => storedPiboEventFromV2Row(row, this.store.payloads)).filter((event) => event !== undefined);
42
42
  return messageTurnTimingsFromEvents(events);
43
43
  }
44
44
  listTraceEvents(input) {
@@ -68,7 +68,7 @@ export class ChatTimelineQueryService {
68
68
  )
69
69
  ORDER BY session_sequence ASC, stream_id ASC
70
70
  `).all(...values, limit);
71
- return rows.map(storedPiboEventFromV2Row).filter((event) => event !== undefined);
71
+ return rows.map((row) => storedPiboEventFromV2Row(row, this.store.payloads)).filter((event) => event !== undefined);
72
72
  }
73
73
  countEventsByType(input = {}) {
74
74
  const clauses = [];