@garuda-agent/garuda 0.0.1 → 0.15.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/CHANGELOG.md +77 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +1097 -0
- package/SECURITY.md +32 -0
- package/dist/acpCommand-FZ2P5JFO.js +153 -0
- package/dist/anthropic-NQDBCHJU.js +327 -0
- package/dist/chunk-23FXBNBB.js +46 -0
- package/dist/chunk-2S62ZNTC.js +320 -0
- package/dist/chunk-2TAXSFWN.js +49 -0
- package/dist/chunk-36GQIVGT.js +526 -0
- package/dist/chunk-3CEPHS4C.js +231 -0
- package/dist/chunk-3NJNVZTK.js +123 -0
- package/dist/chunk-42DSA4EA.js +116 -0
- package/dist/chunk-4JSUUDFQ.js +118 -0
- package/dist/chunk-4P26OKTP.js +100 -0
- package/dist/chunk-5DEWP3YX.js +139 -0
- package/dist/chunk-A2QAIRQL.js +45 -0
- package/dist/chunk-ATW7BNIG.js +31 -0
- package/dist/chunk-B25VL4RU.js +242 -0
- package/dist/chunk-EPKWDCV4.js +9 -0
- package/dist/chunk-EU7PA45O.js +324 -0
- package/dist/chunk-FARS4R67.js +206 -0
- package/dist/chunk-G2AX7MGS.js +36 -0
- package/dist/chunk-HRGX53VC.js +173 -0
- package/dist/chunk-HUIK3WXO.js +234 -0
- package/dist/chunk-INRZR772.js +73 -0
- package/dist/chunk-K3SIUOAG.js +138 -0
- package/dist/chunk-K7KK7U44.js +9358 -0
- package/dist/chunk-KKB5W47S.js +231 -0
- package/dist/chunk-N4I6YS3E.js +73 -0
- package/dist/chunk-NXJ4XLB5.js +19 -0
- package/dist/chunk-OUCV3FCT.js +205 -0
- package/dist/chunk-PQNT34LY.js +1247 -0
- package/dist/chunk-PZS3V6P3.js +46 -0
- package/dist/chunk-S77XDSD4.js +157 -0
- package/dist/chunk-SI2QJYCR.js +1341 -0
- package/dist/chunk-WMOLXTBU.js +61 -0
- package/dist/chunk-YFQJXRIJ.js +193 -0
- package/dist/chunk-YQTGMCU6.js +111 -0
- package/dist/chunk-ZAE25JM2.js +158 -0
- package/dist/cli/index.js +1203 -0
- package/dist/create-N4I7TIZE.js +223 -0
- package/dist/deadline-F5RJJ2QW.js +86 -0
- package/dist/detect-LARDSLLZ.js +10 -0
- package/dist/evalCommand-3SSFMZQD.js +2798 -0
- package/dist/export-HN3CT7AV.js +158 -0
- package/dist/inkChat-34BTFG2K.js +1193 -0
- package/dist/install-VRPBZY5H.js +17 -0
- package/dist/job-3NYDMP2M.js +31 -0
- package/dist/jobCommand-XJ5GULS5.js +30 -0
- package/dist/launchd-QVHQ3VNN.js +40 -0
- package/dist/lspCommand-XNTBHXLA.js +99 -0
- package/dist/manager-4PMSXT47.js +14 -0
- package/dist/manager-CSI76AWF.js +847 -0
- package/dist/nightCommand-CR6ZHYGP.js +247 -0
- package/dist/oauth-W6OK6XXO.js +23 -0
- package/dist/openaiCompatible-CJWVJP5M.js +501 -0
- package/dist/policy-EJPLEEXP.js +31 -0
- package/dist/proxy-XJAHCZB2.js +192 -0
- package/dist/remove-LE7Q7K46.js +59 -0
- package/dist/run-ML6GSPN4.js +888 -0
- package/dist/server-R3GNIC33.js +676 -0
- package/dist/servers-6YDGWOZ6.js +24 -0
- package/dist/text-J2GD647J.js +11 -0
- package/package.json +84 -3
package/SECURITY.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
Garuda runs commands and edits files for a model, so we take security reports seriously.
|
|
4
|
+
|
|
5
|
+
## Supported versions
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| 0.14.x | Yes |
|
|
10
|
+
| Older | No |
|
|
11
|
+
|
|
12
|
+
## Report a vulnerability
|
|
13
|
+
|
|
14
|
+
Do not open a public issue. Use GitHub's private vulnerability reporting: in this repository, open
|
|
15
|
+
**Security**, then **Report a vulnerability**. Give:
|
|
16
|
+
|
|
17
|
+
- the version (`garuda --version`) and the platform (macOS or Linux, the sandbox in use);
|
|
18
|
+
- the steps to reproduce, and what you expected;
|
|
19
|
+
- the effect, for example a sandbox escape, a permission or team-policy bypass, a secret in a
|
|
20
|
+
session file or the audit log, or a write that the user did not approve.
|
|
21
|
+
|
|
22
|
+
You get an answer within 7 days. We agree a fix and a disclosure date with you, and we credit you in
|
|
23
|
+
the release notes unless you ask us not to.
|
|
24
|
+
|
|
25
|
+
## Scope
|
|
26
|
+
|
|
27
|
+
In scope: the permission engine and the team policy, the OS sandbox (Seatbelt, bubblewrap), the
|
|
28
|
+
network allowlist and its proxy, secret redaction, the audit log, and the consent for project
|
|
29
|
+
content (hooks, MCP servers, settings, commands, skills, agents).
|
|
30
|
+
|
|
31
|
+
Known limits are listed in the README under the status table. A report about one of them is still
|
|
32
|
+
welcome when it shows a new way to reach the same effect.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
keepProviderKey,
|
|
4
|
+
loadModelsConfig,
|
|
5
|
+
resolveModel
|
|
6
|
+
} from "./chunk-YFQJXRIJ.js";
|
|
7
|
+
import {
|
|
8
|
+
FileSessionStore,
|
|
9
|
+
Runtime,
|
|
10
|
+
auditDirFor
|
|
11
|
+
} from "./chunk-K7KK7U44.js";
|
|
12
|
+
import "./chunk-A2QAIRQL.js";
|
|
13
|
+
import "./chunk-HRGX53VC.js";
|
|
14
|
+
import "./chunk-G2AX7MGS.js";
|
|
15
|
+
import {
|
|
16
|
+
loadSearchConfig
|
|
17
|
+
} from "./chunk-B25VL4RU.js";
|
|
18
|
+
import "./chunk-23FXBNBB.js";
|
|
19
|
+
import {
|
|
20
|
+
VERSION
|
|
21
|
+
} from "./chunk-EPKWDCV4.js";
|
|
22
|
+
import "./chunk-5DEWP3YX.js";
|
|
23
|
+
import "./chunk-ZAE25JM2.js";
|
|
24
|
+
import "./chunk-ATW7BNIG.js";
|
|
25
|
+
import "./chunk-PZS3V6P3.js";
|
|
26
|
+
import "./chunk-OUCV3FCT.js";
|
|
27
|
+
import "./chunk-SI2QJYCR.js";
|
|
28
|
+
import "./chunk-WMOLXTBU.js";
|
|
29
|
+
import "./chunk-HUIK3WXO.js";
|
|
30
|
+
import "./chunk-3NJNVZTK.js";
|
|
31
|
+
|
|
32
|
+
// src/cli/acpCommand.ts
|
|
33
|
+
import { homedir } from "os";
|
|
34
|
+
import { Readable } from "stream";
|
|
35
|
+
async function acpCommand(options) {
|
|
36
|
+
const output = protocolOutput(process.stdout, process.stderr);
|
|
37
|
+
const input = Readable.toWeb(process.stdin);
|
|
38
|
+
const setup = await prepare(options);
|
|
39
|
+
const { acpServer } = await import("./server-R3GNIC33.js");
|
|
40
|
+
const server = acpServer({
|
|
41
|
+
version: VERSION,
|
|
42
|
+
createRuntime: async ({ root, approver, onEvent, onNotice }) => {
|
|
43
|
+
if (typeof setup === "string") throw new Error(setup);
|
|
44
|
+
return createRuntime(setup, { root, approver, onEvent, onNotice });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
process.on("exit", () => server.shutdown());
|
|
48
|
+
const stop = () => {
|
|
49
|
+
server.shutdown();
|
|
50
|
+
process.exit(143);
|
|
51
|
+
};
|
|
52
|
+
process.once("SIGTERM", stop);
|
|
53
|
+
await server.serve(output, input);
|
|
54
|
+
await server.close();
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
function protocolOutput(stdout, stderr) {
|
|
58
|
+
const write = stdout.write.bind(stdout);
|
|
59
|
+
const toStderr = stderr.write.bind(stderr);
|
|
60
|
+
stdout.write = ((...args) => toStderr(...args));
|
|
61
|
+
return new WritableStream({
|
|
62
|
+
write: (chunk) => new Promise((resolve, reject) => {
|
|
63
|
+
write(chunk, (error) => error ? reject(error) : resolve());
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function prepare(options) {
|
|
68
|
+
const spec = options.model ?? process.env.GARUDA_MODEL;
|
|
69
|
+
if (!spec) return "Set a model with --model <id> or the GARUDA_MODEL variable.";
|
|
70
|
+
const models = await loadModelsConfig();
|
|
71
|
+
if (models.problem !== void 0) return models.problem;
|
|
72
|
+
let resolved;
|
|
73
|
+
let sub;
|
|
74
|
+
try {
|
|
75
|
+
resolved = resolveModel(spec, models.config);
|
|
76
|
+
const subSpec = process.env.GARUDA_SUBAGENT_MODEL;
|
|
77
|
+
if (subSpec) sub = resolveModel(subSpec, models.config);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return error.message;
|
|
80
|
+
}
|
|
81
|
+
const search = await loadSearchConfig();
|
|
82
|
+
for (const name of [resolved.def.apiKeyEnv, sub?.def.apiKeyEnv, "ANTHROPIC_API_KEY"]) {
|
|
83
|
+
if (name !== void 0) keepProviderKey(name);
|
|
84
|
+
}
|
|
85
|
+
const { loadTeamPolicy } = await import("./policy-EJPLEEXP.js");
|
|
86
|
+
let team;
|
|
87
|
+
try {
|
|
88
|
+
team = await loadTeamPolicy();
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return `Team policy: ${error.message}`;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
resolved,
|
|
94
|
+
...sub === void 0 ? {} : { sub },
|
|
95
|
+
models: models.config,
|
|
96
|
+
...team === void 0 ? {} : { team: { policy: team.policy, sources: team.sources } },
|
|
97
|
+
search
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function createRuntime(setup, input) {
|
|
101
|
+
const { resolved, sub, models, team, search } = setup;
|
|
102
|
+
return Runtime.create({
|
|
103
|
+
root: input.root,
|
|
104
|
+
modelId: resolved.spec,
|
|
105
|
+
...team === void 0 ? {} : { policy: team.policy, policySources: team.sources },
|
|
106
|
+
audit: { dir: auditDirFor(input.root) },
|
|
107
|
+
model: () => resolved.create(),
|
|
108
|
+
modelInfo: resolved.info,
|
|
109
|
+
...resolved.maxTokens === void 0 ? {} : { maxTokens: resolved.maxTokens },
|
|
110
|
+
...sub === void 0 ? {} : { subagentModel: { spec: sub.spec, model: () => sub.create(), info: sub.info } },
|
|
111
|
+
approver: input.approver,
|
|
112
|
+
store: new FileSessionStore(input.root),
|
|
113
|
+
undo: {},
|
|
114
|
+
skills: {},
|
|
115
|
+
languages: {},
|
|
116
|
+
// The editor cannot answer a question before session/new returns: only project settings that
|
|
117
|
+
// the user approved in a terminal apply; the rest is left out with a notice (docs/lld/acp.md).
|
|
118
|
+
projectSettings: { home: homedir(), ask: false },
|
|
119
|
+
...search.config === void 0 && search.claude === void 0 ? {} : {
|
|
120
|
+
search: {
|
|
121
|
+
...search.config === void 0 ? {} : { config: search.config },
|
|
122
|
+
...search.claude === void 0 ? {} : { claude: search.claude },
|
|
123
|
+
...search.use === void 0 ? {} : { use: search.use },
|
|
124
|
+
home: homedir()
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
agents: {
|
|
128
|
+
resolveModel: (spec) => {
|
|
129
|
+
const r = resolveModel(spec, models);
|
|
130
|
+
return { spec: r.spec, model: () => r.create(), info: r.info };
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
models: {
|
|
134
|
+
resolve: (spec) => {
|
|
135
|
+
const r = resolveModel(spec, models);
|
|
136
|
+
return {
|
|
137
|
+
spec: r.spec,
|
|
138
|
+
model: () => r.create(),
|
|
139
|
+
info: r.info,
|
|
140
|
+
...r.maxTokens === void 0 ? {} : { maxTokens: r.maxTokens }
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
configured: Object.keys(models.models)
|
|
144
|
+
},
|
|
145
|
+
...input.onEvent === void 0 ? {} : { onEvent: input.onEvent },
|
|
146
|
+
onNotice: input.onNotice
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
export {
|
|
150
|
+
acpCommand,
|
|
151
|
+
protocolOutput
|
|
152
|
+
};
|
|
153
|
+
//# sourceMappingURL=acpCommand-FZ2P5JFO.js.map
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/model/anthropic.ts
|
|
4
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
5
|
+
import { Agent, fetch as undiciFetch } from "undici";
|
|
6
|
+
var WEB_SEARCH_TOOL = "web_search_20250305";
|
|
7
|
+
var AnthropicClient = class {
|
|
8
|
+
/** Claude's web search runs on Anthropic's servers (0.6). */
|
|
9
|
+
serverTools = ["web_search"];
|
|
10
|
+
client;
|
|
11
|
+
model;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.model = options.model;
|
|
14
|
+
this.client = options.client ?? new Anthropic(clientOptions(options.apiKey));
|
|
15
|
+
}
|
|
16
|
+
async *stream(request, options) {
|
|
17
|
+
const stream = this.client.messages.stream(
|
|
18
|
+
toWireParams(this.model, request),
|
|
19
|
+
options?.signal === void 0 ? {} : { signal: options.signal }
|
|
20
|
+
);
|
|
21
|
+
for await (const event of stream) {
|
|
22
|
+
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
|
|
23
|
+
yield { type: "text_delta", text: event.delta.text };
|
|
24
|
+
} else if (event.type === "content_block_delta" && event.delta.type === "thinking_delta" && event.delta.thinking !== "" && request.thinking?.hide !== true) {
|
|
25
|
+
yield { type: "thinking_delta", text: event.delta.thinking };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const final = await stream.finalMessage();
|
|
29
|
+
const response = fromWireMessage(final);
|
|
30
|
+
yield {
|
|
31
|
+
type: "response",
|
|
32
|
+
response: request.thinking?.hide === true ? withHiddenThinking(response) : response
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
function withHiddenThinking(response) {
|
|
37
|
+
return {
|
|
38
|
+
...response,
|
|
39
|
+
content: response.content.map((b) => b.type === "thinking" ? { ...b, text: "" } : b)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
var STREAM_IDLE_MS = 20 * 6e4;
|
|
43
|
+
var dispatchers = /* @__PURE__ */ new Map();
|
|
44
|
+
function streamFetch(idleMs = STREAM_IDLE_MS) {
|
|
45
|
+
let agent = dispatchers.get(idleMs);
|
|
46
|
+
if (agent === void 0) {
|
|
47
|
+
agent = new Agent({ bodyTimeout: idleMs });
|
|
48
|
+
dispatchers.set(idleMs, agent);
|
|
49
|
+
}
|
|
50
|
+
const dispatcher = agent;
|
|
51
|
+
return ((input, init) => undiciFetch(input, { ...init, dispatcher }));
|
|
52
|
+
}
|
|
53
|
+
function clientOptions(apiKey) {
|
|
54
|
+
return { ...apiKey === void 0 ? {} : { apiKey }, fetch: streamFetch() };
|
|
55
|
+
}
|
|
56
|
+
function toWireParams(model, request) {
|
|
57
|
+
const params = {
|
|
58
|
+
model,
|
|
59
|
+
max_tokens: request.maxTokens,
|
|
60
|
+
system: [{ type: "text", text: request.system, cache_control: { type: "ephemeral" } }],
|
|
61
|
+
messages: request.messages.map(toWireMessage)
|
|
62
|
+
};
|
|
63
|
+
const last = params.messages.at(-1);
|
|
64
|
+
if (last !== void 0 && Array.isArray(last.content) && last.content.length > 0) {
|
|
65
|
+
const blocks = last.content;
|
|
66
|
+
const block = blocks.findLast((b) => b.type !== "thinking" && b.type !== "redacted_thinking");
|
|
67
|
+
if (block !== void 0) block.cache_control = { type: "ephemeral" };
|
|
68
|
+
}
|
|
69
|
+
const tools = toWireTools(request.tools, request.serverTools ?? []);
|
|
70
|
+
if (tools.length > 0) params.tools = tools;
|
|
71
|
+
const thinking = request.thinking;
|
|
72
|
+
if (thinking?.adaptive === true || thinking?.display !== void 0) {
|
|
73
|
+
params.thinking = {
|
|
74
|
+
type: "adaptive",
|
|
75
|
+
...thinking.display === void 0 ? {} : { display: thinking.display }
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (thinking?.effort !== void 0) params.output_config = { effort: thinking.effort };
|
|
79
|
+
return params;
|
|
80
|
+
}
|
|
81
|
+
function toWireTools(tools, serverTools = []) {
|
|
82
|
+
const out = [
|
|
83
|
+
...tools.map(
|
|
84
|
+
(tool) => ({
|
|
85
|
+
name: tool.name,
|
|
86
|
+
description: tool.description,
|
|
87
|
+
input_schema: { ...tool.inputSchema, type: "object" }
|
|
88
|
+
})
|
|
89
|
+
),
|
|
90
|
+
...serverTools.map(
|
|
91
|
+
(spec) => ({
|
|
92
|
+
type: WEB_SEARCH_TOOL,
|
|
93
|
+
name: "web_search",
|
|
94
|
+
max_uses: spec.maxUses,
|
|
95
|
+
...spec.allowedDomains === void 0 ? {} : { allowed_domains: [...spec.allowedDomains] },
|
|
96
|
+
...spec.blockedDomains === void 0 ? {} : { blocked_domains: [...spec.blockedDomains] }
|
|
97
|
+
})
|
|
98
|
+
)
|
|
99
|
+
];
|
|
100
|
+
const last = out.at(-1);
|
|
101
|
+
if (last !== void 0) last.cache_control = { type: "ephemeral" };
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
function toWireMessage(message) {
|
|
105
|
+
return { role: message.role, content: message.content.map(toWireBlock) };
|
|
106
|
+
}
|
|
107
|
+
function toWireBlock(block) {
|
|
108
|
+
switch (block.type) {
|
|
109
|
+
case "text":
|
|
110
|
+
return block.citations === void 0 ? { type: "text", text: block.text } : {
|
|
111
|
+
type: "text",
|
|
112
|
+
text: block.text,
|
|
113
|
+
citations: structuredClone(block.citations)
|
|
114
|
+
};
|
|
115
|
+
// Server tool blocks go back exactly as they came (the results hold encrypted content), and so
|
|
116
|
+
// do thinking blocks (0.9: the signature checks them).
|
|
117
|
+
case "server_tool_use":
|
|
118
|
+
case "server_tool_result":
|
|
119
|
+
case "thinking":
|
|
120
|
+
return structuredClone(block.wire);
|
|
121
|
+
case "tool_use":
|
|
122
|
+
return { type: "tool_use", id: block.id, name: block.name, input: block.input };
|
|
123
|
+
case "tool_result":
|
|
124
|
+
return {
|
|
125
|
+
type: "tool_result",
|
|
126
|
+
tool_use_id: block.toolUseId,
|
|
127
|
+
content: block.content,
|
|
128
|
+
is_error: block.isError
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function fromWireMessage(message) {
|
|
133
|
+
const content = [];
|
|
134
|
+
for (const block of message.content) {
|
|
135
|
+
if (block.type === "text") {
|
|
136
|
+
const citations = block.citations ?? [];
|
|
137
|
+
content.push(
|
|
138
|
+
citations.length === 0 ? { type: "text", text: block.text } : { type: "text", text: block.text, citations: structuredClone(citations) }
|
|
139
|
+
);
|
|
140
|
+
} else if (block.type === "tool_use") {
|
|
141
|
+
content.push({ type: "tool_use", id: block.id, name: block.name, input: block.input });
|
|
142
|
+
} else if (block.type === "server_tool_use") {
|
|
143
|
+
content.push({
|
|
144
|
+
type: "server_tool_use",
|
|
145
|
+
id: block.id,
|
|
146
|
+
name: block.name,
|
|
147
|
+
input: block.input,
|
|
148
|
+
wire: structuredClone(block)
|
|
149
|
+
});
|
|
150
|
+
} else if (block.type === "web_search_tool_result") {
|
|
151
|
+
content.push(webSearchResult(block));
|
|
152
|
+
} else if (block.type === "thinking") {
|
|
153
|
+
content.push({ type: "thinking", text: block.thinking, wire: structuredClone(block) });
|
|
154
|
+
} else if (block.type === "redacted_thinking") {
|
|
155
|
+
content.push({ type: "thinking", text: "", wire: structuredClone(block) });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
content,
|
|
160
|
+
stopReason: fromWireStopReason(message.stop_reason),
|
|
161
|
+
usage: fromWireUsage(message.usage)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function webSearchResult(block) {
|
|
165
|
+
const wire = structuredClone(block);
|
|
166
|
+
if (!Array.isArray(block.content)) {
|
|
167
|
+
return {
|
|
168
|
+
type: "server_tool_result",
|
|
169
|
+
toolUseId: block.tool_use_id,
|
|
170
|
+
name: "web_search",
|
|
171
|
+
results: [],
|
|
172
|
+
error: block.content.error_code,
|
|
173
|
+
wire
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
type: "server_tool_result",
|
|
178
|
+
toolUseId: block.tool_use_id,
|
|
179
|
+
name: "web_search",
|
|
180
|
+
results: block.content.map((r) => ({
|
|
181
|
+
title: r.title,
|
|
182
|
+
url: r.url,
|
|
183
|
+
...r.page_age === null || r.page_age === void 0 ? {} : { age: r.page_age }
|
|
184
|
+
})),
|
|
185
|
+
wire
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function fromWireStopReason(reason) {
|
|
189
|
+
switch (reason) {
|
|
190
|
+
case "end_turn":
|
|
191
|
+
case "stop_sequence":
|
|
192
|
+
return "end_turn";
|
|
193
|
+
case "tool_use":
|
|
194
|
+
return "tool_use";
|
|
195
|
+
case "max_tokens":
|
|
196
|
+
case "model_context_window_exceeded":
|
|
197
|
+
return "max_tokens";
|
|
198
|
+
case "refusal":
|
|
199
|
+
return "refusal";
|
|
200
|
+
case "pause_turn":
|
|
201
|
+
return "pause_turn";
|
|
202
|
+
default:
|
|
203
|
+
return "other";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function fromWireUsage(usage) {
|
|
207
|
+
const searches = usage.server_tool_use?.web_search_requests ?? 0;
|
|
208
|
+
return {
|
|
209
|
+
inputTokens: usage.input_tokens,
|
|
210
|
+
outputTokens: usage.output_tokens,
|
|
211
|
+
cacheReadTokens: usage.cache_read_input_tokens ?? 0,
|
|
212
|
+
cacheWriteTokens: usage.cache_creation_input_tokens ?? 0,
|
|
213
|
+
...searches > 0 ? { webSearches: searches } : {}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
var BATCH_CHECK_TIMEOUT_MS = 6e4;
|
|
217
|
+
var MAX_FAILED_CHECKS = 10;
|
|
218
|
+
var BATCH_POLL_MS = [5e3, 1e4, 2e4, 3e4];
|
|
219
|
+
var AnthropicBatchClient = class {
|
|
220
|
+
serverTools = ["web_search"];
|
|
221
|
+
client;
|
|
222
|
+
model;
|
|
223
|
+
pollMs;
|
|
224
|
+
onWait;
|
|
225
|
+
noticeMs;
|
|
226
|
+
constructor(options) {
|
|
227
|
+
this.model = options.model;
|
|
228
|
+
this.pollMs = options.pollMs ?? BATCH_POLL_MS;
|
|
229
|
+
this.onWait = options.onWait;
|
|
230
|
+
this.noticeMs = options.noticeMs ?? 6e4;
|
|
231
|
+
this.client = options.client ?? new Anthropic(clientOptions(options.apiKey));
|
|
232
|
+
}
|
|
233
|
+
async *stream(request, options) {
|
|
234
|
+
const signal = options?.signal;
|
|
235
|
+
const params = toWireParams(
|
|
236
|
+
this.model,
|
|
237
|
+
request
|
|
238
|
+
);
|
|
239
|
+
const batch = await this.client.messages.batches.create(
|
|
240
|
+
{ requests: [{ custom_id: "garuda", params }] },
|
|
241
|
+
signal === void 0 ? {} : { signal }
|
|
242
|
+
);
|
|
243
|
+
const started = Date.now();
|
|
244
|
+
this.onWait?.({ batchId: batch.id, waitedMs: 0, status: "created" });
|
|
245
|
+
let noticed = 0;
|
|
246
|
+
let failed = 0;
|
|
247
|
+
try {
|
|
248
|
+
for (let i = 0; ; i++) {
|
|
249
|
+
await wait(this.pollMs[Math.min(i, this.pollMs.length - 1)] ?? 3e4, signal);
|
|
250
|
+
let status;
|
|
251
|
+
try {
|
|
252
|
+
const state = await this.client.messages.batches.retrieve(batch.id, void 0, {
|
|
253
|
+
timeout: BATCH_CHECK_TIMEOUT_MS,
|
|
254
|
+
...signal === void 0 ? {} : { signal }
|
|
255
|
+
});
|
|
256
|
+
status = state.processing_status;
|
|
257
|
+
failed = 0;
|
|
258
|
+
} catch (error) {
|
|
259
|
+
if (signal?.aborted === true || ++failed >= MAX_FAILED_CHECKS) throw error;
|
|
260
|
+
status = "check failed, trying again";
|
|
261
|
+
}
|
|
262
|
+
if (status === "ended") break;
|
|
263
|
+
const waited = Date.now() - started;
|
|
264
|
+
if (waited - noticed >= this.noticeMs) {
|
|
265
|
+
noticed = waited;
|
|
266
|
+
this.onWait?.({ batchId: batch.id, waitedMs: waited, status });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
await this.client.messages.batches.cancel(batch.id).catch(() => void 0);
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
const results = await this.client.messages.batches.results(batch.id);
|
|
274
|
+
for await (const item of results) {
|
|
275
|
+
if (item.custom_id !== "garuda") continue;
|
|
276
|
+
const result = item.result;
|
|
277
|
+
if (result.type === "succeeded") {
|
|
278
|
+
const response = { ...fromWireMessage(result.message), priceFactor: 0.5 };
|
|
279
|
+
const text = response.content.map((b) => b.type === "text" ? b.text : "").join("");
|
|
280
|
+
if (text !== "") yield { type: "text_delta", text };
|
|
281
|
+
yield { type: "response", response };
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (result.type === "errored") {
|
|
285
|
+
const detail = result.error.error;
|
|
286
|
+
throw Object.assign(new Error(`Batch request failed: ${detail.message}`), {
|
|
287
|
+
error: result.error
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
throw new Error(`The batch request was ${result.type}.`);
|
|
291
|
+
}
|
|
292
|
+
throw new Error("The batch ended without a result.");
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
function wait(ms, signal) {
|
|
296
|
+
return new Promise((resolve, reject) => {
|
|
297
|
+
if (signal?.aborted) {
|
|
298
|
+
reject(signal.reason);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const timer = setTimeout(() => {
|
|
302
|
+
signal?.removeEventListener("abort", onAbort);
|
|
303
|
+
resolve();
|
|
304
|
+
}, ms);
|
|
305
|
+
const onAbort = () => {
|
|
306
|
+
clearTimeout(timer);
|
|
307
|
+
reject(signal?.reason);
|
|
308
|
+
};
|
|
309
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
export {
|
|
313
|
+
AnthropicBatchClient,
|
|
314
|
+
AnthropicClient,
|
|
315
|
+
BATCH_CHECK_TIMEOUT_MS,
|
|
316
|
+
BATCH_POLL_MS,
|
|
317
|
+
STREAM_IDLE_MS,
|
|
318
|
+
WEB_SEARCH_TOOL,
|
|
319
|
+
clientOptions,
|
|
320
|
+
fromWireMessage,
|
|
321
|
+
streamFetch,
|
|
322
|
+
toWireMessage,
|
|
323
|
+
toWireParams,
|
|
324
|
+
toWireTools,
|
|
325
|
+
withHiddenThinking
|
|
326
|
+
};
|
|
327
|
+
//# sourceMappingURL=anthropic-NQDBCHJU.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/builtins.ts
|
|
4
|
+
var BUILTIN_COMMANDS = [
|
|
5
|
+
"help",
|
|
6
|
+
"usage",
|
|
7
|
+
"session",
|
|
8
|
+
"sessions",
|
|
9
|
+
"models",
|
|
10
|
+
"export",
|
|
11
|
+
"compact",
|
|
12
|
+
"diff",
|
|
13
|
+
"schedule",
|
|
14
|
+
"jobs",
|
|
15
|
+
"where",
|
|
16
|
+
"defs",
|
|
17
|
+
"refs",
|
|
18
|
+
"callers",
|
|
19
|
+
"impact",
|
|
20
|
+
"map",
|
|
21
|
+
"mcp",
|
|
22
|
+
"hooks",
|
|
23
|
+
"lsp",
|
|
24
|
+
"languages",
|
|
25
|
+
"experts",
|
|
26
|
+
"audit",
|
|
27
|
+
"commands",
|
|
28
|
+
"agents",
|
|
29
|
+
"plan",
|
|
30
|
+
"build",
|
|
31
|
+
"new",
|
|
32
|
+
"init",
|
|
33
|
+
"editor",
|
|
34
|
+
"details",
|
|
35
|
+
"thinking",
|
|
36
|
+
"search",
|
|
37
|
+
"undo",
|
|
38
|
+
"redo",
|
|
39
|
+
"exit",
|
|
40
|
+
"quit"
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
BUILTIN_COMMANDS
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=chunk-23FXBNBB.js.map
|