zidane 1.3.1 → 1.4.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.
@@ -2,11 +2,108 @@ import {
2
2
  connectMcpServers,
3
3
  init_mcp
4
4
  } from "./chunk-26LIQARN.js";
5
+ import {
6
+ buildCatalog,
7
+ init_catalog,
8
+ init_interpolate,
9
+ init_resolve,
10
+ interpolateShellCommands,
11
+ mergeSkillsConfig,
12
+ resolveSkills
13
+ } from "./chunk-PRNQ7DXE.js";
5
14
  import {
6
15
  __esm,
7
- __export
16
+ __export,
17
+ __toCommonJS
8
18
  } from "./chunk-PNKVD2UK.js";
9
19
 
20
+ // src/tools/list-files.ts
21
+ var listFiles;
22
+ var init_list_files = __esm({
23
+ "src/tools/list-files.ts"() {
24
+ "use strict";
25
+ listFiles = {
26
+ spec: {
27
+ name: "list_files",
28
+ description: "List files and directories at the given path (relative to project root).",
29
+ input_schema: {
30
+ type: "object",
31
+ properties: {
32
+ path: { type: "string", description: 'Relative directory path (default: ".")' }
33
+ },
34
+ required: []
35
+ }
36
+ },
37
+ async execute({ path }, ctx) {
38
+ try {
39
+ const entries = await ctx.execution.listFiles(ctx.handle, path || ".");
40
+ return entries.join("\n") || "(empty directory)";
41
+ } catch {
42
+ return `Directory not found: ${path}`;
43
+ }
44
+ }
45
+ };
46
+ }
47
+ });
48
+
49
+ // src/tools/read-file.ts
50
+ var readFile;
51
+ var init_read_file = __esm({
52
+ "src/tools/read-file.ts"() {
53
+ "use strict";
54
+ readFile = {
55
+ spec: {
56
+ name: "read_file",
57
+ description: "Read the contents of a file at the given path (relative to project root).",
58
+ input_schema: {
59
+ type: "object",
60
+ properties: {
61
+ path: { type: "string", description: "Relative file path" }
62
+ },
63
+ required: ["path"]
64
+ }
65
+ },
66
+ async execute({ path }, ctx) {
67
+ try {
68
+ return await ctx.execution.readFile(ctx.handle, path);
69
+ } catch {
70
+ return `File not found: ${path}`;
71
+ }
72
+ }
73
+ };
74
+ }
75
+ });
76
+
77
+ // src/tools/shell.ts
78
+ var shell;
79
+ var init_shell = __esm({
80
+ "src/tools/shell.ts"() {
81
+ "use strict";
82
+ shell = {
83
+ spec: {
84
+ name: "shell",
85
+ description: "Execute a shell command and return stdout+stderr. Runs in the project root.",
86
+ input_schema: {
87
+ type: "object",
88
+ properties: {
89
+ command: { type: "string", description: "The shell command to run" }
90
+ },
91
+ required: ["command"]
92
+ }
93
+ },
94
+ async execute({ command }, ctx) {
95
+ const result = await ctx.execution.exec(ctx.handle, command);
96
+ if (result.exitCode === 0) {
97
+ return result.stdout || "(no output)";
98
+ }
99
+ return `Exit code ${result.exitCode}
100
+ ${result.stdout}
101
+ ${result.stderr}`.trim();
102
+ }
103
+ };
104
+ }
105
+ });
106
+
10
107
  // src/contexts/docker.ts
11
108
  function createDockerContext(config) {
12
109
  let counter = 0;
@@ -35,16 +132,16 @@ function createDockerContext(config) {
35
132
  const docker = await getDockerode();
36
133
  const id = `docker-${++counter}`;
37
134
  const image = overrides?.image ?? defaultImage;
38
- const cwd5 = overrides?.cwd ?? defaultCwd;
135
+ const cwd = overrides?.cwd ?? defaultCwd;
39
136
  try {
40
137
  await docker.getImage(image).inspect();
41
138
  } catch {
42
- await new Promise((resolve5, reject) => {
139
+ await new Promise((resolve2, reject) => {
43
140
  docker.pull(image, (err, stream) => {
44
141
  if (err)
45
142
  return reject(err);
46
143
  docker.modem.followProgress(stream, (err2) => {
47
- err2 ? reject(err2) : resolve5();
144
+ err2 ? reject(err2) : resolve2();
48
145
  });
49
146
  });
50
147
  });
@@ -61,12 +158,12 @@ function createDockerContext(config) {
61
158
  const container = await docker.createContainer({
62
159
  Image: image,
63
160
  Cmd: ["sleep", "infinity"],
64
- WorkingDir: cwd5,
161
+ WorkingDir: cwd,
65
162
  Env: Object.entries(env).map(([k, v]) => `${k}=${v}`),
66
163
  HostConfig: hostConfig
67
164
  });
68
165
  await container.start();
69
- const handle = { id, type: "docker", cwd: cwd5 };
166
+ const handle = { id, type: "docker", cwd };
70
167
  containers.set(id, { handle, container, docker });
71
168
  return handle;
72
169
  },
@@ -84,12 +181,12 @@ function createDockerContext(config) {
84
181
  AttachStderr: true
85
182
  });
86
183
  const stream = await exec.start({ Detach: false });
87
- return new Promise((resolve5) => {
184
+ return new Promise((resolve2) => {
88
185
  let stdout = "";
89
186
  const stderr = "";
90
187
  const timeout = options?.timeout ?? defaultLimits?.timeout ?? 30;
91
188
  const timer = setTimeout(() => {
92
- resolve5({ stdout, stderr: `${stderr}
189
+ resolve2({ stdout, stderr: `${stderr}
93
190
  [timeout]`, exitCode: 124 });
94
191
  }, timeout * 1e3);
95
192
  stream.on("data", (chunk) => {
@@ -98,7 +195,7 @@ function createDockerContext(config) {
98
195
  stream.on("end", async () => {
99
196
  clearTimeout(timer);
100
197
  const inspect = await exec.inspect();
101
- resolve5({ stdout, stderr, exitCode: inspect.ExitCode ?? 0 });
198
+ resolve2({ stdout, stderr, exitCode: inspect.ExitCode ?? 0 });
102
199
  });
103
200
  });
104
201
  },
@@ -145,7 +242,7 @@ var init_docker = __esm({
145
242
  // src/contexts/process.ts
146
243
  import { exec as execCb } from "child_process";
147
244
  import { mkdir, readdir, readFile as readFile2, writeFile } from "fs/promises";
148
- import { dirname, resolve as resolve3 } from "path";
245
+ import { dirname, resolve } from "path";
149
246
  import { promisify } from "util";
150
247
  function createProcessContext(config) {
151
248
  let counter = 0;
@@ -162,17 +259,17 @@ function createProcessContext(config) {
162
259
  },
163
260
  async spawn(overrides) {
164
261
  const id = `process-${++counter}`;
165
- const cwd5 = overrides?.cwd ?? defaultCwd;
166
- await mkdir(cwd5, { recursive: true });
167
- const handle = { id, type: "process", cwd: cwd5 };
262
+ const cwd = overrides?.cwd ?? defaultCwd;
263
+ await mkdir(cwd, { recursive: true });
264
+ const handle = { id, type: "process", cwd };
168
265
  handles.set(id, handle);
169
266
  return handle;
170
267
  },
171
268
  async exec(handle, command, options) {
172
- const cwd5 = options?.cwd ? resolve3(handle.cwd, options.cwd) : handle.cwd;
269
+ const cwd = options?.cwd ? resolve(handle.cwd, options.cwd) : handle.cwd;
173
270
  try {
174
271
  const { stdout, stderr } = await execAsync(command, {
175
- cwd: cwd5,
272
+ cwd,
176
273
  env: { ...process.env, ...defaultEnv, ...options?.env },
177
274
  timeout: (options?.timeout ?? config?.limits?.timeout ?? 30) * 1e3,
178
275
  maxBuffer: 10 * 1024 * 1024
@@ -187,15 +284,15 @@ function createProcessContext(config) {
187
284
  }
188
285
  },
189
286
  async readFile(handle, path) {
190
- return readFile2(resolve3(handle.cwd, path), "utf-8");
287
+ return readFile2(resolve(handle.cwd, path), "utf-8");
191
288
  },
192
289
  async writeFile(handle, path, content) {
193
- const fullPath = resolve3(handle.cwd, path);
290
+ const fullPath = resolve(handle.cwd, path);
194
291
  await mkdir(dirname(fullPath), { recursive: true });
195
292
  await writeFile(fullPath, content, "utf-8");
196
293
  },
197
294
  async listFiles(handle, path) {
198
- return readdir(resolve3(handle.cwd, path));
295
+ return readdir(resolve(handle.cwd, path));
199
296
  },
200
297
  async destroy(handle) {
201
298
  handles.delete(handle.id);
@@ -270,6 +367,52 @@ var init_contexts = __esm({
270
367
  }
271
368
  });
272
369
 
370
+ // src/harnesses/basic.ts
371
+ function getSpawn() {
372
+ if (!_spawn) {
373
+ _spawn = (init_spawn(), __toCommonJS(spawn_exports)).spawn;
374
+ }
375
+ return _spawn;
376
+ }
377
+ var basicTools, _spawn, spawnProxy, basic_default;
378
+ var init_basic = __esm({
379
+ "src/harnesses/basic.ts"() {
380
+ "use strict";
381
+ init_harnesses();
382
+ init_tools();
383
+ basicTools = { shell, readFile, writeFile: writeFile2, listFiles };
384
+ spawnProxy = {
385
+ get spec() {
386
+ return getSpawn().spec;
387
+ },
388
+ execute(input, ctx) {
389
+ return getSpawn().execute(input, ctx);
390
+ }
391
+ };
392
+ basic_default = defineHarness({
393
+ name: "basic",
394
+ system: "You are a helpful assistant with access to shell, file reading, file writing, directory listing, and sub-agent spawning tools. Use them to accomplish tasks in the project directory.",
395
+ tools: { ...basicTools, spawn: spawnProxy }
396
+ });
397
+ }
398
+ });
399
+
400
+ // src/harnesses/index.ts
401
+ function defineHarness(config) {
402
+ return config;
403
+ }
404
+ var noTools;
405
+ var init_harnesses = __esm({
406
+ "src/harnesses/index.ts"() {
407
+ init_basic();
408
+ noTools = defineHarness({
409
+ name: "none",
410
+ system: "You are a helpful assistant.",
411
+ tools: {}
412
+ });
413
+ }
414
+ });
415
+
273
416
  // src/tools/validation.ts
274
417
  function validateToolArgs(input, schema) {
275
418
  const required = schema.required ?? [];
@@ -288,7 +431,7 @@ var init_validation = __esm({
288
431
 
289
432
  // src/loop.ts
290
433
  function turnsToMessages(turns) {
291
- return turns.map((t) => ({ role: t.role, content: t.content }));
434
+ return turns.filter((t) => t.role !== "system").map((t) => ({ role: t.role, content: t.content }));
292
435
  }
293
436
  async function runLoop(ctx) {
294
437
  let totalIn = 0;
@@ -356,7 +499,7 @@ async function executeTurn(ctx, turn) {
356
499
  await ctx.hooks.callHook("context:transform", { messages });
357
500
  await ctx.hooks.callHook("turn:before", { turn, turnId, options: streamOptions });
358
501
  let currentText = "";
359
- const blockIndex = 0;
502
+ let blockIndex = 0;
360
503
  const result = await ctx.provider.stream(
361
504
  streamOptions,
362
505
  {
@@ -368,6 +511,7 @@ async function executeTurn(ctx, turn) {
368
511
  );
369
512
  if (currentText) {
370
513
  await ctx.hooks.callHook("stream:end", { text: currentText, turnId, blockIndex });
514
+ blockIndex++;
371
515
  }
372
516
  await ctx.hooks.callHook("turn:after", { turn, turnId, usage: result.usage });
373
517
  if (result.done) {
@@ -484,8 +628,9 @@ var init_loop = __esm({
484
628
 
485
629
  // src/agent.ts
486
630
  import { createHooks } from "hookable";
487
- function createAgent({ harness, provider, toolExecution = "sequential", execution, mcpServers, session, _mcpConnector }) {
631
+ function createAgent({ harness: harnessOption, provider, toolExecution = "sequential", enableTools = true, execution, mcpServers, session, skills: agentSkills, _mcpConnector }) {
488
632
  const hooks = createHooks();
633
+ const harness = harnessOption ?? noTools;
489
634
  const executionContext = execution ?? createProcessContext();
490
635
  let abortController;
491
636
  let running = false;
@@ -498,6 +643,11 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
498
643
  const followUpQueue = [];
499
644
  let conversationTurns = session?.turns.slice() ?? [];
500
645
  let runCounter = session?.runs.length ?? 0;
646
+ const mergedSkillsConfig = mergeSkillsConfig(harness.skills, agentSkills);
647
+ const skillsEnabledValue = mergedSkillsConfig?.enabled;
648
+ const skillsDisabled = skillsEnabledValue === false || Array.isArray(skillsEnabledValue) && skillsEnabledValue.length === 0;
649
+ let resolvedSkills = null;
650
+ let skillsCatalog = null;
501
651
  async function run(options) {
502
652
  if (running) {
503
653
  throw new Error("Agent is already running. Use steer() or followUp() to queue messages, or waitForIdle().");
@@ -518,8 +668,8 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
518
668
  options.signal.addEventListener("abort", onExternalAbort, { once: true });
519
669
  }
520
670
  }
521
- idlePromise = new Promise((resolve5) => {
522
- idleResolve = resolve5;
671
+ idlePromise = new Promise((resolve2) => {
672
+ idleResolve = resolve2;
523
673
  });
524
674
  const childrenStats = [];
525
675
  const unregisterSpawnHook = hooks.hook("spawn:complete", (ctx) => {
@@ -535,10 +685,52 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
535
685
  mcpConnection = await connectMcpServers(allMcpServers, void 0, hooks);
536
686
  }
537
687
  }
688
+ if (!skillsDisabled && mergedSkillsConfig && !resolvedSkills) {
689
+ resolvedSkills = await resolveSkills(mergedSkillsConfig);
690
+ await hooks.callHook("skills:resolve", { skills: resolvedSkills });
691
+ if (executionHandle) {
692
+ for (const skill of resolvedSkills) {
693
+ if (skill.instructions.includes("!`")) {
694
+ skill.instructions = await interpolateShellCommands(
695
+ skill.instructions,
696
+ executionContext,
697
+ executionHandle
698
+ );
699
+ }
700
+ }
701
+ }
702
+ const readToolName = mergedSkillsConfig.readToolName ?? "read_file";
703
+ const catalogCtx = { catalog: buildCatalog(resolvedSkills, readToolName), skills: resolvedSkills };
704
+ await hooks.callHook("skills:catalog", catalogCtx);
705
+ skillsCatalog = catalogCtx.catalog;
706
+ const fsSkills = resolvedSkills.filter((s) => s.location);
707
+ if (fsSkills.length > 0) {
708
+ const skillByLocation = new Map(fsSkills.map((s) => [s.location, s]));
709
+ hooks.hook("tool:after", (ctx) => {
710
+ if (ctx.name !== readToolName)
711
+ return;
712
+ const path = ctx.input.path;
713
+ if (!path)
714
+ return;
715
+ const matched = skillByLocation.get(path) ?? fsSkills.find((s) => s.location.endsWith(path));
716
+ if (matched)
717
+ hooks.callHook("skills:activate", { skill: matched });
718
+ });
719
+ }
720
+ }
538
721
  const thinking = options.thinking ?? "off";
539
722
  const model = options.model ?? provider.meta.defaultModel;
540
- const system = options.system || harness.system || "You are a helpful assistant.";
541
- const tools = mcpConnection ? { ...harness.tools, ...mcpConnection.tools } : harness.tools;
723
+ let system = options.system || harness.system || "You are a helpful assistant.";
724
+ if (skillsCatalog) {
725
+ system = `${system}
726
+
727
+ ${skillsCatalog}`;
728
+ }
729
+ const harnessTools = enableTools ? mcpConnection ? { ...harness.tools, ...mcpConnection.tools } : harness.tools : {};
730
+ const tools = {};
731
+ for (const tool of Object.values(harnessTools)) {
732
+ tools[tool.spec.name] = tool;
733
+ }
542
734
  const toolSpecs = Object.values(tools).map(
543
735
  (t) => ({
544
736
  name: t.spec.name,
@@ -546,7 +738,7 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
546
738
  input_schema: t.spec.input_schema
547
739
  })
548
740
  );
549
- const formattedTools = provider.formatTools(toolSpecs);
741
+ const formattedTools = enableTools ? provider.formatTools(toolSpecs) : [];
550
742
  const turns = [];
551
743
  const isResume = session && session.turns.length > 0 && session.runs.length > 0;
552
744
  if (isResume) {
@@ -751,8 +943,12 @@ var init_agent = __esm({
751
943
  "src/agent.ts"() {
752
944
  "use strict";
753
945
  init_contexts();
946
+ init_harnesses();
754
947
  init_loop();
755
948
  init_mcp();
949
+ init_catalog();
950
+ init_interpolate();
951
+ init_resolve();
756
952
  }
757
953
  });
758
954
 
@@ -762,6 +958,17 @@ __export(spawn_exports, {
762
958
  createSpawnTool: () => createSpawnTool,
763
959
  spawn: () => spawn
764
960
  });
961
+ function extractText(message) {
962
+ if (!message || typeof message !== "object")
963
+ return "";
964
+ const msg = message;
965
+ if (typeof msg.content === "string")
966
+ return msg.content;
967
+ if (Array.isArray(msg.content)) {
968
+ return msg.content.filter((block) => block.type === "text").map((block) => block.text).join("\n");
969
+ }
970
+ return "";
971
+ }
765
972
  function createSpawnTool(options = {}) {
766
973
  const localChildren = /* @__PURE__ */ new Map();
767
974
  let localCounter = 0;
@@ -851,257 +1058,71 @@ function createSpawnTool(options = {}) {
851
1058
  }
852
1059
  };
853
1060
  }
854
- function extractText(message) {
855
- if (!message || typeof message !== "object")
856
- return "";
857
- const msg = message;
858
- if (typeof msg.content === "string")
859
- return msg.content;
860
- if (Array.isArray(msg.content)) {
861
- return msg.content.filter((block) => block.type === "text").map((block) => block.text).join("\n");
862
- }
863
- return "";
864
- }
865
- var children, childCounter, activeCount, MAX_CONCURRENT, _totalChildStats, spawn;
1061
+ var spawn;
866
1062
  var init_spawn = __esm({
867
1063
  "src/tools/spawn.ts"() {
868
1064
  "use strict";
869
1065
  init_agent();
870
- children = /* @__PURE__ */ new Map();
871
- childCounter = 0;
872
- activeCount = 0;
873
- MAX_CONCURRENT = 3;
874
- _totalChildStats = {
875
- totalIn: 0,
876
- totalOut: 0,
877
- turns: 0,
878
- elapsed: 0
879
- };
880
- spawn = {
881
- get children() {
882
- return children;
883
- },
884
- get totalChildStats() {
885
- return { ..._totalChildStats };
886
- },
1066
+ spawn = createSpawnTool();
1067
+ }
1068
+ });
1069
+
1070
+ // src/tools/write-file.ts
1071
+ var writeFile2;
1072
+ var init_write_file = __esm({
1073
+ "src/tools/write-file.ts"() {
1074
+ "use strict";
1075
+ writeFile2 = {
887
1076
  spec: {
888
- name: "spawn",
889
- description: "Spawn a sub-agent to work on a specific task. The sub-agent runs independently with its own tool access and returns its final response. Use this to delegate work, parallelize tasks, or isolate concerns.",
1077
+ name: "write_file",
1078
+ description: "Write content to a file. Creates parent directories if needed.",
890
1079
  input_schema: {
891
1080
  type: "object",
892
1081
  properties: {
893
- task: {
894
- type: "string",
895
- description: "The task prompt for the sub-agent. Be specific about what you want it to accomplish."
896
- },
897
- system: {
898
- type: "string",
899
- description: "Optional system prompt override for this specific sub-agent."
900
- }
1082
+ path: { type: "string", description: "Relative file path" },
1083
+ content: { type: "string", description: "File content to write" }
901
1084
  },
902
- required: ["task"]
1085
+ required: ["path", "content"]
903
1086
  }
904
1087
  },
905
- async execute(input, ctx) {
906
- const task = input.task;
907
- const systemOverride = input.system;
908
- if (activeCount >= MAX_CONCURRENT) {
909
- return `Cannot spawn: ${activeCount}/${MAX_CONCURRENT} sub-agents already running. Wait for one to complete.`;
910
- }
911
- const id = `child-${++childCounter}`;
912
- const child = { id, task, startedAt: Date.now() };
913
- const agent = createAgent({
914
- harness: ctx.harness,
915
- provider: ctx.provider,
916
- execution: ctx.execution
917
- });
918
- children.set(id, child);
919
- activeCount++;
920
- await ctx.hooks.callHook("spawn:before", { id, task });
921
- try {
922
- const stats = await agent.run({
923
- prompt: task,
924
- system: systemOverride,
925
- signal: ctx.signal
926
- });
927
- _totalChildStats.totalIn += stats.totalIn;
928
- _totalChildStats.totalOut += stats.totalOut;
929
- _totalChildStats.turns += stats.turns;
930
- _totalChildStats.elapsed += stats.elapsed;
931
- await ctx.hooks.callHook("spawn:complete", {
932
- id,
933
- task,
934
- stats
935
- });
936
- const response = extractText(agent.turns.at(-1));
937
- return [
938
- `[sub-agent ${id}] Completed in ${stats.turns} turns (${stats.elapsed}ms)`,
939
- `Tokens: ${stats.totalIn} in / ${stats.totalOut} out`,
940
- "",
941
- response || "(no text response)"
942
- ].join("\n");
943
- } catch (err) {
944
- await ctx.hooks.callHook("spawn:error", { id, task, error: err });
945
- return `[sub-agent ${id}] Error: ${err.message}`;
946
- } finally {
947
- activeCount--;
948
- await agent.destroy();
949
- children.delete(id);
950
- }
1088
+ async execute({ path, content }, ctx) {
1089
+ await ctx.execution.writeFile(ctx.handle, path, content);
1090
+ return `Wrote ${content.length} bytes to ${path}`;
951
1091
  }
952
1092
  };
953
1093
  }
954
1094
  });
955
1095
 
956
- // src/tools/list-files.ts
957
- import { existsSync, readdirSync, statSync } from "fs";
958
- import { resolve } from "path";
959
- var cwd = process.cwd();
960
- function safePath(p) {
961
- const resolved = resolve(cwd, p);
962
- if (!resolved.startsWith(cwd))
963
- throw new Error(`Path escapes working directory: ${p}`);
964
- return resolved;
965
- }
966
- var listFiles = {
967
- spec: {
968
- name: "list_files",
969
- description: "List files and directories at the given path (relative to project root).",
970
- input_schema: {
971
- type: "object",
972
- properties: {
973
- path: { type: "string", description: 'Relative directory path (default: ".")' }
974
- },
975
- required: []
976
- }
977
- },
978
- async execute({ path }, _ctx) {
979
- const target = safePath(path || ".");
980
- if (!existsSync(target))
981
- return `Directory not found: ${path}`;
982
- const entries = readdirSync(target);
983
- return entries.map((name) => {
984
- const full = resolve(target, name);
985
- const isDir = statSync(full).isDirectory();
986
- return `${isDir ? "\u{1F4C1}" : "\u{1F4C4}"} ${name}`;
987
- }).join("\n");
988
- }
989
- };
990
-
991
- // src/tools/read-file.ts
992
- import { existsSync as existsSync2, readFileSync } from "fs";
993
- import { resolve as resolve2 } from "path";
994
- var cwd2 = process.cwd();
995
- function safePath2(p) {
996
- const resolved = resolve2(cwd2, p);
997
- if (!resolved.startsWith(cwd2))
998
- throw new Error(`Path escapes working directory: ${p}`);
999
- return resolved;
1000
- }
1001
- var readFile = {
1002
- spec: {
1003
- name: "read_file",
1004
- description: "Read the contents of a file at the given path (relative to project root).",
1005
- input_schema: {
1006
- type: "object",
1007
- properties: {
1008
- path: { type: "string", description: "Relative file path" }
1009
- },
1010
- required: ["path"]
1011
- }
1012
- },
1013
- async execute({ path }, _ctx) {
1014
- const target = safePath2(path);
1015
- if (!existsSync2(target))
1016
- return `File not found: ${path}`;
1017
- return readFileSync(target, "utf-8");
1018
- }
1019
- };
1020
-
1021
- // src/tools/shell.ts
1022
- import { execSync } from "child_process";
1023
- var cwd3 = process.cwd();
1024
- var shell = {
1025
- spec: {
1026
- name: "shell",
1027
- description: "Execute a shell command and return stdout+stderr. Runs in the project root.",
1028
- input_schema: {
1029
- type: "object",
1030
- properties: {
1031
- command: { type: "string", description: "The shell command to run" }
1032
- },
1033
- required: ["command"]
1034
- }
1035
- },
1036
- async execute({ command }, _ctx) {
1037
- try {
1038
- const out = execSync(command, {
1039
- cwd: cwd3,
1040
- encoding: "utf-8",
1041
- timeout: 3e4,
1042
- maxBuffer: 1024 * 1024,
1043
- stdio: ["pipe", "pipe", "pipe"]
1044
- });
1045
- return out || "(no output)";
1046
- } catch (err) {
1047
- const stderr = err.stderr?.toString() ?? "";
1048
- const stdout = err.stdout?.toString() ?? "";
1049
- return `Exit code ${err.status ?? 1}
1050
- ${stdout}
1051
- ${stderr}`.trim();
1052
- }
1053
- }
1054
- };
1055
-
1056
1096
  // src/tools/index.ts
1057
- init_spawn();
1058
- init_validation();
1059
-
1060
- // src/tools/write-file.ts
1061
- import { mkdirSync, writeFileSync } from "fs";
1062
- import { dirname as dirname2, resolve as resolve4 } from "path";
1063
- var cwd4 = process.cwd();
1064
- function safePath3(p) {
1065
- const resolved = resolve4(cwd4, p);
1066
- if (!resolved.startsWith(cwd4))
1067
- throw new Error(`Path escapes working directory: ${p}`);
1068
- return resolved;
1069
- }
1070
- var writeFile2 = {
1071
- spec: {
1072
- name: "write_file",
1073
- description: "Write content to a file. Creates parent directories if needed.",
1074
- input_schema: {
1075
- type: "object",
1076
- properties: {
1077
- path: { type: "string", description: "Relative file path" },
1078
- content: { type: "string", description: "File content to write" }
1079
- },
1080
- required: ["path", "content"]
1081
- }
1082
- },
1083
- async execute({ path, content }, _ctx) {
1084
- const target = safePath3(path);
1085
- mkdirSync(dirname2(target), { recursive: true });
1086
- writeFileSync(target, content);
1087
- return `Wrote ${content.length} bytes to ${path}`;
1097
+ var init_tools = __esm({
1098
+ "src/tools/index.ts"() {
1099
+ init_list_files();
1100
+ init_read_file();
1101
+ init_shell();
1102
+ init_spawn();
1103
+ init_validation();
1104
+ init_write_file();
1088
1105
  }
1089
- };
1106
+ });
1090
1107
 
1091
1108
  export {
1092
1109
  createDockerContext,
1093
1110
  createProcessContext,
1094
1111
  createSandboxContext,
1095
1112
  init_contexts,
1096
- validateToolArgs,
1097
- createAgent,
1098
- init_agent,
1099
1113
  listFiles,
1100
1114
  readFile,
1101
1115
  shell,
1102
- spawn,
1103
1116
  createSpawnTool,
1104
- spawn_exports,
1105
- init_spawn,
1106
- writeFile2 as writeFile
1117
+ spawn,
1118
+ validateToolArgs,
1119
+ writeFile2 as writeFile,
1120
+ init_tools,
1121
+ basicTools,
1122
+ basic_default,
1123
+ defineHarness,
1124
+ noTools,
1125
+ init_harnesses,
1126
+ createAgent,
1127
+ init_agent
1107
1128
  };