@usecontextlayer/ctxs 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 +603 -111
- package/dist/cli.mjs.map +1 -1
- package/package.json +4 -3
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]="
|
|
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]="a525501b-8c62-5a9e-a76f-b82b01d56d75")}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.
|
|
63
|
+
var version$2 = "0.5.7";
|
|
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
|
|
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
|
|
271
|
-
*
|
|
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
|
|
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
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
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
|
|
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
|
-
"
|
|
334
|
-
"--
|
|
361
|
+
return (await runGit([
|
|
362
|
+
"merge",
|
|
363
|
+
"--ff-only",
|
|
335
364
|
"FETCH_HEAD"
|
|
336
|
-
], {
|
|
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 (
|
|
597
|
-
*
|
|
598
|
-
*
|
|
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
|
|
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
|
|
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,99 @@ 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
|
+
ask: {
|
|
4634
|
+
children: ["askLabel"],
|
|
4635
|
+
on: { press: {
|
|
4636
|
+
action: "openChat",
|
|
4637
|
+
params: {
|
|
4638
|
+
autoSend: false,
|
|
4639
|
+
content: { $template: "What should I know about @output/${path}?" }
|
|
4640
|
+
}
|
|
4641
|
+
} },
|
|
4642
|
+
props: { className: null },
|
|
4643
|
+
type: "Pressable"
|
|
4644
|
+
},
|
|
4645
|
+
askLabel: {
|
|
4646
|
+
props: { text: "Ask about this doc" },
|
|
4647
|
+
type: "Text"
|
|
4648
|
+
},
|
|
4649
|
+
body: {
|
|
4650
|
+
props: { text: { $item: "body" } },
|
|
4651
|
+
type: "Text"
|
|
4652
|
+
},
|
|
4653
|
+
card: {
|
|
4654
|
+
children: [
|
|
4655
|
+
"body",
|
|
4656
|
+
"draft",
|
|
4657
|
+
"ask"
|
|
4658
|
+
],
|
|
4659
|
+
props: { title: { $item: "title" } },
|
|
4660
|
+
type: "Card"
|
|
4661
|
+
},
|
|
4662
|
+
detail: {
|
|
4663
|
+
children: ["card"],
|
|
4664
|
+
props: {
|
|
4665
|
+
className: "mx-auto max-w-md p-8",
|
|
4666
|
+
direction: "vertical",
|
|
4667
|
+
gap: "md"
|
|
4668
|
+
},
|
|
4669
|
+
repeat: {
|
|
4670
|
+
key: "path",
|
|
4671
|
+
statePath: "/items"
|
|
4672
|
+
},
|
|
4673
|
+
type: "Stack"
|
|
4674
|
+
},
|
|
4675
|
+
draft: {
|
|
4676
|
+
children: ["draftLabel"],
|
|
4677
|
+
on: { press: {
|
|
4678
|
+
action: "openChat",
|
|
4679
|
+
params: {
|
|
4680
|
+
autoSend: true,
|
|
4681
|
+
content: { $template: "Draft a reply to @output/${path}" }
|
|
4682
|
+
}
|
|
4683
|
+
} },
|
|
4684
|
+
props: { className: null },
|
|
4685
|
+
type: "Pressable"
|
|
4686
|
+
},
|
|
4687
|
+
draftLabel: {
|
|
4688
|
+
props: { text: "Draft reply" },
|
|
4689
|
+
type: "Text"
|
|
4690
|
+
}
|
|
4691
|
+
},
|
|
4692
|
+
root: "detail"
|
|
4693
|
+
} }, null, " ")}`, `${JSON.stringify({ render: {
|
|
4694
|
+
elements: {
|
|
4695
|
+
card: {
|
|
4696
|
+
props: { title: { $item: "title" } },
|
|
4697
|
+
type: "Card"
|
|
4698
|
+
},
|
|
4699
|
+
list: {
|
|
4700
|
+
children: ["row"],
|
|
4701
|
+
props: {
|
|
4702
|
+
className: "mx-auto max-w-md p-8",
|
|
4703
|
+
direction: "vertical",
|
|
4704
|
+
gap: "md"
|
|
4705
|
+
},
|
|
4706
|
+
repeat: {
|
|
4707
|
+
key: "path",
|
|
4708
|
+
statePath: "/items"
|
|
4709
|
+
},
|
|
4710
|
+
type: "Stack"
|
|
4711
|
+
},
|
|
4712
|
+
row: {
|
|
4713
|
+
children: ["card"],
|
|
4714
|
+
on: { press: {
|
|
4715
|
+
action: "navigate",
|
|
4716
|
+
params: { path: { $template: "${path}" } }
|
|
4717
|
+
} },
|
|
4718
|
+
props: { className: null },
|
|
4719
|
+
type: "Pressable"
|
|
4720
|
+
}
|
|
4721
|
+
},
|
|
4722
|
+
root: "list"
|
|
4723
|
+
} }, null, " ")}`;
|
|
4562
4724
|
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
4725
|
function segment$1(value, label) {
|
|
4564
4726
|
const result = segmentSchema$1.safeParse(value);
|
|
@@ -4578,7 +4740,7 @@ const sessionMetaSchema$1 = object$3({
|
|
|
4578
4740
|
sessionId: string$4()
|
|
4579
4741
|
});
|
|
4580
4742
|
record$2(string$4(), sessionMetaSchema$1);
|
|
4581
|
-
async function
|
|
4743
|
+
async function ensureWorkspaceCheckout(workspaceId, ctx) {
|
|
4582
4744
|
const repo = await resolveRepo({
|
|
4583
4745
|
platformUrl: ctx.platformUrl,
|
|
4584
4746
|
repoId: buildRepoId$1({
|
|
@@ -4588,10 +4750,16 @@ async function materializeWorkspaceTree(workspaceId, ctx) {
|
|
|
4588
4750
|
}),
|
|
4589
4751
|
token: ctx.token
|
|
4590
4752
|
}, 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
4753
|
return {
|
|
4754
|
+
freshness: await (async () => {
|
|
4755
|
+
if (!await isCloned(repo.hostDir)) {
|
|
4756
|
+
await cloneRepo(repo);
|
|
4757
|
+
return "cloned";
|
|
4758
|
+
}
|
|
4759
|
+
if (await hasUncommittedWork(repo)) return "held_dirty";
|
|
4760
|
+
if (await remoteHead(repo) !== await localHead(repo)) return await fastForwardToRemote(repo) === "fast_forwarded" ? "fresh" : "held_diverged";
|
|
4761
|
+
return "fresh";
|
|
4762
|
+
})(),
|
|
4595
4763
|
head: await localHead(repo),
|
|
4596
4764
|
rootDir: repo.hostDir
|
|
4597
4765
|
};
|
|
@@ -4607,72 +4775,6 @@ async function isCloned(hostDir) {
|
|
|
4607
4775
|
}
|
|
4608
4776
|
}
|
|
4609
4777
|
|
|
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
4778
|
//#endregion
|
|
4677
4779
|
//#region ../base-client/dist/index.mjs
|
|
4678
4780
|
/**
|
|
@@ -4757,6 +4859,19 @@ var ForbiddenError$1 = class extends BaseAPIError {
|
|
|
4757
4859
|
this.name = "ForbiddenError";
|
|
4758
4860
|
}
|
|
4759
4861
|
};
|
|
4862
|
+
var NotFoundError$1 = class extends BaseAPIError {
|
|
4863
|
+
constructor(body, rawResponse) {
|
|
4864
|
+
super({
|
|
4865
|
+
message: "NotFoundError",
|
|
4866
|
+
statusCode: 404,
|
|
4867
|
+
body,
|
|
4868
|
+
rawResponse
|
|
4869
|
+
});
|
|
4870
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
4871
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
4872
|
+
this.name = "NotFoundError";
|
|
4873
|
+
}
|
|
4874
|
+
};
|
|
4760
4875
|
function mergeHeaders$1(...headersArray) {
|
|
4761
4876
|
const result = {};
|
|
4762
4877
|
for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
|
|
@@ -5976,7 +6091,7 @@ function createIdentitySchemaCreator$1(schemaType, validate) {
|
|
|
5976
6091
|
};
|
|
5977
6092
|
};
|
|
5978
6093
|
}
|
|
5979
|
-
function enum_(values) {
|
|
6094
|
+
function enum_$1(values) {
|
|
5980
6095
|
const validValues = new Set(values);
|
|
5981
6096
|
return createIdentitySchemaCreator$1(SchemaType$1.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
|
|
5982
6097
|
if (typeof value !== "string") return {
|
|
@@ -6542,7 +6657,7 @@ const _hasOwn$4 = Object.prototype.hasOwnProperty;
|
|
|
6542
6657
|
function union$1(discriminant, union) {
|
|
6543
6658
|
const rawDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.rawDiscriminant;
|
|
6544
6659
|
const parsedDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.parsedDiscriminant;
|
|
6545
|
-
const discriminantValueSchema = enum_(keys$1(union));
|
|
6660
|
+
const discriminantValueSchema = enum_$1(keys$1(union));
|
|
6546
6661
|
const baseSchema = {
|
|
6547
6662
|
parse: (raw, opts) => {
|
|
6548
6663
|
return transformAndValidateUnion({
|
|
@@ -6795,7 +6910,7 @@ const Binding = object$2({
|
|
|
6795
6910
|
updatedAt: property$1("updated_at", date$3())
|
|
6796
6911
|
});
|
|
6797
6912
|
const ListBindingsResponse = object$2({ bindings: list$1(Binding) });
|
|
6798
|
-
const RunStatus = enum_([
|
|
6913
|
+
const RunStatus = enum_$1([
|
|
6799
6914
|
"QUEUED",
|
|
6800
6915
|
"NOT_STARTED",
|
|
6801
6916
|
"MANAGED",
|
|
@@ -6844,7 +6959,7 @@ const BindingStateResponse = object$2({
|
|
|
6844
6959
|
bindings: record$1(string$3(), BindingState),
|
|
6845
6960
|
version: number$3()
|
|
6846
6961
|
});
|
|
6847
|
-
const DagsterAllPlanBindingMode = enum_(["dagster"]);
|
|
6962
|
+
const DagsterAllPlanBindingMode = enum_$1(["dagster"]);
|
|
6848
6963
|
const DagsterAllPlanBinding = object$2({
|
|
6849
6964
|
auth: BindingAuth,
|
|
6850
6965
|
bindingId: property$1("binding_id", string$3()),
|
|
@@ -7026,6 +7141,62 @@ var BasesClient = class {
|
|
|
7026
7141
|
}
|
|
7027
7142
|
return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "GET", "/base/bases/{base_id}");
|
|
7028
7143
|
}
|
|
7144
|
+
/**
|
|
7145
|
+
* @param {BaseAPI.DeleteBaseRequest} request
|
|
7146
|
+
* @param {BasesClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
7147
|
+
*
|
|
7148
|
+
* @throws {@link BaseAPI.ForbiddenError}
|
|
7149
|
+
* @throws {@link BaseAPI.NotFoundError}
|
|
7150
|
+
*
|
|
7151
|
+
* @example
|
|
7152
|
+
* await client.bases.deleteBase({
|
|
7153
|
+
* baseId: "base_id"
|
|
7154
|
+
* })
|
|
7155
|
+
*/
|
|
7156
|
+
deleteBase(request, requestOptions) {
|
|
7157
|
+
return HttpResponsePromise$1.fromPromise(this.__deleteBase(request, requestOptions));
|
|
7158
|
+
}
|
|
7159
|
+
async __deleteBase(request, requestOptions) {
|
|
7160
|
+
const { baseId } = request;
|
|
7161
|
+
const _headers = mergeHeaders$1(this._options?.headers, requestOptions?.headers);
|
|
7162
|
+
const _response = await fetcher$1({
|
|
7163
|
+
url: join$1(await Supplier$1.get(this._options.baseUrl) ?? await Supplier$1.get(this._options.environment), `base/bases/${encodePathParam$1(baseId)}`),
|
|
7164
|
+
method: "DELETE",
|
|
7165
|
+
headers: _headers,
|
|
7166
|
+
queryString: queryBuilder$1().mergeAdditional(requestOptions?.queryParams).build(),
|
|
7167
|
+
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
|
|
7168
|
+
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
|
|
7169
|
+
abortSignal: requestOptions?.abortSignal,
|
|
7170
|
+
fetchFn: this._options?.fetch,
|
|
7171
|
+
logging: this._options.logging
|
|
7172
|
+
});
|
|
7173
|
+
if (_response.ok) return {
|
|
7174
|
+
data: void 0,
|
|
7175
|
+
rawResponse: _response.rawResponse
|
|
7176
|
+
};
|
|
7177
|
+
if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
|
|
7178
|
+
case 403: throw new ForbiddenError$1(Error_$1.parseOrThrow(_response.error.body, {
|
|
7179
|
+
unrecognizedObjectKeys: "passthrough",
|
|
7180
|
+
allowUnrecognizedUnionMembers: true,
|
|
7181
|
+
allowUnrecognizedEnumValues: true,
|
|
7182
|
+
skipValidation: true,
|
|
7183
|
+
breadcrumbsPrefix: ["response"]
|
|
7184
|
+
}), _response.rawResponse);
|
|
7185
|
+
case 404: throw new NotFoundError$1(Error_$1.parseOrThrow(_response.error.body, {
|
|
7186
|
+
unrecognizedObjectKeys: "passthrough",
|
|
7187
|
+
allowUnrecognizedUnionMembers: true,
|
|
7188
|
+
allowUnrecognizedEnumValues: true,
|
|
7189
|
+
skipValidation: true,
|
|
7190
|
+
breadcrumbsPrefix: ["response"]
|
|
7191
|
+
}), _response.rawResponse);
|
|
7192
|
+
default: throw new BaseAPIError({
|
|
7193
|
+
statusCode: _response.error.statusCode,
|
|
7194
|
+
body: _response.error.body,
|
|
7195
|
+
rawResponse: _response.rawResponse
|
|
7196
|
+
});
|
|
7197
|
+
}
|
|
7198
|
+
return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "DELETE", "/base/bases/{base_id}");
|
|
7199
|
+
}
|
|
7029
7200
|
};
|
|
7030
7201
|
var BindingPlanClient = class {
|
|
7031
7202
|
_options;
|
|
@@ -8662,7 +8833,7 @@ function decodeJwt(jwt) {
|
|
|
8662
8833
|
}
|
|
8663
8834
|
|
|
8664
8835
|
//#endregion
|
|
8665
|
-
//#region ../shared/dist/
|
|
8836
|
+
//#region ../shared/dist/verify-ctx-token-BbswNLaV.mjs
|
|
8666
8837
|
/**
|
|
8667
8838
|
* Global authentication middleware for a platform resource server: require a
|
|
8668
8839
|
* Bearer `aud=ctx` token and verify it offline via the injected verifier. A
|
|
@@ -8689,6 +8860,7 @@ function createCtxAuthMiddleware(verify, machineAzpAllowlist) {
|
|
|
8689
8860
|
if (!token) return c.json({ error: "Missing bearer token." }, 401);
|
|
8690
8861
|
const result = await verify(token);
|
|
8691
8862
|
if (!result.ok) return c.json({ error: "Invalid token." }, 401);
|
|
8863
|
+
c.set("bearer", token);
|
|
8692
8864
|
if (result.kind === "machine") {
|
|
8693
8865
|
if (!machineAzpAllowlist.has(result.azp)) return c.json({ error: "Machine client not allowed." }, 403);
|
|
8694
8866
|
c.set("machine", true);
|
|
@@ -8696,10 +8868,6 @@ function createCtxAuthMiddleware(verify, machineAzpAllowlist) {
|
|
|
8696
8868
|
await next();
|
|
8697
8869
|
};
|
|
8698
8870
|
}
|
|
8699
|
-
function ctxAuthHeaders(tokenProvider) {
|
|
8700
|
-
if (!tokenProvider) return {};
|
|
8701
|
-
return { headers: { Authorization: async () => `Bearer ${await tokenProvider()}` } };
|
|
8702
|
-
}
|
|
8703
8871
|
/**
|
|
8704
8872
|
* jose error codes that mean "the presented token is invalid" → reject (401),
|
|
8705
8873
|
* `reason` is the code (for logging only). Anything else — a JWKS timeout, a
|
|
@@ -8811,6 +8979,13 @@ function createDevJwtVerifier() {
|
|
|
8811
8979
|
};
|
|
8812
8980
|
}
|
|
8813
8981
|
|
|
8982
|
+
//#endregion
|
|
8983
|
+
//#region ../shared/dist/index.mjs
|
|
8984
|
+
function ctxAuthHeaders(tokenProvider) {
|
|
8985
|
+
if (!tokenProvider) return {};
|
|
8986
|
+
return { headers: { Authorization: async () => `Bearer ${await tokenProvider()}` } };
|
|
8987
|
+
}
|
|
8988
|
+
|
|
8814
8989
|
//#endregion
|
|
8815
8990
|
//#region ../slate-client/dist/index.mjs
|
|
8816
8991
|
/**
|
|
@@ -8895,6 +9070,19 @@ var ForbiddenError = class extends SlateAPIError {
|
|
|
8895
9070
|
this.name = "ForbiddenError";
|
|
8896
9071
|
}
|
|
8897
9072
|
};
|
|
9073
|
+
var NotFoundError = class extends SlateAPIError {
|
|
9074
|
+
constructor(body, rawResponse) {
|
|
9075
|
+
super({
|
|
9076
|
+
message: "NotFoundError",
|
|
9077
|
+
statusCode: 404,
|
|
9078
|
+
body,
|
|
9079
|
+
rawResponse
|
|
9080
|
+
});
|
|
9081
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
9082
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
9083
|
+
this.name = "NotFoundError";
|
|
9084
|
+
}
|
|
9085
|
+
};
|
|
8898
9086
|
function mergeHeaders(...headersArray) {
|
|
8899
9087
|
const result = {};
|
|
8900
9088
|
for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
|
|
@@ -10114,6 +10302,29 @@ function createIdentitySchemaCreator(schemaType, validate) {
|
|
|
10114
10302
|
};
|
|
10115
10303
|
};
|
|
10116
10304
|
}
|
|
10305
|
+
function enum_(values) {
|
|
10306
|
+
const validValues = new Set(values);
|
|
10307
|
+
return createIdentitySchemaCreator(SchemaType.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
|
|
10308
|
+
if (typeof value !== "string") return {
|
|
10309
|
+
ok: false,
|
|
10310
|
+
errors: [{
|
|
10311
|
+
path: breadcrumbsPrefix,
|
|
10312
|
+
message: getErrorMessageForIncorrectType(value, "string")
|
|
10313
|
+
}]
|
|
10314
|
+
};
|
|
10315
|
+
if (!validValues.has(value) && !allowUnrecognizedEnumValues) return {
|
|
10316
|
+
ok: false,
|
|
10317
|
+
errors: [{
|
|
10318
|
+
path: breadcrumbsPrefix,
|
|
10319
|
+
message: getErrorMessageForIncorrectType(value, "enum")
|
|
10320
|
+
}]
|
|
10321
|
+
};
|
|
10322
|
+
return {
|
|
10323
|
+
ok: true,
|
|
10324
|
+
value
|
|
10325
|
+
};
|
|
10326
|
+
})();
|
|
10327
|
+
}
|
|
10117
10328
|
function entries(object) {
|
|
10118
10329
|
return Object.entries(object);
|
|
10119
10330
|
}
|
|
@@ -10688,6 +10899,8 @@ const CreateWorkspaceInput = object$1({
|
|
|
10688
10899
|
synthesizerImage: property("synthesizer_image", string$2().optional()),
|
|
10689
10900
|
tick: string$2().optional()
|
|
10690
10901
|
});
|
|
10902
|
+
const DeleteWorkspaceRequestDeleteBases = enum_(["true", "false"]);
|
|
10903
|
+
const DeleteWorkspaceRequestDeleteRepos = enum_(["true", "false"]);
|
|
10691
10904
|
const BridgePlan = object$1({
|
|
10692
10905
|
baseIds: property("base_ids", list(string$2())),
|
|
10693
10906
|
claudeOauthToken: property("claude_oauth_token", string$2().nullable()),
|
|
@@ -11129,6 +11342,72 @@ var WorkspacesClient = class {
|
|
|
11129
11342
|
}
|
|
11130
11343
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/slate/workspaces");
|
|
11131
11344
|
}
|
|
11345
|
+
/**
|
|
11346
|
+
* @param {SlateAPI.DeleteWorkspaceRequest} request
|
|
11347
|
+
* @param {WorkspacesClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
11348
|
+
*
|
|
11349
|
+
* @throws {@link SlateAPI.ForbiddenError}
|
|
11350
|
+
* @throws {@link SlateAPI.NotFoundError}
|
|
11351
|
+
*
|
|
11352
|
+
* @example
|
|
11353
|
+
* await client.workspaces.deleteWorkspace({
|
|
11354
|
+
* workspaceId: "workspace_id"
|
|
11355
|
+
* })
|
|
11356
|
+
*/
|
|
11357
|
+
deleteWorkspace(request, requestOptions) {
|
|
11358
|
+
return HttpResponsePromise.fromPromise(this.__deleteWorkspace(request, requestOptions));
|
|
11359
|
+
}
|
|
11360
|
+
async __deleteWorkspace(request, requestOptions) {
|
|
11361
|
+
const { workspaceId, deleteBases, deleteRepos } = request;
|
|
11362
|
+
const _queryParams = {
|
|
11363
|
+
delete_bases: deleteBases != null ? DeleteWorkspaceRequestDeleteBases.jsonOrThrow(deleteBases, {
|
|
11364
|
+
unrecognizedObjectKeys: "strip",
|
|
11365
|
+
omitUndefined: true
|
|
11366
|
+
}) : void 0,
|
|
11367
|
+
delete_repos: deleteRepos != null ? DeleteWorkspaceRequestDeleteRepos.jsonOrThrow(deleteRepos, {
|
|
11368
|
+
unrecognizedObjectKeys: "strip",
|
|
11369
|
+
omitUndefined: true
|
|
11370
|
+
}) : void 0
|
|
11371
|
+
};
|
|
11372
|
+
const _headers = mergeHeaders(this._options?.headers, requestOptions?.headers);
|
|
11373
|
+
const _response = await fetcher({
|
|
11374
|
+
url: join(await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment), `slate/workspaces/${encodePathParam(workspaceId)}`),
|
|
11375
|
+
method: "DELETE",
|
|
11376
|
+
headers: _headers,
|
|
11377
|
+
queryString: queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
|
|
11378
|
+
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
|
|
11379
|
+
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
|
|
11380
|
+
abortSignal: requestOptions?.abortSignal,
|
|
11381
|
+
fetchFn: this._options?.fetch,
|
|
11382
|
+
logging: this._options.logging
|
|
11383
|
+
});
|
|
11384
|
+
if (_response.ok) return {
|
|
11385
|
+
data: void 0,
|
|
11386
|
+
rawResponse: _response.rawResponse
|
|
11387
|
+
};
|
|
11388
|
+
if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
|
|
11389
|
+
case 403: throw new ForbiddenError(Error_.parseOrThrow(_response.error.body, {
|
|
11390
|
+
unrecognizedObjectKeys: "passthrough",
|
|
11391
|
+
allowUnrecognizedUnionMembers: true,
|
|
11392
|
+
allowUnrecognizedEnumValues: true,
|
|
11393
|
+
skipValidation: true,
|
|
11394
|
+
breadcrumbsPrefix: ["response"]
|
|
11395
|
+
}), _response.rawResponse);
|
|
11396
|
+
case 404: throw new NotFoundError(Error_.parseOrThrow(_response.error.body, {
|
|
11397
|
+
unrecognizedObjectKeys: "passthrough",
|
|
11398
|
+
allowUnrecognizedUnionMembers: true,
|
|
11399
|
+
allowUnrecognizedEnumValues: true,
|
|
11400
|
+
skipValidation: true,
|
|
11401
|
+
breadcrumbsPrefix: ["response"]
|
|
11402
|
+
}), _response.rawResponse);
|
|
11403
|
+
default: throw new SlateAPIError({
|
|
11404
|
+
statusCode: _response.error.statusCode,
|
|
11405
|
+
body: _response.error.body,
|
|
11406
|
+
rawResponse: _response.rawResponse
|
|
11407
|
+
});
|
|
11408
|
+
}
|
|
11409
|
+
return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/slate/workspaces/{workspace_id}");
|
|
11410
|
+
}
|
|
11132
11411
|
};
|
|
11133
11412
|
var SlateAPIClient = class {
|
|
11134
11413
|
_options;
|
|
@@ -14811,6 +15090,9 @@ const ZodURL = /*@__PURE__*/ $constructor("ZodURL", (inst, def) => {
|
|
|
14811
15090
|
$ZodURL.init(inst, def);
|
|
14812
15091
|
ZodStringFormat.init(inst, def);
|
|
14813
15092
|
});
|
|
15093
|
+
function url(params) {
|
|
15094
|
+
return _url(ZodURL, params);
|
|
15095
|
+
}
|
|
14814
15096
|
const ZodEmoji = /*@__PURE__*/ $constructor("ZodEmoji", (inst, def) => {
|
|
14815
15097
|
$ZodEmoji.init(inst, def);
|
|
14816
15098
|
ZodStringFormat.init(inst, def);
|
|
@@ -15320,6 +15602,118 @@ function number(params) {
|
|
|
15320
15602
|
//#endregion
|
|
15321
15603
|
//#region ../slate-shared/dist/index.mjs
|
|
15322
15604
|
const WORKSPACE_DOCS_SUBDIR = "output";
|
|
15605
|
+
const INBOX_CONTENT_TREE = {
|
|
15606
|
+
"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",
|
|
15607
|
+
"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",
|
|
15608
|
+
"output/types/action.loader.js": `export default async ({ vault, path }) => {
|
|
15609
|
+
const node = vault.get(path)
|
|
15610
|
+
return { items: [{ body: node.body, path: node.path, title: node.title }] }
|
|
15611
|
+
}
|
|
15612
|
+
`,
|
|
15613
|
+
"output/types/action.render-spec.json": `${JSON.stringify({ render: {
|
|
15614
|
+
elements: {
|
|
15615
|
+
ask: {
|
|
15616
|
+
children: ["askLabel"],
|
|
15617
|
+
on: { press: {
|
|
15618
|
+
action: "openChat",
|
|
15619
|
+
params: {
|
|
15620
|
+
autoSend: false,
|
|
15621
|
+
content: { $template: "What should I know about @output/${path}?" }
|
|
15622
|
+
}
|
|
15623
|
+
} },
|
|
15624
|
+
props: { className: null },
|
|
15625
|
+
type: "Pressable"
|
|
15626
|
+
},
|
|
15627
|
+
askLabel: {
|
|
15628
|
+
props: { text: "Ask about this doc" },
|
|
15629
|
+
type: "Text"
|
|
15630
|
+
},
|
|
15631
|
+
body: {
|
|
15632
|
+
props: { text: { $item: "body" } },
|
|
15633
|
+
type: "Text"
|
|
15634
|
+
},
|
|
15635
|
+
card: {
|
|
15636
|
+
children: [
|
|
15637
|
+
"body",
|
|
15638
|
+
"draft",
|
|
15639
|
+
"ask"
|
|
15640
|
+
],
|
|
15641
|
+
props: { title: { $item: "title" } },
|
|
15642
|
+
type: "Card"
|
|
15643
|
+
},
|
|
15644
|
+
detail: {
|
|
15645
|
+
children: ["card"],
|
|
15646
|
+
props: {
|
|
15647
|
+
className: "mx-auto max-w-md p-8",
|
|
15648
|
+
direction: "vertical",
|
|
15649
|
+
gap: "md"
|
|
15650
|
+
},
|
|
15651
|
+
repeat: {
|
|
15652
|
+
key: "path",
|
|
15653
|
+
statePath: "/items"
|
|
15654
|
+
},
|
|
15655
|
+
type: "Stack"
|
|
15656
|
+
},
|
|
15657
|
+
draft: {
|
|
15658
|
+
children: ["draftLabel"],
|
|
15659
|
+
on: { press: {
|
|
15660
|
+
action: "openChat",
|
|
15661
|
+
params: {
|
|
15662
|
+
autoSend: true,
|
|
15663
|
+
content: { $template: "Draft a reply to @output/${path}" }
|
|
15664
|
+
}
|
|
15665
|
+
} },
|
|
15666
|
+
props: { className: null },
|
|
15667
|
+
type: "Pressable"
|
|
15668
|
+
},
|
|
15669
|
+
draftLabel: {
|
|
15670
|
+
props: { text: "Draft reply" },
|
|
15671
|
+
type: "Text"
|
|
15672
|
+
}
|
|
15673
|
+
},
|
|
15674
|
+
root: "detail"
|
|
15675
|
+
} }, null, " ")}\n`,
|
|
15676
|
+
"output/views/inbox.loader.js": `export default async ({ vault }) => {
|
|
15677
|
+
const items = vault
|
|
15678
|
+
.all()
|
|
15679
|
+
.filter((entry) => entry.type === "Action")
|
|
15680
|
+
.map((entry) => ({ path: entry.path, title: entry.title }))
|
|
15681
|
+
.sort((a, b) => a.title.localeCompare(b.title))
|
|
15682
|
+
return { items }
|
|
15683
|
+
}
|
|
15684
|
+
`,
|
|
15685
|
+
"output/views/inbox.render-spec.json": `${JSON.stringify({ render: {
|
|
15686
|
+
elements: {
|
|
15687
|
+
card: {
|
|
15688
|
+
props: { title: { $item: "title" } },
|
|
15689
|
+
type: "Card"
|
|
15690
|
+
},
|
|
15691
|
+
list: {
|
|
15692
|
+
children: ["row"],
|
|
15693
|
+
props: {
|
|
15694
|
+
className: "mx-auto max-w-md p-8",
|
|
15695
|
+
direction: "vertical",
|
|
15696
|
+
gap: "md"
|
|
15697
|
+
},
|
|
15698
|
+
repeat: {
|
|
15699
|
+
key: "path",
|
|
15700
|
+
statePath: "/items"
|
|
15701
|
+
},
|
|
15702
|
+
type: "Stack"
|
|
15703
|
+
},
|
|
15704
|
+
row: {
|
|
15705
|
+
children: ["card"],
|
|
15706
|
+
on: { press: {
|
|
15707
|
+
action: "navigate",
|
|
15708
|
+
params: { path: { $template: "${path}" } }
|
|
15709
|
+
} },
|
|
15710
|
+
props: { className: null },
|
|
15711
|
+
type: "Pressable"
|
|
15712
|
+
}
|
|
15713
|
+
},
|
|
15714
|
+
root: "list"
|
|
15715
|
+
} }, null, " ")}\n`
|
|
15716
|
+
};
|
|
15323
15717
|
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
15718
|
function segment(value, label) {
|
|
15325
15719
|
const result = segmentSchema.safeParse(value);
|
|
@@ -42900,16 +43294,16 @@ function osUsername() {
|
|
|
42900
43294
|
}
|
|
42901
43295
|
|
|
42902
43296
|
//#endregion
|
|
42903
|
-
//#region ../slate-bridge/dist/
|
|
43297
|
+
//#region ../slate-bridge/dist/goldens-bnwfOrjq.mjs
|
|
42904
43298
|
const nonEmptyStringSchema = string().trim().min(1);
|
|
42905
43299
|
const portSchema = number().int().min(0).max(65535).default(7777);
|
|
42906
43300
|
const envSchema = object({
|
|
42907
43301
|
CTX_AUTH_SKIP_VERIFY_JWT: string().optional().transform((v) => v === "true"),
|
|
42908
43302
|
CTX_GIT_HOST_BASE_DIR: nonEmptyStringSchema.default(() => path.join(os.homedir(), ".contextlayer", "repos")),
|
|
42909
|
-
CTX_PLATFORM_URL:
|
|
42910
|
-
CTX_WEB_URL:
|
|
43303
|
+
CTX_PLATFORM_URL: url().default("http://127.0.0.1:3010").transform((url) => url.replace(/\/+$/, "")),
|
|
43304
|
+
CTX_WEB_URL: url().default("http://localhost:3000").transform((url) => url.replace(/\/+$/, "")),
|
|
42911
43305
|
CTXS_BRIDGE_PORT: portSchema,
|
|
42912
|
-
CTXS_CLAUDE_IMAGE: nonEmptyStringSchema.default("ghcr.io/usecontextlayer/ctx-sandbox:0.5.
|
|
43306
|
+
CTXS_CLAUDE_IMAGE: nonEmptyStringSchema.default("ghcr.io/usecontextlayer/ctx-sandbox:0.5.7"),
|
|
42913
43307
|
CTXS_CLAUDE_MODEL: nonEmptyStringSchema.default("opus"),
|
|
42914
43308
|
CTXS_HOST_CLAUDE_JSON_PATH: nonEmptyStringSchema.default(() => path.join(os.homedir(), ".claude.json")),
|
|
42915
43309
|
NODE_ENV: _enum([
|
|
@@ -43263,7 +43657,21 @@ const CLAUDE_ARGS = [
|
|
|
43263
43657
|
"--thinking-display",
|
|
43264
43658
|
"summarized",
|
|
43265
43659
|
"--permission-mode",
|
|
43266
|
-
"bypassPermissions"
|
|
43660
|
+
"bypassPermissions",
|
|
43661
|
+
"--append-system-prompt",
|
|
43662
|
+
`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.
|
|
43663
|
+
|
|
43664
|
+
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.
|
|
43665
|
+
|
|
43666
|
+
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\`.
|
|
43667
|
+
|
|
43668
|
+
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.
|
|
43669
|
+
|
|
43670
|
+
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.
|
|
43671
|
+
|
|
43672
|
+
5. The \`.engine/\` directory is the synthesis engine's private state. Leave it alone unless the user explicitly asks.
|
|
43673
|
+
|
|
43674
|
+
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
43675
|
];
|
|
43268
43676
|
function bearerToken(c) {
|
|
43269
43677
|
const header = c.req.header("Authorization") ?? "";
|
|
@@ -43288,6 +43696,15 @@ function assertSingleBaseId(baseIds, workspaceId) {
|
|
|
43288
43696
|
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
43697
|
return baseId;
|
|
43290
43698
|
}
|
|
43699
|
+
function noteDivergedCheckout(workspaceId) {
|
|
43700
|
+
console.error(`[slate-bridge] workspace ${workspaceId} checkout has unpushed commits while origin moved (unfinished heal) — serving the local tree`);
|
|
43701
|
+
Sentry.addBreadcrumb({
|
|
43702
|
+
category: "workspace-checkout",
|
|
43703
|
+
data: { workspaceId },
|
|
43704
|
+
level: "warning",
|
|
43705
|
+
message: "diverged workspace checkout served as-is"
|
|
43706
|
+
});
|
|
43707
|
+
}
|
|
43291
43708
|
function isTurnResult(line) {
|
|
43292
43709
|
if (!line.includes("\"type\":\"result\"")) return false;
|
|
43293
43710
|
try {
|
|
@@ -43337,11 +43754,12 @@ async function createBridgeServer(opts) {
|
|
|
43337
43754
|
const rawParams = (await c.req.json()).params ?? {};
|
|
43338
43755
|
try {
|
|
43339
43756
|
const userToken = bearerToken(c);
|
|
43340
|
-
const { head, rootDir } = await
|
|
43757
|
+
const { head, rootDir, freshness } = await ensureWorkspaceCheckout(workspaceId, {
|
|
43341
43758
|
gitHostBaseDir,
|
|
43342
43759
|
platformUrl,
|
|
43343
43760
|
token: userToken
|
|
43344
43761
|
});
|
|
43762
|
+
if (freshness === "held_diverged") noteDivergedCheckout(workspaceId);
|
|
43345
43763
|
const result = await runWorkspaceView({
|
|
43346
43764
|
rawParams,
|
|
43347
43765
|
resolveDsn: () => resolveRenderDsn(platformUrl, workspaceId, userToken),
|
|
@@ -43361,11 +43779,12 @@ async function createBridgeServer(opts) {
|
|
|
43361
43779
|
const rawParams = body.params ?? {};
|
|
43362
43780
|
try {
|
|
43363
43781
|
const userToken = bearerToken(c);
|
|
43364
|
-
const { head, rootDir } = await
|
|
43782
|
+
const { head, rootDir, freshness } = await ensureWorkspaceCheckout(workspaceId, {
|
|
43365
43783
|
gitHostBaseDir,
|
|
43366
43784
|
platformUrl,
|
|
43367
43785
|
token: userToken
|
|
43368
43786
|
});
|
|
43787
|
+
if (freshness === "held_diverged") noteDivergedCheckout(workspaceId);
|
|
43369
43788
|
const vault = await vaults.get(rootDir, head);
|
|
43370
43789
|
const result = await runWorkspaceContent({
|
|
43371
43790
|
contentPath: body.path,
|
|
@@ -43411,11 +43830,13 @@ async function createBridgeServer(opts) {
|
|
|
43411
43830
|
let phase = "boot";
|
|
43412
43831
|
try {
|
|
43413
43832
|
const plan = await fetchBridgePlan(platformUrl, workspaceId, userToken);
|
|
43414
|
-
const [,
|
|
43833
|
+
const [, checkout] = await Promise.all([claudeRepo.restore(), ensureWorkspaceCheckout(workspaceId, {
|
|
43415
43834
|
gitHostBaseDir,
|
|
43416
43835
|
platformUrl,
|
|
43417
43836
|
token: userToken
|
|
43418
43837
|
})]);
|
|
43838
|
+
if (checkout.freshness === "held_diverged") noteDivergedCheckout(workspaceId);
|
|
43839
|
+
const rootDir = checkout.rootDir;
|
|
43419
43840
|
if (ac.signal.aborted) return;
|
|
43420
43841
|
session = await createClaudeMicrosandbox({
|
|
43421
43842
|
claudeHomeHostDir: claudeRepo.hostDir,
|
|
@@ -43435,7 +43856,12 @@ async function createBridgeServer(opts) {
|
|
|
43435
43856
|
],
|
|
43436
43857
|
env: {
|
|
43437
43858
|
CLAUDE_CODE_ENTRYPOINT: "sdk-ts",
|
|
43438
|
-
...plan.claudeOauthToken ? { CLAUDE_CODE_OAUTH_TOKEN: plan.claudeOauthToken } : {}
|
|
43859
|
+
...plan.claudeOauthToken ? { CLAUDE_CODE_OAUTH_TOKEN: plan.claudeOauthToken } : {},
|
|
43860
|
+
...guestGitEnv({
|
|
43861
|
+
platformUrl,
|
|
43862
|
+
sub: r.sub,
|
|
43863
|
+
token: userToken
|
|
43864
|
+
})
|
|
43439
43865
|
},
|
|
43440
43866
|
signal: ac.signal
|
|
43441
43867
|
});
|
|
@@ -43513,6 +43939,72 @@ async function createBridgeServer(opts) {
|
|
|
43513
43939
|
port: address.port
|
|
43514
43940
|
};
|
|
43515
43941
|
}
|
|
43942
|
+
const PARITY_SCENARIOS = [
|
|
43943
|
+
{
|
|
43944
|
+
name: "text-only",
|
|
43945
|
+
turns: ["Reply with exactly one word: hello", "Now reply with exactly one word: goodbye"]
|
|
43946
|
+
},
|
|
43947
|
+
{
|
|
43948
|
+
name: "code-writing",
|
|
43949
|
+
turns: [
|
|
43950
|
+
"Create a file calc.js that exports a function add(a, b) returning a + b. Use module.exports. Just write the file, no explanation.",
|
|
43951
|
+
"Add a function sub(a, b) returning a - b to calc.js, keeping add. Export both.",
|
|
43952
|
+
"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.",
|
|
43953
|
+
"In one sentence, what does calc.js export now?"
|
|
43954
|
+
]
|
|
43955
|
+
},
|
|
43956
|
+
{
|
|
43957
|
+
name: "thinking-and-error",
|
|
43958
|
+
turns: [
|
|
43959
|
+
"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.",
|
|
43960
|
+
"Read the file /tmp/definitely-does-not-exist-9f3a.txt and tell me its contents.",
|
|
43961
|
+
"In one short sentence, acknowledge that the file could not be read."
|
|
43962
|
+
]
|
|
43963
|
+
},
|
|
43964
|
+
{
|
|
43965
|
+
name: "compaction",
|
|
43966
|
+
turns: [
|
|
43967
|
+
"In two short paragraphs, explain how the TCP three-way handshake works.",
|
|
43968
|
+
"Now, in two short paragraphs, explain how a TLS 1.3 handshake works.",
|
|
43969
|
+
"List three concrete differences between TCP and UDP.",
|
|
43970
|
+
"/compact",
|
|
43971
|
+
"What topics were we just discussing? Answer in one sentence.",
|
|
43972
|
+
"Reply with exactly one word: done"
|
|
43973
|
+
]
|
|
43974
|
+
},
|
|
43975
|
+
{
|
|
43976
|
+
name: "multi-file-tools",
|
|
43977
|
+
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."]
|
|
43978
|
+
},
|
|
43979
|
+
{
|
|
43980
|
+
name: "web-tools",
|
|
43981
|
+
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?"]
|
|
43982
|
+
},
|
|
43983
|
+
{
|
|
43984
|
+
name: "long-conversation",
|
|
43985
|
+
turns: [
|
|
43986
|
+
"Name a primary color. Reply with one word.",
|
|
43987
|
+
"Name a different primary color. Reply with one word.",
|
|
43988
|
+
"Name the third primary color. Reply with one word.",
|
|
43989
|
+
"What color do you get mixing red and blue? Reply with one word.",
|
|
43990
|
+
"Summarize this conversation in one short sentence.",
|
|
43991
|
+
"Reply with exactly one word: bye"
|
|
43992
|
+
]
|
|
43993
|
+
}
|
|
43994
|
+
];
|
|
43995
|
+
function resolveGoldensDir() {
|
|
43996
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
43997
|
+
while (true) {
|
|
43998
|
+
const candidate = path.join(dir, "slate-shared", "lib", "__goldens__");
|
|
43999
|
+
if (existsSync(candidate)) return candidate;
|
|
44000
|
+
const parent = path.dirname(dir);
|
|
44001
|
+
if (parent === dir) throw new Error(`[parity] could not locate slate-shared/lib/__goldens__ above ${fileURLToPath(import.meta.url)}`);
|
|
44002
|
+
dir = parent;
|
|
44003
|
+
}
|
|
44004
|
+
}
|
|
44005
|
+
|
|
44006
|
+
//#endregion
|
|
44007
|
+
//#region ../slate-bridge/dist/index.mjs
|
|
43516
44008
|
async function writeJsonAtomic(filePath, value) {
|
|
43517
44009
|
const tmp = `${filePath}.tmp`;
|
|
43518
44010
|
await writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`);
|
|
@@ -47661,4 +48153,4 @@ runCli().catch((error) => {
|
|
|
47661
48153
|
//#endregion
|
|
47662
48154
|
export { createProgram, runCli };
|
|
47663
48155
|
//# sourceMappingURL=cli.mjs.map
|
|
47664
|
-
//# debugId=
|
|
48156
|
+
//# debugId=a525501b-8c62-5a9e-a76f-b82b01d56d75
|