@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
package/dist/debug/pty.js CHANGED
@@ -8,92 +8,92 @@ const DEFAULT_IDLE_TIMEOUT_MS = 10_000;
8
8
  const DEFAULT_INPUT_DELAY_MS = 40;
9
9
  const DEFAULT_REAL_PROVIDER_MAX_ITERATIONS = 10;
10
10
  const ARTIFACT_SCHEMA_VERSION = 1;
11
- const PYTHON_PTY_DRIVER = String.raw `
12
- import os, sys, pty, select, subprocess, signal, termios, fcntl, struct, time
13
- rows = int(os.environ.get("PIBO_PTY_ROWS", "24"))
14
- cols = int(os.environ.get("PIBO_PTY_COLS", "100"))
15
- cmd = sys.argv[1:]
16
- if cmd and cmd[0] == "--":
17
- cmd = cmd[1:]
18
- if not cmd:
19
- print("missing command", file=sys.stderr)
20
- sys.exit(64)
21
- master, slave = pty.openpty()
22
- try:
23
- fcntl.ioctl(slave, termios.TIOCSWINSZ, struct.pack("HHHH", rows, cols, 0, 0))
24
- except Exception:
25
- pass
26
- proc = subprocess.Popen(cmd, stdin=slave, stdout=slave, stderr=slave, close_fds=True, start_new_session=True)
27
- os.close(slave)
28
- os.set_blocking(master, False)
29
- os.set_blocking(sys.stdin.fileno(), False)
30
- stdin_open = True
31
-
32
- def terminate(signum, frame):
33
- try:
34
- os.killpg(proc.pid, signum)
35
- except Exception:
36
- try:
37
- proc.terminate()
38
- except Exception:
39
- pass
40
- signal.signal(signal.SIGTERM, terminate)
41
- signal.signal(signal.SIGINT, terminate)
42
-
43
- def drain_once():
44
- try:
45
- data = os.read(master, 4096)
46
- except OSError:
47
- return False
48
- if not data:
49
- return False
50
- os.write(sys.stdout.fileno(), data)
51
- sys.stdout.flush()
52
- return True
53
-
54
- exit_code = None
55
- while True:
56
- fds = [master]
57
- if stdin_open:
58
- fds.append(sys.stdin.fileno())
59
- try:
60
- readable, _, _ = select.select(fds, [], [], 0.05)
61
- except OSError:
62
- readable = []
63
- if master in readable:
64
- if not drain_once():
65
- break
66
- if stdin_open and sys.stdin.fileno() in readable:
67
- try:
68
- data = os.read(sys.stdin.fileno(), 4096)
69
- except BlockingIOError:
70
- data = b""
71
- except OSError:
72
- stdin_open = False
73
- data = b""
74
- if data:
75
- try:
76
- os.write(master, data)
77
- except OSError:
78
- pass
79
- else:
80
- stdin_open = False
81
- polled = proc.poll()
82
- if polled is not None:
83
- exit_code = polled
84
- deadline = time.time() + 0.2
85
- while time.time() < deadline and drain_once():
86
- pass
87
- break
88
- if exit_code is None:
89
- exit_code = proc.poll()
90
- if exit_code is None:
91
- try:
92
- proc.terminate()
93
- except Exception:
94
- pass
95
- exit_code = proc.wait(timeout=1)
96
- sys.exit(exit_code if exit_code is not None else 1)
11
+ const PYTHON_PTY_DRIVER = String.raw `
12
+ import os, sys, pty, select, subprocess, signal, termios, fcntl, struct, time
13
+ rows = int(os.environ.get("PIBO_PTY_ROWS", "24"))
14
+ cols = int(os.environ.get("PIBO_PTY_COLS", "100"))
15
+ cmd = sys.argv[1:]
16
+ if cmd and cmd[0] == "--":
17
+ cmd = cmd[1:]
18
+ if not cmd:
19
+ print("missing command", file=sys.stderr)
20
+ sys.exit(64)
21
+ master, slave = pty.openpty()
22
+ try:
23
+ fcntl.ioctl(slave, termios.TIOCSWINSZ, struct.pack("HHHH", rows, cols, 0, 0))
24
+ except Exception:
25
+ pass
26
+ proc = subprocess.Popen(cmd, stdin=slave, stdout=slave, stderr=slave, close_fds=True, start_new_session=True)
27
+ os.close(slave)
28
+ os.set_blocking(master, False)
29
+ os.set_blocking(sys.stdin.fileno(), False)
30
+ stdin_open = True
31
+
32
+ def terminate(signum, frame):
33
+ try:
34
+ os.killpg(proc.pid, signum)
35
+ except Exception:
36
+ try:
37
+ proc.terminate()
38
+ except Exception:
39
+ pass
40
+ signal.signal(signal.SIGTERM, terminate)
41
+ signal.signal(signal.SIGINT, terminate)
42
+
43
+ def drain_once():
44
+ try:
45
+ data = os.read(master, 4096)
46
+ except OSError:
47
+ return False
48
+ if not data:
49
+ return False
50
+ os.write(sys.stdout.fileno(), data)
51
+ sys.stdout.flush()
52
+ return True
53
+
54
+ exit_code = None
55
+ while True:
56
+ fds = [master]
57
+ if stdin_open:
58
+ fds.append(sys.stdin.fileno())
59
+ try:
60
+ readable, _, _ = select.select(fds, [], [], 0.05)
61
+ except OSError:
62
+ readable = []
63
+ if master in readable:
64
+ if not drain_once():
65
+ break
66
+ if stdin_open and sys.stdin.fileno() in readable:
67
+ try:
68
+ data = os.read(sys.stdin.fileno(), 4096)
69
+ except BlockingIOError:
70
+ data = b""
71
+ except OSError:
72
+ stdin_open = False
73
+ data = b""
74
+ if data:
75
+ try:
76
+ os.write(master, data)
77
+ except OSError:
78
+ pass
79
+ else:
80
+ stdin_open = False
81
+ polled = proc.poll()
82
+ if polled is not None:
83
+ exit_code = polled
84
+ deadline = time.time() + 0.2
85
+ while time.time() < deadline and drain_once():
86
+ pass
87
+ break
88
+ if exit_code is None:
89
+ exit_code = proc.poll()
90
+ if exit_code is None:
91
+ try:
92
+ proc.terminate()
93
+ except Exception:
94
+ pass
95
+ exit_code = proc.wait(timeout=1)
96
+ sys.exit(exit_code if exit_code is not None else 1)
97
97
  `;
98
98
  export async function runDebugPty(args) {
99
99
  if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
@@ -132,47 +132,47 @@ export async function runDebugPty(args) {
132
132
  throw new Error(`Unknown pibo debug pty command "${command}". Run pibo debug pty --help.`);
133
133
  }
134
134
  function printPtyDiscovery() {
135
- console.log(`pibo debug pty - run and inspect interactive CLI/TUI commands under a pseudo-terminal
136
-
137
- Commands:
138
- run Run one command under PTY
139
- scenario Run a declarative PTY scenario JSON file
140
- list-scenarios List built-in scenario names
141
-
142
- Usage:
143
- pibo debug pty run [options] -- <command...>
144
- pibo debug pty scenario [options] <file>
145
- pibo debug pty scenario --builtin cli-session-ui-mocked-e2e
146
-
147
- Common options:
148
- --rows <n> Terminal rows (default: ${DEFAULT_ROWS})
149
- --cols <n> Terminal columns (default: ${DEFAULT_COLS})
150
- --timeout-ms <n> Wall-clock timeout (default: ${DEFAULT_TIMEOUT_MS})
151
- --idle-timeout-ms <n> Idle timeout after no output (default: ${DEFAULT_IDLE_TIMEOUT_MS})
152
- --input-delay-ms <n> Delay between typed characters (default: ${DEFAULT_INPUT_DELAY_MS})
153
- --artifact-dir <path> Artifact directory
154
- --artifact Write artifacts for successful runs too
155
- --expect <text> Require cleaned output text (repeatable)
156
- --reject <text> Forbid cleaned output text (repeatable)
157
- --type <text> Type text as a scenario step
158
- --press <key> Press Enter, Escape, CtrlC, Up, or Down
159
- --wait-for <text> Wait until cleaned output contains text
160
- --sleep-ms <n> Sleep as a scenario step
161
- --docker-worker <name> Run inside a named Docker worker/container
162
- --workdir <path> Workdir for host cwd or Docker -w
163
- --real-provider Explicitly allow live provider scenarios
164
- --max-iterations <n> Real-provider iteration cap (default: ${DEFAULT_REAL_PROVIDER_MAX_ITERATIONS})
165
-
166
- Safety:
167
- Mocked/deterministic mode is default. Real provider mode requires --real-provider and bounded iterations.
135
+ console.log(`pibo debug pty - run and inspect interactive CLI/TUI commands under a pseudo-terminal
136
+
137
+ Commands:
138
+ run Run one command under PTY
139
+ scenario Run a declarative PTY scenario JSON file
140
+ list-scenarios List built-in scenario names
141
+
142
+ Usage:
143
+ pibo debug pty run [options] -- <command...>
144
+ pibo debug pty scenario [options] <file>
145
+ pibo debug pty scenario --builtin cli-session-ui-mocked-e2e
146
+
147
+ Common options:
148
+ --rows <n> Terminal rows (default: ${DEFAULT_ROWS})
149
+ --cols <n> Terminal columns (default: ${DEFAULT_COLS})
150
+ --timeout-ms <n> Wall-clock timeout (default: ${DEFAULT_TIMEOUT_MS})
151
+ --idle-timeout-ms <n> Idle timeout after no output (default: ${DEFAULT_IDLE_TIMEOUT_MS})
152
+ --input-delay-ms <n> Delay between typed characters (default: ${DEFAULT_INPUT_DELAY_MS})
153
+ --artifact-dir <path> Artifact directory
154
+ --artifact Write artifacts for successful runs too
155
+ --expect <text> Require cleaned output text (repeatable)
156
+ --reject <text> Forbid cleaned output text (repeatable)
157
+ --type <text> Type text as a scenario step
158
+ --press <key> Press Enter, Escape, CtrlC, Up, or Down
159
+ --wait-for <text> Wait until cleaned output contains text
160
+ --sleep-ms <n> Sleep as a scenario step
161
+ --docker-worker <name> Run inside a named Docker worker/container
162
+ --workdir <path> Workdir for host cwd or Docker -w
163
+ --real-provider Explicitly allow live provider scenarios
164
+ --max-iterations <n> Real-provider iteration cap (default: ${DEFAULT_REAL_PROVIDER_MAX_ITERATIONS})
165
+
166
+ Safety:
167
+ Mocked/deterministic mode is default. Real provider mode requires --real-provider and bounded iterations.
168
168
  `);
169
169
  }
170
170
  function printBuiltinScenarios() {
171
- console.log(`Built-in PTY scenarios:
172
- cli-session-ui-mocked-e2e Runs pibo tui:sessions without --demo using a deterministic debug fixture when available
173
-
174
- Next:
175
- pibo debug pty scenario --builtin cli-session-ui-mocked-e2e --artifact
171
+ console.log(`Built-in PTY scenarios:
172
+ cli-session-ui-mocked-e2e Runs pibo tui:sessions without --demo using a deterministic debug fixture when available
173
+
174
+ Next:
175
+ pibo debug pty scenario --builtin cli-session-ui-mocked-e2e --artifact
176
176
  `);
177
177
  }
178
178
  function parsePtyOptions(args) {
@@ -121,12 +121,12 @@ export function formatDebugSessionSummary(summary) {
121
121
  }
122
122
  function listChildSessions(db, piboSessionId, limit) {
123
123
  const rows = db
124
- .prepare(`
125
- SELECT id, pi_session_id, channel, kind, profile, room_id, root_session_id, parent_id, origin_id, workspace, title, status, metadata_json, created_at, updated_at, last_activity_at
126
- FROM sessions
127
- WHERE parent_id = ?
128
- ORDER BY created_at
129
- LIMIT ?
124
+ .prepare(`
125
+ SELECT id, pi_session_id, channel, kind, profile, room_id, root_session_id, parent_id, origin_id, workspace, title, status, metadata_json, created_at, updated_at, last_activity_at
126
+ FROM sessions
127
+ WHERE parent_id = ?
128
+ ORDER BY created_at
129
+ LIMIT ?
130
130
  `)
131
131
  .all(piboSessionId, limit);
132
132
  return rows.map((row) => {
@@ -150,35 +150,35 @@ function listChildSessions(db, piboSessionId, limit) {
150
150
  function readChatSession(db, piboSessionId) {
151
151
  if (!tableExists(db, "sessions"))
152
152
  return undefined;
153
- return db.prepare(`
154
- SELECT
155
- s.id AS pibo_session_id,
156
- s.room_id,
157
- s.root_session_id,
158
- s.status,
159
- s.last_activity_at,
160
- stats.message_count,
161
- stats.tool_call_count,
162
- stats.error_count,
163
- stats.last_event_stream_id,
164
- nav.child_count,
165
- nav.sort_key
166
- FROM sessions s
167
- LEFT JOIN session_stats stats ON stats.session_id = s.id
168
- LEFT JOIN session_navigation nav ON nav.session_id = s.id
169
- WHERE s.id = ?
153
+ return db.prepare(`
154
+ SELECT
155
+ s.id AS pibo_session_id,
156
+ s.room_id,
157
+ s.root_session_id,
158
+ s.status,
159
+ s.last_activity_at,
160
+ stats.message_count,
161
+ stats.tool_call_count,
162
+ stats.error_count,
163
+ stats.last_event_stream_id,
164
+ nav.child_count,
165
+ nav.sort_key
166
+ FROM sessions s
167
+ LEFT JOIN session_stats stats ON stats.session_id = s.id
168
+ LEFT JOIN session_navigation nav ON nav.session_id = s.id
169
+ WHERE s.id = ?
170
170
  `).get(piboSessionId);
171
171
  }
172
172
  function readEventSummaries(db, piboSessionId, limit) {
173
173
  if (!tableExists(db, "event_log"))
174
174
  return [];
175
175
  return db
176
- .prepare(`
177
- SELECT type, event_id, created_at, stream_id
178
- FROM event_log
179
- WHERE session_id = ?
180
- ORDER BY stream_id DESC
181
- LIMIT ?
176
+ .prepare(`
177
+ SELECT type, event_id, created_at, stream_id
178
+ FROM event_log
179
+ WHERE session_id = ?
180
+ ORDER BY stream_id DESC
181
+ LIMIT ?
182
182
  `)
183
183
  .all(piboSessionId, limit);
184
184
  }
@@ -9,11 +9,11 @@ export function inspectDebugTool(piboSessionId, store, selector, options = {}) {
9
9
  try {
10
10
  if (!tableExists(db, "event_log"))
11
11
  return emptyTool(piboSessionId, selector);
12
- const rows = db.prepare(`
13
- SELECT stream_id, session_id, session_sequence, event_id, type, created_at, preview_text, attributes_json
14
- FROM event_log
15
- WHERE session_id = ? AND type IN ('tool_call', 'tool_execution_started', 'tool_execution_updated', 'tool_execution_finished')
16
- ORDER BY stream_id ASC
12
+ const rows = db.prepare(`
13
+ SELECT stream_id, session_id, session_sequence, event_id, type, created_at, preview_text, attributes_json
14
+ FROM event_log
15
+ WHERE session_id = ? AND type IN ('tool_call', 'tool_execution_started', 'tool_execution_updated', 'tool_execution_finished')
16
+ ORDER BY stream_id ASC
17
17
  `).all(piboSessionId);
18
18
  const matching = rows.filter((row) => toolCallIdFromRow(row)?.includes(selector) || row.event_id === selector);
19
19
  if (matching.length === 0)
@@ -1,6 +1,6 @@
1
1
  import { buildTraceView } from "../apps/chat/trace.js";
2
2
  import { normalizeSessionErrorDetails } from "../core/session-errors.js";
3
- import { compareTraceOrder } from "../shared/trace-order.js";
3
+ import { compareTraceNodes } from "../shared/trace-nodes.js";
4
4
  import { openReadOnlyDebugDatabase, withStorePath } from "./sql.js";
5
5
  import { formatNextCommands } from "./next-commands.js";
6
6
  export async function inspectDebugTrace(piboSessionId, stores, options = {}) {
@@ -16,10 +16,11 @@ export async function inspectDebugTrace(piboSessionId, stores, options = {}) {
16
16
  throw new Error(`Pibo session "${piboSessionId}" not found`);
17
17
  const session = sessionFromRow(sessionRow);
18
18
  const sessions = sessionsDb.prepare("SELECT * FROM sessions").all().map(sessionFromRow);
19
+ const adapterIssues = [];
19
20
  const events = tableExists(chatDb, "event_log")
20
21
  ? chatDb
21
22
  .prepare("SELECT stream_id, session_id, session_sequence, event_id, type, created_at, preview_text, attributes_json FROM event_log WHERE session_id = ? ORDER BY stream_id ASC")
22
- .all(piboSessionId).map(eventFromRow).filter((event) => event !== undefined)
23
+ .all(piboSessionId).map((row) => eventFromRow(row, adapterIssues)).filter((event) => event !== undefined)
23
24
  : [];
24
25
  const view = await buildTraceView({
25
26
  session,
@@ -36,7 +37,7 @@ export async function inspectDebugTrace(piboSessionId, stores, options = {}) {
36
37
  status: traceStatus(view),
37
38
  nodes: filtered,
38
39
  rawNodeCount: rows.length,
39
- ...(options.check ? { checks: checkTraceView(view) } : {}),
40
+ ...(options.check ? { checks: checkTraceView(view, adapterIssues) } : {}),
40
41
  nextCommands: buildTraceNextCommands(view.piboSessionId, filtered),
41
42
  };
42
43
  }
@@ -168,10 +169,11 @@ function traceStatus(view) {
168
169
  return "running";
169
170
  return "done";
170
171
  }
171
- function checkTraceView(view) {
172
- const issues = [];
172
+ export function checkTraceView(view, adapterIssues = []) {
173
+ const issues = [...adapterIssues];
173
174
  const all = flattenPiboTraceNodes(view.nodes);
174
175
  const ids = new Set();
176
+ const stableKeyOwners = new Map();
175
177
  for (const node of all) {
176
178
  if (ids.has(node.id)) {
177
179
  issues.push({
@@ -206,6 +208,20 @@ function checkTraceView(view) {
206
208
  message: "Trace node has no conceptual stable key.",
207
209
  });
208
210
  }
211
+ else {
212
+ const existingOwner = stableKeyOwners.get(node.stableKey);
213
+ if (existingOwner && existingOwner !== node.id) {
214
+ issues.push({
215
+ severity: "warning",
216
+ code: "duplicate_stable_key",
217
+ nodeId: node.id,
218
+ message: `Stable key "${node.stableKey}" is already used by node "${existingOwner}".`,
219
+ });
220
+ }
221
+ else {
222
+ stableKeyOwners.set(node.stableKey, node.id);
223
+ }
224
+ }
209
225
  }
210
226
  for (const node of all) {
211
227
  if (node.parentId && !ids.has(node.parentId)) {
@@ -235,7 +251,7 @@ function checkSiblingOrder(nodes, issues) {
235
251
  checkSiblingOrder(node.children, issues);
236
252
  }
237
253
  function compareOrder(left, right) {
238
- return compareTraceOrder(left.orderKey, right.orderKey) || left.id.localeCompare(right.id);
254
+ return compareTraceNodes(left, right);
239
255
  }
240
256
  function flattenPiboTraceNodes(nodes) {
241
257
  return nodes.flatMap((node) => [node, ...flattenPiboTraceNodes(node.children)]);
@@ -288,10 +304,18 @@ function sessionFromRow(row) {
288
304
  updatedAt: row.updated_at,
289
305
  };
290
306
  }
291
- function eventFromRow(row) {
307
+ function eventFromRow(row, issues) {
292
308
  const payload = outputPayloadFromV2Row(row);
293
309
  if (!payload)
294
310
  return undefined;
311
+ if ((row.type === "assistant_delta" || row.type === "thinking_delta") && !nonEmptyEventText(payload)) {
312
+ issues.push({
313
+ severity: "warning",
314
+ code: "missing_delta_text",
315
+ nodeId: row.event_id ?? String(row.stream_id),
316
+ message: `Persisted ${row.type} event has no readable text payload.`,
317
+ });
318
+ }
295
319
  return {
296
320
  id: String(row.stream_id),
297
321
  piboSessionId: row.session_id ?? undefined,
@@ -315,12 +339,16 @@ function outputPayloadFromV2Row(row) {
315
339
  const base = { piboSessionId, eventId: row.event_id ?? undefined };
316
340
  if (row.type === "assistant_message")
317
341
  return compactObject({ ...base, type: "assistant_message", text: row.preview_text ?? "" });
342
+ if (row.type === "assistant_delta")
343
+ return compactObject({ ...base, type: "assistant_delta", text: inlineTextPayload(inlinePayload) ?? row.preview_text ?? "" });
318
344
  if (row.type === "message_started")
319
345
  return compactObject({ ...base, type: "message_started", text: row.preview_text ?? "" });
320
346
  if (row.type === "message_finished")
321
347
  return compactObject({ ...base, type: "message_finished" });
322
348
  if (row.type === "thinking_started")
323
349
  return compactObject({ ...base, type: "thinking_started" });
350
+ if (row.type === "thinking_delta")
351
+ return compactObject({ ...base, type: "thinking_delta", text: inlineTextPayload(inlinePayload) ?? row.preview_text ?? "" });
324
352
  if (row.type === "thinking_finished")
325
353
  return compactObject({ ...base, type: "thinking_finished", text: row.preview_text ?? "" });
326
354
  if (row.type === "tool_call")
@@ -337,6 +365,13 @@ function outputPayloadFromV2Row(row) {
337
365
  }
338
366
  return compactObject({ ...base, type: row.type });
339
367
  }
368
+ function inlineTextPayload(value) {
369
+ return typeof value === "string" ? value : undefined;
370
+ }
371
+ function nonEmptyEventText(event) {
372
+ const text = event.text;
373
+ return typeof text === "string" && text.length > 0;
374
+ }
340
375
  function stringAttribute(attributes, key) {
341
376
  const value = attributes[key];
342
377
  return typeof value === "string" ? value : undefined;