@abelxiaoxing/cadence 2.0.7 → 2.0.8

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.
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
3
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
4
4
 
5
5
  // src/service/host.ts
6
- import { lstatSync as lstatSync10, opendirSync as opendirSync3 } from "node:fs";
6
+ import { lstatSync as lstatSync11, opendirSync as opendirSync3 } from "node:fs";
7
7
  import { join as join18 } from "node:path";
8
8
 
9
9
  // src/agent-registry.ts
@@ -14800,6 +14800,7 @@ function localOrigin(policy, actualPort) {
14800
14800
  }
14801
14801
 
14802
14802
  // src/service/server-config.ts
14803
+ import { lstatSync as lstatSync8, realpathSync as realpathSync3, statSync } from "node:fs";
14803
14804
  import { dirname as dirname7, join as join10 } from "node:path";
14804
14805
 
14805
14806
  // skills/_shared/load-config.mjs
@@ -14845,8 +14846,38 @@ function accessToken(value) {
14845
14846
  throw new ContractError("invalid");
14846
14847
  return result;
14847
14848
  }
14849
+ class ServerConfigRefusal extends ContractError {
14850
+ path;
14851
+ reason;
14852
+ constructor(path, reason) {
14853
+ super("corrupt-selected");
14854
+ this.path = path;
14855
+ this.reason = reason;
14856
+ }
14857
+ }
14858
+
14859
+ class Unusable extends Error {
14860
+ }
14861
+ var unusable = (reason) => {
14862
+ throw new Unusable(reason);
14863
+ };
14864
+ function syntax(error) {
14865
+ const message = error instanceof Error ? error.message : "";
14866
+ const line = /at line (\d+)$/.exec(message)?.[1];
14867
+ if (!line)
14868
+ return "is not in KEY=value lines";
14869
+ if (message.startsWith("Invalid configuration name"))
14870
+ return `has an invalid name on line ${line} (letters, digits and _ only, no "export")`;
14871
+ if (message.startsWith("Unterminated"))
14872
+ return `has an unterminated quote on line ${line}`;
14873
+ return `has no KEY=value setting on line ${line}`;
14874
+ }
14848
14875
  function settings(source) {
14849
- parseEnvFile(source);
14876
+ try {
14877
+ parseEnvFile(source);
14878
+ } catch (error) {
14879
+ unusable(`${syntax(error)}, which the research skills refuse too`);
14880
+ }
14850
14881
  const parts = source.split(/(\r\n|\r|\n)/);
14851
14882
  const found = {};
14852
14883
  for (let at = 0;at < parts.length; at += 2) {
@@ -14858,53 +14889,103 @@ function settings(source) {
14858
14889
  const name = key2 === PORT_KEY ? "port" : key2 === TOKEN_KEY ? "token" : undefined;
14859
14890
  if (!name)
14860
14891
  continue;
14861
- if (found[name])
14862
- throw new ContractError("invalid");
14892
+ const previous = found[name];
14893
+ if (previous)
14894
+ unusable(`sets ${key2} twice (lines ${previous.line} and ${at / 2 + 1}); keep one`);
14863
14895
  let value = line.slice(separator + 1).trim();
14864
14896
  if (value[0] === '"' || value[0] === "'")
14865
14897
  value = value.slice(1, -1);
14866
- found[name] = { at, value };
14898
+ found[name] = { at, line: at / 2 + 1, value };
14867
14899
  }
14868
14900
  return { parts, ...found };
14869
14901
  }
14870
- function decodeServerConfig(source) {
14902
+ function decode(source) {
14871
14903
  const { port, token } = settings(source);
14872
- if (!port || !/^[1-9][0-9]{0,4}$/.test(port.value))
14873
- throw new ContractError("invalid");
14904
+ if (!port)
14905
+ unusable(`has no ${PORT_KEY} line`);
14874
14906
  if (!token)
14875
- throw new ContractError("invalid");
14876
- return {
14877
- port: integer(Number(port.value), 1, 65535),
14878
- token: accessToken(token.value)
14879
- };
14907
+ unusable(`has no ${TOKEN_KEY} line`);
14908
+ const p = port, t = token;
14909
+ const number = Number(p.value);
14910
+ if (!/^[1-9][0-9]{0,4}$/.test(p.value) || number > 65535)
14911
+ unusable(`has ${PORT_KEY} on line ${p.line} that is not a whole number from 1 to 65535`);
14912
+ try {
14913
+ return { port: number, token: accessToken(t.value) };
14914
+ } catch {
14915
+ return unusable(`has ${TOKEN_KEY} on line ${t.line} shorter than 32 characters or with control characters`);
14916
+ }
14880
14917
  }
14881
-
14882
- class ServerConfigRefusal extends ContractError {
14883
- path;
14884
- constructor(path) {
14885
- super("corrupt-selected");
14886
- this.path = path;
14918
+ var code = (error) => error?.code ?? "error";
14919
+ function locate(path) {
14920
+ let real;
14921
+ try {
14922
+ real = realpathSync3(path);
14923
+ } catch (error) {
14924
+ if (code(error) !== "ENOENT")
14925
+ unusable(`cannot be read (${code(error)})`);
14926
+ let link = false;
14927
+ try {
14928
+ link = lstatSync8(path).isSymbolicLink();
14929
+ } catch {}
14930
+ return unusable(link ? "is a link to a file that does not exist" : "does not exist");
14931
+ }
14932
+ return { real, files: new PrivateFiles(dirname7(real), false) };
14933
+ }
14934
+ function explain(real) {
14935
+ const uid = process.getuid?.();
14936
+ try {
14937
+ const st = lstatSync8(real);
14938
+ if (!st.isFile())
14939
+ return "is not a regular file";
14940
+ if (uid !== undefined && st.uid !== uid)
14941
+ return "is not owned by you";
14942
+ if (uid !== undefined && lstatSync8(dirname7(real)).uid !== uid)
14943
+ return `is in ${dirname7(real)}, which is not owned by you`;
14944
+ if (st.nlink !== 1)
14945
+ return "has more than one hard link";
14946
+ if (st.size > CONFIG_BYTES)
14947
+ return "is larger than 64 KiB";
14948
+ return "changed while Cadence read it; try again";
14949
+ } catch (error) {
14950
+ return `cannot be read (${code(error)})`;
14951
+ }
14952
+ }
14953
+ function load(path) {
14954
+ const { real, files } = locate(path);
14955
+ let snapshot;
14956
+ try {
14957
+ snapshot = files.read(real, CONFIG_BYTES);
14958
+ } catch {
14959
+ return unusable(explain(real));
14960
+ }
14961
+ if (!snapshot)
14962
+ return unusable("does not exist");
14963
+ let source;
14964
+ try {
14965
+ source = decoded(snapshot);
14966
+ } catch {
14967
+ return unusable("is not UTF-8 text");
14887
14968
  }
14969
+ return { path, real, files, snapshot, source };
14888
14970
  }
14889
14971
  function decoded(snapshot) {
14890
14972
  return new TextDecoder("utf-8", { fatal: true }).decode(snapshot.bytes);
14891
14973
  }
14892
- function readServerConfig(path) {
14974
+ function refusing(path, read2) {
14893
14975
  try {
14894
- const files = new PrivateFiles(dirname7(path));
14895
- const snapshot = files.read(path, CONFIG_BYTES);
14896
- if (!snapshot)
14897
- throw new ContractError("corrupt-selected");
14898
- return {
14899
- path,
14900
- config: decodeServerConfig(decoded(snapshot)),
14901
- files,
14902
- snapshot
14903
- };
14904
- } catch {
14905
- throw new ServerConfigRefusal(path);
14976
+ return read2();
14977
+ } catch (error) {
14978
+ if (error instanceof ServerConfigRefusal)
14979
+ throw error;
14980
+ throw new ServerConfigRefusal(path, error instanceof Unusable ? error.message : `cannot be read (${code(error)})`);
14906
14981
  }
14907
14982
  }
14983
+ function readServerConfig(path) {
14984
+ return refusing(path, () => {
14985
+ const file = load(path);
14986
+ return { ...file, config: decode(file.source) };
14987
+ });
14988
+ }
14908
14989
  function withToken(file, token) {
14909
14990
  const { parts, token: line } = settings(decoded(file.snapshot));
14910
14991
  if (!line)
@@ -15142,7 +15223,7 @@ class AccessMaterial {
15142
15223
  if (this.config.path && this.external && this.externalFile)
15143
15224
  this.externalFile = this.external.replace(this.config.path, this.externalFile, secret, TOKEN_BYTES);
15144
15225
  if (configured)
15145
- configured.files.replace(configured.path, configured.snapshot, withToken(configured, secret), CONFIG_BYTES);
15226
+ configured.files.replace(configured.real, configured.snapshot, withToken(configured, secret), CONFIG_BYTES);
15146
15227
  const record2 = {
15147
15228
  ...this.record,
15148
15229
  generation,
@@ -15483,7 +15564,7 @@ class AuthNetwork {
15483
15564
 
15484
15565
  // src/service/coordination.ts
15485
15566
  import { randomBytes as randomBytes4, randomUUID as randomUUID8 } from "node:crypto";
15486
- import { opendirSync as opendirSync2, realpathSync as realpathSync3 } from "node:fs";
15567
+ import { opendirSync as opendirSync2, realpathSync as realpathSync4 } from "node:fs";
15487
15568
  import { hostname as hostname2 } from "node:os";
15488
15569
  import { dirname as dirname9, isAbsolute as isAbsolute5, join as join12, relative as relative4, sep as sep4 } from "node:path";
15489
15570
  var registrationKeys = [
@@ -15641,7 +15722,7 @@ class ServiceCoordination {
15641
15722
  const o = closed(json(snapshot, REGISTRY_BYTES), ["schema", "entries"]);
15642
15723
  const entries = list(o.entries, REGISTRY_ENTRIES, decodeReservation);
15643
15724
  for (const [i, row] of entries.entries()) {
15644
- if (row.stateHome !== this.stateHome || realpathSync3(row.root) !== row.root)
15725
+ if (row.stateHome !== this.stateHome || realpathSync4(row.root) !== row.root)
15645
15726
  refused();
15646
15727
  if (entries.slice(0, i).some((other) => rootsOverlap(row.root, other.root) || row.endpoint === other.endpoint))
15647
15728
  refused();
@@ -16320,10 +16401,10 @@ function decodeSocketInput(value) {
16320
16401
  }
16321
16402
 
16322
16403
  // src/service/http.ts
16323
- function refusal(code = "invalid", uncertain = false) {
16404
+ function refusal(code2 = "invalid", uncertain = false) {
16324
16405
  return {
16325
16406
  kind: "error",
16326
- error: publicError(code, uncertain ? "uncertain" : "none")
16407
+ error: publicError(code2, uncertain ? "uncertain" : "none")
16327
16408
  };
16328
16409
  }
16329
16410
  function fixedHeaders(response) {
@@ -16727,9 +16808,9 @@ Content-Length: 0\r
16727
16808
  if (res.headersSent)
16728
16809
  res.destroy();
16729
16810
  else {
16730
- const code = e instanceof ContractError ? e.code : "unavailable";
16811
+ const code2 = e instanceof ContractError ? e.code : "unavailable";
16731
16812
  res.setHeader("Connection", "close");
16732
- send(res, errorStatus(code), refusal(code, dispatched));
16813
+ send(res, errorStatus(code2), refusal(code2, dispatched));
16733
16814
  }
16734
16815
  } finally {
16735
16816
  clearTimeout(timer);
@@ -17205,7 +17286,7 @@ class OwnerModelChoice {
17205
17286
  }
17206
17287
 
17207
17288
  // src/service/model-config.ts
17208
- import { lstatSync as lstatSync8, realpathSync as realpathSync4 } from "node:fs";
17289
+ import { lstatSync as lstatSync9, realpathSync as realpathSync5 } from "node:fs";
17209
17290
  import { dirname as dirname10, isAbsolute as isAbsolute6, join as join13, resolve as resolve3 } from "node:path";
17210
17291
  var CONFIG_BYTES2 = 1024 * 1024;
17211
17292
  var ENTRY_LIMIT = 256;
@@ -17279,8 +17360,8 @@ function piSource(agentDir, home, cwd, env) {
17279
17360
  if (selected2 === "~" || selected2.startsWith("~/"))
17280
17361
  selected2 = home + selected2.slice(1);
17281
17362
  selected2 = resolve3(cwd, selected2);
17282
- const directory = join13(realpathSync4(dirname10(selected2)), selected2.slice(dirname10(selected2).length + 1));
17283
- if (!lstatSync8(directory).isDirectory() || lstatSync8(directory).isSymbolicLink())
17363
+ const directory = join13(realpathSync5(dirname10(selected2)), selected2.slice(dirname10(selected2).length + 1));
17364
+ if (!lstatSync9(directory).isDirectory() || lstatSync9(directory).isSymbolicLink())
17284
17365
  refuse2();
17285
17366
  const files = new PrivateFiles(directory, false);
17286
17367
  if (!files.directory(directory))
@@ -18789,8 +18870,8 @@ function decodeHostInput(value) {
18789
18870
  class StartupRefusal extends ContractError {
18790
18871
  stage;
18791
18872
  quarantined;
18792
- constructor(code, stage, quarantined = false) {
18793
- super(code);
18873
+ constructor(code2, stage, quarantined = false) {
18874
+ super(code2);
18794
18875
  this.stage = stage;
18795
18876
  this.quarantined = quarantined;
18796
18877
  }
@@ -18811,12 +18892,12 @@ function startupReport(error) {
18811
18892
 
18812
18893
  // src/service/task-actions.ts
18813
18894
  import { randomUUID as randomUUID15 } from "node:crypto";
18814
- import { realpathSync as realpathSync5 } from "node:fs";
18895
+ import { realpathSync as realpathSync6 } from "node:fs";
18815
18896
 
18816
18897
  // src/task-diff.ts
18817
18898
  import { spawnSync as spawnSync2 } from "node:child_process";
18818
18899
  import { createHash as createHash20 } from "node:crypto";
18819
- import { lstatSync as lstatSync9, readdirSync as readdirSync3, readlinkSync } from "node:fs";
18900
+ import { lstatSync as lstatSync10, readdirSync as readdirSync3, readlinkSync } from "node:fs";
18820
18901
  import { join as join15, relative as relative5 } from "node:path";
18821
18902
  var admin = (path) => path === ".cadence/assistant/tasks" || path.startsWith(".cadence/assistant/tasks/");
18822
18903
  function captureChanges(root) {
@@ -18859,7 +18940,7 @@ function captureChanges(root) {
18859
18940
  }
18860
18941
  try {
18861
18942
  const path = join15(root, name);
18862
- const st = lstatSync9(path);
18943
+ const st = lstatSync10(path);
18863
18944
  add(name, `${st.mode}:${st.size}`);
18864
18945
  if (st.isSymbolicLink()) {
18865
18946
  add(name, readlinkSync(path));
@@ -19003,7 +19084,7 @@ ${data2.toString("utf8")}`);
19003
19084
  break;
19004
19085
  }
19005
19086
  try {
19006
- const st = lstatSync9(path);
19087
+ const st = lstatSync10(path);
19007
19088
  if (st.isDirectory())
19008
19089
  walk(path, depth + 1);
19009
19090
  else
@@ -20291,8 +20372,8 @@ function terminateWindowsTree(pid, fallback) {
20291
20372
  const root = process.env.SystemRoot;
20292
20373
  const taskkill = spawn(root ? join17(root, "System32", "taskkill.exe") : "taskkill.exe", ["/F", "/T", "/PID", String(pid)], { stdio: "ignore", windowsHide: true });
20293
20374
  taskkill.once("error", fallback);
20294
- taskkill.once("close", (code) => {
20295
- if (code !== 0)
20375
+ taskkill.once("close", (code2) => {
20376
+ if (code2 !== 0)
20296
20377
  fallback();
20297
20378
  });
20298
20379
  }
@@ -20554,7 +20635,7 @@ function runProcess(spec) {
20554
20635
  child.on("error", () => {
20555
20636
  stopping = "failed";
20556
20637
  });
20557
- child.on("close", (code, signal) => {
20638
+ child.on("close", (code2, signal) => {
20558
20639
  nativeClosed = true;
20559
20640
  clearTimeout(timeout);
20560
20641
  clearTimeout(killTimer);
@@ -20570,7 +20651,7 @@ function runProcess(spec) {
20570
20651
  }
20571
20652
  }
20572
20653
  output += stderrDecoder.end();
20573
- finish(true, code, signal);
20654
+ finish(true, code2, signal);
20574
20655
  };
20575
20656
  if (spec.checkRecording) {
20576
20657
  Promise.all([stdoutWork, stderrWork]).then(async () => {
@@ -21823,9 +21904,9 @@ class TaskActions {
21823
21904
  selection: structuredClone(options.selection),
21824
21905
  ownerSecrets: [...options.ownerSecrets]
21825
21906
  };
21826
- this.cwd = realpathSync5(options.cwd);
21907
+ this.cwd = realpathSync6(options.cwd);
21827
21908
  const config = readHostConfig(options.host.coordination);
21828
- if (!config || realpathSync5(config.cwd) !== this.cwd)
21909
+ if (!config || realpathSync6(config.cwd) !== this.cwd)
21829
21910
  throw new ContractError("unsupported-context");
21830
21911
  this.launchCwd = config.cwd;
21831
21912
  this.checkEnvironment = options.host.checkEnvironment;
@@ -21941,7 +22022,7 @@ class TaskActions {
21941
22022
  if (this.closed || this.options.host.owner.state !== "idle" || this.options.host.writer.quarantined)
21942
22023
  throw new ContractError("quarantine");
21943
22024
  this.options.host.owner.lease.assert();
21944
- if (!this.sources.current() || realpathSync5(this.cwd) !== this.cwd || realpathSync5(this.launchCwd) !== this.cwd || this.options.host.checkEnvironment !== this.checkEnvironment)
22025
+ if (!this.sources.current() || realpathSync6(this.cwd) !== this.cwd || realpathSync6(this.launchCwd) !== this.cwd || this.options.host.checkEnvironment !== this.checkEnvironment)
21945
22026
  throw new ContractError("stale");
21946
22027
  }
21947
22028
  choiceSnapshot() {
@@ -22059,7 +22140,7 @@ class TaskActions {
22059
22140
  const selected2 = taskId ? h.coordination.store.loadSnapshot(taskId) : null;
22060
22141
  if (taskId && !selected2)
22061
22142
  throw new ContractError("stale");
22062
- if (selected2 && realpathSync5(selected2.record.cwd) !== this.cwd)
22143
+ if (selected2 && realpathSync6(selected2.record.cwd) !== this.cwd)
22063
22144
  throw new ContractError("unsupported-context");
22064
22145
  const secrets = this.viewSecrets();
22065
22146
  const roles = this.sources.roles.map(({ role: role2, sha256 }) => ({
@@ -22563,7 +22644,7 @@ class TaskActions {
22563
22644
  this.assertChoice(expected);
22564
22645
  held.assertHeld();
22565
22646
  const actual = h.coordination.store.loadSnapshot(task.id), want = published ?? task;
22566
- if (!actual || actual.identity !== want.identity || actual.record.revision !== want.revision || realpathSync5(actual.record.cwd) !== this.cwd || this.generation !== expected.checkoutGeneration || h.writer.controlRevision(task.id) !== expected.controlRev + 1 || this.scheduler.activeTask(task.id))
22647
+ if (!actual || actual.identity !== want.identity || actual.record.revision !== want.revision || realpathSync6(actual.record.cwd) !== this.cwd || this.generation !== expected.checkoutGeneration || h.writer.controlRevision(task.id) !== expected.controlRev + 1 || this.scheduler.activeTask(task.id))
22567
22648
  throw new ContractError("stale");
22568
22649
  const changes2 = captureChanges(h.coordination.store.root);
22569
22650
  if (changes2.fingerprint !== expected.observation.identity || changes2.complete !== expected.observation.complete)
@@ -22768,7 +22849,7 @@ function legacy(store, budget, reader) {
22768
22849
  if (created.has(entry.name))
22769
22850
  continue;
22770
22851
  const path = join18(store.tasks, entry.name, "task.json");
22771
- const size = lstatSync10(path).size;
22852
+ const size = lstatSync11(path).size;
22772
22853
  if (size > 128 * 1024)
22773
22854
  throw new ContractError("corrupt-selected");
22774
22855
  budget.reserve(size);