@usecontextlayer/ctxs 0.5.5 → 0.5.6

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]="5e70b90f-e938-570a-b3e3-d35af180a822")}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]="3dbc3cff-70da-5d01-b6fc-a83d63e0c3f3")}catch(e){}}();
4
4
  import { createRequire } from "node:module";
5
5
  import * as Sentry from "@sentry/node";
6
6
  import * as fs$2 from "node:fs/promises";
@@ -8,8 +8,6 @@ import { access, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm,
8
8
  import path, { sep } from "node:path";
9
9
  import { execFile } from "node:child_process";
10
10
  import { formatWithOptions, promisify } from "node:util";
11
- import { existsSync } from "node:fs";
12
- import { fileURLToPath } from "node:url";
13
11
  import { serve } from "@hono/node-server";
14
12
  import { createNodeWebSocket } from "@hono/node-ws";
15
13
  import { Hono } from "hono";
@@ -25,6 +23,8 @@ import tls from "tls";
25
23
  import crypto$1 from "crypto";
26
24
  import Stream from "stream";
27
25
  import { performance } from "perf_hooks";
26
+ import { existsSync } from "node:fs";
27
+ import { fileURLToPath } from "node:url";
28
28
  import { getSessionMessages } from "@anthropic-ai/claude-agent-sdk";
29
29
  import { query } from "@anthropic-ai/claude-agent-sdk/browser";
30
30
  import g$1 from "node:process";
@@ -60,7 +60,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
60
60
 
61
61
  //#endregion
62
62
  //#region package.json
63
- var version$2 = "0.5.5";
63
+ var version$2 = "0.5.6";
64
64
 
65
65
  //#endregion
66
66
  //#region sentry.ts
@@ -264,13 +264,21 @@ async function cloneRepo(repo) {
264
264
  ], { auth: repo.remote });
265
265
  }
266
266
  /**
267
- * Snapshot the working dir to pggit: `add -A` -> commit -> `push --force`. A no-op if
267
+ * Snapshot the working dir to pggit: `add -A` -> commit -> plain `push`. A no-op if
268
268
  * nothing changed (a per-turn snapshot may find no new bytes under eventual consistency).
269
269
  * Excludes (`.credentials.json`, `.DS_Store`) come from a `.gitignore` the caller commits,
270
- * not from this function. Self-initializes a fresh dir (the capture-only engine home is
271
- * never cloned), so it works for both the restored (slate) and fresh (engine) cases.
270
+ * not from this function. Self-initializes a fresh dir, so it works for both the
271
+ * restored (slate) and fresh cases.
272
+ *
273
+ * NON-FORCE is load-bearing (the workspace-writes no-overwrites invariant):
274
+ * a snapshot may only ADVANCE the remote. A home is single-writer
275
+ * (one repoId ↔ one owning process — ClaudeRepo's premise), so its history is
276
+ * linear and a plain push always fast-forwards. The accident class this blocks:
277
+ * a self-inited fresh dir pushing over an existing remote's real history is a
278
+ * LOUD client-side rejection instead of silent destruction (and
279
+ * pggit's deny-non-FF is the server backstop).
272
280
  */
273
- async function forcePushSnapshot(repo, opts) {
281
+ async function pushSnapshot(repo, opts) {
274
282
  await ensureGitRepo(repo);
275
283
  await runGit(["add", "-A"], { cwd: repo.hostDir });
276
284
  if ((await runGit([
@@ -289,7 +297,6 @@ async function forcePushSnapshot(repo, opts) {
289
297
  ], { cwd: repo.hostDir });
290
298
  await runGit([
291
299
  "push",
292
- "--force",
293
300
  "origin",
294
301
  `HEAD:${BRANCH}`
295
302
  ], {
@@ -316,11 +323,33 @@ async function localHead(repo) {
316
323
  return result.stdout.trim() || null;
317
324
  }
318
325
  /**
319
- * Fast-forward the working dir to the remote tip (`fetch` + `reset --hard`) the
320
- * refresh half of the read-copy model: callers HEAD-gate it so a reader catches the
321
- * engine's pushes without paying a fetch when nothing changed.
326
+ * Is there a writer's live work in the tree uncommitted changes, untracked files,
327
+ * or a merge in flight? `status --porcelain` covers modified/untracked/conflicted;
328
+ * the MERGE_HEAD probe covers the one state porcelain can miss (a merge whose
329
+ * resolution happens to match HEAD exactly). Callers treat `true` as "the tree is
330
+ * owned; touching it would be an overwrite."
331
+ */
332
+ async function hasUncommittedWork(repo) {
333
+ if ((await runGit(["status", "--porcelain"], { cwd: repo.hostDir })).stdout.trim() !== "") return true;
334
+ return (await runGit([
335
+ "rev-parse",
336
+ "-q",
337
+ "--verify",
338
+ "MERGE_HEAD"
339
+ ], {
340
+ cwd: repo.hostDir,
341
+ throwOnNonZero: false
342
+ })).exitCode === 0;
343
+ }
344
+ /**
345
+ * Fetch the remote tip and integrate by PURE fast-forward or not at all (`merge
346
+ * --ff-only`) — the refresh half of the landlord model. `refused` means local
347
+ * commits exist that origin lacks (an unfinished heal): the caller serves the
348
+ * local tree as-is — which history wins is the healing session's business, never
349
+ * this function's. Fetch failures (network, auth) still throw — those are
350
+ * infrastructure, not divergence.
322
351
  */
323
- async function fetchToHead(repo) {
352
+ async function fastForwardToRemote(repo) {
324
353
  await runGit([
325
354
  "fetch",
326
355
  "origin",
@@ -329,11 +358,14 @@ async function fetchToHead(repo) {
329
358
  auth: repo.remote,
330
359
  cwd: repo.hostDir
331
360
  });
332
- await runGit([
333
- "reset",
334
- "--hard",
361
+ return (await runGit([
362
+ "merge",
363
+ "--ff-only",
335
364
  "FETCH_HEAD"
336
- ], { cwd: repo.hostDir });
365
+ ], {
366
+ cwd: repo.hostDir,
367
+ throwOnNonZero: false
368
+ })).exitCode === 0 ? "fast_forwarded" : "refused";
337
369
  }
338
370
  async function ensureGitRepo(repo) {
339
371
  const inside = await runGit(["rev-parse", "--is-inside-work-tree"], {
@@ -593,9 +625,11 @@ var ClaudeRepo = class ClaudeRepo {
593
625
  * Clone-on-first-use into the host dir (slate resume). A no-op for a capture-only
594
626
  * home (`restore:false`) and after the first success — memoized so concurrent sessions
595
627
  * don't double-clone. Restore failure **propagates**: the caller blocks the connection
596
- * — no boot → no capture → the good repo is untouched (proceeding fresh would
597
- * force-push a blank home over real history). The memo is cleared on failure so a later
598
- * connection retries rather than inheriting a permanent rejection.
628
+ * — no boot → no capture → the good repo is untouched. (Proceeding fresh would try to
629
+ * push a blank home over real history a loud non-force rejection rather than
630
+ * silent destruction, but restore-first stays the invariant:
631
+ * a rejected capture is still a broken session.) The memo is cleared on failure so a
632
+ * later connection retries rather than inheriting a permanent rejection.
599
633
  */
600
634
  async restore() {
601
635
  if (!this.config.restore) return;
@@ -614,7 +648,8 @@ var ClaudeRepo = class ClaudeRepo {
614
648
  }
615
649
  /**
616
650
  * The per-turn snapshot: serialized by the mutex — rebuild the index from the live
617
- * home (when maintaining it), then force-push the whole dir. Capture failure is caught +
651
+ * home (when maintaining it), then push the whole dir (non-force; a home is
652
+ * single-writer so the push always fast-forwards). Capture failure is caught +
618
653
  * logged **loud**, never propagated — the turn already happened and the next snapshot
619
654
  * pushes the cumulative state. The one non-self-healing case is an expired token's 401:
620
655
  * the push auth is the connection's upgrade-time user token (real mint TTL: 15 minutes),
@@ -628,7 +663,7 @@ var ClaudeRepo = class ClaudeRepo {
628
663
  try {
629
664
  await this.ensureGitignore();
630
665
  if (this.config.maintainIndex) await this.writeSessionIndex();
631
- await forcePushSnapshot(this.repo, { message: opts.message });
666
+ await pushSnapshot(this.repo, { message: opts.message });
632
667
  } catch (err) {
633
668
  console.error(`[ClaudeRepo] capture failed (${this.repo.remote.repoId}):`, err);
634
669
  }
@@ -793,6 +828,40 @@ async function drainExecStream(handle, options) {
793
828
  signal?.removeEventListener("abort", onAbort);
794
829
  }
795
830
  }
831
+ const MICROSANDBOX_HOST_ALIAS = "host.microsandbox.internal";
832
+ const HOST_LOOPBACK_HOSTNAMES = new Set([
833
+ "localhost",
834
+ "127.0.0.1",
835
+ "0.0.0.0"
836
+ ]);
837
+ const IPV6_LOOPBACK_HOSTNAMES = new Set(["[::1]", "[::]"]);
838
+ function rewriteHostUrlForGuest(url) {
839
+ const parsed = new URL(url);
840
+ const hostname = parsed.hostname.toLowerCase();
841
+ if (HOST_LOOPBACK_HOSTNAMES.has(hostname) || IPV6_LOOPBACK_HOSTNAMES.has(hostname)) {
842
+ parsed.hostname = MICROSANDBOX_HOST_ALIAS;
843
+ return parsed.toString();
844
+ }
845
+ return url;
846
+ }
847
+ function guestGitEnv(input) {
848
+ const guestBase = rewriteHostUrlForGuest(input.platformUrl).replace(/\/+$/, "");
849
+ const configs = [];
850
+ if (guestBase !== input.platformUrl) configs.push([`url.${guestBase}/git/.insteadOf`, `${input.platformUrl}/git/`]);
851
+ configs.push([`http.${guestBase}/git/.extraHeader`, `Authorization: Bearer ${input.token}`]);
852
+ const env = {
853
+ GIT_AUTHOR_EMAIL: `${input.sub}@users.noreply.usecontextlayer.com`,
854
+ GIT_AUTHOR_NAME: input.sub,
855
+ GIT_COMMITTER_EMAIL: `${input.sub}@users.noreply.usecontextlayer.com`,
856
+ GIT_COMMITTER_NAME: input.sub,
857
+ GIT_CONFIG_COUNT: String(configs.length)
858
+ };
859
+ configs.forEach(([key, value], i) => {
860
+ env[`GIT_CONFIG_KEY_${i}`] = key;
861
+ env[`GIT_CONFIG_VALUE_${i}`] = value;
862
+ });
863
+ return env;
864
+ }
796
865
  const DEBUG_SANDBOX_NAME = "ctx-sandbox-debug";
797
866
  const DEFAULT_BOOT_COMMAND = ["uname", "-a"];
798
867
  async function runSandbox(input) {
@@ -4559,6 +4628,63 @@ function refine$1(fn, _params = {}) {
4559
4628
  function superRefine$1(fn, params) {
4560
4629
  return /* @__PURE__ */ _superRefine$1(fn, params);
4561
4630
  }
4631
+ `${JSON.stringify({ render: {
4632
+ elements: {
4633
+ body: {
4634
+ props: { text: { $item: "body" } },
4635
+ type: "Text"
4636
+ },
4637
+ card: {
4638
+ children: ["body"],
4639
+ props: { title: { $item: "title" } },
4640
+ type: "Card"
4641
+ },
4642
+ detail: {
4643
+ children: ["card"],
4644
+ props: {
4645
+ className: "mx-auto max-w-md p-8",
4646
+ direction: "vertical",
4647
+ gap: "md"
4648
+ },
4649
+ repeat: {
4650
+ key: "path",
4651
+ statePath: "/items"
4652
+ },
4653
+ type: "Stack"
4654
+ }
4655
+ },
4656
+ root: "detail"
4657
+ } }, null, " ")}`, `${JSON.stringify({ render: {
4658
+ elements: {
4659
+ card: {
4660
+ props: { title: { $item: "title" } },
4661
+ type: "Card"
4662
+ },
4663
+ list: {
4664
+ children: ["row"],
4665
+ props: {
4666
+ className: "mx-auto max-w-md p-8",
4667
+ direction: "vertical",
4668
+ gap: "md"
4669
+ },
4670
+ repeat: {
4671
+ key: "path",
4672
+ statePath: "/items"
4673
+ },
4674
+ type: "Stack"
4675
+ },
4676
+ row: {
4677
+ children: ["card"],
4678
+ on: { press: {
4679
+ action: "navigate",
4680
+ params: { path: { $template: "${path}" } }
4681
+ } },
4682
+ props: { className: null },
4683
+ type: "Pressable"
4684
+ }
4685
+ },
4686
+ root: "list"
4687
+ } }, null, " ")}`;
4562
4688
  const segmentSchema$1 = 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 '/'" });
4563
4689
  function segment$1(value, label) {
4564
4690
  const result = segmentSchema$1.safeParse(value);
@@ -4578,7 +4704,7 @@ const sessionMetaSchema$1 = object$3({
4578
4704
  sessionId: string$4()
4579
4705
  });
4580
4706
  record$2(string$4(), sessionMetaSchema$1);
4581
- async function materializeWorkspaceTree(workspaceId, ctx) {
4707
+ async function ensureWorkspaceCheckout(workspaceId, ctx) {
4582
4708
  const repo = await resolveRepo({
4583
4709
  platformUrl: ctx.platformUrl,
4584
4710
  repoId: buildRepoId$1({
@@ -4588,10 +4714,16 @@ async function materializeWorkspaceTree(workspaceId, ctx) {
4588
4714
  }),
4589
4715
  token: ctx.token
4590
4716
  }, ctx.gitHostBaseDir);
4591
- if (await isCloned(repo.hostDir)) {
4592
- if (await remoteHead(repo) !== await localHead(repo)) await fetchToHead(repo);
4593
- } else await cloneRepo(repo);
4594
4717
  return {
4718
+ freshness: await (async () => {
4719
+ if (!await isCloned(repo.hostDir)) {
4720
+ await cloneRepo(repo);
4721
+ return "cloned";
4722
+ }
4723
+ if (await hasUncommittedWork(repo)) return "held_dirty";
4724
+ if (await remoteHead(repo) !== await localHead(repo)) return await fastForwardToRemote(repo) === "fast_forwarded" ? "fresh" : "held_diverged";
4725
+ return "fresh";
4726
+ })(),
4595
4727
  head: await localHead(repo),
4596
4728
  rootDir: repo.hostDir
4597
4729
  };
@@ -4607,72 +4739,6 @@ async function isCloned(hostDir) {
4607
4739
  }
4608
4740
  }
4609
4741
 
4610
- //#endregion
4611
- //#region ../slate-bridge/dist/goldens-Kp_c_7Kf.mjs
4612
- const PARITY_SCENARIOS = [
4613
- {
4614
- name: "text-only",
4615
- turns: ["Reply with exactly one word: hello", "Now reply with exactly one word: goodbye"]
4616
- },
4617
- {
4618
- name: "code-writing",
4619
- turns: [
4620
- "Create a file calc.js that exports a function add(a, b) returning a + b. Use module.exports. Just write the file, no explanation.",
4621
- "Add a function sub(a, b) returning a - b to calc.js, keeping add. Export both.",
4622
- "Create run.js that requires ./calc.js and prints add(2, 3) and sub(5, 1), then run it with `node run.js` and show the output.",
4623
- "In one sentence, what does calc.js export now?"
4624
- ]
4625
- },
4626
- {
4627
- name: "thinking-and-error",
4628
- turns: [
4629
- "Reason carefully step by step before answering: a train travels 90 km in 1 hour 12 minutes. What is its average speed in km/h? Show your reasoning, then the answer.",
4630
- "Read the file /tmp/definitely-does-not-exist-9f3a.txt and tell me its contents.",
4631
- "In one short sentence, acknowledge that the file could not be read."
4632
- ]
4633
- },
4634
- {
4635
- name: "compaction",
4636
- turns: [
4637
- "In two short paragraphs, explain how the TCP three-way handshake works.",
4638
- "Now, in two short paragraphs, explain how a TLS 1.3 handshake works.",
4639
- "List three concrete differences between TCP and UDP.",
4640
- "/compact",
4641
- "What topics were we just discussing? Answer in one sentence.",
4642
- "Reply with exactly one word: done"
4643
- ]
4644
- },
4645
- {
4646
- name: "multi-file-tools",
4647
- turns: ["Create three files in the current directory: a.txt containing exactly `alpha`, b.txt containing exactly `beta`, c.txt containing exactly `gamma`. Just create them, no explanation.", "Read a.txt, b.txt, and c.txt and tell me what each one contains."]
4648
- },
4649
- {
4650
- name: "web-tools",
4651
- turns: ["Use web search to find the current latest stable Node.js LTS major version. Report just the version number.", "In one sentence, what did you search for?"]
4652
- },
4653
- {
4654
- name: "long-conversation",
4655
- turns: [
4656
- "Name a primary color. Reply with one word.",
4657
- "Name a different primary color. Reply with one word.",
4658
- "Name the third primary color. Reply with one word.",
4659
- "What color do you get mixing red and blue? Reply with one word.",
4660
- "Summarize this conversation in one short sentence.",
4661
- "Reply with exactly one word: bye"
4662
- ]
4663
- }
4664
- ];
4665
- function resolveGoldensDir() {
4666
- let dir = path.dirname(fileURLToPath(import.meta.url));
4667
- while (true) {
4668
- const candidate = path.join(dir, "slate-shared", "lib", "__goldens__");
4669
- if (existsSync(candidate)) return candidate;
4670
- const parent = path.dirname(dir);
4671
- if (parent === dir) throw new Error(`[parity] could not locate slate-shared/lib/__goldens__ above ${fileURLToPath(import.meta.url)}`);
4672
- dir = parent;
4673
- }
4674
- }
4675
-
4676
4742
  //#endregion
4677
4743
  //#region ../base-client/dist/index.mjs
4678
4744
  /**
@@ -4757,6 +4823,19 @@ var ForbiddenError$1 = class extends BaseAPIError {
4757
4823
  this.name = "ForbiddenError";
4758
4824
  }
4759
4825
  };
4826
+ var NotFoundError$1 = class extends BaseAPIError {
4827
+ constructor(body, rawResponse) {
4828
+ super({
4829
+ message: "NotFoundError",
4830
+ statusCode: 404,
4831
+ body,
4832
+ rawResponse
4833
+ });
4834
+ Object.setPrototypeOf(this, new.target.prototype);
4835
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
4836
+ this.name = "NotFoundError";
4837
+ }
4838
+ };
4760
4839
  function mergeHeaders$1(...headersArray) {
4761
4840
  const result = {};
4762
4841
  for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
@@ -5976,7 +6055,7 @@ function createIdentitySchemaCreator$1(schemaType, validate) {
5976
6055
  };
5977
6056
  };
5978
6057
  }
5979
- function enum_(values) {
6058
+ function enum_$1(values) {
5980
6059
  const validValues = new Set(values);
5981
6060
  return createIdentitySchemaCreator$1(SchemaType$1.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
5982
6061
  if (typeof value !== "string") return {
@@ -6542,7 +6621,7 @@ const _hasOwn$4 = Object.prototype.hasOwnProperty;
6542
6621
  function union$1(discriminant, union) {
6543
6622
  const rawDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.rawDiscriminant;
6544
6623
  const parsedDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.parsedDiscriminant;
6545
- const discriminantValueSchema = enum_(keys$1(union));
6624
+ const discriminantValueSchema = enum_$1(keys$1(union));
6546
6625
  const baseSchema = {
6547
6626
  parse: (raw, opts) => {
6548
6627
  return transformAndValidateUnion({
@@ -6795,7 +6874,7 @@ const Binding = object$2({
6795
6874
  updatedAt: property$1("updated_at", date$3())
6796
6875
  });
6797
6876
  const ListBindingsResponse = object$2({ bindings: list$1(Binding) });
6798
- const RunStatus = enum_([
6877
+ const RunStatus = enum_$1([
6799
6878
  "QUEUED",
6800
6879
  "NOT_STARTED",
6801
6880
  "MANAGED",
@@ -6844,7 +6923,7 @@ const BindingStateResponse = object$2({
6844
6923
  bindings: record$1(string$3(), BindingState),
6845
6924
  version: number$3()
6846
6925
  });
6847
- const DagsterAllPlanBindingMode = enum_(["dagster"]);
6926
+ const DagsterAllPlanBindingMode = enum_$1(["dagster"]);
6848
6927
  const DagsterAllPlanBinding = object$2({
6849
6928
  auth: BindingAuth,
6850
6929
  bindingId: property$1("binding_id", string$3()),
@@ -7026,6 +7105,62 @@ var BasesClient = class {
7026
7105
  }
7027
7106
  return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "GET", "/base/bases/{base_id}");
7028
7107
  }
7108
+ /**
7109
+ * @param {BaseAPI.DeleteBaseRequest} request
7110
+ * @param {BasesClient.RequestOptions} requestOptions - Request-specific configuration.
7111
+ *
7112
+ * @throws {@link BaseAPI.ForbiddenError}
7113
+ * @throws {@link BaseAPI.NotFoundError}
7114
+ *
7115
+ * @example
7116
+ * await client.bases.deleteBase({
7117
+ * baseId: "base_id"
7118
+ * })
7119
+ */
7120
+ deleteBase(request, requestOptions) {
7121
+ return HttpResponsePromise$1.fromPromise(this.__deleteBase(request, requestOptions));
7122
+ }
7123
+ async __deleteBase(request, requestOptions) {
7124
+ const { baseId } = request;
7125
+ const _headers = mergeHeaders$1(this._options?.headers, requestOptions?.headers);
7126
+ const _response = await fetcher$1({
7127
+ url: join$1(await Supplier$1.get(this._options.baseUrl) ?? await Supplier$1.get(this._options.environment), `base/bases/${encodePathParam$1(baseId)}`),
7128
+ method: "DELETE",
7129
+ headers: _headers,
7130
+ queryString: queryBuilder$1().mergeAdditional(requestOptions?.queryParams).build(),
7131
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
7132
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
7133
+ abortSignal: requestOptions?.abortSignal,
7134
+ fetchFn: this._options?.fetch,
7135
+ logging: this._options.logging
7136
+ });
7137
+ if (_response.ok) return {
7138
+ data: void 0,
7139
+ rawResponse: _response.rawResponse
7140
+ };
7141
+ if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
7142
+ case 403: throw new ForbiddenError$1(Error_$1.parseOrThrow(_response.error.body, {
7143
+ unrecognizedObjectKeys: "passthrough",
7144
+ allowUnrecognizedUnionMembers: true,
7145
+ allowUnrecognizedEnumValues: true,
7146
+ skipValidation: true,
7147
+ breadcrumbsPrefix: ["response"]
7148
+ }), _response.rawResponse);
7149
+ case 404: throw new NotFoundError$1(Error_$1.parseOrThrow(_response.error.body, {
7150
+ unrecognizedObjectKeys: "passthrough",
7151
+ allowUnrecognizedUnionMembers: true,
7152
+ allowUnrecognizedEnumValues: true,
7153
+ skipValidation: true,
7154
+ breadcrumbsPrefix: ["response"]
7155
+ }), _response.rawResponse);
7156
+ default: throw new BaseAPIError({
7157
+ statusCode: _response.error.statusCode,
7158
+ body: _response.error.body,
7159
+ rawResponse: _response.rawResponse
7160
+ });
7161
+ }
7162
+ return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "DELETE", "/base/bases/{base_id}");
7163
+ }
7029
7164
  };
7030
7165
  var BindingPlanClient = class {
7031
7166
  _options;
@@ -8662,7 +8797,7 @@ function decodeJwt(jwt) {
8662
8797
  }
8663
8798
 
8664
8799
  //#endregion
8665
- //#region ../shared/dist/index.mjs
8800
+ //#region ../shared/dist/verify-ctx-token-BbswNLaV.mjs
8666
8801
  /**
8667
8802
  * Global authentication middleware for a platform resource server: require a
8668
8803
  * Bearer `aud=ctx` token and verify it offline via the injected verifier. A
@@ -8689,6 +8824,7 @@ function createCtxAuthMiddleware(verify, machineAzpAllowlist) {
8689
8824
  if (!token) return c.json({ error: "Missing bearer token." }, 401);
8690
8825
  const result = await verify(token);
8691
8826
  if (!result.ok) return c.json({ error: "Invalid token." }, 401);
8827
+ c.set("bearer", token);
8692
8828
  if (result.kind === "machine") {
8693
8829
  if (!machineAzpAllowlist.has(result.azp)) return c.json({ error: "Machine client not allowed." }, 403);
8694
8830
  c.set("machine", true);
@@ -8696,10 +8832,6 @@ function createCtxAuthMiddleware(verify, machineAzpAllowlist) {
8696
8832
  await next();
8697
8833
  };
8698
8834
  }
8699
- function ctxAuthHeaders(tokenProvider) {
8700
- if (!tokenProvider) return {};
8701
- return { headers: { Authorization: async () => `Bearer ${await tokenProvider()}` } };
8702
- }
8703
8835
  /**
8704
8836
  * jose error codes that mean "the presented token is invalid" → reject (401),
8705
8837
  * `reason` is the code (for logging only). Anything else — a JWKS timeout, a
@@ -8811,6 +8943,13 @@ function createDevJwtVerifier() {
8811
8943
  };
8812
8944
  }
8813
8945
 
8946
+ //#endregion
8947
+ //#region ../shared/dist/index.mjs
8948
+ function ctxAuthHeaders(tokenProvider) {
8949
+ if (!tokenProvider) return {};
8950
+ return { headers: { Authorization: async () => `Bearer ${await tokenProvider()}` } };
8951
+ }
8952
+
8814
8953
  //#endregion
8815
8954
  //#region ../slate-client/dist/index.mjs
8816
8955
  /**
@@ -8895,6 +9034,19 @@ var ForbiddenError = class extends SlateAPIError {
8895
9034
  this.name = "ForbiddenError";
8896
9035
  }
8897
9036
  };
9037
+ var NotFoundError = class extends SlateAPIError {
9038
+ constructor(body, rawResponse) {
9039
+ super({
9040
+ message: "NotFoundError",
9041
+ statusCode: 404,
9042
+ body,
9043
+ rawResponse
9044
+ });
9045
+ Object.setPrototypeOf(this, new.target.prototype);
9046
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
9047
+ this.name = "NotFoundError";
9048
+ }
9049
+ };
8898
9050
  function mergeHeaders(...headersArray) {
8899
9051
  const result = {};
8900
9052
  for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
@@ -10114,6 +10266,29 @@ function createIdentitySchemaCreator(schemaType, validate) {
10114
10266
  };
10115
10267
  };
10116
10268
  }
10269
+ function enum_(values) {
10270
+ const validValues = new Set(values);
10271
+ return createIdentitySchemaCreator(SchemaType.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
10272
+ if (typeof value !== "string") return {
10273
+ ok: false,
10274
+ errors: [{
10275
+ path: breadcrumbsPrefix,
10276
+ message: getErrorMessageForIncorrectType(value, "string")
10277
+ }]
10278
+ };
10279
+ if (!validValues.has(value) && !allowUnrecognizedEnumValues) return {
10280
+ ok: false,
10281
+ errors: [{
10282
+ path: breadcrumbsPrefix,
10283
+ message: getErrorMessageForIncorrectType(value, "enum")
10284
+ }]
10285
+ };
10286
+ return {
10287
+ ok: true,
10288
+ value
10289
+ };
10290
+ })();
10291
+ }
10117
10292
  function entries(object) {
10118
10293
  return Object.entries(object);
10119
10294
  }
@@ -10688,6 +10863,8 @@ const CreateWorkspaceInput = object$1({
10688
10863
  synthesizerImage: property("synthesizer_image", string$2().optional()),
10689
10864
  tick: string$2().optional()
10690
10865
  });
10866
+ const DeleteWorkspaceRequestDeleteBases = enum_(["true", "false"]);
10867
+ const DeleteWorkspaceRequestDeleteRepos = enum_(["true", "false"]);
10691
10868
  const BridgePlan = object$1({
10692
10869
  baseIds: property("base_ids", list(string$2())),
10693
10870
  claudeOauthToken: property("claude_oauth_token", string$2().nullable()),
@@ -11129,6 +11306,72 @@ var WorkspacesClient = class {
11129
11306
  }
11130
11307
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/slate/workspaces");
11131
11308
  }
11309
+ /**
11310
+ * @param {SlateAPI.DeleteWorkspaceRequest} request
11311
+ * @param {WorkspacesClient.RequestOptions} requestOptions - Request-specific configuration.
11312
+ *
11313
+ * @throws {@link SlateAPI.ForbiddenError}
11314
+ * @throws {@link SlateAPI.NotFoundError}
11315
+ *
11316
+ * @example
11317
+ * await client.workspaces.deleteWorkspace({
11318
+ * workspaceId: "workspace_id"
11319
+ * })
11320
+ */
11321
+ deleteWorkspace(request, requestOptions) {
11322
+ return HttpResponsePromise.fromPromise(this.__deleteWorkspace(request, requestOptions));
11323
+ }
11324
+ async __deleteWorkspace(request, requestOptions) {
11325
+ const { workspaceId, deleteBases, deleteRepos } = request;
11326
+ const _queryParams = {
11327
+ delete_bases: deleteBases != null ? DeleteWorkspaceRequestDeleteBases.jsonOrThrow(deleteBases, {
11328
+ unrecognizedObjectKeys: "strip",
11329
+ omitUndefined: true
11330
+ }) : void 0,
11331
+ delete_repos: deleteRepos != null ? DeleteWorkspaceRequestDeleteRepos.jsonOrThrow(deleteRepos, {
11332
+ unrecognizedObjectKeys: "strip",
11333
+ omitUndefined: true
11334
+ }) : void 0
11335
+ };
11336
+ const _headers = mergeHeaders(this._options?.headers, requestOptions?.headers);
11337
+ const _response = await fetcher({
11338
+ url: join(await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment), `slate/workspaces/${encodePathParam(workspaceId)}`),
11339
+ method: "DELETE",
11340
+ headers: _headers,
11341
+ queryString: queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
11342
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
11343
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
11344
+ abortSignal: requestOptions?.abortSignal,
11345
+ fetchFn: this._options?.fetch,
11346
+ logging: this._options.logging
11347
+ });
11348
+ if (_response.ok) return {
11349
+ data: void 0,
11350
+ rawResponse: _response.rawResponse
11351
+ };
11352
+ if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
11353
+ case 403: throw new ForbiddenError(Error_.parseOrThrow(_response.error.body, {
11354
+ unrecognizedObjectKeys: "passthrough",
11355
+ allowUnrecognizedUnionMembers: true,
11356
+ allowUnrecognizedEnumValues: true,
11357
+ skipValidation: true,
11358
+ breadcrumbsPrefix: ["response"]
11359
+ }), _response.rawResponse);
11360
+ case 404: throw new NotFoundError(Error_.parseOrThrow(_response.error.body, {
11361
+ unrecognizedObjectKeys: "passthrough",
11362
+ allowUnrecognizedUnionMembers: true,
11363
+ allowUnrecognizedEnumValues: true,
11364
+ skipValidation: true,
11365
+ breadcrumbsPrefix: ["response"]
11366
+ }), _response.rawResponse);
11367
+ default: throw new SlateAPIError({
11368
+ statusCode: _response.error.statusCode,
11369
+ body: _response.error.body,
11370
+ rawResponse: _response.rawResponse
11371
+ });
11372
+ }
11373
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/slate/workspaces/{workspace_id}");
11374
+ }
11132
11375
  };
11133
11376
  var SlateAPIClient = class {
11134
11377
  _options;
@@ -14811,6 +15054,9 @@ const ZodURL = /*@__PURE__*/ $constructor("ZodURL", (inst, def) => {
14811
15054
  $ZodURL.init(inst, def);
14812
15055
  ZodStringFormat.init(inst, def);
14813
15056
  });
15057
+ function url(params) {
15058
+ return _url(ZodURL, params);
15059
+ }
14814
15060
  const ZodEmoji = /*@__PURE__*/ $constructor("ZodEmoji", (inst, def) => {
14815
15061
  $ZodEmoji.init(inst, def);
14816
15062
  ZodStringFormat.init(inst, def);
@@ -15320,6 +15566,82 @@ function number(params) {
15320
15566
  //#endregion
15321
15567
  //#region ../slate-shared/dist/index.mjs
15322
15568
  const WORKSPACE_DOCS_SUBDIR = "output";
15569
+ const INBOX_CONTENT_TREE = {
15570
+ "output/actions/reply-dana-uat-escalation.md": "---\ntype: Action\nstatus: open\n---\n# Reply to Dana Whitfield's UAT currency escalation\n\nDana escalated the multi-currency UAT blocker; reply today.\n",
15571
+ "output/actions/ship-final-invoice.md": "---\ntype: Action\nstatus: open\n---\n# Ship the final invoice\n\nClose out the quarter: send the last invoice and file it.\n",
15572
+ "output/types/action.loader.js": `export default async ({ vault, path }) => {
15573
+ const node = vault.get(path)
15574
+ return { items: [{ body: node.body, path: node.path, title: node.title }] }
15575
+ }
15576
+ `,
15577
+ "output/types/action.render-spec.json": `${JSON.stringify({ render: {
15578
+ elements: {
15579
+ body: {
15580
+ props: { text: { $item: "body" } },
15581
+ type: "Text"
15582
+ },
15583
+ card: {
15584
+ children: ["body"],
15585
+ props: { title: { $item: "title" } },
15586
+ type: "Card"
15587
+ },
15588
+ detail: {
15589
+ children: ["card"],
15590
+ props: {
15591
+ className: "mx-auto max-w-md p-8",
15592
+ direction: "vertical",
15593
+ gap: "md"
15594
+ },
15595
+ repeat: {
15596
+ key: "path",
15597
+ statePath: "/items"
15598
+ },
15599
+ type: "Stack"
15600
+ }
15601
+ },
15602
+ root: "detail"
15603
+ } }, null, " ")}\n`,
15604
+ "output/views/inbox.loader.js": `export default async ({ vault }) => {
15605
+ const items = vault
15606
+ .all()
15607
+ .filter((entry) => entry.type === "Action")
15608
+ .map((entry) => ({ path: entry.path, title: entry.title }))
15609
+ .sort((a, b) => a.title.localeCompare(b.title))
15610
+ return { items }
15611
+ }
15612
+ `,
15613
+ "output/views/inbox.render-spec.json": `${JSON.stringify({ render: {
15614
+ elements: {
15615
+ card: {
15616
+ props: { title: { $item: "title" } },
15617
+ type: "Card"
15618
+ },
15619
+ list: {
15620
+ children: ["row"],
15621
+ props: {
15622
+ className: "mx-auto max-w-md p-8",
15623
+ direction: "vertical",
15624
+ gap: "md"
15625
+ },
15626
+ repeat: {
15627
+ key: "path",
15628
+ statePath: "/items"
15629
+ },
15630
+ type: "Stack"
15631
+ },
15632
+ row: {
15633
+ children: ["card"],
15634
+ on: { press: {
15635
+ action: "navigate",
15636
+ params: { path: { $template: "${path}" } }
15637
+ } },
15638
+ props: { className: null },
15639
+ type: "Pressable"
15640
+ }
15641
+ },
15642
+ root: "list"
15643
+ } }, null, " ")}\n`
15644
+ };
15323
15645
  const segmentSchema = string().min(1, "a repoId segment must be non-empty").refine((s) => s !== "." && s !== ".." && !s.includes("/"), { message: "a repoId segment must not be '.'/'..' or contain '/'" });
15324
15646
  function segment(value, label) {
15325
15647
  const result = segmentSchema.safeParse(value);
@@ -42900,16 +43222,16 @@ function osUsername() {
42900
43222
  }
42901
43223
 
42902
43224
  //#endregion
42903
- //#region ../slate-bridge/dist/index.mjs
43225
+ //#region ../slate-bridge/dist/goldens-C7JkwekQ.mjs
42904
43226
  const nonEmptyStringSchema = string().trim().min(1);
42905
43227
  const portSchema = number().int().min(0).max(65535).default(7777);
42906
43228
  const envSchema = object({
42907
43229
  CTX_AUTH_SKIP_VERIFY_JWT: string().optional().transform((v) => v === "true"),
42908
43230
  CTX_GIT_HOST_BASE_DIR: nonEmptyStringSchema.default(() => path.join(os.homedir(), ".contextlayer", "repos")),
42909
- CTX_PLATFORM_URL: nonEmptyStringSchema.default("http://127.0.0.1:3010"),
42910
- CTX_WEB_URL: nonEmptyStringSchema.default("http://localhost:3000").transform((url) => url.replace(/\/+$/, "")),
43231
+ CTX_PLATFORM_URL: url().default("http://127.0.0.1:3010").transform((url) => url.replace(/\/+$/, "")),
43232
+ CTX_WEB_URL: url().default("http://localhost:3000").transform((url) => url.replace(/\/+$/, "")),
42911
43233
  CTXS_BRIDGE_PORT: portSchema,
42912
- CTXS_CLAUDE_IMAGE: nonEmptyStringSchema.default("ghcr.io/usecontextlayer/ctx-sandbox:0.5.5"),
43234
+ CTXS_CLAUDE_IMAGE: nonEmptyStringSchema.default("ghcr.io/usecontextlayer/ctx-sandbox:0.5.6"),
42913
43235
  CTXS_CLAUDE_MODEL: nonEmptyStringSchema.default("opus"),
42914
43236
  CTXS_HOST_CLAUDE_JSON_PATH: nonEmptyStringSchema.default(() => path.join(os.homedir(), ".claude.json")),
42915
43237
  NODE_ENV: _enum([
@@ -43263,7 +43585,21 @@ const CLAUDE_ARGS = [
43263
43585
  "--thinking-display",
43264
43586
  "summarized",
43265
43587
  "--permission-mode",
43266
- "bypassPermissions"
43588
+ "bypassPermissions",
43589
+ "--append-system-prompt",
43590
+ `You are working in the user's workspace: a directory of documents that is also a shared git repository. The synthesis engine, other sessions, and operators write to this same repository through its remote. Git is how your work persists and how everyone else learns about it — an edit that is not pushed does not exist yet.
43591
+
43592
+ 1. When you complete a change the user asked for, immediately commit and push it: \`git add -A && git commit -m "<message>" && git push\`. Never use \`--force\` on a push, ever.
43593
+
43594
+ 2. Commit messages carry your reasoning, not just a summary. They are how this workspace remembers why things changed — future sessions, the synthesis engine, and the user read them. When you change a document's status or make a judgment call, put the why in the message. When you need context on how the workspace got into its current state, read \`git log\`.
43595
+
43596
+ 3. If a push is rejected, someone else pushed first. Run \`git pull --no-rebase\`. If the merge is clean, push again. If there are conflicts, resolve them together with the user: show what collided, prefer preserving the user's intent, ask when unsure — then commit and push. Never resolve a conflict by discarding someone else's work wholesale.
43597
+
43598
+ 4. At session start the tree may already hold uncommitted changes, unpushed commits, or a merge a previous session left in flight. This is normal. Never discard that work — fold uncommitted changes into your next commit, and finish an in-flight merge before starting new work.
43599
+
43600
+ 5. The \`.engine/\` directory is the synthesis engine's private state. Leave it alone unless the user explicitly asks.
43601
+
43602
+ Do this bookkeeping quietly. Don't narrate routine git operations — mention git only when something needs the user's attention: a conflict, a rejected push you cannot heal, or work you found and preserved.`
43267
43603
  ];
43268
43604
  function bearerToken(c) {
43269
43605
  const header = c.req.header("Authorization") ?? "";
@@ -43288,6 +43624,15 @@ function assertSingleBaseId(baseIds, workspaceId) {
43288
43624
  if (baseId === void 0 || rest.length > 0) throw new Error(`render: workspace ${workspaceId} resolves to ${baseIds.length} base(s), but render-SQL requires exactly one (a sql() call runs against a single base DB). Link exactly one base to this workspace; multi-base render is deferred.`);
43289
43625
  return baseId;
43290
43626
  }
43627
+ function noteDivergedCheckout(workspaceId) {
43628
+ console.error(`[slate-bridge] workspace ${workspaceId} checkout has unpushed commits while origin moved (unfinished heal) — serving the local tree`);
43629
+ Sentry.addBreadcrumb({
43630
+ category: "workspace-checkout",
43631
+ data: { workspaceId },
43632
+ level: "warning",
43633
+ message: "diverged workspace checkout served as-is"
43634
+ });
43635
+ }
43291
43636
  function isTurnResult(line) {
43292
43637
  if (!line.includes("\"type\":\"result\"")) return false;
43293
43638
  try {
@@ -43337,11 +43682,12 @@ async function createBridgeServer(opts) {
43337
43682
  const rawParams = (await c.req.json()).params ?? {};
43338
43683
  try {
43339
43684
  const userToken = bearerToken(c);
43340
- const { head, rootDir } = await materializeWorkspaceTree(workspaceId, {
43685
+ const { head, rootDir, freshness } = await ensureWorkspaceCheckout(workspaceId, {
43341
43686
  gitHostBaseDir,
43342
43687
  platformUrl,
43343
43688
  token: userToken
43344
43689
  });
43690
+ if (freshness === "held_diverged") noteDivergedCheckout(workspaceId);
43345
43691
  const result = await runWorkspaceView({
43346
43692
  rawParams,
43347
43693
  resolveDsn: () => resolveRenderDsn(platformUrl, workspaceId, userToken),
@@ -43361,11 +43707,12 @@ async function createBridgeServer(opts) {
43361
43707
  const rawParams = body.params ?? {};
43362
43708
  try {
43363
43709
  const userToken = bearerToken(c);
43364
- const { head, rootDir } = await materializeWorkspaceTree(workspaceId, {
43710
+ const { head, rootDir, freshness } = await ensureWorkspaceCheckout(workspaceId, {
43365
43711
  gitHostBaseDir,
43366
43712
  platformUrl,
43367
43713
  token: userToken
43368
43714
  });
43715
+ if (freshness === "held_diverged") noteDivergedCheckout(workspaceId);
43369
43716
  const vault = await vaults.get(rootDir, head);
43370
43717
  const result = await runWorkspaceContent({
43371
43718
  contentPath: body.path,
@@ -43411,11 +43758,13 @@ async function createBridgeServer(opts) {
43411
43758
  let phase = "boot";
43412
43759
  try {
43413
43760
  const plan = await fetchBridgePlan(platformUrl, workspaceId, userToken);
43414
- const [, { rootDir }] = await Promise.all([claudeRepo.restore(), materializeWorkspaceTree(workspaceId, {
43761
+ const [, checkout] = await Promise.all([claudeRepo.restore(), ensureWorkspaceCheckout(workspaceId, {
43415
43762
  gitHostBaseDir,
43416
43763
  platformUrl,
43417
43764
  token: userToken
43418
43765
  })]);
43766
+ if (checkout.freshness === "held_diverged") noteDivergedCheckout(workspaceId);
43767
+ const rootDir = checkout.rootDir;
43419
43768
  if (ac.signal.aborted) return;
43420
43769
  session = await createClaudeMicrosandbox({
43421
43770
  claudeHomeHostDir: claudeRepo.hostDir,
@@ -43435,7 +43784,12 @@ async function createBridgeServer(opts) {
43435
43784
  ],
43436
43785
  env: {
43437
43786
  CLAUDE_CODE_ENTRYPOINT: "sdk-ts",
43438
- ...plan.claudeOauthToken ? { CLAUDE_CODE_OAUTH_TOKEN: plan.claudeOauthToken } : {}
43787
+ ...plan.claudeOauthToken ? { CLAUDE_CODE_OAUTH_TOKEN: plan.claudeOauthToken } : {},
43788
+ ...guestGitEnv({
43789
+ platformUrl,
43790
+ sub: r.sub,
43791
+ token: userToken
43792
+ })
43439
43793
  },
43440
43794
  signal: ac.signal
43441
43795
  });
@@ -43513,6 +43867,72 @@ async function createBridgeServer(opts) {
43513
43867
  port: address.port
43514
43868
  };
43515
43869
  }
43870
+ const PARITY_SCENARIOS = [
43871
+ {
43872
+ name: "text-only",
43873
+ turns: ["Reply with exactly one word: hello", "Now reply with exactly one word: goodbye"]
43874
+ },
43875
+ {
43876
+ name: "code-writing",
43877
+ turns: [
43878
+ "Create a file calc.js that exports a function add(a, b) returning a + b. Use module.exports. Just write the file, no explanation.",
43879
+ "Add a function sub(a, b) returning a - b to calc.js, keeping add. Export both.",
43880
+ "Create run.js that requires ./calc.js and prints add(2, 3) and sub(5, 1), then run it with `node run.js` and show the output.",
43881
+ "In one sentence, what does calc.js export now?"
43882
+ ]
43883
+ },
43884
+ {
43885
+ name: "thinking-and-error",
43886
+ turns: [
43887
+ "Reason carefully step by step before answering: a train travels 90 km in 1 hour 12 minutes. What is its average speed in km/h? Show your reasoning, then the answer.",
43888
+ "Read the file /tmp/definitely-does-not-exist-9f3a.txt and tell me its contents.",
43889
+ "In one short sentence, acknowledge that the file could not be read."
43890
+ ]
43891
+ },
43892
+ {
43893
+ name: "compaction",
43894
+ turns: [
43895
+ "In two short paragraphs, explain how the TCP three-way handshake works.",
43896
+ "Now, in two short paragraphs, explain how a TLS 1.3 handshake works.",
43897
+ "List three concrete differences between TCP and UDP.",
43898
+ "/compact",
43899
+ "What topics were we just discussing? Answer in one sentence.",
43900
+ "Reply with exactly one word: done"
43901
+ ]
43902
+ },
43903
+ {
43904
+ name: "multi-file-tools",
43905
+ turns: ["Create three files in the current directory: a.txt containing exactly `alpha`, b.txt containing exactly `beta`, c.txt containing exactly `gamma`. Just create them, no explanation.", "Read a.txt, b.txt, and c.txt and tell me what each one contains."]
43906
+ },
43907
+ {
43908
+ name: "web-tools",
43909
+ turns: ["Use web search to find the current latest stable Node.js LTS major version. Report just the version number.", "In one sentence, what did you search for?"]
43910
+ },
43911
+ {
43912
+ name: "long-conversation",
43913
+ turns: [
43914
+ "Name a primary color. Reply with one word.",
43915
+ "Name a different primary color. Reply with one word.",
43916
+ "Name the third primary color. Reply with one word.",
43917
+ "What color do you get mixing red and blue? Reply with one word.",
43918
+ "Summarize this conversation in one short sentence.",
43919
+ "Reply with exactly one word: bye"
43920
+ ]
43921
+ }
43922
+ ];
43923
+ function resolveGoldensDir() {
43924
+ let dir = path.dirname(fileURLToPath(import.meta.url));
43925
+ while (true) {
43926
+ const candidate = path.join(dir, "slate-shared", "lib", "__goldens__");
43927
+ if (existsSync(candidate)) return candidate;
43928
+ const parent = path.dirname(dir);
43929
+ if (parent === dir) throw new Error(`[parity] could not locate slate-shared/lib/__goldens__ above ${fileURLToPath(import.meta.url)}`);
43930
+ dir = parent;
43931
+ }
43932
+ }
43933
+
43934
+ //#endregion
43935
+ //#region ../slate-bridge/dist/index.mjs
43516
43936
  async function writeJsonAtomic(filePath, value) {
43517
43937
  const tmp = `${filePath}.tmp`;
43518
43938
  await writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`);
@@ -47661,4 +48081,4 @@ runCli().catch((error) => {
47661
48081
  //#endregion
47662
48082
  export { createProgram, runCli };
47663
48083
  //# sourceMappingURL=cli.mjs.map
47664
- //# debugId=5e70b90f-e938-570a-b3e3-d35af180a822
48084
+ //# debugId=3dbc3cff-70da-5d01-b6fc-a83d63e0c3f3