maka-agent 0.2.0-dev.23.20260906 → 0.2.0-dev.25.20260908

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 (215) hide show
  1. package/README.md +38 -19
  2. package/README.zh-CN.md +34 -19
  3. package/dist/acp/maka-acp-agent.js +2 -1
  4. package/dist/acp/session-configuration.js +143 -0
  5. package/dist/acp/session-registry.js +90 -4
  6. package/dist/cli-core.js +2 -0
  7. package/dist/pi-transcript-tools.js +6 -0
  8. package/dist/pi-transcript.js +5 -12
  9. package/dist/pi-tui-layout.js +56 -10
  10. package/dist/pi-tui-pickers.js +102 -1
  11. package/dist/pi-tui-runner.js +230 -46
  12. package/dist/pi-tui-todo.js +221 -0
  13. package/dist/pi-tui-transcript-viewer.js +134 -7
  14. package/dist/runtime-host-cli-context.js +224 -78
  15. package/dist/runtime-host-cli-installation.js +8 -2
  16. package/dist/runtime-host-cli.js +31 -1
  17. package/dist/runtime-host-handoff-surface.js +106 -0
  18. package/dist/runtime-host-installed-update-bootstrap.js +13 -0
  19. package/dist/runtime-host-installed-update-coordinator.js +33 -0
  20. package/dist/runtime-host-lifecycle-transaction.js +9 -1
  21. package/dist/runtime-host-local-handoff.js +48 -5
  22. package/dist/runtime-host-local-managed-activation.js +84 -0
  23. package/dist/runtime-host-local-source-retirement.js +18 -2
  24. package/dist/runtime-host-managed-lifecycle-manager.js +1 -0
  25. package/dist/runtime-host-operator-retirement.js +50 -0
  26. package/dist/runtime-host-service-manager.js +3 -3
  27. package/dist/runtime-host-session-channel.js +13 -0
  28. package/dist/runtime-host-session-driver.js +46 -26
  29. package/dist/runtime-host-session-update.js +62 -0
  30. package/dist/runtime-host-tui-command.js +38 -73
  31. package/dist/runtime-host-tui-context.js +1 -0
  32. package/dist/runtime-host-tui-owner.js +226 -0
  33. package/dist/tui-copy-catalog.js +219 -6
  34. package/dist/tui-host-owner-copy.js +24 -0
  35. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  36. package/node_modules/@maka/core/dist/agent-run.js +1 -0
  37. package/node_modules/@maka/core/dist/attachments.js +3 -0
  38. package/node_modules/@maka/core/dist/canonical-json.js +27 -0
  39. package/node_modules/@maka/core/dist/canonical-runtime-event.js +3 -1
  40. package/node_modules/@maka/core/dist/capabilities.js +35 -0
  41. package/node_modules/@maka/core/dist/computer-use.js +0 -1
  42. package/node_modules/@maka/core/dist/display-redaction.js +18 -0
  43. package/node_modules/@maka/core/dist/llm-connections.js +13 -0
  44. package/node_modules/@maka/core/dist/model-call-attempt.js +2 -0
  45. package/node_modules/@maka/core/dist/model-failure.js +40 -0
  46. package/node_modules/@maka/core/dist/model-metadata.generated.js +4 -4
  47. package/node_modules/@maka/core/dist/model-metadata.js +7 -3
  48. package/node_modules/@maka/core/dist/model-web-search.js +5 -4
  49. package/node_modules/@maka/core/dist/provider-registry.js +45 -4
  50. package/node_modules/@maka/core/dist/record-schema.js +9 -2
  51. package/node_modules/@maka/core/dist/redaction.js +35 -0
  52. package/node_modules/@maka/core/dist/run-composition.js +77 -2
  53. package/node_modules/@maka/core/dist/runtime-boundary.js +31 -11
  54. package/node_modules/@maka/core/dist/runtime-event.js +37 -6
  55. package/node_modules/@maka/core/dist/runtime-handoff.js +98 -0
  56. package/node_modules/@maka/core/dist/runtime-invocation.js +1 -1
  57. package/node_modules/@maka/core/dist/runtime-logical-execution.js +112 -0
  58. package/node_modules/@maka/core/dist/session.js +84 -56
  59. package/node_modules/@maka/core/dist/slash-command-catalog.js +3 -0
  60. package/node_modules/@maka/core/dist/tool-result-archive-evidence.js +20 -0
  61. package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
  62. package/node_modules/@maka/core/dist/usage-record-schema.js +26 -35
  63. package/node_modules/@maka/core/package.json +5 -0
  64. package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
  65. package/node_modules/@maka/mcp/dist/index.js +131 -1
  66. package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
  67. package/node_modules/@maka/runtime/dist/agent-run.js +351 -105
  68. package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +29 -13
  69. package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +109 -34
  70. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +184 -183
  71. package/node_modules/@maka/runtime/dist/archive-read-tool.js +2 -2
  72. package/node_modules/@maka/runtime/dist/context-budget-helpers.js +0 -16
  73. package/node_modules/@maka/runtime/dist/context-budget.js +14 -9
  74. package/node_modules/@maka/runtime/dist/conversation-copy.js +158 -15
  75. package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
  76. package/node_modules/@maka/runtime/dist/goal-continuation.js +36 -4
  77. package/node_modules/@maka/runtime/dist/history-compact-checkpoint.js +18 -9
  78. package/node_modules/@maka/runtime/dist/history-compact-summarizer.js +30 -22
  79. package/node_modules/@maka/runtime/dist/history-compaction.js +29 -4
  80. package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +174 -0
  81. package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
  82. package/node_modules/@maka/runtime/dist/message-authority.js +9 -0
  83. package/node_modules/@maka/runtime/dist/model-adapter.js +19 -98
  84. package/node_modules/@maka/runtime/dist/model-factory.js +19 -81
  85. package/node_modules/@maka/runtime/dist/model-fetcher.js +49 -2
  86. package/node_modules/@maka/runtime/dist/model-history.js +0 -112
  87. package/node_modules/@maka/runtime/dist/model-runtime.js +85 -111
  88. package/node_modules/@maka/runtime/dist/native-web-search-tool.js +2 -1
  89. package/node_modules/@maka/runtime/dist/openai-codex-history-compactor.js +2 -2
  90. package/node_modules/@maka/runtime/dist/opencode-session-header.js +4 -2
  91. package/node_modules/@maka/runtime/dist/plugin-runtime.js +20 -10
  92. package/node_modules/@maka/runtime/dist/plugin-tool-service.js +205 -0
  93. package/node_modules/@maka/runtime/dist/provider-error-classification.js +84 -123
  94. package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +76 -109
  95. package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
  96. package/node_modules/@maka/runtime/dist/run-handoff-gate.js +97 -0
  97. package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +83 -55
  98. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +121 -159
  99. package/node_modules/@maka/runtime/dist/runtime-kernel.js +157 -112
  100. package/node_modules/@maka/runtime/dist/runtime-ledger-repair.js +160 -79
  101. package/node_modules/@maka/runtime/dist/runtime-read-model.js +30 -89
  102. package/node_modules/@maka/runtime/dist/runtime-resume.js +80 -4
  103. package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +5 -0
  104. package/node_modules/@maka/runtime/dist/session-manager.js +171 -288
  105. package/node_modules/@maka/runtime/dist/session-projection-helpers.js +0 -27
  106. package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +21 -0
  107. package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +0 -5
  108. package/node_modules/@maka/runtime/dist/subscription-model-fetch.js +3 -4
  109. package/node_modules/@maka/runtime/dist/test-connection.js +16 -17
  110. package/node_modules/@maka/runtime/dist/tool-activation-identity.js +41 -0
  111. package/node_modules/@maka/runtime/dist/tool-availability.js +11 -1
  112. package/node_modules/@maka/runtime/dist/tool-result-archive-encoding.js +38 -0
  113. package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +63 -1
  114. package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +42 -12
  115. package/node_modules/@maka/runtime/dist/tool-result-archive.js +27 -4
  116. package/node_modules/@maka/runtime/dist/tool-runtime.js +3 -61
  117. package/node_modules/@maka/runtime/package.json +2 -0
  118. package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +35 -0
  119. package/node_modules/@maka/runtime-host/dist/client/connect-or-spawn.js +9 -1
  120. package/node_modules/@maka/runtime-host/dist/client/connection.js +3 -0
  121. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +179 -0
  122. package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +275 -0
  123. package/node_modules/@maka/runtime-host/dist/client/host-retirement.js +26 -5
  124. package/node_modules/@maka/runtime-host/dist/client/index.js +2 -0
  125. package/node_modules/@maka/runtime-host/dist/client/launcher.js +3 -0
  126. package/node_modules/@maka/runtime-host/dist/client/remote-compatibility-error.js +2 -0
  127. package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +46 -5
  128. package/node_modules/@maka/runtime-host/dist/control/endpoint.js +1 -3
  129. package/node_modules/@maka/runtime-host/dist/node-error.js +22 -0
  130. package/node_modules/@maka/runtime-host/dist/operator/index.js +2 -1
  131. package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
  132. package/node_modules/@maka/runtime-host/dist/operator/retirement-cancellation.js +20 -0
  133. package/node_modules/@maka/runtime-host/dist/peer-mesh/limits.js +0 -1
  134. package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +1 -1
  135. package/node_modules/@maka/runtime-host/dist/peer-reachability/publisher.js +1 -3
  136. package/node_modules/@maka/runtime-host/dist/protocol/host-status.js +21 -12
  137. package/node_modules/@maka/runtime-host/dist/protocol/index.js +29 -1
  138. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +1 -0
  139. package/node_modules/@maka/runtime-host/dist/protocol/plan.js +1 -0
  140. package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +27 -5
  141. package/node_modules/@maka/runtime-host/dist/protocol/project-catalog.js +2 -2
  142. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +40 -20
  143. package/node_modules/@maka/runtime-host/dist/protocol/session-transcript.js +0 -5
  144. package/node_modules/@maka/runtime-host/dist/protocol/session-turns.js +29 -58
  145. package/node_modules/@maka/runtime-host/dist/protocol/turn.js +11 -1
  146. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +31 -2
  147. package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +1 -0
  148. package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
  149. package/node_modules/@maka/runtime-host/dist/server/canonical-turn-snapshot.js +19 -4
  150. package/node_modules/@maka/runtime-host/dist/server/connection-session.js +7 -6
  151. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
  152. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +144 -33
  153. package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +5 -5
  154. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +45 -16
  155. package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +40 -1
  156. package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +96 -17
  157. package/node_modules/@maka/runtime-host/dist/server/host-residency-registry.js +13 -7
  158. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-admission-registry.js +3 -1
  159. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +124 -62
  160. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +47 -22
  161. package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +76 -6
  162. package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
  163. package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
  164. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +325 -73
  165. package/node_modules/@maka/runtime-host/dist/server/scheduled-task-coordinator.js +37 -2
  166. package/node_modules/@maka/runtime-host/dist/server/serial-outbound-writer.js +45 -3
  167. package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +50 -7
  168. package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +87 -25
  169. package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +5 -2
  170. package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +12 -55
  171. package/node_modules/@maka/runtime-host/dist/server/session-sidecar-purge.js +1 -16
  172. package/node_modules/@maka/runtime-host/dist/server/session-transcript-pager.js +0 -1
  173. package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +460 -70
  174. package/node_modules/@maka/runtime-host/dist/server/shared-session-transcript.js +1 -1
  175. package/node_modules/@maka/runtime-host/dist/server/storage-maintenance.js +109 -0
  176. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +20 -2
  177. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +13 -4
  178. package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
  179. package/node_modules/@maka/storage/dist/artifact-store.js +21 -10
  180. package/node_modules/@maka/storage/dist/artifact-stores.js +1 -1
  181. package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -5
  182. package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -198
  183. package/node_modules/@maka/storage/dist/context-offload-snapshot.js +325 -0
  184. package/node_modules/@maka/storage/dist/execution-stores.js +9 -7
  185. package/node_modules/@maka/storage/dist/file-session-repository.js +1012 -0
  186. package/node_modules/@maka/storage/dist/git-exec.js +61 -0
  187. package/node_modules/@maka/storage/dist/git-worktree-child-executor.js +8 -35
  188. package/node_modules/@maka/storage/dist/goal-authority.js +2 -2
  189. package/node_modules/@maka/storage/dist/interaction-store.js +2 -2
  190. package/node_modules/@maka/storage/dist/opencode-session-adapter.js +0 -4
  191. package/node_modules/@maka/storage/dist/operational-state-backup.js +9 -5
  192. package/node_modules/@maka/storage/dist/project-catalog.js +2 -23
  193. package/node_modules/@maka/storage/dist/runtime-event-invariants.js +2 -2
  194. package/node_modules/@maka/storage/dist/runtime-event-persistence.js +1 -0
  195. package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
  196. package/node_modules/@maka/storage/dist/runtime-transcript-query.js +308 -0
  197. package/node_modules/@maka/storage/dist/scheduled-task-store.js +249 -283
  198. package/node_modules/@maka/storage/dist/session-bundle-manifest.js +5 -17
  199. package/node_modules/@maka/storage/dist/session-bundle-policy.js +26 -5
  200. package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
  201. package/node_modules/@maka/storage/dist/session-message-projection.js +15 -0
  202. package/node_modules/@maka/storage/dist/session-repository.js +767 -0
  203. package/node_modules/@maka/storage/dist/session-store.js +25 -99
  204. package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +10 -3
  205. package/node_modules/@maka/storage/dist/sqlite-context-offload-store.js +24 -8
  206. package/node_modules/@maka/storage/dist/sqlite-core-execution-schema.js +7 -1
  207. package/node_modules/@maka/storage/dist/sqlite-runtime-schema.js +44 -1
  208. package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +130 -27
  209. package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +109 -892
  210. package/node_modules/@maka/storage/dist/storage-id.js +28 -0
  211. package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +138 -0
  212. package/node_modules/@maka/storage/dist/workspace-identity.js +2 -15
  213. package/node_modules/@maka/storage/dist/workspace-version-authority-internal.js +1 -8
  214. package/node_modules/@maka/storage/package.json +2 -0
  215. package/package.json +1 -1
@@ -0,0 +1,308 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { decodeRuntimeEvent } from '@maka/core/runtime-event';
20
+ /**
21
+ * SQL counterpart of isTerminalRuntimeEvent; shared with the ledger store.
22
+ *
23
+ * The `json_valid` guard is what keeps this usable as a partial index: SQLite
24
+ * evaluates the index predicate over every row while building it, and
25
+ * `json_extract` on a malformed payload fails the whole statement. That would
26
+ * abort the migration that creates the index, roll back its version bump, and
27
+ * leave the next open to try — and fail — again.
28
+ */
29
+ export const TERMINAL_RUNTIME_EVENT_SQL = `(
30
+ json_valid(payload_json)
31
+ AND (
32
+ json_extract(payload_json, '$.actions.endInvocation') = 1
33
+ OR json_extract(payload_json, '$.status') IN ('completed', 'failed', 'aborted', 'cancelled')
34
+ )
35
+ )`;
36
+ export class RuntimeTranscriptOversizedTurnError extends Error {
37
+ name = 'RuntimeTranscriptOversizedTurnError';
38
+ }
39
+ /**
40
+ * A Turn the Session transcript shows: one this Session ran itself rather than
41
+ * on behalf of a subagent.
42
+ *
43
+ * This is a fact about the invocation, not about any row it produces — which
44
+ * rows it produces is the read model's question, and is not asked here.
45
+ */
46
+ const visibleOpening = (payload) => `
47
+ (${payload} IS NOT NULL
48
+ AND (json_extract(${payload}, '$.lineage.parentRunId') IS NULL
49
+ OR (json_extract(${payload}, '$.source.kind') <> 'fresh'
50
+ AND json_extract(${payload}, '$.lineage.agentId') IS NULL)))`;
51
+ /** Where an invocation ends; NULL while it is still running. */
52
+ const endingOrdinal = (invocation) => `
53
+ (SELECT MIN(o2.ordinal) FROM runtime_events t
54
+ JOIN runtime_session_event_ordinals o2 ON o2.event_id = t.event_id
55
+ WHERE t.invocation_id = ${invocation}
56
+ AND ${TERMINAL_RUNTIME_EVENT_SQL.replaceAll('payload_json', 't.payload_json')})`;
57
+ /**
58
+ * A Session migrated from run headers keeps some openings beside the ledger
59
+ * rather than in it, ordered by the anchor event each one names.
60
+ */
61
+ const migratedOpening = `
62
+ FROM runtime_legacy_invocation_openings legacy
63
+ JOIN runtime_session_event_ordinals o ON o.event_id = legacy.anchor_event_id
64
+ WHERE legacy.session_id = :sessionId
65
+ AND ${visibleOpening('legacy.opening_json')}
66
+ AND NOT EXISTS (
67
+ SELECT 1 FROM runtime_events opened
68
+ WHERE opened.invocation_id = legacy.invocation_id
69
+ AND opened.event_kind = 'invocation_opened'
70
+ )`;
71
+ const ledgerOpening = `
72
+ FROM runtime_session_event_ordinals o
73
+ JOIN runtime_events e ON e.event_id = o.event_id
74
+ WHERE o.session_id = :sessionId
75
+ AND e.event_kind = 'invocation_opened'
76
+ AND ${visibleOpening("json_extract(e.payload_json, '$.content')")}`;
77
+ /** Either shelf's opening for one invocation, reached from an event it owns. */
78
+ const openingOrdinal = (invocation) => `
79
+ COALESCE(
80
+ (SELECT o3.ordinal FROM runtime_events op
81
+ JOIN runtime_session_event_ordinals o3 ON o3.event_id = op.event_id
82
+ WHERE op.invocation_id = ${invocation} AND op.event_kind = 'invocation_opened'),
83
+ (SELECT o3.ordinal FROM runtime_legacy_invocation_openings lg
84
+ JOIN runtime_session_event_ordinals o3 ON o3.event_id = lg.anchor_event_id
85
+ WHERE lg.invocation_id = ${invocation}))`;
86
+ const openingContent = (invocation) => `
87
+ COALESCE(
88
+ (SELECT json_extract(op.payload_json, '$.content') FROM runtime_events op
89
+ WHERE op.invocation_id = ${invocation} AND op.event_kind = 'invocation_opened'),
90
+ (SELECT lg.opening_json FROM runtime_legacy_invocation_openings lg
91
+ WHERE lg.invocation_id = ${invocation}))`;
92
+ /** Selects invocations by Session ordinal. Payloads are decoded, never classified. */
93
+ export class RuntimeTranscriptQuery {
94
+ db;
95
+ invocation;
96
+ constructor(db, invocation) {
97
+ this.db = db;
98
+ this.invocation = invocation;
99
+ }
100
+ highWater(sessionId) {
101
+ // The furthest a transcript reaches is the last ending on it.
102
+ const [row] = this.byEnding(sessionId, {
103
+ order: 'DESC',
104
+ from: 0,
105
+ throughOrdinal: Number.MAX_SAFE_INTEGER,
106
+ limit: 1,
107
+ });
108
+ return row?.last ?? null;
109
+ }
110
+ invocations(sessionId, request) {
111
+ assertOrdinal(request.throughOrdinal);
112
+ assertOrdinal(request.position);
113
+ if (request.direction !== 'older' && request.direction !== 'newer') {
114
+ throw new Error('Invalid transcript direction');
115
+ }
116
+ // An invocation is selected by where its own events sit, so a walk that
117
+ // starts inside a Turn still finds that Turn and can serve its rows. Both
118
+ // ends are the invocation's own two events — its opening and its ending —
119
+ // rather than the extremes of everything between them.
120
+ //
121
+ // Each direction walks the end of the Turn that `position` bounds, which
122
+ // is the one the ordinal index can seek to: backward that is the opening,
123
+ // forward the ending. Neither assumes Turns do not overlap, and each stops
124
+ // at the page, so a page costs the page rather than the Session.
125
+ const rows = request.direction === 'older'
126
+ ? this.byOpening(sessionId, request)
127
+ : this.byEnding(sessionId, {
128
+ order: 'ASC',
129
+ from: request.position,
130
+ throughOrdinal: request.throughOrdinal,
131
+ limit: request.limit,
132
+ }).sort((a, b) => a.first - b.first);
133
+ return rows.map((row) => ({
134
+ invocation: this.invocation(sessionId, row.invocation_id),
135
+ firstOrdinal: row.first,
136
+ lastOrdinal: row.last,
137
+ events: this.events(row.invocation_id, request),
138
+ }));
139
+ }
140
+ landmarks(sessionId, throughOrdinal, limit) {
141
+ assertOrdinal(throughOrdinal);
142
+ if (limit < 1)
143
+ return [];
144
+ // Evenly spaced Turn starts, chosen before any payload is read.
145
+ const rows = this.db
146
+ .prepare(`
147
+ WITH settled AS (
148
+ SELECT e.invocation_id AS invocation_id, o.ordinal AS ordinal ${ledgerOpening}
149
+ AND ${endingOrdinal('e.invocation_id')} <= :throughOrdinal
150
+ UNION ALL
151
+ SELECT legacy.invocation_id, o.ordinal ${migratedOpening}
152
+ AND ${endingOrdinal('legacy.invocation_id')} <= :throughOrdinal
153
+ ), candidates AS (
154
+ SELECT invocation_id, ordinal,
155
+ ROW_NUMBER() OVER (ORDER BY ordinal) - 1 AS rank, COUNT(*) OVER () AS total
156
+ FROM settled
157
+ ), samples(n) AS (
158
+ SELECT 0 UNION ALL SELECT n + 1 FROM samples WHERE n + 1 < :limit
159
+ )
160
+ SELECT DISTINCT invocation_id, ordinal FROM candidates
161
+ JOIN samples ON rank = CASE WHEN :limit = 1 THEN total - 1
162
+ ELSE CAST(n * (total - 1) / (:limit - 1) AS INTEGER) END
163
+ ORDER BY ordinal
164
+ `)
165
+ .all({ sessionId, throughOrdinal, limit });
166
+ return rows.map((row) => {
167
+ // The prompt is the Turn's first user text event, which is what the read
168
+ // model projects a user message from. Only that one event is loaded: a
169
+ // landmark is a label, and projecting whole Turns to build a scrollbar
170
+ // would read most of the Session.
171
+ const prompt = this.db
172
+ .prepare(`
173
+ SELECT o.ordinal, e.event_id FROM runtime_events e
174
+ JOIN runtime_session_event_ordinals o ON o.event_id = e.event_id
175
+ WHERE e.invocation_id = ? AND o.ordinal <= ?
176
+ AND e.event_kind = 'text' AND json_extract(e.payload_json, '$.role') = 'user'
177
+ ORDER BY e.event_seq LIMIT 1
178
+ `)
179
+ .get(row.invocation_id, throughOrdinal);
180
+ return {
181
+ invocation: this.invocation(sessionId, row.invocation_id),
182
+ firstOrdinal: row.ordinal,
183
+ ...(prompt
184
+ ? { prompt: { ordinal: prompt.ordinal, event: this.event(prompt.event_id) } }
185
+ : {}),
186
+ };
187
+ });
188
+ }
189
+ /**
190
+ * The page of settled visible invocations that opened at or before
191
+ * `position`, newest first.
192
+ *
193
+ * The two shelves are read as separate statements and merged rather than
194
+ * unioned, so each keeps its own index walk and stops at the page — and the
195
+ * common Session pays nothing for a table its history never wrote to.
196
+ */
197
+ byOpening(sessionId, request) {
198
+ const bind = {
199
+ sessionId,
200
+ position: request.position,
201
+ throughOrdinal: request.throughOrdinal,
202
+ limit: request.limit,
203
+ };
204
+ const ledger = this.db
205
+ .prepare(`
206
+ SELECT e.invocation_id AS invocation_id, o.ordinal AS first,
207
+ ${endingOrdinal('e.invocation_id')} AS last
208
+ ${ledgerOpening}
209
+ AND o.ordinal <= :position
210
+ AND ${endingOrdinal('e.invocation_id')} <= :throughOrdinal
211
+ ORDER BY o.ordinal DESC
212
+ LIMIT :limit
213
+ `)
214
+ .all(bind);
215
+ const migrated = this.db
216
+ .prepare(`
217
+ SELECT legacy.invocation_id AS invocation_id, o.ordinal AS first,
218
+ ${endingOrdinal('legacy.invocation_id')} AS last
219
+ ${migratedOpening}
220
+ AND o.ordinal <= :position
221
+ AND ${endingOrdinal('legacy.invocation_id')} <= :throughOrdinal
222
+ ORDER BY o.ordinal DESC
223
+ LIMIT :limit
224
+ `)
225
+ .all(bind);
226
+ if (migrated.length === 0)
227
+ return ledger;
228
+ return [...ledger, ...migrated].sort((a, b) => b.first - a.first).slice(0, request.limit);
229
+ }
230
+ /**
231
+ * The page of settled visible invocations whose ending sits between `from`
232
+ * and `throughOrdinal`, in `order` of that ending.
233
+ *
234
+ * An ending is an event of the invocation like any other, so this walks the
235
+ * same ordinal index — one statement, because the ending is on the ledger
236
+ * whichever shelf the opening came from.
237
+ */
238
+ byEnding(sessionId, bounds) {
239
+ return this.db
240
+ .prepare(`
241
+ SELECT ending.invocation_id AS invocation_id,
242
+ ${openingOrdinal('ending.invocation_id')} AS first,
243
+ o.ordinal AS last
244
+ FROM runtime_session_event_ordinals o
245
+ JOIN runtime_events ending ON ending.event_id = o.event_id
246
+ WHERE o.session_id = :sessionId
247
+ AND o.ordinal BETWEEN :from AND :throughOrdinal
248
+ AND ${TERMINAL_RUNTIME_EVENT_SQL.replaceAll('payload_json', 'ending.payload_json')}
249
+ AND o.ordinal = ${endingOrdinal('ending.invocation_id')}
250
+ AND ${visibleOpening(openingContent('ending.invocation_id'))}
251
+ ORDER BY o.ordinal ${bounds.order}
252
+ LIMIT :limit
253
+ `)
254
+ .all({
255
+ sessionId,
256
+ from: bounds.from,
257
+ throughOrdinal: bounds.throughOrdinal,
258
+ limit: bounds.limit,
259
+ });
260
+ }
261
+ events(invocationId, limits) {
262
+ // Walked row by row: the limits cap what one Turn may pull into memory, so
263
+ // a check after `.all()` has already paid the cost it was meant to refuse.
264
+ const cursor = this.db
265
+ .prepare(`
266
+ SELECT o.ordinal, e.event_id, e.session_id, e.invocation_id, e.run_id, e.turn_id, e.payload_json
267
+ FROM runtime_events e JOIN runtime_session_event_ordinals o ON o.event_id = e.event_id
268
+ WHERE e.invocation_id = ? ORDER BY e.event_seq
269
+ `)
270
+ .iterate(invocationId);
271
+ const events = [];
272
+ let bytes = 0;
273
+ for (const row of cursor) {
274
+ if (events.length === limits.maxEvents) {
275
+ throw new RuntimeTranscriptOversizedTurnError(`Turn ${invocationId} holds more RuntimeEvents than a transcript page may read`);
276
+ }
277
+ bytes += Buffer.byteLength(row.payload_json);
278
+ if (bytes > limits.maxBytes) {
279
+ throw new RuntimeTranscriptOversizedTurnError(`Turn ${invocationId} holds more RuntimeEvent bytes than a transcript page may read`);
280
+ }
281
+ events.push({ ordinal: row.ordinal, event: decodeStoredEvent(row) });
282
+ }
283
+ return events;
284
+ }
285
+ event(id) {
286
+ const row = this.db
287
+ .prepare('SELECT event_id, session_id, invocation_id, run_id, turn_id, payload_json FROM runtime_events WHERE event_id = ?')
288
+ .get(id);
289
+ if (!row)
290
+ throw new Error(`Transcript RuntimeEvent ${id} is missing`);
291
+ return decodeStoredEvent(row);
292
+ }
293
+ }
294
+ function decodeStoredEvent(row) {
295
+ const event = decodeRuntimeEvent(JSON.parse(row.payload_json));
296
+ if (event.id !== row.event_id ||
297
+ event.sessionId !== row.session_id ||
298
+ event.invocationId !== row.invocation_id ||
299
+ event.runId !== row.run_id ||
300
+ event.turnId !== row.turn_id) {
301
+ throw new Error(`Transcript RuntimeEvent ${row.event_id} has inconsistent storage identity`);
302
+ }
303
+ return event;
304
+ }
305
+ function assertOrdinal(value) {
306
+ if (!Number.isSafeInteger(value) || value < 0)
307
+ throw new Error('Invalid transcript event ordinal');
308
+ }