@signetai/core 0.214.42 → 0.216.5

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/dist/index.js CHANGED
@@ -7129,7 +7129,7 @@ var require_keyring = __commonJS((exports, module) => {
7129
7129
  var __filename = "/home/runner/work/signetai/signetai/node_modules/.bun/@napi-rs+keyring@1.3.0/node_modules/@napi-rs/keyring/index.js";
7130
7130
  var { createRequire: createRequire2 } = __require("node:module");
7131
7131
  __require = createRequire2(__filename);
7132
- var { readFileSync: readFileSync2 } = __require("node:fs");
7132
+ var { readFileSync: readFileSync3 } = __require("node:fs");
7133
7133
  var nativeBinding = null;
7134
7134
  var loadErrors = [];
7135
7135
  var isMusl = () => {
@@ -7148,7 +7148,7 @@ var require_keyring = __commonJS((exports, module) => {
7148
7148
  var isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
7149
7149
  var isMuslFromFilesystem = () => {
7150
7150
  try {
7151
- return readFileSync2("/usr/bin/ldd", "utf-8").includes("musl");
7151
+ return readFileSync3("/usr/bin/ldd", "utf-8").includes("musl");
7152
7152
  } catch {
7153
7153
  return null;
7154
7154
  }
@@ -11148,7 +11148,12 @@ var PIPELINE_MODEL_CATALOG = {
11148
11148
  acpx: [
11149
11149
  { value: "haiku", label: "Claude Code · haiku", tier: "low", source: "harness" },
11150
11150
  { value: "gpt-5.4-mini", label: "Codex CLI · gpt-5.4-mini", tier: "low", source: "harness" },
11151
- { value: "google/gemini-2.5-flash", label: "OpenCode · google/gemini-2.5-flash", tier: "low", source: "harness" }
11151
+ {
11152
+ value: "opencode/gemini-3-flash",
11153
+ label: "OpenCode · opencode/gemini-3-flash",
11154
+ tier: "low",
11155
+ source: "harness"
11156
+ }
11152
11157
  ],
11153
11158
  "llama-cpp": [
11154
11159
  { value: "qwen3:4b", label: "qwen3:4b", tier: "low", source: "local" },
@@ -11164,27 +11169,35 @@ var PIPELINE_MODEL_CATALOG = {
11164
11169
  { value: "opus", label: "Opus", tier: "high", source: "harness" }
11165
11170
  ],
11166
11171
  codex: [
11172
+ { value: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark", tier: "low", source: "harness" },
11167
11173
  { value: "gpt-5.4-mini", label: "gpt-5.4-mini", tier: "low", source: "harness" },
11168
11174
  { value: "gpt-5.4", label: "gpt-5.4", tier: "mid", source: "harness" },
11169
11175
  { value: "gpt-5.5", label: "gpt-5.5", tier: "high", source: "harness" },
11170
- { value: "gpt-5.3-codex", label: "gpt-5.3-codex", tier: "mid", source: "harness" },
11171
- { value: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark", tier: "low", source: "harness" },
11172
- { value: "gpt-5.2", label: "gpt-5.2", tier: "mid", source: "harness" }
11176
+ { value: "gpt-5.6-luna", label: "gpt-5.6-luna", tier: "high", source: "harness" },
11177
+ { value: "gpt-5.6-sol", label: "gpt-5.6-sol", tier: "high", source: "harness" },
11178
+ { value: "gpt-5.6-terra", label: "gpt-5.6-terra", tier: "high", source: "harness" }
11173
11179
  ],
11174
11180
  opencode: [
11175
- { value: "google/gemini-2.5-flash", label: "google/gemini-2.5-flash", tier: "low", source: "harness" },
11176
- { value: "openai/gpt-5.4-mini", label: "openai/gpt-5.4-mini", tier: "low", source: "harness" },
11177
- { value: "openai/gpt-5.4", label: "openai/gpt-5.4", tier: "mid", source: "harness" }
11181
+ { value: "opencode/gemini-3-flash", label: "opencode/gemini-3-flash", tier: "low", source: "harness" },
11182
+ { value: "opencode/gpt-5.4-mini", label: "opencode/gpt-5.4-mini", tier: "low", source: "harness" },
11183
+ { value: "opencode/gpt-5.5", label: "opencode/gpt-5.5", tier: "mid", source: "harness" }
11178
11184
  ],
11179
11185
  anthropic: [
11180
- { value: "claude-3-5-haiku-20241022", label: "Claude 3.5 Haiku", tier: "low", source: "provider" },
11181
- { value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4", tier: "mid", source: "provider" }
11186
+ { value: "claude-haiku-4-5", label: "Claude Haiku 4.5", tier: "low", source: "provider" },
11187
+ { value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", tier: "mid", source: "provider" },
11188
+ { value: "claude-opus-4-6", label: "Claude Opus 4.6", tier: "high", source: "provider" }
11182
11189
  ],
11183
11190
  openrouter: [
11184
- { value: "openai/gpt-4o-mini", label: "openai/gpt-4o-mini", tier: "low", source: "provider" },
11185
11191
  { value: "openai/gpt-5.4-mini", label: "openai/gpt-5.4-mini", tier: "low", source: "provider" },
11186
- { value: "anthropic/claude-3.5-haiku", label: "anthropic/claude-3.5-haiku", tier: "low", source: "provider" },
11187
- { value: "google/gemini-2.5-flash", label: "google/gemini-2.5-flash", tier: "low", source: "provider" }
11192
+ { value: "openai/gpt-5.4", label: "openai/gpt-5.4", tier: "mid", source: "provider" },
11193
+ { value: "anthropic/claude-sonnet-4.6", label: "anthropic/claude-sonnet-4.6", tier: "mid", source: "provider" },
11194
+ {
11195
+ value: "google/gemini-3.1-pro-preview",
11196
+ label: "google/gemini-3.1-pro-preview",
11197
+ tier: "high",
11198
+ source: "provider"
11199
+ },
11200
+ { value: "deepseek/deepseek-v4-pro", label: "deepseek/deepseek-v4-pro", tier: "high", source: "provider" }
11188
11201
  ],
11189
11202
  "openai-compatible": [
11190
11203
  { value: "gpt-4o-mini", label: "gpt-4o-mini", tier: "low", source: "provider" },
@@ -11199,14 +11212,14 @@ var MODEL_DEFAULTS = {
11199
11212
  ollama: "qwen3:4b",
11200
11213
  "claude-code": "haiku",
11201
11214
  codex: "gpt-5.4-mini",
11202
- opencode: "google/gemini-2.5-flash",
11203
- anthropic: "claude-3-5-haiku-20241022",
11204
- openrouter: "openai/gpt-4o-mini",
11215
+ opencode: "opencode/gemini-3-flash",
11216
+ anthropic: "claude-haiku-4-5",
11217
+ openrouter: "openai/gpt-5.4-mini",
11205
11218
  "openai-compatible": "gpt-4o-mini",
11206
11219
  command: ""
11207
11220
  };
11208
11221
  function modelPresetsForProvider(provider) {
11209
- return Object.prototype.hasOwnProperty.call(PIPELINE_MODEL_CATALOG, provider) ? PIPELINE_MODEL_CATALOG[provider] : [];
11222
+ return Object.hasOwn(PIPELINE_MODEL_CATALOG, provider) ? PIPELINE_MODEL_CATALOG[provider] : [];
11210
11223
  }
11211
11224
  function modelDefaultForProvider(provider) {
11212
11225
  return MODEL_DEFAULTS[provider];
@@ -18683,10 +18696,24 @@ function rowToJob(row) {
18683
18696
  var import_yaml = __toESM(require_dist(), 1);
18684
18697
 
18685
18698
  // src/constants.ts
18686
- import { homedir as homedir2 } from "os";
18687
- import { join as join2 } from "path";
18699
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
18700
+ import { homedir as homedir2 } from "node:os";
18701
+ import { join as join2, resolve } from "node:path";
18688
18702
  function resolveDefaultBasePath() {
18689
- return process.env.SIGNET_PATH || join2(homedir2(), ".agents");
18703
+ const envPath = process.env.SIGNET_PATH?.trim() || process.env.SIGNET_WORKSPACE?.trim();
18704
+ if (envPath)
18705
+ return resolve(expandHome(envPath));
18706
+ const home = homedir2();
18707
+ const configHome = process.env.XDG_CONFIG_HOME?.trim() ? resolve(expandHome(process.env.XDG_CONFIG_HOME.trim(), home)) : join2(home, ".config");
18708
+ const configPath = join2(configHome, "signet", "workspace.json");
18709
+ if (existsSync2(configPath)) {
18710
+ try {
18711
+ const value = JSON.parse(readFileSync(configPath, "utf8"));
18712
+ if (typeof value.workspace === "string" && value.workspace.trim())
18713
+ return resolve(expandHome(value.workspace, home));
18714
+ } catch {}
18715
+ }
18716
+ return join2(home, ".agents");
18690
18717
  }
18691
18718
  function expandHome(p, home = homedir2()) {
18692
18719
  if (p === "~")
@@ -18854,7 +18881,7 @@ function generateMemory() {
18854
18881
  }
18855
18882
 
18856
18883
  // src/signet.ts
18857
- import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync } from "fs";
18884
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
18858
18885
  import { join as join3 } from "path";
18859
18886
 
18860
18887
  class Signet {
@@ -18870,7 +18897,7 @@ class Signet {
18870
18897
  }
18871
18898
  async init(name) {
18872
18899
  const basePath = this.getBasePath();
18873
- if (!existsSync2(basePath)) {
18900
+ if (!existsSync3(basePath)) {
18874
18901
  mkdirSync(basePath, { recursive: true });
18875
18902
  }
18876
18903
  const manifest = {
@@ -18892,25 +18919,25 @@ class Signet {
18892
18919
  await this.db.init();
18893
18920
  this.agent = {
18894
18921
  manifest,
18895
- soul: readFileSync(join3(basePath, "soul.md"), "utf-8"),
18896
- memory: readFileSync(join3(basePath, "memory.md"), "utf-8"),
18922
+ soul: readFileSync2(join3(basePath, "soul.md"), "utf-8"),
18923
+ memory: readFileSync2(join3(basePath, "memory.md"), "utf-8"),
18897
18924
  dbPath: join3(basePath, "agent.db")
18898
18925
  };
18899
18926
  return this.agent;
18900
18927
  }
18901
18928
  async load() {
18902
18929
  const basePath = this.getBasePath();
18903
- if (!existsSync2(join3(basePath, "agent.yaml"))) {
18930
+ if (!existsSync3(join3(basePath, "agent.yaml"))) {
18904
18931
  throw new Error(`No agent found at ${basePath}. Run 'signet init' first.`);
18905
18932
  }
18906
- const manifestYaml = readFileSync(join3(basePath, "agent.yaml"), "utf-8");
18933
+ const manifestYaml = readFileSync2(join3(basePath, "agent.yaml"), "utf-8");
18907
18934
  const manifest = parseManifest(manifestYaml);
18908
18935
  this.db = new Database(join3(basePath, "agent.db"));
18909
18936
  await this.db.init();
18910
18937
  this.agent = {
18911
18938
  manifest,
18912
- soul: readFileSync(join3(basePath, "soul.md"), "utf-8"),
18913
- memory: readFileSync(join3(basePath, "memory.md"), "utf-8"),
18939
+ soul: readFileSync2(join3(basePath, "soul.md"), "utf-8"),
18940
+ memory: readFileSync2(join3(basePath, "memory.md"), "utf-8"),
18914
18941
  dbPath: join3(basePath, "agent.db")
18915
18942
  };
18916
18943
  return this.agent;
@@ -18929,7 +18956,7 @@ class Signet {
18929
18956
  }
18930
18957
  static detect(basePath) {
18931
18958
  const path = basePath || resolveDefaultBasePath();
18932
- return existsSync2(join3(path, "agent.yaml"));
18959
+ return existsSync3(join3(path, "agent.yaml"));
18933
18960
  }
18934
18961
  static getDefaultPath() {
18935
18962
  return resolveDefaultBasePath();
@@ -18941,11 +18968,11 @@ import { randomBytes, randomUUID } from "node:crypto";
18941
18968
  import {
18942
18969
  chmodSync,
18943
18970
  closeSync,
18944
- existsSync as existsSync3,
18971
+ existsSync as existsSync4,
18945
18972
  fsyncSync,
18946
18973
  mkdirSync as mkdirSync2,
18947
18974
  openSync,
18948
- readFileSync as readFileSync2,
18975
+ readFileSync as readFileSync3,
18949
18976
  readdirSync as readdirSync2,
18950
18977
  renameSync,
18951
18978
  rmdirSync,
@@ -19153,7 +19180,7 @@ function resolveMachineId() {
19153
19180
  const candidates = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
19154
19181
  for (const p2 of candidates) {
19155
19182
  try {
19156
- const id = readFileSync2(p2, "utf-8").trim();
19183
+ const id = readFileSync3(p2, "utf-8").trim();
19157
19184
  if (id)
19158
19185
  return id;
19159
19186
  } catch {}
@@ -19199,7 +19226,7 @@ class SecretKeyringError extends Error {
19199
19226
  }
19200
19227
  function readPersistedMachineId() {
19201
19228
  try {
19202
- const persisted = readFileSync2(getMachineIdFile(), "utf-8").trim();
19229
+ const persisted = readFileSync3(getMachineIdFile(), "utf-8").trim();
19203
19230
  if (!persisted)
19204
19231
  throw new Error("persisted machine identity is empty");
19205
19232
  return persisted;
@@ -19247,7 +19274,7 @@ function getMachineId() {
19247
19274
  machineIdSelection = { id: `${hostname()}-${username}`, source: "fallback" };
19248
19275
  }
19249
19276
  }
19250
- if (!existsSync3(getSecretsFile())) {
19277
+ if (!existsSync4(getSecretsFile())) {
19251
19278
  const persistedId = persistMachineId(machineIdSelection.id);
19252
19279
  machineIdSelection = { id: persistedId, source: "persisted" };
19253
19280
  }
@@ -19346,13 +19373,13 @@ async function resolveMasterKey(store) {
19346
19373
  }
19347
19374
  if (result.state === "found") {
19348
19375
  const nativeKey = decodeKeyringValue(result);
19349
- if (existsSync3(getSecretsFile()))
19376
+ if (existsSync4(getSecretsFile()))
19350
19377
  await migrateLegacyStore(store, await getLegacyMasterKey(), nativeKey);
19351
19378
  return { key: nativeKey, provider: "native-keyring" };
19352
19379
  }
19353
19380
  if (result.state === "missing") {
19354
19381
  const nativeKey = randomBytes(32);
19355
- const legacyKey = existsSync3(getSecretsFile()) ? await getLegacyMasterKey() : undefined;
19382
+ const legacyKey = existsSync4(getSecretsFile()) ? await getLegacyMasterKey() : undefined;
19356
19383
  const saved = await keyring.set(Buffer.from(nativeKey).toString("base64"));
19357
19384
  if (saved.state === "found") {
19358
19385
  if (legacyKey)
@@ -19384,7 +19411,7 @@ async function decryptWithKey(ciphertext, key) {
19384
19411
  return new TextDecoder().decode(message);
19385
19412
  }
19386
19413
  async function anchorLegacyMachineIdAfterVerification(key) {
19387
- if (!machineIdSelection || machineIdSelection.source === "persisted" || existsSync3(getMachineIdFile()) || !existsSync3(getSecretsFile())) {
19414
+ if (!machineIdSelection || machineIdSelection.source === "persisted" || existsSync4(getMachineIdFile()) || !existsSync4(getSecretsFile())) {
19388
19415
  return;
19389
19416
  }
19390
19417
  const store = loadStore();
@@ -19433,11 +19460,11 @@ function cleanupStaleSecretStoreTemps() {
19433
19460
  function loadStore() {
19434
19461
  cleanupStaleSecretStoreTemps();
19435
19462
  const file = getSecretsFile();
19436
- if (!existsSync3(file)) {
19463
+ if (!existsSync4(file)) {
19437
19464
  return { version: 1, secrets: {} };
19438
19465
  }
19439
19466
  try {
19440
- return parseSecretsStore(JSON.parse(readFileSync2(file, "utf-8")));
19467
+ return parseSecretsStore(JSON.parse(readFileSync3(file, "utf-8")));
19441
19468
  } catch (err) {
19442
19469
  const message = err instanceof Error ? err.message : String(err);
19443
19470
  throw new Error(`Failed to read secrets store: ${message}`);
@@ -19503,14 +19530,14 @@ function isSecretStoreLockDirectory() {
19503
19530
  }
19504
19531
  function readSecretStoreLockOwner() {
19505
19532
  try {
19506
- const owner = readFileSync2(getSecretStoreLockOwnerFile(), "utf-8").trim();
19533
+ const owner = readFileSync3(getSecretStoreLockOwnerFile(), "utf-8").trim();
19507
19534
  return owner || null;
19508
19535
  } catch (error) {
19509
19536
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
19510
19537
  return isSecretStoreLockDirectory() ? null : undefined;
19511
19538
  }
19512
19539
  if (error instanceof Error && "code" in error && error.code === "ENOTDIR") {
19513
- const owner = readFileSync2(getSecretStoreLockFile(), "utf-8").trim();
19540
+ const owner = readFileSync3(getSecretStoreLockFile(), "utf-8").trim();
19514
19541
  return owner || null;
19515
19542
  }
19516
19543
  throw error;
@@ -19537,7 +19564,7 @@ function tryAcquireSecretStoreLock(owner) {
19537
19564
  const ownerFile = join4(tempDirectory, SECRET_STORE_LOCK_OWNER_FILE);
19538
19565
  let fd = null;
19539
19566
  try {
19540
- if (existsSync3(`${lockFile}.${SECRET_STORE_LOCK_STALE_CLAIM_FILE}`))
19567
+ if (existsSync4(`${lockFile}.${SECRET_STORE_LOCK_STALE_CLAIM_FILE}`))
19541
19568
  return false;
19542
19569
  mkdirSync2(tempDirectory, { mode: 448 });
19543
19570
  fd = openSync(ownerFile, "wx", 384);
@@ -19662,7 +19689,7 @@ async function acquireSecretStoreLock() {
19662
19689
  const existingOwner = readSecretStoreLockOwner();
19663
19690
  if (existingOwner !== undefined && removeStaleSecretStoreLock(existingOwner))
19664
19691
  continue;
19665
- await new Promise((resolve) => setTimeout(resolve, SECRET_STORE_LOCK_WAIT_MS));
19692
+ await new Promise((resolve2) => setTimeout(resolve2, SECRET_STORE_LOCK_WAIT_MS));
19666
19693
  }
19667
19694
  throw new Error("Timed out waiting for the secrets store lock");
19668
19695
  }
@@ -19679,7 +19706,7 @@ async function putLocalSecret(name, value) {
19679
19706
  const localName = parseLocalSecretName(name);
19680
19707
  const store = loadStore();
19681
19708
  const resolution = await resolveMasterKey(store);
19682
- if (resolution.provider === "legacy-obfuscated" && existsSync3(getSecretsFile()) && !existsSync3(getMachineIdFile()) && machineIdResolverForTests !== null && !machineIdResolverForTests()?.trim()) {
19709
+ if (resolution.provider === "legacy-obfuscated" && existsSync4(getSecretsFile()) && !existsSync4(getMachineIdFile()) && machineIdResolverForTests !== null && !machineIdResolverForTests()?.trim()) {
19683
19710
  throw new Error("Existing secrets store could not be verified: unable to resolve its machine identity");
19684
19711
  }
19685
19712
  await anchorLegacyMachineIdAfterVerification(resolution.key);
@@ -19795,7 +19822,7 @@ function healthForKeyringState(result) {
19795
19822
  function getLocalSecretProviderHealth() {
19796
19823
  try {
19797
19824
  const store = loadStore();
19798
- if (existsSync3(join4(getSecretsDir(), DEGRADED_WARNING_FILE))) {
19825
+ if (existsSync4(join4(getSecretsDir(), DEGRADED_WARNING_FILE))) {
19799
19826
  return {
19800
19827
  status: "degraded",
19801
19828
  message: "Using legacy machine-id-obfuscated secrets encryption because no native keyring is available",
@@ -19886,7 +19913,7 @@ async function execWithSecrets(command, secretRefs, options = {}) {
19886
19913
  envVars: Object.keys(secretRefs),
19887
19914
  timeoutMs
19888
19915
  });
19889
- return new Promise((resolve, reject) => {
19916
+ return new Promise((resolve2, reject) => {
19890
19917
  const useProcessGroup = process.platform !== "win32";
19891
19918
  const proc = spawn(cmd[0], cmd.slice(1), {
19892
19919
  detached: useProcessGroup,
@@ -19985,7 +20012,7 @@ async function execWithSecrets(command, secretRefs, options = {}) {
19985
20012
  secretCount: secretValues.length,
19986
20013
  timedOut
19987
20014
  });
19988
- resolve({
20015
+ resolve2({
19989
20016
  stdout,
19990
20017
  stderr,
19991
20018
  code: finalCode,
@@ -20292,7 +20319,7 @@ function resolveNetworkBinding(mode) {
20292
20319
  };
20293
20320
  }
20294
20321
  // src/harness-config.ts
20295
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
20322
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
20296
20323
  import { join as join5 } from "node:path";
20297
20324
 
20298
20325
  // src/yaml.ts
@@ -20323,10 +20350,10 @@ var CONFIG_FILES = ["agent.yaml", "AGENT.yaml", "config.yaml"];
20323
20350
  function loadConfiguredHarnesses(agentsDir) {
20324
20351
  for (const name of CONFIG_FILES) {
20325
20352
  const path = join5(agentsDir, name);
20326
- if (!existsSync4(path))
20353
+ if (!existsSync5(path))
20327
20354
  continue;
20328
20355
  try {
20329
- const parsed = parseSimpleYaml(readFileSync3(path, "utf-8"));
20356
+ const parsed = parseSimpleYaml(readFileSync4(path, "utf-8"));
20330
20357
  if (!isRecord4(parsed))
20331
20358
  return [];
20332
20359
  return parseHarnessList(parsed.harnesses);
@@ -20767,18 +20794,18 @@ class StreamingMemoryContextScrubber {
20767
20794
  import { randomUUID as randomUUID2 } from "node:crypto";
20768
20795
  import {
20769
20796
  closeSync as closeSync2,
20770
- existsSync as existsSync5,
20797
+ existsSync as existsSync6,
20771
20798
  fsyncSync as fsyncSync2,
20772
20799
  mkdirSync as mkdirSync3,
20773
20800
  openSync as openSync2,
20774
- readFileSync as readFileSync4,
20801
+ readFileSync as readFileSync5,
20775
20802
  renameSync as renameSync2,
20776
20803
  rmSync,
20777
20804
  statSync as statSync3,
20778
20805
  writeSync
20779
20806
  } from "node:fs";
20780
20807
  import { homedir as homedir4 } from "node:os";
20781
- import { dirname as dirname3, join as join7, resolve } from "node:path";
20808
+ import { dirname as dirname3, join as join7, resolve as resolve2 } from "node:path";
20782
20809
  var defaultWorkspaceFileSystem = {
20783
20810
  closeSync: closeSync2,
20784
20811
  fsyncSync: fsyncSync2,
@@ -20790,7 +20817,7 @@ var defaultWorkspaceFileSystem = {
20790
20817
  var WORKSPACE_ENV_KEYS = ["SIGNET_PATH", "SIGNET_WORKSPACE"];
20791
20818
  var DEFAULT_AGENTS_DIRNAME = ".agents";
20792
20819
  function normalizeWorkspacePath(pathValue, home = homedir4()) {
20793
- return resolve(expandHome(pathValue.trim(), home));
20820
+ return resolve2(expandHome(pathValue.trim(), home));
20794
20821
  }
20795
20822
  function readTrimmedEnv(env, name) {
20796
20823
  const value = env[name];
@@ -20822,11 +20849,11 @@ function getWorkspaceConfigPath(env = process.env, home = homedir4()) {
20822
20849
  function readConfiguredWorkspacePath(env = process.env, home = homedir4(), options = {}) {
20823
20850
  const strict = options.strict ?? true;
20824
20851
  const configPath = getWorkspaceConfigPath(env, home);
20825
- if (!existsSync5(configPath))
20852
+ if (!existsSync6(configPath))
20826
20853
  return null;
20827
20854
  let raw;
20828
20855
  try {
20829
- raw = JSON.parse(readFileSync4(configPath, "utf-8"));
20856
+ raw = JSON.parse(readFileSync5(configPath, "utf-8"));
20830
20857
  } catch (err) {
20831
20858
  if (!strict)
20832
20859
  return null;
@@ -20885,7 +20912,7 @@ function writeConfiguredWorkspacePath(pathValue, env = process.env, home = homed
20885
20912
  }
20886
20913
  function clearConfiguredWorkspacePath(env = process.env) {
20887
20914
  const configPath = getWorkspaceConfigPath(env);
20888
- if (!existsSync5(configPath))
20915
+ if (!existsSync6(configPath))
20889
20916
  return;
20890
20917
  rmSync(configPath, { force: true });
20891
20918
  }
@@ -20920,6 +20947,50 @@ function resolveWorkspacePath(options = {}) {
20920
20947
  configuredPath: configValue
20921
20948
  };
20922
20949
  }
20950
+ function preflightWorkspace(options = {}) {
20951
+ const env = options.env ?? process.env;
20952
+ const home = options.home ?? homedir4();
20953
+ let resolution;
20954
+ try {
20955
+ resolution = resolveWorkspacePath({ ...options, strict: true });
20956
+ } catch (error) {
20957
+ const detail = error instanceof Error ? error.message : String(error);
20958
+ return {
20959
+ path: join7(home, DEFAULT_AGENTS_DIRNAME),
20960
+ source: "default",
20961
+ configPath: getWorkspaceConfigPath(env, home),
20962
+ configuredPath: null,
20963
+ status: "incomplete",
20964
+ reasons: [detail]
20965
+ };
20966
+ }
20967
+ const reasons = [];
20968
+ const hasExplicitConfiguration = resolution.source === "env" || resolution.configuredPath !== null;
20969
+ if (!isExistingDirectory(resolution.path)) {
20970
+ if (hasExplicitConfiguration) {
20971
+ reasons.push("configured workspace directory is missing");
20972
+ return { ...resolution, status: "missing", reasons };
20973
+ }
20974
+ return { ...resolution, status: "fresh", reasons };
20975
+ }
20976
+ const hasAgentConfig = existsSync6(join7(resolution.path, "agent.yaml")) || existsSync6(join7(resolution.path, "config.yaml"));
20977
+ const hasMemoryDb = existsSync6(join7(resolution.path, "memory", "memories.db"));
20978
+ if (hasAgentConfig && hasMemoryDb) {
20979
+ return { ...resolution, status: "ready", reasons };
20980
+ }
20981
+ if (!hasExplicitConfiguration && !hasAgentConfig && !hasMemoryDb) {
20982
+ return { ...resolution, status: "fresh", reasons };
20983
+ }
20984
+ if (!hasAgentConfig)
20985
+ reasons.push("workspace configuration is missing (agent.yaml or config.yaml)");
20986
+ if (!hasMemoryDb)
20987
+ reasons.push("workspace database is missing (memory/memories.db)");
20988
+ return { ...resolution, status: "incomplete", reasons };
20989
+ }
20990
+ function formatWorkspacePreflightError(preflight) {
20991
+ const detail = preflight.reasons.length > 0 ? ` ${preflight.reasons.join("; ")}.` : "";
20992
+ return `Signet cannot start: ${preflight.status} workspace at ${preflight.path}.${detail} Restore the configured workspace or run explicit setup; Signet will not recreate it.`;
20993
+ }
20923
20994
  function resolveEnvWorkspace(env, home, requireExisting) {
20924
20995
  for (const key of WORKSPACE_ENV_KEYS) {
20925
20996
  const raw = readTrimmedEnv(env, key);
@@ -21766,9 +21837,9 @@ var SIGNET_PLUGIN_REGISTRY_DIR = ".daemon/plugins";
21766
21837
  var SIGNET_PLUGIN_REGISTRY_FILE = "registry-v1.json";
21767
21838
  var SIGNET_PLUGIN_REGISTRY_VERSION = 1;
21768
21839
  // src/graphiq.ts
21769
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync5, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
21840
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
21770
21841
  import { homedir as homedir5 } from "node:os";
21771
- import { dirname as dirname4, join as join8, resolve as resolve2 } from "node:path";
21842
+ import { dirname as dirname4, join as join8, resolve as resolve3 } from "node:path";
21772
21843
  var SIGNET_GRAPHIQ_STATE_FILE = ".daemon/graphiq/state.json";
21773
21844
  var GRAPHIQ_SYNCED_VERSION = "4.3.3";
21774
21845
  var GRAPHIQ_DEFAULT_INSTALL_DIR = join8(homedir5(), ".local", "bin");
@@ -21776,7 +21847,7 @@ function getGraphiqStatePath(basePath) {
21776
21847
  return join8(basePath, SIGNET_GRAPHIQ_STATE_FILE);
21777
21848
  }
21778
21849
  function getGraphiqProjectDbPath(projectPath) {
21779
- return join8(resolve2(projectPath), ".graphiq", "graphiq.db");
21850
+ return join8(resolve3(projectPath), ".graphiq", "graphiq.db");
21780
21851
  }
21781
21852
  function emptyGraphiqState(now = new Date) {
21782
21853
  return {
@@ -21789,10 +21860,10 @@ function emptyGraphiqState(now = new Date) {
21789
21860
  }
21790
21861
  function readGraphiqState(basePath) {
21791
21862
  const path = getGraphiqStatePath(basePath);
21792
- if (!existsSync6(path))
21863
+ if (!existsSync7(path))
21793
21864
  return emptyGraphiqState();
21794
21865
  try {
21795
- const parsed = JSON.parse(readFileSync5(path, "utf-8"));
21866
+ const parsed = JSON.parse(readFileSync6(path, "utf-8"));
21796
21867
  return parseGraphiqState(parsed);
21797
21868
  } catch {
21798
21869
  return emptyGraphiqState();
@@ -21846,7 +21917,7 @@ function setGraphiqActiveProject(basePath, activeProject) {
21846
21917
  function updateGraphiqActiveProject(basePath, input) {
21847
21918
  const current = readGraphiqState(basePath);
21848
21919
  const indexedAt = input.indexedAt ?? new Date;
21849
- const projectPath = resolve2(input.projectPath);
21920
+ const projectPath = resolve3(input.projectPath);
21850
21921
  const project = {
21851
21922
  path: projectPath,
21852
21923
  dbPath: getGraphiqProjectDbPath(projectPath),
@@ -21934,8 +22005,8 @@ function isRecord6(value) {
21934
22005
  }
21935
22006
  // src/workspace-source-repo.ts
21936
22007
  import { spawn as spawn2, spawnSync } from "node:child_process";
21937
- import { closeSync as closeSync3, existsSync as existsSync7, mkdirSync as mkdirSync5, openSync as openSync3, readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
21938
- import { join as join9, resolve as resolve3 } from "node:path";
22008
+ import { closeSync as closeSync3, existsSync as existsSync8, mkdirSync as mkdirSync5, openSync as openSync3, readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
22009
+ import { join as join9, resolve as resolve4 } from "node:path";
21939
22010
  var SIGNET_SOURCE_CHECKOUT_DIRNAME = "signetai";
21940
22011
  var SIGNET_SOURCE_REMOTE_URL = "https://github.com/Signet-AI/signetai.git";
21941
22012
  var DEFAULT_GIT_TIMEOUT_MS = 60000;
@@ -21943,7 +22014,7 @@ var SOURCE_REPO_SYNC_LOCK_FILENAME = "source-repo-sync.lock";
21943
22014
  var SOURCE_REPO_SYNC_LOCK_STALE_MS = 5 * 60000;
21944
22015
  var SOURCE_REPO_SYNC_LOCK_WAIT_MS = 15000;
21945
22016
  function resolveWorkspaceSourceRepoPath(workspaceDir, repoDirName = SIGNET_SOURCE_CHECKOUT_DIRNAME) {
21946
- return join9(resolve3(workspaceDir), repoDirName);
22017
+ return join9(resolve4(workspaceDir), repoDirName);
21947
22018
  }
21948
22019
  function syncWorkspaceSourceRepo(workspaceDir, options = {}) {
21949
22020
  const timeoutMs = options.gitTimeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
@@ -21992,7 +22063,7 @@ async function syncWorkspaceSourceRepoAsync(workspaceDir, options = {}) {
21992
22063
  }
21993
22064
  }
21994
22065
  function syncWorkspaceSourceRepoLocked(run, workspaceDir, repoPath, remoteUrl, timeoutMs) {
21995
- if (!existsSync7(repoPath) || isEmptyDirectory(repoPath)) {
22066
+ if (!existsSync8(repoPath) || isEmptyDirectory(repoPath)) {
21996
22067
  const workspaceReady = ensureWorkspaceDir(workspaceDir);
21997
22068
  if (workspaceReady.ok === false) {
21998
22069
  return errorResult(repoPath, workspaceReady.message);
@@ -22087,7 +22158,7 @@ function runGit(args, cwd, timeoutMs) {
22087
22158
  };
22088
22159
  }
22089
22160
  async function runGitAsync(args, cwd, timeoutMs) {
22090
- return await new Promise((resolve4) => {
22161
+ return await new Promise((resolve5) => {
22091
22162
  const proc = spawn2("git", args, {
22092
22163
  cwd,
22093
22164
  stdio: ["ignore", "pipe", "pipe"],
@@ -22108,7 +22179,7 @@ async function runGitAsync(args, cwd, timeoutMs) {
22108
22179
  clearTimeout(killTimer);
22109
22180
  if (fallbackTimer)
22110
22181
  clearTimeout(fallbackTimer);
22111
- resolve4(result);
22182
+ resolve5(result);
22112
22183
  };
22113
22184
  const timer = setTimeout(() => {
22114
22185
  stderr += `
@@ -22156,10 +22227,10 @@ function killGitProcessTree(proc, signal) {
22156
22227
  } catch {}
22157
22228
  }
22158
22229
  function hasGitMetadata(path) {
22159
- return existsSync7(join9(path, ".git"));
22230
+ return existsSync8(join9(path, ".git"));
22160
22231
  }
22161
22232
  function isEmptyDirectory(path) {
22162
- if (!existsSync7(path)) {
22233
+ if (!existsSync8(path)) {
22163
22234
  return true;
22164
22235
  }
22165
22236
  try {
@@ -22238,7 +22309,7 @@ function readErrorCode(err) {
22238
22309
  return typeof maybeErrno.code === "string" ? maybeErrno.code : null;
22239
22310
  }
22240
22311
  function sourceRepoSyncLockPath(workspaceDir) {
22241
- return join9(resolve3(workspaceDir), ".daemon", SOURCE_REPO_SYNC_LOCK_FILENAME);
22312
+ return join9(resolve4(workspaceDir), ".daemon", SOURCE_REPO_SYNC_LOCK_FILENAME);
22242
22313
  }
22243
22314
  function clearStaleSourceRepoSyncLock(path) {
22244
22315
  try {
@@ -22304,7 +22375,7 @@ function releaseSourceRepoSyncLock(lock) {
22304
22375
  rmSync3(lock.path, { force: true });
22305
22376
  }
22306
22377
  async function sleep(ms) {
22307
- await new Promise((resolve4) => setTimeout(resolve4, ms));
22378
+ await new Promise((resolve5) => setTimeout(resolve5, ms));
22308
22379
  }
22309
22380
  function unsafeRemoteResult(repoPath) {
22310
22381
  return {
@@ -22343,7 +22414,7 @@ function sourceRepoSyncLockErrorResult(repoPath, detail) {
22343
22414
  };
22344
22415
  }
22345
22416
  function ensureDaemonDir(workspaceDir) {
22346
- const daemonDir = join9(resolve3(workspaceDir), ".daemon");
22417
+ const daemonDir = join9(resolve4(workspaceDir), ".daemon");
22347
22418
  try {
22348
22419
  mkdirSync5(daemonDir, { recursive: true });
22349
22420
  return { ok: true };
@@ -22670,9 +22741,9 @@ function escapeRegExp(value) {
22670
22741
  }
22671
22742
  // src/sources-config.ts
22672
22743
  import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
22673
- import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync4, rmSync as rmSync4, statSync as statSync5, writeFileSync as writeFileSync5 } from "node:fs";
22744
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync4, statSync as statSync5, writeFileSync as writeFileSync5 } from "node:fs";
22674
22745
  import { homedir as homedir6, platform as platform2 } from "node:os";
22675
- import { basename, dirname as dirname5, resolve as resolve4 } from "node:path";
22746
+ import { basename, dirname as dirname5, resolve as resolve5 } from "node:path";
22676
22747
  var DEFAULT_OBSIDIAN_EXCLUDE_GLOBS = [
22677
22748
  "**/.obsidian/**",
22678
22749
  "**/.trash/**",
@@ -22711,11 +22782,11 @@ function saveSourcesConfig(config, agentsDir = getAgentsDir2()) {
22711
22782
  }
22712
22783
  function loadSourcesConfigForWrite(agentsDir = getAgentsDir2()) {
22713
22784
  const path = getSourcesConfigPath(agentsDir);
22714
- if (!existsSync8(path))
22785
+ if (!existsSync9(path))
22715
22786
  return emptyConfig();
22716
22787
  let parsed;
22717
22788
  try {
22718
- parsed = JSON.parse(readFileSync6(path, "utf8"));
22789
+ parsed = JSON.parse(readFileSync7(path, "utf8"));
22719
22790
  } catch (err) {
22720
22791
  const detail = err instanceof Error ? err.message : String(err);
22721
22792
  throw new Error(`Sources config is not readable JSON; refusing to overwrite ${path}: ${detail}`);
@@ -22737,12 +22808,46 @@ function normalizeSourceEntry(source) {
22737
22808
  function addObsidianSource(input, agentsDir = getAgentsDir2()) {
22738
22809
  return withSourcesConfigLock(agentsDir, () => addObsidianSourceUnlocked(input, agentsDir));
22739
22810
  }
22811
+ function addWebSource(input, agentsDir = getAgentsDir2()) {
22812
+ return withSourcesConfigLock(agentsDir, () => addWebSourceUnlocked(input, agentsDir));
22813
+ }
22740
22814
  function addDiscordSource(input, agentsDir = getAgentsDir2()) {
22741
22815
  return withSourcesConfigLock(agentsDir, () => addDiscordSourceUnlocked(input, agentsDir));
22742
22816
  }
22743
22817
  function addGitHubSource(input, agentsDir = getAgentsDir2()) {
22744
22818
  return withSourcesConfigLock(agentsDir, () => addGitHubSourceUnlocked(input, agentsDir));
22745
22819
  }
22820
+ function addWebSourceUnlocked(input, agentsDir = getAgentsDir2()) {
22821
+ try {
22822
+ const url = normalizePublicWebUrl(input.url);
22823
+ if (!url)
22824
+ return { ok: false, error: "Web page URL must be a public http(s) URL" };
22825
+ const now = input.now ?? new Date().toISOString();
22826
+ const config = loadSourcesConfigForWrite(agentsDir);
22827
+ const sourceId = `web:${createHash4("sha256").update(url).digest("hex").slice(0, 16)}`;
22828
+ const existing = config.sources.find((source2) => source2.id === sourceId);
22829
+ const source = {
22830
+ id: sourceId,
22831
+ generation: existing?.generation ?? newSourceGeneration(),
22832
+ kind: "web",
22833
+ name: cleanName(input.name) ?? existing?.name ?? new URL(url).hostname,
22834
+ root: url,
22835
+ enabled: true,
22836
+ mode: "read-only",
22837
+ createdAt: existing?.createdAt ?? now,
22838
+ updatedAt: now,
22839
+ providerSettings: { url }
22840
+ };
22841
+ saveSourcesConfig({
22842
+ version: SOURCES_CONFIG_VERSION,
22843
+ sources: existing ? config.sources.map((entry) => entry.id === existing.id ? source : entry) : [...config.sources, source]
22844
+ }, agentsDir);
22845
+ return { ok: true, source, created: !existing };
22846
+ } catch (err) {
22847
+ const detail = err instanceof Error ? err.message : String(err);
22848
+ return { ok: false, error: detail };
22849
+ }
22850
+ }
22746
22851
  function addImportedSource(input, agentsDir = getAgentsDir2()) {
22747
22852
  return withSourcesConfigLock(agentsDir, () => {
22748
22853
  const fileName = input.fileName.trim();
@@ -22932,6 +23037,15 @@ function parseGitHubSettings(raw) {
22932
23037
  maxItemsPerRepo: cleanPositiveInteger(raw?.maxItemsPerRepo, MAX_GITHUB_MAX_ITEMS_PER_REPO) ?? DEFAULT_GITHUB_MAX_ITEMS_PER_REPO
22933
23038
  };
22934
23039
  }
23040
+ function parseWebSettings(raw) {
23041
+ const value = raw?.url;
23042
+ if (typeof value !== "string")
23043
+ throw new Error("Web source has no URL");
23044
+ const url = normalizePublicWebUrl(value);
23045
+ if (!url)
23046
+ throw new Error("Web source URL must be a public http(s) URL");
23047
+ return { url };
23048
+ }
22935
23049
  function buildDiscordSettings(input) {
22936
23050
  if (input.syncMode && !isDiscordSyncMode(input.syncMode))
22937
23051
  return { error: `Unsupported Discord sync mode: ${input.syncMode}` };
@@ -23099,8 +23213,8 @@ function addObsidianSourceChecked(input, agentsDir = getAgentsDir2()) {
23099
23213
  const trimmedRoot = input.root.trim();
23100
23214
  if (!trimmedRoot)
23101
23215
  return { ok: false, error: "Obsidian vault path is required" };
23102
- const root = resolve4(trimmedRoot);
23103
- if (!existsSync8(root))
23216
+ const root = resolve5(trimmedRoot);
23217
+ if (!existsSync9(root))
23104
23218
  return { ok: false, error: `Obsidian vault path does not exist: ${root}` };
23105
23219
  try {
23106
23220
  if (!statSync5(root).isDirectory())
@@ -23227,6 +23341,156 @@ function cleanName(value) {
23227
23341
  const trimmed = value?.trim();
23228
23342
  return trimmed && trimmed.length > 0 ? trimmed : null;
23229
23343
  }
23344
+ function normalizePublicWebUrl(value) {
23345
+ const trimmed = value.trim();
23346
+ if (!trimmed || trimmed.length > 2048)
23347
+ return null;
23348
+ let parsed;
23349
+ try {
23350
+ parsed = new URL(trimmed);
23351
+ } catch {
23352
+ return null;
23353
+ }
23354
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
23355
+ return null;
23356
+ if (parsed.username || parsed.password || !parsed.hostname)
23357
+ return null;
23358
+ const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, "");
23359
+ if (host === "localhost" || host.endsWith(".localhost") || host === "local" || host === "broadcasthost" || host.endsWith(".local") || host.endsWith(".internal") || host.endsWith(".home.arpa") || host.endsWith(".test") || host.endsWith(".invalid") || host === "metadata.google.internal" || host === "metadata.google.com" || isUnsafeWebIp(host))
23360
+ return null;
23361
+ parsed.hostname = host;
23362
+ parsed.hash = "";
23363
+ return parsed.toString();
23364
+ }
23365
+ var NON_GLOBAL_IPV4_RANGES = [
23366
+ [0, 16777215],
23367
+ [167772160, 184549375],
23368
+ [1681915904, 1686110207],
23369
+ [2130706432, 2147483647],
23370
+ [2851995648, 2852061183],
23371
+ [2886729728, 2887778303],
23372
+ [3221225472, 3221225727],
23373
+ [3221225984, 3221226239],
23374
+ [3223307264, 3223307519],
23375
+ [3224682752, 3224683007],
23376
+ [3227017984, 3227018239],
23377
+ [3232235520, 3232301055],
23378
+ [3232706560, 3232706815],
23379
+ [3323068416, 3323199487],
23380
+ [3325256704, 3325256959],
23381
+ [3405803776, 3405804031],
23382
+ [3758096384, 4294967295]
23383
+ ];
23384
+ var NON_GLOBAL_IPV6_RANGES = [
23385
+ ["::", 96],
23386
+ ["::ffff:0:0", 96],
23387
+ ["100::", 64],
23388
+ ["100:0:0:1::", 64],
23389
+ ["2001::", 23],
23390
+ ["2001:0::", 32],
23391
+ ["2001:1::", 32],
23392
+ ["2001:2::", 48],
23393
+ ["2001:3::", 32],
23394
+ ["2001:4:112::", 48],
23395
+ ["2001:8::", 32],
23396
+ ["2001:10::", 28],
23397
+ ["2001:20::", 28],
23398
+ ["2001:30::", 28],
23399
+ ["2001:db8::", 32],
23400
+ ["3fff::", 20],
23401
+ ["64:ff9b::", 96],
23402
+ ["64:ff9b:1::", 48],
23403
+ ["2620:4f:8000::", 48],
23404
+ ["fc00::", 7],
23405
+ ["fe80::", 10],
23406
+ ["fec0::", 10],
23407
+ ["ff00::", 8]
23408
+ ];
23409
+ function isUnsafeWebIp(host) {
23410
+ if (/^[0-9.]+$/.test(host)) {
23411
+ const address = parseIpv4Address(host);
23412
+ return address === null || isNonGlobalIpv4(address);
23413
+ }
23414
+ if (host.includes(":")) {
23415
+ const address = parseIpv6Address(host);
23416
+ return address === null || isNonGlobalIpv6(address);
23417
+ }
23418
+ return false;
23419
+ }
23420
+ function parseIpv4Address(host) {
23421
+ const octets = host.split(".");
23422
+ if (octets.length !== 4)
23423
+ return null;
23424
+ let address = 0;
23425
+ for (const octet of octets) {
23426
+ if (!/^\d{1,3}$/.test(octet))
23427
+ return null;
23428
+ const value = Number(octet);
23429
+ if (value > 255)
23430
+ return null;
23431
+ address = address * 256 + value;
23432
+ }
23433
+ return address;
23434
+ }
23435
+ function isNonGlobalIpv4(address) {
23436
+ return NON_GLOBAL_IPV4_RANGES.some(([start, end]) => address >= start && address <= end);
23437
+ }
23438
+ function parseIpv6Address(host) {
23439
+ const normalized = host.toLowerCase();
23440
+ if (normalized.includes("%"))
23441
+ return null;
23442
+ const sections = normalized.split("::");
23443
+ if (sections.length > 2)
23444
+ return null;
23445
+ const head = sections[0] ? parseIpv6Sections(sections[0].split(":"), sections.length === 1) : [];
23446
+ const tail = sections.length === 2 && sections[1] ? parseIpv6Sections(sections[1].split(":"), true) : [];
23447
+ if (head === null || tail === null)
23448
+ return null;
23449
+ const words = sections.length === 2 ? [...head, ...Array.from({ length: 8 - head.length - tail.length }, () => 0), ...tail] : [...head];
23450
+ if (words.length !== 8)
23451
+ return null;
23452
+ return words.reduce((address, word) => address * 0x10000n + BigInt(word), 0n);
23453
+ }
23454
+ function parseIpv6Sections(sections, allowIpv4Tail) {
23455
+ const words = [];
23456
+ for (const [index, section] of sections.entries()) {
23457
+ if (section.includes(".")) {
23458
+ if (!allowIpv4Tail || index !== sections.length - 1)
23459
+ return null;
23460
+ const ipv4 = parseIpv4Address(section);
23461
+ if (ipv4 === null)
23462
+ return null;
23463
+ words.push(Math.floor(ipv4 / 65536), ipv4 % 65536);
23464
+ continue;
23465
+ }
23466
+ if (!/^[0-9a-f]{1,4}$/.test(section))
23467
+ return null;
23468
+ words.push(Number.parseInt(section, 16));
23469
+ }
23470
+ return words;
23471
+ }
23472
+ function isNonGlobalIpv6(address) {
23473
+ const globalUnicastStart = 0x20000000000000000000000000000000n;
23474
+ const globalUnicastEnd = 0x3fffffffffffffffffffffffffffffffn;
23475
+ if (address < globalUnicastStart || address > globalUnicastEnd)
23476
+ return true;
23477
+ if (NON_GLOBAL_IPV6_RANGES.some(([network, prefix]) => matchesIpv6Cidr(address, network, prefix)))
23478
+ return true;
23479
+ if (matchesIpv6Cidr(address, "2002::", 16)) {
23480
+ const embeddedIpv4 = Number(address >> 80n & 0xffffffffn);
23481
+ if (isNonGlobalIpv4(embeddedIpv4))
23482
+ return true;
23483
+ }
23484
+ return false;
23485
+ }
23486
+ function matchesIpv6Cidr(address, network, prefix) {
23487
+ const parsedNetwork = parseIpv6Address(network);
23488
+ if (parsedNetwork === null)
23489
+ return false;
23490
+ const hostBits = 128 - prefix;
23491
+ const mask = (1n << 128n) - 1n ^ (1n << BigInt(hostBits)) - 1n;
23492
+ return (address & mask) === (parsedNetwork & mask);
23493
+ }
23230
23494
  function cleanExcludeGlobs(values) {
23231
23495
  if (!values)
23232
23496
  return null;
@@ -23241,7 +23505,7 @@ function cleanDiscordChannelFilter(values) {
23241
23505
  }
23242
23506
  function cleanLocalPath(value) {
23243
23507
  const trimmed = value?.trim();
23244
- return trimmed ? resolve4(trimmed.replace(/^~(?=$|\/|\\)/, homedir6())) : undefined;
23508
+ return trimmed ? resolve5(trimmed.replace(/^~(?=$|\/|\\)/, homedir6())) : undefined;
23245
23509
  }
23246
23510
  function cleanGitHubRepos(values) {
23247
23511
  return Array.from(new Set(values.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean)));
@@ -23289,11 +23553,11 @@ function isDiscordSyncMode(value) {
23289
23553
  function defaultDiscordDesktopCachePath() {
23290
23554
  switch (platform2()) {
23291
23555
  case "darwin":
23292
- return resolve4(homedir6(), "Library", "Application Support", "discord");
23556
+ return resolve5(homedir6(), "Library", "Application Support", "discord");
23293
23557
  case "win32":
23294
- return resolve4(process.env.APPDATA || resolve4(homedir6(), "AppData", "Roaming"), "discord");
23558
+ return resolve5(process.env.APPDATA || resolve5(homedir6(), "AppData", "Roaming"), "discord");
23295
23559
  default:
23296
- return resolve4(process.env.XDG_CONFIG_HOME || resolve4(homedir6(), ".config"), "discord");
23560
+ return resolve5(process.env.XDG_CONFIG_HOME || resolve5(homedir6(), ".config"), "discord");
23297
23561
  }
23298
23562
  }
23299
23563
  function looksLikeDiscordDesktopCacheRoot(value) {
@@ -23352,7 +23616,7 @@ function isJsonValue(value) {
23352
23616
  var SOURCE_CHUNK_SOURCE_TYPE = "source_chunk";
23353
23617
  var LEGACY_OBSIDIAN_CHUNK_SOURCE_TYPE = "source_obsidian_chunk";
23354
23618
  // src/export.ts
23355
- import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
23619
+ import { existsSync as existsSync10, readFileSync as readFileSync8, readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
23356
23620
  import { join as join10 } from "node:path";
23357
23621
  function recordImportedMemoryContentSafety(db, memoryId, content) {
23358
23622
  if (db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get("memory_content_safety") == null) {
@@ -23381,14 +23645,14 @@ var IDENTITY_FILE_NAMES = [
23381
23645
  function collectExportData(agentsDir, db, options = {}) {
23382
23646
  let agentYaml = null;
23383
23647
  const yamlPath = join10(agentsDir, "agent.yaml");
23384
- if (existsSync9(yamlPath)) {
23385
- agentYaml = readFileSync7(yamlPath, "utf-8");
23648
+ if (existsSync10(yamlPath)) {
23649
+ agentYaml = readFileSync8(yamlPath, "utf-8");
23386
23650
  }
23387
23651
  const identityFiles = [];
23388
23652
  for (const name of IDENTITY_FILE_NAMES) {
23389
23653
  const path = join10(agentsDir, name);
23390
- if (existsSync9(path)) {
23391
- identityFiles.push({ name, content: readFileSync7(path, "utf-8") });
23654
+ if (existsSync10(path)) {
23655
+ identityFiles.push({ name, content: readFileSync8(path, "utf-8") });
23392
23656
  }
23393
23657
  }
23394
23658
  const memories = db.prepare(`SELECT id, content, type, category, confidence, source_type,
@@ -23407,7 +23671,7 @@ function collectExportData(agentsDir, db, options = {}) {
23407
23671
  const skills = [];
23408
23672
  if (options.includeSkills !== false) {
23409
23673
  const skillsDir = join10(agentsDir, "skills");
23410
- if (existsSync9(skillsDir)) {
23674
+ if (existsSync10(skillsDir)) {
23411
23675
  try {
23412
23676
  const entries = readdirSync4(skillsDir, { withFileTypes: true });
23413
23677
  for (const entry of entries) {
@@ -23453,7 +23717,7 @@ function collectSkillFiles(dir, prefix, out) {
23453
23717
  if (stat.size > 1e6)
23454
23718
  continue;
23455
23719
  try {
23456
- out.push({ path: relPath, content: readFileSync7(fullPath, "utf-8") });
23720
+ out.push({ path: relPath, content: readFileSync8(fullPath, "utf-8") });
23457
23721
  } catch {}
23458
23722
  }
23459
23723
  }
@@ -23588,14 +23852,14 @@ function importRelations(db, relationsJsonl) {
23588
23852
  }
23589
23853
  // src/identity.ts
23590
23854
  import { execFileSync as execFileSync3 } from "node:child_process";
23591
- import { existsSync as existsSync12, readFileSync as readFileSync10, readdirSync as readdirSync5, realpathSync, statSync as statSync7 } from "node:fs";
23855
+ import { existsSync as existsSync13, readFileSync as readFileSync11, readdirSync as readdirSync5, realpathSync, statSync as statSync7 } from "node:fs";
23592
23856
  import { homedir as homedir9 } from "node:os";
23593
23857
  import { dirname as dirname8, join as join13 } from "node:path";
23594
23858
 
23595
23859
  // src/oh-my-pi.ts
23596
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync8, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
23860
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync9, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
23597
23861
  import { homedir as homedir7 } from "node:os";
23598
- import { dirname as dirname6, join as join11, resolve as resolve5 } from "node:path";
23862
+ import { dirname as dirname6, join as join11, resolve as resolve6 } from "node:path";
23599
23863
  function readTrimmed(env, name) {
23600
23864
  const raw = env[name];
23601
23865
  if (typeof raw !== "string")
@@ -23604,7 +23868,7 @@ function readTrimmed(env, name) {
23604
23868
  return trimmed.length > 0 ? trimmed : null;
23605
23869
  }
23606
23870
  function normalizePath(pathValue) {
23607
- return resolve5(expandHome(pathValue.trim()));
23871
+ return resolve6(expandHome(pathValue.trim()));
23608
23872
  }
23609
23873
  function readConfigHome2(env) {
23610
23874
  const configured = readTrimmed(env, "XDG_CONFIG_HOME");
@@ -23615,10 +23879,10 @@ function getOhMyPiConfigPath(env = process.env) {
23615
23879
  }
23616
23880
  function readConfiguredOhMyPiAgentDir(env = process.env) {
23617
23881
  const configPath = getOhMyPiConfigPath(env);
23618
- if (!existsSync10(configPath))
23882
+ if (!existsSync11(configPath))
23619
23883
  return null;
23620
23884
  try {
23621
- const raw = JSON.parse(readFileSync8(configPath, "utf-8"));
23885
+ const raw = JSON.parse(readFileSync9(configPath, "utf-8"));
23622
23886
  if (typeof raw !== "object" || raw === null)
23623
23887
  return null;
23624
23888
  const agentDir = Reflect.get(raw, "agentDir");
@@ -23650,7 +23914,7 @@ function listOhMyPiAgentDirCandidates(env = process.env) {
23650
23914
  function writeConfiguredOhMyPiAgentDir(pathValue, env = process.env) {
23651
23915
  const agentDir = normalizePath(pathValue);
23652
23916
  const configPath = getOhMyPiConfigPath(env);
23653
- if (readConfiguredOhMyPiAgentDir(env) === agentDir && existsSync10(configPath)) {
23917
+ if (readConfiguredOhMyPiAgentDir(env) === agentDir && existsSync11(configPath)) {
23654
23918
  return configPath;
23655
23919
  }
23656
23920
  mkdirSync7(dirname6(configPath), { recursive: true });
@@ -23665,7 +23929,7 @@ function writeConfiguredOhMyPiAgentDir(pathValue, env = process.env) {
23665
23929
  }
23666
23930
  function clearConfiguredOhMyPiAgentDir(env = process.env) {
23667
23931
  const configPath = getOhMyPiConfigPath(env);
23668
- if (!existsSync10(configPath))
23932
+ if (!existsSync11(configPath))
23669
23933
  return;
23670
23934
  try {
23671
23935
  rmSync5(configPath, { force: true });
@@ -23673,9 +23937,9 @@ function clearConfiguredOhMyPiAgentDir(env = process.env) {
23673
23937
  }
23674
23938
 
23675
23939
  // src/pi.ts
23676
- import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync9, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
23940
+ import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync10, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
23677
23941
  import { homedir as homedir8 } from "node:os";
23678
- import { dirname as dirname7, join as join12, resolve as resolve6 } from "node:path";
23942
+ import { dirname as dirname7, join as join12, resolve as resolve7 } from "node:path";
23679
23943
  function readTrimmed2(env, name) {
23680
23944
  const raw = env[name];
23681
23945
  if (typeof raw !== "string")
@@ -23694,7 +23958,7 @@ function expandUserPath(pathValue) {
23694
23958
  return trimmed;
23695
23959
  }
23696
23960
  function normalizePath2(pathValue) {
23697
- return resolve6(expandUserPath(pathValue));
23961
+ return resolve7(expandUserPath(pathValue));
23698
23962
  }
23699
23963
  function readConfigHome3(env) {
23700
23964
  const configured = readTrimmed2(env, "XDG_CONFIG_HOME");
@@ -23705,10 +23969,10 @@ function getPiConfigPath(env = process.env) {
23705
23969
  }
23706
23970
  function readConfiguredPiAgentDir(env = process.env) {
23707
23971
  const configPath = getPiConfigPath(env);
23708
- if (!existsSync11(configPath))
23972
+ if (!existsSync12(configPath))
23709
23973
  return null;
23710
23974
  try {
23711
- const raw = JSON.parse(readFileSync9(configPath, "utf-8"));
23975
+ const raw = JSON.parse(readFileSync10(configPath, "utf-8"));
23712
23976
  if (typeof raw !== "object" || raw === null)
23713
23977
  return null;
23714
23978
  const agentDir = Reflect.get(raw, "agentDir");
@@ -23740,7 +24004,7 @@ function listPiAgentDirCandidates(env = process.env) {
23740
24004
  function writeConfiguredPiAgentDir(pathValue, env = process.env) {
23741
24005
  const agentDir = normalizePath2(pathValue);
23742
24006
  const configPath = getPiConfigPath(env);
23743
- if (readConfiguredPiAgentDir(env) === agentDir && existsSync11(configPath)) {
24007
+ if (readConfiguredPiAgentDir(env) === agentDir && existsSync12(configPath)) {
23744
24008
  return configPath;
23745
24009
  }
23746
24010
  mkdirSync8(dirname7(configPath), { recursive: true });
@@ -23755,7 +24019,7 @@ function writeConfiguredPiAgentDir(pathValue, env = process.env) {
23755
24019
  }
23756
24020
  function clearConfiguredPiAgentDir(env = process.env) {
23757
24021
  const configPath = getPiConfigPath(env);
23758
- if (!existsSync11(configPath))
24022
+ if (!existsSync12(configPath))
23759
24023
  return;
23760
24024
  try {
23761
24025
  rmSync6(configPath, { force: true });
@@ -23874,10 +24138,10 @@ function isSignetManagedOhMyPiInstall() {
23874
24138
  const extensionsDir = join13(agentDir, "extensions");
23875
24139
  for (const filename of [OH_MY_PI_MANAGED_EXTENSION_FILENAME, OH_MY_PI_LEGACY_MANAGED_EXTENSION_FILENAME]) {
23876
24140
  const extensionPath = join13(extensionsDir, filename);
23877
- if (!existsSync12(extensionPath))
24141
+ if (!existsSync13(extensionPath))
23878
24142
  continue;
23879
24143
  try {
23880
- const content = readFileSync10(extensionPath, "utf8");
24144
+ const content = readFileSync11(extensionPath, "utf8");
23881
24145
  if (content.includes(OH_MY_PI_MANAGED_MARKER))
23882
24146
  return true;
23883
24147
  } catch {}
@@ -23890,10 +24154,10 @@ function isSignetManagedPiInstall() {
23890
24154
  const extensionsDir = join13(agentDir, "extensions");
23891
24155
  for (const filename of [PI_MANAGED_EXTENSION_FILENAME, PI_LEGACY_MANAGED_EXTENSION_FILENAME]) {
23892
24156
  const extensionPath = join13(extensionsDir, filename);
23893
- if (!existsSync12(extensionPath))
24157
+ if (!existsSync13(extensionPath))
23894
24158
  continue;
23895
24159
  try {
23896
- const content = readFileSync10(extensionPath, "utf8");
24160
+ const content = readFileSync11(extensionPath, "utf8");
23897
24161
  if (content.includes(PI_MANAGED_MARKER))
23898
24162
  return true;
23899
24163
  } catch {}
@@ -23913,15 +24177,15 @@ function resolveKimiHomePath() {
23913
24177
  return legacyOverride;
23914
24178
  const currentHome = join13(userHome(), ".kimi");
23915
24179
  const legacyHome = join13(userHome(), ".kimi-code");
23916
- if (existsSync12(currentHome))
24180
+ if (existsSync13(currentHome))
23917
24181
  return currentHome;
23918
- if (existsSync12(legacyHome))
24182
+ if (existsSync13(legacyHome))
23919
24183
  return legacyHome;
23920
24184
  return currentHome;
23921
24185
  }
23922
24186
  function isBinaryOnPath(bin) {
23923
24187
  const separator = process.platform === "win32" ? ";" : ":";
23924
- return (process.env.PATH ?? "").split(separator).some((directory) => directory.length > 0 && existsSync12(join13(directory, bin)));
24188
+ return (process.env.PATH ?? "").split(separator).some((directory) => directory.length > 0 && existsSync13(join13(directory, bin)));
23925
24189
  }
23926
24190
  var HERMES_PROFILE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
23927
24191
  function resolveHermesHomePath() {
@@ -23955,11 +24219,11 @@ function hermesAgentCandidateDirs() {
23955
24219
  }
23956
24220
  function resolveHermesRepoPath() {
23957
24221
  const hermesRepo = process.env.HERMES_REPO?.trim();
23958
- if (hermesRepo && existsSync12(join13(hermesRepo, "plugins", "memory"))) {
24222
+ if (hermesRepo && existsSync13(join13(hermesRepo, "plugins", "memory"))) {
23959
24223
  return hermesRepo;
23960
24224
  }
23961
24225
  for (const base of hermesAgentCandidateDirs()) {
23962
- if (existsSync12(join13(base, "plugins", "memory")))
24226
+ if (existsSync13(join13(base, "plugins", "memory")))
23963
24227
  return base;
23964
24228
  }
23965
24229
  try {
@@ -23970,7 +24234,7 @@ function resolveHermesRepoPath() {
23970
24234
  }).trim();
23971
24235
  if (hermesPath) {
23972
24236
  const repoDir = dirname8(realpathSync(hermesPath));
23973
- if (existsSync12(join13(repoDir, "plugins", "memory")))
24237
+ if (existsSync13(join13(repoDir, "plugins", "memory")))
23974
24238
  return repoDir;
23975
24239
  }
23976
24240
  } catch {}
@@ -23981,7 +24245,7 @@ function resolveHermesRepoPluginPath() {
23981
24245
  const hermesRepo = resolveHermesRepoPath();
23982
24246
  if (hermesRepo !== null) {
23983
24247
  const candidate = join13(hermesRepo, pluginFile);
23984
- if (existsSync12(candidate))
24248
+ if (existsSync13(candidate))
23985
24249
  return candidate;
23986
24250
  }
23987
24251
  return null;
@@ -23990,13 +24254,13 @@ function detectExistingSetup(basePath) {
23990
24254
  const identityFileNames = Object.values(IDENTITY_FILES).map((spec) => spec.path);
23991
24255
  const foundFiles = [];
23992
24256
  for (const fileName of identityFileNames) {
23993
- if (existsSync12(join13(basePath, fileName))) {
24257
+ if (existsSync13(join13(basePath, fileName))) {
23994
24258
  foundFiles.push(fileName);
23995
24259
  }
23996
24260
  }
23997
24261
  const memoryDir = join13(basePath, "memory");
23998
24262
  let memoryLogCount = 0;
23999
- if (existsSync12(memoryDir)) {
24263
+ if (existsSync13(memoryDir)) {
24000
24264
  try {
24001
24265
  const files = readdirSync5(memoryDir);
24002
24266
  memoryLogCount = files.filter((f2) => f2.endsWith(".md") && !f2.startsWith("TEMPLATE")).length;
@@ -24005,27 +24269,27 @@ function detectExistingSetup(basePath) {
24005
24269
  const home = homedir9();
24006
24270
  return {
24007
24271
  basePath,
24008
- agentsDir: existsSync12(basePath),
24009
- agentYaml: existsSync12(join13(basePath, "agent.yaml")),
24010
- agentsMd: existsSync12(join13(basePath, "AGENTS.md")),
24011
- configYaml: existsSync12(join13(basePath, "config.yaml")),
24012
- memoryDb: existsSync12(join13(basePath, "memory", "memories.db")),
24272
+ agentsDir: existsSync13(basePath),
24273
+ agentYaml: existsSync13(join13(basePath, "agent.yaml")),
24274
+ agentsMd: existsSync13(join13(basePath, "AGENTS.md")),
24275
+ configYaml: existsSync13(join13(basePath, "config.yaml")),
24276
+ memoryDb: existsSync13(join13(basePath, "memory", "memories.db")),
24013
24277
  identityFiles: foundFiles,
24014
- hasMemoryDir: existsSync12(memoryDir),
24278
+ hasMemoryDir: existsSync13(memoryDir),
24015
24279
  memoryLogCount,
24016
- hasClawdhub: existsSync12(join13(basePath, ".clawdhub", "lock.json")),
24017
- hasClaudeSkills: existsSync12(join13(home, ".claude", "skills")),
24280
+ hasClawdhub: existsSync13(join13(basePath, ".clawdhub", "lock.json")),
24281
+ hasClaudeSkills: existsSync13(join13(home, ".claude", "skills")),
24018
24282
  harnesses: {
24019
- claudeCode: existsSync12(join13(home, ".claude", "settings.json")),
24020
- openclaw: existsSync12(join13(home, ".openclaw", "openclaw.json")) || existsSync12(join13(home, ".clawdbot", "clawdbot.json")),
24021
- opencode: existsSync12(join13(home, ".config", "opencode", "config.json")),
24022
- forge: existsSync12(join13(home, ".forge", ".mcp.json")) || existsSync12(join13(home, "forge", ".mcp.json")) || existsSync12(join13(home, ".forge", ".forge.toml")) || existsSync12(join13(home, "forge", ".forge.toml")),
24023
- codex: existsSync12(join13(home, ".codex", "config.toml")) || existsSync12(join13(home, ".config", "signet", "bin", "codex")),
24024
- kimi: existsSync12(join13(resolveKimiHomePath(), "config.toml")) || existsSync12(join13(home, ".kimi-code", "config.toml")) || isBinaryOnPath("kimi"),
24025
- ohMyPi: isSignetManagedOhMyPiInstall() || existsSync12(resolveOhMyPiAgentDir()),
24026
- pi: isSignetManagedPiInstall() || existsSync12(resolvePiAgentDir()),
24283
+ claudeCode: existsSync13(join13(home, ".claude", "settings.json")),
24284
+ openclaw: existsSync13(join13(home, ".openclaw", "openclaw.json")) || existsSync13(join13(home, ".clawdbot", "clawdbot.json")),
24285
+ opencode: existsSync13(join13(home, ".config", "opencode", "config.json")),
24286
+ forge: existsSync13(join13(home, ".forge", ".mcp.json")) || existsSync13(join13(home, "forge", ".mcp.json")) || existsSync13(join13(home, ".forge", ".forge.toml")) || existsSync13(join13(home, "forge", ".forge.toml")),
24287
+ codex: existsSync13(join13(home, ".codex", "config.toml")) || existsSync13(join13(home, ".config", "signet", "bin", "codex")),
24288
+ kimi: existsSync13(join13(resolveKimiHomePath(), "config.toml")) || existsSync13(join13(home, ".kimi-code", "config.toml")) || isBinaryOnPath("kimi"),
24289
+ ohMyPi: isSignetManagedOhMyPiInstall() || existsSync13(resolveOhMyPiAgentDir()),
24290
+ pi: isSignetManagedPiInstall() || existsSync13(resolvePiAgentDir()),
24027
24291
  hermesAgent: resolveHermesRepoPath() !== null,
24028
- gemini: existsSync12(join13(home, ".gemini", "settings.json"))
24292
+ gemini: existsSync13(join13(home, ".gemini", "settings.json"))
24029
24293
  }
24030
24294
  };
24031
24295
  }
@@ -24033,9 +24297,9 @@ async function loadIdentityFiles(basePath) {
24033
24297
  const result = {};
24034
24298
  for (const [key, spec] of Object.entries(IDENTITY_FILES)) {
24035
24299
  const filePath = join13(basePath, spec.path);
24036
- if (existsSync12(filePath)) {
24300
+ if (existsSync13(filePath)) {
24037
24301
  try {
24038
- const content = readFileSync10(filePath, "utf-8");
24302
+ const content = readFileSync11(filePath, "utf-8");
24039
24303
  const stats = statSync7(filePath);
24040
24304
  result[key] = {
24041
24305
  path: spec.path,
@@ -24058,9 +24322,9 @@ function loadIdentityFilesSync(basePath) {
24058
24322
  const result = {};
24059
24323
  for (const [key, spec] of Object.entries(IDENTITY_FILES)) {
24060
24324
  const filePath = join13(basePath, spec.path);
24061
- if (existsSync12(filePath)) {
24325
+ if (existsSync13(filePath)) {
24062
24326
  try {
24063
- const content = readFileSync10(filePath, "utf-8");
24327
+ const content = readFileSync11(filePath, "utf-8");
24064
24328
  const stats = statSync7(filePath);
24065
24329
  result[key] = {
24066
24330
  path: spec.path,
@@ -24084,7 +24348,7 @@ function hasValidIdentity(basePath) {
24084
24348
  if (mode !== "managed")
24085
24349
  return true;
24086
24350
  for (const path of resolveRequiredIdentityPaths(basePath)) {
24087
- if (!existsSync12(join13(basePath, path))) {
24351
+ if (!existsSync13(join13(basePath, path))) {
24088
24352
  return false;
24089
24353
  }
24090
24354
  }
@@ -24096,7 +24360,7 @@ function getMissingIdentityFiles(basePath) {
24096
24360
  return [];
24097
24361
  const missing = [];
24098
24362
  for (const path of resolveRequiredIdentityPaths(basePath)) {
24099
- if (!existsSync12(join13(basePath, path))) {
24363
+ if (!existsSync13(join13(basePath, path))) {
24100
24364
  missing.push(path);
24101
24365
  }
24102
24366
  }
@@ -24105,10 +24369,10 @@ function getMissingIdentityFiles(basePath) {
24105
24369
  function resolveRequiredIdentityPaths(basePath) {
24106
24370
  const legacyRequired = () => REQUIRED_IDENTITY_KEYS.map((key) => IDENTITY_FILES[key].path);
24107
24371
  const agentYaml = join13(basePath, "agent.yaml");
24108
- if (!existsSync12(agentYaml))
24372
+ if (!existsSync13(agentYaml))
24109
24373
  return legacyRequired();
24110
24374
  try {
24111
- const config = parseSimpleYaml(readFileSync10(agentYaml, "utf-8"));
24375
+ const config = parseSimpleYaml(readFileSync11(agentYaml, "utf-8"));
24112
24376
  const identity = readRecord(readRecord(config).identity);
24113
24377
  const configured = readIdentityEntryList(readRecord(identity.startup).load);
24114
24378
  if (configured.length > 0)
@@ -24166,10 +24430,10 @@ function resolveIdentityModeFromConfig(config) {
24166
24430
  }
24167
24431
  function loadIdentityMode(agentsDir) {
24168
24432
  const agentYaml = join13(agentsDir, "agent.yaml");
24169
- if (!existsSync12(agentYaml))
24433
+ if (!existsSync13(agentYaml))
24170
24434
  return "managed";
24171
24435
  try {
24172
- return resolveIdentityModeFromConfig(parseSimpleYaml(readFileSync10(agentYaml, "utf-8")));
24436
+ return resolveIdentityModeFromConfig(parseSimpleYaml(readFileSync11(agentYaml, "utf-8")));
24173
24437
  } catch {
24174
24438
  return "managed";
24175
24439
  }
@@ -24221,10 +24485,10 @@ function identityHeaderFor(path, role) {
24221
24485
  }
24222
24486
  function resolveStartupIdentityFiles(agentsDir) {
24223
24487
  const agentYaml = join13(agentsDir, "agent.yaml");
24224
- if (!existsSync12(agentYaml))
24488
+ if (!existsSync13(agentYaml))
24225
24489
  return STATIC_BUDGETS.map(({ file, budget }) => ({ path: file, budget }));
24226
24490
  try {
24227
- const config = parseSimpleYaml(readFileSync10(agentYaml, "utf-8"));
24491
+ const config = parseSimpleYaml(readFileSync11(agentYaml, "utf-8"));
24228
24492
  if (!identityModeReadsFiles(resolveIdentityModeFromConfig(config)))
24229
24493
  return [];
24230
24494
  const identity = readRecord(config.identity);
@@ -24241,11 +24505,11 @@ function resolveStartupIdentityFiles(agentsDir) {
24241
24505
  }
24242
24506
  function resolveSpecialIdentityFiles(agentsDir, kind) {
24243
24507
  const agentYaml = join13(agentsDir, "agent.yaml");
24244
- if (!existsSync12(agentYaml)) {
24508
+ if (!existsSync13(agentYaml)) {
24245
24509
  return IDENTITY_PRESETS.minimal.special.filter((entry) => entry.kind === kind);
24246
24510
  }
24247
24511
  try {
24248
- const config = parseSimpleYaml(readFileSync10(agentYaml, "utf-8"));
24512
+ const config = parseSimpleYaml(readFileSync11(agentYaml, "utf-8"));
24249
24513
  if (!identityModeReadsFiles(resolveIdentityModeFromConfig(config)))
24250
24514
  return [];
24251
24515
  const identity = readRecord(config.identity);
@@ -24282,17 +24546,17 @@ function resolvePromptSubmitTimeoutMs(raw) {
24282
24546
  return ms;
24283
24547
  }
24284
24548
  function readStaticIdentity(agentsDir, status = STATIC_IDENTITY_OFFLINE_STATUS) {
24285
- if (!existsSync12(agentsDir))
24549
+ if (!existsSync13(agentsDir))
24286
24550
  return null;
24287
24551
  if (!identityModeReadsFiles(loadIdentityMode(agentsDir)))
24288
24552
  return null;
24289
24553
  const parts = [];
24290
24554
  for (const entry of resolveStartupIdentityFiles(agentsDir)) {
24291
24555
  const path = join13(agentsDir, entry.path);
24292
- if (!existsSync12(path))
24556
+ if (!existsSync13(path))
24293
24557
  continue;
24294
24558
  try {
24295
- const raw = readFileSync10(path, "utf-8").trim();
24559
+ const raw = readFileSync11(path, "utf-8").trim();
24296
24560
  if (!raw)
24297
24561
  continue;
24298
24562
  const budget = entry.budget ?? STATIC_BUDGETS.find((candidate) => candidate.file === entry.path)?.budget ?? 4000;
@@ -24327,7 +24591,7 @@ function summarizeIdentity(identity) {
24327
24591
  `);
24328
24592
  }
24329
24593
  // src/agents.ts
24330
- import { existsSync as existsSync13, mkdirSync as mkdirSync9, readdirSync as readdirSync6, writeFileSync as writeFileSync8 } from "node:fs";
24594
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readdirSync as readdirSync6, writeFileSync as writeFileSync8 } from "node:fs";
24331
24595
  import { join as join14 } from "node:path";
24332
24596
  function resolveAgentMemoryPolicy(readPolicy, policyGroup) {
24333
24597
  if (readPolicy !== "isolated" && readPolicy !== "shared" && readPolicy !== "group") {
@@ -24354,22 +24618,22 @@ var IDENTITY_FILES2 = [
24354
24618
  ];
24355
24619
  function discoverAgents(agentsDir) {
24356
24620
  const root = join14(agentsDir, "agents");
24357
- if (!existsSync13(root))
24621
+ if (!existsSync14(root))
24358
24622
  return [];
24359
24623
  return readdirSync6(root, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => ({ name: d2.name }));
24360
24624
  }
24361
24625
  function scaffoldAgent(name, agentsDir) {
24362
24626
  const dir = join14(agentsDir, "agents", name);
24363
- if (!existsSync13(dir))
24627
+ if (!existsSync14(dir))
24364
24628
  mkdirSync9(dir, { recursive: true });
24365
24629
  const soul = join14(dir, "SOUL.md");
24366
- if (!existsSync13(soul))
24630
+ if (!existsSync14(soul))
24367
24631
  writeFileSync8(soul, `# Soul
24368
24632
 
24369
24633
  Add ${name}'s personality here.
24370
24634
  `);
24371
24635
  const identity = join14(dir, "IDENTITY.md");
24372
- if (!existsSync13(identity))
24636
+ if (!existsSync14(identity))
24373
24637
  writeFileSync8(identity, `# Identity
24374
24638
 
24375
24639
  name: ${name}
@@ -24381,9 +24645,9 @@ function getAgentIdentityFiles(name, agentsDir) {
24381
24645
  for (const file of IDENTITY_FILES2) {
24382
24646
  const specific = join14(agentDir, file);
24383
24647
  const fallback = join14(agentsDir, file);
24384
- if (existsSync13(specific))
24648
+ if (existsSync14(specific))
24385
24649
  result[file] = specific;
24386
- else if (existsSync13(fallback))
24650
+ else if (existsSync14(fallback))
24387
24651
  result[file] = fallback;
24388
24652
  }
24389
24653
  return result;
@@ -24431,12 +24695,12 @@ function resolveAgentSkills(agentDef, allSkills) {
24431
24695
  return allSkills.filter((s2) => allowed.has(s2));
24432
24696
  }
24433
24697
  // src/skills.ts
24434
- import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync11, readdirSync as readdirSync8, statSync as statSync8, writeFileSync as writeFileSync9 } from "node:fs";
24698
+ import { existsSync as existsSync16, mkdirSync as mkdirSync11, readFileSync as readFileSync12, readdirSync as readdirSync8, statSync as statSync8, writeFileSync as writeFileSync9 } from "node:fs";
24435
24699
  import { join as join16 } from "node:path";
24436
24700
  import { homedir as homedir10 } from "node:os";
24437
24701
 
24438
24702
  // src/symlinks.ts
24439
- import { existsSync as existsSync14, lstatSync, mkdirSync as mkdirSync10, readdirSync as readdirSync7, symlinkSync, unlinkSync as unlinkSync2 } from "node:fs";
24703
+ import { existsSync as existsSync15, lstatSync, mkdirSync as mkdirSync10, readdirSync as readdirSync7, symlinkSync, unlinkSync as unlinkSync2 } from "node:fs";
24440
24704
  import { join as join15 } from "node:path";
24441
24705
  function linkDirSync(target, path) {
24442
24706
  const type = process.platform === "win32" ? "junction" : "dir";
@@ -24448,14 +24712,14 @@ function symlinkSkills(sourceDir, targetDir, options = {}) {
24448
24712
  skipped: [],
24449
24713
  errors: []
24450
24714
  };
24451
- if (!existsSync14(sourceDir)) {
24715
+ if (!existsSync15(sourceDir)) {
24452
24716
  return result;
24453
24717
  }
24454
24718
  const targetParent = join15(targetDir, "..");
24455
- if (!existsSync14(targetParent)) {
24719
+ if (!existsSync15(targetParent)) {
24456
24720
  mkdirSync10(targetParent, { recursive: true });
24457
24721
  }
24458
- if (!existsSync14(targetDir)) {
24722
+ if (!existsSync15(targetDir)) {
24459
24723
  mkdirSync10(targetDir, { recursive: true });
24460
24724
  }
24461
24725
  let entries;
@@ -24512,10 +24776,10 @@ function symlinkSkills(sourceDir, targetDir, options = {}) {
24512
24776
  return result;
24513
24777
  }
24514
24778
  function symlinkDir(src, dest, options = {}) {
24515
- if (!existsSync14(src)) {
24779
+ if (!existsSync15(src)) {
24516
24780
  return false;
24517
24781
  }
24518
- if (existsSync14(dest)) {
24782
+ if (existsSync15(dest)) {
24519
24783
  try {
24520
24784
  const stat = lstatSync(dest);
24521
24785
  if (stat.isSymbolicLink()) {
@@ -24544,11 +24808,11 @@ function symlinkDir(src, dest, options = {}) {
24544
24808
  var home = homedir10();
24545
24809
  function loadClawdhubLock(basePath) {
24546
24810
  const lockPath = join16(basePath, ".clawdhub", "lock.json");
24547
- if (!existsSync15(lockPath)) {
24811
+ if (!existsSync16(lockPath)) {
24548
24812
  return null;
24549
24813
  }
24550
24814
  try {
24551
- const content = readFileSync11(lockPath, "utf-8");
24815
+ const content = readFileSync12(lockPath, "utf-8");
24552
24816
  return JSON.parse(content);
24553
24817
  } catch {
24554
24818
  return null;
@@ -24557,10 +24821,10 @@ function loadClawdhubLock(basePath) {
24557
24821
  function symlinkClaudeSkills(basePath) {
24558
24822
  const claudeSkillsDir = join16(home, ".claude", "skills");
24559
24823
  const targetSkillsDir = join16(basePath, "skills");
24560
- if (!existsSync15(claudeSkillsDir)) {
24824
+ if (!existsSync16(claudeSkillsDir)) {
24561
24825
  return { symlinked: 0, skills: [] };
24562
24826
  }
24563
- if (!existsSync15(targetSkillsDir)) {
24827
+ if (!existsSync16(targetSkillsDir)) {
24564
24828
  mkdirSync11(targetSkillsDir, { recursive: true });
24565
24829
  }
24566
24830
  const symlinkedSkills = [];
@@ -24585,7 +24849,7 @@ function symlinkClaudeSkills(basePath) {
24585
24849
  function writeRegistry(basePath, registry) {
24586
24850
  const skillsDir = join16(basePath, "skills");
24587
24851
  const registryPath = join16(skillsDir, "registry.json");
24588
- if (!existsSync15(skillsDir)) {
24852
+ if (!existsSync16(skillsDir)) {
24589
24853
  mkdirSync11(skillsDir, { recursive: true });
24590
24854
  }
24591
24855
  writeFileSync9(registryPath, JSON.stringify(registry, null, 2), "utf-8");
@@ -24624,7 +24888,7 @@ async function unifySkills(basePath, config = {}) {
24624
24888
  }
24625
24889
  }
24626
24890
  const claudeResult = symlinkClaudeSkills(basePath);
24627
- if (claudeResult.symlinked > 0 || existsSync15(join16(home, ".claude", "skills"))) {
24891
+ if (claudeResult.symlinked > 0 || existsSync16(join16(home, ".claude", "skills"))) {
24628
24892
  registry.sources.push({
24629
24893
  type: "claude-code",
24630
24894
  path: join16(home, ".claude", "skills")
@@ -24645,7 +24909,7 @@ async function unifySkills(basePath, config = {}) {
24645
24909
  }
24646
24910
  if (config.registries) {
24647
24911
  for (const reg of config.registries) {
24648
- if (!existsSync15(reg.path)) {
24912
+ if (!existsSync16(reg.path)) {
24649
24913
  continue;
24650
24914
  }
24651
24915
  registry.sources.push({
@@ -24668,7 +24932,7 @@ async function unifySkills(basePath, config = {}) {
24668
24932
  }
24669
24933
  if (reg.symlink) {
24670
24934
  const targetPath = join16(basePath, "skills", entry);
24671
- if (!existsSync15(join16(basePath, "skills"))) {
24935
+ if (!existsSync16(join16(basePath, "skills"))) {
24672
24936
  mkdirSync11(join16(basePath, "skills"), { recursive: true });
24673
24937
  }
24674
24938
  if (symlinkDir(entryPath, targetPath)) {
@@ -24785,7 +25049,7 @@ function parseTranscriptSkills(content) {
24785
25049
  return { records, skipped };
24786
25050
  }
24787
25051
  // src/import.ts
24788
- import { existsSync as existsSync16, readFileSync as readFileSync12, readdirSync as readdirSync9 } from "node:fs";
25052
+ import { existsSync as existsSync17, readFileSync as readFileSync13, readdirSync as readdirSync9 } from "node:fs";
24789
25053
  import { join as join17 } from "node:path";
24790
25054
  var DATE_FILENAME_PATTERN = /^(\d{4}-\d{2}-\d{2})\.md$/;
24791
25055
  function estimateTokens(text) {
@@ -24994,7 +25258,7 @@ function importMemoryLogs(basePath, db) {
24994
25258
  errors: []
24995
25259
  };
24996
25260
  const memoryDir = join17(basePath, "memory");
24997
- if (!existsSync16(memoryDir)) {
25261
+ if (!existsSync17(memoryDir)) {
24998
25262
  result.errors.push(`Memory directory not found: ${memoryDir}`);
24999
25263
  return result;
25000
25264
  }
@@ -25016,7 +25280,7 @@ function importMemoryLogs(basePath, db) {
25016
25280
  }
25017
25281
  let content;
25018
25282
  try {
25019
- content = readFileSync12(filePath, "utf-8");
25283
+ content = readFileSync13(filePath, "utf-8");
25020
25284
  } catch (err) {
25021
25285
  const message = err instanceof Error ? err.message : String(err);
25022
25286
  result.errors.push(`Failed to read file ${file}: ${message}`);
@@ -26225,7 +26489,7 @@ function resolveRoutingDecision(config, request, runtimeSnapshot) {
26225
26489
  });
26226
26490
  }
26227
26491
  // src/pipeline-pause.ts
26228
- import { existsSync as existsSync17, readFileSync as readFileSync13, writeFileSync as writeFileSync10 } from "node:fs";
26492
+ import { existsSync as existsSync18, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
26229
26493
  import { join as join18 } from "node:path";
26230
26494
  var PIPELINE_CONFIG_FILES = ["agent.yaml", "AGENT.yaml", "config.yaml"];
26231
26495
  function isRecord10(value) {
@@ -26234,7 +26498,7 @@ function isRecord10(value) {
26234
26498
  function findPipelineConfigFile(dir) {
26235
26499
  for (const name of PIPELINE_CONFIG_FILES) {
26236
26500
  const file = join18(dir, name);
26237
- if (existsSync17(file)) {
26501
+ if (existsSync18(file)) {
26238
26502
  return file;
26239
26503
  }
26240
26504
  }
@@ -26245,7 +26509,7 @@ function readCfg(dir) {
26245
26509
  if (file === null) {
26246
26510
  return { file: null, cfg: null };
26247
26511
  }
26248
- const parsed = parseSimpleYaml(readFileSync13(file, "utf-8"));
26512
+ const parsed = parseSimpleYaml(readFileSync14(file, "utf-8"));
26249
26513
  return { file, cfg: isRecord10(parsed) ? parsed : {} };
26250
26514
  }
26251
26515
  function readMem(cfg) {
@@ -26298,7 +26562,7 @@ function setPipelinePaused(dir, paused) {
26298
26562
  }
26299
26563
  // src/package-manager.ts
26300
26564
  import { spawnSync as spawnSync2 } from "node:child_process";
26301
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "node:fs";
26565
+ import { existsSync as existsSync19, readFileSync as readFileSync15 } from "node:fs";
26302
26566
  import { homedir as homedir12 } from "node:os";
26303
26567
  import { join as join19 } from "node:path";
26304
26568
 
@@ -26401,10 +26665,10 @@ function readConfiguredPackageManager(agentsDir) {
26401
26665
  return null;
26402
26666
  const configPaths = [join19(agentsDir, "agent.yaml"), join19(agentsDir, "AGENT.yaml"), join19(agentsDir, "config.yaml")];
26403
26667
  for (const path of configPaths) {
26404
- if (!existsSync18(path))
26668
+ if (!existsSync19(path))
26405
26669
  continue;
26406
26670
  try {
26407
- const yaml = parseSimpleYaml(readFileSync14(path, "utf-8"));
26671
+ const yaml = parseSimpleYaml(readFileSync15(path, "utf-8"));
26408
26672
  const install = yaml.install;
26409
26673
  const source = install?.source;
26410
26674
  if (source === "fallback")
@@ -26517,7 +26781,7 @@ function resolveGlobalPackagePath(family, packageName) {
26517
26781
  switch (family) {
26518
26782
  case "bun": {
26519
26783
  const bunGlobal = join19(process.env.BUN_INSTALL ?? join19(homedir12(), ".bun"), "install", "global", "node_modules", packageName);
26520
- if (existsSync18(bunGlobal))
26784
+ if (existsSync19(bunGlobal))
26521
26785
  return bunGlobal;
26522
26786
  return;
26523
26787
  }
@@ -26529,7 +26793,7 @@ function resolveGlobalPackagePath(family, packageName) {
26529
26793
  });
26530
26794
  if (result.status === 0 && result.stdout.trim()) {
26531
26795
  const candidate = join19(result.stdout.trim(), packageName);
26532
- if (existsSync18(candidate))
26796
+ if (existsSync19(candidate))
26533
26797
  return candidate;
26534
26798
  }
26535
26799
  return;
@@ -26542,7 +26806,7 @@ function resolveGlobalPackagePath(family, packageName) {
26542
26806
  });
26543
26807
  if (result.status === 0 && result.stdout.trim()) {
26544
26808
  const candidate = join19(result.stdout.trim(), packageName);
26545
- if (existsSync18(candidate))
26809
+ if (existsSync19(candidate))
26546
26810
  return candidate;
26547
26811
  }
26548
26812
  return;
@@ -26562,12 +26826,12 @@ function resolveGlobalPackagePath(family, packageName) {
26562
26826
  });
26563
26827
  if (result.status === 0 && result.stdout.trim()) {
26564
26828
  const candidate = join19(result.stdout.trim(), "node_modules", packageName);
26565
- if (existsSync18(candidate))
26829
+ if (existsSync19(candidate))
26566
26830
  return candidate;
26567
26831
  }
26568
26832
  } else {
26569
26833
  const berryGlobal = join19(process.env.YARN_GLOBAL_FOLDER ?? join19(homedir12(), ".yarn", "berry", "global"), "node_modules", packageName);
26570
- if (existsSync18(berryGlobal))
26834
+ if (existsSync19(berryGlobal))
26571
26835
  return berryGlobal;
26572
26836
  }
26573
26837
  return;
@@ -26590,7 +26854,7 @@ function getGlobalInstallCommand(family, packageName) {
26590
26854
  }
26591
26855
  }
26592
26856
  // src/signet-installation.ts
26593
- import { existsSync as existsSync19, realpathSync as realpathSync2 } from "node:fs";
26857
+ import { existsSync as existsSync20, realpathSync as realpathSync2 } from "node:fs";
26594
26858
  import { homedir as homedir13 } from "node:os";
26595
26859
  import { posix as posix2, win32 as win322 } from "node:path";
26596
26860
  var PACKAGE_MANAGERS = ["npm", "pnpm", "bun", "yarn"];
@@ -26653,7 +26917,7 @@ function detectSignetInstallations(options = {}) {
26653
26917
  const home2 = options.home ?? homedir13();
26654
26918
  const platform3 = options.platform ?? process.platform;
26655
26919
  const activeExecutablePath = options.execPath ?? process.execPath;
26656
- const pathExists = options.exists ?? existsSync19;
26920
+ const pathExists = options.exists ?? existsSync20;
26657
26921
  const realpath = options.realpath ?? realpathSync2;
26658
26922
  const activeRealPath = safeRealpath(activeExecutablePath, platform3, realpath);
26659
26923
  const signetDir = env.SIGNET_DIR?.trim();
@@ -26823,8 +27087,10 @@ export {
26823
27087
  readConfiguredPiAgentDir,
26824
27088
  readConfiguredOhMyPiAgentDir,
26825
27089
  putLocalSecret,
27090
+ preflightWorkspace,
26826
27091
  partitionRecallRows,
26827
27092
  parseYamlDocument,
27093
+ parseWebSettings,
26828
27094
  parseTranscriptSkills,
26829
27095
  parseSoul,
26830
27096
  parseSimpleYaml,
@@ -26843,6 +27109,7 @@ export {
26843
27109
  normalizeWorkspacePath,
26844
27110
  normalizeStructuredMemoryPayload,
26845
27111
  normalizeSecretExecTimeoutMs,
27112
+ normalizePublicWebUrl,
26846
27113
  normalizePromptContext,
26847
27114
  normalizeNetworkMode,
26848
27115
  normalizeLoopbackHost,
@@ -26908,6 +27175,7 @@ export {
26908
27175
  generateMemory,
26909
27176
  generateManifest,
26910
27177
  formatYaml,
27178
+ formatWorkspacePreflightError,
26911
27179
  formatRecallText,
26912
27180
  findSqliteVecExtension,
26913
27181
  findPipelineConfigFile,
@@ -26951,6 +27219,7 @@ export {
26951
27219
  assessMemoryContent,
26952
27220
  applyRecallScoreThreshold,
26953
27221
  allTargetRefs,
27222
+ addWebSource,
26954
27223
  addObsidianSource,
26955
27224
  addImportedSource,
26956
27225
  addGitHubSource,