praxis-agent 0.37.0 → 0.39.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.
- package/README.md +31 -53
- package/dist/application/background-agent-manager.js +7 -4
- package/dist/application/background-bash-manager.d.ts +2 -2
- package/dist/application/background-bash-manager.js +6 -6
- package/dist/application/claude-project-purge.js +36 -74
- package/dist/application/native-session-transcript.d.ts +14 -3
- package/dist/application/native-session-transcript.js +30 -9
- package/dist/application/scheduled-prompt-manager.d.ts +2 -2
- package/dist/application/scheduled-prompt-manager.js +3 -3
- package/dist/application/session-memory.d.ts +2 -5
- package/dist/application/session-memory.js +4 -7
- package/dist/application/session-service.d.ts +18 -29
- package/dist/application/session-service.js +1084 -1784
- package/dist/application/session-worktree.d.ts +2 -3
- package/dist/application/session-worktree.js +3 -3
- package/dist/application/subagent-service.d.ts +2 -5
- package/dist/application/subagent-service.js +152 -319
- package/dist/application/team-agent-runtime.d.ts +3 -0
- package/dist/application/team-agent-runtime.js +20 -3
- package/dist/application/team-lead-decision-surface.d.ts +22 -0
- package/dist/application/team-lead-decision-surface.js +16 -0
- package/dist/application/team-observability.d.ts +113 -0
- package/dist/application/team-observability.js +312 -0
- package/dist/application/top-level-agent-manager.js +19 -37
- package/dist/application/transcript-projection.js +18 -2
- package/dist/application/workflow-manager.d.ts +1 -1
- package/dist/application/workflow-manager.js +11 -19
- package/dist/cli/controls.d.ts +10 -6
- package/dist/cli/controls.js +28 -6
- package/dist/cli/interactive.d.ts +4 -3
- package/dist/cli/interactive.js +461 -216
- package/dist/cli/protocol.d.ts +1 -1
- package/dist/cli/protocol.js +0 -13
- package/dist/cli/tui/btw-surface-model.d.ts +22 -0
- package/dist/cli/tui/btw-surface-model.js +10 -0
- package/dist/cli/tui/claude-style.d.ts +52 -90
- package/dist/cli/tui/claude-style.js +96 -79
- package/dist/cli/tui/command-palette-model.d.ts +33 -0
- package/dist/cli/tui/command-palette-model.js +44 -0
- package/dist/cli/tui/config-dashboard.d.ts +3 -9
- package/dist/cli/tui/config-dashboard.js +2 -1
- package/dist/cli/tui/config-settings.js +5 -14
- package/dist/cli/tui/config-surface-model.d.ts +24 -0
- package/dist/cli/tui/config-surface-model.js +16 -0
- package/dist/cli/tui/diff-surface-model.d.ts +83 -0
- package/dist/cli/tui/diff-surface-model.js +142 -0
- package/dist/cli/tui/doctor-dashboard.d.ts +3 -4
- package/dist/cli/tui/doctor-dashboard.js +3 -2
- package/dist/cli/tui/doctor-surface-model.d.ts +13 -0
- package/dist/cli/tui/doctor-surface-model.js +9 -0
- package/dist/cli/tui/hook-settings.d.ts +2 -2
- package/dist/cli/tui/hooks-surface-model.d.ts +18 -0
- package/dist/cli/tui/hooks-surface-model.js +11 -0
- package/dist/cli/tui/leaf-surface-model.d.ts +68 -0
- package/dist/cli/tui/leaf-surface-model.js +55 -0
- package/dist/cli/tui/list-surface-model.d.ts +27 -0
- package/dist/cli/tui/list-surface-model.js +22 -0
- package/dist/cli/tui/mcp-elicitation-surface-model.d.ts +27 -0
- package/dist/cli/tui/mcp-elicitation-surface-model.js +25 -0
- package/dist/cli/tui/mcp-elicitation.d.ts +7 -1
- package/dist/cli/tui/mcp-elicitation.js +6 -2
- package/dist/cli/tui/mcp-panel.d.ts +3 -6
- package/dist/cli/tui/mcp-panel.js +6 -8
- package/dist/cli/tui/mcp-surface-model.d.ts +11 -0
- package/dist/cli/tui/mcp-surface-model.js +4 -0
- package/dist/cli/tui/memory-files.d.ts +3 -5
- package/dist/cli/tui/memory-files.js +12 -30
- package/dist/cli/tui/memory-surface-model.d.ts +20 -0
- package/dist/cli/tui/memory-surface-model.js +12 -0
- package/dist/cli/tui/mention-picker-model.d.ts +41 -0
- package/dist/cli/tui/mention-picker-model.js +53 -0
- package/dist/cli/tui/model-effort-surface-model.d.ts +29 -0
- package/dist/cli/tui/model-effort-surface-model.js +38 -0
- package/dist/cli/tui/permission-settings.d.ts +6 -9
- package/dist/cli/tui/permission-settings.js +9 -15
- package/dist/cli/tui/rewind-surface-model.d.ts +53 -0
- package/dist/cli/tui/rewind-surface-model.js +54 -0
- package/dist/cli/tui/sandbox-dashboard.d.ts +3 -4
- package/dist/cli/tui/sandbox-dashboard.js +2 -1
- package/dist/cli/tui/sandbox-settings.d.ts +3 -5
- package/dist/cli/tui/sandbox-settings.js +5 -9
- package/dist/cli/tui/sandbox-surface-model.d.ts +13 -0
- package/dist/cli/tui/sandbox-surface-model.js +4 -0
- package/dist/cli/tui/session-picker-model.d.ts +41 -0
- package/dist/cli/tui/session-picker-model.js +69 -0
- package/dist/cli/tui/slash-commands.js +1 -1
- package/dist/cli/tui/status-line.d.ts +5 -5
- package/dist/cli/tui/status-line.js +12 -30
- package/dist/cli/tui/task-panel.d.ts +3 -3
- package/dist/cli/tui/task-panel.js +2 -1
- package/dist/cli/tui/task-surface-model.d.ts +11 -0
- package/dist/cli/tui/task-surface-model.js +4 -0
- package/dist/cli/tui/terminal-setup.js +2 -4
- package/dist/cli/tui/theme-surface-model.d.ts +85 -0
- package/dist/cli/tui/theme-surface-model.js +52 -0
- package/dist/cli/tui/theme.d.ts +2 -2
- package/dist/cli/tui/tool-permission.d.ts +1 -1
- package/dist/cli/tui/tool-permission.js +13 -15
- package/dist/cli-runtime.d.ts +1 -1
- package/dist/cli-runtime.js +163 -317
- package/dist/{compatibility/claude → core}/agent-color.d.ts +1 -2
- package/dist/core/project-memory.d.ts +4 -3
- package/dist/core/project-memory.js +2 -4
- package/dist/core/runtime.d.ts +2 -0
- package/dist/core/transcript-event.d.ts +4 -0
- package/dist/core/transcript-event.js +11 -1
- package/dist/extensions/claude-extensions.d.ts +5 -6
- package/dist/extensions/claude-extensions.js +13 -27
- package/dist/extensions/claude-init-command.d.ts +2 -3
- package/dist/extensions/claude-init-command.js +7 -70
- package/dist/hooks/claude-file-change-watcher.d.ts +3 -0
- package/dist/hooks/claude-file-change-watcher.js +70 -8
- package/dist/hooks/claude-hook-tools.js +6 -1
- package/dist/hooks/claude-hooks.d.ts +4 -4
- package/dist/maintenance/doctor-diagnostic.d.ts +0 -1
- package/dist/maintenance/doctor-diagnostic.js +0 -4
- package/dist/maintenance/doctor.d.ts +8 -4
- package/dist/maintenance/doctor.js +10 -63
- package/dist/mcp/claude-mcp-management.d.ts +3 -3
- package/dist/mcp/claude-mcp-management.js +16 -37
- package/dist/mcp/claude-mcp-oauth.js +1 -1
- package/dist/mcp/claude-mcp-tools.d.ts +4 -4
- package/dist/mcp/claude-mcp-tools.js +1 -3
- package/dist/{compatibility/claude → native}/compaction.d.ts +4 -4
- package/dist/{compatibility/claude → native}/context.d.ts +6 -2
- package/dist/{compatibility/claude → native}/context.js +21 -9
- package/dist/native/file-history.d.ts +14 -0
- package/dist/{compatibility/claude → native}/fork.d.ts +3 -3
- package/dist/{compatibility/claude → native}/fork.js +4 -4
- package/dist/{compatibility/claude → native}/history.d.ts +6 -6
- package/dist/{compatibility/claude → native}/interruption.d.ts +3 -3
- package/dist/{compatibility/claude → native}/ownership.d.ts +17 -17
- package/dist/{compatibility/claude → native}/ownership.js +17 -17
- package/dist/{compatibility/claude → native}/paths.d.ts +8 -8
- package/dist/{compatibility/claude → native}/paths.js +23 -26
- package/dist/{compatibility/claude → native}/pr-links.d.ts +2 -2
- package/dist/{compatibility/claude → native}/projection.d.ts +8 -8
- package/dist/native/schema.d.ts +14 -0
- package/dist/native/schema.js +24 -0
- package/dist/{compatibility/claude → native}/session-metadata.d.ts +6 -6
- package/dist/{compatibility/claude → native}/sidechain.d.ts +4 -4
- package/dist/{compatibility/claude → native}/tool-links.d.ts +5 -5
- package/dist/{compatibility/claude → native}/translation.d.ts +10 -10
- package/dist/{compatibility/claude → native}/translation.js +17 -7
- package/dist/permissions/bash-path-safety.js +2 -4
- package/dist/permissions/bypass-immune-paths.d.ts +0 -2
- package/dist/permissions/bypass-immune-paths.js +2 -2
- package/dist/permissions/claude-auto-classifier.d.ts +2 -2
- package/dist/permissions/claude-permission-resolver.d.ts +3 -3
- package/dist/permissions/claude-permission-resolver.js +9 -13
- package/dist/persistence/claude-cost-state-store.js +1 -2
- package/dist/persistence/claude-workflow-store.d.ts +26 -4
- package/dist/persistence/claude-workflow-store.js +47 -2
- package/dist/persistence/data-plane-adapter.d.ts +1 -2
- package/dist/persistence/data-plane.d.ts +2 -3
- package/dist/persistence/data-plane.js +15 -12
- package/dist/persistence/in-memory-sidechain-store.d.ts +24 -7
- package/dist/persistence/in-memory-sidechain-store.js +23 -19
- package/dist/persistence/in-memory-transcript-store.d.ts +13 -6
- package/dist/persistence/in-memory-transcript-store.js +38 -58
- package/dist/persistence/native-resources.js +63 -7
- package/dist/persistence/{claude-scheduled-task-store.d.ts → native-scheduled-task-store.d.ts} +10 -10
- package/dist/persistence/{claude-scheduled-task-store.js → native-scheduled-task-store.js} +14 -14
- package/dist/persistence/native-transcript-reader.d.ts +6 -6
- package/dist/persistence/native-transcript-reader.js +2 -2
- package/dist/persistence/native-transcript-store.d.ts +9 -0
- package/dist/persistence/native-transcript-store.js +47 -5
- package/dist/persistence/subagent-lifecycle-store.js +3 -4
- package/dist/persistence/unknown-cost-sidecar.d.ts +2 -2
- package/dist/persistence/unknown-cost-sidecar.js +2 -2
- package/dist/platform/project-memory-paths.d.ts +3 -4
- package/dist/platform/project-memory-paths.js +4 -5
- package/dist/plugins/claude-plugin-marketplace.js +3 -2
- package/dist/plugins/claude-plugin-mcpb.js +3 -4
- package/dist/plugins/claude-plugin-runtime.d.ts +6 -6
- package/dist/providers/anthropic-prompt-cache.d.ts +1 -1
- package/dist/providers/anthropic-prompt-cache.js +3 -26
- package/dist/sandbox/claude-sandbox-settings.d.ts +5 -6
- package/dist/sandbox/claude-sandbox-settings.js +5 -5
- package/dist/tools/claude-interactive-tools.d.ts +1 -2
- package/dist/tools/claude-interactive-tools.js +3 -1
- package/dist/tools/claude-scheduled-tools.js +6 -7
- package/dist/tools/claude-workflow-tools.d.ts +0 -2
- package/dist/tools/claude-workflow-tools.js +4 -4
- package/dist/tools/claude-worktree-tools.js +3 -5
- package/dist/tools/local-tools.d.ts +2 -1
- package/dist/tools/local-tools.js +11 -5
- package/dist/tools/team-lead-tools.d.ts +1 -1
- package/dist/tools/team-lead-tools.js +0 -1
- package/package.json +8 -65
- package/dist/compatibility/claude/data-plane-adapter.d.ts +0 -9
- package/dist/compatibility/claude/data-plane-adapter.js +0 -44
- package/dist/compatibility/claude/file-history.d.ts +0 -14
- package/dist/compatibility/claude/schema.d.ts +0 -26
- package/dist/compatibility/claude/schema.js +0 -1071
- package/dist/compatibility/claude/shared-resources.d.ts +0 -27
- package/dist/compatibility/claude/shared-resources.js +0 -459
- package/dist/compatibility/claude/transcript-codec.d.ts +0 -21
- package/dist/compatibility/claude/transcript-codec.js +0 -518
- package/dist/persistence/claude-migration.d.ts +0 -5
- package/dist/persistence/claude-migration.js +0 -225
- package/dist/persistence/claude-session-index.d.ts +0 -39
- package/dist/persistence/claude-session-index.js +0 -175
- package/dist/persistence/claude-sidechain-store.d.ts +0 -18
- package/dist/persistence/claude-sidechain-store.js +0 -123
- package/dist/persistence/claude-transcript-store.d.ts +0 -90
- package/dist/persistence/claude-transcript-store.js +0 -469
- package/dist/platform/claude-version.d.ts +0 -5
- package/dist/platform/claude-version.js +0 -18
- /package/dist/{compatibility/claude → core}/agent-color.js +0 -0
- /package/dist/{compatibility/claude → native}/compaction.js +0 -0
- /package/dist/{compatibility/claude → native}/dynamic-context.d.ts +0 -0
- /package/dist/{compatibility/claude → native}/dynamic-context.js +0 -0
- /package/dist/{compatibility/claude → native}/file-history.js +0 -0
- /package/dist/{compatibility/claude → native}/file-resources.d.ts +0 -0
- /package/dist/{compatibility/claude → native}/file-resources.js +0 -0
- /package/dist/{compatibility/claude → native}/history.js +0 -0
- /package/dist/{compatibility/claude → native}/interruption.js +0 -0
- /package/dist/{compatibility/claude → native}/pr-links.js +0 -0
- /package/dist/{compatibility/claude → native}/projection.js +0 -0
- /package/dist/{compatibility/claude → native}/session-metadata.js +0 -0
- /package/dist/{compatibility/claude → native}/sidechain.js +0 -0
- /package/dist/{compatibility/claude → native}/tool-links.js +0 -0
- /package/dist/{compatibility/claude → native}/workflow-replay.d.ts +0 -0
- /package/dist/{compatibility/claude → native}/workflow-replay.js +0 -0
- /package/dist/{compatibility/claude → native}/workflow.d.ts +0 -0
- /package/dist/{compatibility/claude → native}/workflow.js +0 -0
package/README.md
CHANGED
|
@@ -17,15 +17,10 @@ Anthropic/OpenAI-compatible model access. Praxis deliberately excludes
|
|
|
17
17
|
accounts, organizations, billing, managed enterprise policy, remote control,
|
|
18
18
|
IDE surfaces, and telemetry control planes.
|
|
19
19
|
|
|
20
|
-
Claude Code 2.1.208 remains
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
the existing enterprise, authentication, hosted, and client surfaces plus the
|
|
25
|
-
explicitly classified subscription-bound integration, campaign, hidden
|
|
26
|
-
maintainer diagnostic, and build-experimental commands. A similar Praxis
|
|
27
|
-
surface is not a substitute for the corresponding Claude command or runtime
|
|
28
|
-
contract.
|
|
20
|
+
Claude Code 2.1.208 remains a clean-room behavioral reference for the
|
|
21
|
+
developer-facing CLI surface. It is not a runtime dependency or a data source:
|
|
22
|
+
Praxis runs one native data plane and does not read or write Claude Code
|
|
23
|
+
sessions, configuration, or compatibility directories.
|
|
29
24
|
|
|
30
25
|
## Requirements
|
|
31
26
|
|
|
@@ -34,9 +29,12 @@ contract.
|
|
|
34
29
|
- [`ripgrep`](https://github.com/BurntSushi/ripgrep) (`rg`) for the Grep tool
|
|
35
30
|
- an API key and model ID for an Anthropic or OpenAI-compatible provider
|
|
36
31
|
|
|
37
|
-
Praxis does not use Claude subscription authentication. Claude
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
Praxis does not use Claude subscription authentication. Claude-shaped message,
|
|
33
|
+
tool, and CLI protocol forms remain supported where they are part of the
|
|
34
|
+
public surface, while all persisted state is Praxis-native.
|
|
35
|
+
|
|
36
|
+
Team operations are local-only and opt-in. Unsupported or lossy Team payloads
|
|
37
|
+
are rejected rather than silently simplified.
|
|
40
38
|
|
|
41
39
|
## Install
|
|
42
40
|
|
|
@@ -85,7 +83,7 @@ praxis doctor
|
|
|
85
83
|
|
|
86
84
|
See
|
|
87
85
|
[Getting Started](https://github.com/Forest-Isle/Praxis/blob/main/docs/GETTING_STARTED.md)
|
|
88
|
-
for provider setup, shared
|
|
86
|
+
for provider setup, shared Praxis state, permissions, updating, and
|
|
89
87
|
troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
90
88
|
|
|
91
89
|
## What Praxis provides
|
|
@@ -112,7 +110,7 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
|
112
110
|
context/status/skill/task dashboards, prompt stash and continuation shortcuts,
|
|
113
111
|
filterable `@` file and agent references, composer undo, `Ctrl+G` external
|
|
114
112
|
editing, shared `/keybindings` creation/editing and supported-action remapping,
|
|
115
|
-
shared built-in and
|
|
113
|
+
shared built-in and custom `/theme` profiles with immediate
|
|
116
114
|
semantic recoloring, token editing/reset, deletion, and persisted syntax
|
|
117
115
|
toggles across transcript code and diff views,
|
|
118
116
|
shared runtime preferences for reduced motion, spinner tips, progress and
|
|
@@ -123,7 +121,9 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
|
123
121
|
`Ctrl+V` text/image clipboard paste, `Ctrl+Z` shell suspension and `fg`
|
|
124
122
|
recovery, permission-gated `!` shell turns, navigable current/per-turn Git
|
|
125
123
|
diff views, semantic plan/question decision panels with complete
|
|
126
|
-
screen-reader actions,
|
|
124
|
+
screen-reader actions, semantic screen projection across selectable surfaces,
|
|
125
|
+
deterministic resize-aware URL/form elicitation rendering, and measured
|
|
126
|
+
context budgets; print mode,
|
|
127
127
|
structured JSON/JSONL, context compaction, tool loops, and bounded execution.
|
|
128
128
|
- **Built-in tools** — read, write, edit, glob, search, shell, notebook, PDF,
|
|
129
129
|
image, web, scheduled prompts, workflows, and worktrees.
|
|
@@ -166,10 +166,14 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
|
166
166
|
and shutdown-drain budgets.
|
|
167
167
|
Child permissions can only tighten the parent; concurrent asks form one FIFO
|
|
168
168
|
Lead Decision queue with provenance. Coordinator leads are restricted to
|
|
169
|
-
orchestration, and custom Team agents receive no MCP capability.
|
|
170
|
-
|
|
169
|
+
orchestration, and custom Team agents receive no MCP capability. The native
|
|
170
|
+
CLI also exposes `praxis team status`, `logs`, and `attach` in human or JSON
|
|
171
|
+
form; durable-local attach does not require tmux. Native task, notification,
|
|
172
|
+
context, and Team resume/inbox seams are implemented with fail-closed
|
|
173
|
+
validation for unsupported payloads.
|
|
174
|
+
- **Native resource ecosystem** — shared Praxis instructions with recursive `@`
|
|
171
175
|
imports, memory, skills, commands, agents, hooks, settings, MCP servers,
|
|
172
|
-
plugins, and transcript
|
|
176
|
+
plugins, and append-only `praxis.transcript` JSONL sessions under `~/.praxis`.
|
|
173
177
|
- **Provider-neutral models** — native Anthropic Messages and OpenAI-compatible
|
|
174
178
|
streaming adapters with explicit capability checks and metering controls.
|
|
175
179
|
|
|
@@ -177,39 +181,6 @@ Detailed feature status and executable evidence live in the
|
|
|
177
181
|
[parity matrix](https://github.com/Forest-Isle/Praxis/blob/main/docs/PARITY_MATRIX.md),
|
|
178
182
|
not in this entry-point README.
|
|
179
183
|
|
|
180
|
-
## Claude Code interoperability
|
|
181
|
-
|
|
182
|
-
Praxis uses an independent local data plane by default:
|
|
183
|
-
|
|
184
|
-
```text
|
|
185
|
-
Praxis ─── ~/.praxis (or PRAXIS_HOME)
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Use `praxis --data-plane claude` when you need the legacy shared Claude Code
|
|
189
|
-
layout (`~/.claude` or `CLAUDE_CONFIG_DIR`). Praxis can resume Claude Code
|
|
190
|
-
sessions in that mode, and Claude Code can resume compatible sessions written
|
|
191
|
-
there. Every semver-like Claude Code producer version is
|
|
192
|
-
structurally validated and is read/write compatible when its entry shape is
|
|
193
|
-
supported; schema adapters are selected from transcript entry structure rather
|
|
194
|
-
than an installed or fixed producer version, and malformed or unsupported
|
|
195
|
-
shapes fail closed before any write. Each transcript record keeps its original
|
|
196
|
-
producer version, so supported shapes may be mixed across versions in one
|
|
197
|
-
session. Native fork creation is a separate restricted lossless copy path that
|
|
198
|
-
preserves each existing source record's producer version, so it can copy
|
|
199
|
-
specific black-box-verified foreign shapes such as the observed Claude Code
|
|
200
|
-
2.1.233 records; unsupported record shapes and unverified versions still fail
|
|
201
|
-
closed and remain read-only. Maintainers can prove mixed-version Claude JSONL interoperability with
|
|
202
|
-
`npm run test:cross-version-session-compat`, `test:cross-version-fork-compat`,
|
|
203
|
-
`test:cross-version-sidechain-compat`, `test:cross-version-compaction-compat`,
|
|
204
|
-
and `test:cross-version-resume-at-compat`, covering linear resume, native fork,
|
|
205
|
-
foreground sidechain, compaction, and `--resume-session-at` branch projection.
|
|
206
|
-
Each requires `PRAXIS_CLAUDE_BINARY` (Claude Code 2.1.208) and
|
|
207
|
-
`PRAXIS_CLAUDE_CROSS_VERSION_BINARY` (a different Claude Code version).
|
|
208
|
-
|
|
209
|
-
See the
|
|
210
|
-
[compatibility contract](https://github.com/Forest-Isle/Praxis/blob/main/docs/COMPATIBILITY.md)
|
|
211
|
-
for exact shared data, version boundaries, exclusions, and verification gates.
|
|
212
|
-
|
|
213
184
|
## Documentation
|
|
214
185
|
|
|
215
186
|
| Need | Document |
|
|
@@ -254,9 +225,16 @@ npm ci
|
|
|
254
225
|
npm run check
|
|
255
226
|
```
|
|
256
227
|
|
|
257
|
-
`npm run build:native` compiles the
|
|
258
|
-
|
|
228
|
+
`npm run build:native` compiles the Praxis-owned core, provider, native
|
|
229
|
+
transcript, and session profile.
|
|
230
|
+
`npm run test:native:deletion` adds an emitted-output deletion gate. These are
|
|
231
|
+
implemented profile checks, not qualification of the full native package.
|
|
232
|
+
`npm run test:performance` runs the native projection scaling and regression
|
|
233
|
+
budgets; the retained-render p95 budget remains 50 ms.
|
|
259
234
|
`npm run check` also enforces the corresponding source dependency direction.
|
|
235
|
+
`npm run test:core-completion` runs the 56-story #402 audit and reports
|
|
236
|
+
implemented, qualified, blocked, deferred, and out-of-scope states separately;
|
|
237
|
+
it never treats missing live prerequisites as a pass.
|
|
260
238
|
|
|
261
239
|
Contributions use Conventional Commit pull-request titles and the protected
|
|
262
240
|
squash-merge workflow. Read
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { isTerminalLifecycleState, } from '../core/agent-orchestration.js';
|
|
3
|
-
import { isClaudeAgentId } from '../compatibility/claude/sidechain.js';
|
|
4
3
|
const MAX_TIMEOUT_MS = 600_000;
|
|
5
4
|
const DEFAULT_CLOSE_DRAIN_MS = 5_000;
|
|
5
|
+
const NATIVE_AGENT_ID_PATTERN = /^a[0-9a-f]{16}$/u;
|
|
6
|
+
function isNativeAgentId(agentId) {
|
|
7
|
+
return NATIVE_AGENT_ID_PATTERN.test(agentId);
|
|
8
|
+
}
|
|
6
9
|
export class BackgroundAgentRunError extends Error {
|
|
7
10
|
result;
|
|
8
11
|
constructor(message, result, cause) {
|
|
@@ -37,7 +40,7 @@ function notificationWireStatus(status) {
|
|
|
37
40
|
return null;
|
|
38
41
|
}
|
|
39
42
|
function assertAgentId(agentId) {
|
|
40
|
-
if (!
|
|
43
|
+
if (!isNativeAgentId(agentId)) {
|
|
41
44
|
throw new Error(`Invalid background agent ID: ${agentId}`);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -625,7 +628,7 @@ export class BackgroundAgentManager {
|
|
|
625
628
|
return { task, created: true };
|
|
626
629
|
}
|
|
627
630
|
resolveOptional(identifier) {
|
|
628
|
-
if (
|
|
631
|
+
if (isNativeAgentId(identifier))
|
|
629
632
|
return identifier;
|
|
630
633
|
return this.names.get(identifier);
|
|
631
634
|
}
|
|
@@ -669,7 +672,7 @@ export class BackgroundAgentManager {
|
|
|
669
672
|
}
|
|
670
673
|
resolveRequired(identifier) {
|
|
671
674
|
const resolved = this.resolveOptional(identifier);
|
|
672
|
-
if (!
|
|
675
|
+
if (!isNativeAgentId(identifier) &&
|
|
673
676
|
!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u.test(identifier)) {
|
|
674
677
|
assertAgentId(identifier);
|
|
675
678
|
}
|
|
@@ -32,8 +32,8 @@ export interface BackgroundBashToolResult {
|
|
|
32
32
|
task?: Record<string, unknown>;
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
-
export declare function
|
|
36
|
-
export declare function
|
|
35
|
+
export declare function nativeBackgroundTaskParent(cwd: string): string;
|
|
36
|
+
export declare function nativeBackgroundTaskRoot(cwd: string, sessionId: string): string;
|
|
37
37
|
export declare class BackgroundBashManager {
|
|
38
38
|
private readonly options;
|
|
39
39
|
private readonly tasks;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { sanitizeProjectPath } from '../platform/project-path-key.js';
|
|
4
4
|
import { writeFileAtomically } from '../platform/atomic-write.js';
|
|
5
5
|
import { BoundedProcessRunner, } from '../platform/bounded-process-runner.js';
|
|
6
6
|
import { commandShell, commandShellArguments, } from '../platform/command-shell.js';
|
|
7
7
|
import { assertBackgroundBashTaskId, backgroundBashTaskIdFromStateFile, createBackgroundBashTaskId, } from './background-task-id.js';
|
|
8
|
-
export function
|
|
8
|
+
export function nativeBackgroundTaskParent(cwd) {
|
|
9
9
|
const uid = process.getuid?.() ?? 'unknown';
|
|
10
|
-
return resolve('/tmp', `
|
|
10
|
+
return resolve('/tmp', `praxis-${uid}`, sanitizeProjectPath(resolve(cwd)));
|
|
11
11
|
}
|
|
12
|
-
export function
|
|
13
|
-
return resolve(
|
|
12
|
+
export function nativeBackgroundTaskRoot(cwd, sessionId) {
|
|
13
|
+
return resolve(nativeBackgroundTaskParent(cwd), sessionId, 'tasks');
|
|
14
14
|
}
|
|
15
15
|
function parsePersistedTask(source, taskId, outputFile) {
|
|
16
16
|
let value;
|
|
@@ -65,7 +65,7 @@ export class BackgroundBashManager {
|
|
|
65
65
|
cwd: options.cwd,
|
|
66
66
|
maxOutputBytes: options.maxOutputBytes ?? 128 * 1024,
|
|
67
67
|
});
|
|
68
|
-
this.outputRoot =
|
|
68
|
+
this.outputRoot = nativeBackgroundTaskRoot(options.cwd, options.sessionId);
|
|
69
69
|
this.sessionStateRoot = resolve(options.stateRoot, options.sessionId);
|
|
70
70
|
}
|
|
71
71
|
has(taskId) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { lstat, readFile, readdir, realpath, rm } from 'node:fs/promises';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep, } from 'node:path';
|
|
4
|
-
import {
|
|
5
|
-
import { resolveClaudeProjectIdentity } from '../compatibility/claude/shared-resources.js';
|
|
4
|
+
import { isSessionId } from '../core/session.js';
|
|
6
5
|
import { writeFileAtomically } from '../platform/atomic-write.js';
|
|
6
|
+
import { resolveProjectIdentity } from '../platform/project-identity.js';
|
|
7
|
+
import { sanitizeProjectPath } from '../platform/project-path-key.js';
|
|
7
8
|
const MAX_ATOMIC_UPDATE_RETRIES = 8;
|
|
8
9
|
function errorCode(error) {
|
|
9
10
|
return error.code;
|
|
@@ -182,17 +183,17 @@ async function discoverSessionIds(projectRoot) {
|
|
|
182
183
|
for (const entry of entries) {
|
|
183
184
|
if (entry.isFile() && entry.name.endsWith('.jsonl')) {
|
|
184
185
|
const sessionId = entry.name.slice(0, -'.jsonl'.length);
|
|
185
|
-
if (
|
|
186
|
+
if (isSessionId(sessionId))
|
|
186
187
|
sessionIds.add(sessionId);
|
|
187
188
|
}
|
|
188
|
-
if (entry.isDirectory() &&
|
|
189
|
+
if (entry.isDirectory() && isSessionId(entry.name)) {
|
|
189
190
|
sessionIds.add(entry.name);
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
return [...sessionIds].sort();
|
|
193
194
|
}
|
|
194
|
-
async function discoverProjectRoots(configRoot, targetPaths
|
|
195
|
-
const projectsRoot = join(configRoot,
|
|
195
|
+
async function discoverProjectRoots(configRoot, targetPaths) {
|
|
196
|
+
const projectsRoot = join(configRoot, 'sessions');
|
|
196
197
|
if (!(await pathExists(projectsRoot)))
|
|
197
198
|
return [];
|
|
198
199
|
await assertSafePurgePath(configRoot, projectsRoot);
|
|
@@ -206,8 +207,8 @@ async function discoverProjectRoots(configRoot, targetPaths, dataPlane) {
|
|
|
206
207
|
}
|
|
207
208
|
throw error;
|
|
208
209
|
}
|
|
209
|
-
const targetKeys = targetPaths.map(
|
|
210
|
-
const worktreeSegment =
|
|
210
|
+
const targetKeys = targetPaths.map(sanitizeProjectPath);
|
|
211
|
+
const worktreeSegment = '--praxis-worktrees-';
|
|
211
212
|
return entries
|
|
212
213
|
.filter((entry) => targetKeys.some((targetKey) => entry.name === targetKey ||
|
|
213
214
|
entry.name.startsWith(`${targetKey}${worktreeSegment}`)))
|
|
@@ -231,32 +232,18 @@ async function addExistingPath(items, configRoot, item) {
|
|
|
231
232
|
items.push(item);
|
|
232
233
|
}
|
|
233
234
|
export async function planClaudeProjectPurge(options) {
|
|
235
|
+
void options.dataPlane;
|
|
234
236
|
if (options.all && options.path !== undefined) {
|
|
235
237
|
throw new Error('Cannot specify both a path and --all');
|
|
236
238
|
}
|
|
237
239
|
const configuredRoot = options.configRoot ??
|
|
238
|
-
(process.env.
|
|
240
|
+
(process.env.PRAXIS_HOME || join(homedir(), '.praxis'));
|
|
239
241
|
const configRoot = await canonicalPath(configuredRoot);
|
|
240
|
-
const
|
|
241
|
-
const homeDirectory = options.homeDirectory ?? homedir();
|
|
242
|
-
const legacyClaudeStatePath = resolve(homeDirectory, '.claude.json');
|
|
243
|
-
const legacyClaudeConfigRoot = await canonicalPath(resolve(homeDirectory, '.claude'));
|
|
244
|
-
const defaultStatePath = dataPlane === 'native'
|
|
245
|
-
? join(configRoot, 'state.json')
|
|
246
|
-
: options.configRoot !== undefined ||
|
|
247
|
-
Boolean(process.env.CLAUDE_CONFIG_DIR)
|
|
248
|
-
? join(configRoot, '.claude.json')
|
|
249
|
-
: legacyClaudeStatePath;
|
|
242
|
+
const defaultStatePath = join(configRoot, 'state.json');
|
|
250
243
|
const statePath = resolve(options.statePath ?? defaultStatePath);
|
|
251
|
-
const usesLegacyDefaultClaudeState = dataPlane === 'claude' &&
|
|
252
|
-
!process.env.CLAUDE_CONFIG_DIR &&
|
|
253
|
-
configRoot === legacyClaudeConfigRoot &&
|
|
254
|
-
statePath === legacyClaudeStatePath;
|
|
255
244
|
const canonicalStateParent = await canonicalPath(dirname(statePath));
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
await assertMutableRegularFile(statePath, usesLegacyDefaultClaudeState ? canonicalStateParent : configRoot);
|
|
245
|
+
assertLexicallyContained(configRoot, join(canonicalStateParent, basename(statePath)));
|
|
246
|
+
await assertMutableRegularFile(statePath, configRoot);
|
|
260
247
|
const state = parseState(await readOptionalFile(statePath), statePath);
|
|
261
248
|
const projects = stateProjects(state);
|
|
262
249
|
const items = [];
|
|
@@ -264,30 +251,22 @@ export async function planClaudeProjectPurge(options) {
|
|
|
264
251
|
const roots = [
|
|
265
252
|
{
|
|
266
253
|
kind: 'project',
|
|
267
|
-
name:
|
|
268
|
-
description:
|
|
269
|
-
|
|
270
|
-
|
|
254
|
+
name: 'sessions',
|
|
255
|
+
description: 'all project transcripts',
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
kind: 'memory',
|
|
259
|
+
name: 'memory',
|
|
260
|
+
description: 'all project memory',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
kind: 'scheduled',
|
|
264
|
+
name: 'scheduled',
|
|
265
|
+
description: 'all project scheduled prompts',
|
|
271
266
|
},
|
|
272
|
-
...(dataPlane === 'native'
|
|
273
|
-
? [
|
|
274
|
-
{
|
|
275
|
-
kind: 'memory',
|
|
276
|
-
name: 'memory',
|
|
277
|
-
description: 'all project memory',
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
kind: 'scheduled',
|
|
281
|
-
name: 'scheduled',
|
|
282
|
-
description: 'all project scheduled prompts',
|
|
283
|
-
},
|
|
284
|
-
]
|
|
285
|
-
: []),
|
|
286
267
|
{
|
|
287
268
|
kind: 'memory',
|
|
288
|
-
name:
|
|
289
|
-
? join('state', 'project-memory')
|
|
290
|
-
: join('praxis', 'project-memory'),
|
|
269
|
+
name: join('state', 'project-memory'),
|
|
291
270
|
description: 'all private Project-memory operational state',
|
|
292
271
|
},
|
|
293
272
|
{
|
|
@@ -330,9 +309,6 @@ export async function planClaudeProjectPurge(options) {
|
|
|
330
309
|
mode: 'all',
|
|
331
310
|
configRoot,
|
|
332
311
|
statePath,
|
|
333
|
-
...(usesLegacyDefaultClaudeState
|
|
334
|
-
? { allowStateOutsideConfigRoot: true }
|
|
335
|
-
: {}),
|
|
336
312
|
projectRootPaths: [],
|
|
337
313
|
sessionIds: [],
|
|
338
314
|
items,
|
|
@@ -341,10 +317,8 @@ export async function planClaudeProjectPurge(options) {
|
|
|
341
317
|
const requestedPath = resolve(options.path ?? options.cwd);
|
|
342
318
|
const targetPath = await canonicalPath(requestedPath);
|
|
343
319
|
const targetPaths = [...new Set([requestedPath, targetPath])];
|
|
344
|
-
const projectIdentity = await
|
|
345
|
-
|
|
346
|
-
});
|
|
347
|
-
const projectRootPaths = await discoverProjectRoots(configRoot, targetPaths, dataPlane);
|
|
320
|
+
const projectIdentity = await resolveProjectIdentity(targetPath);
|
|
321
|
+
const projectRootPaths = await discoverProjectRoots(configRoot, targetPaths);
|
|
348
322
|
const sessionIdSet = new Set();
|
|
349
323
|
for (const projectRoot of projectRootPaths) {
|
|
350
324
|
await assertSafePurgePath(configRoot, projectRoot);
|
|
@@ -359,26 +333,17 @@ export async function planClaudeProjectPurge(options) {
|
|
|
359
333
|
await addExistingPath(items, configRoot, removePathItem('file-history', join(configRoot, 'file-history', sessionId), `file edit history for session ${sessionId}`));
|
|
360
334
|
}
|
|
361
335
|
const projectKeys = new Set([
|
|
362
|
-
...targetPaths.map(
|
|
336
|
+
...targetPaths.map(sanitizeProjectPath),
|
|
363
337
|
...projectRootPaths.map((path) => basename(path)),
|
|
364
|
-
|
|
338
|
+
sanitizeProjectPath(projectIdentity),
|
|
365
339
|
]);
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
await addExistingPath(items, configRoot, removePathItem('scheduled', join(configRoot, 'scheduled', `${projectKey}.json`), `scheduled prompts for project ${projectKey}`));
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
for (const projectKey of projectKeys) {
|
|
375
|
-
await addExistingPath(items, configRoot, removePathItem('memory', join(configRoot, 'praxis', 'project-memory', projectKey), `private Project-memory state for project ${projectKey}`));
|
|
376
|
-
}
|
|
340
|
+
for (const projectKey of projectKeys) {
|
|
341
|
+
await addExistingPath(items, configRoot, removePathItem('memory', join(configRoot, 'memory', projectKey), `memory for project ${projectKey}`));
|
|
342
|
+
await addExistingPath(items, configRoot, removePathItem('memory', join(configRoot, 'state', 'project-memory', projectKey), `private Project-memory state for project ${projectKey}`));
|
|
343
|
+
await addExistingPath(items, configRoot, removePathItem('scheduled', join(configRoot, 'scheduled', `${projectKey}.json`), `scheduled prompts for project ${projectKey}`));
|
|
377
344
|
}
|
|
378
345
|
for (const projectRoot of projectRootPaths) {
|
|
379
|
-
await addExistingPath(items, configRoot, removePathItem('project', projectRoot,
|
|
380
|
-
? 'project transcripts'
|
|
381
|
-
: 'project transcripts and memory'));
|
|
346
|
+
await addExistingPath(items, configRoot, removePathItem('project', projectRoot, 'project transcripts'));
|
|
382
347
|
}
|
|
383
348
|
const historyPath = join(configRoot, 'history.jsonl');
|
|
384
349
|
const historyExists = await pathExists(historyPath);
|
|
@@ -420,9 +385,6 @@ export async function planClaudeProjectPurge(options) {
|
|
|
420
385
|
mode: 'project',
|
|
421
386
|
configRoot,
|
|
422
387
|
statePath,
|
|
423
|
-
...(usesLegacyDefaultClaudeState
|
|
424
|
-
? { allowStateOutsideConfigRoot: true }
|
|
425
|
-
: {}),
|
|
426
388
|
targetPath,
|
|
427
389
|
projectIdentity,
|
|
428
390
|
projectRootPaths,
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { ModelMessage, ModelToolCall, ToolExecutionResult } from '../core/runtime.js';
|
|
2
|
-
import type { TranscriptMessagesEvent } from '../core/transcript-event.js';
|
|
3
|
-
import type {
|
|
2
|
+
import type { TranscriptEvent, TranscriptMessagesEvent } from '../core/transcript-event.js';
|
|
3
|
+
import type { NativeTranscriptLease, NativeTranscriptLeaseResult } from '../persistence/native-transcript-store.js';
|
|
4
|
+
/** Minimal transcript-store contract required by the native session facade. */
|
|
5
|
+
export interface NativeSessionTranscriptStore {
|
|
6
|
+
withLease<T>(operation: (lease: NativeTranscriptLease) => Promise<T>): Promise<NativeTranscriptLeaseResult<T>>;
|
|
7
|
+
}
|
|
4
8
|
export type NativeTranscriptActivation = {
|
|
5
9
|
readonly kind: 'start';
|
|
6
10
|
} | {
|
|
@@ -19,6 +23,11 @@ export interface NativeCompactionAppend {
|
|
|
19
23
|
readonly postTokens: number;
|
|
20
24
|
readonly durationMs: number;
|
|
21
25
|
readonly preservedMessages?: readonly ModelMessage[];
|
|
26
|
+
/** Optional parent in the active branch when compacting a selected range. */
|
|
27
|
+
readonly logicalParentId?: string;
|
|
28
|
+
readonly direction?: 'from' | 'up_to';
|
|
29
|
+
readonly messagesSummarized?: number;
|
|
30
|
+
readonly preservePrefix?: boolean;
|
|
22
31
|
}
|
|
23
32
|
export type NativeInterruption = {
|
|
24
33
|
readonly kind: 'complete' | 'none';
|
|
@@ -35,6 +44,8 @@ export type NativeInterruption = {
|
|
|
35
44
|
readonly callIds: readonly string[];
|
|
36
45
|
};
|
|
37
46
|
export interface NativeSessionTranscriptLease {
|
|
47
|
+
/** Events on the currently selected active branch, in parent order. */
|
|
48
|
+
activeEvents(): TranscriptEvent[];
|
|
38
49
|
activeMessages(): ModelMessage[];
|
|
39
50
|
interruption(): NativeInterruption;
|
|
40
51
|
beginToolExecution(callId: string): Promise<void>;
|
|
@@ -56,7 +67,7 @@ export interface NativeForkOptions {
|
|
|
56
67
|
}
|
|
57
68
|
export interface NativeSessionTranscriptOptions {
|
|
58
69
|
readonly sessionId: string;
|
|
59
|
-
readonly store:
|
|
70
|
+
readonly store: NativeSessionTranscriptStore;
|
|
60
71
|
readonly createId?: () => string;
|
|
61
72
|
readonly now?: () => string;
|
|
62
73
|
}
|
|
@@ -83,6 +83,14 @@ export class NativeSessionTranscript {
|
|
|
83
83
|
const initial = prepared;
|
|
84
84
|
const currentId = selectedId ?? initial.records.at(-1)?.event.id ?? null;
|
|
85
85
|
const records = [...initial.records];
|
|
86
|
+
const usedIds = new Set(records.map((record) => record.event.id));
|
|
87
|
+
const createUniqueId = () => {
|
|
88
|
+
let id = this.createId();
|
|
89
|
+
while (usedIds.has(id))
|
|
90
|
+
id = this.createId();
|
|
91
|
+
usedIds.add(id);
|
|
92
|
+
return id;
|
|
93
|
+
};
|
|
86
94
|
let tail = currentId === null
|
|
87
95
|
? initial.tail
|
|
88
96
|
: { ...initial.tail, branchParentId: currentId };
|
|
@@ -94,6 +102,7 @@ export class NativeSessionTranscript {
|
|
|
94
102
|
return result;
|
|
95
103
|
};
|
|
96
104
|
const lease = {
|
|
105
|
+
activeEvents: () => activeEvents(records.map((record) => record.event), activeId ?? undefined).slice(),
|
|
97
106
|
activeMessages: () => projectActiveMessages(records.map((record) => record.event), activeId ?? undefined).slice(),
|
|
98
107
|
interruption: () => {
|
|
99
108
|
const events = activeEvents(records.map((record) => record.event), activeId ?? undefined);
|
|
@@ -166,7 +175,7 @@ export class NativeSessionTranscript {
|
|
|
166
175
|
throw new Error(`Native tool call already claimed: ${callId}`);
|
|
167
176
|
const event = {
|
|
168
177
|
kind: 'tool-execution-started',
|
|
169
|
-
id:
|
|
178
|
+
id: createUniqueId(),
|
|
170
179
|
parentId: activeId,
|
|
171
180
|
sessionId: this.sessionId,
|
|
172
181
|
timestamp: this.now(),
|
|
@@ -196,7 +205,7 @@ export class NativeSessionTranscript {
|
|
|
196
205
|
throw new Error(`Native tool call is already resolved: ${callId}`);
|
|
197
206
|
const event = {
|
|
198
207
|
kind: 'messages',
|
|
199
|
-
id:
|
|
208
|
+
id: createUniqueId(),
|
|
200
209
|
parentId: activeId,
|
|
201
210
|
sessionId: this.sessionId,
|
|
202
211
|
timestamp: this.now(),
|
|
@@ -232,7 +241,7 @@ export class NativeSessionTranscript {
|
|
|
232
241
|
throw new Error('native transcript cannot append empty messages');
|
|
233
242
|
const event = {
|
|
234
243
|
kind: 'messages',
|
|
235
|
-
id:
|
|
244
|
+
id: createUniqueId(),
|
|
236
245
|
parentId: activeId,
|
|
237
246
|
sessionId: this.sessionId,
|
|
238
247
|
timestamp: this.now(),
|
|
@@ -266,19 +275,28 @@ export class NativeSessionTranscript {
|
|
|
266
275
|
const events = records.map((record) => record.event);
|
|
267
276
|
if (unresolvedActiveToolCallIds(projectActiveMessages(events, activeId)).length > 0)
|
|
268
277
|
throw new Error('Cannot compact a native transcript with unresolved tool calls');
|
|
269
|
-
const boundaryId =
|
|
270
|
-
const summaryId =
|
|
278
|
+
const boundaryId = createUniqueId();
|
|
279
|
+
const summaryId = createUniqueId();
|
|
271
280
|
const boundary = {
|
|
272
281
|
kind: 'context-boundary',
|
|
273
282
|
id: boundaryId,
|
|
274
283
|
parentId: null,
|
|
275
284
|
sessionId: this.sessionId,
|
|
276
285
|
timestamp: this.now(),
|
|
277
|
-
logicalParentId: activeId,
|
|
286
|
+
logicalParentId: input.logicalParentId ?? activeId,
|
|
278
287
|
trigger: input.trigger,
|
|
279
288
|
preTokens: input.preTokens,
|
|
280
289
|
postTokens: input.postTokens,
|
|
281
290
|
durationMs: input.durationMs,
|
|
291
|
+
...(input.direction === undefined
|
|
292
|
+
? {}
|
|
293
|
+
: { direction: input.direction }),
|
|
294
|
+
...(input.messagesSummarized === undefined
|
|
295
|
+
? {}
|
|
296
|
+
: { messagesSummarized: input.messagesSummarized }),
|
|
297
|
+
...(input.preservePrefix === undefined
|
|
298
|
+
? {}
|
|
299
|
+
: { preservePrefix: input.preservePrefix }),
|
|
282
300
|
};
|
|
283
301
|
const summary = {
|
|
284
302
|
kind: 'context-summary',
|
|
@@ -294,9 +312,12 @@ export class NativeSessionTranscript {
|
|
|
294
312
|
if (message.role !== 'assistant')
|
|
295
313
|
continue;
|
|
296
314
|
for (const call of message.toolCalls ?? [])
|
|
297
|
-
replayToolCallIds.set(call.id,
|
|
315
|
+
replayToolCallIds.set(call.id, createUniqueId());
|
|
298
316
|
}
|
|
299
|
-
const replaySuffix = suffix
|
|
317
|
+
const replaySuffix = suffix
|
|
318
|
+
.filter((message) => message.role !== 'tool' ||
|
|
319
|
+
replayToolCallIds.has(message.toolCallId))
|
|
320
|
+
.map((message) => {
|
|
300
321
|
if (message.role === 'assistant')
|
|
301
322
|
return {
|
|
302
323
|
...message,
|
|
@@ -320,7 +341,7 @@ export class NativeSessionTranscript {
|
|
|
320
341
|
const suffixEvent = replaySuffix.length
|
|
321
342
|
? {
|
|
322
343
|
kind: 'messages',
|
|
323
|
-
id:
|
|
344
|
+
id: createUniqueId(),
|
|
324
345
|
parentId: summaryId,
|
|
325
346
|
sessionId: this.sessionId,
|
|
326
347
|
timestamp: this.now(),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type NativeScheduledTask } from '../persistence/native-scheduled-task-store.js';
|
|
2
2
|
export declare const MAX_JOBS = 50;
|
|
3
3
|
export declare class ScheduledJobLimitError extends Error {
|
|
4
4
|
readonly maxJobs: number;
|
|
@@ -24,7 +24,7 @@ export interface ScheduledPrompt {
|
|
|
24
24
|
id: string;
|
|
25
25
|
prompt: string;
|
|
26
26
|
}
|
|
27
|
-
export interface ListedScheduledPrompt extends
|
|
27
|
+
export interface ListedScheduledPrompt extends NativeScheduledTask {
|
|
28
28
|
durable: boolean;
|
|
29
29
|
}
|
|
30
30
|
export interface DynamicWakeupResult {
|
|
@@ -2,7 +2,7 @@ import { execFile } from 'node:child_process';
|
|
|
2
2
|
import { randomBytes } from 'node:crypto';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { CronExpressionParser } from 'cron-parser';
|
|
5
|
-
import {
|
|
5
|
+
import { NativeScheduledTaskLimitError, NativeScheduledTaskStore, } from '../persistence/native-scheduled-task-store.js';
|
|
6
6
|
const execFileAsync = promisify(execFile);
|
|
7
7
|
const RECURRING_LIFETIME_MS = 7 * 24 * 60 * 60 * 1_000;
|
|
8
8
|
const MIN_DYNAMIC_WAKEUP_SECONDS = 60;
|
|
@@ -111,7 +111,7 @@ export class ScheduledPromptManager {
|
|
|
111
111
|
initialization;
|
|
112
112
|
closed = false;
|
|
113
113
|
constructor(options) {
|
|
114
|
-
this.store = new
|
|
114
|
+
this.store = new NativeScheduledTaskStore({
|
|
115
115
|
filePath: options.filePath,
|
|
116
116
|
lockFile: options.lockFile,
|
|
117
117
|
});
|
|
@@ -145,7 +145,7 @@ export class ScheduledPromptManager {
|
|
|
145
145
|
task = await this.store.create(base, { maxJobs: MAX_JOBS });
|
|
146
146
|
}
|
|
147
147
|
catch (error) {
|
|
148
|
-
if (error instanceof
|
|
148
|
+
if (error instanceof NativeScheduledTaskLimitError) {
|
|
149
149
|
throw new ScheduledJobLimitError(MAX_JOBS);
|
|
150
150
|
}
|
|
151
151
|
throw error;
|
|
@@ -34,11 +34,8 @@ export interface SessionMemoryStoreOptions {
|
|
|
34
34
|
sidecarRoot?: string;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Durable sidecar for one session's extracted memory.
|
|
38
|
-
*
|
|
39
|
-
* select another data plane with
|
|
40
|
-
* `<sidecarRoot>/session-memory/<sessionId>/` (for example, native
|
|
41
|
-
* `<configRoot>/state/session-memory/<sessionId>/`). All writes are atomic
|
|
37
|
+
* Durable sidecar for one session's extracted memory. Native callers place it
|
|
38
|
+
* under `<configRoot>/state/session-memory/<sessionId>/`. All writes are atomic
|
|
42
39
|
* (same-directory temp file, fsync, then rename) and version-checked. Never
|
|
43
40
|
* touches shared Claude transcript entries.
|
|
44
41
|
*/
|