@abelxiaoxing/cadence 2.0.15 → 2.0.16

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.
@@ -5353,7 +5353,7 @@ function sdkNetworkEnvironment(ambient, scoped) {
5353
5353
 
5354
5354
  // src/service/coordination.ts
5355
5355
  import { randomBytes as randomBytes2, randomUUID as randomUUID4 } from "node:crypto";
5356
- import { opendirSync, realpathSync as realpathSync3 } from "node:fs";
5356
+ import { opendirSync } from "node:fs";
5357
5357
  import { hostname as hostname2 } from "node:os";
5358
5358
  import { dirname as dirname5, isAbsolute as isAbsolute4, join as join6, relative as relative3, sep as sep3 } from "node:path";
5359
5359
  var registrationKeys = [
@@ -5489,19 +5489,25 @@ function recoveryDigest(registry, selected) {
5489
5489
  }
5490
5490
 
5491
5491
  class ServiceCoordination {
5492
- store;
5492
+ project;
5493
5493
  files;
5494
- directory;
5495
5494
  registryDirectory;
5496
5495
  stateHome;
5497
5496
  constructor(workspace, stateHome) {
5498
- this.store = new TaskStore(resolveWorkspace(workspace).root, stateHome);
5499
- const namespace = dirname5(this.store.privateRoot);
5497
+ this.project = workspace === null ? undefined : new TaskStore(resolveWorkspace(workspace).root, stateHome);
5498
+ this.stateHome = this.project ? dirname5(dirname5(this.project.privateRoot)) : canonicalAmbientRoot(stateHome ?? defaultStateHome());
5499
+ const namespace = join6(this.stateHome, "cadence-assistant-v1");
5500
5500
  this.files = new PrivateFiles(namespace);
5501
- this.stateHome = dirname5(namespace);
5502
- this.directory = join6(this.store.privateRoot, "service-v1");
5503
5501
  this.registryDirectory = join6(namespace, "service-registry-v1");
5504
5502
  }
5503
+ get store() {
5504
+ if (!this.project)
5505
+ throw new ContractError("forbidden");
5506
+ return this.project;
5507
+ }
5508
+ get directory() {
5509
+ return join6(this.store.privateRoot, "service-v1");
5510
+ }
5505
5511
  path(name) {
5506
5512
  return join6(this.directory, name);
5507
5513
  }
@@ -5522,7 +5528,7 @@ class ServiceCoordination {
5522
5528
  const o = closed(json(snapshot, REGISTRY_BYTES), ["schema", "entries"]);
5523
5529
  const entries = list(o.entries, REGISTRY_ENTRIES, decodeReservation);
5524
5530
  for (const [i, row] of entries.entries()) {
5525
- if (row.stateHome !== this.stateHome || realpathSync3(row.root) !== row.root)
5531
+ if (row.stateHome !== this.stateHome || canonicalAmbientRoot(row.root) !== row.root)
5526
5532
  refused();
5527
5533
  if (entries.slice(0, i).some((other) => rootsOverlap(row.root, other.root) || row.endpoint === other.endpoint))
5528
5534
  refused();
@@ -5714,6 +5720,7 @@ class ServiceCoordination {
5714
5720
  }
5715
5721
  }
5716
5722
  acquire(input, resolvedEndpoint = input.endpoint, initializeNew, reselectExisting) {
5723
+ this.store;
5717
5724
  const config = decodeOwnerConfig(input);
5718
5725
  const bound = endpoint(resolvedEndpoint);
5719
5726
  if (!endpointMatches(config.endpoint, bound))
@@ -6135,6 +6142,7 @@ class OwnerLease {
6135
6142
  // src/service/gateway-store.ts
6136
6143
  import { randomBytes as randomBytes3, randomUUID as randomUUID5 } from "node:crypto";
6137
6144
  import { opendirSync as opendirSync2 } from "node:fs";
6145
+ import { hostname as hostname3 } from "node:os";
6138
6146
  import { join as join7, resolve as resolve3 } from "node:path";
6139
6147
 
6140
6148
  // src/service/contracts/gateway.ts
@@ -6178,6 +6186,8 @@ function decodeGatewayProject(value) {
6178
6186
  return project;
6179
6187
  }
6180
6188
  function registration(value) {
6189
+ const hasHost = !!value && typeof value === "object" && Object.hasOwn(value, "host");
6190
+ const hasRecovery = !!value && typeof value === "object" && Object.hasOwn(value, "recovery");
6181
6191
  const o = closed(value, [
6182
6192
  "schema",
6183
6193
  "epoch",
@@ -6186,8 +6196,22 @@ function registration(value) {
6186
6196
  "capability",
6187
6197
  "selection",
6188
6198
  "pid",
6189
- "phase"
6199
+ "phase",
6200
+ ...hasHost ? ["host"] : [],
6201
+ ...hasRecovery ? ["recovery"] : []
6190
6202
  ]);
6203
+ let recovery;
6204
+ if (hasRecovery) {
6205
+ const r = closed(o.recovery, ["receipt", "sha256", "stamp"]);
6206
+ const receipt = text(r.receipt, 128, true);
6207
+ if (!/^recovery-v1\/[a-f0-9]{64}\/(?:0|[1-9][0-9]{0,2})\.json$/.test(receipt))
6208
+ throw new ContractError("corrupt-selected");
6209
+ recovery = {
6210
+ receipt,
6211
+ sha256: decodeHash(r.sha256),
6212
+ stamp: text(r.stamp, 512, true)
6213
+ };
6214
+ }
6191
6215
  const endpoint2 = text(o.endpoint, 128, true), capability = text(o.capability, 43, true);
6192
6216
  if (!/^http:\/\/(?:127\.0\.0\.1|\[::1\]):[1-9][0-9]{0,4}$/.test(endpoint2) || !/^[A-Za-z0-9_-]{43}$/.test(capability))
6193
6217
  throw new ContractError("corrupt-selected");
@@ -6198,7 +6222,9 @@ function registration(value) {
6198
6222
  endpoint: endpoint2,
6199
6223
  capability,
6200
6224
  selection: decodeHash(o.selection),
6201
- pid: integer(o.pid, 1),
6225
+ pid: integer(o.pid, 1, 2147483647),
6226
+ ...hasHost ? { host: text(o.host, 255, true) } : {},
6227
+ ...recovery ? { recovery } : {},
6202
6228
  phase: oneOf(o.phase, ["alive", "stopping", "stopped", "quarantined"])
6203
6229
  };
6204
6230
  }
@@ -6258,6 +6284,8 @@ class GatewayStore {
6258
6284
  const previous = this.read();
6259
6285
  if (previous && previous.phase !== "stopped")
6260
6286
  throw new ContractError("quarantine");
6287
+ if (previous?.recovery)
6288
+ this.associatedProjects();
6261
6289
  this.lock = this.files.create(this.path("gateway.lock"), encoded({ epoch: randomUUID5() }));
6262
6290
  const source = { serverConfig: this.serverConfig, token };
6263
6291
  if (!previous)
@@ -6277,6 +6305,8 @@ class GatewayStore {
6277
6305
  capability: randomBytes3(32).toString("base64url"),
6278
6306
  selection: hash2(inputBytes),
6279
6307
  pid: process.pid,
6308
+ host: hostname3(),
6309
+ ...previous?.recovery ? { recovery: previous.recovery } : {},
6280
6310
  phase: "alive"
6281
6311
  };
6282
6312
  this.selected = this.selected ? this.files.replace(this.path("gateway.json"), this.selected, encoded(this.value)) : this.files.create(this.path("gateway.json"), encoded(this.value));
@@ -6320,6 +6350,21 @@ class GatewayStore {
6320
6350
  }
6321
6351
  return out;
6322
6352
  }
6353
+ associatedProjects() {
6354
+ const projects = this.projects(), recovery = this.read()?.recovery;
6355
+ if (!recovery)
6356
+ return projects;
6357
+ const receipt = this.files.read(this.path(recovery.receipt), 65536);
6358
+ if (!receipt || receipt.identity !== recovery.sha256 || receipt.stamp !== recovery.stamp)
6359
+ throw new ContractError("corrupt-selected");
6360
+ const value = json(receipt, 65536);
6361
+ literal(value.schema, "cadence-workbench-recovery/1");
6362
+ const retired = list(value.retiredProjects, 128, (entry) => {
6363
+ const row = closed(entry, ["id", "stamp"]);
6364
+ return { id: decodeHash(row.id), stamp: text(row.stamp, 512, true) };
6365
+ });
6366
+ return projects.filter((project) => !retired.some((row) => row.id === project.id && row.stamp === this.files.read(this.path(`projects/${project.id}.json`))?.stamp));
6367
+ }
6323
6368
  saveProject(project) {
6324
6369
  this.assert();
6325
6370
  const p = decodeGatewayProject(project), path = this.path(`projects/${p.id}.json`), before = this.files.read(path);
@@ -6335,205 +6380,10 @@ class GatewayStore {
6335
6380
  }
6336
6381
  }
6337
6382
 
6338
- // src/service/runtime.ts
6339
- import { homedir as homedir2 } from "node:os";
6340
- import { dirname as dirname6, isAbsolute as isAbsolute5, join as join8, resolve as resolve4 } from "node:path";
6341
- var STARTUP_INPUT_BYTES = 16 * 1024;
6342
- function absolute(value) {
6343
- const result = text(value, 4096, true);
6344
- if (!isAbsolute5(result))
6345
- throw new ContractError("invalid");
6346
- return result;
6347
- }
6348
- function decodeHostConfig(value) {
6349
- const o = closed(value, [
6350
- "schema",
6351
- "http",
6352
- "cwd",
6353
- "agentDir",
6354
- "tokenSource",
6355
- "tokenFile"
6356
- ]);
6357
- const tokenSource = oneOf(o.tokenSource, [
6358
- "generated",
6359
- "environment",
6360
- "file",
6361
- "config"
6362
- ]);
6363
- const tokenFile = o.tokenFile === null ? null : absolute(o.tokenFile);
6364
- if ((tokenSource === "file" || tokenSource === "config") !== !!tokenFile)
6365
- throw new ContractError("invalid");
6366
- return {
6367
- schema: literal(o.schema, "cadence-service-host/1"),
6368
- http: decodeHttpPolicy(o.http),
6369
- cwd: absolute(o.cwd),
6370
- agentDir: absolute(o.agentDir),
6371
- tokenSource,
6372
- tokenFile
6373
- };
6374
- }
6375
- function reselectable(old, next) {
6376
- const kept = (c) => encoded({
6377
- ...c,
6378
- http: { ...c.http, port: 0 },
6379
- tokenSource: null,
6380
- tokenFile: null
6381
- });
6382
- return next.tokenSource === "config" && kept(old) === kept(next);
6383
- }
6384
- function readHostConfig(c) {
6385
- const owner = c.configuration();
6386
- if (!owner)
6387
- return;
6388
- const snapshot = c.files.read(c.path("host-config.json"));
6389
- if (!snapshot)
6390
- throw new ContractError("corrupt-selected");
6391
- const config = decodeHostConfig(json(snapshot));
6392
- if (!config.http.port || owner.endpoint !== localOrigin(config.http, config.http.port) || owner.policyIdentity !== hash2(encoded(config)))
6393
- throw new ContractError("conflict");
6394
- return config;
6395
- }
6396
- function hostEnvironment(ambient) {
6397
- let route;
6398
- const facts = networkSnapshot(ambient);
6399
- try {
6400
- if (facts.NODE_OPTIONS.present)
6401
- throw new Error;
6402
- route = sdkNetworkEnvironment(facts, networkSnapshot(undefined));
6403
- } catch {
6404
- throw new ContractError("unsupported-context");
6405
- }
6406
- const result = Object.create(null);
6407
- for (const key of Object.keys(ambient)) {
6408
- const d = Object.getOwnPropertyDescriptor(ambient, key);
6409
- if (!d || !("value" in d) || typeof d.value !== "string")
6410
- throw new ContractError("invalid");
6411
- if (/^(?:CADENCE_|PI_|ABEL_|TRELLIS_|GIT_)/i.test(key) || networkKeys.some((name) => name === key))
6412
- continue;
6413
- result[key] = d.value;
6414
- }
6415
- if (route.redactionLiterals.length) {
6416
- result.HTTP_PROXY = route.env.HTTP_PROXY;
6417
- result.HTTPS_PROXY = route.env.HTTPS_PROXY;
6418
- result.NODE_USE_ENV_PROXY = "1";
6419
- }
6420
- result.PI_OFFLINE = "1";
6421
- result.NO_COLOR = "1";
6422
- if (!sameNetwork(facts, networkSnapshot(ambient)))
6423
- throw new ContractError("stale");
6424
- return result;
6425
- }
6426
- function selectStart(options, ambient) {
6427
- const workspace = resolveWorkspace(options.workspace), c = new ServiceCoordination(workspace.root, options.stateHome);
6428
- const old = readHostConfig(c);
6429
- const env = Object.getOwnPropertyDescriptor(ambient, "CADENCE_WEB_TOKEN");
6430
- if (env && (!("value" in env) || typeof env.value !== "string"))
6431
- throw new ContractError("invalid");
6432
- let fromFile;
6433
- if (options.config) {
6434
- const path = resolve4(options.config), f = new PrivateFiles(dirname6(path));
6435
- const bytes = f.read(path);
6436
- if (!bytes)
6437
- throw new ContractError("corrupt-selected");
6438
- fromFile = decodeHostConfig(json(bytes));
6439
- }
6440
- const base = old ?? fromFile ?? decodeHostConfig({
6441
- schema: "cadence-service-host/1",
6442
- cwd: workspace.cwd,
6443
- http: {
6444
- schema: "cadence-service-http/1",
6445
- host: options.host ?? "127.0.0.1",
6446
- port: options.port ?? 17423,
6447
- proxy: null
6448
- },
6449
- agentDir: resolve4(options.agentDir ?? ambient.PI_CODING_AGENT_DIR ?? join8(ambient.HOME ?? ambient.USERPROFILE ?? homedir2(), ".pi", "agent")),
6450
- tokenSource: options.tokenFile ? "file" : env ? "environment" : "generated",
6451
- tokenFile: options.tokenFile ? resolve4(options.tokenFile) : null
6452
- });
6453
- const server = options.serverConfig !== undefined ? resolve4(options.serverConfig) : old?.tokenSource === "config" ? old.tokenFile : null;
6454
- let selected = base;
6455
- if (server) {
6456
- if (options.tokenFile !== undefined)
6457
- throw new ContractError("conflict");
6458
- const { port } = readServerConfig(server).config;
6459
- selected = decodeHostConfig({
6460
- ...base,
6461
- http: { ...base.http, port },
6462
- tokenSource: "config",
6463
- tokenFile: server
6464
- });
6465
- }
6466
- if (fromFile && encoded(fromFile) !== encoded(selected) || options.port !== undefined && options.port !== selected.http.port || options.host !== undefined && options.host !== selected.http.host || options.agentDir !== undefined && resolve4(options.agentDir) !== selected.agentDir || options.tokenFile !== undefined && resolve4(options.tokenFile) !== selected.tokenFile || env && selected.tokenSource !== "environment" || selected.tokenSource === "environment" && !env || resolveWorkspace(selected.cwd).root !== workspace.root)
6467
- throw new ContractError("conflict");
6468
- return {
6469
- workspace: workspace.root,
6470
- stateHome: c.stateHome,
6471
- config: selected,
6472
- environmentToken: env?.value ?? null
6473
- };
6474
- }
6475
- function decodeHostInput(value) {
6476
- const o = closed(value, [
6477
- "workspace",
6478
- "stateHome",
6479
- "config",
6480
- "environmentToken"
6481
- ]);
6482
- const config = decodeHostConfig(o.config);
6483
- const environmentToken = o.environmentToken === null ? null : text(o.environmentToken, 1024, true);
6484
- if (config.tokenSource === "environment" !== (environmentToken !== null))
6485
- throw new ContractError("invalid");
6486
- return {
6487
- workspace: absolute(o.workspace),
6488
- stateHome: absolute(o.stateHome),
6489
- config,
6490
- environmentToken
6491
- };
6492
- }
6493
- var STARTUP_STAGES = [
6494
- "package",
6495
- "pi-agent-directory",
6496
- "pi-auth",
6497
- "pi-models",
6498
- "pi-runtime",
6499
- "service"
6500
- ];
6501
-
6502
- class StartupRefusal extends ContractError {
6503
- stage;
6504
- quarantined;
6505
- constructor(code2, stage, quarantined = false) {
6506
- super(code2);
6507
- this.stage = stage;
6508
- this.quarantined = quarantined;
6509
- }
6510
- }
6511
- function startupReport(error) {
6512
- if (error instanceof StartupRefusal)
6513
- return {
6514
- status: error.quarantined ? "quarantined" : "refused",
6515
- error: error.code,
6516
- stage: error.stage
6517
- };
6518
- return {
6519
- status: "refused",
6520
- error: error instanceof ContractError ? error.code : "unavailable",
6521
- stage: "service"
6522
- };
6523
- }
6524
- function decodeStartupReport(value) {
6525
- const o = closed(value, ["status", "error", "stage"]);
6526
- return {
6527
- status: oneOf(o.status, ["refused", "quarantined"]),
6528
- error: oneOf(o.error, ERROR_CODES),
6529
- stage: oneOf(o.stage, STARTUP_STAGES)
6530
- };
6531
- }
6532
-
6533
6383
  // src/history/recovery.ts
6534
6384
  import { createHash as createHash8, randomUUID as randomUUID7 } from "node:crypto";
6535
6385
  import { lstatSync as lstatSync7, opendirSync as opendirSync4 } from "node:fs";
6536
- import { join as join10, relative as relative4 } from "node:path";
6386
+ import { join as join9, relative as relative4 } from "node:path";
6537
6387
 
6538
6388
  // src/service/recovery.ts
6539
6389
  async function inspectRecovery(coordination, history) {
@@ -6565,7 +6415,7 @@ import {
6565
6415
  statfsSync
6566
6416
  } from "node:fs";
6567
6417
  import { open } from "node:fs/promises";
6568
- import { dirname as dirname8, join as join9 } from "node:path";
6418
+ import { dirname as dirname7, join as join8 } from "node:path";
6569
6419
 
6570
6420
  // src/history/admission.ts
6571
6421
  function decodeRunAdmission(value) {
@@ -6594,13 +6444,13 @@ import {
6594
6444
  openSync as openSync3,
6595
6445
  readSync as readSync3
6596
6446
  } from "node:fs";
6597
- import { dirname as dirname7 } from "node:path";
6447
+ import { dirname as dirname6 } from "node:path";
6598
6448
  function bad() {
6599
6449
  throw new ContractError("corrupt-selected");
6600
6450
  }
6601
6451
  var stamp2 = (s) => [s.dev, s.ino, s.size, s.mode, s.uid, s.nlink, s.ctimeMs, s.mtimeMs].join(":");
6602
6452
  function selected(files, path, read, walks) {
6603
- if (!files.files.directory(dirname7(path), false, walks))
6453
+ if (!files.files.directory(dirname6(path), false, walks))
6604
6454
  bad();
6605
6455
  const before = lstatSync5(path);
6606
6456
  if (!before.isFile() || before.nlink !== 1 || process.platform !== "win32" && (before.mode & 63 || process.getuid && before.uid !== process.getuid()))
@@ -7134,7 +6984,7 @@ async function retryStalled(read) {
7134
6984
  } catch (error) {
7135
6985
  if (!(error instanceof StalledQuantum) || retry >= STALL_RETRIES)
7136
6986
  throw error;
7137
- await new Promise((resolve5) => setImmediate(resolve5));
6987
+ await new Promise((resolve4) => setImmediate(resolve4));
7138
6988
  }
7139
6989
  }
7140
6990
  }
@@ -7155,14 +7005,14 @@ class HistoryFiles {
7155
7005
  this.coordination = coordination;
7156
7006
  this.format = format;
7157
7007
  this.formatSnapshot = formatSnapshot;
7158
- this.directory = join9(coordination.directory, "history-v2");
7008
+ this.directory = join8(coordination.directory, "history-v2");
7159
7009
  this.files = coordination.files;
7160
7010
  }
7161
7011
  static open(coordination) {
7162
- const dir = join9(coordination.directory, "history-v2");
7012
+ const dir = join8(coordination.directory, "history-v2");
7163
7013
  if (!coordination.files.directory(dir))
7164
7014
  return;
7165
- const file = coordination.files.read(join9(dir, "format.json"));
7015
+ const file = coordination.files.read(join8(dir, "format.json"));
7166
7016
  if (!file)
7167
7017
  corrupt();
7168
7018
  const format = decodeFormat(json(file));
@@ -7178,7 +7028,7 @@ class HistoryFiles {
7178
7028
  existing.assertWritable();
7179
7029
  return existing;
7180
7030
  }
7181
- const dir = join9(c.directory, "history-v2");
7031
+ const dir = join8(c.directory, "history-v2");
7182
7032
  const format = {
7183
7033
  schema: FORMAT,
7184
7034
  storeId: randomUUID6(),
@@ -7188,19 +7038,19 @@ class HistoryFiles {
7188
7038
  c.files.directory(dir, true);
7189
7039
  for (const name of ["commands", "ledger", "runs", "indexes"]) {
7190
7040
  lease.assert();
7191
- c.files.directory(join9(dir, name), true);
7041
+ c.files.directory(join8(dir, name), true);
7192
7042
  }
7193
7043
  lease.assert();
7194
- const keyPath = join9(dir, "read-proof-key.json");
7044
+ const keyPath = join8(dir, "read-proof-key.json");
7195
7045
  c.files.create(keyPath, encoded({
7196
7046
  schema: "cadence-history-read-key/1",
7197
7047
  storeId: format.storeId,
7198
7048
  key: randomBytes4(32).toString("base64url")
7199
7049
  }));
7200
7050
  lease.assert();
7201
- const snapshot = c.files.create(join9(dir, "format.json"), encoded(format));
7051
+ const snapshot = c.files.create(join8(dir, "format.json"), encoded(format));
7202
7052
  const result = new HistoryFiles(c, format, snapshot);
7203
- result.syncParents(join9(dir, "format.json"));
7053
+ result.syncParents(join8(dir, "format.json"));
7204
7054
  result.assertWritable();
7205
7055
  return result;
7206
7056
  }
@@ -7235,7 +7085,7 @@ class HistoryFiles {
7235
7085
  throw new ContractError("quarantine");
7236
7086
  }
7237
7087
  assertFormat() {
7238
- this.files.assert(join9(this.directory, "format.json"), this.formatSnapshot);
7088
+ this.files.assert(join8(this.directory, "format.json"), this.formatSnapshot);
7239
7089
  }
7240
7090
  readProofMaterial(budget) {
7241
7091
  if (this.format.schema !== FORMAT)
@@ -7244,7 +7094,7 @@ class HistoryFiles {
7244
7094
  this.assertReadFormat(budget);
7245
7095
  else
7246
7096
  this.assertFormat();
7247
- const selected2 = this.readBudgeted(join9(this.directory, "read-proof-key.json"), 512, budget);
7097
+ const selected2 = this.readBudgeted(join8(this.directory, "read-proof-key.json"), 512, budget);
7248
7098
  if (!selected2 || this.proofSnapshot && (selected2.identity !== this.proofSnapshot.identity || selected2.stamp !== this.proofSnapshot.stamp))
7249
7099
  corrupt();
7250
7100
  try {
@@ -7272,17 +7122,17 @@ class HistoryFiles {
7272
7122
  return;
7273
7123
  }
7274
7124
  this.assertFormat();
7275
- assertIncarnation(this, join9(this.directory, "read-proof-key.json"), this.proofSnapshot.stamp);
7125
+ assertIncarnation(this, join8(this.directory, "read-proof-key.json"), this.proofSnapshot.stamp);
7276
7126
  }
7277
7127
  segmentPath(segment) {
7278
- return join9(this.directory, "ledger", `${String(segment).padStart(12, "0")}.jsonl`);
7128
+ return join8(this.directory, "ledger", `${String(segment).padStart(12, "0")}.jsonl`);
7279
7129
  }
7280
7130
  artifactPath(ref) {
7281
- return join9(this.directory, "runs", ref.runId, "artifacts", ref.artifactId, `${ref.part}.part`);
7131
+ return join8(this.directory, "runs", ref.runId, "artifacts", ref.artifactId, `${ref.part}.part`);
7282
7132
  }
7283
7133
  admissionPath(runId) {
7284
7134
  decodeId(runId);
7285
- return join9(this.directory, "runs", runId, "admission.json");
7135
+ return join8(this.directory, "runs", runId, "admission.json");
7286
7136
  }
7287
7137
  writeAdmission(lease, input) {
7288
7138
  lease.assert();
@@ -7308,7 +7158,7 @@ class HistoryFiles {
7308
7158
  readCommand(commandId, budget) {
7309
7159
  decodeId(commandId);
7310
7160
  this.assertReadFormat(budget);
7311
- return this.readBudgeted(join9(this.directory, "commands", commandId, "intent.json"), RECORD_BYTES, budget);
7161
+ return this.readBudgeted(join8(this.directory, "commands", commandId, "intent.json"), RECORD_BYTES, budget);
7312
7162
  }
7313
7163
  readAdmission(runId, identity, budget) {
7314
7164
  return this.readAdmissionIdentity(runId, hash2(canonicalJson(identity)), budget);
@@ -7329,7 +7179,7 @@ class HistoryFiles {
7329
7179
  syncParents(file) {
7330
7180
  if (process.platform === "win32")
7331
7181
  return;
7332
- for (let path = dirname8(file);; path = dirname8(path)) {
7182
+ for (let path = dirname7(file);; path = dirname7(path)) {
7333
7183
  if (!this.files.directory(path))
7334
7184
  corrupt();
7335
7185
  const fd = openSync4(path, constants4.O_RDONLY | constants4.O_DIRECTORY);
@@ -7340,13 +7190,13 @@ class HistoryFiles {
7340
7190
  }
7341
7191
  if (path === this.coordination.directory)
7342
7192
  break;
7343
- if (path === dirname8(path))
7193
+ if (path === dirname7(path))
7344
7194
  corrupt();
7345
7195
  }
7346
7196
  }
7347
7197
  assertReadFormat(budget) {
7348
7198
  budget.reserve(this.formatSnapshot.bytes.length);
7349
- this.files.assert(join9(this.directory, "format.json"), this.formatSnapshot, this.formatSnapshot.bytes.length);
7199
+ this.files.assert(join8(this.directory, "format.json"), this.formatSnapshot, this.formatSnapshot.bytes.length);
7350
7200
  }
7351
7201
  assertPublished(segment, end, seq) {
7352
7202
  const fence = publicationFences.get(this.directory);
@@ -7384,7 +7234,7 @@ class HistoryFiles {
7384
7234
  const dir = opendirSync3(path);
7385
7235
  try {
7386
7236
  for (let e = dir.readSync();e; e = dir.readSync()) {
7387
- const p = join9(path, e.name), st = lstatSync6(p);
7237
+ const p = join8(path, e.name), st = lstatSync6(p);
7388
7238
  if (st.isDirectory())
7389
7239
  bytes += walk(p, depth + 1);
7390
7240
  else {
@@ -7419,7 +7269,7 @@ class HistoryFiles {
7419
7269
  state.bytes = 0;
7420
7270
  state.identity = null;
7421
7271
  let count = 0;
7422
- const ledger = join9(this.directory, "ledger");
7272
+ const ledger = join8(this.directory, "ledger");
7423
7273
  if (!this.files.directory(ledger))
7424
7274
  corrupt();
7425
7275
  const dir = opendirSync3(ledger);
@@ -7736,7 +7586,7 @@ class HistoryFiles {
7736
7586
  checkpoint(lease, state) {
7737
7587
  lease.assert();
7738
7588
  this.assertWritable();
7739
- const path = join9(this.directory, "checkpoint.json"), old = this.files.read(path);
7589
+ const path = join8(this.directory, "checkpoint.json"), old = this.files.read(path);
7740
7590
  const body = encoded({
7741
7591
  schema: "cadence-history-checkpoint/2",
7742
7592
  storeId: this.format.storeId,
@@ -8343,7 +8193,7 @@ function digestHistory(files, exclude) {
8343
8193
  dir.closeSync();
8344
8194
  }
8345
8195
  for (const name of names2.sort()) {
8346
- const selected2 = join10(path, name);
8196
+ const selected2 = join9(path, name);
8347
8197
  if (selected2 === exclude)
8348
8198
  continue;
8349
8199
  const rel = relative4(files.directory, selected2);
@@ -8531,6 +8381,201 @@ class HistoryRecovery {
8531
8381
  }
8532
8382
  }
8533
8383
 
8384
+ // src/service/runtime.ts
8385
+ import { homedir as homedir2 } from "node:os";
8386
+ import { dirname as dirname8, isAbsolute as isAbsolute5, join as join10, resolve as resolve4 } from "node:path";
8387
+ var STARTUP_INPUT_BYTES = 16 * 1024;
8388
+ function absolute(value) {
8389
+ const result = text(value, 4096, true);
8390
+ if (!isAbsolute5(result))
8391
+ throw new ContractError("invalid");
8392
+ return result;
8393
+ }
8394
+ function decodeHostConfig(value) {
8395
+ const o = closed(value, [
8396
+ "schema",
8397
+ "http",
8398
+ "cwd",
8399
+ "agentDir",
8400
+ "tokenSource",
8401
+ "tokenFile"
8402
+ ]);
8403
+ const tokenSource = oneOf(o.tokenSource, [
8404
+ "generated",
8405
+ "environment",
8406
+ "file",
8407
+ "config"
8408
+ ]);
8409
+ const tokenFile = o.tokenFile === null ? null : absolute(o.tokenFile);
8410
+ if ((tokenSource === "file" || tokenSource === "config") !== !!tokenFile)
8411
+ throw new ContractError("invalid");
8412
+ return {
8413
+ schema: literal(o.schema, "cadence-service-host/1"),
8414
+ http: decodeHttpPolicy(o.http),
8415
+ cwd: absolute(o.cwd),
8416
+ agentDir: absolute(o.agentDir),
8417
+ tokenSource,
8418
+ tokenFile
8419
+ };
8420
+ }
8421
+ function reselectable(old, next) {
8422
+ const kept = (c) => encoded({
8423
+ ...c,
8424
+ http: { ...c.http, port: 0 },
8425
+ tokenSource: null,
8426
+ tokenFile: null
8427
+ });
8428
+ return next.tokenSource === "config" && kept(old) === kept(next);
8429
+ }
8430
+ function readHostConfig(c) {
8431
+ const owner = c.configuration();
8432
+ if (!owner)
8433
+ return;
8434
+ const snapshot = c.files.read(c.path("host-config.json"));
8435
+ if (!snapshot)
8436
+ throw new ContractError("corrupt-selected");
8437
+ const config = decodeHostConfig(json(snapshot));
8438
+ if (!config.http.port || owner.endpoint !== localOrigin(config.http, config.http.port) || owner.policyIdentity !== hash2(encoded(config)))
8439
+ throw new ContractError("conflict");
8440
+ return config;
8441
+ }
8442
+ function hostEnvironment(ambient) {
8443
+ let route;
8444
+ const facts = networkSnapshot(ambient);
8445
+ try {
8446
+ if (facts.NODE_OPTIONS.present)
8447
+ throw new Error;
8448
+ route = sdkNetworkEnvironment(facts, networkSnapshot(undefined));
8449
+ } catch {
8450
+ throw new ContractError("unsupported-context");
8451
+ }
8452
+ const result = Object.create(null);
8453
+ for (const key of Object.keys(ambient)) {
8454
+ const d = Object.getOwnPropertyDescriptor(ambient, key);
8455
+ if (!d || !("value" in d) || typeof d.value !== "string")
8456
+ throw new ContractError("invalid");
8457
+ if (/^(?:CADENCE_|PI_|ABEL_|TRELLIS_|GIT_)/i.test(key) || networkKeys.some((name) => name === key))
8458
+ continue;
8459
+ result[key] = d.value;
8460
+ }
8461
+ if (route.redactionLiterals.length) {
8462
+ result.HTTP_PROXY = route.env.HTTP_PROXY;
8463
+ result.HTTPS_PROXY = route.env.HTTPS_PROXY;
8464
+ result.NODE_USE_ENV_PROXY = "1";
8465
+ }
8466
+ result.PI_OFFLINE = "1";
8467
+ result.NO_COLOR = "1";
8468
+ if (!sameNetwork(facts, networkSnapshot(ambient)))
8469
+ throw new ContractError("stale");
8470
+ return result;
8471
+ }
8472
+ function selectStart(options, ambient) {
8473
+ const workspace = resolveWorkspace(options.workspace), c = new ServiceCoordination(workspace.root, options.stateHome);
8474
+ const old = readHostConfig(c);
8475
+ const env = Object.getOwnPropertyDescriptor(ambient, "CADENCE_WEB_TOKEN");
8476
+ if (env && (!("value" in env) || typeof env.value !== "string"))
8477
+ throw new ContractError("invalid");
8478
+ let fromFile;
8479
+ if (options.config) {
8480
+ const path = resolve4(options.config), f = new PrivateFiles(dirname8(path));
8481
+ const bytes = f.read(path);
8482
+ if (!bytes)
8483
+ throw new ContractError("corrupt-selected");
8484
+ fromFile = decodeHostConfig(json(bytes));
8485
+ }
8486
+ const base = old ?? fromFile ?? decodeHostConfig({
8487
+ schema: "cadence-service-host/1",
8488
+ cwd: workspace.cwd,
8489
+ http: {
8490
+ schema: "cadence-service-http/1",
8491
+ host: options.host ?? "127.0.0.1",
8492
+ port: options.port ?? 17423,
8493
+ proxy: null
8494
+ },
8495
+ agentDir: resolve4(options.agentDir ?? ambient.PI_CODING_AGENT_DIR ?? join10(ambient.HOME ?? ambient.USERPROFILE ?? homedir2(), ".pi", "agent")),
8496
+ tokenSource: options.tokenFile ? "file" : env ? "environment" : "generated",
8497
+ tokenFile: options.tokenFile ? resolve4(options.tokenFile) : null
8498
+ });
8499
+ const server = options.serverConfig !== undefined ? resolve4(options.serverConfig) : old?.tokenSource === "config" ? old.tokenFile : null;
8500
+ let selected2 = base;
8501
+ if (server) {
8502
+ if (options.tokenFile !== undefined)
8503
+ throw new ContractError("conflict");
8504
+ const { port } = readServerConfig(server).config;
8505
+ selected2 = decodeHostConfig({
8506
+ ...base,
8507
+ http: { ...base.http, port },
8508
+ tokenSource: "config",
8509
+ tokenFile: server
8510
+ });
8511
+ }
8512
+ if (fromFile && encoded(fromFile) !== encoded(selected2) || options.port !== undefined && options.port !== selected2.http.port || options.host !== undefined && options.host !== selected2.http.host || options.agentDir !== undefined && resolve4(options.agentDir) !== selected2.agentDir || options.tokenFile !== undefined && resolve4(options.tokenFile) !== selected2.tokenFile || env && selected2.tokenSource !== "environment" || selected2.tokenSource === "environment" && !env || resolveWorkspace(selected2.cwd).root !== workspace.root)
8513
+ throw new ContractError("conflict");
8514
+ return {
8515
+ workspace: workspace.root,
8516
+ stateHome: c.stateHome,
8517
+ config: selected2,
8518
+ environmentToken: env?.value ?? null
8519
+ };
8520
+ }
8521
+ function decodeHostInput(value) {
8522
+ const o = closed(value, [
8523
+ "workspace",
8524
+ "stateHome",
8525
+ "config",
8526
+ "environmentToken"
8527
+ ]);
8528
+ const config = decodeHostConfig(o.config);
8529
+ const environmentToken = o.environmentToken === null ? null : text(o.environmentToken, 1024, true);
8530
+ if (config.tokenSource === "environment" !== (environmentToken !== null))
8531
+ throw new ContractError("invalid");
8532
+ return {
8533
+ workspace: absolute(o.workspace),
8534
+ stateHome: absolute(o.stateHome),
8535
+ config,
8536
+ environmentToken
8537
+ };
8538
+ }
8539
+ var STARTUP_STAGES = [
8540
+ "package",
8541
+ "pi-agent-directory",
8542
+ "pi-auth",
8543
+ "pi-models",
8544
+ "pi-runtime",
8545
+ "service"
8546
+ ];
8547
+
8548
+ class StartupRefusal extends ContractError {
8549
+ stage;
8550
+ quarantined;
8551
+ constructor(code2, stage, quarantined = false) {
8552
+ super(code2);
8553
+ this.stage = stage;
8554
+ this.quarantined = quarantined;
8555
+ }
8556
+ }
8557
+ function startupReport(error) {
8558
+ if (error instanceof StartupRefusal)
8559
+ return {
8560
+ status: error.quarantined ? "quarantined" : "refused",
8561
+ error: error.code,
8562
+ stage: error.stage
8563
+ };
8564
+ return {
8565
+ status: "refused",
8566
+ error: error instanceof ContractError ? error.code : "unavailable",
8567
+ stage: "service"
8568
+ };
8569
+ }
8570
+ function decodeStartupReport(value) {
8571
+ const o = closed(value, ["status", "error", "stage"]);
8572
+ return {
8573
+ status: oneOf(o.status, ["refused", "quarantined"]),
8574
+ error: oneOf(o.error, ERROR_CODES),
8575
+ stage: oneOf(o.stage, STARTUP_STAGES)
8576
+ };
8577
+ }
8578
+
8534
8579
  // src/service/cli.ts
8535
8580
  function nativeCall(c, operation, reveal = false, controlBody) {
8536
8581
  const access = c.localAccess();
@@ -8625,7 +8670,12 @@ async function stopService(c) {
8625
8670
  }
8626
8671
  const deadline = performance.now() + LIMITS.stopWaitMs;
8627
8672
  while (performance.now() < deadline) {
8628
- const observed = c.inspect();
8673
+ let observed;
8674
+ try {
8675
+ observed = c.inspect();
8676
+ } catch {
8677
+ observed = { status: "unavailable" };
8678
+ }
8629
8679
  if ("epoch" in observed && observed.epoch === epoch && observed.status === "stopped")
8630
8680
  return { status: "stopped", epoch };
8631
8681
  if (observed.status === "quarantined")
@@ -8639,6 +8689,15 @@ async function stopService(c) {
8639
8689
  function failedStatus(result) {
8640
8690
  return !!(result && typeof result === "object" && ("status" in result) && ["unconfirmed", "unavailable", "quarantined", "refused"].includes(String(result.status)));
8641
8691
  }
8692
+ function managementExitCode(result, foreground = false) {
8693
+ if (foreground) {
8694
+ try {
8695
+ decodeStartupReport(result);
8696
+ return 78;
8697
+ } catch {}
8698
+ }
8699
+ return 1;
8700
+ }
8642
8701
  function serverConfigHint(error) {
8643
8702
  return `Cadence changed nothing: ${error.path} ${error.reason}.
8644
8703
  Fix it and run the command again; the file holds the WebUI port and token as ${PORT_KEY}=<1-65535> and ${TOKEN_KEY}=<at least 32 characters>, one line each.
@@ -8801,6 +8860,8 @@ async function launchHost(input, c, foreground, hostUrl, cwd, env, network) {
8801
8860
  process.stdout.write(`${JSON.stringify(result)}
8802
8861
  `);
8803
8862
  await closure;
8863
+ if (failedStatus(result))
8864
+ process.exitCode = managementExitCode(result, true);
8804
8865
  return null;
8805
8866
  }
8806
8867
  return result;
@@ -9709,7 +9770,7 @@ import {
9709
9770
  opendirSync as opendirSync5,
9710
9771
  openSync as openSync5,
9711
9772
  readSync as readSync4,
9712
- realpathSync as realpathSync4
9773
+ realpathSync as realpathSync3
9713
9774
  } from "node:fs";
9714
9775
  import { dirname as dirname10, isAbsolute as isAbsolute6, join as join12, relative as relative5, resolve as resolve6, sep as sep4 } from "node:path";
9715
9776
 
@@ -10084,7 +10145,7 @@ class WorkbenchFiles {
10084
10145
  excluded;
10085
10146
  constructor(root, excluded, secrets) {
10086
10147
  this.secrets = secrets;
10087
- this.root = realpathSync4(root);
10148
+ this.root = realpathSync3(root);
10088
10149
  this.excluded = excluded.flatMap((path) => [
10089
10150
  resolve6(path),
10090
10151
  canonicalAmbientRoot(path)
@@ -10100,7 +10161,7 @@ class WorkbenchFiles {
10100
10161
  directory(path) {
10101
10162
  if (!isAbsolute6(path) || !safeDirectory(path))
10102
10163
  throw new ContractError("invalid");
10103
- const canonical = realpathSync4(path);
10164
+ const canonical = realpathSync3(path);
10104
10165
  this.allowed(canonical);
10105
10166
  return canonical;
10106
10167
  }
@@ -10378,7 +10439,7 @@ Content-Length: 0\r
10378
10439
  return result;
10379
10440
  }
10380
10441
  function binding(id) {
10381
- const project = store.projects().find((p) => p.id === id);
10442
+ const project = store.associatedProjects().find((p) => p.id === id);
10382
10443
  if (!project)
10383
10444
  throw new ContractError("unavailable");
10384
10445
  const c = new ServiceCoordination(project.path, input.stateHome), local = c.localAccess();
@@ -10421,7 +10482,7 @@ Content-Length: 0\r
10421
10482
  const originals = await Promise.allSettled([...opens.values()].map((o) => o.result));
10422
10483
  const uncertainOpening = originals.some((r) => r.status === "rejected" && !(r.reason instanceof ProjectOpenRefusal && r.reason.noOwner));
10423
10484
  const retired = await Promise.allSettled([...retirements]);
10424
- const targets = store.projects();
10485
+ const targets = store.associatedProjects();
10425
10486
  await joinProjectStops(targets, async (p) => {
10426
10487
  const c = new ServiceCoordination(p.path, input.stateHome), observed = await serviceStatus(c);
10427
10488
  const status = observed && typeof observed === "object" && "status" in observed ? observed.status : "unavailable";
@@ -17317,7 +17378,7 @@ import {
17317
17378
  constants as constants6,
17318
17379
  fsyncSync as fsyncSync4,
17319
17380
  openSync as openSync6,
17320
- realpathSync as realpathSync5
17381
+ realpathSync as realpathSync4
17321
17382
  } from "node:fs";
17322
17383
  import { dirname as dirname12, isAbsolute as isAbsolute7, join as join16, relative as relative6, sep as sep5 } from "node:path";
17323
17384
  function summary(text2, maximum, runId) {
@@ -17368,7 +17429,7 @@ function publicationRecord(store, reader, intent, link, run, request3, expected,
17368
17429
  else {
17369
17430
  if (action.kind !== "create" || !request3.cwd || store.list().length >= 1000)
17370
17431
  bad11();
17371
- const cwd = realpathSync5(request3.cwd), within = relative6(store.root, cwd);
17432
+ const cwd = realpathSync4(request3.cwd), within = relative6(store.root, cwd);
17372
17433
  if (isAbsolute7(within) || within === ".." || within.startsWith(`..${sep5}`))
17373
17434
  bad11();
17374
17435
  record2 = {
@@ -19446,7 +19507,7 @@ class OwnerModelChoice {
19446
19507
  }
19447
19508
 
19448
19509
  // src/service/model-config.ts
19449
- import { lstatSync as lstatSync11, realpathSync as realpathSync6 } from "node:fs";
19510
+ import { lstatSync as lstatSync11, realpathSync as realpathSync5 } from "node:fs";
19450
19511
  import { dirname as dirname13, isAbsolute as isAbsolute8, join as join18, resolve as resolve7 } from "node:path";
19451
19512
  var CONFIG_BYTES2 = 1024 * 1024;
19452
19513
  var ENTRY_LIMIT = 256;
@@ -19520,7 +19581,7 @@ function piSource(agentDir, home, cwd, env) {
19520
19581
  if (selected2 === "~" || selected2.startsWith("~/"))
19521
19582
  selected2 = home + selected2.slice(1);
19522
19583
  selected2 = resolve7(cwd, selected2);
19523
- const directory = join18(realpathSync6(dirname13(selected2)), selected2.slice(dirname13(selected2).length + 1));
19584
+ const directory = join18(realpathSync5(dirname13(selected2)), selected2.slice(dirname13(selected2).length + 1));
19524
19585
  if (!lstatSync11(directory).isDirectory() || lstatSync11(directory).isSymbolicLink())
19525
19586
  refuse2();
19526
19587
  const files = new PrivateFiles(directory, false);
@@ -20958,7 +21019,7 @@ class ServiceOwner {
20958
21019
 
20959
21020
  // src/service/task-actions.ts
20960
21021
  import { randomUUID as randomUUID18 } from "node:crypto";
20961
- import { realpathSync as realpathSync7 } from "node:fs";
21022
+ import { realpathSync as realpathSync6 } from "node:fs";
20962
21023
 
20963
21024
  // src/task-diff.ts
20964
21025
  import { spawnSync as spawnSync2 } from "node:child_process";
@@ -24132,9 +24193,9 @@ class TaskActions {
24132
24193
  selection: structuredClone(options.selection),
24133
24194
  ownerSecrets: [...options.ownerSecrets]
24134
24195
  };
24135
- this.cwd = realpathSync7(options.cwd);
24196
+ this.cwd = realpathSync6(options.cwd);
24136
24197
  const config = readHostConfig(options.host.coordination);
24137
- if (!config || realpathSync7(config.cwd) !== this.cwd)
24198
+ if (!config || realpathSync6(config.cwd) !== this.cwd)
24138
24199
  throw new ContractError("unsupported-context");
24139
24200
  this.launchCwd = config.cwd;
24140
24201
  this.checkEnvironment = options.host.checkEnvironment;
@@ -24258,7 +24319,7 @@ class TaskActions {
24258
24319
  if (this.closed || this.options.host.owner.state !== "idle" || this.options.host.writer.quarantined)
24259
24320
  throw new ContractError("quarantine");
24260
24321
  this.options.host.owner.lease.assert();
24261
- if (!this.sources.current() || realpathSync7(this.cwd) !== this.cwd || realpathSync7(this.launchCwd) !== this.cwd || this.options.host.checkEnvironment !== this.checkEnvironment)
24322
+ if (!this.sources.current() || realpathSync6(this.cwd) !== this.cwd || realpathSync6(this.launchCwd) !== this.cwd || this.options.host.checkEnvironment !== this.checkEnvironment)
24262
24323
  throw new ContractError("stale");
24263
24324
  }
24264
24325
  choiceSnapshot() {
@@ -24374,7 +24435,7 @@ class TaskActions {
24374
24435
  const access = this.currentAccess();
24375
24436
  const committedSeq = snapshot ?? h.writer.committedSeq;
24376
24437
  const selected2 = taskId ? h.coordination.store.loadSnapshot(taskId) : null;
24377
- if (selected2 && realpathSync7(selected2.record.cwd) !== this.cwd)
24438
+ if (selected2 && realpathSync6(selected2.record.cwd) !== this.cwd)
24378
24439
  throw new ContractError("unsupported-context");
24379
24440
  const secrets = this.viewSecrets();
24380
24441
  const roles = this.sources.roles.map(({ role: role2, sha256 }) => ({
@@ -24880,7 +24941,7 @@ class TaskActions {
24880
24941
  this.assertChoice(expected);
24881
24942
  held.assertHeld();
24882
24943
  const actual = h.coordination.store.loadSnapshot(task.id), want = published ?? task;
24883
- if (!actual || actual.identity !== want.identity || actual.record.revision !== want.revision || realpathSync7(actual.record.cwd) !== this.cwd || this.generation !== expected.checkoutGeneration || h.writer.controlRevision(task.id) !== expected.controlRev + 1 || this.scheduler.activeTask(task.id))
24944
+ 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))
24884
24945
  throw new ContractError("stale");
24885
24946
  const changes2 = captureChanges(h.coordination.store.root);
24886
24947
  if (changes2.fingerprint !== expected.observation.identity || changes2.complete !== expected.observation.complete)
@@ -25065,7 +25126,7 @@ import { join as join23 } from "node:path";
25065
25126
 
25066
25127
  // src/service/conversations.ts
25067
25128
  import { randomUUID as randomUUID19 } from "node:crypto";
25068
- import { lstatSync as lstatSync13, opendirSync as opendirSync7, realpathSync as realpathSync8, statfsSync as statfsSync2 } from "node:fs";
25129
+ import { lstatSync as lstatSync13, opendirSync as opendirSync7, realpathSync as realpathSync7, statfsSync as statfsSync2 } from "node:fs";
25069
25130
  import { dirname as dirname14, join as join22 } from "node:path";
25070
25131
  var TURN_BYTES = 384 * 1024;
25071
25132
  var META_BYTES = 64 * 1024;
@@ -25186,7 +25247,7 @@ class Conversations {
25186
25247
  constructor(o) {
25187
25248
  this.o = o;
25188
25249
  this.root = join22(o.coordination.directory, "conversations-v1");
25189
- this.cwd = realpathSync8(o.cwd);
25250
+ this.cwd = realpathSync7(o.cwd);
25190
25251
  }
25191
25252
  currentDirectory() {
25192
25253
  const current2 = resolveWorkspace(this.o.cwd);