@cruxy/cli 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/dist/agent/loop.js +3 -0
  2. package/dist/agent/session.js +2 -1
  3. package/dist/theme/tokens.js +3 -0
  4. package/dist/usage/collect.js +41 -2
  5. package/dist/usage/index.js +1 -1
  6. package/dist/usage/summary.js +19 -0
  7. package/dist/usage/types.js +9 -0
  8. package/package.json +1 -1
  9. package/dist/agent/budget.d.ts +0 -52
  10. package/dist/agent/index.d.ts +0 -3
  11. package/dist/agent/loop.d.ts +0 -159
  12. package/dist/agent/prompts.d.ts +0 -69
  13. package/dist/agent/session.d.ts +0 -212
  14. package/dist/approval/classify.d.ts +0 -18
  15. package/dist/approval/index.d.ts +0 -6
  16. package/dist/approval/mutex.d.ts +0 -45
  17. package/dist/approval/policy.d.ts +0 -43
  18. package/dist/approval/prompt.d.ts +0 -48
  19. package/dist/approval/service.d.ts +0 -36
  20. package/dist/approval/types.d.ts +0 -82
  21. package/dist/brand/index.d.ts +0 -1
  22. package/dist/brand/voice.d.ts +0 -94
  23. package/dist/checkpoint/capture.d.ts +0 -17
  24. package/dist/checkpoint/gate-hook.d.ts +0 -28
  25. package/dist/checkpoint/gate.d.ts +0 -71
  26. package/dist/checkpoint/git-store.d.ts +0 -61
  27. package/dist/checkpoint/index.d.ts +0 -10
  28. package/dist/checkpoint/restore.d.ts +0 -23
  29. package/dist/checkpoint/service.d.ts +0 -89
  30. package/dist/checkpoint/set-rollback.d.ts +0 -51
  31. package/dist/checkpoint/set.d.ts +0 -44
  32. package/dist/checkpoint/shadow-store.d.ts +0 -23
  33. package/dist/checkpoint/types.d.ts +0 -164
  34. package/dist/cli/commands/checkpoint.d.ts +0 -7
  35. package/dist/cli/commands/config.d.ts +0 -2
  36. package/dist/cli/commands/hooks.d.ts +0 -8
  37. package/dist/cli/commands/index.d.ts +0 -7
  38. package/dist/cli/commands/init.d.ts +0 -7
  39. package/dist/cli/commands/login.d.ts +0 -8
  40. package/dist/cli/commands/mcp.d.ts +0 -9
  41. package/dist/cli/commands/memory.d.ts +0 -8
  42. package/dist/cli/commands/pr.d.ts +0 -8
  43. package/dist/cli/commands/rollback.d.ts +0 -18
  44. package/dist/cli/commands/run.d.ts +0 -2
  45. package/dist/cli/commands/skills.d.ts +0 -8
  46. package/dist/cli/commands/test.d.ts +0 -9
  47. package/dist/cli/commands/usage.d.ts +0 -9
  48. package/dist/cli/onboard.d.ts +0 -25
  49. package/dist/cli/program.d.ts +0 -2
  50. package/dist/cli/repl.d.ts +0 -27
  51. package/dist/cli/session-factory.d.ts +0 -42
  52. package/dist/cli/stream-print.d.ts +0 -14
  53. package/dist/components/autocomplete.d.ts +0 -32
  54. package/dist/components/frame.d.ts +0 -28
  55. package/dist/components/fuzzy.d.ts +0 -61
  56. package/dist/components/index.d.ts +0 -6
  57. package/dist/components/input.d.ts +0 -78
  58. package/dist/components/keys.d.ts +0 -48
  59. package/dist/components/select.d.ts +0 -28
  60. package/dist/config/credentials.d.ts +0 -18
  61. package/dist/config/index.d.ts +0 -5
  62. package/dist/config/manager.d.ts +0 -39
  63. package/dist/config/owner-only.d.ts +0 -19
  64. package/dist/config/paths.d.ts +0 -9
  65. package/dist/config/project.d.ts +0 -10
  66. package/dist/config/schema.d.ts +0 -2143
  67. package/dist/constants.d.ts +0 -65
  68. package/dist/errors/boundary.d.ts +0 -43
  69. package/dist/errors/constructors.d.ts +0 -411
  70. package/dist/errors/format.d.ts +0 -31
  71. package/dist/errors/index.d.ts +0 -4
  72. package/dist/errors/types.d.ts +0 -270
  73. package/dist/hooks/config.d.ts +0 -21
  74. package/dist/hooks/index.d.ts +0 -7
  75. package/dist/hooks/router.d.ts +0 -58
  76. package/dist/hooks/runner.d.ts +0 -88
  77. package/dist/hooks/service.d.ts +0 -38
  78. package/dist/hooks/slash.d.ts +0 -48
  79. package/dist/hooks/trust.d.ts +0 -46
  80. package/dist/hooks/types.d.ts +0 -147
  81. package/dist/index.d.ts +0 -2
  82. package/dist/indexing/chunker.d.ts +0 -28
  83. package/dist/indexing/embedder.d.ts +0 -98
  84. package/dist/indexing/index.d.ts +0 -9
  85. package/dist/indexing/indexer.d.ts +0 -45
  86. package/dist/indexing/retriever.d.ts +0 -61
  87. package/dist/indexing/service.d.ts +0 -49
  88. package/dist/indexing/store.d.ts +0 -103
  89. package/dist/indexing/types.d.ts +0 -78
  90. package/dist/indexing/util.d.ts +0 -34
  91. package/dist/indexing/walker.d.ts +0 -53
  92. package/dist/jobs/approval-queue.d.ts +0 -85
  93. package/dist/jobs/dispatch-tool.d.ts +0 -34
  94. package/dist/jobs/index.d.ts +0 -6
  95. package/dist/jobs/log-buffer.d.ts +0 -31
  96. package/dist/jobs/log-renderer.d.ts +0 -32
  97. package/dist/jobs/manager.d.ts +0 -139
  98. package/dist/jobs/types.d.ts +0 -81
  99. package/dist/lsp/client.d.ts +0 -25
  100. package/dist/lsp/index.d.ts +0 -8
  101. package/dist/lsp/pool.d.ts +0 -48
  102. package/dist/lsp/registry.d.ts +0 -38
  103. package/dist/lsp/server.d.ts +0 -48
  104. package/dist/lsp/service.d.ts +0 -44
  105. package/dist/lsp/tools/common.d.ts +0 -50
  106. package/dist/lsp/tools/find-definition.d.ts +0 -23
  107. package/dist/lsp/tools/find-references.d.ts +0 -23
  108. package/dist/lsp/tools/get-diagnostics.d.ts +0 -17
  109. package/dist/lsp/tools/hover.d.ts +0 -23
  110. package/dist/lsp/tools/index.d.ts +0 -4
  111. package/dist/lsp/transport.d.ts +0 -39
  112. package/dist/lsp/types.d.ts +0 -107
  113. package/dist/mcp/adapter.d.ts +0 -44
  114. package/dist/mcp/bounds.d.ts +0 -35
  115. package/dist/mcp/client.d.ts +0 -19
  116. package/dist/mcp/demarcate.d.ts +0 -12
  117. package/dist/mcp/http-transport.d.ts +0 -89
  118. package/dist/mcp/index.d.ts +0 -12
  119. package/dist/mcp/service.d.ts +0 -71
  120. package/dist/mcp/sibling-banner.d.ts +0 -25
  121. package/dist/mcp/transport.d.ts +0 -30
  122. package/dist/mcp/trust-gate.d.ts +0 -59
  123. package/dist/mcp/trust.d.ts +0 -62
  124. package/dist/mcp/types.d.ts +0 -62
  125. package/dist/mcp/url-guard.d.ts +0 -48
  126. package/dist/memory/index.d.ts +0 -7
  127. package/dist/memory/recall.d.ts +0 -56
  128. package/dist/memory/remember-tool.d.ts +0 -28
  129. package/dist/memory/secrets.d.ts +0 -29
  130. package/dist/memory/service.d.ts +0 -92
  131. package/dist/memory/store.d.ts +0 -32
  132. package/dist/memory/trust.d.ts +0 -52
  133. package/dist/memory/types.d.ts +0 -101
  134. package/dist/net/ip-guard.d.ts +0 -55
  135. package/dist/onboarding/detect.d.ts +0 -26
  136. package/dist/onboarding/flow.d.ts +0 -28
  137. package/dist/onboarding/index.d.ts +0 -5
  138. package/dist/onboarding/io.d.ts +0 -9
  139. package/dist/onboarding/steps.d.ts +0 -17
  140. package/dist/onboarding/types.d.ts +0 -81
  141. package/dist/plan/approve.d.ts +0 -16
  142. package/dist/plan/execute.d.ts +0 -28
  143. package/dist/plan/index.d.ts +0 -7
  144. package/dist/plan/policy.d.ts +0 -26
  145. package/dist/plan/render.d.ts +0 -5
  146. package/dist/plan/service.d.ts +0 -58
  147. package/dist/plan/submit-plan.d.ts +0 -33
  148. package/dist/plan/types.d.ts +0 -60
  149. package/dist/render/capabilities.d.ts +0 -31
  150. package/dist/render/diff.d.ts +0 -18
  151. package/dist/render/highlight.d.ts +0 -47
  152. package/dist/render/index.d.ts +0 -22
  153. package/dist/render/layout.d.ts +0 -59
  154. package/dist/render/motion.d.ts +0 -76
  155. package/dist/render/plain-renderer.d.ts +0 -39
  156. package/dist/render/resize.d.ts +0 -36
  157. package/dist/render/screen-reader-renderer.d.ts +0 -45
  158. package/dist/render/state.d.ts +0 -49
  159. package/dist/render/tty-renderer.d.ts +0 -106
  160. package/dist/render/types.d.ts +0 -201
  161. package/dist/routing/index.d.ts +0 -2
  162. package/dist/routing/resolve.d.ts +0 -17
  163. package/dist/routing/router.d.ts +0 -47
  164. package/dist/routing/types.d.ts +0 -42
  165. package/dist/sandbox/detect.d.ts +0 -22
  166. package/dist/sandbox/docker-runtime.d.ts +0 -32
  167. package/dist/sandbox/index.d.ts +0 -7
  168. package/dist/sandbox/policy.d.ts +0 -26
  169. package/dist/sandbox/service.d.ts +0 -64
  170. package/dist/sandbox/types.d.ts +0 -123
  171. package/dist/skills/index.d.ts +0 -4
  172. package/dist/skills/loader.d.ts +0 -43
  173. package/dist/skills/parser.d.ts +0 -31
  174. package/dist/skills/service.d.ts +0 -41
  175. package/dist/skills/types.d.ts +0 -94
  176. package/dist/subagent/index.d.ts +0 -5
  177. package/dist/subagent/orchestrator.d.ts +0 -169
  178. package/dist/subagent/registry-scope.d.ts +0 -41
  179. package/dist/subagent/semaphore.d.ts +0 -56
  180. package/dist/subagent/spawn-tool.d.ts +0 -86
  181. package/dist/subagent/types.d.ts +0 -65
  182. package/dist/testing/detect.d.ts +0 -3
  183. package/dist/testing/index.d.ts +0 -5
  184. package/dist/testing/parse.d.ts +0 -33
  185. package/dist/testing/run-tests-tool.d.ts +0 -64
  186. package/dist/testing/runner.d.ts +0 -26
  187. package/dist/testing/sandbox-runner.d.ts +0 -16
  188. package/dist/testing/types.d.ts +0 -66
  189. package/dist/theme/index.d.ts +0 -2
  190. package/dist/theme/resolve.d.ts +0 -43
  191. package/dist/theme/tokens.d.ts +0 -119
  192. package/dist/tools/create-pull-request.d.ts +0 -27
  193. package/dist/tools/file/apply-patch.d.ts +0 -94
  194. package/dist/tools/file/edit-file.d.ts +0 -12
  195. package/dist/tools/file/glob.d.ts +0 -17
  196. package/dist/tools/file/grep-files.d.ts +0 -43
  197. package/dist/tools/file/index.d.ts +0 -7
  198. package/dist/tools/file/match.d.ts +0 -43
  199. package/dist/tools/file/paths.d.ts +0 -160
  200. package/dist/tools/file/read-file.d.ts +0 -8
  201. package/dist/tools/file/write-file.d.ts +0 -10
  202. package/dist/tools/git-status.d.ts +0 -15
  203. package/dist/tools/index.d.ts +0 -9
  204. package/dist/tools/list-files.d.ts +0 -13
  205. package/dist/tools/list-skills.d.ts +0 -9
  206. package/dist/tools/load-skill.d.ts +0 -21
  207. package/dist/tools/registry.d.ts +0 -23
  208. package/dist/tools/search-codebase.d.ts +0 -35
  209. package/dist/tools/shell/exec.d.ts +0 -53
  210. package/dist/tools/shell/index.d.ts +0 -1
  211. package/dist/tools/shell/resolve-shell.d.ts +0 -81
  212. package/dist/tools/shell/run-command.d.ts +0 -14
  213. package/dist/tools/types.d.ts +0 -257
  214. package/dist/usage/collect.d.ts +0 -40
  215. package/dist/usage/cost.d.ts +0 -19
  216. package/dist/usage/index.d.ts +0 -15
  217. package/dist/usage/store.d.ts +0 -37
  218. package/dist/usage/summary.d.ts +0 -32
  219. package/dist/usage/types.d.ts +0 -220
  220. package/dist/utils/child-tree.d.ts +0 -33
  221. package/dist/utils/git.d.ts +0 -17
  222. package/dist/utils/logger.d.ts +0 -18
  223. package/dist/utils/process-tree.d.ts +0 -16
  224. package/dist/vcs/auth.d.ts +0 -22
  225. package/dist/vcs/generate.d.ts +0 -74
  226. package/dist/vcs/git.d.ts +0 -60
  227. package/dist/vcs/github.d.ts +0 -50
  228. package/dist/vcs/guidance.d.ts +0 -20
  229. package/dist/vcs/index.d.ts +0 -7
  230. package/dist/vcs/service.d.ts +0 -61
  231. package/dist/vcs/types.d.ts +0 -73
  232. package/dist/web/demarcate.d.ts +0 -13
  233. package/dist/web/fetch.d.ts +0 -11
  234. package/dist/web/index.d.ts +0 -7
  235. package/dist/web/provider.d.ts +0 -29
  236. package/dist/web/search.d.ts +0 -17
  237. package/dist/web/ssrf.d.ts +0 -41
  238. package/dist/web/tools.d.ts +0 -20
  239. package/dist/web/types.d.ts +0 -64
  240. package/dist/workspace/add-root.d.ts +0 -27
  241. package/dist/workspace/index.d.ts +0 -6
  242. package/dist/workspace/resolve.d.ts +0 -54
  243. package/dist/workspace/select.d.ts +0 -41
  244. package/dist/workspace/types.d.ts +0 -30
  245. package/dist/workspace/workspace.d.ts +0 -61
@@ -1,201 +0,0 @@
1
- import type { ActionPreview } from "../tools/types.js";
2
- import type { Theme } from "../theme/index.js";
3
- /**
4
- * The streaming render seam (U.2): the agent loop talks to a
5
- * {@link StreamRenderer}, never to raw stdout. Two implementations exist —
6
- * `TtyRenderer` (managed one-line live region, append-only committed content)
7
- * and `PlainRenderer` (append-only, zero ANSI) — picked by the factory from
8
- * detected {@link RenderCapabilities}. Same swappable discipline as
9
- * `Formatter`/`VectorStore`.
10
- */
11
- /**
12
- * What the output medium supports, detected once at construction (see
13
- * `detectCapabilities`). Renderers and the factory key off these flags; nothing
14
- * downstream re-probes the environment.
15
- */
16
- export interface RenderCapabilities {
17
- /** The primary output stream is a terminal. */
18
- tty: boolean;
19
- /** Emit ANSI color (NO_COLOR / FORCE_COLOR / TTY resolved; `TERM=dumb` → false). */
20
- color: boolean;
21
- /** Cursor-control sequences are safe (`tty` and not `TERM=dumb`). */
22
- cursor: boolean;
23
- /** Animation is welcome (`cursor` and motion is not reduced). */
24
- spinner: boolean;
25
- /**
26
- * Motion is reduced (U.11): no spinner animation/timer, no in-place
27
- * re-animation — state survives as static text, only movement stops. True
28
- * under `CRUXY_NO_SPINNER` (alias) / `NO_MOTION` / `CRUXY_REDUCED_MOTION`, and
29
- * implied by `screenReader`. The one axis the spinner gate keys off.
30
- */
31
- reducedMotion: boolean;
32
- /**
33
- * Screen-reader mode (U.11): plain, linear, announce-friendly output — no
34
- * live-region redraws (each state change is a committed line), no spinners,
35
- * status glyphs rendered as words. Opt-in via `CRUXY_SCREEN_READER` /
36
- * `ACCESSIBLE`; routes rendering to the linear path regardless of `cursor`.
37
- */
38
- screenReader: boolean;
39
- /** Unicode glyphs are safe (U.1) — false under `TERM=dumb` / `CRUXY_ASCII`;
40
- * independent of `color`. Drives the theme's glyph table, not its stylers. */
41
- unicode: boolean;
42
- /**
43
- * Terminal columns (U.12) — the ONE width source every surface reads; 80 when
44
- * unknown (non-TTY / no `columns`). Honors `COLUMNS` when set. Mutated in
45
- * place on resize (see {@link onResize}), so a surface reading it after a
46
- * SIGWINCH sees the new width without re-probing anything.
47
- */
48
- width: number;
49
- /**
50
- * Subscribe to width changes (U.12): the SIGWINCH push signal for the live
51
- * region / transient frames to reflow at the new width. The listener fires
52
- * with the new width AFTER {@link width} has been updated; the returned
53
- * function unsubscribes. Absent when the stream cannot resize (non-TTY / no
54
- * `columns`) — those surfaces just read the static {@link width}. Committed
55
- * output is never re-rendered from here; only live surfaces subscribe.
56
- */
57
- onResize?(listener: (width: number) => void): () => void;
58
- }
59
- /** Accumulated token usage the loop already tracks (U.4) — never fabricated. */
60
- export interface TokenUsage {
61
- input: number;
62
- output: number;
63
- }
64
- /**
65
- * Semantic live-state phases (U.4). The loop and the approval seam emit these
66
- * instead of format strings; renderers decide presentation per capability.
67
- * One phase is live at a time — it is a register, not a queue.
68
- */
69
- export type RenderPhase =
70
- /**
71
- * Waiting on the model. `tokens` = usage accumulated so far, omitted at 0.
72
- * `tier` = the routing tier this turn runs on (C.30), shown only when routing
73
- * is active — an honest signal of the real tier, never a fabricated one, and
74
- * always a tier name (never an upstream model id, U.8).
75
- */
76
- {
77
- kind: "thinking";
78
- tokens?: TokenUsage;
79
- tier?: string;
80
- }
81
- /** A tool call is executing; `label` is the human form ("read_file src/x.ts"). */
82
- | {
83
- kind: "calling-tool";
84
- label: string;
85
- }
86
- /** An interactive prompt owns the terminal — the live line must yield to it. */
87
- | {
88
- kind: "awaiting-approval";
89
- }
90
- /** A plan step is active but the model is not yet engaged (C.31). */
91
- | {
92
- kind: "executing-step";
93
- }
94
- /** A subagent is running its task (C.14); `label` is the (truncated) task. */
95
- | {
96
- kind: "subagent";
97
- label: string;
98
- };
99
- /**
100
- * Plan-mode step progress (U.4/C.31): rendered as a persistent `[i/n] title`
101
- * prefix on the live line. A separate register from {@link RenderPhase} with a
102
- * separate owner (the plan executor), so `endTurn` clearing the loop's phase
103
- * can never wipe step context mid-step.
104
- */
105
- export interface ProgressState {
106
- step: number;
107
- of: number;
108
- title: string;
109
- }
110
- /**
111
- * Tool-call lifecycle (U.4): `start` paints live state and starts the honest
112
- * elapsed clock; `end` commits the `✓/✗` trail note (with a duration suffix
113
- * when the measured start→end gap crossed the threshold — never estimated).
114
- */
115
- export type ToolLifecycleEvent = {
116
- event: "start";
117
- label: string;
118
- } | {
119
- event: "end";
120
- label: string;
121
- ok: boolean;
122
- };
123
- /**
124
- * How the agent loop paints a turn. The contract that keeps output flicker-free:
125
- *
126
- * - **Committed content is append-only.** `write`/`note`/`preview` output is
127
- * never repainted, moved, or cleared.
128
- * - **Transient state is one line.** `status` owns a single live line that is
129
- * redrawn in place and erased before any committed write lands.
130
- *
131
- * Call shape per user turn: `beginTurn` → per model turn: `write`* +
132
- * `endSegment`, with `status`/`note`/`preview` between segments → `endTurn`.
133
- * All methods must be safe to call in any environment — degradation is the
134
- * implementation's job, not the caller's.
135
- */
136
- export interface StreamRenderer {
137
- readonly caps: RenderCapabilities;
138
- /** The one resolved design system (U.1) — glyphs/roles for chrome a
139
- * surface emits through this renderer (e.g. the subagent trail notes). */
140
- readonly theme: Theme;
141
- /** Start a user turn: reset leading-newline trim and code-fence state. */
142
- beginTurn(): void;
143
- /**
144
- * Append streamed assistant text. Must forward promptly — implementations may
145
- * hold back at most the current line (for fence detection), never the block
146
- * or the response. Dismisses any live status first.
147
- */
148
- write(delta: string): void;
149
- /**
150
- * Close one model-turn text segment: flush any held partial line / open
151
- * fence and terminate with a single newline (only if the segment produced
152
- * visible text), so whatever follows starts on its own line.
153
- */
154
- endSegment(): void;
155
- /** A committed one-line chrome note (e.g. `✓ read_file src/x.ts`), dim when colored. */
156
- note(text: string): void;
157
- /** A committed diff/action preview, rendered by the shared diff renderer. */
158
- preview(preview: ActionPreview): void;
159
- /**
160
- * Replace the transient status line ("thinking…", "running bash…"); `null`
161
- * clears it. Where in-place updates are impossible this may drop the text —
162
- * status is progress decor, never information of record (use `note` for that).
163
- * Ad-hoc/legacy; production callers use the typed U.4 methods below.
164
- */
165
- status(text: string | null): void;
166
- /**
167
- * Set (or clear) the semantic live phase (U.4). Rendered into the same
168
- * managed status line; `awaiting-approval` yields the line to the prompt.
169
- * PlainRenderer drops phases — transient state has no meaning append-only.
170
- */
171
- setPhase(phase: RenderPhase | null): void;
172
- /**
173
- * Set (or clear) plan-step progress (U.4). Persists across phase changes and
174
- * `endTurn` — only the plan executor clears it. Rendered as an `[i/n] title`
175
- * prefix on the live line; dropped by PlainRenderer.
176
- */
177
- progress(state: ProgressState | null): void;
178
- /**
179
- * Tool-call lifecycle (U.4): `start` → live "label…" state (+ elapsed clock),
180
- * `end` → the committed `✓/✗ label` note, with an honest duration suffix for
181
- * long calls. Replaces the loop's ad-hoc status/note pair.
182
- */
183
- toolLifecycle(event: ToolLifecycleEvent): void;
184
- /**
185
- * The interactive prompt released the terminal (its key/line read resolved):
186
- * the pair-closer for `awaiting-approval`. Restores the phase the prompt
187
- * displaced — with its original clock, so a long tool call approved late
188
- * still reports honest wall-time. No-op where there is no live region.
189
- */
190
- promptResolved(): void;
191
- /** End the user turn: clear any status and the live phase (never progress), flush everything held. */
192
- endTurn(): void;
193
- /** Release resources (spinner timer). Further calls are no-ops. */
194
- close(): void;
195
- }
196
- /** The minimal stream surface a renderer writes to. Injectable for tests. */
197
- export interface RenderStream {
198
- isTTY?: boolean;
199
- columns?: number;
200
- write(text: string): unknown;
201
- }
@@ -1,2 +0,0 @@
1
- export * from "./types.js";
2
- export { ConfigRouter, DEFAULT_TIER, routerForConfig, resolveTaskModel, } from "./router.js";
@@ -1,17 +0,0 @@
1
- import type { Tier } from "./types.js";
2
- /**
3
- * Tier → gateway wire model-id. This is the SINGLE place the mapping lives, and
4
- * it is INTERNAL to the routing package (deliberately not re-exported from the
5
- * barrel) so it can never be called from a user-facing render path.
6
- *
7
- * For the Cruxy gateway a tier IS the wire model id — the gateway maps the tier
8
- * to a concrete upstream model SERVER-SIDE. So this returns the tier name
9
- * unchanged: the output is always a tier, and no upstream model name can
10
- * originate here. That property is what keeps the U.8 gag structural rather than
11
- * a filter — there is no upstream id in the process to leak (see the tier-gag
12
- * test, which asserts this output is always a MODEL_TIERS member).
13
- *
14
- * The seam exists for a future provider whose tiers map to distinct wire ids;
15
- * that mapping would live here and here only.
16
- */
17
- export declare function resolveModelId(tier: Tier): string;
@@ -1,47 +0,0 @@
1
- import type { CruxyConfig } from "../config/index.js";
2
- import type { Router, RoutingConfig, TaskClass, Tier } from "./types.js";
3
- /**
4
- * The tier a config resolves to when nothing else pins one down — mirrors the
5
- * gateway's `auto` fallback (`AUTO_FALLBACK_TIER` in the SDK), so an unrouted
6
- * cruxy session lands on exactly the tier it does today.
7
- */
8
- export declare const DEFAULT_TIER: Tier;
9
- /**
10
- * The config-driven {@link Router}: maps a declared task class to a tier from
11
- * `{ default, map }`, and fails loud when the resolved tier is not offered. It
12
- * NEVER inspects prompt content — selection is purely `map[taskClass] ?? default`.
13
- */
14
- export declare class ConfigRouter implements Router {
15
- private readonly cfg;
16
- private readonly offered;
17
- /**
18
- * @param cfg the resolved routing table (default tier + per-task map)
19
- * @param offered the tiers this gateway/plan actually provides; a resolved
20
- * tier outside this set fails loud. Defaults to all tiers — the
21
- * seam a future entitlement check narrows (never a silent
22
- * downgrade).
23
- */
24
- constructor(cfg: RoutingConfig, offered?: Iterable<Tier>);
25
- select(taskClass: TaskClass): Tier;
26
- }
27
- /**
28
- * Build a router from resolved config, or `null` when routing should stay
29
- * inert. Routing is:
30
- *
31
- * - a cruxy-gateway concept — tiers do not apply to BYO providers, so non-cruxy
32
- * providers get `null` (no override, their `model.model` is used unchanged);
33
- * - opt-in — with no `routing.default` and an empty `routing.map`, this returns
34
- * `null` so behavior (and the wire body, and the state line) is byte-identical
35
- * to today. Multi-tier routing activates only once the user configures it.
36
- */
37
- export declare function routerForConfig(config: CruxyConfig): Router | null;
38
- /**
39
- * Resolve a declared task class to `{ tier, model }`: the tier for honest
40
- * surfacing (the U.4 state line), the wire model id for the request. The model
41
- * id comes from the internal {@link resolveModelId} — callers never touch that
42
- * mapping directly, so it stays the single source of truth.
43
- */
44
- export declare function resolveTaskModel(router: Router, taskClass: TaskClass): {
45
- tier: Tier;
46
- model: string;
47
- };
@@ -1,42 +0,0 @@
1
- import { MODEL_TIERS } from "../brand/voice.js";
2
- /**
3
- * Multi-model routing (C.30): route each unit of work to the right tier instead
4
- * of running one model for everything. The caller DECLARES a {@link TaskClass}
5
- * at the call site; a {@link Router} maps that class to a {@link Tier} via config
6
- * — it never sniffs the prompt to guess difficulty. The tier→gateway model-id
7
- * mapping is internal (see `resolve.ts`); only tier names ever appear in config,
8
- * logs, errors, or the state line (the U.8 tier gag).
9
- */
10
- /**
11
- * The unit-of-work classes a caller can declare. Each is an explicit intent —
12
- * NOT a difficulty the router infers. Unknown/unset resolves to the router's
13
- * default tier, never a crash.
14
- */
15
- export declare const TASK_CLASSES: readonly ["main-turn", "subagent", "plan", "commit-msg", "classify", "summarize"];
16
- export type TaskClass = (typeof TASK_CLASSES)[number];
17
- /** A routing tier — the ONLY model vocabulary the user ever sees (U.8). */
18
- export type Tier = (typeof MODEL_TIERS)[number];
19
- /**
20
- * Selects a tier for a declared task class. Deliberately one method: the caller
21
- * passes intent, the router returns a tier from its configured mapping. No
22
- * prompt-content inspection, ever — difficulty detection is explicitly out of
23
- * scope (a caller declares; the router does not guess).
24
- */
25
- export interface Router {
26
- /**
27
- * Map a task class to its tier. Falls back to the configured default when the
28
- * class has no explicit mapping; throws `CRUXY_E_ROUTING_TIER_UNAVAILABLE`
29
- * (fail loud, never a silent substitution) when the resolved tier is not
30
- * offered.
31
- */
32
- select(taskClass: TaskClass): Tier;
33
- }
34
- /**
35
- * The declarative routing table: a `default` tier plus per-task overrides. Lives
36
- * in config (`routing.default`, `routing.map`). An empty map means every class
37
- * resolves to `default` — a single tier, no traffic splitting.
38
- */
39
- export interface RoutingConfig {
40
- default: Tier;
41
- map: Partial<Record<TaskClass, Tier>>;
42
- }
@@ -1,22 +0,0 @@
1
- import type { SandboxCapability } from "./types.js";
2
- /**
3
- * Runtime detection (C.16): a container runtime is a *capability*, not an
4
- * assumption. Presence means both that the binary exists AND its daemon
5
- * answers — `docker` installed with a dead daemon is NOT available, and the
6
- * caller must fail loud rather than pretend a box exists.
7
- */
8
- /** Injectable probe seam — spawns a short command and reports how it exited. */
9
- export type RuntimeProbe = (bin: string, args: string[]) => Promise<{
10
- code: number | null;
11
- stdout: string;
12
- stderr: string;
13
- }>;
14
- /**
15
- * Detect the Docker runtime. `docker version --format {{.Server.Version}}`
16
- * exits non-zero when the daemon is unreachable (even though the client is
17
- * installed), so a zero exit with a server version is the honest "available"
18
- * signal. Memoized for the process; pass a probe (tests) to bypass the cache.
19
- */
20
- export declare function detectDocker(probe?: RuntimeProbe): Promise<SandboxCapability>;
21
- /** Clear the memoized capability (tests). */
22
- export declare function resetDetectionCache(): void;
@@ -1,32 +0,0 @@
1
- import type { ExecOptions, ExecResult, IsolationPolicy, SandboxRuntime } from "./types.js";
2
- /**
3
- * The shipped {@link SandboxRuntime}: shells out to the `docker` CLI (no SDK —
4
- * matches the no-vendor-client ethos). {@link buildRunArgs} is a pure function
5
- * so the entire isolation posture can be asserted from the argv without a live
6
- * daemon; `exec` spawns docker, captures bias-capped output, enforces the
7
- * wall-clock timeout by force-killing the container, and maps the result.
8
- *
9
- * The exit code from `docker run` is the command's own — EXCEPT `125`, which
10
- * docker reserves for "the run itself failed" (bad flags, daemon error): that,
11
- * and a spawn failure, are the only container-start failures, surfaced as a
12
- * coded {@link sandboxExec} error. An ordinary non-zero command exit is a
13
- * normal result (exit code is truth), never a thrown error and never a host run.
14
- */
15
- export declare class DockerRuntime implements SandboxRuntime {
16
- private readonly bin;
17
- readonly name = "docker";
18
- constructor(bin?: string);
19
- ensureImage(image: string, onPull?: () => void): Promise<void>;
20
- /** Run a non-container docker subcommand to completion, capturing output. */
21
- private simpleRun;
22
- exec(command: string, policy: IsolationPolicy, opts: ExecOptions): Promise<ExecResult>;
23
- private run;
24
- /** Best-effort container teardown after a timeout kill. */
25
- private forceRemove;
26
- }
27
- /**
28
- * Build the `docker run` argv from a resolved policy. Pure and total — the
29
- * single source of truth for the isolation boundary, asserted directly in
30
- * tests. Order is stable for readability; docker is order-insensitive for flags.
31
- */
32
- export declare function buildRunArgs(policy: IsolationPolicy, container: string, command: string): string[];
@@ -1,7 +0,0 @@
1
- export * from "./types.js";
2
- export { detectDocker, resetDetectionCache } from "./detect.js";
3
- export type { RuntimeProbe } from "./detect.js";
4
- export { DockerRuntime, buildRunArgs } from "./docker-runtime.js";
5
- export { buildPolicy } from "./policy.js";
6
- export { SandboxService } from "./service.js";
7
- export type { SandboxReporter, SandboxServiceDeps } from "./service.js";
@@ -1,26 +0,0 @@
1
- import type { SandboxConfig } from "../config/index.js";
2
- import type { IsolationPolicy } from "./types.js";
3
- /**
4
- * Turn a validated {@link SandboxConfig} + the run's cwd into a fully-resolved
5
- * {@link IsolationPolicy}. This is where the security posture is decided, and
6
- * every default here is deny/minimal:
7
- *
8
- * - the DEFAULT read-write mount is the command's own project workdir (at its
9
- * identical absolute path, so paths stay coherent with the host and the C.32
10
- * checkpoint);
11
- * - other declared roots in a multi-repo session (C.26, R5) are mounted READ-ONLY
12
- * — readable for legit cross-repo builds, never writable unless an explicit
13
- * per-command escalation names that root in `writableRoots`;
14
- * - extra mounts come solely from `sandbox.mounts` (explicit by construction),
15
- * and a mount of the docker socket, the cruxy home, or the user's home root
16
- * is rejected — those are the escape hatches we refuse to open;
17
- * - the container runs as the host's non-root uid:gid so mounted edits are
18
- * writable and never left root-owned;
19
- * - network defaults to `none`; any widening can only come from explicit config.
20
- */
21
- export declare function buildPolicy(cfg: SandboxConfig, cwd: string, opts?: {
22
- /** Absolute paths of the OTHER declared roots (this command's siblings). */
23
- siblingRoots?: readonly string[];
24
- /** Sibling roots that got an approved cross-root-write escalation (R5). */
25
- writableRoots?: readonly string[];
26
- }): IsolationPolicy;
@@ -1,64 +0,0 @@
1
- import type { CruxyConfig } from "../config/index.js";
2
- import type { ExecOptions, ExecResult, IsolationPolicy, SandboxCapability, SandboxRuntime } from "./types.js";
3
- /**
4
- * The minimal surface the sandbox needs to report a first-run image pull
5
- * through the U.4 state layer. `StreamRenderer` satisfies it structurally, so
6
- * callers pass the renderer directly and the sandbox stays render-decoupled.
7
- */
8
- export interface SandboxReporter {
9
- status(text: string | null): void;
10
- }
11
- export interface SandboxServiceDeps {
12
- config: CruxyConfig;
13
- /** The command's own workspace root — mounted read-write as the workdir. */
14
- cwd: string;
15
- /** The OTHER declared roots in a multi-repo session (C.26, R5). Each is
16
- * mounted READ-ONLY so cross-repo reads work but a command can't silently
17
- * write a sibling. Empty/absent in a single-root session. */
18
- siblingRoots?: readonly string[];
19
- /** Sibling roots granted an approved cross-root-write escalation (R5): each
20
- * named one flips to read-write, and ONLY that one — never blanket. */
21
- writableRoots?: readonly string[];
22
- /** Execution runtime seam (defaults to Docker). */
23
- runtime?: SandboxRuntime;
24
- /** Capability probe seam (defaults to real docker detection). */
25
- detect?: () => Promise<SandboxCapability>;
26
- /** U.4 sink for the "pulling sandbox image…" line (optional). */
27
- reporter?: SandboxReporter;
28
- }
29
- /**
30
- * The sandbox execution service (C.16) — what `ToolContext.sandbox` points at.
31
- * It is only ever constructed when the sandbox is enabled, and constructing it
32
- * is where the fail-loud guarantee lives: {@link SandboxService.create} probes
33
- * the runtime and throws {@link sandboxUnavailable} if it isn't available, so a
34
- * user who asked for the box either gets the box or a loud, coded error — never
35
- * a silent drop back to host execution. `exec` then contains an approved
36
- * command inside the isolation policy, ensuring the image on first use.
37
- */
38
- export declare class SandboxService {
39
- private readonly runtime;
40
- private readonly policy;
41
- private readonly reporter?;
42
- private imageReady?;
43
- private constructor();
44
- /**
45
- * Resolve the runtime and build the policy. THROWS {@link sandboxUnavailable}
46
- * when the runtime is missing/unreachable — the caller (session wiring) lets
47
- * it propagate so the run stops before any command executes. There is no code
48
- * path from here to host execution.
49
- */
50
- static create(deps: SandboxServiceDeps): Promise<SandboxService>;
51
- /** The runtime backing this service (e.g. "docker") — for logging. */
52
- get runtimeName(): string;
53
- /** The resolved isolation policy — exposed for logging/inspection. */
54
- get isolationPolicy(): IsolationPolicy;
55
- /**
56
- * Execute an already-approved command inside the box. Ensures the image once
57
- * (surfacing the pull via U.4), then delegates to the runtime. A container
58
- * that fails to start throws a coded error; an ordinary non-zero command exit
59
- * comes back as a normal {@link ExecResult} — exit code is truth.
60
- */
61
- exec(command: string, opts: ExecOptions): Promise<ExecResult>;
62
- /** Ensure the image is present, at most once per service (memoized). */
63
- private ensureImage;
64
- }
@@ -1,123 +0,0 @@
1
- /**
2
- * Sandbox execution (C.16) — the isolation boundary beneath the U.3 gate.
3
- *
4
- * When the sandbox is enabled, the highest-risk tools (`run_command`,
5
- * `run_tests`) execute inside a container instead of directly on the host: the
6
- * project workdir is mounted so the agent edits real files, but the *process*
7
- * cannot reach the network, cannot touch the host beyond that mount, and cannot
8
- * exhaust the machine. Approval still gates every command (see U.3) — the
9
- * sandbox contains what an approved command is able to do; it does not replace
10
- * the decision to run it.
11
- *
12
- * Execution is abstracted behind {@link SandboxRuntime} (Docker ships; podman /
13
- * none slot in without touching call sites), and the neutral {@link ExecResult}
14
- * matches what host execution conceptually returns so `run_command`/`run_tests`
15
- * stay substrate-agnostic — exit code is the source of truth on either path.
16
- */
17
- /** Egress policy for the container. `none` is the default (deny all). */
18
- export type NetworkPolicy = "none" | "host-loopback" | "full";
19
- /** One resolved bind mount: an absolute host path exposed in the container. */
20
- export interface BindMount {
21
- /** Absolute host path. */
22
- readonly source: string;
23
- /** Absolute container path (the workdir mount uses `source === target`). */
24
- readonly target: string;
25
- /** Read-only when true; the workdir mount is read-write. */
26
- readonly readonly: boolean;
27
- }
28
- /**
29
- * A fully-resolved isolation policy — every knob the runtime needs, already
30
- * merged from config and validated. `docker-runtime` turns this (plus the
31
- * command) into an argv; nothing here is optional or defaulted downstream.
32
- */
33
- export interface IsolationPolicy {
34
- /** Pinned base image the container runs (never chosen dynamically). */
35
- readonly image: string;
36
- /** Egress policy — `none` unless the user deliberately widened it. */
37
- readonly network: NetworkPolicy;
38
- /** Non-root `uid:gid` the container runs as (host uid, so mounts stay writable). */
39
- readonly user: string;
40
- /** Memory cap (`--memory`, also mirrored to `--memory-swap` to disable swap). */
41
- readonly memory: string;
42
- /** Process/thread cap (`--pids-limit`). */
43
- readonly pids: number;
44
- /** CPU cap (`--cpus`, fractional allowed). */
45
- readonly cpus: number;
46
- /** The command's OWN workspace root, mounted read-write at its absolute path. */
47
- readonly workdir: BindMount;
48
- /**
49
- * The OTHER declared workspace roots in a multi-repo session (C.26, R5). Each
50
- * is mounted **read-only** so a legit build can *read* a sibling (e.g. generated
51
- * client types) — but never write it. A sibling flips to read-write ONLY when an
52
- * explicit per-command cross-root-write escalation was approved for that exact
53
- * root; ambient cross-root write authority is never the default. Empty in a
54
- * single-root session (identical to the pre-C.26 posture).
55
- */
56
- readonly siblingRoots?: readonly BindMount[];
57
- /** Extra explicit mounts beyond the workdir (from `sandbox.mounts`). */
58
- readonly mounts: readonly BindMount[];
59
- /** Writable in-memory tmp mount point; the rest of the root fs is read-only. */
60
- readonly tmpfs: string;
61
- }
62
- /** Which end of the output to keep when the byte cap is exceeded. */
63
- export type CaptureBias = "head" | "tail";
64
- /** Per-exec bounds handed to a runtime. */
65
- export interface ExecOptions {
66
- /** Host project directory → bind-mounted as the workdir (same absolute path). */
67
- readonly cwd: string;
68
- /** Wall-clock timeout in ms; overrun kills the container and returns a failure. */
69
- readonly timeoutMs: number;
70
- /** Cap on combined stdout+stderr bytes captured. */
71
- readonly maxOutputBytes: number;
72
- /**
73
- * Head-bias keeps the start of the output (`run_command`); tail-bias keeps
74
- * the end, where test runners print their failure summaries (`run_tests`).
75
- */
76
- readonly capture: CaptureBias;
77
- }
78
- /**
79
- * The neutral outcome of one sandboxed execution — the SAME shape host
80
- * execution conceptually produces, so both `run_command` and `run_tests` map it
81
- * to their own result type without caring which substrate ran the command.
82
- */
83
- export interface ExecResult {
84
- /** Process exit code; `null` on a signal kill / timeout. Exit code is truth. */
85
- readonly exitCode: number | null;
86
- /** Combined stdout+stderr, already bias-capped to `maxOutputBytes`. */
87
- readonly output: string;
88
- /** True when output was dropped to honor the cap. */
89
- readonly outputTruncated: boolean;
90
- /** Measured wall-clock duration of the execution. */
91
- readonly durationMs: number;
92
- /** True when the wall-clock timeout fired and the container was killed. */
93
- readonly timedOut: boolean;
94
- }
95
- /**
96
- * The swappable execution seam. Docker ships as {@link DockerRuntime}; a future
97
- * podman/other runtime implements this without touching the tools or service.
98
- * `exec` never falls back to the host and never throws for an ordinary non-zero
99
- * command exit — it throws only when the container itself cannot run (a coded
100
- * {@link CruxyError}), so the fail-loud guarantee is structural.
101
- */
102
- export interface SandboxRuntime {
103
- /** Identifier surfaced in errors/logs (e.g. "docker"). */
104
- readonly name: string;
105
- /**
106
- * Ensure `image` is present locally, pulling it if needed. `onPull` fires
107
- * once, only if a pull actually starts (so callers can surface it via U.4).
108
- * Throws a coded {@link CruxyError} on pull/build failure — never silently
109
- * substitutes another image.
110
- */
111
- ensureImage(image: string, onPull?: () => void): Promise<void>;
112
- /** Run `command` inside the box under `policy`, returning a neutral result. */
113
- exec(command: string, policy: IsolationPolicy, opts: ExecOptions): Promise<ExecResult>;
114
- }
115
- /** Result of probing for a container runtime; presence is a capability. */
116
- export interface SandboxCapability {
117
- /** True when the runtime binary exists AND its daemon is reachable. */
118
- readonly available: boolean;
119
- /** The runtime that was probed. */
120
- readonly runtime: string;
121
- /** Why it's unavailable (for the fail-loud error), when not available. */
122
- readonly detail?: string;
123
- }
@@ -1,4 +0,0 @@
1
- export * from "./types.js";
2
- export * from "./parser.js";
3
- export * from "./loader.js";
4
- export * from "./service.js";
@@ -1,43 +0,0 @@
1
- import { CruxyError } from "../errors/index.js";
2
- import { type Skill, type SkillCatalog, type SkillError, type SkillSource } from "./types.js";
3
- /** The three source directories the loader scans. */
4
- export interface LoaderSources {
5
- /** `<cwd>/.cruxy/skills` */
6
- project: string;
7
- /** `~/.cruxy/skills` */
8
- user: string;
9
- /** `<pkg>/skills` (shipped). */
10
- builtin: string;
11
- }
12
- /** A valid skill discovered in a source, before precedence is resolved. */
13
- interface SkillCandidate {
14
- name: string;
15
- description: string;
16
- source: SkillSource;
17
- dir: string;
18
- }
19
- /** Thrown by `getSkill` when no catalog entry matches the requested name. */
20
- export declare class SkillNotFoundError extends CruxyError {
21
- constructor(message: string);
22
- }
23
- /**
24
- * Scan all three sources, validate every SKILL.md, and resolve precedence into a
25
- * {@link SkillCatalog}. Validation failures become {@link SkillError}s (excluded
26
- * from the catalog, surfaced in `cruxy skills --status`) rather than throwing —
27
- * one bad skill never breaks the rest.
28
- */
29
- export declare function loadCatalog(sources: LoaderSources): Promise<SkillCatalog>;
30
- /**
31
- * Resolve candidates into a catalog. Pure (no I/O) so precedence and collision
32
- * rules are directly testable. `candidates` must arrive in precedence order
33
- * (project first); the first occurrence of a name wins across sources, while a
34
- * second occurrence *within the same source* is a loud, excluded error.
35
- */
36
- export declare function resolvePrecedence(candidates: SkillCandidate[], baseErrors?: SkillError[]): SkillCatalog;
37
- /**
38
- * Read a skill's full body and resolve its asset paths on demand. The body is
39
- * re-read from disk every call (never cached), so edits are always live. Throws
40
- * {@link SkillNotFoundError} if `name` isn't in the catalog.
41
- */
42
- export declare function getSkill(catalog: SkillCatalog, name: string): Promise<Skill>;
43
- export {};