@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.
- package/dist/agent/loop.js +3 -0
- package/dist/agent/session.js +2 -1
- package/dist/theme/tokens.js +3 -0
- package/dist/usage/collect.js +41 -2
- package/dist/usage/index.js +1 -1
- package/dist/usage/summary.js +19 -0
- package/dist/usage/types.js +9 -0
- package/package.json +1 -1
- package/dist/agent/budget.d.ts +0 -52
- package/dist/agent/index.d.ts +0 -3
- package/dist/agent/loop.d.ts +0 -159
- package/dist/agent/prompts.d.ts +0 -69
- package/dist/agent/session.d.ts +0 -212
- package/dist/approval/classify.d.ts +0 -18
- package/dist/approval/index.d.ts +0 -6
- package/dist/approval/mutex.d.ts +0 -45
- package/dist/approval/policy.d.ts +0 -43
- package/dist/approval/prompt.d.ts +0 -48
- package/dist/approval/service.d.ts +0 -36
- package/dist/approval/types.d.ts +0 -82
- package/dist/brand/index.d.ts +0 -1
- package/dist/brand/voice.d.ts +0 -94
- package/dist/checkpoint/capture.d.ts +0 -17
- package/dist/checkpoint/gate-hook.d.ts +0 -28
- package/dist/checkpoint/gate.d.ts +0 -71
- package/dist/checkpoint/git-store.d.ts +0 -61
- package/dist/checkpoint/index.d.ts +0 -10
- package/dist/checkpoint/restore.d.ts +0 -23
- package/dist/checkpoint/service.d.ts +0 -89
- package/dist/checkpoint/set-rollback.d.ts +0 -51
- package/dist/checkpoint/set.d.ts +0 -44
- package/dist/checkpoint/shadow-store.d.ts +0 -23
- package/dist/checkpoint/types.d.ts +0 -164
- package/dist/cli/commands/checkpoint.d.ts +0 -7
- package/dist/cli/commands/config.d.ts +0 -2
- package/dist/cli/commands/hooks.d.ts +0 -8
- package/dist/cli/commands/index.d.ts +0 -7
- package/dist/cli/commands/init.d.ts +0 -7
- package/dist/cli/commands/login.d.ts +0 -8
- package/dist/cli/commands/mcp.d.ts +0 -9
- package/dist/cli/commands/memory.d.ts +0 -8
- package/dist/cli/commands/pr.d.ts +0 -8
- package/dist/cli/commands/rollback.d.ts +0 -18
- package/dist/cli/commands/run.d.ts +0 -2
- package/dist/cli/commands/skills.d.ts +0 -8
- package/dist/cli/commands/test.d.ts +0 -9
- package/dist/cli/commands/usage.d.ts +0 -9
- package/dist/cli/onboard.d.ts +0 -25
- package/dist/cli/program.d.ts +0 -2
- package/dist/cli/repl.d.ts +0 -27
- package/dist/cli/session-factory.d.ts +0 -42
- package/dist/cli/stream-print.d.ts +0 -14
- package/dist/components/autocomplete.d.ts +0 -32
- package/dist/components/frame.d.ts +0 -28
- package/dist/components/fuzzy.d.ts +0 -61
- package/dist/components/index.d.ts +0 -6
- package/dist/components/input.d.ts +0 -78
- package/dist/components/keys.d.ts +0 -48
- package/dist/components/select.d.ts +0 -28
- package/dist/config/credentials.d.ts +0 -18
- package/dist/config/index.d.ts +0 -5
- package/dist/config/manager.d.ts +0 -39
- package/dist/config/owner-only.d.ts +0 -19
- package/dist/config/paths.d.ts +0 -9
- package/dist/config/project.d.ts +0 -10
- package/dist/config/schema.d.ts +0 -2143
- package/dist/constants.d.ts +0 -65
- package/dist/errors/boundary.d.ts +0 -43
- package/dist/errors/constructors.d.ts +0 -411
- package/dist/errors/format.d.ts +0 -31
- package/dist/errors/index.d.ts +0 -4
- package/dist/errors/types.d.ts +0 -270
- package/dist/hooks/config.d.ts +0 -21
- package/dist/hooks/index.d.ts +0 -7
- package/dist/hooks/router.d.ts +0 -58
- package/dist/hooks/runner.d.ts +0 -88
- package/dist/hooks/service.d.ts +0 -38
- package/dist/hooks/slash.d.ts +0 -48
- package/dist/hooks/trust.d.ts +0 -46
- package/dist/hooks/types.d.ts +0 -147
- package/dist/index.d.ts +0 -2
- package/dist/indexing/chunker.d.ts +0 -28
- package/dist/indexing/embedder.d.ts +0 -98
- package/dist/indexing/index.d.ts +0 -9
- package/dist/indexing/indexer.d.ts +0 -45
- package/dist/indexing/retriever.d.ts +0 -61
- package/dist/indexing/service.d.ts +0 -49
- package/dist/indexing/store.d.ts +0 -103
- package/dist/indexing/types.d.ts +0 -78
- package/dist/indexing/util.d.ts +0 -34
- package/dist/indexing/walker.d.ts +0 -53
- package/dist/jobs/approval-queue.d.ts +0 -85
- package/dist/jobs/dispatch-tool.d.ts +0 -34
- package/dist/jobs/index.d.ts +0 -6
- package/dist/jobs/log-buffer.d.ts +0 -31
- package/dist/jobs/log-renderer.d.ts +0 -32
- package/dist/jobs/manager.d.ts +0 -139
- package/dist/jobs/types.d.ts +0 -81
- package/dist/lsp/client.d.ts +0 -25
- package/dist/lsp/index.d.ts +0 -8
- package/dist/lsp/pool.d.ts +0 -48
- package/dist/lsp/registry.d.ts +0 -38
- package/dist/lsp/server.d.ts +0 -48
- package/dist/lsp/service.d.ts +0 -44
- package/dist/lsp/tools/common.d.ts +0 -50
- package/dist/lsp/tools/find-definition.d.ts +0 -23
- package/dist/lsp/tools/find-references.d.ts +0 -23
- package/dist/lsp/tools/get-diagnostics.d.ts +0 -17
- package/dist/lsp/tools/hover.d.ts +0 -23
- package/dist/lsp/tools/index.d.ts +0 -4
- package/dist/lsp/transport.d.ts +0 -39
- package/dist/lsp/types.d.ts +0 -107
- package/dist/mcp/adapter.d.ts +0 -44
- package/dist/mcp/bounds.d.ts +0 -35
- package/dist/mcp/client.d.ts +0 -19
- package/dist/mcp/demarcate.d.ts +0 -12
- package/dist/mcp/http-transport.d.ts +0 -89
- package/dist/mcp/index.d.ts +0 -12
- package/dist/mcp/service.d.ts +0 -71
- package/dist/mcp/sibling-banner.d.ts +0 -25
- package/dist/mcp/transport.d.ts +0 -30
- package/dist/mcp/trust-gate.d.ts +0 -59
- package/dist/mcp/trust.d.ts +0 -62
- package/dist/mcp/types.d.ts +0 -62
- package/dist/mcp/url-guard.d.ts +0 -48
- package/dist/memory/index.d.ts +0 -7
- package/dist/memory/recall.d.ts +0 -56
- package/dist/memory/remember-tool.d.ts +0 -28
- package/dist/memory/secrets.d.ts +0 -29
- package/dist/memory/service.d.ts +0 -92
- package/dist/memory/store.d.ts +0 -32
- package/dist/memory/trust.d.ts +0 -52
- package/dist/memory/types.d.ts +0 -101
- package/dist/net/ip-guard.d.ts +0 -55
- package/dist/onboarding/detect.d.ts +0 -26
- package/dist/onboarding/flow.d.ts +0 -28
- package/dist/onboarding/index.d.ts +0 -5
- package/dist/onboarding/io.d.ts +0 -9
- package/dist/onboarding/steps.d.ts +0 -17
- package/dist/onboarding/types.d.ts +0 -81
- package/dist/plan/approve.d.ts +0 -16
- package/dist/plan/execute.d.ts +0 -28
- package/dist/plan/index.d.ts +0 -7
- package/dist/plan/policy.d.ts +0 -26
- package/dist/plan/render.d.ts +0 -5
- package/dist/plan/service.d.ts +0 -58
- package/dist/plan/submit-plan.d.ts +0 -33
- package/dist/plan/types.d.ts +0 -60
- package/dist/render/capabilities.d.ts +0 -31
- package/dist/render/diff.d.ts +0 -18
- package/dist/render/highlight.d.ts +0 -47
- package/dist/render/index.d.ts +0 -22
- package/dist/render/layout.d.ts +0 -59
- package/dist/render/motion.d.ts +0 -76
- package/dist/render/plain-renderer.d.ts +0 -39
- package/dist/render/resize.d.ts +0 -36
- package/dist/render/screen-reader-renderer.d.ts +0 -45
- package/dist/render/state.d.ts +0 -49
- package/dist/render/tty-renderer.d.ts +0 -106
- package/dist/render/types.d.ts +0 -201
- package/dist/routing/index.d.ts +0 -2
- package/dist/routing/resolve.d.ts +0 -17
- package/dist/routing/router.d.ts +0 -47
- package/dist/routing/types.d.ts +0 -42
- package/dist/sandbox/detect.d.ts +0 -22
- package/dist/sandbox/docker-runtime.d.ts +0 -32
- package/dist/sandbox/index.d.ts +0 -7
- package/dist/sandbox/policy.d.ts +0 -26
- package/dist/sandbox/service.d.ts +0 -64
- package/dist/sandbox/types.d.ts +0 -123
- package/dist/skills/index.d.ts +0 -4
- package/dist/skills/loader.d.ts +0 -43
- package/dist/skills/parser.d.ts +0 -31
- package/dist/skills/service.d.ts +0 -41
- package/dist/skills/types.d.ts +0 -94
- package/dist/subagent/index.d.ts +0 -5
- package/dist/subagent/orchestrator.d.ts +0 -169
- package/dist/subagent/registry-scope.d.ts +0 -41
- package/dist/subagent/semaphore.d.ts +0 -56
- package/dist/subagent/spawn-tool.d.ts +0 -86
- package/dist/subagent/types.d.ts +0 -65
- package/dist/testing/detect.d.ts +0 -3
- package/dist/testing/index.d.ts +0 -5
- package/dist/testing/parse.d.ts +0 -33
- package/dist/testing/run-tests-tool.d.ts +0 -64
- package/dist/testing/runner.d.ts +0 -26
- package/dist/testing/sandbox-runner.d.ts +0 -16
- package/dist/testing/types.d.ts +0 -66
- package/dist/theme/index.d.ts +0 -2
- package/dist/theme/resolve.d.ts +0 -43
- package/dist/theme/tokens.d.ts +0 -119
- package/dist/tools/create-pull-request.d.ts +0 -27
- package/dist/tools/file/apply-patch.d.ts +0 -94
- package/dist/tools/file/edit-file.d.ts +0 -12
- package/dist/tools/file/glob.d.ts +0 -17
- package/dist/tools/file/grep-files.d.ts +0 -43
- package/dist/tools/file/index.d.ts +0 -7
- package/dist/tools/file/match.d.ts +0 -43
- package/dist/tools/file/paths.d.ts +0 -160
- package/dist/tools/file/read-file.d.ts +0 -8
- package/dist/tools/file/write-file.d.ts +0 -10
- package/dist/tools/git-status.d.ts +0 -15
- package/dist/tools/index.d.ts +0 -9
- package/dist/tools/list-files.d.ts +0 -13
- package/dist/tools/list-skills.d.ts +0 -9
- package/dist/tools/load-skill.d.ts +0 -21
- package/dist/tools/registry.d.ts +0 -23
- package/dist/tools/search-codebase.d.ts +0 -35
- package/dist/tools/shell/exec.d.ts +0 -53
- package/dist/tools/shell/index.d.ts +0 -1
- package/dist/tools/shell/resolve-shell.d.ts +0 -81
- package/dist/tools/shell/run-command.d.ts +0 -14
- package/dist/tools/types.d.ts +0 -257
- package/dist/usage/collect.d.ts +0 -40
- package/dist/usage/cost.d.ts +0 -19
- package/dist/usage/index.d.ts +0 -15
- package/dist/usage/store.d.ts +0 -37
- package/dist/usage/summary.d.ts +0 -32
- package/dist/usage/types.d.ts +0 -220
- package/dist/utils/child-tree.d.ts +0 -33
- package/dist/utils/git.d.ts +0 -17
- package/dist/utils/logger.d.ts +0 -18
- package/dist/utils/process-tree.d.ts +0 -16
- package/dist/vcs/auth.d.ts +0 -22
- package/dist/vcs/generate.d.ts +0 -74
- package/dist/vcs/git.d.ts +0 -60
- package/dist/vcs/github.d.ts +0 -50
- package/dist/vcs/guidance.d.ts +0 -20
- package/dist/vcs/index.d.ts +0 -7
- package/dist/vcs/service.d.ts +0 -61
- package/dist/vcs/types.d.ts +0 -73
- package/dist/web/demarcate.d.ts +0 -13
- package/dist/web/fetch.d.ts +0 -11
- package/dist/web/index.d.ts +0 -7
- package/dist/web/provider.d.ts +0 -29
- package/dist/web/search.d.ts +0 -17
- package/dist/web/ssrf.d.ts +0 -41
- package/dist/web/tools.d.ts +0 -20
- package/dist/web/types.d.ts +0 -64
- package/dist/workspace/add-root.d.ts +0 -27
- package/dist/workspace/index.d.ts +0 -6
- package/dist/workspace/resolve.d.ts +0 -54
- package/dist/workspace/select.d.ts +0 -41
- package/dist/workspace/types.d.ts +0 -30
- package/dist/workspace/workspace.d.ts +0 -61
package/dist/agent/loop.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CruxyError, providerUnsupported } from "../errors/index.js";
|
|
2
2
|
import { resolveTaskModel, } from "../routing/index.js";
|
|
3
|
+
import { accumulateCacheTokens } from "../usage/collect.js";
|
|
3
4
|
import { buildSystemPrompt } from "./prompts.js";
|
|
4
5
|
import { resolveShell } from "../tools/shell/resolve-shell.js";
|
|
5
6
|
/** Tools whose successful call is a file change (drives the `on-file-change`
|
|
@@ -155,12 +156,14 @@ async function driveLoop(args, renderer, routed) {
|
|
|
155
156
|
case "usage":
|
|
156
157
|
usage.input_tokens = ev.usage.input_tokens || usage.input_tokens;
|
|
157
158
|
usage.output_tokens += ev.usage.output_tokens;
|
|
159
|
+
accumulateCacheTokens(usage, ev.usage);
|
|
158
160
|
// Mirror the accumulation into the per-request figure the telemetry
|
|
159
161
|
// callback reports (same last-non-zero-in / summed-out semantics).
|
|
160
162
|
sawUsage = true;
|
|
161
163
|
reqUsage.input_tokens =
|
|
162
164
|
ev.usage.input_tokens || reqUsage.input_tokens;
|
|
163
165
|
reqUsage.output_tokens += ev.usage.output_tokens;
|
|
166
|
+
accumulateCacheTokens(reqUsage, ev.usage);
|
|
164
167
|
break;
|
|
165
168
|
case "message_stop":
|
|
166
169
|
// Turn complete; the stream ends after this.
|
package/dist/agent/session.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { loadProjectInstructions } from "../config/index.js";
|
|
3
3
|
import { resolveTaskModel } from "../routing/index.js";
|
|
4
|
-
import { UsageCollector, } from "../usage/index.js";
|
|
4
|
+
import { UsageCollector, accumulateCacheTokens, } from "../usage/index.js";
|
|
5
5
|
import { Budget } from "./budget.js";
|
|
6
6
|
import { runAgent, } from "./loop.js";
|
|
7
7
|
import { SUMMARY_SYSTEM, COMPACTION_MARKER } from "./prompts.js";
|
|
@@ -345,6 +345,7 @@ export class Session {
|
|
|
345
345
|
case "usage":
|
|
346
346
|
usage.input_tokens = ev.usage.input_tokens || usage.input_tokens;
|
|
347
347
|
usage.output_tokens += ev.usage.output_tokens;
|
|
348
|
+
accumulateCacheTokens(usage, ev.usage);
|
|
348
349
|
sawUsage = true;
|
|
349
350
|
break;
|
|
350
351
|
case "error":
|
package/dist/theme/tokens.js
CHANGED
|
@@ -20,6 +20,7 @@ export const UNICODE_GLYPHS = {
|
|
|
20
20
|
arrow: "→",
|
|
21
21
|
caretUp: "↑",
|
|
22
22
|
caretDown: "↓",
|
|
23
|
+
cached: "↻",
|
|
23
24
|
cursorBar: "▏",
|
|
24
25
|
bullet: "•",
|
|
25
26
|
sep: "·",
|
|
@@ -42,6 +43,7 @@ export const ASCII_GLYPHS = {
|
|
|
42
43
|
arrow: "->",
|
|
43
44
|
caretUp: "^",
|
|
44
45
|
caretDown: "v",
|
|
46
|
+
cached: "",
|
|
45
47
|
cursorBar: "|",
|
|
46
48
|
bullet: "*",
|
|
47
49
|
sep: "-",
|
|
@@ -68,6 +70,7 @@ export const SCREEN_READER_GLYPHS = {
|
|
|
68
70
|
arrow: "->",
|
|
69
71
|
caretUp: "up",
|
|
70
72
|
caretDown: "down",
|
|
73
|
+
cached: "",
|
|
71
74
|
cursorBar: "",
|
|
72
75
|
bullet: "-",
|
|
73
76
|
sep: "-",
|
package/dist/usage/collect.js
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage collection (C.22). Accumulates per-request usage exactly as the agent
|
|
3
|
+
* loop reports it — one {@link UsageEntry} per completed model request — and
|
|
4
|
+
* emits a {@link UsageRecord} for the run.
|
|
5
|
+
*
|
|
6
|
+
* The one honesty invariant: `usage: undefined` (the loop's signal that the
|
|
7
|
+
* provider returned NO usage event for a request) is recorded as `undefined`
|
|
8
|
+
* token counts — the honest "unknown". A provider-reported `0` arrives as a real
|
|
9
|
+
* `Usage` and is stored as `0`. Nothing is estimated, re-tokenized, or
|
|
10
|
+
* zero-filled, and this module makes ZERO network calls.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Fold a streamed {@link Usage} event's cache counters into an accumulator.
|
|
14
|
+
*
|
|
15
|
+
* Phase-A prompt caching (Anthropic dev path only) reports `cache_read_*` /
|
|
16
|
+
* `cache_creation_*` ONCE per request but echoes the same value on both the
|
|
17
|
+
* `message_start` and terminal `message_delta` usage events — so we ASSIGN
|
|
18
|
+
* (never `+=`) to avoid double-counting within a request. `undefined` is left
|
|
19
|
+
* untouched: a provider that doesn't cache (the cruxy gateway, OpenAI-compat)
|
|
20
|
+
* never sets these, so the accumulator's fields stay `undefined` — the honest
|
|
21
|
+
* "unknown", never a fabricated `0`. A real reported `0` (cache in play, no read
|
|
22
|
+
* this request) is captured as `0`.
|
|
23
|
+
*/
|
|
24
|
+
export function accumulateCacheTokens(acc, ev) {
|
|
25
|
+
if (ev.cache_read_input_tokens !== undefined)
|
|
26
|
+
acc.cache_read_input_tokens = ev.cache_read_input_tokens;
|
|
27
|
+
if (ev.cache_creation_input_tokens !== undefined)
|
|
28
|
+
acc.cache_creation_input_tokens = ev.cache_creation_input_tokens;
|
|
29
|
+
}
|
|
1
30
|
const systemClock = () => new Date().toISOString();
|
|
2
31
|
export class UsageCollector {
|
|
3
32
|
now;
|
|
@@ -11,10 +40,20 @@ export class UsageCollector {
|
|
|
11
40
|
* nothing. A real reported `0` is preserved as `0`.
|
|
12
41
|
*/
|
|
13
42
|
record(req) {
|
|
43
|
+
const u = req.usage;
|
|
14
44
|
this.entries.push({
|
|
15
45
|
tier: req.tier,
|
|
16
|
-
inputTokens:
|
|
17
|
-
outputTokens:
|
|
46
|
+
inputTokens: u?.input_tokens,
|
|
47
|
+
outputTokens: u?.output_tokens,
|
|
48
|
+
// Cache counters are conditionally spread so an unreported field stays
|
|
49
|
+
// absent from the persisted entry (undefined ≠ 0) — only the Anthropic
|
|
50
|
+
// dev path ever populates them.
|
|
51
|
+
...(u?.cache_read_input_tokens !== undefined
|
|
52
|
+
? { cacheReadTokens: u.cache_read_input_tokens }
|
|
53
|
+
: {}),
|
|
54
|
+
...(u?.cache_creation_input_tokens !== undefined
|
|
55
|
+
? { cacheCreationTokens: u.cache_creation_input_tokens }
|
|
56
|
+
: {}),
|
|
18
57
|
at: this.now(),
|
|
19
58
|
});
|
|
20
59
|
}
|
package/dist/usage/index.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* ships nothing that sends. Asserted by the runtime + static no-phone-home tests.
|
|
10
10
|
*/
|
|
11
11
|
export * from "./types.js";
|
|
12
|
-
export { UsageCollector } from "./collect.js";
|
|
12
|
+
export { UsageCollector, accumulateCacheTokens, } from "./collect.js";
|
|
13
13
|
export { costFor, priceForTier } from "./cost.js";
|
|
14
14
|
export { loadUsage, appendRun, usageStorePath } from "./store.js";
|
|
15
15
|
export { summarizeRuns, renderSummary, formatCost, } from "./summary.js";
|
package/dist/usage/summary.js
CHANGED
|
@@ -5,6 +5,8 @@ export function summarizeRuns(runs, opts) {
|
|
|
5
5
|
const byTier = new Map();
|
|
6
6
|
let totalInputTokens;
|
|
7
7
|
let totalOutputTokens;
|
|
8
|
+
let totalCacheReadTokens;
|
|
9
|
+
let totalCacheCreationTokens;
|
|
8
10
|
let requests = 0;
|
|
9
11
|
let requestsWithoutUsage = 0;
|
|
10
12
|
const addKnown = (acc, v) => (v === undefined ? acc : (acc ?? 0) + v);
|
|
@@ -16,6 +18,8 @@ export function summarizeRuns(runs, opts) {
|
|
|
16
18
|
requestsWithoutUsage++;
|
|
17
19
|
totalInputTokens = addKnown(totalInputTokens, e.inputTokens);
|
|
18
20
|
totalOutputTokens = addKnown(totalOutputTokens, e.outputTokens);
|
|
21
|
+
totalCacheReadTokens = addKnown(totalCacheReadTokens, e.cacheReadTokens);
|
|
22
|
+
totalCacheCreationTokens = addKnown(totalCacheCreationTokens, e.cacheCreationTokens);
|
|
19
23
|
// Per-tier attribution only for entries that carry a tier. Untiered
|
|
20
24
|
// requests (routing inert) still count toward totals — the total stays
|
|
21
25
|
// honest — but there is no tier label to bucket them under.
|
|
@@ -29,6 +33,8 @@ export function summarizeRuns(runs, opts) {
|
|
|
29
33
|
b.requestsWithoutUsage++;
|
|
30
34
|
b.inputTokens = addKnown(b.inputTokens, e.inputTokens);
|
|
31
35
|
b.outputTokens = addKnown(b.outputTokens, e.outputTokens);
|
|
36
|
+
b.cacheReadTokens = addKnown(b.cacheReadTokens, e.cacheReadTokens);
|
|
37
|
+
b.cacheCreationTokens = addKnown(b.cacheCreationTokens, e.cacheCreationTokens);
|
|
32
38
|
byTier.set(e.tier, b);
|
|
33
39
|
}
|
|
34
40
|
}
|
|
@@ -37,6 +43,8 @@ export function summarizeRuns(runs, opts) {
|
|
|
37
43
|
tier,
|
|
38
44
|
inputTokens: b.inputTokens,
|
|
39
45
|
outputTokens: b.outputTokens,
|
|
46
|
+
cacheReadTokens: b.cacheReadTokens,
|
|
47
|
+
cacheCreationTokens: b.cacheCreationTokens,
|
|
40
48
|
requests: b.requests,
|
|
41
49
|
requestsWithoutUsage: b.requestsWithoutUsage,
|
|
42
50
|
cost: costFor(tier, b.inputTokens, b.outputTokens, opts.prices),
|
|
@@ -50,6 +58,8 @@ export function summarizeRuns(runs, opts) {
|
|
|
50
58
|
perTier,
|
|
51
59
|
totalInputTokens,
|
|
52
60
|
totalOutputTokens,
|
|
61
|
+
totalCacheReadTokens,
|
|
62
|
+
totalCacheCreationTokens,
|
|
53
63
|
totalCost,
|
|
54
64
|
priced,
|
|
55
65
|
currency: opts.currency,
|
|
@@ -106,6 +116,15 @@ export function renderSummary(summary, t) {
|
|
|
106
116
|
parts.push(totalKnown
|
|
107
117
|
? `${t.strong("total")} ${tokenText(summary.totalInputTokens, summary.totalOutputTokens, t)}${t.muted(totalCost)}`
|
|
108
118
|
: `${t.strong("total")} —`);
|
|
119
|
+
// Cache reads (phase-A caching, Anthropic dev path): shown ONLY when the
|
|
120
|
+
// provider actually reported cache usage — `undefined` on the cruxy gateway
|
|
121
|
+
// and every OpenAI-compat path, so normal users never see this segment. A
|
|
122
|
+
// reported 0 IS shown (`cached ↻0`): honest proof the counter is flowing,
|
|
123
|
+
// e.g. the first request of a run that writes the cache but reads nothing.
|
|
124
|
+
if (summary.totalCacheReadTokens !== undefined) {
|
|
125
|
+
const glyph = t.glyph.cached;
|
|
126
|
+
parts.push(t.muted(`cached ${glyph}${formatTokens(summary.totalCacheReadTokens)}`));
|
|
127
|
+
}
|
|
109
128
|
// The honesty guard on display: a visible note whenever any request went
|
|
110
129
|
// unreported, so the total above is never read as the whole story.
|
|
111
130
|
if (summary.requestsWithoutUsage > 0) {
|
package/dist/usage/types.js
CHANGED
|
@@ -22,6 +22,15 @@ export const UsageEntrySchema = z
|
|
|
22
22
|
inputTokens: z.number().int().nonnegative().optional(),
|
|
23
23
|
/** Provider-reported completion tokens; `undefined` ⇔ no usage was reported. */
|
|
24
24
|
outputTokens: z.number().int().nonnegative().optional(),
|
|
25
|
+
/**
|
|
26
|
+
* Prompt-cache tokens READ from a warm cache (phase-A caching, Anthropic dev
|
|
27
|
+
* path). `undefined` ⇔ the provider doesn't cache / reported nothing (the
|
|
28
|
+
* cruxy gateway today) — never zero-filled. Optional, so older on-disk
|
|
29
|
+
* entries without the field still parse.
|
|
30
|
+
*/
|
|
31
|
+
cacheReadTokens: z.number().int().nonnegative().optional(),
|
|
32
|
+
/** Prompt-cache tokens WRITTEN this request (the ~1.25× write premium); same `undefined`-≠-0 rule. */
|
|
33
|
+
cacheCreationTokens: z.number().int().nonnegative().optional(),
|
|
25
34
|
/** ISO-8601 timestamp the request completed. */
|
|
26
35
|
at: z.string(),
|
|
27
36
|
})
|
package/package.json
CHANGED
package/dist/agent/budget.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { Usage } from "@cruxy/sdk";
|
|
2
|
-
import type { LoopBudget } from "./loop.js";
|
|
3
|
-
/**
|
|
4
|
-
* The live budget primitive for the agent loop: iteration + token + optional
|
|
5
|
-
* wall-clock caps, checked by {@link runAgent} before every model turn (see
|
|
6
|
-
* `LoopBudget`). A tripped cap stops the run with a human-readable reason and
|
|
7
|
-
* the coherent partial history — the loop never runs unbounded.
|
|
8
|
-
*
|
|
9
|
-
* It lives beside the loop it guards: the loop defines the `LoopBudget` seam,
|
|
10
|
-
* this is its one concrete implementation, and the subagent orchestrator, the
|
|
11
|
-
* job manager, and {@link Session} (per-turn token guard) all consume it.
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* Hard caps a run executes under. `maxTokens` is always finite; `maxIterations`
|
|
15
|
-
* is finite for a subagent (bounded by construction) but may be
|
|
16
|
-
* `Number.POSITIVE_INFINITY` for a token-only guard where iteration count is
|
|
17
|
-
* bounded elsewhere (a main turn is already capped by `agent.maxIterations` in
|
|
18
|
-
* the loop). `timeoutMs` is an optional wall-clock backstop on top.
|
|
19
|
-
*/
|
|
20
|
-
export interface BudgetLimits {
|
|
21
|
-
/** Cap on the run's model turns (may be `Infinity` for a token-only guard). */
|
|
22
|
-
maxIterations: number;
|
|
23
|
-
/** Cap on the run's combined input+output tokens. */
|
|
24
|
-
maxTokens: number;
|
|
25
|
-
/** Optional wall-clock cap in milliseconds. */
|
|
26
|
-
timeoutMs?: number;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Resolve the effective limits for one spawn: start from the configured
|
|
30
|
-
* ceilings and let overrides only *narrow* them. A request above a ceiling is
|
|
31
|
-
* clamped down, not honored — "budget overrides within limits" by construction.
|
|
32
|
-
*/
|
|
33
|
-
export declare function resolveBudget(defaults: BudgetLimits, overrides?: Partial<BudgetLimits>): BudgetLimits;
|
|
34
|
-
/**
|
|
35
|
-
* A live budget for one run. The wall clock starts at construction (spawn /
|
|
36
|
-
* turn start); the clock source is injectable so tests never sleep.
|
|
37
|
-
*/
|
|
38
|
-
export declare class Budget implements LoopBudget {
|
|
39
|
-
private readonly limits;
|
|
40
|
-
private readonly now;
|
|
41
|
-
private readonly startedAt;
|
|
42
|
-
constructor(limits: BudgetLimits, now?: () => number);
|
|
43
|
-
/**
|
|
44
|
-
* The reason to stop before the next model turn, or `null` to continue.
|
|
45
|
-
* Checked at iteration boundaries — the in-flight turn always completes, so
|
|
46
|
-
* overshoot is bounded by one turn.
|
|
47
|
-
*/
|
|
48
|
-
exceeded(state: {
|
|
49
|
-
iterations: number;
|
|
50
|
-
usage: Usage;
|
|
51
|
-
}): string | null;
|
|
52
|
-
}
|
package/dist/agent/index.d.ts
DELETED
package/dist/agent/loop.d.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import type { Message, Provider, Usage } from "@cruxy/sdk";
|
|
2
|
-
import type { CruxyConfig } from "../config/index.js";
|
|
3
|
-
import type { HookEvent } from "../hooks/index.js";
|
|
4
|
-
import type { StreamRenderer } from "../render/index.js";
|
|
5
|
-
import { type Router, type TaskClass } from "../routing/index.js";
|
|
6
|
-
import type { ToolContext } from "../tools/index.js";
|
|
7
|
-
import { ToolRegistry } from "../tools/index.js";
|
|
8
|
-
/** Optional per-fire context (C.26 step 5). For tool-scoped events the loop
|
|
9
|
-
* passes the raw tool-call `input` so a multi-root {@link HookRouter} can resolve
|
|
10
|
-
* the ONE acting root and fire only that root's hooks. Session lifecycle events
|
|
11
|
-
* (`before-run`/`after-run`) carry no hint — they have no acting root and fan
|
|
12
|
-
* every trusted root. Ignored by the single-root runner. */
|
|
13
|
-
export interface HookFireHint {
|
|
14
|
-
input?: unknown;
|
|
15
|
-
}
|
|
16
|
-
/** The lifecycle-hook firing seam (C.19). Structural so the loop stays
|
|
17
|
-
* decoupled from the concrete `HookRunner`. `fire` resolves when hooks pass (or
|
|
18
|
-
* advisory ones fail) and throws `CRUXY_E_HOOK_FAILED` on a blocking failure. */
|
|
19
|
-
export interface LifecycleHookRunner {
|
|
20
|
-
fire(event: HookEvent, ctx: ToolContext, hint?: HookFireHint): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
export interface RunAgentArgs {
|
|
23
|
-
/**
|
|
24
|
-
* The full running conversation. The caller owns history and must append the
|
|
25
|
-
* user turn before calling; `runAgent` does not fabricate the initial array.
|
|
26
|
-
*/
|
|
27
|
-
messages: Message[];
|
|
28
|
-
/** A constructed provider to stream from. */
|
|
29
|
-
provider: Provider;
|
|
30
|
-
/** The tool catalogue advertised to the model and dispatched against. */
|
|
31
|
-
registry: ToolRegistry;
|
|
32
|
-
/** Resolved CLI configuration (turn ceiling, etc.). */
|
|
33
|
-
config: CruxyConfig;
|
|
34
|
-
/** Ambient capabilities handed to each tool. */
|
|
35
|
-
ctx: ToolContext;
|
|
36
|
-
/**
|
|
37
|
-
* The render seam (U.2): assistant text streams through `renderer.write`
|
|
38
|
-
* delta by delta (each non-empty segment closed via `endSegment`), and
|
|
39
|
-
* tool-call progress is surfaced as transient `status` + committed `note`
|
|
40
|
-
* lines. When omitted, behavior is unchanged (one buffered print per turn,
|
|
41
|
-
* no tool-call chrome). The loop never touches stdout directly.
|
|
42
|
-
*/
|
|
43
|
-
renderer?: StreamRenderer;
|
|
44
|
-
/** Git context (branch + dirty) for the system prompt's Environment section. */
|
|
45
|
-
git?: {
|
|
46
|
-
branch: string;
|
|
47
|
-
dirty: boolean;
|
|
48
|
-
} | null;
|
|
49
|
-
/** Project instructions (e.g. from CRUXY.md) folded into the system prompt. */
|
|
50
|
-
projectInstructions?: string | null;
|
|
51
|
-
/** Persistent memory (C.29): the pre-rendered recall block for the system
|
|
52
|
-
* prompt, or null. Reference data only — never influences the U.3 gate. */
|
|
53
|
-
recalledMemory?: string | null;
|
|
54
|
-
/** Plan mode's propose phase (C.31): inject the plan-first system directive. */
|
|
55
|
-
planMode?: boolean;
|
|
56
|
-
/** Subagent runs (C.14): inject the bounded-subtask system directive. */
|
|
57
|
-
subagent?: boolean;
|
|
58
|
-
/**
|
|
59
|
-
* Optional hard budget (C.14): checked before every model turn; a non-null
|
|
60
|
-
* reason stops the loop with `stop: "budget"` and the partial history. The
|
|
61
|
-
* in-flight turn (model call + its tool executions) always completes, so
|
|
62
|
-
* histories stay coherent — overshoot is bounded by one turn.
|
|
63
|
-
*/
|
|
64
|
-
budget?: LoopBudget;
|
|
65
|
-
/**
|
|
66
|
-
* Lifecycle hooks (C.19). When set, `before-tool` fires before each tool call
|
|
67
|
-
* (a blocking failure fails the call closed — the tool does NOT run), and
|
|
68
|
-
* `after-tool` / `on-file-change` fire after. Omitted for subagents and the
|
|
69
|
-
* no-hooks path, so their tools never fire hooks.
|
|
70
|
-
*/
|
|
71
|
-
hooks?: LifecycleHookRunner;
|
|
72
|
-
/**
|
|
73
|
-
* Multi-model routing (C.30): when set, the tier for `taskClass` is resolved
|
|
74
|
-
* ONCE up front (fail loud before any model turn) and its wire model overrides
|
|
75
|
-
* the provider default for every turn in this run; the tier is surfaced on the
|
|
76
|
-
* live line. Omitted → no override, the provider's default model is used
|
|
77
|
-
* (unchanged behavior).
|
|
78
|
-
*/
|
|
79
|
-
router?: Router;
|
|
80
|
-
/** The declared task class for routing; defaults to `main-turn`. Ignored
|
|
81
|
-
* unless `router` is set. */
|
|
82
|
-
taskClass?: TaskClass;
|
|
83
|
-
/**
|
|
84
|
-
* Usage telemetry (C.22): fired ONCE per completed model request with the
|
|
85
|
-
* routing tier (C.30) and the provider's usage for THAT request — or
|
|
86
|
-
* `usage: undefined` when the provider emitted no usage event, so the caller
|
|
87
|
-
* records it as unknown (never a fabricated zero). LOCAL accounting only:
|
|
88
|
-
* this is a callback into the process, nothing is transmitted. Omitted → no
|
|
89
|
-
* collection, behavior unchanged.
|
|
90
|
-
*/
|
|
91
|
-
onRequestUsage?: (req: {
|
|
92
|
-
tier?: string;
|
|
93
|
-
usage?: Usage;
|
|
94
|
-
}) => void;
|
|
95
|
-
/**
|
|
96
|
-
* Cooperative cancellation (C.33). When the signal aborts, the loop stops at
|
|
97
|
-
* the NEXT turn boundary and returns `stop: "aborted"` with the coherent
|
|
98
|
-
* partial history — the in-flight turn (model call + its tool executions)
|
|
99
|
-
* always completes first, exactly like a tripped {@link budget}, so overshoot
|
|
100
|
-
* is bounded by one turn. Used by the parallel orchestrator to cancel sibling
|
|
101
|
-
* subagents on a fatal failure or Ctrl-C; omitted → no cancellation (unchanged).
|
|
102
|
-
* The same signal reaches tools via `ctx.signal`, so an in-flight shell child
|
|
103
|
-
* is kill-tree'd rather than orphaned.
|
|
104
|
-
*/
|
|
105
|
-
signal?: AbortSignal;
|
|
106
|
-
/**
|
|
107
|
-
* Mid-loop compaction seam (build item 3). Called at the top of every
|
|
108
|
-
* iteration with the running history; returns the history to continue from —
|
|
109
|
-
* unchanged when under threshold, or with its older prefix summarized away
|
|
110
|
-
* when over. Supplied by {@link Session}, which reuses its own
|
|
111
|
-
* threshold/cut/summarize machinery, so the loop gains no summarization
|
|
112
|
-
* knowledge and no logic is duplicated. Omitted → history is never compacted
|
|
113
|
-
* mid-loop (unchanged behavior; subagents pass nothing).
|
|
114
|
-
*
|
|
115
|
-
* This is what keeps a long autonomous turn — where `send` compacts only once
|
|
116
|
-
* up front and never again — within the context window: without it a run that
|
|
117
|
-
* drives dozens of tool calls (each result appended, some tens of KB) grows
|
|
118
|
-
* unbounded until the next `send`, which in one-shot never comes.
|
|
119
|
-
*/
|
|
120
|
-
compact?: (messages: Message[]) => Promise<Message[]>;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* The budget seam for {@link runAgent}: implementations track their own caps
|
|
124
|
-
* (iterations, tokens, wall clock — see `subagent/budget.ts`); the loop only
|
|
125
|
-
* asks "may I start another turn?". Kept a one-method interface so future
|
|
126
|
-
* callers (C.22 cost tracking) can slot in without touching the loop again.
|
|
127
|
-
*/
|
|
128
|
-
export interface LoopBudget {
|
|
129
|
-
/**
|
|
130
|
-
* Return a human-readable reason to stop *before* the next model turn, or
|
|
131
|
-
* `null` to continue. `iterations` = model turns completed so far.
|
|
132
|
-
*/
|
|
133
|
-
exceeded(state: {
|
|
134
|
-
iterations: number;
|
|
135
|
-
usage: Usage;
|
|
136
|
-
}): string | null;
|
|
137
|
-
}
|
|
138
|
-
export interface AgentResult {
|
|
139
|
-
/** The full conversation, including assistant tool calls and tool results. */
|
|
140
|
-
messages: Message[];
|
|
141
|
-
/** Number of model turns consumed. */
|
|
142
|
-
iterations: number;
|
|
143
|
-
/** Why the loop ended. */
|
|
144
|
-
stop: "completed" | "max_iterations" | "budget" | "aborted";
|
|
145
|
-
/** Which cap tripped, when `stop === "budget"` (from {@link LoopBudget}). */
|
|
146
|
-
stopReason?: string;
|
|
147
|
-
/** Accumulated token usage (stashed for cost tracking in C.22). */
|
|
148
|
-
usage: Usage;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Drive the model/tool loop over an existing conversation. Streams each turn,
|
|
152
|
-
* renders assistant text, reassembles tool calls, executes them, feeds the
|
|
153
|
-
* results back, and repeats until the model stops calling tools or the turn
|
|
154
|
-
* ceiling is hit.
|
|
155
|
-
*
|
|
156
|
-
* Requires a tool-capable provider — it throws up front otherwise rather than
|
|
157
|
-
* silently running tool-less.
|
|
158
|
-
*/
|
|
159
|
-
export declare function runAgent(args: RunAgentArgs): Promise<AgentResult>;
|
package/dist/agent/prompts.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cruxy-code agent prompts.
|
|
3
|
-
*
|
|
4
|
-
* These are ORIGINAL prompts written for cruxy — not copied from any other
|
|
5
|
-
* tool. The system prompt is assembled at runtime from a static core plus a
|
|
6
|
-
* dynamic environment block, so the model always knows where it is, what it
|
|
7
|
-
* can do, and how it's expected to behave.
|
|
8
|
-
*/
|
|
9
|
-
import type { ShellDialect } from "../tools/shell/resolve-shell.js";
|
|
10
|
-
export interface ToolSummary {
|
|
11
|
-
name: string;
|
|
12
|
-
}
|
|
13
|
-
export interface PromptContext {
|
|
14
|
-
/** Absolute working directory the agent is rooted in. */
|
|
15
|
-
cwd: string;
|
|
16
|
-
/** node `process.platform`, e.g. "linux", "darwin", "win32". */
|
|
17
|
-
platform: string;
|
|
18
|
-
/** Provider/model string, for the model's self-awareness. */
|
|
19
|
-
model: string;
|
|
20
|
-
/** Current ISO date (so the model isn't guessing). */
|
|
21
|
-
date: string;
|
|
22
|
-
/** Tools available this session (from the tool registry). */
|
|
23
|
-
tools: ToolSummary[];
|
|
24
|
-
/** Optional git context, when the cwd is a repo. */
|
|
25
|
-
git?: {
|
|
26
|
-
branch: string;
|
|
27
|
-
dirty: boolean;
|
|
28
|
-
} | null;
|
|
29
|
-
/** Optional extra instructions (e.g. from a project CRUXY.md). */
|
|
30
|
-
projectInstructions?: string | null;
|
|
31
|
-
/**
|
|
32
|
-
* Persistent memory (C.29): the pre-rendered, demarcated recall block injected
|
|
33
|
-
* at session start. It is REFERENCE DATA, not instructions — the block carries
|
|
34
|
-
* its own data-only framing (see memory/recall.ts) and is appended as an
|
|
35
|
-
* ordinary section; the U.3 gate never reads it. Null when nothing is recalled.
|
|
36
|
-
*/
|
|
37
|
-
recalledMemory?: string | null;
|
|
38
|
-
/** Plan mode's propose phase (C.31): inject the plan-first directive. */
|
|
39
|
-
planMode?: boolean;
|
|
40
|
-
/** Subagent run (C.14): inject the bounded-subtask directive. */
|
|
41
|
-
subagent?: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* The resolved shell's command dialect (from resolve-shell.ts). When it is not
|
|
44
|
-
* a POSIX shell — e.g. PowerShell, because no Git Bash was found on Windows —
|
|
45
|
-
* a directive tells the model to emit that dialect instead of bash. Absent /
|
|
46
|
-
* "posix" → no directive (bash-isms are correct there; a nudge would be wrong).
|
|
47
|
-
*/
|
|
48
|
-
shellDialect?: ShellDialect;
|
|
49
|
-
}
|
|
50
|
-
/** Assemble the full system prompt for a session. */
|
|
51
|
-
export declare function buildSystemPrompt(ctx: PromptContext): string;
|
|
52
|
-
/**
|
|
53
|
-
* Compact reminder injected after tool results when the loop has run long, to
|
|
54
|
-
* keep the model anchored to the original objective and the verify step.
|
|
55
|
-
*/
|
|
56
|
-
export declare const PROGRESS_REMINDER = "Reminder: stay focused on the original task. Before declaring done, verify your change actually works (build/tests/lint), then summarize what changed.";
|
|
57
|
-
/**
|
|
58
|
-
* System prompt for the side conversation that compacts an over-long history
|
|
59
|
-
* (see Session.compact). It runs as a standalone, tool-less completion over a
|
|
60
|
-
* rendered transcript — the goal is a synopsis dense enough that the main loop
|
|
61
|
-
* can continue without the verbatim prefix.
|
|
62
|
-
*/
|
|
63
|
-
export declare const SUMMARY_SYSTEM = "You are compacting a coding assistant's conversation to fit within its context window. Summarize the conversation so far into a compact synopsis that preserves: decisions made and their rationale, concrete file paths and identifiers touched, the current state of the work, and any open or pending tasks. Be specific and terse \u2014 omit pleasantries and restated instructions. Output only the synopsis.";
|
|
64
|
-
/**
|
|
65
|
-
* Marker embedded in the synthetic messages that replace a compacted prefix, so
|
|
66
|
-
* they're recognizable in the history (and fold cleanly into a later
|
|
67
|
-
* re-summarization rather than being mistaken for live conversation).
|
|
68
|
-
*/
|
|
69
|
-
export declare const COMPACTION_MARKER = "[conversation compacted]";
|