@pasko70/pibo 1.9.13 → 1.10.1

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 (163) hide show
  1. package/README.md +183 -183
  2. package/context/codex-base-prompt.md +148 -148
  3. package/context/compute-worker.md +23 -23
  4. package/context/pibo-compaction-prompt.md +100 -100
  5. package/context/pibo-native-tooling.md +18 -18
  6. package/context/pibo-system-prompt.md +77 -77
  7. package/dist/apps/chat/agent-profiles.js +2 -2
  8. package/dist/apps/chat/agent-store.js +263 -250
  9. package/dist/apps/chat/chat-request-normalizers.js +17 -0
  10. package/dist/apps/chat/data/chat-data-mappers.js +2 -0
  11. package/dist/apps/chat/data/project-service.js +168 -168
  12. package/dist/apps/chat/data/read-state-service.js +18 -18
  13. package/dist/apps/chat/data/session-query-service.js +25 -25
  14. package/dist/apps/chat/data/timeline-query-service.js +19 -19
  15. package/dist/apps/chat/loop-api.js +181 -0
  16. package/dist/apps/chat/static-assets.js +854 -854
  17. package/dist/apps/chat/web-app.js +36 -16
  18. package/dist/apps/chat/workflow-manual-trigger-runtime.js +149 -46
  19. package/dist/apps/chat/workflow-persistence.js +255 -255
  20. package/dist/apps/chat-ui/assets/{dist-BZ2eTC4f.js → dist-3Sts0Afa.js} +1 -1
  21. package/dist/apps/chat-ui/assets/{dist-BHa-kcGl.js → dist-4NlLjLs7.js} +1 -1
  22. package/dist/apps/chat-ui/assets/{dist-yCYNNb5d.js → dist-BA6mhAec.js} +1 -1
  23. package/dist/apps/chat-ui/assets/{dist-D811wJeV.js → dist-BPl-fzRB.js} +1 -1
  24. package/dist/apps/chat-ui/assets/{dist-Dq4GxJi3.js → dist-BPnn9e2B.js} +1 -1
  25. package/dist/apps/chat-ui/assets/{dist-CzE6k3F3.js → dist-BpfBSMzK.js} +1 -1
  26. package/dist/apps/chat-ui/assets/{dist-CnVsqwSG.js → dist-Cvx5M97R.js} +1 -1
  27. package/dist/apps/chat-ui/assets/{dist-WyXdYl-w.js → dist-DnXWNQRm.js} +1 -1
  28. package/dist/apps/chat-ui/assets/{dist-BNMu92bb.js → dist-hU-2oAb6.js} +1 -1
  29. package/dist/apps/chat-ui/assets/{dist-BCB6zezO.js → dist-r31x5Fcc.js} +1 -1
  30. package/dist/apps/chat-ui/assets/{dist-HqTN67dc.js → dist-uF6UXzI7.js} +1 -1
  31. package/dist/apps/chat-ui/assets/index-CaTGYBOS.js +173 -0
  32. package/dist/apps/chat-ui/assets/{index-C0x9nEcf.css → index-al8DeEjA.css} +1 -1
  33. package/dist/apps/chat-ui/index.html +18 -18
  34. package/dist/apps/chat-ui/manifest.webmanifest +25 -25
  35. package/dist/apps/chat-ui/sw.js +47 -47
  36. package/dist/apps/chat-vscode-web/assets/index-CK4SMZuu.js +41 -0
  37. package/dist/apps/chat-vscode-web/index.html +13 -13
  38. package/dist/apps/cli-ui/cliSessionsCommand.js +23 -23
  39. package/dist/apps/context-files-ui/index.html +11 -11
  40. package/dist/cli-session/localSessionSource.js +34 -12
  41. package/dist/cli.js +61 -44
  42. package/dist/compute/cli.js +54 -54
  43. package/dist/compute/resource-health.js +35 -2
  44. package/dist/core/events.js +6 -1
  45. package/dist/core/routed-session.js +97 -5
  46. package/dist/core/runtime.js +6 -1
  47. package/dist/core/session-router.js +27 -8
  48. package/dist/cron/cli.js +15 -15
  49. package/dist/cron/store.js +49 -49
  50. package/dist/data/cli.js +23 -23
  51. package/dist/data/event-log.js +23 -23
  52. package/dist/data/ingest-service.js +3 -1
  53. package/dist/data/message-store.js +27 -27
  54. package/dist/data/navigation-store.js +9 -9
  55. package/dist/data/observation-store.js +4 -4
  56. package/dist/data/payload-store.js +17 -17
  57. package/dist/data/schema.js +433 -433
  58. package/dist/data/session-store.js +4 -4
  59. package/dist/data/telemetry-queries.js +54 -54
  60. package/dist/data/telemetry.js +197 -197
  61. package/dist/debug/events.js +12 -12
  62. package/dist/debug/failures.js +6 -6
  63. package/dist/debug/index.js +231 -227
  64. package/dist/debug/messages.js +6 -6
  65. package/dist/debug/pty.js +124 -124
  66. package/dist/debug/session.js +29 -29
  67. package/dist/debug/tools.js +5 -5
  68. package/dist/debug/trace.js +42 -7
  69. package/dist/debug/web-snapshot-browser-scripts.js +294 -294
  70. package/dist/debug/web-streaming-browser-library.js +925 -925
  71. package/dist/debug/web-streaming-browser-scripts.js +232 -232
  72. package/dist/debug/web-streaming-provider-telemetry.js +4 -4
  73. package/dist/debug/web.js +93 -93
  74. package/dist/gateway/cli.js +19 -19
  75. package/dist/gateway/server.js +4 -2
  76. package/dist/gateway/web.js +2 -2
  77. package/dist/index.js +1 -0
  78. package/dist/loops/accounting.js +19 -0
  79. package/dist/loops/channel.js +8 -0
  80. package/dist/loops/cli.js +224 -0
  81. package/dist/loops/plugin.js +16 -0
  82. package/dist/loops/prompts.js +86 -0
  83. package/dist/loops/service.js +446 -0
  84. package/dist/loops/stopping.js +170 -0
  85. package/dist/loops/store.js +642 -0
  86. package/dist/loops/templates.js +232 -0
  87. package/dist/loops/tools.js +184 -0
  88. package/dist/loops/types.js +1 -0
  89. package/dist/mcp/config-command.js +53 -53
  90. package/dist/mcp/index.js +21 -21
  91. package/dist/mcp/registry.js +11 -11
  92. package/dist/pi-packages/cli.js +11 -11
  93. package/dist/plugins/builtin.js +8 -0
  94. package/dist/plugins/context-files-store.js +110 -110
  95. package/dist/plugins/context-files.js +4 -4
  96. package/dist/plugins/registry.js +23 -12
  97. package/dist/ralph/cli.js +18 -18
  98. package/dist/ralph/templates.js +140 -140
  99. package/dist/reliability/store.js +256 -229
  100. package/dist/runs/lifecycle.js +59 -0
  101. package/dist/runs/registry.js +47 -1
  102. package/dist/runs/tools.js +31 -13
  103. package/dist/session-ui/terminalRows.js +66 -2
  104. package/dist/sessions/pibo-data-store.js +16 -16
  105. package/dist/sessions/sqlite-store.js +53 -53
  106. package/dist/setup/cli.js +58 -58
  107. package/dist/shared/trace-async-agent-runs.js +4 -4
  108. package/dist/shared/trace-event-projection.js +59 -19
  109. package/dist/shared/trace-nodes.js +5 -0
  110. package/dist/shared/trace-page-merge.js +15 -0
  111. package/dist/shared/trace-run-notifications.js +3 -1
  112. package/dist/signals/projector.js +6 -2
  113. package/dist/tools/agent-browser-wrapper.js +80 -80
  114. package/dist/tools/browser-pool.js +50 -0
  115. package/dist/tools/browser-use-cdp.js +12 -12
  116. package/dist/tools/browser-use-leases.js +12 -8
  117. package/dist/tools/browser-use-wrapper.js +762 -762
  118. package/dist/tools/guides.js +596 -538
  119. package/dist/tools/index.js +123 -99
  120. package/dist/tools/registry.js +21 -3
  121. package/dist/tools/runtime/node-worker-source.js +205 -205
  122. package/dist/tools/runtime/python-worker-source.js +177 -177
  123. package/dist/vscode/cli.js +9 -9
  124. package/dist/web-annotations/cdp.js +900 -900
  125. package/dist/web-annotations/store.js +96 -96
  126. package/docs/README.md +23 -23
  127. package/docs/ops/install-developer-host.md +112 -112
  128. package/docs/ops/install-user-host.md +96 -96
  129. package/docs/ops/upgrade-user-to-developer-host.md +69 -69
  130. package/docs/ops/vscode-extension-release.md +160 -160
  131. package/package.json +99 -95
  132. package/skills/builtin/graphify/SKILL.md +52 -52
  133. package/skills/builtin/loop/SKILL.md +78 -0
  134. package/skills/builtin/pi-agent-harness/SKILL.md +319 -319
  135. package/skills/builtin/pi-agent-harness/agents/openai.yaml +4 -4
  136. package/skills/builtin/pibo-docker-system/SKILL.md +170 -170
  137. package/skills/builtin/pibo-spec-writing/SKILL.md +330 -330
  138. package/skills/builtin/prd/SKILL.md +143 -143
  139. package/skills/builtin/ralph-loop/SKILL.md +361 -359
  140. package/skills/builtin/ralph-prd-json/SKILL.md +123 -123
  141. package/skills/builtin/skill-creator/LICENSE.txt +201 -201
  142. package/skills/builtin/skill-creator/SKILL.md +513 -513
  143. package/skills/builtin/skill-creator/agents/analyzer.md +274 -274
  144. package/skills/builtin/skill-creator/agents/comparator.md +202 -202
  145. package/skills/builtin/skill-creator/agents/grader.md +223 -223
  146. package/skills/builtin/skill-creator/assets/eval_review.html +146 -146
  147. package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -471
  148. package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -1325
  149. package/skills/builtin/skill-creator/references/schemas.md +430 -430
  150. package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -401
  151. package/skills/builtin/skill-creator/scripts/generate_report.py +326 -326
  152. package/skills/builtin/skill-creator/scripts/improve_description.py +247 -247
  153. package/skills/builtin/skill-creator/scripts/package_skill.py +136 -136
  154. package/skills/builtin/skill-creator/scripts/quick_validate.py +102 -102
  155. package/skills/builtin/skill-creator/scripts/run_eval.py +310 -310
  156. package/skills/builtin/skill-creator/scripts/run_loop.py +328 -328
  157. package/skills/builtin/skill-creator/scripts/utils.py +47 -47
  158. package/skills/builtin/web-annotations/SKILL.md +93 -93
  159. package/src/mcp/LICENSE.mcp-cli +21 -21
  160. package/dist/apps/chat-ui/assets/index-DwHJfmiF.js +0 -173
  161. package/dist/apps/chat-vscode-web/assets/index-BAMxIaI_.js +0 -41
  162. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  163. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.9.13.vsix +0 -0
@@ -18,35 +18,36 @@ export class CustomAgentStore {
18
18
  this.db.exec("PRAGMA foreign_keys = ON");
19
19
  if (resolvedPath !== ":memory:")
20
20
  this.db.exec("PRAGMA journal_mode = WAL");
21
- this.db.exec(`
22
- CREATE TABLE IF NOT EXISTS chat_agents (
23
- id TEXT PRIMARY KEY,
24
- profile_name TEXT NOT NULL UNIQUE,
25
- display_name TEXT NOT NULL,
26
- description TEXT,
27
- native_tools_json TEXT NOT NULL,
28
- skills_json TEXT NOT NULL,
29
- context_files_json TEXT NOT NULL,
30
- subagents_json TEXT NOT NULL,
31
- mcp_servers_json TEXT NOT NULL DEFAULT '[]',
32
- pi_packages_json TEXT NOT NULL DEFAULT '[]',
33
- main_model_json TEXT,
34
- subagent_model_json TEXT,
35
- thinking_level TEXT,
36
- main_thinking_level TEXT,
37
- subagent_thinking_level TEXT,
38
- fast INTEGER,
39
- main_fast INTEGER,
40
- subagent_fast INTEGER,
41
- builtin_tools TEXT NOT NULL,
42
- builtin_tool_names_json TEXT NOT NULL DEFAULT '["read","bash","edit","write"]',
43
- auto_context_files INTEGER NOT NULL DEFAULT 1,
44
- run_control INTEGER NOT NULL,
45
- created_at TEXT NOT NULL,
46
- updated_at TEXT NOT NULL,
47
- archived_at TEXT
48
- );
49
-
21
+ this.db.exec(`
22
+ CREATE TABLE IF NOT EXISTS chat_agents (
23
+ id TEXT PRIMARY KEY,
24
+ profile_name TEXT NOT NULL UNIQUE,
25
+ display_name TEXT NOT NULL,
26
+ description TEXT,
27
+ native_tools_json TEXT NOT NULL,
28
+ skills_json TEXT NOT NULL,
29
+ context_files_json TEXT NOT NULL,
30
+ subagents_json TEXT NOT NULL,
31
+ mcp_servers_json TEXT NOT NULL DEFAULT '[]',
32
+ pi_packages_json TEXT NOT NULL DEFAULT '[]',
33
+ main_model_json TEXT,
34
+ subagent_model_json TEXT,
35
+ thinking_level TEXT,
36
+ main_thinking_level TEXT,
37
+ subagent_thinking_level TEXT,
38
+ fast INTEGER,
39
+ main_fast INTEGER,
40
+ subagent_fast INTEGER,
41
+ builtin_tools TEXT NOT NULL,
42
+ builtin_tool_names_json TEXT NOT NULL DEFAULT '["read","bash","edit","write"]',
43
+ auto_context_files INTEGER NOT NULL DEFAULT 1,
44
+ run_control INTEGER NOT NULL,
45
+ goal_control INTEGER NOT NULL DEFAULT 1,
46
+ created_at TEXT NOT NULL,
47
+ updated_at TEXT NOT NULL,
48
+ archived_at TEXT
49
+ );
50
+
50
51
  `);
51
52
  this.migrateProfileAliasTable();
52
53
  this.migrateArchivedAtColumn();
@@ -57,6 +58,7 @@ export class CustomAgentStore {
57
58
  this.migrateThinkingLevelColumn();
58
59
  this.migrateThinkingOptionColumns();
59
60
  this.migrateBuiltinToolNamesColumn();
61
+ this.migrateGoalControlColumn();
60
62
  this.migrateAgentHistory();
61
63
  this.migrateLegacyProfileNames();
62
64
  this.migrateDuplicateProfileNames();
@@ -104,6 +106,7 @@ export class CustomAgentStore {
104
106
  builtinToolNames: sanitizeBuiltinToolNames(input.builtinToolNames),
105
107
  autoContextFiles: input.autoContextFiles ?? true,
106
108
  runControl: input.runControl ?? false,
109
+ goalControl: input.goalControl ?? true,
107
110
  createdAt: now,
108
111
  updatedAt: now,
109
112
  };
@@ -143,36 +146,38 @@ export class CustomAgentStore {
143
146
  builtinToolNames: input.builtinToolNames ? sanitizeBuiltinToolNames(input.builtinToolNames) : existing.builtinToolNames,
144
147
  autoContextFiles: input.autoContextFiles ?? existing.autoContextFiles,
145
148
  runControl: input.runControl ?? existing.runControl,
149
+ goalControl: input.goalControl ?? existing.goalControl,
146
150
  updatedAt: new Date().toISOString(),
147
151
  };
148
152
  this.db
149
- .prepare(`
150
- UPDATE chat_agents SET
151
- profile_name = ?,
152
- display_name = ?,
153
- description = ?,
154
- native_tools_json = ?,
155
- skills_json = ?,
156
- context_files_json = ?,
157
- subagents_json = ?,
158
- mcp_servers_json = ?,
159
- pi_packages_json = ?,
160
- main_model_json = ?,
161
- subagent_model_json = ?,
162
- thinking_level = ?,
163
- main_thinking_level = ?,
164
- subagent_thinking_level = ?,
165
- fast = ?,
166
- main_fast = ?,
167
- subagent_fast = ?,
168
- builtin_tools = ?,
169
- builtin_tool_names_json = ?,
170
- auto_context_files = ?,
171
- run_control = ?,
172
- updated_at = ?
173
- WHERE id = ?
153
+ .prepare(`
154
+ UPDATE chat_agents SET
155
+ profile_name = ?,
156
+ display_name = ?,
157
+ description = ?,
158
+ native_tools_json = ?,
159
+ skills_json = ?,
160
+ context_files_json = ?,
161
+ subagents_json = ?,
162
+ mcp_servers_json = ?,
163
+ pi_packages_json = ?,
164
+ main_model_json = ?,
165
+ subagent_model_json = ?,
166
+ thinking_level = ?,
167
+ main_thinking_level = ?,
168
+ subagent_thinking_level = ?,
169
+ fast = ?,
170
+ main_fast = ?,
171
+ subagent_fast = ?,
172
+ builtin_tools = ?,
173
+ builtin_tool_names_json = ?,
174
+ auto_context_files = ?,
175
+ run_control = ?,
176
+ goal_control = ?,
177
+ updated_at = ?
178
+ WHERE id = ?
174
179
  `)
175
- .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.updatedAt, id);
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);
176
181
  return this.get(id);
177
182
  }
178
183
  setArchived(id, archived) {
@@ -196,36 +201,37 @@ export class CustomAgentStore {
196
201
  }
197
202
  insert(agent) {
198
203
  this.db
199
- .prepare(`
200
- INSERT INTO chat_agents (
201
- id,
202
- profile_name,
203
- display_name,
204
- description,
205
- native_tools_json,
206
- skills_json,
207
- context_files_json,
208
- subagents_json,
209
- mcp_servers_json,
210
- pi_packages_json,
211
- main_model_json,
212
- subagent_model_json,
213
- thinking_level,
214
- main_thinking_level,
215
- subagent_thinking_level,
216
- fast,
217
- main_fast,
218
- subagent_fast,
219
- builtin_tools,
220
- builtin_tool_names_json,
221
- auto_context_files,
222
- run_control,
223
- created_at,
224
- updated_at,
225
- archived_at
226
- ) VALUES (${Array.from({ length: 25 }, () => "?").join(", ")})
204
+ .prepare(`
205
+ INSERT INTO chat_agents (
206
+ id,
207
+ profile_name,
208
+ display_name,
209
+ description,
210
+ native_tools_json,
211
+ skills_json,
212
+ context_files_json,
213
+ subagents_json,
214
+ mcp_servers_json,
215
+ pi_packages_json,
216
+ main_model_json,
217
+ subagent_model_json,
218
+ thinking_level,
219
+ main_thinking_level,
220
+ subagent_thinking_level,
221
+ fast,
222
+ main_fast,
223
+ subagent_fast,
224
+ builtin_tools,
225
+ builtin_tool_names_json,
226
+ auto_context_files,
227
+ run_control,
228
+ goal_control,
229
+ created_at,
230
+ updated_at,
231
+ archived_at
232
+ ) VALUES (${Array.from({ length: 26 }, () => "?").join(", ")})
227
233
  `)
228
- .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.createdAt, agent.updatedAt, agent.archivedAt ?? null);
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);
229
235
  }
230
236
  requireProfileNameAvailable(profileName, currentId) {
231
237
  const row = this.db.prepare("SELECT id FROM chat_agents WHERE profile_name = ?").get(profileName);
@@ -276,42 +282,42 @@ export class CustomAgentStore {
276
282
  }
277
283
  }
278
284
  migrateProfileAliasTable() {
279
- this.db.exec(`
280
- CREATE TABLE IF NOT EXISTS chat_agent_profile_aliases (
281
- id TEXT PRIMARY KEY,
282
- agent_id TEXT NOT NULL,
283
- old_profile_name TEXT NOT NULL UNIQUE,
284
- new_profile_name TEXT NOT NULL,
285
- created_at TEXT NOT NULL,
286
- FOREIGN KEY(agent_id) REFERENCES chat_agents(id) ON DELETE CASCADE
287
- );
288
-
289
- CREATE TRIGGER IF NOT EXISTS chat_agents_profile_alias_insert
290
- AFTER UPDATE OF profile_name ON chat_agents
291
- WHEN OLD.profile_name IS NOT NEW.profile_name
292
- BEGIN
293
- INSERT INTO chat_agent_profile_aliases (
294
- id,
295
- agent_id,
296
- old_profile_name,
297
- new_profile_name,
298
- created_at
299
- ) VALUES (
300
- 'alias_' || lower(hex(randomblob(16))),
301
- NEW.id,
302
- OLD.profile_name,
303
- NEW.profile_name,
304
- strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
305
- )
306
- ON CONFLICT(old_profile_name) DO UPDATE SET
307
- agent_id = excluded.agent_id,
308
- new_profile_name = excluded.new_profile_name,
309
- created_at = excluded.created_at
310
- WHERE chat_agent_profile_aliases.agent_id = excluded.agent_id;
311
-
312
- DELETE FROM chat_agent_profile_aliases
313
- WHERE agent_id = NEW.id AND old_profile_name = NEW.profile_name;
314
- END;
285
+ this.db.exec(`
286
+ CREATE TABLE IF NOT EXISTS chat_agent_profile_aliases (
287
+ id TEXT PRIMARY KEY,
288
+ agent_id TEXT NOT NULL,
289
+ old_profile_name TEXT NOT NULL UNIQUE,
290
+ new_profile_name TEXT NOT NULL,
291
+ created_at TEXT NOT NULL,
292
+ FOREIGN KEY(agent_id) REFERENCES chat_agents(id) ON DELETE CASCADE
293
+ );
294
+
295
+ CREATE TRIGGER IF NOT EXISTS chat_agents_profile_alias_insert
296
+ AFTER UPDATE OF profile_name ON chat_agents
297
+ WHEN OLD.profile_name IS NOT NEW.profile_name
298
+ BEGIN
299
+ INSERT INTO chat_agent_profile_aliases (
300
+ id,
301
+ agent_id,
302
+ old_profile_name,
303
+ new_profile_name,
304
+ created_at
305
+ ) VALUES (
306
+ 'alias_' || lower(hex(randomblob(16))),
307
+ NEW.id,
308
+ OLD.profile_name,
309
+ NEW.profile_name,
310
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
311
+ )
312
+ ON CONFLICT(old_profile_name) DO UPDATE SET
313
+ agent_id = excluded.agent_id,
314
+ new_profile_name = excluded.new_profile_name,
315
+ created_at = excluded.created_at
316
+ WHERE chat_agent_profile_aliases.agent_id = excluded.agent_id;
317
+
318
+ DELETE FROM chat_agent_profile_aliases
319
+ WHERE agent_id = NEW.id AND old_profile_name = NEW.profile_name;
320
+ END;
315
321
  `);
316
322
  }
317
323
  tableColumns() {
@@ -380,137 +386,143 @@ export class CustomAgentStore {
380
386
  this.db.prepare("ALTER TABLE chat_agents ADD COLUMN builtin_tool_names_json TEXT NOT NULL DEFAULT '[\"read\",\"bash\",\"edit\",\"write\"]'").run();
381
387
  }
382
388
  }
389
+ migrateGoalControlColumn() {
390
+ const columns = new Set(this.db.prepare("PRAGMA table_info(chat_agents)").all().map((column) => column.name));
391
+ if (!columns.has("goal_control")) {
392
+ this.db.prepare("ALTER TABLE chat_agents ADD COLUMN goal_control INTEGER NOT NULL DEFAULT 1").run();
393
+ }
394
+ }
383
395
  migrateAgentHistory() {
384
- this.db.exec(`
385
- CREATE TABLE IF NOT EXISTS chat_agent_events (
386
- id TEXT PRIMARY KEY,
387
- agent_id TEXT NOT NULL,
388
- event_type TEXT NOT NULL CHECK (event_type IN ('updated', 'deleted')),
389
- field_name TEXT,
390
- old_value TEXT,
391
- new_value TEXT,
392
- old_profile_name TEXT,
393
- new_profile_name TEXT,
394
- old_display_name TEXT,
395
- new_display_name TEXT,
396
- recorded_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
397
- );
398
-
399
- CREATE INDEX IF NOT EXISTS chat_agent_events_agent_id_idx
400
- ON chat_agent_events(agent_id, recorded_at);
401
-
402
- CREATE INDEX IF NOT EXISTS chat_agent_events_profile_name_idx
403
- ON chat_agent_events(old_profile_name, new_profile_name, recorded_at);
404
-
405
- CREATE TRIGGER IF NOT EXISTS chat_agents_profile_name_history_update
406
- AFTER UPDATE OF profile_name ON chat_agents
407
- FOR EACH ROW
408
- WHEN OLD.profile_name IS NOT NEW.profile_name
409
- BEGIN
410
- INSERT INTO chat_agent_events (
411
- id,
412
- agent_id,
413
- event_type,
414
- field_name,
415
- old_value,
416
- new_value,
417
- old_profile_name,
418
- new_profile_name,
419
- old_display_name,
420
- new_display_name,
421
- recorded_at
422
- ) VALUES (
423
- 'agent_event_' || lower(hex(randomblob(16))),
424
- NEW.id,
425
- 'updated',
426
- 'profile_name',
427
- OLD.profile_name,
428
- NEW.profile_name,
429
- OLD.profile_name,
430
- NEW.profile_name,
431
- OLD.display_name,
432
- NEW.display_name,
433
- strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
434
- );
435
- END;
436
-
437
- CREATE TRIGGER IF NOT EXISTS chat_agents_display_name_history_update
438
- AFTER UPDATE OF display_name ON chat_agents
439
- FOR EACH ROW
440
- WHEN OLD.display_name IS NOT NEW.display_name
441
- BEGIN
442
- INSERT INTO chat_agent_events (
443
- id,
444
- agent_id,
445
- event_type,
446
- field_name,
447
- old_value,
448
- new_value,
449
- old_profile_name,
450
- new_profile_name,
451
- old_display_name,
452
- new_display_name,
453
- recorded_at
454
- ) VALUES (
455
- 'agent_event_' || lower(hex(randomblob(16))),
456
- NEW.id,
457
- 'updated',
458
- 'display_name',
459
- OLD.display_name,
460
- NEW.display_name,
461
- OLD.profile_name,
462
- NEW.profile_name,
463
- OLD.display_name,
464
- NEW.display_name,
465
- strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
466
- );
467
- END;
468
-
469
- CREATE TRIGGER IF NOT EXISTS chat_agents_history_delete
470
- AFTER DELETE ON chat_agents
471
- FOR EACH ROW
472
- BEGIN
473
- INSERT INTO chat_agent_events (
474
- id,
475
- agent_id,
476
- event_type,
477
- field_name,
478
- old_value,
479
- new_value,
480
- old_profile_name,
481
- new_profile_name,
482
- old_display_name,
483
- new_display_name,
484
- recorded_at
485
- ) VALUES (
486
- 'agent_event_' || lower(hex(randomblob(16))),
487
- OLD.id,
488
- 'deleted',
489
- NULL,
490
- OLD.profile_name,
491
- NULL,
492
- OLD.profile_name,
493
- NULL,
494
- OLD.display_name,
495
- NULL,
496
- strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
497
- );
498
- END;
499
-
500
- CREATE VIEW IF NOT EXISTS chat_agent_history AS
501
- SELECT
502
- id,
503
- agent_id,
504
- event_type,
505
- field_name,
506
- old_value,
507
- new_value,
508
- old_profile_name,
509
- new_profile_name,
510
- old_display_name,
511
- new_display_name,
512
- recorded_at
513
- FROM chat_agent_events;
396
+ this.db.exec(`
397
+ CREATE TABLE IF NOT EXISTS chat_agent_events (
398
+ id TEXT PRIMARY KEY,
399
+ agent_id TEXT NOT NULL,
400
+ event_type TEXT NOT NULL CHECK (event_type IN ('updated', 'deleted')),
401
+ field_name TEXT,
402
+ old_value TEXT,
403
+ new_value TEXT,
404
+ old_profile_name TEXT,
405
+ new_profile_name TEXT,
406
+ old_display_name TEXT,
407
+ new_display_name TEXT,
408
+ recorded_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
409
+ );
410
+
411
+ CREATE INDEX IF NOT EXISTS chat_agent_events_agent_id_idx
412
+ ON chat_agent_events(agent_id, recorded_at);
413
+
414
+ CREATE INDEX IF NOT EXISTS chat_agent_events_profile_name_idx
415
+ ON chat_agent_events(old_profile_name, new_profile_name, recorded_at);
416
+
417
+ CREATE TRIGGER IF NOT EXISTS chat_agents_profile_name_history_update
418
+ AFTER UPDATE OF profile_name ON chat_agents
419
+ FOR EACH ROW
420
+ WHEN OLD.profile_name IS NOT NEW.profile_name
421
+ BEGIN
422
+ INSERT INTO chat_agent_events (
423
+ id,
424
+ agent_id,
425
+ event_type,
426
+ field_name,
427
+ old_value,
428
+ new_value,
429
+ old_profile_name,
430
+ new_profile_name,
431
+ old_display_name,
432
+ new_display_name,
433
+ recorded_at
434
+ ) VALUES (
435
+ 'agent_event_' || lower(hex(randomblob(16))),
436
+ NEW.id,
437
+ 'updated',
438
+ 'profile_name',
439
+ OLD.profile_name,
440
+ NEW.profile_name,
441
+ OLD.profile_name,
442
+ NEW.profile_name,
443
+ OLD.display_name,
444
+ NEW.display_name,
445
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
446
+ );
447
+ END;
448
+
449
+ CREATE TRIGGER IF NOT EXISTS chat_agents_display_name_history_update
450
+ AFTER UPDATE OF display_name ON chat_agents
451
+ FOR EACH ROW
452
+ WHEN OLD.display_name IS NOT NEW.display_name
453
+ BEGIN
454
+ INSERT INTO chat_agent_events (
455
+ id,
456
+ agent_id,
457
+ event_type,
458
+ field_name,
459
+ old_value,
460
+ new_value,
461
+ old_profile_name,
462
+ new_profile_name,
463
+ old_display_name,
464
+ new_display_name,
465
+ recorded_at
466
+ ) VALUES (
467
+ 'agent_event_' || lower(hex(randomblob(16))),
468
+ NEW.id,
469
+ 'updated',
470
+ 'display_name',
471
+ OLD.display_name,
472
+ NEW.display_name,
473
+ OLD.profile_name,
474
+ NEW.profile_name,
475
+ OLD.display_name,
476
+ NEW.display_name,
477
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
478
+ );
479
+ END;
480
+
481
+ CREATE TRIGGER IF NOT EXISTS chat_agents_history_delete
482
+ AFTER DELETE ON chat_agents
483
+ FOR EACH ROW
484
+ BEGIN
485
+ INSERT INTO chat_agent_events (
486
+ id,
487
+ agent_id,
488
+ event_type,
489
+ field_name,
490
+ old_value,
491
+ new_value,
492
+ old_profile_name,
493
+ new_profile_name,
494
+ old_display_name,
495
+ new_display_name,
496
+ recorded_at
497
+ ) VALUES (
498
+ 'agent_event_' || lower(hex(randomblob(16))),
499
+ OLD.id,
500
+ 'deleted',
501
+ NULL,
502
+ OLD.profile_name,
503
+ NULL,
504
+ OLD.profile_name,
505
+ NULL,
506
+ OLD.display_name,
507
+ NULL,
508
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
509
+ );
510
+ END;
511
+
512
+ CREATE VIEW IF NOT EXISTS chat_agent_history AS
513
+ SELECT
514
+ id,
515
+ agent_id,
516
+ event_type,
517
+ field_name,
518
+ old_value,
519
+ new_value,
520
+ old_profile_name,
521
+ new_profile_name,
522
+ old_display_name,
523
+ new_display_name,
524
+ recorded_at
525
+ FROM chat_agent_events;
514
526
  `);
515
527
  }
516
528
  }
@@ -542,6 +554,7 @@ function agentFromRow(row, profileAliases) {
542
554
  builtinToolNames: sanitizeBuiltinToolNames(parseStringArray(row.builtin_tool_names_json)),
543
555
  autoContextFiles: row.auto_context_files !== 0,
544
556
  runControl: row.run_control === 1,
557
+ goalControl: row.goal_control !== 0,
545
558
  createdAt: row.created_at,
546
559
  updatedAt: row.updated_at,
547
560
  archivedAt: row.archived_at ?? undefined,
@@ -193,6 +193,13 @@ export function normalizeRunControl(value) {
193
193
  throw new PiboWebHttpError("runControl must be a boolean", 400);
194
194
  return value;
195
195
  }
196
+ export function normalizeGoalControl(value) {
197
+ if (value === undefined)
198
+ return true;
199
+ if (typeof value !== "boolean")
200
+ throw new PiboWebHttpError("goalControl must be a boolean", 400);
201
+ return value;
202
+ }
196
203
  export function normalizeOptionalBoolean(value, fieldName) {
197
204
  if (value === undefined || value === null)
198
205
  return undefined;
@@ -361,6 +368,13 @@ export function normalizeMessageText(value) {
361
368
  }
362
369
  return value;
363
370
  }
371
+ export function normalizeMessageDelivery(value) {
372
+ if (value === undefined)
373
+ return "queue";
374
+ if (value === "queue" || value === "steer")
375
+ return value;
376
+ throw new PiboWebHttpError('Message delivery must be "queue" or "steer"', 400);
377
+ }
364
378
  export function defaultStreamingFixtureDeltas(mix) {
365
379
  if (mix === "markdown")
366
380
  return [" **a**", " **b**", " **c**", " **d**", " **e**", " **f**", " **g**", " **h**", " **i**", " **j**", " **k**", " **l**"];
@@ -611,6 +625,7 @@ export function createAgentInput(body) {
611
625
  builtinToolNames: normalizeBuiltinToolNames(body.builtinToolNames),
612
626
  autoContextFiles: normalizeAutoContextFiles(body.autoContextFiles),
613
627
  runControl: normalizeRunControl(body.runControl),
628
+ goalControl: normalizeGoalControl(body.goalControl),
614
629
  };
615
630
  }
616
631
  export function createAgentUpdate(body) {
@@ -655,6 +670,8 @@ export function createAgentUpdate(body) {
655
670
  update.autoContextFiles = normalizeAutoContextFiles(body.autoContextFiles);
656
671
  if (body.runControl !== undefined)
657
672
  update.runControl = normalizeRunControl(body.runControl);
673
+ if (body.goalControl !== undefined)
674
+ update.goalControl = normalizeGoalControl(body.goalControl);
658
675
  if (Object.keys(update).length === 0 && body.archived === undefined) {
659
676
  throw new PiboWebHttpError("No agent update fields provided", 400);
660
677
  }
@@ -23,6 +23,8 @@ function outputPayloadFromV2Row(row, attributes) {
23
23
  return { ...base, type: "assistant_message", text: row.preview_text ?? "" };
24
24
  if (row.type === "message_queued")
25
25
  return { ...base, type: "message_queued", text: stringAttribute(attributes, "inlineText") ?? row.preview_text ?? "", source: stringAttribute(attributes, "source") ?? "user", queuedMessages: numberAttribute(attributes, "queuedMessages") ?? 1 };
26
+ if (row.type === "message_steered")
27
+ return { ...base, type: "message_steered", text: stringAttribute(attributes, "inlineText") ?? row.preview_text ?? "", source: stringAttribute(attributes, "source") ?? "user", activeEventId: stringAttribute(attributes, "activeEventId") };
26
28
  if (row.type === "message_started")
27
29
  return { ...base, type: "message_started", text: row.preview_text ?? "" };
28
30
  if (row.type === "message_finished")