@gajae-code/coding-agent 0.13.0 → 0.13.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.
- package/CHANGELOG.md +18 -0
- package/dist/types/config/file-lock.d.ts +2 -0
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/models-config-schema.d.ts +6 -0
- package/dist/types/config/settings-schema.d.ts +17 -5
- package/dist/types/config/settings.d.ts +10 -1
- package/dist/types/edit/streaming.d.ts +5 -5
- package/dist/types/eval/py/kernel.d.ts +2 -2
- package/dist/types/eval/py/runtime.d.ts +5 -1
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +3 -1
- package/dist/types/modes/components/model-selector.d.ts +3 -2
- package/dist/types/runtime/process-lifecycle.d.ts +12 -31
- package/dist/types/sdk/broker/identity.d.ts +2 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +17 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +11 -6
- package/dist/types/sdk/broker/startup-failure.d.ts +32 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +4 -0
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +10 -1
- package/dist/types/sdk/bus/reconciliation-store.d.ts +2 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -2
- package/dist/types/sdk/bus/telegram-daemon.d.ts +17 -1
- package/dist/types/sdk/host/query/cursor.d.ts +4 -0
- package/dist/types/sdk/host/query/handlers.d.ts +6 -0
- package/dist/types/sdk/host/session-runtime.d.ts +7 -6
- package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/turn-result.d.ts +37 -0
- package/dist/types/session/agent-session.d.ts +8 -11
- package/dist/types/session/blob-store.d.ts +6 -3
- package/dist/types/slash-commands/helpers/fast-status-report.d.ts +12 -3
- package/dist/types/task/executor.d.ts +4 -7
- package/dist/types/tools/index.d.ts +1 -1
- package/dist/types/tools/read.d.ts +1 -1
- package/dist/types/tools/search.d.ts +1 -1
- package/dist/types/utils/edit-mode.d.ts +69 -0
- package/package.json +8 -8
- package/scripts/generate-hotkeys-docs.ts +8 -6
- package/src/commands/sdk.ts +23 -2
- package/src/config/file-lock.ts +25 -5
- package/src/config/keybindings.ts +4 -2
- package/src/config/model-registry.ts +20 -0
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +29 -22
- package/src/config/settings.ts +42 -10
- package/src/coordinator-mcp/server.ts +84 -106
- package/src/edit/index.ts +5 -19
- package/src/edit/renderer.ts +3 -2
- package/src/edit/streaming.ts +28 -15
- package/src/eval/py/executor.ts +108 -10
- package/src/eval/py/kernel.ts +86 -12
- package/src/eval/py/runtime.ts +200 -16
- package/src/exec/bash-executor.ts +36 -37
- package/src/gjc-runtime/gc-runtime.ts +25 -3
- package/src/gjc-runtime/managed-owner-supervisor.ts +27 -1
- package/src/gjc-runtime/session-state-sidecar.ts +110 -4
- package/src/gjc-runtime/tmux-sessions.ts +34 -5
- package/src/internal-urls/docs-index.generated.ts +6 -6
- package/src/modes/acp/acp-agent.ts +10 -2
- package/src/modes/components/model-selector.ts +28 -8
- package/src/modes/controllers/plan-mode-controller.ts +3 -3
- package/src/modes/controllers/selector-controller.ts +4 -2
- package/src/runtime/process-lifecycle.ts +126 -27
- package/src/runtime-mcp/transports/stdio.ts +11 -6
- package/src/sdk/acp/adapter.ts +18 -10
- package/src/sdk/broker/broker.ts +55 -4
- package/src/sdk/broker/ensure.ts +10 -7
- package/src/sdk/broker/identity.ts +10 -0
- package/src/sdk/broker/lifecycle-ledger.ts +56 -6
- package/src/sdk/broker/lifecycle.ts +53 -10
- package/src/sdk/broker/session-index.ts +28 -11
- package/src/sdk/broker/startup-failure.ts +101 -0
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +4 -3
- package/src/sdk/bus/chat-daemon-runtime.ts +8 -1
- package/src/sdk/bus/conversation-store.ts +171 -50
- package/src/sdk/bus/index.ts +101 -47
- package/src/sdk/bus/kind-aware-reconciliation.ts +52 -2
- package/src/sdk/bus/notification-service.ts +3 -3
- package/src/sdk/bus/reconciliation-store.ts +16 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +11 -2
- package/src/sdk/bus/telegram-daemon.ts +131 -29
- package/src/sdk/bus/topic-registry.ts +38 -9
- package/src/sdk/cli/session-cli.ts +20 -7
- package/src/sdk/client/discovery.ts +23 -2
- package/src/sdk/host/query/cursor.ts +4 -0
- package/src/sdk/host/query/handlers.ts +99 -100
- package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
- package/src/sdk/host/session-runtime.test.ts +98 -1
- package/src/sdk/host/session-runtime.ts +57 -15
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +192 -2
- package/src/sdk/host/websocket-transport.ts +54 -30
- package/src/sdk/index.ts +1 -0
- package/src/sdk/mcp/server.ts +19 -6
- package/src/sdk/protocol/operation-inventory.generated.json +1 -1
- package/src/sdk/protocol/operation-registry.ts +8 -12
- package/src/sdk/session.ts +5 -14
- package/src/sdk/turn-result.ts +53 -0
- package/src/session/agent-session.ts +112 -69
- package/src/session/blob-store.ts +91 -21
- package/src/session/session-manager.ts +408 -81
- package/src/session/session-storage.ts +68 -10
- package/src/slash-commands/helpers/fast-status-report.ts +24 -8
- package/src/task/executor.ts +25 -8
- package/src/task/index.ts +0 -2
- package/src/tools/index.ts +1 -1
- package/src/tools/read.ts +12 -11
- package/src/tools/search.ts +7 -7
- package/src/utils/edit-mode.ts +180 -9
- package/src/web/search/providers/insane.ts +55 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,24 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.13.1] - 2026-08-11
|
|
6
|
+
|
|
5
7
|
### Added
|
|
6
8
|
- `/model <preset>` and `/model gajae-code/<preset>` now activate a known model profile immediately instead of failing with "Unknown model". Unknown names still fall through to model resolution, and `/model <role> <preset>` keeps assigning a model to the named role.
|
|
7
9
|
- Browser `act` and `run` responses can now surface an opt-in (`open(..., { diagnostics: true })`), bounded mailbox of page exceptions and `console.error` metadata. Entries carry only kind, timestamp, origin-only URL, line/column, and an allowlisted built-in error class; path segments, query strings, messages, arguments, values, and stacks are never retained. Serialization is byte-bounded with an explicit truncation marker.
|
|
8
10
|
- A generated, host-neutral `sdk-skills/` bundle now provides namespaced external-agent skills for direct GJC SDK session discovery, approved trusted-local operations, and TypeScript/Python script authoring, with deterministic drift checks and credential-safe fail-closed templates. The bundle carries a versioned `manifest.json` (format version 1) so installed bundles fail closed on missing or unsupported layouts, and the skill prompts are authored as static Markdown sources under `scripts/gjc-sdk-skills/prompts/` that the generator copies and validates.
|
|
9
11
|
- `GJC_SESSION_CONTEXT_BUDGET_BYTES` now overrides the synchronous session-context materialization budget that backs `SessionContextTooLargeError` (previously hardcoded to 64 MiB, now a 512 MiB default). The override parses fail-closed: only a canonical positive-integer value is honored, while empty, non-numeric, negative, zero, safe-integer-overflowing, or above-ceiling (8 GiB) values fall back to the 512 MiB default with a warning, so a malformed value can never silently raise or lower the memory guard. Raise it above your measured session size to suppress the preflight, or lower it to restore the old tight bound.
|
|
12
|
+
- Custom OpenAI-compatible providers can opt into `/fast` forwarding with `compat.supportsServiceTier: true`; first-class OpenCodex discovery enables it automatically so client `service_tier: "priority"` reaches an OpenCodex proxy running in passthrough (`Auto`) mode.
|
|
10
13
|
|
|
11
14
|
### Fixed
|
|
15
|
+
- A just-created or just-registered SDK session no longer reads as not-live (failing immediate `session.close`/`session.delete`, endpoint resolution, and chat-daemon attachment) for up to one heartbeat interval: the host-written registration now counts as initial liveness evidence, aging out exactly like a heartbeat, with the OS process-incarnation match still required. The broker's shutdown-escalation identity proof also accepts the incarnation the index auto-stamps at registration, and ACP `session/list` no longer advertises or re-adopts closed/unregistered (DR-1 terminal) rows — repeated ACP deletes answer already-gone instead of escalating against a host that no longer exists.
|
|
16
|
+
- Insane public-route search now cancels and rejects response bodies larger than 1 MiB instead of buffering unbounded feed, HTML, or JSON payloads.
|
|
17
|
+
- The Telegram notification daemon no longer terminates with an uncaught `EPERM` when publishing its heartbeat sidecar while an external Windows file lock (antivirus, indexer) briefly holds the destination. The rename is retried a bounded number of times under the ownership-lock fence, a still-failing publication is contained as a diagnostic-logged transient (the next heartbeat cycle republishes), and only a proven ownership loss stops the daemon; the stale-writer fence and staging-temp cleanup are preserved on every path (#4200).
|
|
18
|
+
- `/fast` status, model badges, and task/subagent badges no longer show `⚡` for providers that silently drop unscoped priority intent. Indicators now follow wire-effective built-in support or an explicit `compat.supportsServiceTier` capability instead of treating every provider as fast-capable.
|
|
19
|
+
- The broker's dead-registration sweep now requires positive proof of host death (ESRCH, or a readable OS process incarnation that differs from the recorded one) before unregistering a session. Under heartbeat-based liveness a registered host whose heartbeat had not yet been checkpointed read as not-live and could be reaped while still running; a stale or missing heartbeat is no longer grounds for a reap, and terminal registrations are never re-reaped.
|
|
12
20
|
- Option+Q verification now supports normal macOS Terminal.app profiles and fails with an actionable Settings > Profiles > Keyboard > Use Option as Meta key diagnostic when the profile cannot forward Option as Meta/Esc.
|
|
13
21
|
- Enabling Speech-to-Text from `/settings` now checks and configures its local dependencies immediately instead of deferring setup until the first recording. Setup progress is shown in the status line; failures disable STT again rather than leaving an unusable enabled toggle. Setup also reports platform-correct recorder commands, detects Ghostty's `macos-option-as-alt` requirement, and documents the Ctrl+P command-palette fallback, permissions, models, troubleshooting, and remapping.
|
|
14
22
|
- Queued-message selection now accepts the actual macOS Terminal.app Option+Up/Down byte sequence from either physical Option key, enabling multi-message restore, delete, and reorder flows.
|
|
15
23
|
- Keybinding configuration now normalizes `option`/`meta` to Option and `command`/`cmd` to Command, while Terminal.app guidance covers both physical Option keys and explicit Command profile mappings.
|
|
16
24
|
- ACP prompts now settle when a terminal frame arrives before prompt acknowledgement with correlation split between the frame envelope and event payload. Live and deferred frames share strict ownership derivation, correlated nonterminals wait for exact acknowledgement ownership, and watchdog or cancel settlement no longer waits for a missing acknowledgement. Incomplete or foreign terminals emit structured error logs, unrelated session traffic cannot keep a wedged turn alive, and correlationless session events remain publishable without contaminating prompt-owned final-text state. Deferred terminal replay failures are contained by the session frame queue.
|
|
25
|
+
- Closing a managed session no longer crashes the process when its cold-history sidecar resident-cache directory has already been removed. `SessionManager.close()` released the sidecar cache through an unguarded `dispose()`, so a `ResidentCacheTrustError` escaped teardown as an unhandled rejection (`directory_unverifiable`) and took down the CLI. Disposing an instance directory that no longer exists is now a completed disposal rather than a trust violation — a present-but-untrusted directory still fails closed — and sidecar release both clears its state before disposing and downgrades any remaining trust failure to a warning, matching every other resident-store disposal site.
|
|
17
26
|
- `bun run restart:sdk-broker --close-session-hosts` no longer fails against session hosts whose workspace was deleted while they kept running. The teardown fence proved a pid's identity only from the spawn-time marker inside the session's own workspace state root, so deleting that workspace (a removed worktree, a cleaned scratch directory) destroyed the only evidence the broker would accept: `session.close` answered `close_refused` forever, the host stayed resident serving the source it started with, and every restart exited non-zero naming the same unkillable orphans. Hosts now publish their OS start incarnation into the broker-owned session index at registration — and reconciliation preserves it — so the pid stays provable after its workspace is gone, while a marker naming a different process still refuses the signal and an incarnation that no longer matches the live pid still fails closed. A host that dies before withdrawing its own registration is now retired by the broker on the same evidence its dead-registration sweep already uses, so a completed teardown is reported as one instead of surfacing as `endpoint_stale` or `terminal_uncertain`.
|
|
18
27
|
- Bounded cold-session resume now uses automatic size routing, keeps ordinary sessions eager, admits two-GiB transcripts with fork-header headroom, and reduces first-open work with reusable scanning, buffered sidecar writes, pressure-based GC, one full transcript JSON pass plus a bounded authenticated suffix read, owner-bound concurrent publication, fail-closed post-admission tamper handling, deferred secondary artifacts, and split reservation/residency/disk accounting.
|
|
19
28
|
- Session resume entrypoints now share size-aware bounded admission without weakening strict small-session validation, and hard-link fallback cleanup uses identity-bound native retirement instead of a pathname `lstat`/`unlink` pair.
|
|
20
29
|
- OpenCode Go Responses completions that carry a response id but no output items or token usage are now treated as typed retryable failures instead of successful turns; untyped proxy empty responses retain the existing context-overflow promotion and compaction path.
|
|
21
30
|
- Memory-pressure sweeps now request asynchronous garbage collection instead of forcing a stop-the-world collection on the main event loop, preventing periodic input and rendering stalls under the opt-in memory guard.
|
|
22
31
|
- `gjc gc --disk --prune` now fences the blob mark/sweep so a session transcript that keeps changing under the mark can never cause unsafe reclamation: each transcript's references are bound to a stat snapshot taken before and after its read, the store must be observed completely quiet across a quiescence window before the sweep may act, and the fence is re-verified immediately before every removal. A store that still moves withholds the sweep with `keep:withheld_evidence_incomplete: sessions_changed_during_mark` instead of reclaiming on evidence it could not prove stable (#4158).
|
|
32
|
+
- Concurrent interactive launches now atomically publish mode-600 core SDK discovery even when notification-daemon ownership is blocked, retry failed notification readiness without republishing the SDK endpoint, wait through bounded session-index contention with dead-owner recovery, and recover exact tmux-owner cleanup from competing valid terminal-verdict publishers.
|
|
23
33
|
- Follow-up queue auto-continuation now waits for compaction and foreground bash/eval work to settle, preventing queued prompts from starting a model turn concurrently with those operations.
|
|
24
34
|
- Scheduled continuations no longer route through `continueQueuedMessages()` merely because the last message is a non-assistant execution tail. The queue-consuming continuation is now used only for the explicit follow-up/steer drains (post-execution settlement, auto-compaction `queued_continue` recovery, and user-interrupt steering), so retry, fallback, auto-compaction, deep-interview, active-goal, TTSR, and reminder continuations keep `continue()` semantics and no longer fail with "No queued messages to continue" when no prompt is queued.
|
|
25
35
|
- Follow-up queue submissions now defer slash/skill text during foreground bash/eval work instead of invoking a competing custom-message turn.
|
|
@@ -31,12 +41,15 @@
|
|
|
31
41
|
- Read-tool code summarization and ZIP extraction now run asynchronously instead of blocking the TUI event loop during structural parsing or decompression.
|
|
32
42
|
- `secrets.yml` entries with `mode: "replace"` and no explicit `replacement` now derive their substitute from a keyed, domain-separated HMAC-SHA256 construction over the process key instead of an unkeyed public `Bun.hash`. Derived replacements are no longer confirmable offline without the key (issue #4166); same-process determinism, same-length output, and alphanumeric character behavior are preserved, and explicit `replacement` values are unchanged. Note: derived replacements differ across processes/key rotations — set an explicit `replacement` when a stable value is required.
|
|
33
43
|
- Managed scope preparation now reaps scrubbed write-protocol remnants. The POSIX exact-unlink fallback detaches and scrubs but never deletes, and macOS has no retained directory authority to complete deletion, so every managed replacement leaked zero-length `.gjc-exact-unlink-placeholder-*`, `.gjc-receipt-remove-*`, and `.gjc-exact-replace-destination-*` entries; scope directories grew without bound (observed at 83k dirents), degrading every per-mutation receipt scan and widening the quarantine-collision window behind intermittent `Could not prepare managed session scope (binding_invalid: prepare:binding_publish)` launch crashes. Preparation now removes zero-length, single-link remnants older than 15 minutes; non-zero displaced predecessors and detached receipts are retained as evidence, and in-flight protocol steps are protected by the age gate.
|
|
44
|
+
- Conversation store file locks now publish complete, synced metadata atomically and release idempotently: failed lock construction cleans its pending artifact, release cleanup is ownership-checked, and recovery reclaims only stale locks or provably abandoned locks from the same process isolate. Empty, malformed, and unproven legacy markers fail closed at the normal timeout; concurrent healers and predecessors cannot delete a successor lock.
|
|
45
|
+
- Owned subprocess teardown now recognizes zombie-only Linux process groups without consuming its grace window, while failing closed on unreadable `/proc` evidence, guarding recycled process-group leaders with their spawn-time identity, and reporting an explicit incomplete-teardown outcome to MCP stdio callers. Recycled-leader guarding applies only where that identity is readable (`/proc`); on macOS and other POSIX platforms teardown still signals the owned group instead of refusing it as unverifiable.
|
|
34
46
|
|
|
35
47
|
### Added
|
|
36
48
|
- `gjc setup provider` now ships parameterized proxy presets: `--preset litellm` and `--preset openai-compatible-proxy` (aliases `litellm-proxy`, `openai-proxy`, `compatible-proxy`, `custom-proxy`) with a required `--base-url`, configurable `--api-key-env`, and live model discovery (#4123).
|
|
37
49
|
- New `modelProfile.proxyProvider` and `modelProfile.proxyMode` settings route built-in model-preset selectors through an authenticated OpenAI-compatible proxy (e.g. `xai/grok-4.3` → `litellm/xai/grok-4.3`). `fallback` preserves directly authenticated providers by default; `always` forces every proxy-routable built-in selector through the configured gateway. Routing fails closed for unconfigured or unauthenticated proxies and missing or ambiguous proxy models (#4123).
|
|
38
50
|
- SDK-only session hosts now publish their session ID and register their endpoint lifecycle with the broker, matching its identity and staleness fences. This restores broker/coordinator resolution for durable workflow-gate controls (`workflow.gates.list` and `workflow.gate_answer`) without relying on tmux pane input; broker unavailability leaves non-lifecycle local hosts usable and retries publication later.
|
|
39
51
|
|
|
52
|
+
- Python eval now settles managed-runtime provisioning before cancellation, retires cancelled initialization without sharing it with successors, and retains late kernels whose shutdown is unconfirmed for postmortem retry.
|
|
40
53
|
## [0.12.21] - 2026-08-09
|
|
41
54
|
|
|
42
55
|
### Fixed
|
|
@@ -63,6 +76,8 @@
|
|
|
63
76
|
|
|
64
77
|
- Attached image placeholders such as `[image 1]`, including the `[image N] source="…"` pasted-path reference form, are now deleted atomically with Backspace when the cursor sits at the placeholder boundary or the end of the full reference, instead of being erased one character at a time.
|
|
65
78
|
- Root CLI help and shell completion now share the launch flag table instead of maintaining divergent copies, advertise the working `--fork` and `--worktree` options, omit retired extension/skill flags, and reject unknown options instead of silently dropping typos (#4023).
|
|
79
|
+
- SDK broker startup diagnostics (#3963): a detached broker that exits before publishing discovery now writes a durable bounded startup-failure marker under `sdk/`, and the caller surfaces a typed `broker_startup_failed` error carrying the exit code, reason, and a bounded stderr excerpt instead of a bare `code=0`.
|
|
80
|
+
- Image paste now defaults to Ctrl+V before Command+V on macOS (where terminals commonly consume Command+V), while Windows also accepts Ctrl+V and Alt+V; generated hotkey guidance reflects every platform chord.
|
|
66
81
|
|
|
67
82
|
### Added
|
|
68
83
|
- Added a deterministic quick-lane task classifier (`classifyQuickLane`) exposed through a read-only `gjc quick-lane classify` command. It is an auditable classification surface that performs no routing and is NOT wired into runtime routing: it only prints whether a task request carries quick-lane eligibility signals (explicit file paths, issue/PR numbers, named symbols, explicit tests, numbered steps, acceptance criteria, error references, code blocks, or an explicit `force:`/`!` override) or deep-lane exclusions (vague, ambiguous, exploratory, risk-sensitive, or multi-file/cross-contract scope), and it never alters deep-path defaults. The classifier is deterministic and fail-closed: any exclusion forces the deep lane even when a concrete anchor is present. The #3984 routing decision remains open.
|
|
@@ -102,6 +117,7 @@
|
|
|
102
117
|
- Edit cards now keep live calls concise when collapsed and show per-file results, diff statistics, diagnostics availability, and full details consistently when expanded.
|
|
103
118
|
|
|
104
119
|
### Fixed
|
|
120
|
+
- SDK turn-result reconciliation now has one canonical content-bearing query with durable, UTF-8-safe bounded (16 KiB) terminal content. Prompt and skill terminal results remain correlated to their exact invocation and survive restart without retaining process-local revisions or cursors. Cursored continuation was removed as unreachable: the bounded content cap is well under both the response ceiling and the page target, so no revision is ever created; cursors are now rejected upfront instead of advertising a dead continuation path. Legacy status aliases delegate to the same authority, while provider query IDs and adapter dispositions remain unchanged.
|
|
105
121
|
|
|
106
122
|
- SDK snapshot shutdown now reserves a revision write synchronously before any asynchronous serialization work, so an immediate `close()` cannot begin terminal cleanup ahead of an in-progress spill write under heavily contended CI scheduling. The coordinator owner-intent negative matrix also receives the same 30-second contention budget used by other filesystem-backed integration cases; its assertions and four-case coverage are unchanged.
|
|
107
123
|
- Provider-agnostic preset ranking now uses AuthStorage's effective selectable credential type. Unusable stored command keys no longer misclassify OAuth-backed providers, and session-selected OAuth, fail-closed selectors, blocked/expired OAuth retry, and `openai-codex-device` aliases now follow the same precedence and normalization as request dispatch.
|
|
@@ -137,6 +153,8 @@
|
|
|
137
153
|
- Codex GPT-5.6 OAuth context-window overrides are honored instead of silently re-clamped: explicit `modelOverrides.<id>.contextWindow` values survive the bundled 372K cap when positive and finite, non-positive values are ignored with a warning, and the precedence/fallback contract is codified in the Codex context-cap policy (#3987).
|
|
138
154
|
|
|
139
155
|
### Changed
|
|
156
|
+
- `edit.mode` now defaults to `auto`: the edit protocol is routed by the active model's family (GPT/Codex → `apply_patch`; Claude/DeepSeek/Qwen → `replace`; MiniMax/GLM/Kimi/Moonshot and unknown models → `hashline`), independent of which provider serves the model. Resolution precedence is `GJC_EDIT_VARIANT`/`PI_EDIT_VARIANT` env force, then a matching `edit.modelVariants` rule, then explicit non-`auto` `edit.mode`, then a model-catalog edit recommendation when the session exposes one, then the built-in family mapping, then the `hashline` fallback. Invalid forced env values fail fast and a matched-but-invalid `edit.modelVariants` value fails closed with a diagnostic instead of silently falling through. Persisted explicit `edit.mode` values and the `atom` → `hashline` migration are unchanged; `resolveEditModeDetails()` exposes the resolved mode with provenance (source, model, family, matched rule).
|
|
157
|
+
- Because `read`/`search` emit hash-line anchors and default line numbers only in `hashline` mode, `edit.mode: auto` now routes those display surfaces with the edit protocol: GPT/Codex (`apply_patch`) and Claude/DeepSeek/Qwen (`replace`) sessions no longer show hash anchors or line numbers in `read`/`search` output unless `readLineNumbers: true` is configured, while MiniMax/GLM/Kimi/Moonshot and unknown models keep the hashline display. `GJC_EDIT_VARIANT=hashline` restores the previous hashline read/search display exactly.
|
|
140
158
|
|
|
141
159
|
- Workflow skills are no longer implicitly auto-routed. The UserPromptSubmit keyword autoroute now matches only explicit `$`-prefixed tokens (`$deep-interview`, `$ralplan`, `$ultragoal`, `$team`); natural-language phrases ("don't assume", "consensus plan", "interview me", "coordinated team") and bare skill names no longer activate workflows. The system prompt now ranks explicit user intent above every routing heuristic, forbids workflow self-invocation and plan stacking, bans task-difficulty overestimation, directs the agent to offer heuristic workflow escalation (especially deep-interview for vague requirements) through the `ask` tool with an opt-out, and adds an `<engineering>` principles section.
|
|
142
160
|
- Deferred notification adapters, native bindings, provider construction, tools, skills, eval, session artifacts, and history storage until their feature paths are used, reducing the CLI startup module graph without changing default behavior.
|
|
@@ -57,7 +57,7 @@ declare module "@gajae-code/tui" {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
export declare function defaultMessageQueueKeysForPlatform(platform?: NodeJS.Platform): KeyId;
|
|
60
|
-
export declare function defaultClipboardPasteImageKeysForPlatform(platform?: NodeJS.Platform): KeyId;
|
|
60
|
+
export declare function defaultClipboardPasteImageKeysForPlatform(platform?: NodeJS.Platform): KeyId[];
|
|
61
61
|
/**
|
|
62
62
|
* All keybindings definitions: TUI + app-specific.
|
|
63
63
|
*/
|
|
@@ -259,7 +259,7 @@ export declare const KEYBINDINGS: {
|
|
|
259
259
|
readonly description: "Select queued message to edit";
|
|
260
260
|
};
|
|
261
261
|
readonly "app.clipboard.pasteImage": {
|
|
262
|
-
readonly defaultKeys: KeyId;
|
|
262
|
+
readonly defaultKeys: KeyId[];
|
|
263
263
|
readonly description: "Paste image from clipboard";
|
|
264
264
|
};
|
|
265
265
|
readonly "app.clipboard.pasteText": {
|
|
@@ -61,6 +61,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
61
61
|
supportsDeveloperRole?: boolean | undefined;
|
|
62
62
|
sendSessionHeaders?: boolean | undefined;
|
|
63
63
|
supportsResponsesSessionAffinity?: boolean | undefined;
|
|
64
|
+
supportsServiceTier?: boolean | undefined;
|
|
64
65
|
supportsMultipleSystemMessages?: boolean | undefined;
|
|
65
66
|
supportsReasoningEffort?: boolean | undefined;
|
|
66
67
|
reasoningEffortMap?: {
|
|
@@ -145,6 +146,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
145
146
|
supportsDeveloperRole?: boolean | undefined;
|
|
146
147
|
sendSessionHeaders?: boolean | undefined;
|
|
147
148
|
supportsResponsesSessionAffinity?: boolean | undefined;
|
|
149
|
+
supportsServiceTier?: boolean | undefined;
|
|
148
150
|
supportsMultipleSystemMessages?: boolean | undefined;
|
|
149
151
|
supportsReasoningEffort?: boolean | undefined;
|
|
150
152
|
reasoningEffortMap?: {
|
|
@@ -222,6 +224,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
222
224
|
supportsDeveloperRole?: boolean | undefined;
|
|
223
225
|
sendSessionHeaders?: boolean | undefined;
|
|
224
226
|
supportsResponsesSessionAffinity?: boolean | undefined;
|
|
227
|
+
supportsServiceTier?: boolean | undefined;
|
|
225
228
|
supportsMultipleSystemMessages?: boolean | undefined;
|
|
226
229
|
supportsReasoningEffort?: boolean | undefined;
|
|
227
230
|
reasoningEffortMap?: {
|
|
@@ -341,6 +344,7 @@ export declare class ModelRegistry {
|
|
|
341
344
|
* @param authStorage - Auth storage for API key resolution
|
|
342
345
|
*/
|
|
343
346
|
constructor(authStorage: AuthStorage, modelsPath?: string);
|
|
347
|
+
onCatalogChanged(listener: () => void): () => void;
|
|
344
348
|
/**
|
|
345
349
|
* Reload models from disk (built-in + custom from models.json).
|
|
346
350
|
*/
|
|
@@ -4,6 +4,7 @@ export declare const ModelCompatSchema: z.ZodObject<{
|
|
|
4
4
|
supportsDeveloperRole: z.ZodOptional<z.ZodBoolean>;
|
|
5
5
|
sendSessionHeaders: z.ZodOptional<z.ZodBoolean>;
|
|
6
6
|
supportsResponsesSessionAffinity: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
+
supportsServiceTier: z.ZodOptional<z.ZodBoolean>;
|
|
7
8
|
supportsMultipleSystemMessages: z.ZodOptional<z.ZodBoolean>;
|
|
8
9
|
supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
|
|
9
10
|
reasoningEffortMap: z.ZodOptional<z.ZodObject<{
|
|
@@ -74,6 +75,7 @@ export declare const OpenAICompatSchema: z.ZodObject<{
|
|
|
74
75
|
supportsDeveloperRole: z.ZodOptional<z.ZodBoolean>;
|
|
75
76
|
sendSessionHeaders: z.ZodOptional<z.ZodBoolean>;
|
|
76
77
|
supportsResponsesSessionAffinity: z.ZodOptional<z.ZodBoolean>;
|
|
78
|
+
supportsServiceTier: z.ZodOptional<z.ZodBoolean>;
|
|
77
79
|
supportsMultipleSystemMessages: z.ZodOptional<z.ZodBoolean>;
|
|
78
80
|
supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
|
|
79
81
|
reasoningEffortMap: z.ZodOptional<z.ZodObject<{
|
|
@@ -262,6 +264,7 @@ export declare const ModelOverrideSchema: z.ZodObject<{
|
|
|
262
264
|
supportsDeveloperRole: z.ZodOptional<z.ZodBoolean>;
|
|
263
265
|
sendSessionHeaders: z.ZodOptional<z.ZodBoolean>;
|
|
264
266
|
supportsResponsesSessionAffinity: z.ZodOptional<z.ZodBoolean>;
|
|
267
|
+
supportsServiceTier: z.ZodOptional<z.ZodBoolean>;
|
|
265
268
|
supportsMultipleSystemMessages: z.ZodOptional<z.ZodBoolean>;
|
|
266
269
|
supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
|
|
267
270
|
reasoningEffortMap: z.ZodOptional<z.ZodObject<{
|
|
@@ -389,6 +392,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
389
392
|
supportsDeveloperRole: z.ZodOptional<z.ZodBoolean>;
|
|
390
393
|
sendSessionHeaders: z.ZodOptional<z.ZodBoolean>;
|
|
391
394
|
supportsResponsesSessionAffinity: z.ZodOptional<z.ZodBoolean>;
|
|
395
|
+
supportsServiceTier: z.ZodOptional<z.ZodBoolean>;
|
|
392
396
|
supportsMultipleSystemMessages: z.ZodOptional<z.ZodBoolean>;
|
|
393
397
|
supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
|
|
394
398
|
reasoningEffortMap: z.ZodOptional<z.ZodObject<{
|
|
@@ -569,6 +573,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
569
573
|
supportsDeveloperRole: z.ZodOptional<z.ZodBoolean>;
|
|
570
574
|
sendSessionHeaders: z.ZodOptional<z.ZodBoolean>;
|
|
571
575
|
supportsResponsesSessionAffinity: z.ZodOptional<z.ZodBoolean>;
|
|
576
|
+
supportsServiceTier: z.ZodOptional<z.ZodBoolean>;
|
|
572
577
|
supportsMultipleSystemMessages: z.ZodOptional<z.ZodBoolean>;
|
|
573
578
|
supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
|
|
574
579
|
reasoningEffortMap: z.ZodOptional<z.ZodObject<{
|
|
@@ -717,6 +722,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
717
722
|
supportsDeveloperRole: z.ZodOptional<z.ZodBoolean>;
|
|
718
723
|
sendSessionHeaders: z.ZodOptional<z.ZodBoolean>;
|
|
719
724
|
supportsResponsesSessionAffinity: z.ZodOptional<z.ZodBoolean>;
|
|
725
|
+
supportsServiceTier: z.ZodOptional<z.ZodBoolean>;
|
|
720
726
|
supportsMultipleSystemMessages: z.ZodOptional<z.ZodBoolean>;
|
|
721
727
|
supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
|
|
722
728
|
reasoningEffortMap: z.ZodOptional<z.ZodObject<{
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Effort } from "@gajae-code/ai/model-thinking";
|
|
2
|
+
import { type EditMode } from "../utils/edit-mode";
|
|
2
3
|
import type { ModelSelectorValue } from "./model-selector-value";
|
|
3
4
|
import { type SkillDiscoverySettings } from "./skill-settings-defaults";
|
|
4
5
|
/** Unified settings schema - single source of truth for all settings.
|
|
@@ -97,9 +98,12 @@ interface ArrayDef<T> {
|
|
|
97
98
|
};
|
|
98
99
|
ui?: UiBase;
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
+
type RecordValueDef = {
|
|
101
102
|
type: "model-selector-value";
|
|
102
|
-
}
|
|
103
|
+
} | {
|
|
104
|
+
type: "string-enum";
|
|
105
|
+
values: readonly string[];
|
|
106
|
+
};
|
|
103
107
|
interface RecordDef<T> {
|
|
104
108
|
type: "record";
|
|
105
109
|
default: Record<string, T>;
|
|
@@ -2544,12 +2548,20 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
2544
2548
|
};
|
|
2545
2549
|
readonly "edit.mode": {
|
|
2546
2550
|
readonly type: "enum";
|
|
2547
|
-
readonly values: import("../edit").
|
|
2548
|
-
readonly default: "
|
|
2551
|
+
readonly values: import("../utils/edit-mode").EditModeSetting[];
|
|
2552
|
+
readonly default: import("../utils/edit-mode").EditModeSetting;
|
|
2549
2553
|
readonly ui: {
|
|
2550
2554
|
readonly tab: "editing";
|
|
2551
2555
|
readonly label: "Edit Mode";
|
|
2552
|
-
readonly description: "Select the edit tool variant (replace, patch, hashline, vim, or apply_patch)";
|
|
2556
|
+
readonly description: "Select the edit tool variant (auto routes by model family; replace, patch, hashline, vim, or apply_patch)";
|
|
2557
|
+
};
|
|
2558
|
+
};
|
|
2559
|
+
readonly "edit.modelVariants": {
|
|
2560
|
+
readonly type: "record";
|
|
2561
|
+
readonly default: Record<string, EditMode>;
|
|
2562
|
+
readonly valueSchema: {
|
|
2563
|
+
readonly type: "string-enum";
|
|
2564
|
+
readonly values: EditMode[];
|
|
2553
2565
|
};
|
|
2554
2566
|
};
|
|
2555
2567
|
readonly "edit.fuzzyMatch": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ModelRole } from "../config/model-registry";
|
|
2
2
|
import { type NotificationSettingsReader, type NotificationSettingsSnapshot } from "../sdk/bus/config";
|
|
3
3
|
import { AgentStorage } from "../session/agent-storage";
|
|
4
|
-
import { type EditMode } from "../utils/edit-mode";
|
|
4
|
+
import { type EditMode, type EditVariantMatch } from "../utils/edit-mode";
|
|
5
5
|
import { type CasReceipt } from "./atomic-yaml-patch";
|
|
6
6
|
import { type ModelSelectorValue } from "./model-selector-value";
|
|
7
7
|
import { type BashInterceptorRule, type GroupPrefix, type GroupTypeMap, type SettingPath, type SettingsSchemaReport, type SettingValue } from "./settings-schema";
|
|
@@ -139,8 +139,17 @@ export declare class Settings implements NotificationSettingsReader {
|
|
|
139
139
|
/**
|
|
140
140
|
* Get the edit variant for a specific model.
|
|
141
141
|
* Returns "patch", "replace", "hashline", "vim", "apply_patch", or null (use global default).
|
|
142
|
+
* Skips invalid values; prefer `matchEditVariantForModel` when invalid
|
|
143
|
+
* matches must fail closed instead of falling through.
|
|
142
144
|
*/
|
|
143
145
|
getEditVariantForModel(model: string | undefined): EditMode | null;
|
|
146
|
+
/**
|
|
147
|
+
* First matching `edit.modelVariants` rule for a model, with its raw
|
|
148
|
+
* (unvalidated) value. The edit-mode resolver uses this discriminated
|
|
149
|
+
* result so a matched-but-invalid value fails closed with a diagnostic
|
|
150
|
+
* rather than silently resolving to another mode.
|
|
151
|
+
*/
|
|
152
|
+
matchEditVariantForModel(model: string | undefined): EditVariantMatch | null;
|
|
144
153
|
/**
|
|
145
154
|
* Get bash interceptor rules (typed accessor for complex array config).
|
|
146
155
|
*/
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { Theme } from "../modes/theme/theme";
|
|
16
16
|
import { type EditMode, resolveEditMode } from "../utils/edit-mode";
|
|
17
|
-
import { type
|
|
17
|
+
import { type PatchEditEntry } from "./modes/patch";
|
|
18
18
|
export interface PerFileDiffPreview {
|
|
19
19
|
path: string;
|
|
20
20
|
diff?: string;
|
|
@@ -55,11 +55,11 @@ export interface EditStreamingStrategy<Args = unknown> {
|
|
|
55
55
|
}
|
|
56
56
|
export interface EditRequestTargetInventory {
|
|
57
57
|
paths: string[];
|
|
58
|
-
/** Operation of the first target (Create/Delete) when derivable from the
|
|
59
|
-
* request payload (apply_patch/hashline free-form envelopes carry op on the
|
|
60
|
-
* parsed entry, not on the top-level args). */
|
|
61
|
-
firstOp?: Operation;
|
|
62
58
|
parseError?: string;
|
|
59
|
+
/** First envelope entry operation, for free-form modes that carry no structured `edits`. */
|
|
60
|
+
op?: PatchEditEntry["op"];
|
|
61
|
+
/** First envelope entry rename target, for free-form modes that carry no structured `edits`. */
|
|
62
|
+
rename?: string;
|
|
63
63
|
}
|
|
64
64
|
export declare function orderedDistinctPaths(paths: readonly (string | undefined)[]): string[];
|
|
65
65
|
export declare function getEditRequestTargetInventory(args: unknown, editMode: EditMode | undefined, options: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type KernelDisplayOutput } from "./display";
|
|
2
|
-
import { type PythonRuntimeOptions } from "./runtime";
|
|
2
|
+
import { type PythonRuntimeLifecycleOptions, type PythonRuntimeOptions } from "./runtime";
|
|
3
3
|
export type { KernelDisplayOutput, PythonStatusEvent } from "./display";
|
|
4
4
|
export { renderKernelDisplay } from "./display";
|
|
5
5
|
export interface KernelExecuteOptions {
|
|
@@ -50,7 +50,7 @@ export interface PythonKernelAvailability {
|
|
|
50
50
|
pythonPath?: string;
|
|
51
51
|
reason?: string;
|
|
52
52
|
}
|
|
53
|
-
export declare function checkPythonKernelAvailability(cwd: string, runtimeOptions?: PythonRuntimeOptions): Promise<PythonKernelAvailability>;
|
|
53
|
+
export declare function checkPythonKernelAvailability(cwd: string, runtimeOptions?: PythonRuntimeOptions, lifecycle?: PythonRuntimeLifecycleOptions): Promise<PythonKernelAvailability>;
|
|
54
54
|
export declare class PythonKernel {
|
|
55
55
|
#private;
|
|
56
56
|
readonly id: string;
|
|
@@ -5,6 +5,10 @@ export interface PythonRuntimeOptions {
|
|
|
5
5
|
/** Packages to seed into the managed workspace venv when provisioning it. */
|
|
6
6
|
seedPackages?: readonly string[];
|
|
7
7
|
}
|
|
8
|
+
export interface PythonRuntimeLifecycleOptions {
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
deadlineMs?: number;
|
|
11
|
+
}
|
|
8
12
|
export interface PythonRuntime {
|
|
9
13
|
/** Path to python executable */
|
|
10
14
|
pythonPath: string;
|
|
@@ -26,4 +30,4 @@ export declare function resolveVenvPath(cwd: string): string | undefined;
|
|
|
26
30
|
* Resolve Python runtime including executable path, environment, and venv detection.
|
|
27
31
|
*/
|
|
28
32
|
export declare function resolvePythonRuntime(cwd: string, baseEnv: Record<string, string | undefined>, options?: PythonRuntimeOptions): PythonRuntime;
|
|
29
|
-
export declare function ensurePythonRuntime(cwd: string, baseEnv: Record<string, string | undefined>, options?: PythonRuntimeOptions): Promise<PythonRuntime>;
|
|
33
|
+
export declare function ensurePythonRuntime(cwd: string, baseEnv: Record<string, string | undefined>, options?: PythonRuntimeOptions, lifecycle?: PythonRuntimeLifecycleOptions): Promise<PythonRuntime>;
|
|
@@ -27,6 +27,9 @@ export declare const __sessionStateSidecarPerfCounters: {
|
|
|
27
27
|
interface RuntimeStateEvent {
|
|
28
28
|
type: string;
|
|
29
29
|
messages?: unknown[];
|
|
30
|
+
toolCallId?: unknown;
|
|
31
|
+
toolName?: unknown;
|
|
32
|
+
isError?: unknown;
|
|
30
33
|
}
|
|
31
34
|
export interface OwnerTerminalContext {
|
|
32
35
|
generation: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ProviderAuthority } from "./tmux-common";
|
|
2
|
-
import { type OwnerIsolationProbeSync, type PlanResponse, type TmuxOwnerIsolationExecutionDependencies, type TmuxOwnerIsolationExecutionResult } from "./tmux-owner-isolation";
|
|
2
|
+
import { type OwnerIsolationProbeSync, type OwnerVerdict, type PlanResponse, type TmuxOwnerIsolationExecutionDependencies, type TmuxOwnerIsolationExecutionResult } from "./tmux-owner-isolation";
|
|
3
3
|
export interface GjcTmuxSessionStatus {
|
|
4
4
|
name: string;
|
|
5
5
|
attached: boolean;
|
|
@@ -71,6 +71,8 @@ export interface ForceCloseOwnerDependencies {
|
|
|
71
71
|
now(): Date;
|
|
72
72
|
sleep(ms: number): Promise<void>;
|
|
73
73
|
listPanePids(sessionName: string, env: NodeJS.ProcessEnv): number[];
|
|
74
|
+
/** Test/runtime seam for an exact owner-exit observer; durable validation remains authoritative. */
|
|
75
|
+
waitForOwnerExitVerdict?(): Promise<OwnerVerdict>;
|
|
74
76
|
}
|
|
75
77
|
export interface CreateGjcTmuxSessionOptions {
|
|
76
78
|
platform?: NodeJS.Platform;
|
|
@@ -42,13 +42,14 @@ export declare class ModelSelectorComponent extends Container {
|
|
|
42
42
|
temporaryOnly?: boolean;
|
|
43
43
|
initialSearchInput?: string;
|
|
44
44
|
sessionId?: string;
|
|
45
|
-
isFastForProvider?: (provider?: string) => boolean;
|
|
46
|
-
isFastForSubagentProvider?: (provider?: string) => boolean;
|
|
45
|
+
isFastForProvider?: (provider?: string, supportsServiceTier?: boolean) => boolean;
|
|
46
|
+
isFastForSubagentProvider?: (provider?: string, supportsServiceTier?: boolean) => boolean;
|
|
47
47
|
isCurrentModelFastModeActive?: () => boolean;
|
|
48
48
|
currentThinkingLevel?: ThinkingLevel;
|
|
49
49
|
activeModelProfile?: string;
|
|
50
50
|
configuredDefaultChain?: readonly string[];
|
|
51
51
|
});
|
|
52
|
+
dispose(): void;
|
|
52
53
|
refreshRoleAssignments(options?: {
|
|
53
54
|
currentModel?: Model;
|
|
54
55
|
currentThinkingLevel?: ThinkingLevel;
|
|
@@ -1,34 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared runtime lifecycle foundation.
|
|
3
|
-
*
|
|
4
|
-
* Two minimal, deliberately small primitives that subsystem runtimes
|
|
5
|
-
* (DAP/LSP/MCP stdio, eval workers, etc.) adopt so spawned children and
|
|
6
|
-
* non-process resources cannot outlive their owner:
|
|
7
|
-
*
|
|
8
|
-
* F1(a) `spawnOwnedProcess` — wraps `ptree.spawn` with explicit
|
|
9
|
-
* process-group ownership, escalating (SIGTERM -> grace -> SIGKILL)
|
|
10
|
-
* tree termination, bounded `awaitExit`, abort-listener cleanup on
|
|
11
|
-
* settle, idempotent `dispose`, and a single postmortem hook that
|
|
12
|
-
* reaps every still-live owned process group on fatal/normal shutdown.
|
|
13
|
-
*
|
|
14
|
-
* F1(b) `registerResourceOwner` — a generic, idempotent postmortem adapter
|
|
15
|
-
* for non-process resources (Bun Workers, VM contexts, timers,
|
|
16
|
-
* sockets) built on the existing `postmortem.register` facility.
|
|
17
|
-
*
|
|
18
|
-
* Ownership is keyed to the *process group*, not the root process. A root that
|
|
19
|
-
* exits after backgrounding descendants (`sh -c "worker & exit 0"`) keeps the
|
|
20
|
-
* owner registered until the group is actually gone, so the descendant tree is
|
|
21
|
-
* still reaped by `dispose()`/postmortem.
|
|
22
|
-
*
|
|
23
|
-
* This module intentionally owns only these primitives. It does not migrate
|
|
24
|
-
* existing call sites; subsystem PRs adopt it incrementally.
|
|
25
|
-
*
|
|
26
|
-
* Note: `ptree.spawn` always pipes stdout/stderr. Adopters that expect output
|
|
27
|
-
* (DAP/LSP/MCP protocol servers) must consume `owner.child.stdout`; F1 does not
|
|
28
|
-
* drain it, so a chatty child whose stdout is never read can still block on a
|
|
29
|
-
* full pipe. That draining is the adopter's responsibility.
|
|
30
|
-
*/
|
|
31
1
|
import { ptree } from "@gajae-code/utils";
|
|
2
|
+
import { type LinuxProcPidProbeResult } from "../gjc-runtime/linux-proc";
|
|
3
|
+
/** Whether an unreadable `/proc` entry might still describe a running process. */
|
|
4
|
+
export declare function procEntryMayStillBeRunning(error: unknown): boolean;
|
|
5
|
+
/** Whether a process-group leader still has the spawn-time identity we own. */
|
|
6
|
+
export declare function groupLeaderIdentityMatches(expectedStartTime: string | undefined, leader: LinuxProcPidProbeResult): boolean;
|
|
32
7
|
/** Options for {@link spawnOwnedProcess}. */
|
|
33
8
|
export interface SpawnOwnedOptions {
|
|
34
9
|
cwd?: string;
|
|
@@ -55,6 +30,12 @@ export interface AwaitExitResult {
|
|
|
55
30
|
/** Exit code if known, else `null`. */
|
|
56
31
|
code: number | null;
|
|
57
32
|
}
|
|
33
|
+
/** The observed outcome of an owned-process teardown attempt. */
|
|
34
|
+
export type OwnedProcessTeardownStatus = "terminated" | "still_running" | "identity_unverified";
|
|
35
|
+
/** Result of {@link OwnedProcess.dispose}. */
|
|
36
|
+
export interface OwnedProcessTeardownResult {
|
|
37
|
+
status: OwnedProcessTeardownStatus;
|
|
38
|
+
}
|
|
58
39
|
/** A spawned child process owned by the runtime with guaranteed teardown. */
|
|
59
40
|
export interface OwnedProcess {
|
|
60
41
|
readonly child: ptree.ChildProcess;
|
|
@@ -76,7 +57,7 @@ export interface OwnedProcess {
|
|
|
76
57
|
* abort listener and deregisters from the live-owner set only after teardown
|
|
77
58
|
* has completed. Repeated/concurrent calls return the same in-flight promise.
|
|
78
59
|
*/
|
|
79
|
-
dispose(): Promise<
|
|
60
|
+
dispose(): Promise<OwnedProcessTeardownResult>;
|
|
80
61
|
}
|
|
81
62
|
/**
|
|
82
63
|
* Spawn a child process owned by the runtime. The returned {@link OwnedProcess}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function brokerIdentityPath(agentDir: string): string;
|
|
2
2
|
export declare function getBrokerIdentityKey(agentDir: string): Promise<string>;
|
|
3
|
-
export declare function deriveIdempotencyIdentity(agentDir: string, operation: string, callerKey: string,
|
|
3
|
+
export declare function deriveIdempotencyIdentity(agentDir: string, operation: string, callerKey: string, _protocolVersionOrLegacyTargetHash?: string): Promise<string>;
|
|
4
|
+
export declare function deriveLegacyTargetIdentity(agentDir: string, operation: string, callerKey: string, canonicalTargetHash: string): Promise<string>;
|
|
@@ -53,6 +53,8 @@ export interface LifecycleDurableEffectsReceipt {
|
|
|
53
53
|
digest?: string;
|
|
54
54
|
}
|
|
55
55
|
export interface LifecycleLedgerEntry {
|
|
56
|
+
operationKey?: string;
|
|
57
|
+
fingerprint?: string;
|
|
56
58
|
version: typeof SDK_STATE_VERSION;
|
|
57
59
|
identity: string;
|
|
58
60
|
requestHash: string;
|
|
@@ -115,8 +117,22 @@ export declare class LifecycleLedger {
|
|
|
115
117
|
* synced row as unpersisted and replace its true reason with a generic one.
|
|
116
118
|
*/
|
|
117
119
|
readTerminal(identity: string, requestHash: string): Promise<LifecycleLedgerEntry | undefined>;
|
|
120
|
+
findByOperationKey(operationKey: string): LifecycleLedgerEntry | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* Legacy target-inclusive rows predate the operation/key index. Their opaque
|
|
123
|
+
* identities cannot establish that a different target is safe, so callers
|
|
124
|
+
* must reject rather than create a second admission.
|
|
125
|
+
*/
|
|
126
|
+
hasLegacyIdentity(): boolean;
|
|
127
|
+
migrateIdentity(from: string, to: string, metadata: {
|
|
128
|
+
operationKey: string;
|
|
129
|
+
fingerprint: string;
|
|
130
|
+
}): Promise<LifecycleLedgerEntry | undefined>;
|
|
118
131
|
get warnings(): readonly string[];
|
|
119
|
-
begin(identity: string, requestHash: string
|
|
132
|
+
begin(identity: string, requestHash: string, metadata?: {
|
|
133
|
+
operationKey?: string;
|
|
134
|
+
fingerprint?: string;
|
|
135
|
+
}): Promise<BeginResult>;
|
|
120
136
|
transition(identity: string, state: LifecycleState, fields?: Omit<Partial<LifecycleLedgerEntry>, "identity" | "requestHash" | "state" | "ts">): Promise<LifecycleLedgerEntry>;
|
|
121
137
|
assertSupportedStateVersions(): Promise<void>;
|
|
122
138
|
findCleanupPendingByDeleteTarget(target: {
|
|
@@ -182,12 +182,17 @@ export interface ReapedSessionRegistration {
|
|
|
182
182
|
/**
|
|
183
183
|
* Drops every indexed session registration whose host process is provably gone.
|
|
184
184
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
185
|
+
* Proof of death is positive, never inferred from a missing liveness proof:
|
|
186
|
+
* `observeProcess` reports "exited" only on ESRCH or on a readable OS process
|
|
187
|
+
* incarnation that differs from the recorded one (a reused pid). A stale or
|
|
188
|
+
* missing heartbeat merely makes a session read as not-live — the host may
|
|
189
|
+
* still be running ahead of the next heartbeat checkpoint pass, so it is never
|
|
190
|
+
* grounds for a reap. EPERM and unreadable incarnations stay "uncertain", so an
|
|
191
|
+
* alien or unreadable process is never mistaken for a dead one. Registrations
|
|
192
|
+
* already terminal or marked `terminalUncertain` are left alone: their
|
|
193
|
+
* disposition belongs to the terminal-uncertainty reconciliation path, and
|
|
194
|
+
* silently dropping them would turn a fail-closed `session.close`/
|
|
195
|
+
* `session.delete` refusal into `not_found`.
|
|
191
196
|
*/
|
|
192
197
|
export declare function reapDeadSessionRegistrations(broker: Pick<Broker, "index">): Promise<ReapedSessionRegistration[]>;
|
|
193
198
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface BrokerStartupFailureMarker {
|
|
2
|
+
version: 1;
|
|
3
|
+
reason: string;
|
|
4
|
+
exitCode: number | null;
|
|
5
|
+
signal: string | null;
|
|
6
|
+
writtenAt: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function brokerStartupFailurePath(agentDir: string): string;
|
|
9
|
+
/** Best-effort durable marker write; never throws (diagnostics must not mask the exit itself). */
|
|
10
|
+
export declare function writeBrokerStartupFailureMarker(agentDir: string, failure: {
|
|
11
|
+
reason: string;
|
|
12
|
+
exitCode: number | null;
|
|
13
|
+
signal: string | null;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
/** Reads a bounded startup-failure marker; `undefined` when absent or malformed. */
|
|
16
|
+
export declare function readBrokerStartupFailureMarker(agentDir: string): Promise<BrokerStartupFailureMarker | undefined>;
|
|
17
|
+
/** Best-effort marker removal; used at spawn so a stale marker never misattributes an older failure. */
|
|
18
|
+
export declare function clearBrokerStartupFailureMarker(agentDir: string): Promise<void>;
|
|
19
|
+
/** Typed error returned when a detached broker exits before discovery. */
|
|
20
|
+
export declare class BrokerStartupError extends Error {
|
|
21
|
+
readonly code = "broker_startup_failed";
|
|
22
|
+
readonly exitCode: number | null;
|
|
23
|
+
readonly signal: string | null;
|
|
24
|
+
readonly reason: string;
|
|
25
|
+
readonly stderrExcerpt?: string;
|
|
26
|
+
constructor(fields: {
|
|
27
|
+
exitCode: number | null;
|
|
28
|
+
signal: string | null;
|
|
29
|
+
reason: string;
|
|
30
|
+
stderrExcerpt?: string;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -44,7 +44,8 @@ export type ChatDaemonAction = "stop" | "reload";
|
|
|
44
44
|
* before the host heartbeat TTL expires and permanently loses its attachment. Discord
|
|
45
45
|
* generation 29 / slack generation 28 advance the replay cursor only after a frame is
|
|
46
46
|
* published, so an owner at an earlier generation acknowledges an event before delivering
|
|
47
|
-
* it and loses that event for good the first time a surface refuses it.
|
|
47
|
+
* it and loses that event for good the first time a surface refuses it. Discord generation 30 /
|
|
48
|
+
* slack generation 29 invalidate existing owners after SDK discovery validation changes.
|
|
48
49
|
*/
|
|
49
50
|
export declare const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>>;
|
|
50
51
|
export declare function chatDaemonGeneration(kind: ChatDaemonKind): number;
|
|
@@ -24,6 +24,7 @@ export interface ConversationStoreFs {
|
|
|
24
24
|
mode: number;
|
|
25
25
|
}): Promise<void>;
|
|
26
26
|
rename(from: string, to: string): Promise<void>;
|
|
27
|
+
link(from: string, to: string): Promise<void>;
|
|
27
28
|
unlink(file: string): Promise<void>;
|
|
28
29
|
open(file: string, flags: string): Promise<ConversationStoreFileHandle>;
|
|
29
30
|
stat?(file: string): Promise<{
|
|
@@ -333,6 +333,8 @@ interface SessionRuntime {
|
|
|
333
333
|
cursors: CursorRegistry;
|
|
334
334
|
/** Current endpoint session identity; never re-key an existing host across a switch. */
|
|
335
335
|
id: string;
|
|
336
|
+
/** Discovery scope is fixed before publication; a live default endpoint is never rotated in place. */
|
|
337
|
+
endpointScope: "default" | "chat";
|
|
336
338
|
idleSeq: number;
|
|
337
339
|
/** Interactive asks awaiting a remote answer, by action id. */
|
|
338
340
|
pendingInteractive: Map<string, PendingInteractiveAsk>;
|
|
@@ -344,6 +346,8 @@ interface SessionRuntime {
|
|
|
344
346
|
disposeGateListener: () => void;
|
|
345
347
|
/** Whether notification-only delivery and answer resources are active. */
|
|
346
348
|
notificationsActive: boolean;
|
|
349
|
+
/** Provider ownership state is independent from the already-published core SDK runtime. */
|
|
350
|
+
notificationOwnerState: "ready" | "retry" | "blocked";
|
|
347
351
|
/** Rejects new SDK frames while a leased terminal response drains. */
|
|
348
352
|
inboundFenced: boolean;
|
|
349
353
|
/** Set as soon as terminal teardown is requested, before startup settles. */
|