@usecontextlayer/ctxe 0.5.5 → 0.5.7

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/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6317e92d-f910-5336-9f6a-2445ebdf6ed8")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7463ebb3-f56d-51c5-a74a-b15957e43865")}catch(e){}}();
4
4
  import { createRequire } from "node:module";
5
5
  import * as Sentry from "@sentry/node";
6
6
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
@@ -59,7 +59,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
59
59
 
60
60
  //#endregion
61
61
  //#region package.json
62
- var version$2 = "0.5.5";
62
+ var version$2 = "0.5.7";
63
63
 
64
64
  //#endregion
65
65
  //#region sentry.ts
@@ -363,6 +363,22 @@ async function drainExecStream(handle, options) {
363
363
  signal?.removeEventListener("abort", onAbort);
364
364
  }
365
365
  }
366
+ const MICROSANDBOX_HOST_ALIAS = "host.microsandbox.internal";
367
+ const HOST_LOOPBACK_HOSTNAMES = new Set([
368
+ "localhost",
369
+ "127.0.0.1",
370
+ "0.0.0.0"
371
+ ]);
372
+ const IPV6_LOOPBACK_HOSTNAMES = new Set(["[::1]", "[::]"]);
373
+ function rewriteHostUrlForGuest(url) {
374
+ const parsed = new URL(url);
375
+ const hostname = parsed.hostname.toLowerCase();
376
+ if (HOST_LOOPBACK_HOSTNAMES.has(hostname) || IPV6_LOOPBACK_HOSTNAMES.has(hostname)) {
377
+ parsed.hostname = MICROSANDBOX_HOST_ALIAS;
378
+ return parsed.toString();
379
+ }
380
+ return url;
381
+ }
366
382
  const DEBUG_SANDBOX_NAME = "ctx-sandbox-debug";
367
383
  const DEFAULT_BOOT_COMMAND = ["uname", "-a"];
368
384
  async function runSandbox(input) {
@@ -4129,6 +4145,99 @@ function refine$1(fn, _params = {}) {
4129
4145
  function superRefine$1(fn, params) {
4130
4146
  return /* @__PURE__ */ _superRefine$1(fn, params);
4131
4147
  }
4148
+ `${JSON.stringify({ render: {
4149
+ elements: {
4150
+ ask: {
4151
+ children: ["askLabel"],
4152
+ on: { press: {
4153
+ action: "openChat",
4154
+ params: {
4155
+ autoSend: false,
4156
+ content: { $template: "What should I know about @output/${path}?" }
4157
+ }
4158
+ } },
4159
+ props: { className: null },
4160
+ type: "Pressable"
4161
+ },
4162
+ askLabel: {
4163
+ props: { text: "Ask about this doc" },
4164
+ type: "Text"
4165
+ },
4166
+ body: {
4167
+ props: { text: { $item: "body" } },
4168
+ type: "Text"
4169
+ },
4170
+ card: {
4171
+ children: [
4172
+ "body",
4173
+ "draft",
4174
+ "ask"
4175
+ ],
4176
+ props: { title: { $item: "title" } },
4177
+ type: "Card"
4178
+ },
4179
+ detail: {
4180
+ children: ["card"],
4181
+ props: {
4182
+ className: "mx-auto max-w-md p-8",
4183
+ direction: "vertical",
4184
+ gap: "md"
4185
+ },
4186
+ repeat: {
4187
+ key: "path",
4188
+ statePath: "/items"
4189
+ },
4190
+ type: "Stack"
4191
+ },
4192
+ draft: {
4193
+ children: ["draftLabel"],
4194
+ on: { press: {
4195
+ action: "openChat",
4196
+ params: {
4197
+ autoSend: true,
4198
+ content: { $template: "Draft a reply to @output/${path}" }
4199
+ }
4200
+ } },
4201
+ props: { className: null },
4202
+ type: "Pressable"
4203
+ },
4204
+ draftLabel: {
4205
+ props: { text: "Draft reply" },
4206
+ type: "Text"
4207
+ }
4208
+ },
4209
+ root: "detail"
4210
+ } }, null, " ")}`, `${JSON.stringify({ render: {
4211
+ elements: {
4212
+ card: {
4213
+ props: { title: { $item: "title" } },
4214
+ type: "Card"
4215
+ },
4216
+ list: {
4217
+ children: ["row"],
4218
+ props: {
4219
+ className: "mx-auto max-w-md p-8",
4220
+ direction: "vertical",
4221
+ gap: "md"
4222
+ },
4223
+ repeat: {
4224
+ key: "path",
4225
+ statePath: "/items"
4226
+ },
4227
+ type: "Stack"
4228
+ },
4229
+ row: {
4230
+ children: ["card"],
4231
+ on: { press: {
4232
+ action: "navigate",
4233
+ params: { path: { $template: "${path}" } }
4234
+ } },
4235
+ props: { className: null },
4236
+ type: "Pressable"
4237
+ }
4238
+ },
4239
+ root: "list"
4240
+ } }, null, " ")}`;
4132
4241
  const segmentSchema = string$4().min(1, "a repoId segment must be non-empty").refine((s) => s !== "." && s !== ".." && !s.includes("/"), { message: "a repoId segment must not be '.'/'..' or contain '/'" });
4133
4242
  const sessionMetaSchema = object$3({
4134
4243
  created: string$4().nullable(),
@@ -30553,9 +30662,7 @@ async function inspectWorkingTree(repo) {
30553
30662
  paths: parsePorcelainV1Z(result.stdout)
30554
30663
  };
30555
30664
  }
30556
- async function assertSynthesizerTransactionReady(repo) {
30557
- const branch = await inspectBranchReadiness(repo);
30558
- if (branch.kind !== "ready" && branch.kind !== "ready_empty") throw new Error(formatBranchReadinessError(repo, branch));
30665
+ async function assertCleanWorkingTree(repo) {
30559
30666
  const tree = await inspectWorkingTree(repo);
30560
30667
  if (!tree.clean) throw new Error(formatDirtyTreeError(repo, tree.paths));
30561
30668
  }
@@ -30572,10 +30679,15 @@ async function fastForwardRoot(repo) {
30572
30679
  if (remoteSha === null) throw new Error(`Remote ${repo.branch} did not exist after 'git fetch origin ${repo.branch}'; nothing to fast-forward.`);
30573
30680
  if (fromSha === remoteSha) return {
30574
30681
  from: fromSha,
30682
+ kind: "fast_forwarded",
30575
30683
  to: remoteSha
30576
30684
  };
30577
30685
  if (fromSha !== null) {
30578
- if (!await isAncestorRef(repo, fromSha, remoteSha)) throw new Error(`Local HEAD ${fromSha} is not an ancestor of ${repo.branch} (${remoteSha}); fast-forward refused (no merge, rebase, or reset).`);
30686
+ if (!await isAncestorRef(repo, fromSha, remoteSha)) return {
30687
+ kind: "diverged",
30688
+ localSha: fromSha,
30689
+ remoteSha
30690
+ };
30579
30691
  await runGit(repo, [
30580
30692
  "merge",
30581
30693
  "--ff-only",
@@ -30600,6 +30712,7 @@ async function fastForwardRoot(repo) {
30600
30712
  }
30601
30713
  return {
30602
30714
  from: fromSha,
30715
+ kind: "fast_forwarded",
30603
30716
  to: remoteSha
30604
30717
  };
30605
30718
  }
@@ -30625,11 +30738,39 @@ async function commitRootReset(repo, input) {
30625
30738
  return await createCommit(repo, buildRootResetCommitMessage(input));
30626
30739
  }
30627
30740
  async function pushToOrigin(repo) {
30628
- await runGit(repo, [
30741
+ const result = await runGit(repo, [
30629
30742
  "push",
30630
30743
  "origin",
30631
30744
  `HEAD:${repo.branch}`
30745
+ ], {
30746
+ auth: true,
30747
+ throwOnNonZero: false
30748
+ });
30749
+ if (result.exitCode === 0) return "pushed";
30750
+ if (classifyPushFailure(result.stderr) === "rejected") return "rejected";
30751
+ throw new Error(`git push origin HEAD:${repo.branch} (exit ${result.exitCode}) in ${repo.rootDir}\n${result.stderr.trim()}`);
30752
+ }
30753
+ function classifyPushFailure(stderr) {
30754
+ return /\[(rejected|remote rejected)\]/.test(stderr) ? "rejected" : "transport";
30755
+ }
30756
+ async function discardToOrigin(repo) {
30757
+ const discardedSha = await readLocalHeadSha(repo);
30758
+ await runGit(repo, [
30759
+ "fetch",
30760
+ "origin",
30761
+ repo.branch
30632
30762
  ], { auth: true });
30763
+ const originSha = await readFetchHeadSha(repo);
30764
+ if (originSha === null) throw new Error(`Remote ${repo.branch} did not exist after 'git fetch origin ${repo.branch}'; nothing to discard to.`);
30765
+ await runGit(repo, [
30766
+ "reset",
30767
+ "--hard",
30768
+ originSha
30769
+ ]);
30770
+ return {
30771
+ discardedSha,
30772
+ originSha
30773
+ };
30633
30774
  }
30634
30775
  async function runGit(repo, args, options = {}) {
30635
30776
  const throwOnNonZero = options.throwOnNonZero ?? true;
@@ -30778,17 +30919,6 @@ function parsePorcelainV1Z(stdout) {
30778
30919
  }
30779
30920
  return paths;
30780
30921
  }
30781
- function formatBranchReadinessError(repo, branch) {
30782
- const prefix = `Engine root '${repo.rootDir}' is not transaction-ready (branch state)`;
30783
- switch (branch.kind) {
30784
- case "no_origin": return `${prefix}: 'origin' remote is not configured. Provisioning must configure origin.`;
30785
- case "local_unborn_remote_has_main": return `${prefix}: local checkout has no commits but origin/${repo.branch} exists at ${branch.remoteSha}. Run 'ctxe repair' to fast-forward.`;
30786
- case "local_head_without_remote_main": return `${prefix}: local HEAD is at ${branch.localSha} but origin/${repo.branch} does not exist. Operator must reconcile.`;
30787
- case "remote_mismatch": return `${prefix}: local HEAD ${branch.localSha} does not match origin/${repo.branch} ${branch.remoteSha}. Run 'ctxe repair' if local can fast-forward; otherwise reconcile manually.`;
30788
- case "ready":
30789
- case "ready_empty": return `${prefix}: state '${branch.kind}' is unexpectedly being treated as not ready (this is a bug).`;
30790
- }
30791
- }
30792
30922
  function formatDirtyTreeError(repo, paths) {
30793
30923
  const list = formatWorkingTreePaths(paths);
30794
30924
  return `Engine root '${repo.rootDir}' has uncommitted or untracked changes:\n${list}`;
@@ -30861,11 +30991,11 @@ function branchIssueFor(branch) {
30861
30991
  };
30862
30992
  case "local_head_without_remote_main": return {
30863
30993
  code: "local_head_without_remote_main",
30864
- message: `Local HEAD is at ${branch.localSha} but origin/main does not exist. Operator must reconcile manually.`
30994
+ message: `Local HEAD is at ${branch.localSha} but origin/main does not exist. Run 'ctxe repair' (publishes the local commits, or discards them if origin was created meanwhile).`
30865
30995
  };
30866
30996
  case "remote_mismatch": return {
30867
30997
  code: "remote_mismatch",
30868
- message: `Local HEAD ${branch.localSha} does not match origin/main ${branch.remoteSha}. If local is behind, run 'ctxe repair'; otherwise reconcile manually.`
30998
+ message: `Local HEAD ${branch.localSha} does not match origin/main ${branch.remoteSha}. Run 'ctxe repair' (fast-forwards when behind; publishes or discards own commits when ahead/diverged).`
30869
30999
  };
30870
31000
  }
30871
31001
  }
@@ -30884,7 +31014,8 @@ _enum([
30884
31014
  "success",
30885
31015
  "failed",
30886
31016
  "timed_out",
30887
- "rate_limited"
31017
+ "rate_limited",
31018
+ "stale"
30888
31019
  ]);
30889
31020
  const runStatusSchema = _enum([
30890
31021
  "starting",
@@ -30893,6 +31024,7 @@ const runStatusSchema = _enum([
30893
31024
  "failed",
30894
31025
  "timed_out",
30895
31026
  "rate_limited",
31027
+ "stale",
30896
31028
  "interrupted"
30897
31029
  ]);
30898
31030
  const claudeResultSchema = strictObject({
@@ -31058,23 +31190,35 @@ function compareRunRecordEntries(left, right) {
31058
31190
  if (timeCompare !== 0) return timeCompare;
31059
31191
  return right.runId.localeCompare(left.runId);
31060
31192
  }
31061
- async function runRootFastForward(repo) {
31193
+ async function runRootReconcile(repo) {
31062
31194
  await assertGitCheckout(repo);
31063
31195
  const branch = await inspectBranchReadiness(repo);
31064
31196
  const tree = await inspectWorkingTree(repo);
31065
31197
  if (branch.kind === "no_origin") throw new Error("RootRepair requires 'origin' to be configured. Provisioning must add origin before repair.");
31066
- if (branch.kind === "local_head_without_remote_main") throw new Error(`RootRepair refuses to act: local HEAD is at ${branch.localSha} but origin/${repo.branch} does not exist. Operator must reconcile manually.`);
31067
- const needsFastForward = branch.kind === "local_unborn_remote_has_main" || branch.kind === "remote_mismatch";
31068
- if (needsFastForward && !tree.clean) throw new Error(formatCombinedRepairError(repo, branch, tree));
31069
- if (needsFastForward) return {
31070
- kind: "fast_forward",
31071
- ...await fastForwardRoot(repo)
31198
+ if (branch.kind === "ready" || branch.kind === "ready_empty") return { kind: "no_op" };
31199
+ if (!tree.clean) throw new Error(formatCombinedRepairError(repo, branch, tree));
31200
+ if (branch.kind === "local_head_without_remote_main") return await publishOrDiscard(repo, branch.localSha);
31201
+ const ff = await fastForwardRoot(repo);
31202
+ if (ff.kind === "fast_forwarded") return {
31203
+ from: ff.from,
31204
+ kind: "fast_forwarded",
31205
+ to: ff.to
31206
+ };
31207
+ return await publishOrDiscard(repo, ff.localSha);
31208
+ }
31209
+ async function publishOrDiscard(repo, localSha) {
31210
+ if (await pushToOrigin(repo) === "pushed") return {
31211
+ kind: "published",
31212
+ sha: localSha
31213
+ };
31214
+ return {
31215
+ kind: "discarded_to_origin",
31216
+ ...await discardToOrigin(repo)
31072
31217
  };
31073
- return { kind: "no_op" };
31074
31218
  }
31075
31219
  async function runRootRepair(repo) {
31076
- const fastForward = await runRootFastForward(repo);
31077
- if (fastForward.kind === "fast_forward") return fastForward;
31220
+ const reconciled = await runRootReconcile(repo);
31221
+ if (reconciled.kind !== "no_op") return reconciled;
31078
31222
  if (!(await inspectWorkingTree(repo)).clean) return await runDirtyRootRepair(repo);
31079
31223
  return { kind: "no_op" };
31080
31224
  }
@@ -31090,7 +31234,14 @@ async function runDirtyRootRepair(repo) {
31090
31234
  interruptedRunIds,
31091
31235
  repairId: v7()
31092
31236
  });
31093
- await pushToOrigin(repo);
31237
+ if (await pushToOrigin(repo) === "rejected") {
31238
+ await discardToOrigin(repo);
31239
+ return {
31240
+ commit: null,
31241
+ interruptedRunIds,
31242
+ kind: "dirty_root_repair"
31243
+ };
31244
+ }
31094
31245
  return {
31095
31246
  commit: { sha },
31096
31247
  interruptedRunIds,
@@ -31100,7 +31251,7 @@ async function runDirtyRootRepair(repo) {
31100
31251
  function formatCombinedRepairError(repo, branch, tree) {
31101
31252
  const dirtyPaths = tree.clean ? "(clean)" : formatWorkingTreePaths(tree.paths);
31102
31253
  return [
31103
- "RootRepair refuses to combine branch fast-forward with dirty-root repair in v1.",
31254
+ "RootRepair refuses to combine branch reconcile with dirty-root repair in v1.",
31104
31255
  `Branch: ${branch.kind === "local_unborn_remote_has_main" ? `local checkout is unborn but origin/${repo.branch} exists` : branch.kind === "remote_mismatch" ? `local HEAD does not match origin/${repo.branch}` : `branch state is '${branch.kind}'`}.`,
31105
31256
  "Dirty paths:",
31106
31257
  dirtyPaths,
@@ -31250,22 +31401,6 @@ function fromParseError(error) {
31250
31401
  sourcePath: error.sourcePath
31251
31402
  };
31252
31403
  }
31253
- const MICROSANDBOX_HOST_ALIAS = "host.microsandbox.internal";
31254
- const HOST_LOOPBACK_HOSTNAMES = new Set([
31255
- "localhost",
31256
- "127.0.0.1",
31257
- "0.0.0.0"
31258
- ]);
31259
- const IPV6_LOOPBACK_HOSTNAMES = new Set(["[::1]", "[::]"]);
31260
- function rewriteHostUrlForGuest(url) {
31261
- const parsed = new URL(url);
31262
- const hostname = parsed.hostname.toLowerCase();
31263
- if (HOST_LOOPBACK_HOSTNAMES.has(hostname) || IPV6_LOOPBACK_HOSTNAMES.has(hostname)) {
31264
- parsed.hostname = MICROSANDBOX_HOST_ALIAS;
31265
- return parsed.toString();
31266
- }
31267
- return url;
31268
- }
31269
31404
  function assembleGuestEnv(input) {
31270
31405
  return {
31271
31406
  ...input.contextEngineEnv,
@@ -31514,7 +31649,13 @@ async function finalizeSuccessfulSynthesizerTransaction(input) {
31514
31649
  await rollbackAfterTransactionCommitFailure(input.repo);
31515
31650
  throw commitError;
31516
31651
  }
31517
- await pushToOrigin(input.repo);
31652
+ if (await pushToOrigin(input.repo) === "rejected") {
31653
+ await discardToOrigin(input.repo);
31654
+ return {
31655
+ ...input.record,
31656
+ status: "stale"
31657
+ };
31658
+ }
31518
31659
  return input.record;
31519
31660
  }
31520
31661
  async function finalizeFailedSynthesizerTransaction(input) {
@@ -31526,7 +31667,7 @@ async function finalizeFailedSynthesizerTransaction(input) {
31526
31667
  synthesizerName: input.ctx.synthesizer.name,
31527
31668
  trigger: input.ctx.trigger
31528
31669
  });
31529
- await pushToOrigin(input.repo);
31670
+ if (await pushToOrigin(input.repo) === "rejected") await discardToOrigin(input.repo);
31530
31671
  return input.record;
31531
31672
  }
31532
31673
  function buildTerminalRecord(input) {
@@ -31602,8 +31743,8 @@ var Engine = class {
31602
31743
  try {
31603
31744
  let report = await runRootPreflight(this.repo);
31604
31745
  if (!report.ready) {
31605
- const repaired = await runRootFastForward(this.repo);
31606
- if (repaired.kind === "fast_forward") this.logger.info(`[engine] root was behind origin/${this.repo.branch} — fast-forwarded ${repaired.from ?? "(unborn)"} → ${repaired.to}`);
31746
+ const repaired = await runRootReconcile(this.repo);
31747
+ if (repaired.kind !== "no_op") this.logger.info(`[engine] startup reconcile: ${describeReconcile(repaired)}`);
31607
31748
  report = await runRootPreflight(this.repo);
31608
31749
  }
31609
31750
  if (!report.ready) throw new Error(formatPreflightFailure(this.repo.rootDir, report.issues));
@@ -31766,7 +31907,9 @@ var Engine = class {
31766
31907
  async runSynthesizerTransaction(request) {
31767
31908
  const releaseLock = await acquireTransactionLock(this.repo.rootDir);
31768
31909
  try {
31769
- await assertSynthesizerTransactionReady(this.repo);
31910
+ await assertCleanWorkingTree(this.repo);
31911
+ const reconciled = await runRootReconcile(this.repo);
31912
+ if (reconciled.kind !== "no_op") this.logger.info(`[engine] pre-run reconcile: ${describeReconcile(reconciled)}`);
31770
31913
  await this.refreshSynthesizers();
31771
31914
  const synthesizer = this.synthesizers.get(request.synthesizerName);
31772
31915
  if (!synthesizer) throw new Error(`Synthesizer '${request.synthesizerName}' was not found after refresh; no run record manufactured.`);
@@ -31851,6 +31994,14 @@ function sleepAbortable(ms, signal) {
31851
31994
  function formatPreflightFailure(rootDir, issues) {
31852
31995
  return `Engine root '${rootDir}' is not ready:\n${issues.map((issue) => ` [${issue.code}] ${issue.message}`).join("\n")}`;
31853
31996
  }
31997
+ function describeReconcile(result) {
31998
+ switch (result.kind) {
31999
+ case "no_op": return "no-op";
32000
+ case "fast_forwarded": return `fast-forwarded ${result.from ?? "(unborn)"} → ${result.to}`;
32001
+ case "published": return `published own unpushed commit ${result.sha}`;
32002
+ case "discarded_to_origin": return `discarded own commit ${result.discardedSha ?? "(none)"} to origin ${result.originSha} (someone else advanced)`;
32003
+ }
32004
+ }
31854
32005
  function assembleEngineStatus(input) {
31855
32006
  const observation = input.syncHorizon;
31856
32007
  const horizon = observation.kind === "captured" ? observation.horizon : null;
@@ -32220,7 +32371,7 @@ async function runRootReset(repo, options = {}) {
32220
32371
  });
32221
32372
  if ((await inspectWorkingTree(repo)).clean) return { kind: "no_op" };
32222
32373
  const { sha } = await commitRootReset(repo, { resetId: v7() });
32223
- await pushToOrigin(repo);
32374
+ if (await pushToOrigin(repo) === "rejected") throw new Error(`Reset commit ${sha} was not pushed: origin/${repo.branch} advanced during the reset (non-fast-forward). Nothing was reset on origin. Re-run 'ctxe reset' against the new head.`);
32224
32375
  return {
32225
32376
  commit: { sha },
32226
32377
  kind: "reset",
@@ -32397,6 +32548,19 @@ var ForbiddenError$1 = class extends BaseAPIError {
32397
32548
  this.name = "ForbiddenError";
32398
32549
  }
32399
32550
  };
32551
+ var NotFoundError$1 = class extends BaseAPIError {
32552
+ constructor(body, rawResponse) {
32553
+ super({
32554
+ message: "NotFoundError",
32555
+ statusCode: 404,
32556
+ body,
32557
+ rawResponse
32558
+ });
32559
+ Object.setPrototypeOf(this, new.target.prototype);
32560
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
32561
+ this.name = "NotFoundError";
32562
+ }
32563
+ };
32400
32564
  function mergeHeaders$1(...headersArray) {
32401
32565
  const result = {};
32402
32566
  for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
@@ -33616,7 +33780,7 @@ function createIdentitySchemaCreator$1(schemaType, validate) {
33616
33780
  };
33617
33781
  };
33618
33782
  }
33619
- function enum_(values) {
33783
+ function enum_$1(values) {
33620
33784
  const validValues = new Set(values);
33621
33785
  return createIdentitySchemaCreator$1(SchemaType$1.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
33622
33786
  if (typeof value !== "string") return {
@@ -34182,7 +34346,7 @@ const _hasOwn$4 = Object.prototype.hasOwnProperty;
34182
34346
  function union(discriminant, union) {
34183
34347
  const rawDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.rawDiscriminant;
34184
34348
  const parsedDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.parsedDiscriminant;
34185
- const discriminantValueSchema = enum_(keys$1(union));
34349
+ const discriminantValueSchema = enum_$1(keys$1(union));
34186
34350
  const baseSchema = {
34187
34351
  parse: (raw, opts) => {
34188
34352
  return transformAndValidateUnion({
@@ -34435,7 +34599,7 @@ const Binding = object$1({
34435
34599
  updatedAt: property$1("updated_at", date$1())
34436
34600
  });
34437
34601
  const ListBindingsResponse = object$1({ bindings: list$1(Binding) });
34438
- const RunStatus = enum_([
34602
+ const RunStatus = enum_$1([
34439
34603
  "QUEUED",
34440
34604
  "NOT_STARTED",
34441
34605
  "MANAGED",
@@ -34484,7 +34648,7 @@ const BindingStateResponse = object$1({
34484
34648
  bindings: record(string$1(), BindingState),
34485
34649
  version: number$1()
34486
34650
  });
34487
- const DagsterAllPlanBindingMode = enum_(["dagster"]);
34651
+ const DagsterAllPlanBindingMode = enum_$1(["dagster"]);
34488
34652
  const DagsterAllPlanBinding = object$1({
34489
34653
  auth: BindingAuth,
34490
34654
  bindingId: property$1("binding_id", string$1()),
@@ -34666,6 +34830,62 @@ var BasesClient = class {
34666
34830
  }
34667
34831
  return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "GET", "/base/bases/{base_id}");
34668
34832
  }
34833
+ /**
34834
+ * @param {BaseAPI.DeleteBaseRequest} request
34835
+ * @param {BasesClient.RequestOptions} requestOptions - Request-specific configuration.
34836
+ *
34837
+ * @throws {@link BaseAPI.ForbiddenError}
34838
+ * @throws {@link BaseAPI.NotFoundError}
34839
+ *
34840
+ * @example
34841
+ * await client.bases.deleteBase({
34842
+ * baseId: "base_id"
34843
+ * })
34844
+ */
34845
+ deleteBase(request, requestOptions) {
34846
+ return HttpResponsePromise$1.fromPromise(this.__deleteBase(request, requestOptions));
34847
+ }
34848
+ async __deleteBase(request, requestOptions) {
34849
+ const { baseId } = request;
34850
+ const _headers = mergeHeaders$1(this._options?.headers, requestOptions?.headers);
34851
+ const _response = await fetcher$1({
34852
+ url: join$1(await Supplier$1.get(this._options.baseUrl) ?? await Supplier$1.get(this._options.environment), `base/bases/${encodePathParam$1(baseId)}`),
34853
+ method: "DELETE",
34854
+ headers: _headers,
34855
+ queryString: queryBuilder$1().mergeAdditional(requestOptions?.queryParams).build(),
34856
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
34857
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
34858
+ abortSignal: requestOptions?.abortSignal,
34859
+ fetchFn: this._options?.fetch,
34860
+ logging: this._options.logging
34861
+ });
34862
+ if (_response.ok) return {
34863
+ data: void 0,
34864
+ rawResponse: _response.rawResponse
34865
+ };
34866
+ if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
34867
+ case 403: throw new ForbiddenError$1(Error_$1.parseOrThrow(_response.error.body, {
34868
+ unrecognizedObjectKeys: "passthrough",
34869
+ allowUnrecognizedUnionMembers: true,
34870
+ allowUnrecognizedEnumValues: true,
34871
+ skipValidation: true,
34872
+ breadcrumbsPrefix: ["response"]
34873
+ }), _response.rawResponse);
34874
+ case 404: throw new NotFoundError$1(Error_$1.parseOrThrow(_response.error.body, {
34875
+ unrecognizedObjectKeys: "passthrough",
34876
+ allowUnrecognizedUnionMembers: true,
34877
+ allowUnrecognizedEnumValues: true,
34878
+ skipValidation: true,
34879
+ breadcrumbsPrefix: ["response"]
34880
+ }), _response.rawResponse);
34881
+ default: throw new BaseAPIError({
34882
+ statusCode: _response.error.statusCode,
34883
+ body: _response.error.body,
34884
+ rawResponse: _response.rawResponse
34885
+ });
34886
+ }
34887
+ return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "DELETE", "/base/bases/{base_id}");
34888
+ }
34669
34889
  };
34670
34890
  var BindingPlanClient = class {
34671
34891
  _options;
@@ -35230,6 +35450,19 @@ var ForbiddenError = class extends SlateAPIError {
35230
35450
  this.name = "ForbiddenError";
35231
35451
  }
35232
35452
  };
35453
+ var NotFoundError = class extends SlateAPIError {
35454
+ constructor(body, rawResponse) {
35455
+ super({
35456
+ message: "NotFoundError",
35457
+ statusCode: 404,
35458
+ body,
35459
+ rawResponse
35460
+ });
35461
+ Object.setPrototypeOf(this, new.target.prototype);
35462
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
35463
+ this.name = "NotFoundError";
35464
+ }
35465
+ };
35233
35466
  function mergeHeaders(...headersArray) {
35234
35467
  const result = {};
35235
35468
  for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
@@ -36449,6 +36682,29 @@ function createIdentitySchemaCreator(schemaType, validate) {
36449
36682
  };
36450
36683
  };
36451
36684
  }
36685
+ function enum_(values) {
36686
+ const validValues = new Set(values);
36687
+ return createIdentitySchemaCreator(SchemaType.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
36688
+ if (typeof value !== "string") return {
36689
+ ok: false,
36690
+ errors: [{
36691
+ path: breadcrumbsPrefix,
36692
+ message: getErrorMessageForIncorrectType(value, "string")
36693
+ }]
36694
+ };
36695
+ if (!validValues.has(value) && !allowUnrecognizedEnumValues) return {
36696
+ ok: false,
36697
+ errors: [{
36698
+ path: breadcrumbsPrefix,
36699
+ message: getErrorMessageForIncorrectType(value, "enum")
36700
+ }]
36701
+ };
36702
+ return {
36703
+ ok: true,
36704
+ value
36705
+ };
36706
+ })();
36707
+ }
36452
36708
  function entries(object) {
36453
36709
  return Object.entries(object);
36454
36710
  }
@@ -37023,6 +37279,8 @@ const CreateWorkspaceInput = object({
37023
37279
  synthesizerImage: property("synthesizer_image", string().optional()),
37024
37280
  tick: string().optional()
37025
37281
  });
37282
+ const DeleteWorkspaceRequestDeleteBases = enum_(["true", "false"]);
37283
+ const DeleteWorkspaceRequestDeleteRepos = enum_(["true", "false"]);
37026
37284
  const BridgePlan = object({
37027
37285
  baseIds: property("base_ids", list(string())),
37028
37286
  claudeOauthToken: property("claude_oauth_token", string().nullable()),
@@ -37464,6 +37722,72 @@ var WorkspacesClient = class {
37464
37722
  }
37465
37723
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/slate/workspaces");
37466
37724
  }
37725
+ /**
37726
+ * @param {SlateAPI.DeleteWorkspaceRequest} request
37727
+ * @param {WorkspacesClient.RequestOptions} requestOptions - Request-specific configuration.
37728
+ *
37729
+ * @throws {@link SlateAPI.ForbiddenError}
37730
+ * @throws {@link SlateAPI.NotFoundError}
37731
+ *
37732
+ * @example
37733
+ * await client.workspaces.deleteWorkspace({
37734
+ * workspaceId: "workspace_id"
37735
+ * })
37736
+ */
37737
+ deleteWorkspace(request, requestOptions) {
37738
+ return HttpResponsePromise.fromPromise(this.__deleteWorkspace(request, requestOptions));
37739
+ }
37740
+ async __deleteWorkspace(request, requestOptions) {
37741
+ const { workspaceId, deleteBases, deleteRepos } = request;
37742
+ const _queryParams = {
37743
+ delete_bases: deleteBases != null ? DeleteWorkspaceRequestDeleteBases.jsonOrThrow(deleteBases, {
37744
+ unrecognizedObjectKeys: "strip",
37745
+ omitUndefined: true
37746
+ }) : void 0,
37747
+ delete_repos: deleteRepos != null ? DeleteWorkspaceRequestDeleteRepos.jsonOrThrow(deleteRepos, {
37748
+ unrecognizedObjectKeys: "strip",
37749
+ omitUndefined: true
37750
+ }) : void 0
37751
+ };
37752
+ const _headers = mergeHeaders(this._options?.headers, requestOptions?.headers);
37753
+ const _response = await fetcher({
37754
+ url: join(await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment), `slate/workspaces/${encodePathParam(workspaceId)}`),
37755
+ method: "DELETE",
37756
+ headers: _headers,
37757
+ queryString: queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
37758
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
37759
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
37760
+ abortSignal: requestOptions?.abortSignal,
37761
+ fetchFn: this._options?.fetch,
37762
+ logging: this._options.logging
37763
+ });
37764
+ if (_response.ok) return {
37765
+ data: void 0,
37766
+ rawResponse: _response.rawResponse
37767
+ };
37768
+ if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
37769
+ case 403: throw new ForbiddenError(Error_.parseOrThrow(_response.error.body, {
37770
+ unrecognizedObjectKeys: "passthrough",
37771
+ allowUnrecognizedUnionMembers: true,
37772
+ allowUnrecognizedEnumValues: true,
37773
+ skipValidation: true,
37774
+ breadcrumbsPrefix: ["response"]
37775
+ }), _response.rawResponse);
37776
+ case 404: throw new NotFoundError(Error_.parseOrThrow(_response.error.body, {
37777
+ unrecognizedObjectKeys: "passthrough",
37778
+ allowUnrecognizedUnionMembers: true,
37779
+ allowUnrecognizedEnumValues: true,
37780
+ skipValidation: true,
37781
+ breadcrumbsPrefix: ["response"]
37782
+ }), _response.rawResponse);
37783
+ default: throw new SlateAPIError({
37784
+ statusCode: _response.error.statusCode,
37785
+ body: _response.error.body,
37786
+ rawResponse: _response.rawResponse
37787
+ });
37788
+ }
37789
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/slate/workspaces/{workspace_id}");
37790
+ }
37467
37791
  };
37468
37792
  var SlateAPIClient = class {
37469
37793
  _options;
@@ -38586,7 +38910,7 @@ function createProgram() {
38586
38910
  program.command("preflight").description("Report whether the ContextEngine root is ready to run. Validation-only; never mutates the checkout. Exits non-zero when not ready.").action(async function() {
38587
38911
  await runPreflightCommand(resolveRepoContext(this));
38588
38912
  });
38589
- program.command("repair").description("Explicit out-of-band root repair: safe fast-forward when clean and stale, or dirty-root rollback that preserves .engine/runs/**. Refuses local-ahead state, divergence, and the combined stale-plus-dirty case.").action(async function() {
38913
+ program.command("repair").description("Explicit out-of-band root repair: reconciles the root against origin (fast-forward when behind; publish own unpushed commits, or discard them to origin when the push is rejected) and rolls back a dirty tree preserving .engine/runs/**.").action(async function() {
38590
38914
  await runRepairCommand(resolveRepoContext(this));
38591
38915
  });
38592
38916
  program.command("reset").option("--yes", "Execute the reset (delete cursors + wipe synthesized content, then commit). Without it, prints the plan and exits without mutating.").option("--force", "Reset even when the root is not preflight-ready (e.g. a dirty working tree). Use with care; normally you commit authored config or run 'ctxe repair' first.").description("Reset the whole workspace to a clean pre-synthesis state so it can be rebuilt from scratch: delete every synthesizer cursor (the next run bootstraps from the configured oldestConsideredPoint) and wipe all synthesized content under output/ except the authored types/ and views/, in one commit. Whole-workspace by design — output/ is not partitioned by synthesizer. Preserves .engine/runs/**. Default is a dry run; pass --yes to execute, then rebuild with 'ctxe backfill <synthesizer>' or 'ctxe daemon start'.").action(async function(options) {
@@ -38646,4 +38970,4 @@ runCli().catch((error) => {
38646
38970
  //#endregion
38647
38971
  export { createProgram, resolveRepoContext, resolveRuntimePaths, runCli };
38648
38972
  //# sourceMappingURL=cli.mjs.map
38649
- //# debugId=6317e92d-f910-5336-9f6a-2445ebdf6ed8
38973
+ //# debugId=7463ebb3-f56d-51c5-a74a-b15957e43865