@bentoai/cli 1.1.1 → 1.1.3

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/README.md CHANGED
@@ -85,7 +85,12 @@ live inventory and revoke unwanted entries before explicitly exporting again.
85
85
  Rotation uses a second export, host deployment and verification, then revocation
86
86
  of the prior credential. `bento app credentials --help` owns the command surface.
87
87
 
88
- The local `.duet` directory remains the persisted state boundary for existing logins, memory, training, sync identities, and VM compatibility. Bento reads those bytes in place so an upgrade does not migrate or rewrite established state.
88
+ Laptop-local state has one selected root for login, memory, training, sync
89
+ identity, sessions, caches and logs. A fresh install creates `~/.bento`; an
90
+ existing install with only `~/.duet` continues reading and writing there. If
91
+ both directories exist, `~/.bento` wins silently. Bento never migrates,
92
+ deletes, symlinks or merges the old directory. VM and project-local `.duet`
93
+ paths remain their own contracts.
89
94
 
90
95
  The saved human login and default API/workspace live in config.json. Other
91
96
  provider keys remain in provider env files, and connected subscriptions keep
package/dist/cli-entry.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "@bentoai/cli",
55
- version: "1.1.1"
55
+ version: "1.1.3"
56
56
  };
57
57
  });
58
58
 
@@ -26359,12 +26359,34 @@ var require_main = __commonJS((exports, module) => {
26359
26359
  module.exports = DotenvModule;
26360
26360
  });
26361
26361
 
26362
+ // packages/agent/src/memory/paths.ts
26363
+ import { lstatSync } from "fs";
26364
+ import { homedir } from "os";
26365
+ import { join } from "path";
26366
+ function selectBentoStateRoot(home = homedir()) {
26367
+ const cached2 = selectedRoots.get(home);
26368
+ if (cached2)
26369
+ return cached2;
26370
+ const bento = join(home, ".bento");
26371
+ const duet = join(home, ".duet");
26372
+ const root = lstatSync(bento, { throwIfNoEntry: false }) || !lstatSync(duet, { throwIfNoEntry: false }) ? bento : duet;
26373
+ selectedRoots.set(home, root);
26374
+ return root;
26375
+ }
26376
+ var selectedRoots, DEFAULT_BENTO_HOME, DEFAULT_SESSION_STORAGE_DIR, DEFAULT_MEMORY_DB_PATH;
26377
+ var init_paths = __esm(() => {
26378
+ selectedRoots = new Map;
26379
+ DEFAULT_BENTO_HOME = selectBentoStateRoot();
26380
+ DEFAULT_SESSION_STORAGE_DIR = join(DEFAULT_BENTO_HOME, "sessions");
26381
+ DEFAULT_MEMORY_DB_PATH = join(DEFAULT_BENTO_HOME, "memory.db");
26382
+ });
26383
+
26362
26384
  // packages/bento/src/config.ts
26363
26385
  import { chmod, mkdir, readFile, writeFile } from "fs/promises";
26364
- import { homedir } from "os";
26365
- import { dirname, join } from "path";
26366
- function configPathForHome(home = homedir()) {
26367
- return join(home, CONFIG_HOME_DIR_NAME, CONFIG_FILE_NAME);
26386
+ import { homedir as homedir2 } from "os";
26387
+ import { dirname, join as join2 } from "path";
26388
+ function configPathForHome(home = homedir2()) {
26389
+ return join2(selectBentoStateRoot(home), CONFIG_FILE_NAME);
26368
26390
  }
26369
26391
  async function loadConfig(path = configPathForHome()) {
26370
26392
  let config2 = {};
@@ -26381,7 +26403,7 @@ async function loadConfig(path = configPathForHome()) {
26381
26403
  if (!isNodeError(error51) || error51.code !== "ENOENT")
26382
26404
  throw error51;
26383
26405
  }
26384
- const legacyPath = join(dirname(path), ".env");
26406
+ const legacyPath = join2(dirname(path), ".env");
26385
26407
  try {
26386
26408
  const text = await readFile(legacyPath, "utf8");
26387
26409
  const legacyKey = import_dotenv.default.parse(text).DUET_API_KEY;
@@ -26399,7 +26421,7 @@ async function loadConfig(path = configPathForHome()) {
26399
26421
  return config2;
26400
26422
  }
26401
26423
  async function saveConfig(config2, path = configPathForHome()) {
26402
- await mkdir(join(path, ".."), { recursive: true, mode: 448 });
26424
+ await mkdir(join2(path, ".."), { recursive: true, mode: 448 });
26403
26425
  await writeFile(path, `${JSON.stringify(config2, null, 2)}
26404
26426
  `, { mode: 384 });
26405
26427
  await chmod(path, 384);
@@ -26411,8 +26433,9 @@ function effectiveApiUrl(config2, env, override) {
26411
26433
  function isNodeError(error51) {
26412
26434
  return error51 instanceof Error && "code" in error51;
26413
26435
  }
26414
- var import_dotenv, CONFIG_HOME_DIR_NAME = ".duet", CONFIG_FILE_NAME = "config.json";
26436
+ var import_dotenv, CONFIG_FILE_NAME = "config.json";
26415
26437
  var init_config = __esm(() => {
26438
+ init_paths();
26416
26439
  init_src();
26417
26440
  import_dotenv = __toESM(require_main(), 1);
26418
26441
  });
@@ -26530,7 +26553,7 @@ var init_http2 = __esm(() => {
26530
26553
  });
26531
26554
 
26532
26555
  // packages/bento/src/cli-support.ts
26533
- import { homedir as homedir2 } from "os";
26556
+ import { homedir as homedir3 } from "os";
26534
26557
 
26535
26558
  class CommandRegistry {
26536
26559
  commands = new Map;
@@ -26551,7 +26574,7 @@ class CommandRegistry {
26551
26574
  async function createCommandContext(argv, runtime) {
26552
26575
  const io = runtime.io ?? { stdout: process.stdout, stderr: process.stderr };
26553
26576
  const env = runtime.env ?? process.env;
26554
- const home = runtime.home ?? env.HOME ?? homedir2();
26577
+ const home = runtime.home ?? env.HOME ?? homedir3();
26555
26578
  const cwd2 = runtime.cwd ?? process.cwd();
26556
26579
  const fetchImpl = runtime.fetch ?? fetch;
26557
26580
  const sleep = runtime.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
@@ -26774,8 +26797,8 @@ var init_billing3 = __esm(() => {
26774
26797
 
26775
26798
  // packages/bento/src/cli/shared.ts
26776
26799
  import { mkdir as mkdir2, readFile as readFile2, stat, writeFile as writeFile2 } from "fs/promises";
26777
- import { homedir as homedir3 } from "os";
26778
- import { dirname as dirname2, isAbsolute, join as join2, resolve } from "path";
26800
+ import { homedir as homedir4 } from "os";
26801
+ import { dirname as dirname2, isAbsolute, join as join3, resolve } from "path";
26779
26802
  function fail(message, exitCode = 1) {
26780
26803
  console.error(`Fatal: ${message}`);
26781
26804
  process.exit(exitCode);
@@ -26791,17 +26814,17 @@ function resolveUserPath(path, baseDir = process.cwd()) {
26791
26814
  }
26792
26815
  function expandHomeDir(path) {
26793
26816
  if (path === "~")
26794
- return homedir3();
26817
+ return homedir4();
26795
26818
  if (path.startsWith("~/"))
26796
- return join2(homedir3(), path.slice(2));
26819
+ return join3(homedir4(), path.slice(2));
26797
26820
  return path;
26798
26821
  }
26799
26822
  function defaultBentoEnvFilePath() {
26800
- return resolveUserPath(DEFAULT_BENTO_ENV_FILE);
26823
+ return join3(selectBentoStateRoot(homedir4()), ".env");
26801
26824
  }
26802
26825
  function cliEnvFilePaths(workDir, envFilePath) {
26803
26826
  return [
26804
- join2(workDir, ".env"),
26827
+ join3(workDir, ".env"),
26805
26828
  envFilePath ? resolveUserPath(envFilePath, workDir) : defaultBentoEnvFilePath()
26806
26829
  ];
26807
26830
  }
@@ -26883,8 +26906,9 @@ function shellQuote(value2) {
26883
26906
  function normalizePackageVersion(version2) {
26884
26907
  return version2.replace(/^v/, "");
26885
26908
  }
26886
- var import_dotenv2, DEFAULT_BENTO_ENV_FILE = "~/.duet/.env", SUPPORTED_API_KEYS;
26909
+ var import_dotenv2, SUPPORTED_API_KEYS;
26887
26910
  var init_shared = __esm(() => {
26911
+ init_paths();
26888
26912
  init_src();
26889
26913
  init_config();
26890
26914
  import_dotenv2 = __toESM(require_main(), 1);
@@ -26954,12 +26978,13 @@ COMMANDS
26954
26978
  memory Browse memories in a TUI, or query them with --json/filters (alias: memories)
26955
26979
  model Call a gateway model directly (text/image/video) via the AI SDK
26956
26980
  route Probe the live virtual-model classifier (bento route "<prompt>")
26957
- config export Write the built-in routing table to .duet/models.json for tweaking
26981
+ config export Write the built-in routing table to project .duet/models.json for tweaking
26958
26982
  send-feedback Send free-form markdown feedback to the Bento team
26959
26983
  upgrade Upgrade the global ${packageName} installation
26960
26984
 
26961
26985
  CONFIGURATION
26962
- ~/.duet/config.json owns the saved apiKey, apiUrl, defaultWorkspace and machineId.
26986
+ ${DEFAULT_BENTO_HOME}/config.json owns the saved apiKey, apiUrl, defaultWorkspace and machineId.
26987
+ New installs use ~/.bento; an existing ~/.duet remains active when no ~/.bento exists; ~/.bento wins silently when both exist.
26963
26988
  bento workspace use <slug> selects the default remote/model billing workspace.
26964
26989
  memory and train stay local unless --workspace explicitly selects REST mode.
26965
26990
  Bare prompts run locally; bento session operates remote conversations.
@@ -26977,7 +27002,7 @@ OPTIONS
26977
27002
  Accepts: bento, vercel, openrouter.
26978
27003
  Mutually exclusive with --model / --memory-model.
26979
27004
  -i, --incognito Keep memory in-process; do not read or write durable memory
26980
- --db <path> Memory database path (default: ~/.duet/memory.db); ignored under --incognito
27005
+ --db <path> Memory database path (default: ${DEFAULT_MEMORY_DB_PATH}); ignored under --incognito
26981
27006
  -w, --workdir <path> Working directory (default: cwd)
26982
27007
  -r, --resume <id> Resume a saved session
26983
27008
  --resume-history-messages <n>
@@ -26986,7 +27011,7 @@ OPTIONS
26986
27011
  --system-prompt-file <path>
26987
27012
  Load a file into the system prompt; repeatable
26988
27013
  --no-system-prompt-files Disable default AGENTS.md system prompt loading
26989
- --env-file <path> Shared env file to load after <workdir>/.env (default: ${DEFAULT_BENTO_ENV_FILE})
27014
+ --env-file <path> Shared env file to load after <workdir>/.env (default: ${defaultBentoEnvFilePath()})
26990
27015
  --no-auto-upgrade Skip the auto-upgrade probe for this run (also: DUET_NO_AUTO_UPGRADE=1)
26991
27016
  --rpc Bare turn-runner control surface. Reads newline-delimited RpcRunnerCommand
26992
27017
  JSON from stdin and writes RpcEvent JSON to stdout. Prompt, answer, and wake
@@ -27073,7 +27098,7 @@ By default, env only prints this help. Choose --import to copy
27073
27098
  provider keys from cwd .env or a provided env file, or --keys to paste keys interactively.
27074
27099
 
27075
27100
  OPTIONS
27076
- --env-file <path> Env file to write (default: ${DEFAULT_BENTO_ENV_FILE})
27101
+ --env-file <path> Env file to write (default: ${defaultBentoEnvFilePath()})
27077
27102
  -i, --import [path] Import cwd .env, or import the provided env file
27078
27103
  --keys Prompt for supported provider API keys
27079
27104
  -h, --help Show this help
@@ -27153,7 +27178,7 @@ QUERY OPTIONS
27153
27178
  YYYY-MM-DD (end of day UTC) or YYYY-MM-DDTHH:MM:SS (UTC)
27154
27179
 
27155
27180
  OPTIONS
27156
- --db <path> Memory database path (default: ~/.duet/memory.db)
27181
+ --db <path> Memory database path (default: ${DEFAULT_MEMORY_DB_PATH})
27157
27182
  --wait <seconds> Seconds to wait for the cross-process open-lock when a peer
27158
27183
  bento process is holding it (default: 30; 0 fails immediately)
27159
27184
  -h, --help Show this help
@@ -27206,7 +27231,7 @@ USAGE
27206
27231
  bento memory recall [options] [--query <q> | <query...>]
27207
27232
 
27208
27233
  DESCRIPTION
27209
- Searches ~/.duet/memory.db with the exact pipeline the runner's
27234
+ Searches ${DEFAULT_MEMORY_DB_PATH} with the exact pipeline the runner's
27210
27235
  recall_memory tool uses: vector (embedding) search and keyword search run
27211
27236
  in parallel and merge via Reciprocal Rank Fusion, so fuzzy paraphrases and
27212
27237
  exact tokens (proper nouns, IDs, code symbols) both match. Results print
@@ -27233,7 +27258,7 @@ OPTIONS
27233
27258
  --model <name> Model used for --expand paraphrases (default: cheap CLI memory model)
27234
27259
  --json Emit a bare JSON array of canonical memory objects
27235
27260
  (best-first) with packScore + relevanceScore
27236
- --db <path> Memory database path (default: ~/.duet/memory.db)
27261
+ --db <path> Memory database path (default: ${DEFAULT_MEMORY_DB_PATH})
27237
27262
  This command is DB-only; --store is rejected because
27238
27263
  store memories are already loaded into agent context
27239
27264
  --wait <seconds> Seconds to wait for the cross-process open-lock
@@ -27268,7 +27293,7 @@ DESCRIPTION
27268
27293
  --dry-run to preview without writing.
27269
27294
 
27270
27295
  OPTIONS
27271
- --db <path> Memory database path (default: ~/.duet/memory.db)
27296
+ --db <path> Memory database path (default: ${DEFAULT_MEMORY_DB_PATH})
27272
27297
  --dry-run Print the reflected log without writing it back
27273
27298
  --min-age-days <n> Skip observations newer than this many days
27274
27299
  (default: 3)
@@ -27357,7 +27382,7 @@ DESCRIPTION
27357
27382
  .duet-train.json \u2014 structured handoff with headline + observation.
27358
27383
 
27359
27384
  'train' then persists the synthesis into exactly one backend and archives
27360
- the corpus under ~/.duet/train/<memory-id>/. With no backend flag it writes
27385
+ the corpus under ${DEFAULT_BENTO_HOME}/train/<memory-id>/. With no backend flag it writes
27361
27386
  a markdown file under the nearest ancestor .agents/memories directory,
27362
27387
  creating that directory when needed. --db retains the legacy manual-row
27363
27388
  behavior. Passing more than one backend to create is a usage error.
@@ -27365,7 +27390,7 @@ DESCRIPTION
27365
27390
  Reads accept repeatable --store and --db flags. Any explicit backend flags
27366
27391
  replace discovery; stores are consulted in flag order before DBs. Without
27367
27392
  flags, reads union inherited stores from cwd toward the filesystem root,
27368
- then ~/.duet/memory.db. Duplicate slugs resolve to the first source, while
27393
+ then ${DEFAULT_MEMORY_DB_PATH}. Duplicate slugs resolve to the first source, while
27369
27394
  surviving entries are listed newest-first. show/update/delete use that same
27370
27395
  first-source precedence.
27371
27396
 
@@ -27454,6 +27479,7 @@ ${GATEWAY_CUSTOMER_BINDINGS.map((binding) => ` bento ${binding.cli} ... ${bin
27454
27479
  }
27455
27480
  var DEFAULT_RESUME_HISTORY_MESSAGES = 5;
27456
27481
  var init_help = __esm(() => {
27482
+ init_paths();
27457
27483
  init_src();
27458
27484
  init_shared();
27459
27485
  });
@@ -120172,15 +120198,14 @@ var init_file_lock = __esm(() => {
120172
120198
  // packages/agent/src/connected-providers/store.ts
120173
120199
  import { randomUUID as randomUUID2 } from "crypto";
120174
120200
  import { chmod as chmod2, mkdir as mkdir4, readFile as readFile5, rename, unlink, writeFile as writeFile5 } from "fs/promises";
120175
- import { homedir as homedir4 } from "os";
120176
- import { join as join4 } from "path";
120201
+ import { join as join5 } from "path";
120177
120202
  function isConnectedProviderId(provider) {
120178
120203
  return CONNECTED_PROVIDER_ORDER.some((candidate) => candidate === provider);
120179
120204
  }
120180
120205
  function createConnectedProviderStore(opts = {}) {
120181
- const bentoDir = join4(opts.homeDir ?? homedir4(), ".duet");
120182
- const storePath = join4(bentoDir, CONNECTED_PROVIDERS_FILE);
120183
- const lockPath = join4(bentoDir, `${CONNECTED_PROVIDERS_FILE}.lock`);
120206
+ const bentoDir = opts.homeDir ? selectBentoStateRoot(opts.homeDir) : DEFAULT_BENTO_HOME;
120207
+ const storePath = join5(bentoDir, CONNECTED_PROVIDERS_FILE);
120208
+ const lockPath = join5(bentoDir, `${CONNECTED_PROVIDERS_FILE}.lock`);
120184
120209
  const now2 = opts.now ?? (() => Date.now());
120185
120210
  const readDocument = async () => {
120186
120211
  let raw;
@@ -120300,6 +120325,7 @@ function hasCode2(error54, code2) {
120300
120325
  var CONNECTED_PROVIDER_ORDER, CONNECTED_PROVIDERS_FILE = "connected-providers.json", STORE_VERSION = 1, LOCK_RETRY_MS = 20;
120301
120326
  var init_store = __esm(() => {
120302
120327
  init_file_lock();
120328
+ init_paths();
120303
120329
  CONNECTED_PROVIDER_ORDER = [
120304
120330
  "openai-codex",
120305
120331
  "github-copilot"
@@ -124373,7 +124399,7 @@ var init_walk_ancestors = () => {};
124373
124399
  // packages/agent/src/model-routing/loader.ts
124374
124400
  import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
124375
124401
  import { homedir as homedir6 } from "os";
124376
- import { join as join5 } from "path";
124402
+ import { join as join6 } from "path";
124377
124403
  function isMissingFile(error54) {
124378
124404
  return error54 instanceof Error && "code" in error54 && error54.code === "ENOENT";
124379
124405
  }
@@ -124394,9 +124420,10 @@ ${issues.map((issue2) => `- ${issue2.path}: ${issue2.message}`).join(`
124394
124420
  }
124395
124421
  async function loadRoutingTable(options) {
124396
124422
  const home = options.homeDir ?? homedir6();
124423
+ const stateRoot = selectBentoStateRoot(home);
124397
124424
  const candidates2 = [
124398
- ...walkAncestors(options.cwd, home).map((dir) => join5(dir, ROUTING_TABLE_RELATIVE_PATH)),
124399
- join5(home, ROUTING_TABLE_RELATIVE_PATH)
124425
+ ...walkAncestors(options.cwd, home).map((dir) => join6(dir, ROUTING_TABLE_RELATIVE_PATH)),
124426
+ join6(stateRoot, "models.json")
124400
124427
  ];
124401
124428
  for (const path6 of candidates2) {
124402
124429
  let contents;
@@ -124435,8 +124462,8 @@ async function loadRoutingTable(options) {
124435
124462
  return { table: BUILT_IN_ROUTING_TABLE, source: "built-in" };
124436
124463
  }
124437
124464
  async function exportRoutingTable(options) {
124438
- const directory2 = join5(options.cwd, ".duet");
124439
- const path6 = join5(options.cwd, ROUTING_TABLE_RELATIVE_PATH);
124465
+ const directory2 = join6(options.cwd, ".duet");
124466
+ const path6 = join6(options.cwd, ROUTING_TABLE_RELATIVE_PATH);
124440
124467
  await mkdir5(directory2, { recursive: true });
124441
124468
  const contents = `${JSON.stringify(BUILT_IN_ROUTING_TABLE, null, 2)}
124442
124469
  `;
@@ -124456,8 +124483,9 @@ var ROUTING_TABLE_RELATIVE_PATH;
124456
124483
  var init_loader = __esm(() => {
124457
124484
  init_value2();
124458
124485
  init_walk_ancestors();
124486
+ init_paths();
124459
124487
  init_table();
124460
- ROUTING_TABLE_RELATIVE_PATH = join5(".duet", "models.json");
124488
+ ROUTING_TABLE_RELATIVE_PATH = join6(".duet", "models.json");
124461
124489
  });
124462
124490
 
124463
124491
  // packages/bento/src/cli/model-selection.ts
@@ -125217,7 +125245,7 @@ var init_workspace = __esm(() => {
125217
125245
 
125218
125246
  // packages/importers/src/index.ts
125219
125247
  import { readdir as readdir2, readFile as readFile10, stat as stat5 } from "fs/promises";
125220
- import { join as join6 } from "path";
125248
+ import { join as join7 } from "path";
125221
125249
  function isImportSource(value2) {
125222
125250
  return IMPORT_SOURCES.includes(value2);
125223
125251
  }
@@ -125267,10 +125295,10 @@ async function parseOpenClawSessions(home) {
125267
125295
  }
125268
125296
  function assumedPath(source, home) {
125269
125297
  if (source === "claude-code")
125270
- return join6(home, ".claude", "projects");
125298
+ return join7(home, ".claude", "projects");
125271
125299
  if (source === "codex")
125272
- return join6(home, ".codex", "sessions");
125273
- return join6(home, ".openclaw", "sessions");
125300
+ return join7(home, ".codex", "sessions");
125301
+ return join7(home, ".openclaw", "sessions");
125274
125302
  }
125275
125303
  async function parseJsonlTree(source, root, extract3) {
125276
125304
  const snippets = [];
@@ -125308,7 +125336,7 @@ async function listFiles2(root, warnings, source) {
125308
125336
  return [];
125309
125337
  });
125310
125338
  for (const entry of entries) {
125311
- const path6 = join6(dir, entry.name);
125339
+ const path6 = join7(dir, entry.name);
125312
125340
  if (entry.isDirectory()) {
125313
125341
  await walk3(path6);
125314
125342
  } else if (entry.isFile()) {
@@ -125693,24 +125721,24 @@ var init_binary = __esm(() => {
125693
125721
  });
125694
125722
 
125695
125723
  // packages/bento/src/sync/daemon-status.ts
125724
+ import { createHash as createHash2 } from "crypto";
125696
125725
  import { existsSync } from "fs";
125697
125726
  import { mkdir as mkdir6, readFile as readFile12, rename as rename2, writeFile as writeFile8 } from "fs/promises";
125698
- import { dirname as dirname6, join as join7 } from "path";
125699
- import { createHash as createHash2 } from "crypto";
125727
+ import { dirname as dirname6, join as join8 } from "path";
125700
125728
  function syncRoot(home) {
125701
- return join7(home, ".duet", "sync");
125729
+ return join8(selectBentoStateRoot(home), "sync");
125702
125730
  }
125703
125731
  function workspaceSyncKey(apiOrigin, workspaceId) {
125704
125732
  return createHash2("sha256").update(JSON.stringify([new URL(apiOrigin).href, workspaceId])).digest("hex");
125705
125733
  }
125706
125734
  function defaultMirrorDir(home, syncKey) {
125707
- const existing = join7(home, "duet", syncKey);
125735
+ const existing = join8(home, "duet", syncKey);
125708
125736
  if (existsSync(existing))
125709
125737
  return existing;
125710
- return join7(home, "bento", syncKey);
125738
+ return join8(home, "bento", syncKey);
125711
125739
  }
125712
125740
  function statusFilePath(home) {
125713
- return join7(syncRoot(home), "status.json");
125741
+ return join8(syncRoot(home), "status.json");
125714
125742
  }
125715
125743
  async function readStatusSnapshot(home) {
125716
125744
  let text2;
@@ -125768,6 +125796,7 @@ function formatStateLabel(row) {
125768
125796
  }
125769
125797
  var STATE_LABELS;
125770
125798
  var init_daemon_status = __esm(() => {
125799
+ init_paths();
125771
125800
  STATE_LABELS = {
125772
125801
  starting: "starting",
125773
125802
  "up-to-date": "up to date",
@@ -125780,9 +125809,9 @@ var init_daemon_status = __esm(() => {
125780
125809
  // packages/bento/src/sync/machine.ts
125781
125810
  import { copyFile, mkdir as mkdir7, mkdtemp, readFile as readFile13, rename as rename3, rm } from "fs/promises";
125782
125811
  import { hostname as hostname3 } from "os";
125783
- import { dirname as dirname7, join as join8 } from "path";
125812
+ import { dirname as dirname7, join as join9 } from "path";
125784
125813
  function macIdentityHome(home) {
125785
- return join8(syncRoot(home), "identity");
125814
+ return join9(syncRoot(home), "identity");
125786
125815
  }
125787
125816
  async function prepareMacIdentity(binaryPath, identityHome) {
125788
125817
  try {
@@ -125793,7 +125822,7 @@ async function prepareMacIdentity(binaryPath, identityHome) {
125793
125822
  throw error54;
125794
125823
  }
125795
125824
  await mkdir7(dirname7(identityHome), { recursive: true, mode: 448 });
125796
- const scratch = await mkdtemp(join8(dirname7(identityHome), "identity-"));
125825
+ const scratch = await mkdtemp(join9(dirname7(identityHome), "identity-"));
125797
125826
  try {
125798
125827
  const proc = Bun.spawn([binaryPath, "generate", `--home=${scratch}`], {
125799
125828
  stdout: "ignore",
@@ -125814,7 +125843,7 @@ async function prepareMacIdentity(binaryPath, identityHome) {
125814
125843
  }
125815
125844
  }
125816
125845
  async function copyMacIdentity(identityHome, workspaceHome) {
125817
- await Promise.all(["cert.pem", "key.pem"].map((name26) => copyFile(join8(identityHome, name26), join8(workspaceHome, name26))));
125846
+ await Promise.all(["cert.pem", "key.pem"].map((name26) => copyFile(join9(identityHome, name26), join9(workspaceHome, name26))));
125818
125847
  }
125819
125848
  async function registerSyncMachine(ctx, binaryPath) {
125820
125849
  const identityHome = macIdentityHome(ctx.home);
@@ -125850,7 +125879,7 @@ async function isSyncMachineActive(api2, machineId) {
125850
125879
  return false;
125851
125880
  }
125852
125881
  async function readIdentity(home) {
125853
- await Promise.all(["cert.pem", "key.pem"].map((name26) => readFile13(join8(home, name26))));
125882
+ await Promise.all(["cert.pem", "key.pem"].map((name26) => readFile13(join9(home, name26))));
125854
125883
  }
125855
125884
  function isFileError(error54, code2) {
125856
125885
  return error54 instanceof Error && "code" in error54 && error54.code === code2;
@@ -126441,7 +126470,7 @@ var init_orchestrator = __esm(() => {
126441
126470
 
126442
126471
  // packages/bento/src/sync/status.ts
126443
126472
  import { readdir as readdir3 } from "fs/promises";
126444
- import { join as join9, relative } from "path";
126473
+ import { join as join10, relative } from "path";
126445
126474
  function isConflictPath(path6) {
126446
126475
  const base = path6.split("/").pop() ?? path6;
126447
126476
  return base.includes(".sync-conflict-");
@@ -126485,7 +126514,7 @@ async function walk3(root, current, found) {
126485
126514
  return;
126486
126515
  }
126487
126516
  for (const entry of entries) {
126488
- const full = join9(current, entry.name);
126517
+ const full = join10(current, entry.name);
126489
126518
  if (entry.isDirectory()) {
126490
126519
  if (SKIP_DIRS.has(entry.name))
126491
126520
  continue;
@@ -126503,7 +126532,7 @@ var init_status = __esm(() => {
126503
126532
  // packages/bento/src/sync/supervisor.ts
126504
126533
  import { randomBytes } from "crypto";
126505
126534
  import { mkdir as mkdir8, readFile as readFile14, writeFile as writeFile9 } from "fs/promises";
126506
- import { join as join10 } from "path";
126535
+ import { join as join11 } from "path";
126507
126536
  function createSupervisor(options) {
126508
126537
  const fetchImpl = options.fetch ?? ((input, init) => fetch(input, init));
126509
126538
  const now2 = options.now ?? Date.now;
@@ -126512,7 +126541,7 @@ function createSupervisor(options) {
126512
126541
  const generate2 = options.generate ?? defaultGenerate;
126513
126542
  const restartBackoffMs = options.restartBackoffMs ?? DEFAULT_RESTART_BACKOFF_MS;
126514
126543
  const readyTimeoutMs = options.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
126515
- const configPath = join10(options.home, "config.xml");
126544
+ const configPath = join11(options.home, "config.xml");
126516
126545
  let apiKey = null;
126517
126546
  let desired = false;
126518
126547
  let restartCount = 0;
@@ -126693,9 +126722,9 @@ var init_supervisor = __esm(() => {
126693
126722
  import { readFile as readFile15, readdir as readdir4 } from "fs/promises";
126694
126723
  import { mkdir as mkdir9 } from "fs/promises";
126695
126724
  import { createServer as createServer3 } from "net";
126696
- import { join as join11 } from "path";
126725
+ import { join as join12 } from "path";
126697
126726
  function workspaceSyncHome(home, syncKey) {
126698
- return join11(syncRoot(home), "workspaces", syncKey);
126727
+ return join12(syncRoot(home), "workspaces", syncKey);
126699
126728
  }
126700
126729
  function createRealMirrorStarter(options) {
126701
126730
  const allocatePort = options.allocatePort ?? freeLoopbackPort;
@@ -126782,7 +126811,7 @@ async function reposMissingRemoteUnder(dir) {
126782
126811
  const candidates2 = [".", ...await immediateSubdirs(dir)];
126783
126812
  const missing = [];
126784
126813
  for (const rel of candidates2) {
126785
- const gitConfig = join11(dir, rel, ".git", "config");
126814
+ const gitConfig = join12(dir, rel, ".git", "config");
126786
126815
  let text2;
126787
126816
  try {
126788
126817
  text2 = await readFile15(gitConfig, "utf8");
@@ -127071,12 +127100,12 @@ var init_daemon = __esm(() => {
127071
127100
 
127072
127101
  // packages/bento/src/sync/launchd.ts
127073
127102
  import { mkdir as mkdir10, rm as rm2, writeFile as writeFile10 } from "fs/promises";
127074
- import { join as join12 } from "path";
127103
+ import { join as join13 } from "path";
127075
127104
  function launchAgentsDir(home) {
127076
- return join12(home, "Library", "LaunchAgents");
127105
+ return join13(home, "Library", "LaunchAgents");
127077
127106
  }
127078
127107
  function launchAgentPlistPath(home) {
127079
- return join12(launchAgentsDir(home), `${LAUNCH_AGENT_LABEL}.plist`);
127108
+ return join13(launchAgentsDir(home), `${LAUNCH_AGENT_LABEL}.plist`);
127080
127109
  }
127081
127110
  function renderLaunchAgentPlist(input) {
127082
127111
  const args = input.programArguments.map((arg) => ` <string>${xmlEscape(arg)}</string>`).join(`
@@ -127115,7 +127144,7 @@ async function installLaunchAgent(env3) {
127115
127144
  const run = env3.runLaunchctl ?? defaultRunLaunchctl;
127116
127145
  const log3 = env3.log ?? (() => {});
127117
127146
  const plistPath = launchAgentPlistPath(env3.home);
127118
- const logPath = join12(syncRoot(env3.home), "daemon.log");
127147
+ const logPath = join13(syncRoot(env3.home), "daemon.log");
127119
127148
  await mkdir10(launchAgentsDir(env3.home), { recursive: true });
127120
127149
  await mkdir10(syncRoot(env3.home), { recursive: true, mode: 448 });
127121
127150
  const plist = renderLaunchAgentPlist({
@@ -127601,7 +127630,7 @@ import {
127601
127630
  writeSync as writeSync2
127602
127631
  } from "fs";
127603
127632
  import { readFile as readFile16 } from "fs/promises";
127604
- import { basename as basename3, dirname as dirname8, resolve as resolvePath2, join as join13 } from "path";
127633
+ import { basename as basename3, dirname as dirname8, resolve as resolvePath2, join as join14 } from "path";
127605
127634
  import { fileURLToPath, pathToFileURL } from "url";
127606
127635
  import { PGlite } from "@electric-sql/pglite";
127607
127636
  import { vector as upstreamVector } from "@electric-sql/pglite/vector";
@@ -127611,7 +127640,7 @@ function resolvePGliteExtensionBundle(upstreamBundle, executablePath = process.e
127611
127640
  const upstreamPath = fileURLToPath(upstreamBundle);
127612
127641
  if (pathExists(upstreamPath))
127613
127642
  return upstreamBundle;
127614
- const sidecarPath = join13(dirname8(executablePath), basename3(upstreamPath));
127643
+ const sidecarPath = join14(dirname8(executablePath), basename3(upstreamPath));
127615
127644
  return pathExists(sidecarPath) ? pathToFileURL(sidecarPath) : upstreamBundle;
127616
127645
  }
127617
127646
  async function pgliteRuntimeOptions() {
@@ -127619,7 +127648,7 @@ async function pgliteRuntimeOptions() {
127619
127648
  return pgliteRuntimeOptionsPromise;
127620
127649
  }
127621
127650
  async function loadPGliteRuntimeOptions(executablePath) {
127622
- const assetPaths = Object.fromEntries(PGLITE_RUNTIME_ASSET_NAMES.map((name26) => [name26, join13(dirname8(executablePath), name26)]));
127651
+ const assetPaths = Object.fromEntries(PGLITE_RUNTIME_ASSET_NAMES.map((name26) => [name26, join14(dirname8(executablePath), name26)]));
127623
127652
  const present = PGLITE_RUNTIME_ASSET_NAMES.filter((name26) => existsSync2(assetPaths[name26]));
127624
127653
  if (present.length === 0)
127625
127654
  return {};
@@ -127806,11 +127835,11 @@ function isExternalAssetError(error54, dataDir) {
127806
127835
  function looksLikeIntactPGliteDirectory(path6) {
127807
127836
  if (!isExistingDirectory(path6))
127808
127837
  return false;
127809
- const versionFile = join13(path6, "PG_VERSION");
127838
+ const versionFile = join14(path6, "PG_VERSION");
127810
127839
  const version2 = tryReadFile(versionFile);
127811
127840
  if (!version2 || version2.trim().length === 0)
127812
127841
  return false;
127813
- return REQUIRED_PGLITE_SUBDIRS.every((sub) => isExistingDirectory(join13(path6, sub)));
127842
+ return REQUIRED_PGLITE_SUBDIRS.every((sub) => isExistingDirectory(join14(path6, sub)));
127814
127843
  }
127815
127844
  function listBackups(path6) {
127816
127845
  const dir = dirname8(path6);
@@ -127824,7 +127853,7 @@ function listBackups(path6) {
127824
127853
  throw error54;
127825
127854
  }
127826
127855
  const prefix = `${base}${BACKUP_SUFFIX_PREFIX}`;
127827
- return entries.filter((name26) => name26.startsWith(prefix)).map((name26) => join13(dir, name26)).sort().reverse();
127856
+ return entries.filter((name26) => name26.startsWith(prefix)).map((name26) => join14(dir, name26)).sort().reverse();
127828
127857
  }
127829
127858
  async function snapshotAfterSuccessfulOpen(db, path6) {
127830
127859
  try {
@@ -127906,7 +127935,7 @@ function quarantineDataDirectory(path6) {
127906
127935
  return backup;
127907
127936
  }
127908
127937
  function peekOpenLockHolderPid(dataDir) {
127909
- const lockPath = join13(dataDir, OPEN_LOCK_FILE);
127938
+ const lockPath = join14(dataDir, OPEN_LOCK_FILE);
127910
127939
  const contents = tryReadFile(lockPath);
127911
127940
  if (contents === undefined)
127912
127941
  return null;
@@ -127923,7 +127952,7 @@ function peekOpenLockHolderPid(dataDir) {
127923
127952
  }
127924
127953
  function tryAcquireOpenLock(dataDir) {
127925
127954
  mkdirSync(dataDir, { recursive: true });
127926
- const lockPath = join13(dataDir, OPEN_LOCK_FILE);
127955
+ const lockPath = join14(dataDir, OPEN_LOCK_FILE);
127927
127956
  const created = createLockFile(lockPath);
127928
127957
  if (created) {
127929
127958
  heldLockPaths.add(created);
@@ -127988,7 +128017,7 @@ function createLockFile(lockPath) {
127988
128017
  function clearStalePostmasterLock(dataDir) {
127989
128018
  if (!isExistingDirectory(dataDir))
127990
128019
  return;
127991
- const lockPath = join13(dataDir, "postmaster.pid");
128020
+ const lockPath = join14(dataDir, "postmaster.pid");
127992
128021
  const contents = tryReadFile(lockPath);
127993
128022
  if (contents === undefined)
127994
128023
  return;
@@ -128085,16 +128114,6 @@ function nanoid3(size = 21) {
128085
128114
  var POOL_SIZE_MULTIPLIER = 128, pool, poolOffset;
128086
128115
  var init_nanoid = () => {};
128087
128116
 
128088
- // packages/agent/src/memory/paths.ts
128089
- import { homedir as homedir7 } from "os";
128090
- import { join as join14 } from "path";
128091
- var DEFAULT_BENTO_DIR = ".duet", DEFAULT_BENTO_HOME, DEFAULT_SESSION_STORAGE_DIR, DEFAULT_MEMORY_DB_PATH;
128092
- var init_paths = __esm(() => {
128093
- DEFAULT_BENTO_HOME = join14(homedir7(), DEFAULT_BENTO_DIR);
128094
- DEFAULT_SESSION_STORAGE_DIR = join14(DEFAULT_BENTO_HOME, "sessions");
128095
- DEFAULT_MEMORY_DB_PATH = join14(DEFAULT_BENTO_HOME, "memory.db");
128096
- });
128097
-
128098
128117
  // packages/agent/src/turn-runner/runtime-clock.ts
128099
128118
  class SystemRuntimeClock {
128100
128119
  now() {
@@ -149406,7 +149425,6 @@ var init_session3 = __esm(() => {
149406
149425
  });
149407
149426
 
149408
149427
  // packages/agent/src/memory/storage.ts
149409
- import { homedir as homedir8 } from "os";
149410
149428
  import { join as join15 } from "path";
149411
149429
  async function loadStoredMemory(memoryPath, cwd2, options = {}) {
149412
149430
  if (!memoryPath) {
@@ -149458,7 +149476,7 @@ async function loadStoredMemory(memoryPath, cwd2, options = {}) {
149458
149476
  return { session: session2, embed: options.embed, dispose };
149459
149477
  }
149460
149478
  function defaultEmbeddingLogPath() {
149461
- return join15(homedir8(), ".duet", "logs", "memory-backfill.log");
149479
+ return join15(DEFAULT_BENTO_HOME, "logs", "memory-backfill.log");
149462
149480
  }
149463
149481
  async function appendObservation(session2, input, options = {}) {
149464
149482
  const observation = {
@@ -149618,6 +149636,7 @@ var init_storage3 = __esm(() => {
149618
149636
  init_id3();
149619
149637
  init_migrations();
149620
149638
  init_observational();
149639
+ init_paths();
149621
149640
  init_session3();
149622
149641
  });
149623
149642
 
@@ -164618,7 +164637,7 @@ var init_child_process = __esm(() => {
164618
164637
 
164619
164638
  // node_modules/@earendil-works/pi-coding-agent/dist/utils/paths.js
164620
164639
  import { realpathSync, statSync as statSync4 } from "fs";
164621
- import { homedir as homedir9 } from "os";
164640
+ import { homedir as homedir7 } from "os";
164622
164641
  import { isAbsolute as isAbsolute3, join as join19, resolve as nodeResolvePath, relative as relative2, sep } from "path";
164623
164642
  import { fileURLToPath as fileURLToPath2 } from "url";
164624
164643
  function canonicalizePath(path6) {
@@ -164664,7 +164683,7 @@ function normalizePath(input, options = {}) {
164664
164683
  normalized = normalizeWindowsShellPath(normalized);
164665
164684
  }
164666
164685
  if (options.expandTilde ?? true) {
164667
- const home = options.homeDir ?? homedir9();
164686
+ const home = options.homeDir ?? homedir7();
164668
164687
  if (normalized === "~")
164669
164688
  return home;
164670
164689
  if (normalized.startsWith("~/") || process.platform === "win32" && normalized.startsWith("~\\")) {
@@ -164718,7 +164737,7 @@ function stripBom2(content) {
164718
164737
 
164719
164738
  // node_modules/@earendil-works/pi-coding-agent/dist/config.js
164720
164739
  import { accessSync, constants as constants3, existsSync as existsSync3, readFileSync as readFileSync3, realpathSync as realpathSync2 } from "fs";
164721
- import { homedir as homedir10 } from "os";
164740
+ import { homedir as homedir8 } from "os";
164722
164741
  import { basename as basename6, dirname as dirname10, join as join20, resolve as resolve12, sep as sep2, win32 } from "path";
164723
164742
  import { fileURLToPath as fileURLToPath3 } from "url";
164724
164743
  function findNodePackageDir(startDir) {
@@ -164799,7 +164818,7 @@ function getAgentDir() {
164799
164818
  if (envDir) {
164800
164819
  return expandTildePath(envDir);
164801
164820
  }
164802
- return join20(homedir10(), CONFIG_DIR_NAME, "agent");
164821
+ return join20(homedir8(), CONFIG_DIR_NAME, "agent");
164803
164822
  }
164804
164823
  function getCustomThemesDir() {
164805
164824
  return join20(getAgentDir(), "themes");
@@ -166270,7 +166289,7 @@ function fuzzyFilter(items3, query3, getText) {
166270
166289
  // node_modules/@earendil-works/pi-tui/dist/autocomplete.js
166271
166290
  import { spawn as spawn3 } from "child_process";
166272
166291
  import { readdirSync as readdirSync2, statSync as statSync5 } from "fs";
166273
- import { homedir as homedir11 } from "os";
166292
+ import { homedir as homedir9 } from "os";
166274
166293
  import { basename as basename7, dirname as dirname11, join as join21 } from "path";
166275
166294
  function toDisplayPath(value3) {
166276
166295
  return value3.replace(/\\/g, "/");
@@ -166618,10 +166637,10 @@ class CombinedAutocompleteProvider {
166618
166637
  }
166619
166638
  expandHomePath(path6) {
166620
166639
  if (path6.startsWith("~/")) {
166621
- const expandedPath = join21(homedir11(), path6.slice(2));
166640
+ const expandedPath = join21(homedir9(), path6.slice(2));
166622
166641
  return path6.endsWith("/") && !expandedPath.endsWith("/") ? `${expandedPath}/` : expandedPath;
166623
166642
  } else if (path6 === "~") {
166624
- return homedir11();
166643
+ return homedir9();
166625
166644
  }
166626
166645
  return path6;
166627
166646
  }
@@ -167613,7 +167632,7 @@ var init_terminal_colors = __esm(() => {
167613
167632
 
167614
167633
  // node_modules/@earendil-works/pi-tui/dist/terminal-image.js
167615
167634
  import { execSync } from "child_process";
167616
- import { homedir as homedir12 } from "os";
167635
+ import { homedir as homedir10 } from "os";
167617
167636
  import { isAbsolute as isAbsolute4 } from "path";
167618
167637
  import { pathToFileURL as pathToFileURL2 } from "url";
167619
167638
  function getCellDimensions() {
@@ -168034,7 +168053,7 @@ function hyperlink(text2, url2) {
168034
168053
  return `\x1B]8;;${url2}\x1B\\${text2}\x1B]8;;\x1B\\`;
168035
168054
  }
168036
168055
  function shortenImagePath(filename) {
168037
- const home = homedir12();
168056
+ const home = homedir10();
168038
168057
  if (home && (filename === home || filename.startsWith(`${home}/`) || filename.startsWith(`${home}\\`))) {
168039
168058
  return `~${filename.slice(home.length)}`;
168040
168059
  }
@@ -267748,7 +267767,7 @@ var init_output_guard = __esm(() => {
267748
267767
  // node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
267749
267768
  import { createHash as createHash4 } from "crypto";
267750
267769
  import { chmodSync as chmodSync2, existsSync as existsSync12, globSync, mkdirSync as mkdirSync8, readdirSync as readdirSync7, readFileSync as readFileSync10, rmSync as rmSync3, statSync as statSync9, writeFileSync as writeFileSync6 } from "fs";
267751
- import { homedir as homedir14 } from "os";
267770
+ import { homedir as homedir12 } from "os";
267752
267771
  import { basename as basename12, dirname as dirname23, join as join40, relative as relative5, resolve as resolve17, sep as sep6 } from "path";
267753
267772
  function getEnv2() {
267754
267773
  if (process.platform !== "linux" || Object.keys(process.env).length > 0) {
@@ -267790,7 +267809,7 @@ function toPosixPath3(p) {
267790
267809
  return p.split(sep6).join("/");
267791
267810
  }
267792
267811
  function getHomeDir() {
267793
- return process.env.HOME || homedir14();
267812
+ return process.env.HOME || homedir12();
267794
267813
  }
267795
267814
  function getExtensionTempFolder(agentDir) {
267796
267815
  const tempFolder = join40(agentDir, "tmp", "extensions");
@@ -271208,7 +271227,7 @@ var init_sdk2 = __esm(() => {
271208
271227
 
271209
271228
  // node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js
271210
271229
  import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
271211
- import { homedir as homedir15 } from "os";
271230
+ import { homedir as homedir13 } from "os";
271212
271231
  import { dirname as dirname26, join as join43 } from "path";
271213
271232
  function normalizeCwd(cwd2) {
271214
271233
  return canonicalizePath(resolvePath3(cwd2));
@@ -271331,7 +271350,7 @@ function withTrustFileLock(path15, fn) {
271331
271350
  }
271332
271351
  }
271333
271352
  function hasTrustRequiringProjectResources(cwd2) {
271334
- const homeDir = canonicalizePath(resolvePath3(process.env.HOME || homedir15()));
271353
+ const homeDir = canonicalizePath(resolvePath3(process.env.HOME || homedir13()));
271335
271354
  const userAgentsSkillsDir = join43(homeDir, ".agents", "skills");
271336
271355
  let currentDir = canonicalizePath(resolvePath3(cwd2));
271337
271356
  const configDir = join43(currentDir, CONFIG_DIR_NAME);
@@ -288935,6 +288954,7 @@ var BUILTIN_PATH_PREFIX = "<duet-builtin>", RELAY_ORCHESTRATION_RULES, RELAY_INS
288935
288954
  var init_built_in_skills = __esm(() => {
288936
288955
  init_dist13();
288937
288956
  init_dedent();
288957
+ init_paths();
288938
288958
  RELAY_ORCHESTRATION_RULES = [
288939
288959
  "The tool descriptions and their parameter docs are the exact contract for every call shape and field; read them when building a definition or an override. What follows is when and how to use them.",
288940
288960
  '**You are the orchestrator and you alone route.** You select states; the runner runs each one outside your turn \u2014 agent states in a fresh sub-agent context, scripts as commands \u2014 then wakes you with a compact result, and you decide every transition. Sub-agents and scripts never route: tell each state what to do and what to report back, and map its report to the next state yourself. Never write a state prompt that says "route to X if approved" or "go to state Y"; it has no way to do that.',
@@ -288999,10 +289019,10 @@ var init_built_in_skills = __esm(() => {
288999
289019
 
289000
289020
  ### Architecture
289001
289021
 
289002
- - **Schedule file** (e.g. \`~/.duet/relay/schedule.json\`):
289022
+ - **Schedule file** (e.g. \`${DEFAULT_BENTO_HOME}/relay/schedule.json\`):
289003
289023
  \`{ "<task>": { "interval": <ms>, "next": <unix-ms>, "kind": "agent"|"script" } }\`.
289004
289024
  This is the only source of truth for "what's due when."
289005
- - **Dispatcher script** (e.g. \`~/.duet/relay/dispatch.sh\`): reads
289025
+ - **Dispatcher script** (e.g. \`${DEFAULT_BENTO_HOME}/relay/dispatch.sh\`): reads
289006
289026
  \`schedule.json\`, sorted by \`next\` ascending. For every due task:
289007
289027
  - If \`kind: "script"\` (shell-only): run inline inside the dispatcher,
289008
289028
  append output to a bounded log, then bump \`next += interval\` and
@@ -289488,11 +289508,14 @@ var init_shell_state_handle = __esm(() => {
289488
289508
  // packages/agent/src/turn-runner/skills.ts
289489
289509
  import { execFile as execFile2, execFileSync as execFileSync2 } from "child_process";
289490
289510
  import { readFileSync as readFileSync20 } from "fs";
289491
- import { homedir as homedir18 } from "os";
289511
+ import { homedir as homedir16 } from "os";
289492
289512
  import { join as join50, resolve as resolve21, sep as sep9 } from "path";
289493
289513
  function buildSkillDiscoveryOptions(options, cwd2) {
289494
289514
  const effectiveCwd = options?.cwd ?? cwd2;
289495
- const globalSkillRoots = options?.agentDir ? [options.agentDir] : DEFAULT_SKILL_DIR_NAMES.map((dirName) => join50(homedir18(), dirName));
289515
+ const globalSkillRoots = options?.agentDir ? [options.agentDir] : [
289516
+ selectBentoStateRoot(homedir16()),
289517
+ ...GLOBAL_SKILL_DIR_NAMES.map((dirName) => join50(homedir16(), dirName))
289518
+ ];
289496
289519
  const includeDefaults = options?.includeDefaults ?? true;
289497
289520
  return {
289498
289521
  cwd: effectiveCwd,
@@ -289507,7 +289530,7 @@ function buildSkillDiscoveryOptions(options, cwd2) {
289507
289530
  function defaultSkillPaths(globalSkillRoots, cwd2) {
289508
289531
  const ancestorPaths = [];
289509
289532
  for (const ancestor of walkAncestors(cwd2)) {
289510
- for (const dirName of DEFAULT_SKILL_DIR_NAMES) {
289533
+ for (const dirName of PROJECT_SKILL_DIR_NAMES) {
289511
289534
  ancestorPaths.push(join50(ancestor, dirName, "skills"));
289512
289535
  }
289513
289536
  }
@@ -289626,13 +289649,15 @@ function resolveSkillScope(skill, cwd2) {
289626
289649
  if (isBuiltInSkill(skill))
289627
289650
  return "builtin";
289628
289651
  const baseDir = resolve21(skill.baseDir);
289629
- const home = homedir18();
289630
- for (const dirName of DEFAULT_SKILL_DIR_NAMES) {
289652
+ const home = homedir16();
289653
+ if (isUnderPath(baseDir, join50(selectBentoStateRoot(home), "skills")))
289654
+ return "user";
289655
+ for (const dirName of GLOBAL_SKILL_DIR_NAMES) {
289631
289656
  if (isUnderPath(baseDir, join50(home, dirName, "skills")))
289632
289657
  return "user";
289633
289658
  }
289634
289659
  for (const ancestor of walkAncestors(cwd2)) {
289635
- for (const dirName of DEFAULT_SKILL_DIR_NAMES) {
289660
+ for (const dirName of PROJECT_SKILL_DIR_NAMES) {
289636
289661
  if (isUnderPath(baseDir, join50(ancestor, dirName, "skills")))
289637
289662
  return "project";
289638
289663
  }
@@ -289646,13 +289671,15 @@ function isUnderPath(target2, root) {
289646
289671
  const prefix = normalizedRoot.endsWith(sep9) ? normalizedRoot : `${normalizedRoot}${sep9}`;
289647
289672
  return target2.startsWith(prefix);
289648
289673
  }
289649
- var SKILL_SHELL_EXPANSION_PATTERN, DEFAULT_SKILL_DIR_NAMES, SKILL_SHELL_EXPANSION_TIMEOUT_MS = 30000, SKILL_METADATA_EXPANSION_CONCURRENCY = 4, SKILL_SHELL_EXPANSION_OPTIONS;
289674
+ var SKILL_SHELL_EXPANSION_PATTERN, PROJECT_SKILL_DIR_NAMES, GLOBAL_SKILL_DIR_NAMES, SKILL_SHELL_EXPANSION_TIMEOUT_MS = 30000, SKILL_METADATA_EXPANSION_CONCURRENCY = 4, SKILL_SHELL_EXPANSION_OPTIONS;
289650
289675
  var init_skills8 = __esm(() => {
289651
289676
  init_dist13();
289652
289677
  init_walk_ancestors();
289678
+ init_paths();
289653
289679
  init_built_in_skills();
289654
289680
  SKILL_SHELL_EXPANSION_PATTERN = /!`([\s\S]*?)`/g;
289655
- DEFAULT_SKILL_DIR_NAMES = [".duet", ".agents", ".claude"];
289681
+ PROJECT_SKILL_DIR_NAMES = [".duet", ".agents", ".claude"];
289682
+ GLOBAL_SKILL_DIR_NAMES = [".agents", ".claude"];
289656
289683
  SKILL_SHELL_EXPANSION_OPTIONS = {
289657
289684
  encoding: "utf-8",
289658
289685
  maxBuffer: 1024 * 1024,
@@ -296105,13 +296132,13 @@ var init_connect = __esm(() => {
296105
296132
  // packages/agent/src/train/archive.ts
296106
296133
  import { createHash as createHash6 } from "crypto";
296107
296134
  import { copyFile as copyFile2, mkdir as mkdir13, readdir as readdir7, readFile as readFile21, rm as rm4, stat as stat7, writeFile as writeFile11 } from "fs/promises";
296108
- import { homedir as homedir19 } from "os";
296135
+ import { homedir as homedir17 } from "os";
296109
296136
  import path18, { dirname as dirname31, join as join56 } from "path";
296110
296137
  function archiveRootForMemoryId(memoryId) {
296111
296138
  if (!/^[A-Za-z0-9_-]+$/.test(memoryId)) {
296112
296139
  throw new Error(`Archive memory id must be a safe path segment: ${memoryId}`);
296113
296140
  }
296114
- return join56(homedir19(), ".duet", "train", memoryId);
296141
+ return join56(selectBentoStateRoot(homedir17()), "train", memoryId);
296115
296142
  }
296116
296143
  async function writeArchive(input) {
296117
296144
  const root = archiveRootForMemoryId(input.memoryId);
@@ -296178,7 +296205,9 @@ async function collectArchiveFiles(folder) {
296178
296205
  files2.sort((a, b2) => a.relPath < b2.relPath ? -1 : a.relPath > b2.relPath ? 1 : 0);
296179
296206
  return files2;
296180
296207
  }
296181
- var init_archive2 = () => {};
296208
+ var init_archive2 = __esm(() => {
296209
+ init_paths();
296210
+ });
296182
296211
 
296183
296212
  // packages/agent/src/train/tags.ts
296184
296213
  function trainSlugTag(slug2) {
@@ -297645,7 +297674,6 @@ var init_memory7 = __esm(() => {
297645
297674
 
297646
297675
  // packages/bento/src/tui/recent-sessions.ts
297647
297676
  import { readFileSync as readFileSync23, readdirSync as readdirSync8, statSync as statSync12 } from "fs";
297648
- import { homedir as homedir20 } from "os";
297649
297677
  import { join as join58 } from "path";
297650
297678
  function listRecentSessions(input = {}) {
297651
297679
  const root = input.sessionsRoot ?? DEFAULT_SESSIONS_ROOT;
@@ -297756,7 +297784,8 @@ function userMessageText(content) {
297756
297784
  }
297757
297785
  var DEFAULT_SESSIONS_ROOT, RECENT_PROMPT_MAX_LENGTH = 60;
297758
297786
  var init_recent_sessions = __esm(() => {
297759
- DEFAULT_SESSIONS_ROOT = join58(homedir20(), ".duet", "sessions");
297787
+ init_paths();
297788
+ DEFAULT_SESSIONS_ROOT = join58(DEFAULT_BENTO_HOME, "sessions");
297760
297789
  });
297761
297790
 
297762
297791
  // packages/bento/src/cli/route.ts
@@ -298918,7 +298947,7 @@ import {
298918
298947
  rmSync as rmSync6,
298919
298948
  statSync as statSync13
298920
298949
  } from "fs";
298921
- import { homedir as homedir21 } from "os";
298950
+ import { homedir as homedir18 } from "os";
298922
298951
  import { join as join60 } from "path";
298923
298952
  function createUpgradeStatusStream() {
298924
298953
  const listeners = new Set;
@@ -299048,7 +299077,7 @@ function describeUpgradeStatus(packageName, status) {
299048
299077
  }
299049
299078
  }
299050
299079
  function upgradePaths() {
299051
- const bentoDir = join60(homedir21(), ".duet");
299080
+ const bentoDir = selectBentoStateRoot(homedir18());
299052
299081
  return {
299053
299082
  bentoDir,
299054
299083
  lockPath: join60(bentoDir, "upgrade.lock"),
@@ -299163,6 +299192,7 @@ function readStderrTail(path20, startByte) {
299163
299192
  var NO_AUTO_UPGRADE_ENV = "DUET_NO_AUTO_UPGRADE", STALE_LOCK_MS, REGISTRY_TIMEOUT_MS = 8000, PACKAGE_MANAGER_SPAWN_OPTIONS;
299164
299193
  var init_auto_upgrade = __esm(() => {
299165
299194
  init_file_lock();
299195
+ init_paths();
299166
299196
  init_pglite();
299167
299197
  init_session_manager2();
299168
299198
  init_managed_runtime();
@@ -300198,7 +300228,7 @@ var init_slash_commands2 = __esm(() => {
300198
300228
  });
300199
300229
 
300200
300230
  // packages/bento/src/tui/boot-screen.ts
300201
- import { homedir as homedir22 } from "os";
300231
+ import { homedir as homedir19 } from "os";
300202
300232
  import { TextRenderable as TextRenderable2 } from "@opentui/core";
300203
300233
  function renderSetupIntro(deps, skills3, agentFiles) {
300204
300234
  for (const line of BENTO_BANNER_LINES_COMPACT)
@@ -300280,7 +300310,7 @@ async function renderBootScreen(deps) {
300280
300310
  refreshSidebarFromSession({ session: deps.session, sidebar: deps.sidebar });
300281
300311
  }
300282
300312
  function shortenCwd(cwd2) {
300283
- const home = homedir22();
300313
+ const home = homedir19();
300284
300314
  if (cwd2 === home)
300285
300315
  return "~";
300286
300316
  if (cwd2.startsWith(`${home}/`))
@@ -301038,7 +301068,7 @@ var init_copy_controller = __esm(() => {
301038
301068
  import { spawn as spawn19 } from "child_process";
301039
301069
  import { existsSync as existsSync23 } from "fs";
301040
301070
  import { mkdir as mkdir14, readFile as readFile25, unlink as unlink5, writeFile as writeFile12 } from "fs/promises";
301041
- import { homedir as homedir23, platform as platform3, tmpdir as tmpdir10 } from "os";
301071
+ import { homedir as homedir20, platform as platform3, tmpdir as tmpdir10 } from "os";
301042
301072
  import { extname as extname3, isAbsolute as isAbsolute10, join as join62, resolve as resolve25 } from "path";
301043
301073
  function sniffImageMimeType(bytes) {
301044
301074
  if (bytes.length < 4)
@@ -301081,7 +301111,7 @@ function extensionForMimeType(mimeType) {
301081
301111
  return ".bin";
301082
301112
  }
301083
301113
  function pasteCacheDir(sessionId) {
301084
- return resolve25(homedir23(), ".duet", "cache", "paste", sessionId);
301114
+ return resolve25(DEFAULT_BENTO_HOME, "cache", "paste", sessionId);
301085
301115
  }
301086
301116
  async function persistPastedImage(input) {
301087
301117
  if (!SUPPORTED_MIME_TYPES.has(input.mimeType)) {
@@ -301197,9 +301227,9 @@ function resolveExistingImagePath(cwd2, rawPath) {
301197
301227
  }
301198
301228
  function expandUserPath(input) {
301199
301229
  if (input.startsWith("~/"))
301200
- return resolve25(homedir23(), input.slice(2));
301230
+ return resolve25(homedir20(), input.slice(2));
301201
301231
  if (input === "~")
301202
- return homedir23();
301232
+ return homedir20();
301203
301233
  return input;
301204
301234
  }
301205
301235
  async function tryReadClipboardText() {
@@ -301385,6 +301415,7 @@ function runCommandRaw(cmd, args) {
301385
301415
  }
301386
301416
  var MAX_IMAGE_BYTES, SUPPORTED_MIME_TYPES;
301387
301417
  var init_paste = __esm(() => {
301418
+ init_paths();
301388
301419
  MAX_IMAGE_BYTES = 20 * 1024 * 1024;
301389
301420
  SUPPORTED_MIME_TYPES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
301390
301421
  });
@@ -302314,7 +302345,6 @@ var init_input2 = __esm(() => {
302314
302345
 
302315
302346
  // packages/bento/src/tui/dino/persistence.ts
302316
302347
  import { mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync13 } from "fs";
302317
- import { homedir as homedir24 } from "os";
302318
302348
  import { dirname as dirname32, join as join63 } from "path";
302319
302349
  function loadHighScore() {
302320
302350
  try {
@@ -302337,7 +302367,8 @@ function ensureDir2(filePath2) {
302337
302367
  }
302338
302368
  var DINO_DIR, HIGHSCORE_FILE;
302339
302369
  var init_persistence = __esm(() => {
302340
- DINO_DIR = join63(homedir24(), ".duet", "dino");
302370
+ init_paths();
302371
+ DINO_DIR = join63(DEFAULT_BENTO_HOME, "dino");
302341
302372
  HIGHSCORE_FILE = join63(DINO_DIR, "highscore");
302342
302373
  });
302343
302374
 
@@ -303281,7 +303312,7 @@ var init_renderer_lifecycle = () => {};
303281
303312
  // packages/bento/src/tui/starters.ts
303282
303313
  import { execFileSync as execFileSync3 } from "child_process";
303283
303314
  import { existsSync as existsSync24, readdirSync as readdirSync10, statSync as statSync14 } from "fs";
303284
- import { homedir as homedir25 } from "os";
303315
+ import { homedir as homedir21 } from "os";
303285
303316
  import { join as join64, resolve as resolve26 } from "path";
303286
303317
  function orderedSelectableStarters(result2) {
303287
303318
  const ordered = [];
@@ -303340,7 +303371,7 @@ function hasPackageJson(cwd2) {
303340
303371
  }
303341
303372
  function isScratchDir(cwd2) {
303342
303373
  const resolved = resolve26(cwd2);
303343
- const home = homedir25();
303374
+ const home = homedir21();
303344
303375
  return resolved === "/tmp" || resolved === join64(home, "Desktop") || resolved === join64(home, "Downloads");
303345
303376
  }
303346
303377
  function isEmptyDir(cwd2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bentoai/cli",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Bento CLI for local agents, workspaces and file sync",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",