@pasko70/pibo 1.9.13 → 1.10.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 (139) 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 +10 -0
  10. package/dist/apps/chat/data/project-service.js +168 -168
  11. package/dist/apps/chat/data/read-state-service.js +18 -18
  12. package/dist/apps/chat/data/session-query-service.js +25 -25
  13. package/dist/apps/chat/data/timeline-query-service.js +19 -19
  14. package/dist/apps/chat/loop-api.js +176 -0
  15. package/dist/apps/chat/static-assets.js +854 -854
  16. package/dist/apps/chat/web-app.js +6 -6
  17. package/dist/apps/chat/workflow-manual-trigger-runtime.js +149 -46
  18. package/dist/apps/chat/workflow-persistence.js +255 -255
  19. package/dist/apps/chat-ui/assets/{dist-yCYNNb5d.js → dist-BwKObYnX.js} +1 -1
  20. package/dist/apps/chat-ui/assets/{dist-BCB6zezO.js → dist-CKtT8YGm.js} +1 -1
  21. package/dist/apps/chat-ui/assets/{dist-CnVsqwSG.js → dist-CS7wdk0Z.js} +1 -1
  22. package/dist/apps/chat-ui/assets/{dist-HqTN67dc.js → dist-D-cxLQO1.js} +1 -1
  23. package/dist/apps/chat-ui/assets/{dist-BNMu92bb.js → dist-DUlaXAk7.js} +1 -1
  24. package/dist/apps/chat-ui/assets/{dist-CzE6k3F3.js → dist-DlATLa-U.js} +1 -1
  25. package/dist/apps/chat-ui/assets/{dist-Dq4GxJi3.js → dist-GdEM8UW1.js} +1 -1
  26. package/dist/apps/chat-ui/assets/{dist-BZ2eTC4f.js → dist-LHRs1Nhr.js} +1 -1
  27. package/dist/apps/chat-ui/assets/{dist-D811wJeV.js → dist-Y-AA2omI.js} +1 -1
  28. package/dist/apps/chat-ui/assets/{dist-WyXdYl-w.js → dist-nOLTkZrJ.js} +1 -1
  29. package/dist/apps/chat-ui/assets/{dist-BHa-kcGl.js → dist-wE9nop9V.js} +1 -1
  30. package/dist/apps/chat-ui/assets/{index-DwHJfmiF.js → index-8W_yMHQI.js} +6 -6
  31. package/dist/apps/chat-ui/index.html +17 -17
  32. package/dist/apps/chat-ui/manifest.webmanifest +25 -25
  33. package/dist/apps/chat-ui/sw.js +47 -47
  34. package/dist/apps/chat-vscode-web/index.html +12 -12
  35. package/dist/apps/cli-ui/cliSessionsCommand.js +23 -23
  36. package/dist/apps/context-files-ui/index.html +11 -11
  37. package/dist/cli.js +61 -44
  38. package/dist/compute/cli.js +54 -54
  39. package/dist/core/routed-session.js +30 -1
  40. package/dist/core/runtime.js +6 -1
  41. package/dist/core/session-router.js +4 -2
  42. package/dist/cron/cli.js +15 -15
  43. package/dist/cron/store.js +49 -49
  44. package/dist/data/cli.js +23 -23
  45. package/dist/data/event-log.js +23 -23
  46. package/dist/data/message-store.js +27 -27
  47. package/dist/data/navigation-store.js +9 -9
  48. package/dist/data/observation-store.js +4 -4
  49. package/dist/data/payload-store.js +17 -17
  50. package/dist/data/schema.js +433 -433
  51. package/dist/data/session-store.js +4 -4
  52. package/dist/data/telemetry-queries.js +54 -54
  53. package/dist/data/telemetry.js +197 -197
  54. package/dist/debug/events.js +12 -12
  55. package/dist/debug/failures.js +6 -6
  56. package/dist/debug/index.js +227 -227
  57. package/dist/debug/messages.js +6 -6
  58. package/dist/debug/pty.js +124 -124
  59. package/dist/debug/session.js +29 -29
  60. package/dist/debug/tools.js +5 -5
  61. package/dist/debug/web-snapshot-browser-scripts.js +294 -294
  62. package/dist/debug/web-streaming-browser-library.js +925 -925
  63. package/dist/debug/web-streaming-browser-scripts.js +232 -232
  64. package/dist/debug/web-streaming-provider-telemetry.js +4 -4
  65. package/dist/debug/web.js +93 -93
  66. package/dist/gateway/cli.js +19 -19
  67. package/dist/gateway/server.js +4 -2
  68. package/dist/gateway/web.js +2 -2
  69. package/dist/loops/channel.js +8 -0
  70. package/dist/loops/cli.js +208 -0
  71. package/dist/loops/plugin.js +16 -0
  72. package/dist/loops/prompts.js +83 -0
  73. package/dist/loops/service.js +357 -0
  74. package/dist/loops/stopping.js +170 -0
  75. package/dist/loops/store.js +531 -0
  76. package/dist/loops/templates.js +232 -0
  77. package/dist/loops/tools.js +167 -0
  78. package/dist/loops/types.js +1 -0
  79. package/dist/mcp/config-command.js +53 -53
  80. package/dist/mcp/index.js +21 -21
  81. package/dist/mcp/registry.js +11 -11
  82. package/dist/pi-packages/cli.js +11 -11
  83. package/dist/plugins/builtin.js +8 -0
  84. package/dist/plugins/context-files-store.js +110 -110
  85. package/dist/plugins/context-files.js +4 -4
  86. package/dist/plugins/registry.js +23 -12
  87. package/dist/ralph/cli.js +18 -18
  88. package/dist/ralph/templates.js +140 -140
  89. package/dist/reliability/store.js +226 -226
  90. package/dist/sessions/pibo-data-store.js +16 -16
  91. package/dist/sessions/sqlite-store.js +53 -53
  92. package/dist/setup/cli.js +58 -58
  93. package/dist/tools/agent-browser-wrapper.js +80 -80
  94. package/dist/tools/browser-use-cdp.js +12 -12
  95. package/dist/tools/browser-use-wrapper.js +762 -762
  96. package/dist/tools/guides.js +589 -538
  97. package/dist/tools/index.js +122 -99
  98. package/dist/tools/registry.js +21 -3
  99. package/dist/tools/runtime/node-worker-source.js +205 -205
  100. package/dist/tools/runtime/python-worker-source.js +177 -177
  101. package/dist/vscode/cli.js +9 -9
  102. package/dist/web-annotations/cdp.js +900 -900
  103. package/dist/web-annotations/store.js +96 -96
  104. package/docs/README.md +23 -23
  105. package/docs/ops/install-developer-host.md +112 -112
  106. package/docs/ops/install-user-host.md +96 -96
  107. package/docs/ops/upgrade-user-to-developer-host.md +69 -69
  108. package/docs/ops/vscode-extension-release.md +160 -160
  109. package/package.json +98 -95
  110. package/skills/builtin/graphify/SKILL.md +52 -52
  111. package/skills/builtin/loop/SKILL.md +69 -0
  112. package/skills/builtin/pi-agent-harness/SKILL.md +319 -319
  113. package/skills/builtin/pi-agent-harness/agents/openai.yaml +4 -4
  114. package/skills/builtin/pibo-docker-system/SKILL.md +170 -170
  115. package/skills/builtin/pibo-spec-writing/SKILL.md +330 -330
  116. package/skills/builtin/prd/SKILL.md +143 -143
  117. package/skills/builtin/ralph-loop/SKILL.md +361 -359
  118. package/skills/builtin/ralph-prd-json/SKILL.md +123 -123
  119. package/skills/builtin/skill-creator/LICENSE.txt +201 -201
  120. package/skills/builtin/skill-creator/SKILL.md +513 -513
  121. package/skills/builtin/skill-creator/agents/analyzer.md +274 -274
  122. package/skills/builtin/skill-creator/agents/comparator.md +202 -202
  123. package/skills/builtin/skill-creator/agents/grader.md +223 -223
  124. package/skills/builtin/skill-creator/assets/eval_review.html +146 -146
  125. package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -471
  126. package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -1325
  127. package/skills/builtin/skill-creator/references/schemas.md +430 -430
  128. package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -401
  129. package/skills/builtin/skill-creator/scripts/generate_report.py +326 -326
  130. package/skills/builtin/skill-creator/scripts/improve_description.py +247 -247
  131. package/skills/builtin/skill-creator/scripts/package_skill.py +136 -136
  132. package/skills/builtin/skill-creator/scripts/quick_validate.py +102 -102
  133. package/skills/builtin/skill-creator/scripts/run_eval.py +310 -310
  134. package/skills/builtin/skill-creator/scripts/run_loop.py +328 -328
  135. package/skills/builtin/skill-creator/scripts/utils.py +47 -47
  136. package/skills/builtin/web-annotations/SKILL.md +93 -93
  137. package/src/mcp/LICENSE.mcp-cli +21 -21
  138. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  139. 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;
@@ -611,6 +618,7 @@ export function createAgentInput(body) {
611
618
  builtinToolNames: normalizeBuiltinToolNames(body.builtinToolNames),
612
619
  autoContextFiles: normalizeAutoContextFiles(body.autoContextFiles),
613
620
  runControl: normalizeRunControl(body.runControl),
621
+ goalControl: normalizeGoalControl(body.goalControl),
614
622
  };
615
623
  }
616
624
  export function createAgentUpdate(body) {
@@ -655,6 +663,8 @@ export function createAgentUpdate(body) {
655
663
  update.autoContextFiles = normalizeAutoContextFiles(body.autoContextFiles);
656
664
  if (body.runControl !== undefined)
657
665
  update.runControl = normalizeRunControl(body.runControl);
666
+ if (body.goalControl !== undefined)
667
+ update.goalControl = normalizeGoalControl(body.goalControl);
658
668
  if (Object.keys(update).length === 0 && body.archived === undefined) {
659
669
  throw new PiboWebHttpError("No agent update fields provided", 400);
660
670
  }