vaan-ai 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.
Files changed (106) hide show
  1. package/LICENSE +216 -0
  2. package/README.md +390 -0
  3. package/dist/src/agent.js +151 -0
  4. package/dist/src/agent.js.map +1 -0
  5. package/dist/src/cli/args.js +38 -0
  6. package/dist/src/cli/args.js.map +1 -0
  7. package/dist/src/cli/doctor.js +98 -0
  8. package/dist/src/cli/doctor.js.map +1 -0
  9. package/dist/src/cli/dotenv.js +58 -0
  10. package/dist/src/cli/dotenv.js.map +1 -0
  11. package/dist/src/cli/main.js +138 -0
  12. package/dist/src/cli/main.js.map +1 -0
  13. package/dist/src/cli/memory-cmd.js +31 -0
  14. package/dist/src/cli/memory-cmd.js.map +1 -0
  15. package/dist/src/cli/repl.js +275 -0
  16. package/dist/src/cli/repl.js.map +1 -0
  17. package/dist/src/cli/schedule.js +184 -0
  18. package/dist/src/cli/schedule.js.map +1 -0
  19. package/dist/src/cli/suggested.js +26 -0
  20. package/dist/src/cli/suggested.js.map +1 -0
  21. package/dist/src/cli/trace-cmd.js +69 -0
  22. package/dist/src/cli/trace-cmd.js.map +1 -0
  23. package/dist/src/cli/wizard.js +346 -0
  24. package/dist/src/cli/wizard.js.map +1 -0
  25. package/dist/src/config.js +130 -0
  26. package/dist/src/config.js.map +1 -0
  27. package/dist/src/eval/graders.js +145 -0
  28. package/dist/src/eval/graders.js.map +1 -0
  29. package/dist/src/eval/report.js +20 -0
  30. package/dist/src/eval/report.js.map +1 -0
  31. package/dist/src/eval/runner.js +67 -0
  32. package/dist/src/eval/runner.js.map +1 -0
  33. package/dist/src/eval/suites.js +164 -0
  34. package/dist/src/eval/suites.js.map +1 -0
  35. package/dist/src/http.js +134 -0
  36. package/dist/src/http.js.map +1 -0
  37. package/dist/src/inbox.js +51 -0
  38. package/dist/src/inbox.js.map +1 -0
  39. package/dist/src/index.js +180 -0
  40. package/dist/src/index.js.map +1 -0
  41. package/dist/src/memory/context.js +63 -0
  42. package/dist/src/memory/context.js.map +1 -0
  43. package/dist/src/memory/index.js +28 -0
  44. package/dist/src/memory/index.js.map +1 -0
  45. package/dist/src/memory/search.js +32 -0
  46. package/dist/src/memory/search.js.map +1 -0
  47. package/dist/src/memory/store.js +171 -0
  48. package/dist/src/memory/store.js.map +1 -0
  49. package/dist/src/observability/events.js +109 -0
  50. package/dist/src/observability/events.js.map +1 -0
  51. package/dist/src/observability/request.js +20 -0
  52. package/dist/src/observability/request.js.map +1 -0
  53. package/dist/src/observability/trace.js +149 -0
  54. package/dist/src/observability/trace.js.map +1 -0
  55. package/dist/src/paths.js +24 -0
  56. package/dist/src/paths.js.map +1 -0
  57. package/dist/src/permissions/approval.js +80 -0
  58. package/dist/src/permissions/approval.js.map +1 -0
  59. package/dist/src/permissions/policy.js +75 -0
  60. package/dist/src/permissions/policy.js.map +1 -0
  61. package/dist/src/permissions/rules.js +200 -0
  62. package/dist/src/permissions/rules.js.map +1 -0
  63. package/dist/src/prompt.js +114 -0
  64. package/dist/src/prompt.js.map +1 -0
  65. package/dist/src/providers/anthropic.js +233 -0
  66. package/dist/src/providers/anthropic.js.map +1 -0
  67. package/dist/src/providers/custom.js +46 -0
  68. package/dist/src/providers/custom.js.map +1 -0
  69. package/dist/src/providers/google.js +197 -0
  70. package/dist/src/providers/google.js.map +1 -0
  71. package/dist/src/providers/index.js +122 -0
  72. package/dist/src/providers/index.js.map +1 -0
  73. package/dist/src/providers/ollama.js +44 -0
  74. package/dist/src/providers/ollama.js.map +1 -0
  75. package/dist/src/providers/openai.js +193 -0
  76. package/dist/src/providers/openai.js.map +1 -0
  77. package/dist/src/providers/shared.js +32 -0
  78. package/dist/src/providers/shared.js.map +1 -0
  79. package/dist/src/sandbox/filesystem.js +193 -0
  80. package/dist/src/sandbox/filesystem.js.map +1 -0
  81. package/dist/src/sandbox/network.js +119 -0
  82. package/dist/src/sandbox/network.js.map +1 -0
  83. package/dist/src/sandbox/process.js +198 -0
  84. package/dist/src/sandbox/process.js.map +1 -0
  85. package/dist/src/skills.js +80 -0
  86. package/dist/src/skills.js.map +1 -0
  87. package/dist/src/tools/basics.js +41 -0
  88. package/dist/src/tools/basics.js.map +1 -0
  89. package/dist/src/tools/code.js +114 -0
  90. package/dist/src/tools/code.js.map +1 -0
  91. package/dist/src/tools/files.js +162 -0
  92. package/dist/src/tools/files.js.map +1 -0
  93. package/dist/src/tools/git.js +91 -0
  94. package/dist/src/tools/git.js.map +1 -0
  95. package/dist/src/tools/grep.js +92 -0
  96. package/dist/src/tools/grep.js.map +1 -0
  97. package/dist/src/tools/index.js +66 -0
  98. package/dist/src/tools/index.js.map +1 -0
  99. package/dist/src/tools/shared.js +11 -0
  100. package/dist/src/tools/shared.js.map +1 -0
  101. package/dist/src/tools/web.js +217 -0
  102. package/dist/src/tools/web.js.map +1 -0
  103. package/dist/src/types.js +14 -0
  104. package/dist/src/types.js.map +1 -0
  105. package/package.json +59 -0
  106. package/scripts/postinstall.js +47 -0
@@ -0,0 +1,122 @@
1
+ // The registry, and the string that picks a model.
2
+ //
3
+ // `anthropic/claude-opus-4-8`, `openai/gpt-5`, `google/gemini-2.5-pro`,
4
+ // `ollama/qwen3:8b`. The prefix picks an adapter; everything after the first
5
+ // slash is the model name and is passed through untouched. There is no
6
+ // allowlist of model names anywhere in this codebase, on purpose — a model
7
+ // released tomorrow works today.
8
+ import { customProvider, isShape, SHAPES } from "./custom.js";
9
+ import { OLLAMA_BASE_URL } from "./ollama.js";
10
+ const ENV_PREFIX = "VAAN_PROVIDER_";
11
+ const BUILT_IN = [
12
+ {
13
+ name: "anthropic",
14
+ shape: "anthropic",
15
+ baseUrl: "https://api.anthropic.com",
16
+ envKey: "ANTHROPIC_API_KEY",
17
+ },
18
+ {
19
+ name: "openai",
20
+ shape: "openai",
21
+ baseUrl: "https://api.openai.com/v1",
22
+ envKey: "OPENAI_API_KEY",
23
+ },
24
+ {
25
+ name: "google",
26
+ shape: "google",
27
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta",
28
+ envKey: "GOOGLE_API_KEY",
29
+ altEnvKeys: ["GEMINI_API_KEY"],
30
+ },
31
+ { name: "ollama", shape: "openai", baseUrl: OLLAMA_BASE_URL },
32
+ {
33
+ name: "groq",
34
+ shape: "openai",
35
+ baseUrl: "https://api.groq.com/openai/v1",
36
+ envKey: "GROQ_API_KEY",
37
+ },
38
+ ];
39
+ /**
40
+ * Built-ins plus anything registered through the environment:
41
+ *
42
+ * VAAN_PROVIDER_TOGETHER=openai:https://api.together.xyz/v1
43
+ *
44
+ * which reads its key from `TOGETHER_API_KEY`. A name that collides with a
45
+ * built-in overrides it, which is how you point `openai` at a proxy.
46
+ */
47
+ export function registry(env = process.env) {
48
+ const specs = new Map(BUILT_IN.map((spec) => [spec.name, spec]));
49
+ for (const [key, value] of Object.entries(env)) {
50
+ if (!key.startsWith(ENV_PREFIX) || !value)
51
+ continue;
52
+ const name = key.slice(ENV_PREFIX.length).toLowerCase();
53
+ specs.set(name, parseSpec(key, name, value));
54
+ }
55
+ return [...specs.values()];
56
+ }
57
+ function parseSpec(envName, name, value) {
58
+ const separator = value.indexOf(":");
59
+ const shape = value.slice(0, separator);
60
+ const baseUrl = value.slice(separator + 1).replace(/\/+$/, "");
61
+ if (!isShape(shape) || !baseUrl) {
62
+ // Loudly, rather than silently ignoring a typo and failing much later
63
+ // with a confusing 404 from whatever the default endpoint was.
64
+ throw new Error(`${envName} is malformed. Expected "<shape>:<url>" where shape is ` +
65
+ `"anthropic", "openai" or "google", for example "openai:https://api.example.com/v1".`);
66
+ }
67
+ return { name, shape, baseUrl, envKey: `${name.toUpperCase()}_API_KEY` };
68
+ }
69
+ /** The first of a spec's key names that is actually set. */
70
+ export function keyFor(spec, env) {
71
+ for (const name of [spec.envKey, ...(spec.altEnvKeys ?? [])]) {
72
+ if (name && env[name])
73
+ return env[name];
74
+ }
75
+ return undefined;
76
+ }
77
+ /** Split `provider/model` and build the adapter. Throws if the key is missing. */
78
+ export function resolve(spec, env = process.env) {
79
+ const slash = spec.indexOf("/");
80
+ const known = registry(env);
81
+ if (slash === -1) {
82
+ const names = known.map((entry) => entry.name).join(", ");
83
+ throw new Error(`"${spec}" is missing a provider prefix. Try one of: ${names}. ` +
84
+ `For example "${known[0]?.name ?? "anthropic"}/${spec}".`);
85
+ }
86
+ const name = spec.slice(0, slash).toLowerCase();
87
+ // Everything after the first slash, verbatim: model names contain slashes
88
+ // (meta-llama/Llama-3-70b) and colons (qwen3:8b).
89
+ const model = spec.slice(slash + 1);
90
+ const found = known.find((entry) => entry.name === name);
91
+ if (!found) {
92
+ const names = known.map((entry) => entry.name).join(", ");
93
+ throw new Error(`Unknown provider "${name}". Registered: ${names}.`);
94
+ }
95
+ if (!model)
96
+ throw new Error(`"${spec}" has a provider but no model name.`);
97
+ return { provider: build(found, env), model };
98
+ }
99
+ export function build(spec, env = process.env) {
100
+ const apiKey = spec.envKey ? (keyFor(spec, env) ?? "") : "";
101
+ if (spec.envKey && !apiKey) {
102
+ const names = [spec.envKey, ...(spec.altEnvKeys ?? [])].join(" or ");
103
+ throw new Error(`${spec.name} needs ${names}. Set it in your environment or .env, ` +
104
+ `or run \`vaan init\` to write one.`);
105
+ }
106
+ return customProvider({
107
+ name: spec.name,
108
+ shape: spec.shape,
109
+ baseUrl: spec.baseUrl,
110
+ apiKey,
111
+ ...(spec.envKey ? { envKey: spec.envKey } : {}),
112
+ });
113
+ }
114
+ /** What bare `/model` prints: registered prefixes and which keys are set. */
115
+ export function statuses(env = process.env) {
116
+ return registry(env).map((spec) => ({
117
+ ...spec,
118
+ ready: !spec.envKey || Boolean(keyFor(spec, env)),
119
+ }));
120
+ }
121
+ export { isShape, SHAPES };
122
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ // Ollama, and anything else serving an OpenAI-shaped API on this machine.
2
+ //
3
+ // It is the chat-completions adapter pointed at localhost, with one thing added
4
+ // that matters more than it looks: when the daemon isn't running, `fetch` fails
5
+ // with `ECONNREFUSED` and a URL, which reads like a bug in Vaan rather than a
6
+ // program that isn't started. Local models are the path people try first, so
7
+ // the first failure they see should say what to do.
8
+ import { openaiProvider } from "./openai.js";
9
+ export const OLLAMA_BASE_URL = "http://localhost:11434/v1";
10
+ export function ollamaProvider(opts) {
11
+ // No key: the header goes out anyway and the daemon ignores it.
12
+ const inner = openaiProvider({ ...opts, apiKey: opts.apiKey || "local" });
13
+ return {
14
+ name: opts.name,
15
+ async generate(req) {
16
+ try {
17
+ return await inner.generate(req);
18
+ }
19
+ catch (err) {
20
+ throw explain(err, opts.baseUrl, req.model);
21
+ }
22
+ },
23
+ async *stream(req) {
24
+ try {
25
+ yield* inner.stream(req);
26
+ }
27
+ catch (err) {
28
+ throw explain(err, opts.baseUrl, req.model);
29
+ }
30
+ },
31
+ };
32
+ }
33
+ function explain(err, baseUrl, model) {
34
+ const detail = err instanceof Error ? err.message : String(err);
35
+ if (/ECONNREFUSED|fetch failed|ENOTFOUND/i.test(detail)) {
36
+ return new Error(`Nothing is answering at ${baseUrl}. Start the daemon with \`ollama serve\`, ` +
37
+ `then \`ollama pull ${model}\` if you haven't already.`);
38
+ }
39
+ if (/404/.test(detail) && /model/i.test(detail)) {
40
+ return new Error(`Ollama doesn't have "${model}". Pull it first: \`ollama pull ${model}\`.`);
41
+ }
42
+ return err instanceof Error ? err : new Error(detail);
43
+ }
44
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/providers/ollama.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,8EAA8E;AAC9E,6EAA6E;AAC7E,oDAAoD;AAGpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,CAAC,MAAM,eAAe,GAAG,2BAA2B,CAAC;AAI3D,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,gEAAgE;IAChE,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,CAAC,QAAQ,CAAC,GAAoB;YACjC,IAAI,CAAC;gBACH,OAAO,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACnC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG;YACf,IAAI,CAAC;gBACH,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,GAAY,EAAE,OAAe,EAAE,KAAa;IAC3D,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAEhE,IAAI,sCAAsC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,OAAO,IAAI,KAAK,CACd,2BAA2B,OAAO,4CAA4C;YAC5E,sBAAsB,KAAK,4BAA4B,CAC1D,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,KAAK,CAAC,wBAAwB,KAAK,mCAAmC,KAAK,KAAK,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,193 @@
1
+ // Chat-completions adapter. Speaks to OpenAI and to everything that copies its
2
+ // shape — Groq, Together, Ollama, vLLM, LM Studio — by pointing at a different
3
+ // base URL. Two things differ from the Messages API and both bite:
4
+ //
5
+ // 1. Tool results are their own `role: "tool"` messages, one per result, not
6
+ // blocks inside a user turn. One Vaan message fans out into several.
7
+ // 2. `max_tokens` is deprecated upstream in favour of `max_completion_tokens`,
8
+ // but most compatible servers only accept the old name. We send the name
9
+ // that works everywhere.
10
+ import { parseFrameData, postJson, postSse } from "../http.js";
11
+ import { fallbackStream, isRecord, parseArguments } from "./shared.js";
12
+ export function openaiProvider(opts) {
13
+ const generate = async (req) => {
14
+ const json = (await postJson(`${opts.baseUrl}/chat/completions`, {
15
+ // Ollama and friends ignore the header; sending it unconditionally is
16
+ // simpler than teaching the adapter which servers want auth.
17
+ headers: { authorization: `Bearer ${opts.apiKey}` },
18
+ body: wireBody(req, false),
19
+ ...(req.signal ? { signal: req.signal } : {}),
20
+ }));
21
+ return fromWire(json);
22
+ };
23
+ return {
24
+ name: opts.name,
25
+ ...(opts.envKey ? { envKey: opts.envKey } : {}),
26
+ generate,
27
+ stream(req) {
28
+ return streamCompletions(opts, req, generate);
29
+ },
30
+ };
31
+ }
32
+ function wireBody(req, stream) {
33
+ const messages = [];
34
+ if (req.system)
35
+ messages.push({ role: "system", content: req.system });
36
+ for (const message of req.messages)
37
+ messages.push(...toWireMessages(message));
38
+ return {
39
+ model: req.model,
40
+ max_tokens: req.maxTokens,
41
+ messages,
42
+ ...(req.tools.length ? { tools: req.tools.map(toWireTool) } : {}),
43
+ ...(stream ? { stream: true, stream_options: { include_usage: true } } : {}),
44
+ };
45
+ }
46
+ function toWireMessages(message) {
47
+ // GUARD 1. Echo the assistant turn exactly as it arrived. Reasoning models
48
+ // return fields we don't model (`reasoning_content` and friends) that have to
49
+ // come back unmodified, and the turn's `tool_calls` must match the `tool`
50
+ // messages that follow it.
51
+ if (message.role === "assistant" && isRecord(message.raw))
52
+ return [message.raw];
53
+ const results = message.parts.filter((part) => part.type === "tool_result");
54
+ if (results.length > 0) {
55
+ // Fan out: one `tool` message per result. Unlike the Messages API these
56
+ // are siblings, not blocks inside a single user turn.
57
+ return results.map((part) => ({
58
+ role: "tool",
59
+ tool_call_id: part.id,
60
+ content: part.isError ? `Error: ${part.output}` : part.output,
61
+ }));
62
+ }
63
+ const text = message.parts
64
+ .filter((part) => part.type === "text")
65
+ .map((part) => part.text)
66
+ .join("");
67
+ return [{ role: message.role, content: text }];
68
+ }
69
+ const toWireTool = (tool) => ({
70
+ type: "function",
71
+ function: {
72
+ name: tool.name,
73
+ description: tool.description,
74
+ parameters: tool.parameters,
75
+ },
76
+ });
77
+ function fromWire(res) {
78
+ const choice = res.choices?.[0];
79
+ const wire = choice?.message ?? {};
80
+ const message = { role: "assistant", parts: partsOf(wire), raw: wire };
81
+ const usage = res.usage
82
+ ? { input: res.usage.prompt_tokens ?? 0, output: res.usage.completion_tokens ?? 0 }
83
+ : undefined;
84
+ return { message, stop: toStopReason(choice?.finish_reason), ...(usage ? { usage } : {}) };
85
+ }
86
+ function partsOf(wire) {
87
+ const parts = [];
88
+ if (wire.content)
89
+ parts.push({ type: "text", text: wire.content });
90
+ for (const call of wire.tool_calls ?? []) {
91
+ if (!call.id || !call.function?.name)
92
+ continue;
93
+ parts.push({
94
+ type: "tool_call",
95
+ id: call.id,
96
+ name: call.function.name,
97
+ input: parseArguments(call.function.arguments),
98
+ });
99
+ }
100
+ return parts;
101
+ }
102
+ function toStopReason(reason) {
103
+ switch (reason) {
104
+ case "tool_calls":
105
+ case "function_call":
106
+ return "tool_use";
107
+ case "length":
108
+ return "max_tokens";
109
+ default:
110
+ // There is no `pause_turn` equivalent in this shape.
111
+ return "done";
112
+ }
113
+ }
114
+ /**
115
+ * Reassemble a streamed completion into the same message `generate` returns.
116
+ *
117
+ * Tool calls arrive as fragments keyed by `index`, not by id — the id itself
118
+ * only appears in the first fragment — so they're accumulated positionally and
119
+ * only announced once the stream is done and the arguments are complete JSON.
120
+ */
121
+ async function* streamCompletions(opts, req, generate) {
122
+ const calls = [];
123
+ let text = "";
124
+ let finish;
125
+ let usage;
126
+ let yielded = false;
127
+ try {
128
+ const frames = postSse(`${opts.baseUrl}/chat/completions`, {
129
+ headers: { authorization: `Bearer ${opts.apiKey}` },
130
+ body: wireBody(req, true),
131
+ ...(req.signal ? { signal: req.signal } : {}),
132
+ });
133
+ for await (const frame of frames) {
134
+ const chunk = parseFrameData(frame.data);
135
+ if (!chunk)
136
+ continue;
137
+ if (chunk.usage) {
138
+ usage = {
139
+ input: chunk.usage.prompt_tokens ?? 0,
140
+ output: chunk.usage.completion_tokens ?? 0,
141
+ };
142
+ }
143
+ const choice = chunk.choices?.[0];
144
+ if (!choice)
145
+ continue;
146
+ if (choice.finish_reason)
147
+ finish = choice.finish_reason;
148
+ const content = choice.delta?.content;
149
+ if (content) {
150
+ text += content;
151
+ yielded = true;
152
+ yield { type: "text", text: content };
153
+ }
154
+ for (const fragment of choice.delta?.tool_calls ?? []) {
155
+ const index = fragment.index ?? calls.length;
156
+ const existing = calls[index] ?? { function: { name: "", arguments: "" } };
157
+ calls[index] = {
158
+ id: fragment.id ?? existing.id,
159
+ index,
160
+ function: {
161
+ name: fragment.function?.name ?? existing.function?.name,
162
+ arguments: (existing.function?.arguments ?? "") + (fragment.function?.arguments ?? ""),
163
+ },
164
+ };
165
+ }
166
+ }
167
+ }
168
+ catch (err) {
169
+ if (!yielded) {
170
+ yield* fallbackStream(generate, req);
171
+ return;
172
+ }
173
+ throw err;
174
+ }
175
+ const assembled = {
176
+ ...(text ? { content: text } : {}),
177
+ ...(calls.length ? { tool_calls: calls.filter((call) => call !== undefined) } : {}),
178
+ };
179
+ for (const part of partsOf(assembled)) {
180
+ if (part.type === "tool_call") {
181
+ yield { type: "tool_call", id: part.id, name: part.name, input: part.input };
182
+ }
183
+ }
184
+ yield {
185
+ type: "done",
186
+ reply: {
187
+ message: { role: "assistant", parts: partsOf(assembled), raw: assembled },
188
+ stop: toStopReason(finish),
189
+ ...(usage ? { usage } : {}),
190
+ },
191
+ };
192
+ }
193
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ // Bits every adapter needs, so none of them grows its own copy.
2
+ /**
3
+ * `stream` for an adapter that has no streaming endpoint, or whose stream just
4
+ * failed. It waits for the whole turn and then replays it as events: correct,
5
+ * and indistinguishable to a caller that only cares about the events — just not
6
+ * incremental. Better than an interface that is optional on half the providers.
7
+ */
8
+ export async function* fallbackStream(generate, req) {
9
+ const reply = await generate(req);
10
+ for (const part of reply.message.parts) {
11
+ if (part.type === "text")
12
+ yield { type: "text", text: part.text };
13
+ else if (part.type === "tool_call") {
14
+ yield { type: "tool_call", id: part.id, name: part.name, input: part.input };
15
+ }
16
+ }
17
+ yield { type: "done", reply };
18
+ }
19
+ /** Tool-call arguments arrive as a JSON string, and a model can emit bad JSON. */
20
+ export function parseArguments(raw) {
21
+ if (!raw)
22
+ return {};
23
+ try {
24
+ return JSON.parse(raw);
25
+ }
26
+ catch {
27
+ // An empty input reaches the tool, which reports what it needed.
28
+ return {};
29
+ }
30
+ }
31
+ export const isRecord = (value) => value !== null && typeof value === "object";
32
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/providers/shared.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAWhE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,cAAc,CACnC,QAA0D,EAC1D,GAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;aAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACnC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,GAAuB;IACpD,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAC3E,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC"}
@@ -0,0 +1,193 @@
1
+ // The filesystem boundary.
2
+ //
3
+ // Every path a tool is handed is resolved against the workspace and rejected if
4
+ // it lands outside. This is the fence. GUARDRAILS.md is instruction; a confused
5
+ // model can talk itself past instruction. It cannot talk itself past this.
6
+ //
7
+ // The permission policy sits above this and decides whether an in-bounds path
8
+ // may be written at all. The two are separate on purpose: the jail answers
9
+ // "where", the policy answers "may you".
10
+ import { readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from "node:fs";
11
+ import { dirname, join, relative, resolve, sep } from "node:path";
12
+ export class JailError extends Error {
13
+ constructor(candidate) {
14
+ super(`"${candidate}" is outside the workspace, so Vaan won't touch it.`);
15
+ this.name = "JailError";
16
+ }
17
+ }
18
+ /**
19
+ * Resolve `candidate` inside `workspace`, or throw.
20
+ *
21
+ * Two checks, because either alone has a hole. Resolving normalises away `..`,
22
+ * which stops a traversal spelled out in the path. But a symlink inside the
23
+ * workspace can point anywhere, and resolving doesn't follow it — so we also
24
+ * resolve the real path and check that. For a file that doesn't exist yet we
25
+ * check the nearest ancestor that does: components that don't exist can't be
26
+ * symlinks, so if the deepest real ancestor is inside, the new file will be too.
27
+ */
28
+ export function jail(workspace, candidate) {
29
+ const root = realpathSync(resolve(workspace));
30
+ const target = resolve(root, candidate);
31
+ if (!within(root, target))
32
+ throw new JailError(candidate);
33
+ if (!within(root, realpathOfNearest(target)))
34
+ throw new JailError(candidate);
35
+ return target;
36
+ }
37
+ /** The same question without the throw, for classification rather than access. */
38
+ export function isInside(workspace, candidate) {
39
+ try {
40
+ jail(workspace, candidate);
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ const within = (root, path) => path === root || path.startsWith(root + sep);
48
+ function realpathOfNearest(target) {
49
+ let current = target;
50
+ for (;;) {
51
+ try {
52
+ return realpathSync(current);
53
+ }
54
+ catch {
55
+ const parent = dirname(current);
56
+ // Hit the filesystem root without finding anything real. Nothing to
57
+ // resolve, and the plain resolve() check above already passed.
58
+ if (parent === current)
59
+ return current;
60
+ current = parent;
61
+ }
62
+ }
63
+ }
64
+ export const MAX_READ_BYTES = 100_000;
65
+ export const MAX_ENTRIES = 300;
66
+ export function readText(workspace, path) {
67
+ const target = jail(workspace, path);
68
+ const { size } = statSync(target);
69
+ const text = readFileSync(target, "utf8");
70
+ return size <= MAX_READ_BYTES
71
+ ? { text, bytes: size, truncated: false }
72
+ : { text: text.slice(0, MAX_READ_BYTES), bytes: size, truncated: true };
73
+ }
74
+ export function writeText(workspace, path, content) {
75
+ const target = jail(workspace, path);
76
+ writeFileSync(target, content, "utf8");
77
+ return target;
78
+ }
79
+ export function listEntries(workspace, path) {
80
+ const target = jail(workspace, path);
81
+ const all = readdirSync(target, { withFileTypes: true })
82
+ .map((entry) => (entry.isDirectory() ? `${entry.name}/` : entry.name))
83
+ .sort((a, b) => a.localeCompare(b));
84
+ return { entries: all.slice(0, MAX_ENTRIES), more: Math.max(0, all.length - MAX_ENTRIES) };
85
+ }
86
+ /** Directories that are never worth walking, and never what anyone meant. */
87
+ export const IGNORED_DIRS = new Set([
88
+ ".git",
89
+ ".vaan",
90
+ "node_modules",
91
+ "dist",
92
+ "build",
93
+ "out",
94
+ "target",
95
+ "coverage",
96
+ ".next",
97
+ ".nuxt",
98
+ ".venv",
99
+ "venv",
100
+ "__pycache__",
101
+ ".pytest_cache",
102
+ ".mypy_cache",
103
+ ".gradle",
104
+ ".idea",
105
+ ".cache",
106
+ "vendor",
107
+ ]);
108
+ /** Every file under `workspace`, skipping the directories nobody greps. */
109
+ export function* walk(workspace, opts = {}) {
110
+ const limit = opts.limit ?? 20_000;
111
+ const maxDepth = opts.maxDepth ?? 12;
112
+ const root = realpathSync(resolve(workspace));
113
+ let seen = 0;
114
+ const queue = [{ dir: root, depth: 0 }];
115
+ while (queue.length > 0) {
116
+ const next = queue.shift();
117
+ if (!next || next.depth > maxDepth)
118
+ continue;
119
+ let entries;
120
+ try {
121
+ entries = readdirSync(next.dir, { withFileTypes: true });
122
+ }
123
+ catch {
124
+ continue; // Unreadable directory: not an error, just nothing to report.
125
+ }
126
+ for (const entry of entries) {
127
+ if (entry.name.startsWith(".") && entry.name !== ".github") {
128
+ if (IGNORED_DIRS.has(entry.name) || entry.isDirectory())
129
+ continue;
130
+ }
131
+ const full = join(next.dir, entry.name);
132
+ if (entry.isDirectory()) {
133
+ if (!IGNORED_DIRS.has(entry.name))
134
+ queue.push({ dir: full, depth: next.depth + 1 });
135
+ continue;
136
+ }
137
+ if (!entry.isFile())
138
+ continue;
139
+ if (++seen > limit)
140
+ return;
141
+ yield relative(root, full);
142
+ }
143
+ }
144
+ }
145
+ /** Bytes past which a file is assumed to be a build artefact rather than source. */
146
+ const MAX_SEARCHABLE_BYTES = 400_000;
147
+ /**
148
+ * Grep the workspace. Plain substring by default; a regex when asked, compiled
149
+ * with a length cap so a pathological pattern can't hang the turn.
150
+ */
151
+ export function search(workspace, needle, opts = {}) {
152
+ const limit = opts.limit ?? 60;
153
+ const matcher = opts.regex ? safeRegex(needle) : undefined;
154
+ const lowered = needle.toLowerCase();
155
+ const out = [];
156
+ for (const path of walk(workspace)) {
157
+ if (out.length >= limit)
158
+ break;
159
+ if (opts.glob && !path.includes(opts.glob) && !path.endsWith(opts.glob))
160
+ continue;
161
+ let body;
162
+ try {
163
+ const full = join(realpathSync(resolve(workspace)), path);
164
+ if (statSync(full).size > MAX_SEARCHABLE_BYTES)
165
+ continue;
166
+ body = readFileSync(full, "utf8");
167
+ }
168
+ catch {
169
+ continue; // Binary, unreadable, or gone since the walk. Skip it.
170
+ }
171
+ if (body.includes("\u0000"))
172
+ continue;
173
+ const lines = body.split("\n");
174
+ for (let index = 0; index < lines.length && out.length < limit; index++) {
175
+ const line = lines[index] ?? "";
176
+ const hit = matcher ? matcher.test(line) : line.toLowerCase().includes(lowered);
177
+ if (hit)
178
+ out.push({ path, line: index + 1, text: line.trim().slice(0, 200) });
179
+ }
180
+ }
181
+ return out;
182
+ }
183
+ function safeRegex(pattern) {
184
+ if (pattern.length > 200)
185
+ throw new Error("Pattern is too long.");
186
+ try {
187
+ return new RegExp(pattern);
188
+ }
189
+ catch (err) {
190
+ throw new Error(`Not a valid regular expression: ${err instanceof Error ? err.message : err}`);
191
+ }
192
+ }
193
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../../src/sandbox/filesystem.ts"],"names":[],"mappings":"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"}