merlion 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/merlion.js +2 -0
- package/dist/artifacts/agents.d.ts +11 -0
- package/dist/artifacts/agents.d.ts.map +1 -0
- package/dist/artifacts/agents.js +81 -0
- package/dist/artifacts/agents.js.map +1 -0
- package/dist/artifacts/codebase_index.d.ts +16 -0
- package/dist/artifacts/codebase_index.d.ts.map +1 -0
- package/dist/artifacts/codebase_index.js +193 -0
- package/dist/artifacts/codebase_index.js.map +1 -0
- package/dist/artifacts/progress.d.ts +23 -0
- package/dist/artifacts/progress.d.ts.map +1 -0
- package/dist/artifacts/progress.js +152 -0
- package/dist/artifacts/progress.js.map +1 -0
- package/dist/cli/diff.d.ts +11 -0
- package/dist/cli/diff.d.ts.map +1 -0
- package/dist/cli/diff.js +58 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/experience.d.ts +71 -0
- package/dist/cli/experience.d.ts.map +1 -0
- package/dist/cli/experience.js +489 -0
- package/dist/cli/experience.js.map +1 -0
- package/dist/cli/keybindings.d.ts +3 -0
- package/dist/cli/keybindings.d.ts.map +1 -0
- package/dist/cli/keybindings.js +14 -0
- package/dist/cli/keybindings.js.map +1 -0
- package/dist/cli/markdown.d.ts +7 -0
- package/dist/cli/markdown.d.ts.map +1 -0
- package/dist/cli/markdown.js +77 -0
- package/dist/cli/markdown.js.map +1 -0
- package/dist/cli/message_content.d.ts +13 -0
- package/dist/cli/message_content.d.ts.map +1 -0
- package/dist/cli/message_content.js +23 -0
- package/dist/cli/message_content.js.map +1 -0
- package/dist/cli/render.d.ts +23 -0
- package/dist/cli/render.d.ts.map +1 -0
- package/dist/cli/render.js +44 -0
- package/dist/cli/render.js.map +1 -0
- package/dist/cli/repl.d.ts +32 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +54 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/sanitize.d.ts +2 -0
- package/dist/cli/sanitize.d.ts.map +1 -0
- package/dist/cli/sanitize.js +66 -0
- package/dist/cli/sanitize.js.map +1 -0
- package/dist/cli/status.d.ts +3 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +27 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/tui_frame.d.ts +10 -0
- package/dist/cli/tui_frame.d.ts.map +1 -0
- package/dist/cli/tui_frame.js +44 -0
- package/dist/cli/tui_frame.js.map +1 -0
- package/dist/config/store.d.ts +27 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +73 -0
- package/dist/config/store.js.map +1 -0
- package/dist/config/wizard.d.ts +27 -0
- package/dist/config/wizard.d.ts.map +1 -0
- package/dist/config/wizard.js +83 -0
- package/dist/config/wizard.js.map +1 -0
- package/dist/context/compact.d.ts +11 -0
- package/dist/context/compact.d.ts.map +1 -0
- package/dist/context/compact.js +38 -0
- package/dist/context/compact.js.map +1 -0
- package/dist/context/orientation.d.ts +19 -0
- package/dist/context/orientation.d.ts.map +1 -0
- package/dist/context/orientation.js +111 -0
- package/dist/context/orientation.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +401 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions/store.d.ts +3 -0
- package/dist/permissions/store.d.ts.map +1 -0
- package/dist/permissions/store.js +22 -0
- package/dist/permissions/store.js.map +1 -0
- package/dist/providers/openai.d.ts +16 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +75 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/runtime/budget.d.ts +11 -0
- package/dist/runtime/budget.d.ts.map +1 -0
- package/dist/runtime/budget.js +43 -0
- package/dist/runtime/budget.js.map +1 -0
- package/dist/runtime/cost_gate.d.ts +34 -0
- package/dist/runtime/cost_gate.d.ts.map +1 -0
- package/dist/runtime/cost_gate.js +85 -0
- package/dist/runtime/cost_gate.js.map +1 -0
- package/dist/runtime/executor.d.ts +25 -0
- package/dist/runtime/executor.d.ts.map +1 -0
- package/dist/runtime/executor.js +136 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/loop.d.ts +48 -0
- package/dist/runtime/loop.d.ts.map +1 -0
- package/dist/runtime/loop.js +184 -0
- package/dist/runtime/loop.js.map +1 -0
- package/dist/runtime/retry.d.ts +7 -0
- package/dist/runtime/retry.d.ts.map +1 -0
- package/dist/runtime/retry.js +42 -0
- package/dist/runtime/retry.js.map +1 -0
- package/dist/runtime/session.d.ts +26 -0
- package/dist/runtime/session.d.ts.map +1 -0
- package/dist/runtime/session.js +146 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/runtime/usage.d.ts +29 -0
- package/dist/runtime/usage.d.ts.map +1 -0
- package/dist/runtime/usage.js +71 -0
- package/dist/runtime/usage.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +3 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +104 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/create_file.d.ts +3 -0
- package/dist/tools/builtin/create_file.d.ts.map +1 -0
- package/dist/tools/builtin/create_file.js +64 -0
- package/dist/tools/builtin/create_file.js.map +1 -0
- package/dist/tools/builtin/edit_file.d.ts +3 -0
- package/dist/tools/builtin/edit_file.d.ts.map +1 -0
- package/dist/tools/builtin/edit_file.js +128 -0
- package/dist/tools/builtin/edit_file.js.map +1 -0
- package/dist/tools/builtin/fetch.d.ts +3 -0
- package/dist/tools/builtin/fetch.d.ts.map +1 -0
- package/dist/tools/builtin/fetch.js +82 -0
- package/dist/tools/builtin/fetch.js.map +1 -0
- package/dist/tools/builtin/index.d.ts +3 -0
- package/dist/tools/builtin/index.d.ts.map +1 -0
- package/dist/tools/builtin/index.js +18 -0
- package/dist/tools/builtin/index.js.map +1 -0
- package/dist/tools/builtin/read_file.d.ts +3 -0
- package/dist/tools/builtin/read_file.d.ts.map +1 -0
- package/dist/tools/builtin/read_file.js +77 -0
- package/dist/tools/builtin/read_file.js.map +1 -0
- package/dist/tools/builtin/search.d.ts +3 -0
- package/dist/tools/builtin/search.d.ts.map +1 -0
- package/dist/tools/builtin/search.js +91 -0
- package/dist/tools/builtin/search.js.map +1 -0
- package/dist/tools/registry.d.ts +8 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +16 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +45 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types.d.ts +56 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/verification/checks.d.ts +10 -0
- package/dist/verification/checks.d.ts.map +1 -0
- package/dist/verification/checks.js +501 -0
- package/dist/verification/checks.js.map +1 -0
- package/dist/verification/fix_round.d.ts +20 -0
- package/dist/verification/fix_round.d.ts.map +1 -0
- package/dist/verification/fix_round.js +59 -0
- package/dist/verification/fix_round.js.map +1 -0
- package/dist/verification/runner.d.ts +26 -0
- package/dist/verification/runner.d.ts.map +1 -0
- package/dist/verification/runner.js +155 -0
- package/dist/verification/runner.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/runtime/session.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAA6D,MAAM,aAAa,CAAA;AAEzG,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,2BAA2B,EAAE,MAAM,CAAA;CACpC;AAkDD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWnD;AAmBD,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAa3E;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAcpG;AAED,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzG;AAED,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAErF;AAED,wBAAsB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBxF"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { appendFile, mkdir, readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
const VALID_ROLES = new Set(['system', 'user', 'assistant', 'tool']);
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === 'object' && value !== null;
|
|
8
|
+
}
|
|
9
|
+
function isTranscriptMessageEntry(value) {
|
|
10
|
+
if (!isRecord(value))
|
|
11
|
+
return false;
|
|
12
|
+
if (value.type !== 'message')
|
|
13
|
+
return false;
|
|
14
|
+
if (typeof value.role !== 'string' || !VALID_ROLES.has(value.role))
|
|
15
|
+
return false;
|
|
16
|
+
if ('content' in value && value.content !== null && typeof value.content !== 'string')
|
|
17
|
+
return false;
|
|
18
|
+
if ('name' in value && value.name !== undefined && typeof value.name !== 'string')
|
|
19
|
+
return false;
|
|
20
|
+
if ('tool_call_id' in value && value.tool_call_id !== undefined && typeof value.tool_call_id !== 'string')
|
|
21
|
+
return false;
|
|
22
|
+
if ('tool_calls' in value && value.tool_calls !== undefined && !Array.isArray(value.tool_calls))
|
|
23
|
+
return false;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
function parseTranscriptEntry(line) {
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
parsed = JSON.parse(line);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (!isRecord(parsed))
|
|
35
|
+
return null;
|
|
36
|
+
if (parsed.type === 'message') {
|
|
37
|
+
return isTranscriptMessageEntry(parsed) ? parsed : null;
|
|
38
|
+
}
|
|
39
|
+
if (parsed.type === 'session_meta') {
|
|
40
|
+
if (typeof parsed.id === 'string' &&
|
|
41
|
+
typeof parsed.createdAt === 'string' &&
|
|
42
|
+
typeof parsed.model === 'string' &&
|
|
43
|
+
typeof parsed.projectPath === 'string') {
|
|
44
|
+
const entry = {
|
|
45
|
+
type: 'session_meta',
|
|
46
|
+
id: parsed.id,
|
|
47
|
+
createdAt: parsed.createdAt,
|
|
48
|
+
model: parsed.model,
|
|
49
|
+
projectPath: parsed.projectPath
|
|
50
|
+
};
|
|
51
|
+
return entry;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
export function redactSecrets(input) {
|
|
57
|
+
let output = input;
|
|
58
|
+
output = output.replace(/Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi, 'Bearer [REDACTED]');
|
|
59
|
+
output = output.replace(/\bsk-[A-Za-z0-9_-]{16,}\b/g, 'sk-[REDACTED]');
|
|
60
|
+
output = output.replace(/\bsk-ant-[A-Za-z0-9_-]{16,}\b/g, 'sk-ant-[REDACTED]');
|
|
61
|
+
output = output.replace(/\bghp_[A-Za-z0-9]{20,}\b/g, 'ghp_[REDACTED]');
|
|
62
|
+
output = output.replace(/-----BEGIN [A-Z ]+PRIVATE KEY-----[\s\S]*?-----END [A-Z ]+PRIVATE KEY-----/g, '[REDACTED_PRIVATE_KEY]');
|
|
63
|
+
return output;
|
|
64
|
+
}
|
|
65
|
+
function redactMessage(message) {
|
|
66
|
+
const redacted = { ...message };
|
|
67
|
+
if (typeof redacted.content === 'string') {
|
|
68
|
+
redacted.content = redactSecrets(redacted.content);
|
|
69
|
+
}
|
|
70
|
+
if (redacted.tool_calls) {
|
|
71
|
+
redacted.tool_calls = redacted.tool_calls.map((call) => ({
|
|
72
|
+
...call,
|
|
73
|
+
function: {
|
|
74
|
+
...call.function,
|
|
75
|
+
arguments: redactSecrets(call.function.arguments)
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
return redacted;
|
|
80
|
+
}
|
|
81
|
+
export async function createSessionFiles(cwd) {
|
|
82
|
+
const dataDir = process.env.MERLION_DATA_DIR ?? join(homedir(), '.merlion');
|
|
83
|
+
const projectHash = createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
84
|
+
const sessionId = randomUUID();
|
|
85
|
+
const projectDir = join(dataDir, 'projects', projectHash);
|
|
86
|
+
await mkdir(projectDir, { recursive: true });
|
|
87
|
+
return {
|
|
88
|
+
sessionId,
|
|
89
|
+
projectHash,
|
|
90
|
+
projectDir,
|
|
91
|
+
transcriptPath: join(projectDir, `${sessionId}.jsonl`),
|
|
92
|
+
usagePath: join(projectDir, `${sessionId}.usage.jsonl`)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export async function getSessionFilesForResume(cwd, sessionId) {
|
|
96
|
+
const dataDir = process.env.MERLION_DATA_DIR ?? join(homedir(), '.merlion');
|
|
97
|
+
const projectHash = createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
98
|
+
const projectDir = join(dataDir, 'projects', projectHash);
|
|
99
|
+
const transcriptPath = join(projectDir, `${sessionId}.jsonl`);
|
|
100
|
+
const usagePath = join(projectDir, `${sessionId}.usage.jsonl`);
|
|
101
|
+
try {
|
|
102
|
+
await stat(transcriptPath);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
throw new Error(`Session transcript not found: ${sessionId}`);
|
|
106
|
+
}
|
|
107
|
+
return { sessionId, projectHash, projectDir, transcriptPath, usagePath };
|
|
108
|
+
}
|
|
109
|
+
export async function appendSessionMeta(transcriptPath, sessionId, model, projectPath) {
|
|
110
|
+
const entry = {
|
|
111
|
+
type: 'session_meta',
|
|
112
|
+
id: sessionId,
|
|
113
|
+
createdAt: new Date().toISOString(),
|
|
114
|
+
model,
|
|
115
|
+
projectPath
|
|
116
|
+
};
|
|
117
|
+
await appendFile(transcriptPath, `${JSON.stringify(entry)}\n`, 'utf8');
|
|
118
|
+
}
|
|
119
|
+
export async function appendTranscriptMessage(transcriptPath, message) {
|
|
120
|
+
const redacted = redactMessage(message);
|
|
121
|
+
const entry = { type: 'message', ...redacted };
|
|
122
|
+
await appendFile(transcriptPath, `${JSON.stringify(entry)}\n`, 'utf8');
|
|
123
|
+
}
|
|
124
|
+
export async function appendUsage(usagePath, entry) {
|
|
125
|
+
await appendFile(usagePath, `${JSON.stringify(entry)}\n`, 'utf8');
|
|
126
|
+
}
|
|
127
|
+
export async function loadSessionMessages(transcriptPath) {
|
|
128
|
+
const text = await readFile(transcriptPath, 'utf8');
|
|
129
|
+
const lines = text.split('\n').filter((line) => line.trim() !== '');
|
|
130
|
+
const messages = [];
|
|
131
|
+
for (const line of lines) {
|
|
132
|
+
const parsed = parseTranscriptEntry(line);
|
|
133
|
+
if (!parsed || parsed.type !== 'message')
|
|
134
|
+
continue;
|
|
135
|
+
const message = {
|
|
136
|
+
role: parsed.role,
|
|
137
|
+
content: parsed.content ?? null,
|
|
138
|
+
tool_calls: parsed.tool_calls,
|
|
139
|
+
tool_call_id: parsed.tool_call_id,
|
|
140
|
+
name: parsed.name
|
|
141
|
+
};
|
|
142
|
+
messages.push(message);
|
|
143
|
+
}
|
|
144
|
+
return messages;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/runtime/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface UsageLike {
|
|
2
|
+
prompt_tokens: number;
|
|
3
|
+
completion_tokens: number;
|
|
4
|
+
cached_tokens?: number | null;
|
|
5
|
+
}
|
|
6
|
+
export interface UsageTotals {
|
|
7
|
+
prompt_tokens: number;
|
|
8
|
+
completion_tokens: number;
|
|
9
|
+
cached_tokens: number;
|
|
10
|
+
total_tokens: number;
|
|
11
|
+
}
|
|
12
|
+
export interface UsageSnapshot {
|
|
13
|
+
turn: number;
|
|
14
|
+
delta: UsageTotals;
|
|
15
|
+
totals: UsageTotals;
|
|
16
|
+
}
|
|
17
|
+
export interface UsageRates {
|
|
18
|
+
inputPerMillion: number;
|
|
19
|
+
outputPerMillion: number;
|
|
20
|
+
cachedInputPerMillion?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function calculateUsageCostUsd(totals: UsageTotals, rates: UsageRates): number;
|
|
23
|
+
export declare function formatUsageProgressLine(snapshot: UsageSnapshot, estimatedCostUsd?: number): string;
|
|
24
|
+
export declare function createUsageTracker(initial?: Partial<UsageTotals>): {
|
|
25
|
+
record(usage: UsageLike): UsageSnapshot;
|
|
26
|
+
getTotals(): UsageTotals;
|
|
27
|
+
getTurn(): number;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/runtime/usage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B;AAmBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAYpF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAclG;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;kBAW/C,SAAS,GAAG,aAAa;iBAa1B,WAAW;eAGb,MAAM;EAIpB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function toNumberOrZero(value) {
|
|
2
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
|
3
|
+
}
|
|
4
|
+
function normalizedUsage(usage) {
|
|
5
|
+
const prompt = Math.max(0, Math.floor(toNumberOrZero(usage.prompt_tokens)));
|
|
6
|
+
const completion = Math.max(0, Math.floor(toNumberOrZero(usage.completion_tokens)));
|
|
7
|
+
const cachedRaw = Math.max(0, Math.floor(toNumberOrZero(usage.cached_tokens)));
|
|
8
|
+
const cached = Math.min(prompt, cachedRaw);
|
|
9
|
+
return {
|
|
10
|
+
prompt_tokens: prompt,
|
|
11
|
+
completion_tokens: completion,
|
|
12
|
+
cached_tokens: cached,
|
|
13
|
+
total_tokens: prompt + completion,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function calculateUsageCostUsd(totals, rates) {
|
|
17
|
+
const inputRate = Math.max(0, rates.inputPerMillion);
|
|
18
|
+
const outputRate = Math.max(0, rates.outputPerMillion);
|
|
19
|
+
const cachedRate = Math.max(0, rates.cachedInputPerMillion ?? inputRate);
|
|
20
|
+
const cached = Math.min(totals.cached_tokens, totals.prompt_tokens);
|
|
21
|
+
const nonCachedPrompt = Math.max(0, totals.prompt_tokens - cached);
|
|
22
|
+
const promptCost = (nonCachedPrompt * inputRate) / 1_000_000;
|
|
23
|
+
const cachedCost = (cached * cachedRate) / 1_000_000;
|
|
24
|
+
const outputCost = (totals.completion_tokens * outputRate) / 1_000_000;
|
|
25
|
+
return promptCost + cachedCost + outputCost;
|
|
26
|
+
}
|
|
27
|
+
export function formatUsageProgressLine(snapshot, estimatedCostUsd) {
|
|
28
|
+
const base = `[usage] turn ${snapshot.turn} ` +
|
|
29
|
+
`+in ${snapshot.delta.prompt_tokens} ` +
|
|
30
|
+
`+out ${snapshot.delta.completion_tokens} ` +
|
|
31
|
+
`+cached ${snapshot.delta.cached_tokens} | ` +
|
|
32
|
+
`total in ${snapshot.totals.prompt_tokens} ` +
|
|
33
|
+
`out ${snapshot.totals.completion_tokens} ` +
|
|
34
|
+
`cached ${snapshot.totals.cached_tokens}`;
|
|
35
|
+
if (typeof estimatedCostUsd !== 'number' || !Number.isFinite(estimatedCostUsd) || estimatedCostUsd < 0) {
|
|
36
|
+
return base;
|
|
37
|
+
}
|
|
38
|
+
return `${base} | est $${estimatedCostUsd.toFixed(6)}`;
|
|
39
|
+
}
|
|
40
|
+
export function createUsageTracker(initial) {
|
|
41
|
+
let turn = 0;
|
|
42
|
+
const totals = {
|
|
43
|
+
prompt_tokens: Math.max(0, Math.floor(toNumberOrZero(initial?.prompt_tokens))),
|
|
44
|
+
completion_tokens: Math.max(0, Math.floor(toNumberOrZero(initial?.completion_tokens))),
|
|
45
|
+
cached_tokens: Math.max(0, Math.floor(toNumberOrZero(initial?.cached_tokens))),
|
|
46
|
+
total_tokens: 0,
|
|
47
|
+
};
|
|
48
|
+
totals.total_tokens = totals.prompt_tokens + totals.completion_tokens;
|
|
49
|
+
return {
|
|
50
|
+
record(usage) {
|
|
51
|
+
turn += 1;
|
|
52
|
+
const delta = normalizedUsage(usage);
|
|
53
|
+
totals.prompt_tokens += delta.prompt_tokens;
|
|
54
|
+
totals.completion_tokens += delta.completion_tokens;
|
|
55
|
+
totals.cached_tokens += delta.cached_tokens;
|
|
56
|
+
totals.total_tokens = totals.prompt_tokens + totals.completion_tokens;
|
|
57
|
+
return {
|
|
58
|
+
turn,
|
|
59
|
+
delta,
|
|
60
|
+
totals: { ...totals },
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
getTotals() {
|
|
64
|
+
return { ...totals };
|
|
65
|
+
},
|
|
66
|
+
getTurn() {
|
|
67
|
+
return turn;
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/runtime/usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/bash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAiEjD,eAAO,MAAM,QAAQ,EAAE,cAgDtB,CAAA"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
const WARN_PATTERNS = [
|
|
3
|
+
/\brm\s+-[rf]{1,2}\b/,
|
|
4
|
+
/\bgit\s+reset\s+--hard\b/,
|
|
5
|
+
/\bgit\s+push\s+--force\b/,
|
|
6
|
+
/DROP\s+TABLE/i,
|
|
7
|
+
/\bTRUNCATE\b/i,
|
|
8
|
+
/\bkubectl\s+delete\b/
|
|
9
|
+
];
|
|
10
|
+
const BLOCK_PATTERNS = [
|
|
11
|
+
/rm\s+-rf\s+[\/~]/,
|
|
12
|
+
/>\s*\/etc\//,
|
|
13
|
+
/curl[^|]*\|\s*(ba)?sh/,
|
|
14
|
+
/wget[^|]*\|\s*(ba)?sh/,
|
|
15
|
+
/`[^`]*rm[^`]*`/,
|
|
16
|
+
/\$\([^)]*rm[^)]*\)/
|
|
17
|
+
];
|
|
18
|
+
function assessCommandRisk(command) {
|
|
19
|
+
if (BLOCK_PATTERNS.some((p) => p.test(command)))
|
|
20
|
+
return 'block';
|
|
21
|
+
if (WARN_PATTERNS.some((p) => p.test(command)))
|
|
22
|
+
return 'warn';
|
|
23
|
+
return 'safe';
|
|
24
|
+
}
|
|
25
|
+
function runBash(command, cwd, timeoutMs) {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
const child = spawn('bash', ['-c', command], { cwd });
|
|
28
|
+
let combined = '';
|
|
29
|
+
let timedOut = false;
|
|
30
|
+
let done = false;
|
|
31
|
+
const killTimer = setTimeout(() => {
|
|
32
|
+
timedOut = true;
|
|
33
|
+
child.kill('SIGTERM');
|
|
34
|
+
setTimeout(() => child.kill('SIGKILL'), 2000).unref();
|
|
35
|
+
}, timeoutMs);
|
|
36
|
+
const append = (chunk) => {
|
|
37
|
+
combined += String(chunk);
|
|
38
|
+
if (combined.length > 100_000) {
|
|
39
|
+
combined = `${combined.slice(0, 100_000)}\n[output truncated]`;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
child.stdout.on('data', append);
|
|
43
|
+
child.stderr.on('data', append);
|
|
44
|
+
child.on('close', (code) => {
|
|
45
|
+
if (done)
|
|
46
|
+
return;
|
|
47
|
+
done = true;
|
|
48
|
+
clearTimeout(killTimer);
|
|
49
|
+
resolve({ content: combined, exit: code ?? -1, timedOut });
|
|
50
|
+
});
|
|
51
|
+
child.on('error', (error) => {
|
|
52
|
+
if (done)
|
|
53
|
+
return;
|
|
54
|
+
done = true;
|
|
55
|
+
clearTimeout(killTimer);
|
|
56
|
+
resolve({ content: String(error), exit: -1, timedOut: false });
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
export const bashTool = {
|
|
61
|
+
name: 'bash',
|
|
62
|
+
description: 'Execute a shell command. Avoid interactive commands.',
|
|
63
|
+
parameters: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
command: { type: 'string' },
|
|
67
|
+
timeout: { type: 'integer' }
|
|
68
|
+
},
|
|
69
|
+
required: ['command']
|
|
70
|
+
},
|
|
71
|
+
concurrencySafe: false,
|
|
72
|
+
async execute(input, ctx) {
|
|
73
|
+
const command = input.command;
|
|
74
|
+
const timeoutRaw = input.timeout;
|
|
75
|
+
if (typeof command !== 'string' || command.trim() === '') {
|
|
76
|
+
return { content: 'Invalid command: expected non-empty string.', isError: true };
|
|
77
|
+
}
|
|
78
|
+
const timeout = typeof timeoutRaw === 'number' && Number.isFinite(timeoutRaw)
|
|
79
|
+
? Math.min(Math.max(Math.floor(timeoutRaw), 1), 300_000)
|
|
80
|
+
: 30_000;
|
|
81
|
+
const risk = assessCommandRisk(command);
|
|
82
|
+
if (risk === 'block') {
|
|
83
|
+
return { content: `[Blocked: command matched high-risk policy] ${command}`, isError: true };
|
|
84
|
+
}
|
|
85
|
+
if (risk === 'warn') {
|
|
86
|
+
const decision = await ctx.permissions?.ask('bash', command);
|
|
87
|
+
if (decision === 'deny' || decision === undefined) {
|
|
88
|
+
return { content: '[Permission denied]', isError: true };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const result = await runBash(command, ctx.cwd, timeout);
|
|
92
|
+
if (result.timedOut) {
|
|
93
|
+
return {
|
|
94
|
+
content: `${result.content}\n[Command timed out after ${timeout} ms]`,
|
|
95
|
+
isError: true
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const text = result.content.trim().length > 0
|
|
99
|
+
? `${result.content}\n[exit: ${result.exit}]`
|
|
100
|
+
: `[exit: ${result.exit}]`;
|
|
101
|
+
return { content: text, isError: result.exit !== 0 };
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=bash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/tools/builtin/bash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_file.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/create_file.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAgBjD,eAAO,MAAM,cAAc,EAAE,cAmD5B,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { mkdir, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, isAbsolute, relative, resolve } from 'node:path';
|
|
3
|
+
function isWithinWorkspace(workspaceRoot, candidatePath) {
|
|
4
|
+
const root = resolve(workspaceRoot);
|
|
5
|
+
const target = resolve(candidatePath);
|
|
6
|
+
const rel = relative(root, target);
|
|
7
|
+
return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
|
|
8
|
+
}
|
|
9
|
+
function countLines(content) {
|
|
10
|
+
if (content.length === 0)
|
|
11
|
+
return 0;
|
|
12
|
+
const lines = content.split(/\r?\n/);
|
|
13
|
+
if (lines[lines.length - 1] === '')
|
|
14
|
+
lines.pop();
|
|
15
|
+
return lines.length;
|
|
16
|
+
}
|
|
17
|
+
export const createFileTool = {
|
|
18
|
+
name: 'create_file',
|
|
19
|
+
description: 'Create a new file with content. Fails if file already exists.',
|
|
20
|
+
parameters: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
path: { type: 'string' },
|
|
24
|
+
content: { type: 'string' }
|
|
25
|
+
},
|
|
26
|
+
required: ['path', 'content']
|
|
27
|
+
},
|
|
28
|
+
concurrencySafe: false,
|
|
29
|
+
async execute(input, ctx) {
|
|
30
|
+
const pathInput = input.path;
|
|
31
|
+
const contentInput = input.content;
|
|
32
|
+
if (typeof pathInput !== 'string' || pathInput.trim() === '') {
|
|
33
|
+
return { content: 'Invalid path: expected non-empty string.', isError: true };
|
|
34
|
+
}
|
|
35
|
+
if (typeof contentInput !== 'string') {
|
|
36
|
+
return { content: 'Invalid content: expected string.', isError: true };
|
|
37
|
+
}
|
|
38
|
+
const decision = await ctx.permissions?.ask('create_file', `Create: ${pathInput}`);
|
|
39
|
+
if (decision === 'deny' || decision === undefined) {
|
|
40
|
+
return { content: '[Permission denied]', isError: true };
|
|
41
|
+
}
|
|
42
|
+
const resolvedPath = isAbsolute(pathInput) ? resolve(pathInput) : resolve(ctx.cwd, pathInput);
|
|
43
|
+
if (!isWithinWorkspace(ctx.cwd, resolvedPath)) {
|
|
44
|
+
return { content: 'Path is outside the workspace root and cannot be modified.', isError: true };
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await stat(resolvedPath);
|
|
48
|
+
return {
|
|
49
|
+
content: 'File already exists. Use edit_file to modify existing files.',
|
|
50
|
+
isError: true
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// expected when file does not exist
|
|
55
|
+
}
|
|
56
|
+
await mkdir(dirname(resolvedPath), { recursive: true });
|
|
57
|
+
await writeFile(resolvedPath, contentInput, 'utf8');
|
|
58
|
+
return {
|
|
59
|
+
content: `Created ${resolvedPath} (${countLines(contentInput)} lines, ${contentInput.length} chars)`,
|
|
60
|
+
isError: false
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=create_file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_file.js","sourceRoot":"","sources":["../../../src/tools/builtin/create_file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit_file.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/edit_file.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAA;AAwD/D,eAAO,MAAM,YAAY,EAAE,cA2E1B,CAAA"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
3
|
+
function isWithinWorkspace(workspaceRoot, candidatePath) {
|
|
4
|
+
const root = resolve(workspaceRoot);
|
|
5
|
+
const target = resolve(candidatePath);
|
|
6
|
+
const rel = relative(root, target);
|
|
7
|
+
return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
|
|
8
|
+
}
|
|
9
|
+
function countOccurrences(text, needle) {
|
|
10
|
+
if (needle.length === 0)
|
|
11
|
+
return 0;
|
|
12
|
+
let index = 0;
|
|
13
|
+
let count = 0;
|
|
14
|
+
while (true) {
|
|
15
|
+
const found = text.indexOf(needle, index);
|
|
16
|
+
if (found === -1)
|
|
17
|
+
return count;
|
|
18
|
+
count += 1;
|
|
19
|
+
index = found + needle.length;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function lineNumberAtOffset(text, offset) {
|
|
23
|
+
let line = 1;
|
|
24
|
+
for (let i = 0; i < offset; i += 1) {
|
|
25
|
+
if (text[i] === '\n')
|
|
26
|
+
line += 1;
|
|
27
|
+
}
|
|
28
|
+
return line;
|
|
29
|
+
}
|
|
30
|
+
function splitForDiff(text) {
|
|
31
|
+
if (text === '')
|
|
32
|
+
return [];
|
|
33
|
+
const lines = text.split('\n');
|
|
34
|
+
if (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
35
|
+
lines.pop();
|
|
36
|
+
}
|
|
37
|
+
return lines;
|
|
38
|
+
}
|
|
39
|
+
function buildEditDiffHunk(original, oldString, newString) {
|
|
40
|
+
const startOffset = original.indexOf(oldString);
|
|
41
|
+
if (startOffset === -1)
|
|
42
|
+
return null;
|
|
43
|
+
const oldLines = splitForDiff(oldString);
|
|
44
|
+
const newLines = splitForDiff(newString);
|
|
45
|
+
const startLine = lineNumberAtOffset(original, startOffset);
|
|
46
|
+
return {
|
|
47
|
+
oldStart: startLine,
|
|
48
|
+
oldLines: oldLines.length,
|
|
49
|
+
newStart: startLine,
|
|
50
|
+
newLines: newLines.length,
|
|
51
|
+
lines: [
|
|
52
|
+
...oldLines.map((line) => ({ type: 'remove', text: line })),
|
|
53
|
+
...newLines.map((line) => ({ type: 'add', text: line })),
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export const editFileTool = {
|
|
58
|
+
name: 'edit_file',
|
|
59
|
+
description: 'Edit file by replacing exact text. old_string must match exactly once in the file. new_string is the literal replacement text (plain string, not an object or dict).',
|
|
60
|
+
parameters: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
path: { type: 'string' },
|
|
64
|
+
old_string: { type: 'string' },
|
|
65
|
+
new_string: { type: 'string' }
|
|
66
|
+
},
|
|
67
|
+
required: ['path', 'old_string', 'new_string']
|
|
68
|
+
},
|
|
69
|
+
concurrencySafe: false,
|
|
70
|
+
async execute(input, ctx) {
|
|
71
|
+
const pathInput = input.path;
|
|
72
|
+
const oldString = input.old_string;
|
|
73
|
+
const newString = input.new_string;
|
|
74
|
+
if (typeof pathInput !== 'string' || pathInput.trim() === '') {
|
|
75
|
+
return { content: 'Invalid path: expected non-empty string.', isError: true };
|
|
76
|
+
}
|
|
77
|
+
if (typeof oldString !== 'string' || typeof newString !== 'string') {
|
|
78
|
+
return { content: 'Invalid edit payload: old_string/new_string must be strings.', isError: true };
|
|
79
|
+
}
|
|
80
|
+
const decision = await ctx.permissions?.ask('edit_file', `Edit: ${pathInput}`);
|
|
81
|
+
if (decision === 'deny' || decision === undefined) {
|
|
82
|
+
return { content: '[Permission denied]', isError: true };
|
|
83
|
+
}
|
|
84
|
+
const resolvedPath = isAbsolute(pathInput) ? resolve(pathInput) : resolve(ctx.cwd, pathInput);
|
|
85
|
+
if (!isWithinWorkspace(ctx.cwd, resolvedPath)) {
|
|
86
|
+
return { content: 'Path is outside the workspace root and cannot be modified.', isError: true };
|
|
87
|
+
}
|
|
88
|
+
let content;
|
|
89
|
+
try {
|
|
90
|
+
content = await readFile(resolvedPath, 'utf8');
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { content: `File not found: ${pathInput}`, isError: true };
|
|
94
|
+
}
|
|
95
|
+
const occurrences = countOccurrences(content, oldString);
|
|
96
|
+
if (occurrences === 0) {
|
|
97
|
+
return {
|
|
98
|
+
content: 'old_string not found in file. Check exact content including whitespace and indentation.',
|
|
99
|
+
isError: true
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (occurrences > 1) {
|
|
103
|
+
return {
|
|
104
|
+
content: `Found ${occurrences} occurrences of old_string. Provide a more specific string that uniquely identifies the target section.`,
|
|
105
|
+
isError: true
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const updated = content.replace(oldString, newString);
|
|
109
|
+
const hunk = buildEditDiffHunk(content, oldString, newString);
|
|
110
|
+
const removedLines = splitForDiff(oldString).length;
|
|
111
|
+
const addedLines = splitForDiff(newString).length;
|
|
112
|
+
await writeFile(resolvedPath, updated, 'utf8');
|
|
113
|
+
return {
|
|
114
|
+
content: `Edited ${resolvedPath} (+${addedLines} -${removedLines})`,
|
|
115
|
+
isError: false,
|
|
116
|
+
uiPayload: hunk
|
|
117
|
+
? {
|
|
118
|
+
kind: 'edit_diff',
|
|
119
|
+
path: resolvedPath,
|
|
120
|
+
addedLines,
|
|
121
|
+
removedLines,
|
|
122
|
+
hunks: [hunk]
|
|
123
|
+
}
|
|
124
|
+
: undefined
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=edit_file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit_file.js","sourceRoot":"","sources":["../../../src/tools/builtin/edit_file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAgBjD,eAAO,MAAM,SAAS,EAAE,cAmEvB,CAAA"}
|