open-walnut 0.4.1 → 0.4.2

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 (31) hide show
  1. package/README.md +2 -5
  2. package/dist/cli-fast.js +69 -46
  3. package/dist/cli.js +704 -274
  4. package/dist/daemon-binaries/acp-worker.js.version +1 -1
  5. package/dist/web/server.js +704 -274
  6. package/dist/web/static/assets/{OfficePreview-C8OMbtiq.js → OfficePreview-CEHO0xkd.js} +2 -2
  7. package/dist/web/static/assets/{docx-preview-hDgtrOpv.js → docx-preview-CuZwjAMS.js} +1 -1
  8. package/dist/web/static/assets/{index-CWIydpPr.js → index-0MyC-yGG.js} +1 -1
  9. package/dist/web/static/assets/{index-BAb6UVet.js → index-BBjg7m-_.js} +1 -1
  10. package/dist/web/static/assets/{index-D1uUk0AQ.js → index-BFF_G72i.js} +289 -289
  11. package/dist/web/static/assets/{index-CPHXL-wy.js → index-BRLxNhyy.js} +1 -1
  12. package/dist/web/static/assets/{index-VcSnwuHG.js → index-Bqg4_WEG.js} +1 -1
  13. package/dist/web/static/assets/{index-bfZj1PAc.js → index-C2YGUYGS.js} +1 -1
  14. package/dist/web/static/assets/{index-ph8Hxff-.js → index-D1dpOEzW.js} +1 -1
  15. package/dist/web/static/assets/{index-nRBC-NJN.js → index-D9qPPm7h.js} +1 -1
  16. package/dist/web/static/assets/{index-D81YKipC.js → index-DAOPV34I.js} +1 -1
  17. package/dist/web/static/assets/{index-CBHRNnCk.js → index-DLjK8dGE.js} +1 -1
  18. package/dist/web/static/assets/{index-KY36bfpA.js → index-DOXm2Aye.js} +1 -1
  19. package/dist/web/static/assets/{index-EowLf_Xf.js → index-DR-LSqAg.js} +1 -1
  20. package/dist/web/static/assets/{index-gv-TJwHT.js → index-DXtp_ZWh.js} +1 -1
  21. package/dist/web/static/assets/index-DeYCGmOR.css +32 -0
  22. package/dist/web/static/assets/{index-B2-N8jTH.js → index-DrWzb338.js} +1 -1
  23. package/dist/web/static/assets/{index-Caj09uf7.js → index-DtRwkh8J.js} +1 -1
  24. package/dist/web/static/assets/{index-C5-vT4kT.js → index-ccs5s80D.js} +1 -1
  25. package/dist/web/static/assets/{index-DtRt21Zi.js → index-mWEwJcqw.js} +1 -1
  26. package/dist/web/static/assets/{index-B35fidy6.js → index-unnPilnK.js} +1 -1
  27. package/dist/web/static/assets/{jszip.min-DyrlNEg4.js → jszip.min-DYFwy4PE.js} +1 -1
  28. package/dist/web/static/assets/{pptx-preview.es-DjND6y6O.js → pptx-preview.es-eu2nX9JC.js} +1 -1
  29. package/dist/web/static/index.html +2 -2
  30. package/package.json +1 -1
  31. package/dist/web/static/assets/index-Btn4AoIy.css +0 -32
package/README.md CHANGED
@@ -44,12 +44,9 @@ local-first, self-hosted, and has no telemetry.
44
44
  - Node.js 22 or newer. If you don't have it: `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash` then `nvm install 22`.
45
45
  - git, only for the checkout route below (macOS: `xcode-select --install`, Ubuntu: `sudo apt install git`)
46
46
  - Linux: a C library from 2019 or later (glibc 2.29+: Ubuntu 20.04+, Debian 11+, AL2023, Fedora). Older distros compile one native module and need a newer Python and GCC first; `npm start` prints the exact commands, and [Getting Started](GETTING_STARTED.md#older-linux-glibc-before-229) has them too.
47
- - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) for coding sessions
48
- - An Anthropic API key, AWS Bedrock credentials, or another supported model provider
49
- for Walnut
47
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code), signed in once (`npm install -g @anthropic-ai/claude-code`, then run `claude`)
50
48
 
51
- Claude Code and Walnut authenticate separately. Coding sessions use your existing
52
- Claude Code CLI login, while Walnut uses the model provider selected during setup.
49
+ That is the whole AI setup. Walnut runs on your Claude Code: the chat, coding sessions, and background work (summaries, titles, subagents) all use the `claude` you already have, however it signs in (Anthropic account, Bedrock, or Vertex). An Anthropic API key or AWS Bedrock credentials are optional, for people who would rather point Walnut's background work at a provider directly (Settings → AI Provider).
53
50
 
54
51
  ### Install
55
52
 
package/dist/cli-fast.js CHANGED
@@ -291,9 +291,9 @@ function causeCode(err) {
291
291
  }
292
292
  return void 0;
293
293
  }
294
- async function rawRequest(base, method, path6, body, timeoutMs, prov) {
294
+ async function rawRequest(base, method, path7, body, timeoutMs, prov) {
295
295
  const serverRoot = base.replace(/\/api\/v1$/, "");
296
- const url = path6.startsWith("/api/") ? `${serverRoot}${path6}` : `${base}${path6}`;
296
+ const url = path7.startsWith("/api/") ? `${serverRoot}${path7}` : `${base}${path7}`;
297
297
  let res;
298
298
  try {
299
299
  res = await fetch(url, {
@@ -312,7 +312,7 @@ async function rawRequest(base, method, path6, body, timeoutMs, prov) {
312
312
  return { ok: false, message: `Walnut server not running at ${base} \u2014 start with \`open-walnut web\`` };
313
313
  }
314
314
  if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
315
- return { ok: false, message: `Walnut request timed out after ${timeoutMs}ms: ${method} ${path6}` };
315
+ return { ok: false, message: `Walnut request timed out after ${timeoutMs}ms: ${method} ${path7}` };
316
316
  }
317
317
  return { ok: false, message: `Walnut request failed: ${err instanceof Error ? err.message : String(err)}` };
318
318
  }
@@ -335,7 +335,7 @@ async function rawRequest(base, method, path6, body, timeoutMs, prov) {
335
335
  }
336
336
  function materializeBinding(bind, args2) {
337
337
  const used = /* @__PURE__ */ new Set();
338
- const path6 = bind.path.replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, (_, name) => {
338
+ const path7 = bind.path.replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, (_, name) => {
339
339
  used.add(name);
340
340
  const v = args2[name];
341
341
  if (v === void 0 || v === null || v === "") {
@@ -363,7 +363,7 @@ function materializeBinding(bind, args2) {
363
363
  const qs = sp.toString();
364
364
  const needsBody = bind.method !== "GET" && bind.method !== "DELETE";
365
365
  const body = bodyEntries.length > 0 ? Object.fromEntries(bodyEntries) : needsBody ? {} : void 0;
366
- return { path: qs ? `${path6}?${qs}` : path6, body };
366
+ return { path: qs ? `${path7}?${qs}` : path7, body };
367
367
  }
368
368
  async function executeOp(name, rawArgs, options = {}) {
369
369
  const op = getOp(name);
@@ -384,8 +384,8 @@ async function runOp(op, args2, base, prov) {
384
384
  const timeoutMs = op.timeoutMs ?? REQUEST_TIMEOUT_MS;
385
385
  if (op.handler) {
386
386
  try {
387
- const call = async (method, path6, body) => {
388
- const r2 = await rawRequest(base, method, path6, body, timeoutMs, prov);
387
+ const call = async (method, path7, body) => {
388
+ const r2 = await rawRequest(base, method, path7, body, timeoutMs, prov);
389
389
  if (!r2.ok) throw new Error(r2.message);
390
390
  return r2.result;
391
391
  };
@@ -1104,11 +1104,34 @@ var init_model_catalog = __esm({
1104
1104
  }
1105
1105
  });
1106
1106
 
1107
+ // src/core/claude-cli-detect.ts
1108
+ import { execFileSync } from "child_process";
1109
+ import fs3 from "fs";
1110
+ import os2 from "os";
1111
+ import path3 from "path";
1112
+ var _CLAUDE_CREDENTIALS_HOME;
1113
+ var init_claude_cli_detect = __esm({
1114
+ "src/core/claude-cli-detect.ts"() {
1115
+ "use strict";
1116
+ init_constants();
1117
+ _CLAUDE_CREDENTIALS_HOME = os2.homedir();
1118
+ }
1119
+ });
1120
+
1121
+ // src/agent/providers/default-provider.ts
1122
+ var init_default_provider = __esm({
1123
+ "src/agent/providers/default-provider.ts"() {
1124
+ "use strict";
1125
+ init_claude_cli_detect();
1126
+ }
1127
+ });
1128
+
1107
1129
  // src/core/cheap-model.ts
1108
1130
  var init_cheap_model = __esm({
1109
1131
  "src/core/cheap-model.ts"() {
1110
1132
  "use strict";
1111
1133
  init_model_catalog();
1134
+ init_default_provider();
1112
1135
  }
1113
1136
  });
1114
1137
 
@@ -1257,8 +1280,8 @@ var init_output_mode = __esm({
1257
1280
  });
1258
1281
 
1259
1282
  // src/core/session-hooks/builtins.ts
1260
- import fs3 from "fs";
1261
- import path3 from "path";
1283
+ import fs4 from "fs";
1284
+ import path4 from "path";
1262
1285
  function caseInsensitiveFragment(pattern) {
1263
1286
  return pattern.replace(/[a-zA-Z]/g, (ch) => `[${ch.toUpperCase()}${ch.toLowerCase()}]`);
1264
1287
  }
@@ -1456,8 +1479,8 @@ var init_tasks = __esm({
1456
1479
  if (effective.limit === void 0 && args2.working_set !== true) {
1457
1480
  effective.limit = DEFAULT_TASK_LIST_LIMIT;
1458
1481
  }
1459
- const { path: path6 } = materializeBinding(TASK_LIST_BINDING, effective);
1460
- const body = await call("GET", path6);
1482
+ const { path: path7 } = materializeBinding(TASK_LIST_BINDING, effective);
1483
+ const body = await call("GET", path7);
1461
1484
  const tasks = body?.tasks;
1462
1485
  if (!Array.isArray(tasks)) return body;
1463
1486
  const total = typeof body?.total === "number" ? body.total : tasks.length;
@@ -1687,10 +1710,10 @@ function looksLikeNoteId(value) {
1687
1710
  }
1688
1711
  async function resolveNoteTarget(args2, call) {
1689
1712
  const id = typeof args2.id === "string" ? args2.id.trim() : "";
1690
- const path6 = typeof args2.path === "string" ? args2.path.trim() : "";
1691
- if (!id && !path6) throw new Error("pass path (vault-relative note path) or id (from note_search)");
1692
- const ref = id || path6;
1693
- if (!id && !looksLikeNoteId(path6)) return path6;
1713
+ const path7 = typeof args2.path === "string" ? args2.path.trim() : "";
1714
+ if (!id && !path7) throw new Error("pass path (vault-relative note path) or id (from note_search)");
1715
+ const ref = id || path7;
1716
+ if (!id && !looksLikeNoteId(path7)) return path7;
1694
1717
  const resolved = await call("GET", `/notes/resolve?ref=${encodeURIComponent(ref)}`);
1695
1718
  const resolvedPath = resolved.path;
1696
1719
  if (typeof resolvedPath !== "string" || !resolvedPath) throw new Error(`cannot resolve note reference: ${ref}`);
@@ -1829,16 +1852,16 @@ var init_core = __esm({
1829
1852
  expectedHash: z4.string().optional().describe("contentHash from note_read (update only)")
1830
1853
  },
1831
1854
  handler: async (args2, call) => {
1832
- const { path: path6, content, expectedHash } = args2;
1833
- const encoded = encodeVaultPath(String(path6));
1855
+ const { path: path7, content, expectedHash } = args2;
1856
+ const encoded = encodeVaultPath(String(path7));
1834
1857
  if (expectedHash === void 0) {
1835
1858
  try {
1836
- return await call("POST", "/notes", { path: path6, content });
1859
+ return await call("POST", "/notes", { path: path7, content });
1837
1860
  } catch (err) {
1838
1861
  const message = err instanceof Error ? err.message : String(err);
1839
1862
  if (/already exists/i.test(message)) {
1840
1863
  throw new Error(
1841
- `note exists; pass expectedHash from note_read to update ${String(path6)} (note_read \u2192 contentHash \u2192 note_write), or use note_edit for a partial change`
1864
+ `note exists; pass expectedHash from note_read to update ${String(path7)} (note_read \u2192 contentHash \u2192 note_write), or use note_edit for a partial change`
1842
1865
  );
1843
1866
  }
1844
1867
  throw err;
@@ -1926,11 +1949,11 @@ var init_core = __esm({
1926
1949
  },
1927
1950
  handler: async (args2, call) => {
1928
1951
  const method = String(args2.method);
1929
- const path6 = String(args2.path);
1930
- if (!path6.startsWith("/api/")) {
1952
+ const path7 = String(args2.path);
1953
+ if (!path7.startsWith("/api/")) {
1931
1954
  throw new Error("api passthrough only accepts paths starting with /api/");
1932
1955
  }
1933
- return call(method, path6, args2.body);
1956
+ return call(method, path7, args2.body);
1934
1957
  },
1935
1958
  tags: { readonly: false, remote: "allow" }
1936
1959
  });
@@ -2215,9 +2238,9 @@ function classifyArgsSource(raw, stdinIsTty) {
2215
2238
  const value = raw.trim();
2216
2239
  if (value === "-") return { kind: "stdin" };
2217
2240
  if (value.startsWith("@")) {
2218
- const path6 = value.slice(1);
2219
- if (!path6) return { kind: "usage-error", message: "@ needs a file path, e.g. @/tmp/letter.json" };
2220
- return { kind: "file", path: path6 };
2241
+ const path7 = value.slice(1);
2242
+ if (!path7) return { kind: "usage-error", message: "@ needs a file path, e.g. @/tmp/letter.json" };
2243
+ return { kind: "file", path: path7 };
2221
2244
  }
2222
2245
  if (!value) return { kind: "none" };
2223
2246
  return { kind: "inline", json: raw };
@@ -2260,10 +2283,10 @@ __export(wn_cli_exports, {
2260
2283
  resolveWalnutCliEndpoint: () => resolveWalnutCliEndpoint,
2261
2284
  runWalnutCli: () => runWalnutCli
2262
2285
  });
2263
- import fs4 from "fs";
2286
+ import fs5 from "fs";
2264
2287
  import net from "net";
2265
- import os2 from "os";
2266
- import path4 from "path";
2288
+ import os3 from "os";
2289
+ import path5 from "path";
2267
2290
  function parseWalnutCliArgs(argv2) {
2268
2291
  const [head, ...rest2] = argv2;
2269
2292
  if (head === void 0) return { kind: "usage-error", message: "missing command" };
@@ -2399,7 +2422,7 @@ The 0600 socket mode is the gateway credential, so walnut will not talk to it.`
2399
2422
  }
2400
2423
  function probeSocket(socketPath) {
2401
2424
  try {
2402
- const st = fs4.statSync(socketPath);
2425
+ const st = fs5.statSync(socketPath);
2403
2426
  return { isSocket: st.isSocket(), uid: st.uid, mode: st.mode & 511 };
2404
2427
  } catch {
2405
2428
  return null;
@@ -2505,12 +2528,12 @@ run \`walnut --help\` for usage
2505
2528
  else if (source.kind === "stdin") {
2506
2529
  rawJson = await readStdin();
2507
2530
  if (Buffer.byteLength(rawJson, "utf-8") > GATEWAY_INLINE_ARGS_MAX_BYTES) {
2508
- spilledArgsFile = path4.join(
2509
- os2.tmpdir(),
2531
+ spilledArgsFile = path5.join(
2532
+ os3.tmpdir(),
2510
2533
  `walnut-args-${process.pid}-${Date.now().toString(36)}.json`
2511
2534
  );
2512
2535
  try {
2513
- fs4.writeFileSync(spilledArgsFile, rawJson, { encoding: "utf-8", mode: 384 });
2536
+ fs5.writeFileSync(spilledArgsFile, rawJson, { encoding: "utf-8", mode: 384 });
2514
2537
  } catch (err) {
2515
2538
  process.stderr.write(
2516
2539
  `walnut: cannot stage a large payload at ${spilledArgsFile}: ${err instanceof Error ? err.message : String(err)}
@@ -2521,10 +2544,10 @@ run \`walnut --help\` for usage
2521
2544
  argsFile = spilledArgsFile;
2522
2545
  }
2523
2546
  } else if (source.kind === "file") {
2524
- const abs = path4.resolve(source.path);
2547
+ const abs = path5.resolve(source.path);
2525
2548
  let size = -1;
2526
2549
  try {
2527
- size = fs4.statSync(abs).size;
2550
+ size = fs5.statSync(abs).size;
2528
2551
  } catch (err) {
2529
2552
  process.stderr.write(
2530
2553
  `walnut: cannot read arguments from ${source.path}: ${err instanceof Error ? err.message : String(err)}
@@ -2536,7 +2559,7 @@ run \`walnut --help\` for usage
2536
2559
  argsFile = abs;
2537
2560
  } else {
2538
2561
  try {
2539
- rawJson = fs4.readFileSync(abs, "utf-8");
2562
+ rawJson = fs5.readFileSync(abs, "utf-8");
2540
2563
  } catch (err) {
2541
2564
  process.stderr.write(
2542
2565
  `walnut: cannot read arguments from ${source.path}: ${err instanceof Error ? err.message : String(err)}
@@ -2577,7 +2600,7 @@ run \`walnut --help\` for usage
2577
2600
  } finally {
2578
2601
  if (spilledArgsFile) {
2579
2602
  try {
2580
- fs4.unlinkSync(spilledArgsFile);
2603
+ fs5.unlinkSync(spilledArgsFile);
2581
2604
  } catch {
2582
2605
  }
2583
2606
  }
@@ -2997,12 +3020,12 @@ function apiBaseUrl() {
2997
3020
  const raw = process.env.OPEN_WALNUT_API_URL?.trim();
2998
3021
  return (raw || DEFAULT_BASE_URL).replace(/\/+$/, "");
2999
3022
  }
3000
- async function request(method, path6, body, opts) {
3023
+ async function request(method, path7, body, opts) {
3001
3024
  const base = apiBaseUrl();
3002
3025
  const timeoutMs = opts?.timeoutMs ?? REQUEST_TIMEOUT_MS2;
3003
3026
  let res;
3004
3027
  try {
3005
- res = await fetch(base + path6, {
3028
+ res = await fetch(base + path7, {
3006
3029
  method,
3007
3030
  ...body !== void 0 ? { headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) } : {},
3008
3031
  signal: AbortSignal.timeout(timeoutMs)
@@ -3036,11 +3059,11 @@ async function request(method, path6, body, opts) {
3036
3059
  }
3037
3060
  return parsed;
3038
3061
  }
3039
- function apiGet(path6, opts) {
3040
- return request("GET", path6, void 0, opts);
3062
+ function apiGet(path7, opts) {
3063
+ return request("GET", path7, void 0, opts);
3041
3064
  }
3042
- function apiPost(path6, body) {
3043
- return request("POST", path6, body ?? {});
3065
+ function apiPost(path7, body) {
3066
+ return request("POST", path7, body ?? {});
3044
3067
  }
3045
3068
  function reportApiError(err, globals2) {
3046
3069
  const message = err instanceof ApiUnreachableError ? `Open Walnut server is not running at ${err.baseUrl} \u2014 start it with: open-walnut web` : err instanceof Error ? err.message : String(err);
@@ -3519,8 +3542,8 @@ var init_start = __esm({
3519
3542
  });
3520
3543
 
3521
3544
  // src/cli-fast.ts
3522
- import fs5 from "fs";
3523
- import path5 from "path";
3545
+ import fs6 from "fs";
3546
+ import path6 from "path";
3524
3547
  import { fileURLToPath as fileURLToPath2 } from "url";
3525
3548
  var LITE_COMMANDS = /* @__PURE__ */ new Set([
3526
3549
  "tools",
@@ -3537,8 +3560,8 @@ var LITE_COMMANDS = /* @__PURE__ */ new Set([
3537
3560
  var argv = process.argv.slice(2);
3538
3561
  if (argv.includes("--version") || argv.includes("-V")) {
3539
3562
  try {
3540
- const pkgPath = path5.join(path5.dirname(fileURLToPath2(import.meta.url)), "..", "package.json");
3541
- console.log(JSON.parse(fs5.readFileSync(pkgPath, "utf-8")).version ?? "0.0.0");
3563
+ const pkgPath = path6.join(path6.dirname(fileURLToPath2(import.meta.url)), "..", "package.json");
3564
+ console.log(JSON.parse(fs6.readFileSync(pkgPath, "utf-8")).version ?? "0.0.0");
3542
3565
  } catch {
3543
3566
  console.log("0.0.0");
3544
3567
  }