@agentsky/sky 2.24.1 → 2.25.0
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/{chunk-S4YG3TXA.js → chunk-LPUGEMCV.js} +1 -1
- package/dist/{chunk-KWLEADJQ.js → chunk-QROAAJN2.js} +5 -1
- package/dist/index.js +295 -103
- package/dist/{trace-WLTD4C22.js → trace-HV4E2BPX.js} +1 -1
- package/dist/{trace-library-YMAVLH4Y.js → trace-library-HJWI7KM7.js} +2 -2
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
apiBase,
|
|
4
4
|
apiToken,
|
|
5
5
|
currentUniverse
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LPUGEMCV.js";
|
|
7
7
|
|
|
8
8
|
// src/api.ts
|
|
9
9
|
import { createWriteStream, writeFileSync } from "fs";
|
|
@@ -97,6 +97,9 @@ async function downloadFileTo(fileId, outPath) {
|
|
|
97
97
|
headers: { "user-agent": USER_AGENT, ...authHeaders() }
|
|
98
98
|
});
|
|
99
99
|
if (!res.ok) await parseError(res);
|
|
100
|
+
return writeResponseFile(res, outPath);
|
|
101
|
+
}
|
|
102
|
+
async function writeResponseFile(res, outPath) {
|
|
100
103
|
if (!res.body) {
|
|
101
104
|
writeFileSync(outPath, new Uint8Array(0));
|
|
102
105
|
return 0;
|
|
@@ -189,6 +192,7 @@ export {
|
|
|
189
192
|
uploadFile,
|
|
190
193
|
apiForm,
|
|
191
194
|
downloadFileTo,
|
|
195
|
+
writeResponseFile,
|
|
192
196
|
apiBytes,
|
|
193
197
|
resolveSessionRef,
|
|
194
198
|
streamEvents,
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
postEvents,
|
|
10
10
|
resolveSessionRef,
|
|
11
11
|
streamEvents,
|
|
12
|
-
uploadFile
|
|
13
|
-
|
|
12
|
+
uploadFile,
|
|
13
|
+
writeResponseFile
|
|
14
|
+
} from "./chunk-QROAAJN2.js";
|
|
14
15
|
import {
|
|
15
16
|
CLI_VERSION,
|
|
16
17
|
USER_AGENT,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
currentUniverse,
|
|
22
23
|
loadConfig,
|
|
23
24
|
saveConfig
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-LPUGEMCV.js";
|
|
25
26
|
import {
|
|
26
27
|
AGENT_TYPES,
|
|
27
28
|
MODEL_SUBSCRIPTION_PLAN_PHRASE,
|
|
@@ -47,7 +48,7 @@ import {
|
|
|
47
48
|
import "./chunk-MLKGABMK.js";
|
|
48
49
|
|
|
49
50
|
// src/index.ts
|
|
50
|
-
import { existsSync as existsSync13, readFileSync as
|
|
51
|
+
import { existsSync as existsSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync10 } from "fs";
|
|
51
52
|
import { basename as basename9, resolve as resolve9 } from "path";
|
|
52
53
|
import { createInterface as createInterface6 } from "readline";
|
|
53
54
|
import { Command } from "commander";
|
|
@@ -2643,6 +2644,35 @@ it, and name its path in the brief.
|
|
|
2643
2644
|
6. Tell the person what was done, which agent did which part, and what it cost
|
|
2644
2645
|
(\`get_task\` reports the task's cost).
|
|
2645
2646
|
|
|
2647
|
+
## Share an existing Library document
|
|
2648
|
+
|
|
2649
|
+
Use \`read_library_file_links\` with the document's exact \`ref\` to read its
|
|
2650
|
+
current revision, supported access and real available members. The reference
|
|
2651
|
+
can name a Drive file (including an uploaded meeting note), task file, memory
|
|
2652
|
+
note, skill file, agent user instructions (\`{kind:"agent_prompt",agentId}\`), saved artifact or platform artifact. Only the user-authored AGENTS.md is shared; system instructions and credentials are never included. \`workspace\` names the
|
|
2653
|
+
audience workspace, never a storage move or the connection's default.
|
|
2654
|
+
\`share_library_file\` changes only the requested workspace/member grants;
|
|
2655
|
+
\`publish_library_file\` enables or disables a public view-only link while
|
|
2656
|
+
preserving other grants. Both read first and merge against the current
|
|
2657
|
+
revision. \`revoke_library_file_links\` needs the explicit revision you reviewed.
|
|
2658
|
+
A conflict is an error: read the current state before intentionally retrying.
|
|
2659
|
+
These tools send no messages and start no sessions. CLI equivalents are
|
|
2660
|
+
\`sky library links show\`, \`share\`, \`publish\` and \`revoke\`; their help
|
|
2661
|
+
shows every reference shape. Existing artifact links and version pins keep
|
|
2662
|
+
using their existing controls and \`share_artifact\`.
|
|
2663
|
+
|
|
2664
|
+
When you receive a Library shared/public URL, \`read_shared_library_file\`
|
|
2665
|
+
accepts the 43-character token at its end; \`public: true\` chooses the public
|
|
2666
|
+
view-only reader. A recipient with a live edit grant can use
|
|
2667
|
+
\`save_shared_library_file\` with the opaque source revision from that read
|
|
2668
|
+
and exactly one native text/HTML/Office/restore field. Public links have no
|
|
2669
|
+
writer. The CLI equivalents are \`sky library links read --token \u2026\`
|
|
2670
|
+
(\`--output\` streams original bytes) and \`sky library links save --token \u2026
|
|
2671
|
+
--revision \u2026 --file \u2026\`; \`--data\` accepts the other native save fields.
|
|
2672
|
+
A 403 is not a saved result; a 409 requires reading current state before an
|
|
2673
|
+
intentional retry. This source revision is distinct from the integer revision
|
|
2674
|
+
of the sharing settings.
|
|
2675
|
+
|
|
2646
2676
|
## Build an agent that the person's own application runs
|
|
2647
2677
|
|
|
2648
2678
|
When the person wants an agent their product starts for its customers, built
|
|
@@ -5261,6 +5291,83 @@ function renderThreadSummary(t) {
|
|
|
5261
5291
|
return `${t.id.slice(0, 12)} ${flag}${t.title.slice(0, 40).padEnd(44)} [${agents}] ${status}`;
|
|
5262
5292
|
}
|
|
5263
5293
|
|
|
5294
|
+
// src/library.ts
|
|
5295
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
5296
|
+
|
|
5297
|
+
// src/api-command.ts
|
|
5298
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
5299
|
+
var API_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
5300
|
+
function readData(data, stdin = () => readFileSync16(0, "utf8")) {
|
|
5301
|
+
if (data === void 0) return void 0;
|
|
5302
|
+
const raw = data === "-" ? stdin() : data.startsWith("@") ? readFileSync16(data.slice(1), "utf8") : data;
|
|
5303
|
+
try {
|
|
5304
|
+
JSON.parse(raw);
|
|
5305
|
+
} catch {
|
|
5306
|
+
throw new Error("--data must be JSON (inline, @file or - for stdin)");
|
|
5307
|
+
}
|
|
5308
|
+
return raw;
|
|
5309
|
+
}
|
|
5310
|
+
function requestPath(path, query = []) {
|
|
5311
|
+
if (!path.startsWith("/") || path.startsWith("//")) throw new Error("path must start with /, e.g. /threads");
|
|
5312
|
+
const clean = path.replace(/^\/v1(?=\/)/, "");
|
|
5313
|
+
const params = new URLSearchParams();
|
|
5314
|
+
for (const pair of query) {
|
|
5315
|
+
const at = pair.indexOf("=");
|
|
5316
|
+
if (at <= 0) throw new Error(`--query needs key=value, got "${pair}"`);
|
|
5317
|
+
params.append(pair.slice(0, at), pair.slice(at + 1));
|
|
5318
|
+
}
|
|
5319
|
+
const sep4 = clean.includes("?") ? "&" : "?";
|
|
5320
|
+
const encoded = params.toString();
|
|
5321
|
+
return encoded ? `${clean}${sep4}${encoded}` : clean;
|
|
5322
|
+
}
|
|
5323
|
+
function matchOperations(doc, words) {
|
|
5324
|
+
const needles = words.map((w) => w.toLowerCase());
|
|
5325
|
+
const out = [];
|
|
5326
|
+
for (const [path, item] of Object.entries(doc.paths ?? {})) {
|
|
5327
|
+
for (const [method, op] of Object.entries(item)) {
|
|
5328
|
+
if (!API_METHODS.includes(method.toUpperCase())) continue;
|
|
5329
|
+
const hay = `${method} ${path} ${op.summary ?? ""} ${op.operationId ?? ""}`.toLowerCase();
|
|
5330
|
+
if (needles.every((n) => hay.includes(n))) out.push({ method: method.toUpperCase(), path, summary: op.summary, operationId: op.operationId });
|
|
5331
|
+
}
|
|
5332
|
+
}
|
|
5333
|
+
return out.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
|
|
5334
|
+
}
|
|
5335
|
+
async function searchApi(words) {
|
|
5336
|
+
const res = await apiRaw("GET", "/openapi.json", { auth: false });
|
|
5337
|
+
if (!res.ok) throw new Error(`could not read the API reference (${res.status})`);
|
|
5338
|
+
const ops = matchOperations(await res.json(), words);
|
|
5339
|
+
if (!ops.length) {
|
|
5340
|
+
console.log("no operations match");
|
|
5341
|
+
return;
|
|
5342
|
+
}
|
|
5343
|
+
for (const op of ops) console.log(`${op.method.padEnd(6)} ${op.path}${op.summary ? ` \u2014 ${op.summary}` : ""}`);
|
|
5344
|
+
}
|
|
5345
|
+
async function callApi(method, path, opts) {
|
|
5346
|
+
const verb = method.toUpperCase();
|
|
5347
|
+
if (!API_METHODS.includes(verb)) throw new Error(`method must be one of ${API_METHODS.join(", ")} or "search"`);
|
|
5348
|
+
const body = readData(opts.data);
|
|
5349
|
+
if (body !== void 0 && verb === "GET") throw new Error("a GET takes no --data; use --query");
|
|
5350
|
+
const res = await apiRaw(verb, requestPath(path, opts.query), { body, idempotencyKey: opts.idempotencyKey, universe: opts.workspace });
|
|
5351
|
+
const type = res.headers.get("content-type") ?? "";
|
|
5352
|
+
if (opts.output) {
|
|
5353
|
+
await writeResponseFile(res, opts.output);
|
|
5354
|
+
console.error(`${res.status} \u2192 ${opts.output}`);
|
|
5355
|
+
} else if (/json/.test(type)) {
|
|
5356
|
+
const text = await res.text();
|
|
5357
|
+
let printed = text;
|
|
5358
|
+
try {
|
|
5359
|
+
printed = JSON.stringify(JSON.parse(text), null, 2);
|
|
5360
|
+
} catch {
|
|
5361
|
+
}
|
|
5362
|
+
(res.ok ? console.log : console.error)(printed);
|
|
5363
|
+
} else if (/^text\/|xml|csv|markdown/.test(type) || !type) {
|
|
5364
|
+
(res.ok ? console.log : console.error)(await res.text());
|
|
5365
|
+
} else {
|
|
5366
|
+
console.error(`${res.status}: ${type} body (${res.headers.get("content-length") ?? "?"} bytes); pass --output <file> to save it`);
|
|
5367
|
+
}
|
|
5368
|
+
if (!res.ok && res.status !== 304) process.exitCode = 1;
|
|
5369
|
+
}
|
|
5370
|
+
|
|
5264
5371
|
// src/library.ts
|
|
5265
5372
|
var artifactPath = (id) => `/library/artifacts/${encodeURIComponent(id)}`;
|
|
5266
5373
|
async function listLibrary(query = {}) {
|
|
@@ -5295,9 +5402,139 @@ function renderLibraryArtifact(artifact2) {
|
|
|
5295
5402
|
const version = artifact2.currentVersion ? `v${artifact2.currentVersion}` : "";
|
|
5296
5403
|
return `${artifact2.id} ${artifact2.name} ${version}${artifact2.shared ? " shared" : ""}`;
|
|
5297
5404
|
}
|
|
5405
|
+
var libraryFileRefSchema = external_exports.discriminatedUnion("kind", [
|
|
5406
|
+
external_exports.object({ kind: external_exports.literal("agent_prompt"), agentId: external_exports.string().min(1).max(200).regex(/^[a-zA-Z0-9_-]+$/) }).strict(),
|
|
5407
|
+
external_exports.object({ kind: external_exports.literal("file"), fileId: external_exports.string().min(1), sessionId: external_exports.string().min(1).optional() }).strict(),
|
|
5408
|
+
external_exports.object({ kind: external_exports.literal("task_file"), taskId: external_exports.string().min(1), path: external_exports.string().min(1) }).strict(),
|
|
5409
|
+
external_exports.object({ kind: external_exports.literal("memory_note"), storeId: external_exports.string().min(1), memoryId: external_exports.string().min(1) }).strict(),
|
|
5410
|
+
external_exports.object({ kind: external_exports.literal("skill_file"), skillId: external_exports.string().min(1), path: external_exports.string().min(1) }).strict(),
|
|
5411
|
+
external_exports.object({ kind: external_exports.literal("artifact"), artifactId: external_exports.string().min(1) }).strict(),
|
|
5412
|
+
external_exports.object({ kind: external_exports.literal("platform_artifact"), artifactId: external_exports.string().min(1), path: external_exports.string().min(1).optional() }).strict()
|
|
5413
|
+
]);
|
|
5414
|
+
var linkAccessSchema = external_exports.enum(["none", "view", "edit"]);
|
|
5415
|
+
var linkMemberSchema = external_exports.object({ userId: external_exports.string().min(1), access: external_exports.enum(["view", "edit"]) });
|
|
5416
|
+
var linkRevisionSchema = external_exports.number().int().nonnegative();
|
|
5417
|
+
var libraryLinksSchema = external_exports.object({
|
|
5418
|
+
link: external_exports.object({
|
|
5419
|
+
id: external_exports.string().nullable(),
|
|
5420
|
+
ref: libraryFileRefSchema,
|
|
5421
|
+
workspace: external_exports.string().nullable(),
|
|
5422
|
+
revision: linkRevisionSchema,
|
|
5423
|
+
editable: external_exports.boolean(),
|
|
5424
|
+
workspaceAccess: linkAccessSchema,
|
|
5425
|
+
members: external_exports.array(linkMemberSchema),
|
|
5426
|
+
publicEnabled: external_exports.boolean(),
|
|
5427
|
+
sharedUrl: external_exports.string().nullable(),
|
|
5428
|
+
publicUrl: external_exports.string().nullable()
|
|
5429
|
+
}),
|
|
5430
|
+
availableMembers: external_exports.array(external_exports.object({ userId: external_exports.string(), name: external_exports.string().nullable(), email: external_exports.string().nullable() }))
|
|
5431
|
+
});
|
|
5432
|
+
function parseLibraryFileRef(value) {
|
|
5433
|
+
return libraryFileRefSchema.parse(JSON.parse(value));
|
|
5434
|
+
}
|
|
5435
|
+
async function getLibraryLinks(ref, workspace2) {
|
|
5436
|
+
const params = new URLSearchParams({ ref: JSON.stringify(libraryFileRefSchema.parse(ref)), ...workspace2 ? { workspace: workspace2 } : {} });
|
|
5437
|
+
const result = libraryLinksSchema.parse(await api("GET", `/library/links?${params}`));
|
|
5438
|
+
if (JSON.stringify(result.link.ref) !== JSON.stringify(libraryFileRefSchema.parse(ref)) || workspace2 !== void 0 && result.link.workspace !== workspace2) throw new Error("The API returned sharing for a different source. No access was changed.");
|
|
5439
|
+
return result;
|
|
5440
|
+
}
|
|
5441
|
+
async function updateLibraryLinks(ref, change) {
|
|
5442
|
+
const current = await getLibraryLinks(ref, change.workspace);
|
|
5443
|
+
if (change.revision !== void 0 && linkRevisionSchema.parse(change.revision) !== current.link.revision) throw new Error("Sharing changed since that revision. Read the current links and retry.");
|
|
5444
|
+
const members = new Map(current.link.members.map((member) => [member.userId, member]));
|
|
5445
|
+
for (const member of change.memberChanges ?? []) {
|
|
5446
|
+
const userId = external_exports.string().min(1).parse(member.userId);
|
|
5447
|
+
const access = linkAccessSchema.parse(member.access);
|
|
5448
|
+
if (access === "none") members.delete(userId);
|
|
5449
|
+
else members.set(userId, { userId, access });
|
|
5450
|
+
}
|
|
5451
|
+
return libraryLinksSchema.parse(await api("PUT", "/library/links", {
|
|
5452
|
+
ref,
|
|
5453
|
+
workspace: current.link.workspace,
|
|
5454
|
+
revision: current.link.revision,
|
|
5455
|
+
workspaceAccess: change.workspaceAccess === void 0 ? current.link.workspaceAccess : linkAccessSchema.parse(change.workspaceAccess),
|
|
5456
|
+
members: [...members.values()],
|
|
5457
|
+
publicEnabled: change.publicEnabled === void 0 ? current.link.publicEnabled : external_exports.boolean().parse(change.publicEnabled)
|
|
5458
|
+
}));
|
|
5459
|
+
}
|
|
5460
|
+
async function revokeLibraryLinks(ref, revision, workspace2) {
|
|
5461
|
+
return libraryLinksSchema.parse(await api("DELETE", "/library/links", {
|
|
5462
|
+
ref: libraryFileRefSchema.parse(ref),
|
|
5463
|
+
revision: linkRevisionSchema.parse(revision),
|
|
5464
|
+
...workspace2 ? { workspace: workspace2 } : {}
|
|
5465
|
+
}));
|
|
5466
|
+
}
|
|
5467
|
+
var sharedLibraryToken = external_exports.string().length(43).regex(/^[A-Za-z0-9_-]{43}$/, "use the 43-character token from the Library shared or public URL");
|
|
5468
|
+
var sharedLibrarySource = external_exports.object({
|
|
5469
|
+
name: external_exports.string(),
|
|
5470
|
+
format: external_exports.enum(["file", "site"]),
|
|
5471
|
+
mediaType: external_exports.string(),
|
|
5472
|
+
revision: external_exports.string(),
|
|
5473
|
+
editable: external_exports.boolean(),
|
|
5474
|
+
url: external_exports.string(),
|
|
5475
|
+
maxBytes: external_exports.number(),
|
|
5476
|
+
history: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown()))
|
|
5477
|
+
}).passthrough();
|
|
5478
|
+
var sharedLibrarySaved = external_exports.object({ url: external_exports.string(), revision: external_exports.string().min(1), publishedAt: external_exports.string().datetime({ offset: true }), text: external_exports.string().nullable().optional(), historyRevision: external_exports.string().optional() });
|
|
5479
|
+
var sharedLibrarySaveSchema = external_exports.object({
|
|
5480
|
+
revision: external_exports.string().min(1),
|
|
5481
|
+
text: external_exports.string().optional(),
|
|
5482
|
+
html: external_exports.string().optional(),
|
|
5483
|
+
office: external_exports.string().optional(),
|
|
5484
|
+
docx: external_exports.string().optional(),
|
|
5485
|
+
restoreRevision: external_exports.string().min(1).optional(),
|
|
5486
|
+
requestId: external_exports.string().uuid().optional()
|
|
5487
|
+
}).strict().refine((body) => [body.text, body.html, body.office, body.docx, body.restoreRevision].filter((field) => field !== void 0).length === 1, "provide exactly one of text, html, office, docx or restoreRevision");
|
|
5488
|
+
async function readSharedLibraryFile(token, options = {}) {
|
|
5489
|
+
const path = `/library/${options.public ? "public" : "shared"}/${sharedLibraryToken.parse(token)}`;
|
|
5490
|
+
if (!options.output) return sharedLibrarySource.parse(await api("GET", path, void 0, { auth: options.public !== true }));
|
|
5491
|
+
const response = await apiRaw("GET", `${path}?raw=1`, { auth: options.public !== true });
|
|
5492
|
+
if (!response.ok) {
|
|
5493
|
+
const body = await response.json().catch(() => null);
|
|
5494
|
+
throw new ApiError(response.status, body?.error?.code ?? "http_error", body?.error?.message ?? `Download failed (${response.status}).`);
|
|
5495
|
+
}
|
|
5496
|
+
return { output: options.output, bytes: await writeResponseFile(response, options.output) };
|
|
5497
|
+
}
|
|
5498
|
+
async function saveSharedLibraryFile(token, body) {
|
|
5499
|
+
return sharedLibrarySaved.parse(await api("PUT", `/library/shared/${sharedLibraryToken.parse(token)}`, sharedLibrarySaveSchema.parse(body)));
|
|
5500
|
+
}
|
|
5501
|
+
function registerLibraryLinkCommands(library2) {
|
|
5502
|
+
const libraryLinks = library2.command("links").description("share or publish any Library file; --workspace selects the sharing audience without moving the file");
|
|
5503
|
+
libraryLinks.command("read").description("read a shared native document snapshot; --public reads a public view-only link").requiredOption("--token <token>", "43-character token from a Library shared or public URL").option("--public", "use the public reader without sending your API key").option("--output <file>", "stream the original bytes to this file instead of printing the JSON snapshot").action(async (opts) => {
|
|
5504
|
+
console.log(JSON.stringify(await readSharedLibraryFile(opts.token, opts), null, 2));
|
|
5505
|
+
});
|
|
5506
|
+
libraryLinks.command("save").description("save through a live recipient edit grant; --revision is the opaque source revision from links read").requiredOption("--token <token>", "43-character token from the authenticated shared URL (public URLs have no writer)").requiredOption("--revision <revision>", "native source revision from links read; stale revisions fail without retry").option("--file <path>", "UTF-8 text file to save").option("--data <json>", "instead of --file, JSON/ @file / - containing exactly one text/html/office/docx/restoreRevision and optional requestId").action(async (opts) => {
|
|
5507
|
+
if (opts.file !== void 0 === (opts.data !== void 0)) throw new Error("Choose exactly one of --file or --data.");
|
|
5508
|
+
const body = opts.file !== void 0 ? { text: new TextDecoder("utf-8", { fatal: true }).decode(readFileSync17(opts.file)) } : JSON.parse(readData(opts.data));
|
|
5509
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) throw new Error("--data must be a JSON object with one native save field.");
|
|
5510
|
+
if ("revision" in body && body.revision !== opts.revision) throw new Error("--data revision must match --revision.");
|
|
5511
|
+
console.log(JSON.stringify(await saveSharedLibraryFile(opts.token, sharedLibrarySaveSchema.parse({ ...body, revision: opts.revision })), null, 2));
|
|
5512
|
+
});
|
|
5513
|
+
const linkRefOption = (command) => command.requiredOption("--ref <json>", 'file reference JSON, e.g. {"kind":"file","fileId":"file_\u2026"}').option("--workspace <slug>", "the team audience for this link (omit for private/public-only sharing)");
|
|
5514
|
+
const linkRevision = (value) => value === void 0 ? void 0 : linkRevisionSchema.parse(Number(external_exports.string().regex(/^\d+$/, "revision must be a nonnegative integer").parse(value)));
|
|
5515
|
+
const printLibraryLinks = (value) => console.log(JSON.stringify(value, null, 2));
|
|
5516
|
+
linkRefOption(libraryLinks.command("show").description("read sharing, real workspace members and the current revision without creating a link")).action(async (opts) => printLibraryLinks(await getLibraryLinks(parseLibraryFileRef(opts.ref), opts.workspace)));
|
|
5517
|
+
linkRefOption(libraryLinks.command("share").description("change workspace or specific members' access while preserving every unmentioned grant")).option("--workspace-access <access>", "none, view or edit (edit requires an editable source)").option("--member <user:access>", "grant a member view or edit; repeat to update several members", (value, previous) => [...previous, value], []).option("--remove-member <user>", "clear a member override; workspace access still applies", (value, previous) => [...previous, value], []).option("--revision <n>", "refuse if sharing changed since this reviewed revision").action(async (opts) => {
|
|
5518
|
+
if (opts.workspaceAccess === void 0 && !opts.member?.length && !opts.removeMember?.length) throw new Error("Choose --workspace-access, --member or --remove-member; links show reads without changing access.");
|
|
5519
|
+
const memberChanges = (opts.member ?? []).map((value) => {
|
|
5520
|
+
const colon = value.lastIndexOf(":");
|
|
5521
|
+
if (colon < 1) throw new Error("--member must be a user id followed by :view or :edit");
|
|
5522
|
+
return { userId: value.slice(0, colon), access: external_exports.enum(["view", "edit"]).parse(value.slice(colon + 1)) };
|
|
5523
|
+
});
|
|
5524
|
+
memberChanges.push(...(opts.removeMember ?? []).map((userId) => ({ userId, access: "none" })));
|
|
5525
|
+
printLibraryLinks(await updateLibraryLinks(parseLibraryFileRef(opts.ref), {
|
|
5526
|
+
workspace: opts.workspace,
|
|
5527
|
+
revision: linkRevision(opts.revision),
|
|
5528
|
+
memberChanges,
|
|
5529
|
+
workspaceAccess: opts.workspaceAccess === void 0 ? void 0 : external_exports.enum(["none", "view", "edit"]).parse(opts.workspaceAccess)
|
|
5530
|
+
}));
|
|
5531
|
+
});
|
|
5532
|
+
linkRefOption(libraryLinks.command("publish").description("create a public view-only link; --disable revokes only public access and keeps other grants")).option("--disable", "turn off public viewing").option("--revision <n>", "refuse if sharing changed since this reviewed revision").action(async (opts) => printLibraryLinks(await updateLibraryLinks(parseLibraryFileRef(opts.ref), { workspace: opts.workspace, revision: linkRevision(opts.revision), publicEnabled: !opts.disable })));
|
|
5533
|
+
linkRefOption(libraryLinks.command("revoke").description("stop all sharing at an explicitly reviewed revision")).requiredOption("--revision <n>", "current revision from links show; stale revisions fail without retry").action(async (opts) => printLibraryLinks(await revokeLibraryLinks(parseLibraryFileRef(opts.ref), linkRevision(opts.revision), opts.workspace)));
|
|
5534
|
+
}
|
|
5298
5535
|
|
|
5299
5536
|
// src/design-systems.ts
|
|
5300
|
-
import { readdirSync as readdirSync8, readFileSync as
|
|
5537
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync18, statSync as statSync9 } from "fs";
|
|
5301
5538
|
import { join as join18, relative as relative5, sep as sep3 } from "path";
|
|
5302
5539
|
var TEXT2 = /\.(mdx?|markdown|txt|json|m?js|cjs|jsx|tsx?|css|html?|svg|xml|csv|ya?ml|toml)$/i;
|
|
5303
5540
|
var MEDIA = {
|
|
@@ -5341,7 +5578,7 @@ function fileTableFrom(dir) {
|
|
|
5341
5578
|
continue;
|
|
5342
5579
|
}
|
|
5343
5580
|
const key = relative5(dir, path).split(sep3).join("/");
|
|
5344
|
-
const bytes =
|
|
5581
|
+
const bytes = readFileSync18(path);
|
|
5345
5582
|
files2[key] = TEXT2.test(name) ? bytes.toString("utf8") : `data:${MEDIA[name.split(".").pop()?.toLowerCase() ?? ""] ?? "application/octet-stream"};base64,${bytes.toString("base64")}`;
|
|
5346
5583
|
}
|
|
5347
5584
|
};
|
|
@@ -5364,80 +5601,6 @@ async function designComments(id, input) {
|
|
|
5364
5601
|
return api(input ? "POST" : "GET", `/artifacts/${encodeURIComponent(id)}/design-system/comments`, input);
|
|
5365
5602
|
}
|
|
5366
5603
|
|
|
5367
|
-
// src/api-command.ts
|
|
5368
|
-
import { readFileSync as readFileSync17, writeFileSync as writeFileSync9 } from "fs";
|
|
5369
|
-
var API_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
5370
|
-
function readData(data, stdin = () => readFileSync17(0, "utf8")) {
|
|
5371
|
-
if (data === void 0) return void 0;
|
|
5372
|
-
const raw = data === "-" ? stdin() : data.startsWith("@") ? readFileSync17(data.slice(1), "utf8") : data;
|
|
5373
|
-
try {
|
|
5374
|
-
JSON.parse(raw);
|
|
5375
|
-
} catch {
|
|
5376
|
-
throw new Error("--data must be JSON (inline, @file or - for stdin)");
|
|
5377
|
-
}
|
|
5378
|
-
return raw;
|
|
5379
|
-
}
|
|
5380
|
-
function requestPath(path, query = []) {
|
|
5381
|
-
if (!path.startsWith("/") || path.startsWith("//")) throw new Error("path must start with /, e.g. /threads");
|
|
5382
|
-
const clean = path.replace(/^\/v1(?=\/)/, "");
|
|
5383
|
-
const params = new URLSearchParams();
|
|
5384
|
-
for (const pair of query) {
|
|
5385
|
-
const at = pair.indexOf("=");
|
|
5386
|
-
if (at <= 0) throw new Error(`--query needs key=value, got "${pair}"`);
|
|
5387
|
-
params.append(pair.slice(0, at), pair.slice(at + 1));
|
|
5388
|
-
}
|
|
5389
|
-
const sep4 = clean.includes("?") ? "&" : "?";
|
|
5390
|
-
const encoded = params.toString();
|
|
5391
|
-
return encoded ? `${clean}${sep4}${encoded}` : clean;
|
|
5392
|
-
}
|
|
5393
|
-
function matchOperations(doc, words) {
|
|
5394
|
-
const needles = words.map((w) => w.toLowerCase());
|
|
5395
|
-
const out = [];
|
|
5396
|
-
for (const [path, item] of Object.entries(doc.paths ?? {})) {
|
|
5397
|
-
for (const [method, op] of Object.entries(item)) {
|
|
5398
|
-
if (!API_METHODS.includes(method.toUpperCase())) continue;
|
|
5399
|
-
const hay = `${method} ${path} ${op.summary ?? ""} ${op.operationId ?? ""}`.toLowerCase();
|
|
5400
|
-
if (needles.every((n) => hay.includes(n))) out.push({ method: method.toUpperCase(), path, summary: op.summary, operationId: op.operationId });
|
|
5401
|
-
}
|
|
5402
|
-
}
|
|
5403
|
-
return out.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
|
|
5404
|
-
}
|
|
5405
|
-
async function searchApi(words) {
|
|
5406
|
-
const res = await apiRaw("GET", "/openapi.json", { auth: false });
|
|
5407
|
-
if (!res.ok) throw new Error(`could not read the API reference (${res.status})`);
|
|
5408
|
-
const ops = matchOperations(await res.json(), words);
|
|
5409
|
-
if (!ops.length) {
|
|
5410
|
-
console.log("no operations match");
|
|
5411
|
-
return;
|
|
5412
|
-
}
|
|
5413
|
-
for (const op of ops) console.log(`${op.method.padEnd(6)} ${op.path}${op.summary ? ` \u2014 ${op.summary}` : ""}`);
|
|
5414
|
-
}
|
|
5415
|
-
async function callApi(method, path, opts) {
|
|
5416
|
-
const verb = method.toUpperCase();
|
|
5417
|
-
if (!API_METHODS.includes(verb)) throw new Error(`method must be one of ${API_METHODS.join(", ")} or "search"`);
|
|
5418
|
-
const body = readData(opts.data);
|
|
5419
|
-
if (body !== void 0 && verb === "GET") throw new Error("a GET takes no --data; use --query");
|
|
5420
|
-
const res = await apiRaw(verb, requestPath(path, opts.query), { body, idempotencyKey: opts.idempotencyKey, universe: opts.workspace });
|
|
5421
|
-
const type = res.headers.get("content-type") ?? "";
|
|
5422
|
-
if (opts.output) {
|
|
5423
|
-
writeFileSync9(opts.output, new Uint8Array(await res.arrayBuffer()));
|
|
5424
|
-
console.error(`${res.status} \u2192 ${opts.output}`);
|
|
5425
|
-
} else if (/json/.test(type)) {
|
|
5426
|
-
const text = await res.text();
|
|
5427
|
-
let printed = text;
|
|
5428
|
-
try {
|
|
5429
|
-
printed = JSON.stringify(JSON.parse(text), null, 2);
|
|
5430
|
-
} catch {
|
|
5431
|
-
}
|
|
5432
|
-
(res.ok ? console.log : console.error)(printed);
|
|
5433
|
-
} else if (/^text\/|xml|csv|markdown/.test(type) || !type) {
|
|
5434
|
-
(res.ok ? console.log : console.error)(await res.text());
|
|
5435
|
-
} else {
|
|
5436
|
-
console.error(`${res.status}: ${type} body (${res.headers.get("content-length") ?? "?"} bytes); pass --output <file> to save it`);
|
|
5437
|
-
}
|
|
5438
|
-
if (!res.ok && res.status !== 304) process.exitCode = 1;
|
|
5439
|
-
}
|
|
5440
|
-
|
|
5441
5604
|
// src/billing-plans.ts
|
|
5442
5605
|
var readCodingPlan = () => api("GET", "/billing/coding-plan");
|
|
5443
5606
|
function joinCodingPlan(dollars2, requestId) {
|
|
@@ -5524,7 +5687,7 @@ function workspaceFlagIsCommands(argv, commandPath) {
|
|
|
5524
5687
|
}
|
|
5525
5688
|
|
|
5526
5689
|
// src/harness.ts
|
|
5527
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as
|
|
5690
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync19, writeFileSync as writeFileSync9 } from "fs";
|
|
5528
5691
|
import { dirname as dirname9, join as join19, resolve as resolve8 } from "path";
|
|
5529
5692
|
var HARNESS_FILE = "harness.json";
|
|
5530
5693
|
function harnessFilePath(dir) {
|
|
@@ -5536,7 +5699,7 @@ function readHarnessFile(dir) {
|
|
|
5536
5699
|
throw new Error(`no ${HARNESS_FILE} found in ${resolve8(dir)} \u2014 run \`sky harness init\` first`);
|
|
5537
5700
|
}
|
|
5538
5701
|
try {
|
|
5539
|
-
return JSON.parse(
|
|
5702
|
+
return JSON.parse(readFileSync19(path, "utf8"));
|
|
5540
5703
|
} catch (err) {
|
|
5541
5704
|
throw new Error(`could not parse ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
5542
5705
|
}
|
|
@@ -5567,7 +5730,7 @@ function harnessInit(dir) {
|
|
|
5567
5730
|
throw new Error(`${path} already exists \u2014 delete it to re-init`);
|
|
5568
5731
|
}
|
|
5569
5732
|
mkdirSync6(dirname9(path), { recursive: true });
|
|
5570
|
-
|
|
5733
|
+
writeFileSync9(path, `${JSON.stringify(INIT_SKELETON, null, 2)}
|
|
5571
5734
|
`);
|
|
5572
5735
|
console.log(`Created ${path}`);
|
|
5573
5736
|
console.log(INIT_COMMENT);
|
|
@@ -6306,7 +6469,7 @@ sessionWorkspace.command("cat <ref> <path>").description("print a file (up to 1
|
|
|
6306
6469
|
run(async (ref, path, opts) => {
|
|
6307
6470
|
const bytes = await readFile(await resolveSessionRef(ref), path);
|
|
6308
6471
|
if (opts.out) {
|
|
6309
|
-
|
|
6472
|
+
writeFileSync10(opts.out, bytes);
|
|
6310
6473
|
console.error(`saved ${bytes.length} bytes to ${opts.out}`);
|
|
6311
6474
|
} else process.stdout.write(bytes);
|
|
6312
6475
|
})
|
|
@@ -6323,7 +6486,7 @@ sessionWorkspace.command("patch <ref> [repo]").description("the work in a reposi
|
|
|
6323
6486
|
console.error(`${meta.repo}: ${meta.commits.length} commit${meta.commits.length === 1 ? "" : "s"} since ${meta.base_branch || "the imported copy"} (${meta.base_commit.slice(0, 12)})`);
|
|
6324
6487
|
if (!patch.length) console.error("nothing changed");
|
|
6325
6488
|
else if (opts.out) {
|
|
6326
|
-
|
|
6489
|
+
writeFileSync10(opts.out, patch);
|
|
6327
6490
|
console.error(`wrote ${opts.out} \u2014 apply with: git apply ${opts.out}`);
|
|
6328
6491
|
} else process.stdout.write(patch);
|
|
6329
6492
|
})
|
|
@@ -6828,14 +6991,14 @@ task.command("get <task> <path>").description("read one task file; prints it, or
|
|
|
6828
6991
|
run(async (taskId, path, opts) => {
|
|
6829
6992
|
const bytes = await readTaskFile(taskId, path);
|
|
6830
6993
|
if (opts.out) {
|
|
6831
|
-
|
|
6994
|
+
writeFileSync10(opts.out, bytes);
|
|
6832
6995
|
console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
|
|
6833
6996
|
} else process.stdout.write(bytes);
|
|
6834
6997
|
})
|
|
6835
6998
|
);
|
|
6836
6999
|
task.command("put <task> <path> <local>").description("write a local file to <path> in the task's files (every session of the task sees it)").action(
|
|
6837
7000
|
run(async (taskId, path, local) => {
|
|
6838
|
-
const { file, conflict } = await writeTaskFile(taskId, path,
|
|
7001
|
+
const { file, conflict } = await writeTaskFile(taskId, path, readFileSync20(local), mediaTypeFor(local));
|
|
6839
7002
|
console.log(`${renderTaskFile(file)}${conflict ? " (replaced a version you had not seen)" : ""}`);
|
|
6840
7003
|
})
|
|
6841
7004
|
);
|
|
@@ -6908,6 +7071,34 @@ task.command("verdict <task> <did-the-job>").description("record whether the tas
|
|
|
6908
7071
|
console.log(`Recorded verdict on task ${updated.id}: did_the_job=${value === "yes"}`);
|
|
6909
7072
|
})
|
|
6910
7073
|
);
|
|
7074
|
+
var plugins = program.command("plugins").description("Claude Code plugins in the workspace: install from GitHub, list, remove");
|
|
7075
|
+
plugins.command("list").description("the workspace's installed plugins and the skills each one installed").option("--json", "print the list as JSON").action(
|
|
7076
|
+
run(async (opts) => {
|
|
7077
|
+
const { plugins: list } = await api("GET", "/plugins");
|
|
7078
|
+
if (opts.json) return void console.log(JSON.stringify(list));
|
|
7079
|
+
if (list.length === 0) return void console.log("No plugins. `sky plugins install github:owner/repo[/path][@ref]`");
|
|
7080
|
+
for (const p of list) console.log(`${p.name} ${p.skills.length} skill${p.skills.length === 1 ? "" : "s"}: ${p.skills.map((s) => s.displayName.split("/").pop()).join(", ")}`);
|
|
7081
|
+
})
|
|
7082
|
+
);
|
|
7083
|
+
plugins.command("install <source>").description("install or update a plugin: github:owner/repo[/path][@ref] or a github.com URL").option("--json", "print the result as JSON").action(
|
|
7084
|
+
run(async (source, opts) => {
|
|
7085
|
+
const result = await api("POST", "/plugins", { source });
|
|
7086
|
+
if (opts.json) return void console.log(JSON.stringify(result));
|
|
7087
|
+
console.log(`Installed ${result.plugin.name}${result.plugin.version ? ` ${result.plugin.version}` : ""} from ${result.plugin.source}: ${result.skills.length} skill(s), on for every new session.`);
|
|
7088
|
+
for (const c of result.connectors) {
|
|
7089
|
+
const state = c.app === null ? "no AgentSky connector for it yet" : c.connected ? `uses your ${c.app} connection` : `connect ${c.app}: ${c.connect_url}`;
|
|
7090
|
+
console.log(` connector ${c.server}: ${state}`);
|
|
7091
|
+
}
|
|
7092
|
+
for (const s of result.skipped) console.log(` skipped ${s.part}: ${s.reason}`);
|
|
7093
|
+
for (const r of result.removed) console.log(` ${r.part}: ${r.result.replace("_", " ")} (no longer in the plugin)`);
|
|
7094
|
+
})
|
|
7095
|
+
);
|
|
7096
|
+
plugins.command("rm <name>").description("remove a plugin's skills (a skill a session still holds is switched off)").action(
|
|
7097
|
+
run(async (name) => {
|
|
7098
|
+
const result = await api("DELETE", `/plugins/${encodeURIComponent(name)}`);
|
|
7099
|
+
console.log(`Removed ${result.name}: ${result.parts.map((p) => `${p.part} ${p.result.replace("_", " ")}`).join(", ")}`);
|
|
7100
|
+
})
|
|
7101
|
+
);
|
|
6911
7102
|
var skills = program.command("skills").description("the workspace's skill store: upload a skill, then attach it to an agent (sky skills attach, or [[skills]] in agent.toml)");
|
|
6912
7103
|
skills.command("upload <dir>").description("upload a skill directory (SKILL.md at its root) as a new skill").option("--name <name>", "display name (default: the directory's name)").option("--json", "print the stored skill as JSON").action(
|
|
6913
7104
|
run(async (dir, opts) => {
|
|
@@ -6999,7 +7190,7 @@ library.command("list").description("your Library, newest first").option("--sear
|
|
|
6999
7190
|
);
|
|
7000
7191
|
library.command("upload <path>").description("save a file from this computer to your Library").option("--workspace <key>", "place it in this workspace").action(
|
|
7001
7192
|
run(async (path, opts) => {
|
|
7002
|
-
const bytes =
|
|
7193
|
+
const bytes = readFileSync20(path);
|
|
7003
7194
|
const { artifact: artifact2 } = await uploadToLibrary({ bytes, name: basename9(path), mediaType: "application/octet-stream" }, `sky-upload-${crypto.randomUUID()}`, opts.workspace);
|
|
7004
7195
|
console.log(renderLibraryArtifact(artifact2));
|
|
7005
7196
|
})
|
|
@@ -7030,10 +7221,11 @@ library.command("place <id> <workspace>").description('place your artifact in a
|
|
|
7030
7221
|
library.command("download <id> <out>").description("save one version's bytes to a file").option("--version <n>", "a saved version (the current one when omitted)").action(
|
|
7031
7222
|
run(async (id, out, opts) => {
|
|
7032
7223
|
const { bytes } = await downloadLibraryArtifact(id, opts.version ? Number(opts.version) : void 0);
|
|
7033
|
-
|
|
7224
|
+
writeFileSync10(out, bytes);
|
|
7034
7225
|
console.log(`wrote ${bytes.length} bytes to ${out}`);
|
|
7035
7226
|
})
|
|
7036
7227
|
);
|
|
7228
|
+
registerLibraryLinkCommands(library);
|
|
7037
7229
|
var artifact = program.command("artifact").description("artifacts: publish a task's files as a named, shareable result");
|
|
7038
7230
|
artifact.command("list").description("the workspace's artifacts, or one task's with --task").option("--task <task>", "only this task's artifacts").action(
|
|
7039
7231
|
run(async (opts) => {
|
|
@@ -7051,7 +7243,7 @@ artifact.command("get <id> <path>").description("read one file of an artifact; p
|
|
|
7051
7243
|
run(async (id, path, opts) => {
|
|
7052
7244
|
const bytes = await readArtifactFile(id, path);
|
|
7053
7245
|
if (opts.out) {
|
|
7054
|
-
|
|
7246
|
+
writeFileSync10(opts.out, bytes);
|
|
7055
7247
|
console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
|
|
7056
7248
|
} else process.stdout.write(bytes);
|
|
7057
7249
|
})
|
|
@@ -7089,7 +7281,7 @@ designSystem.command("import <task> <folder>").description("import a local desig
|
|
|
7089
7281
|
);
|
|
7090
7282
|
designSystem.command("tokens <id> <file>").description("save a tokens.json file as the system's next version; --base is the version you edited").requiredOption("--base <version>", "the version the file was edited from", (value) => Number(value)).option("--note <note>", "one line saying what changed").action(
|
|
7091
7283
|
run(async (id, file, opts) => {
|
|
7092
|
-
const tokens = JSON.parse(
|
|
7284
|
+
const tokens = JSON.parse(readFileSync20(resolve9(file), "utf8"));
|
|
7093
7285
|
console.log(renderArtifact(await saveDesignTokens(id, opts.base, tokens, opts.note)));
|
|
7094
7286
|
})
|
|
7095
7287
|
);
|
|
@@ -7402,7 +7594,7 @@ usageOptions(
|
|
|
7402
7594
|
run(async (opts) => {
|
|
7403
7595
|
const { bytes } = await apiBytes("GET", `/billing/usage/export${usageQuery(opts)}`);
|
|
7404
7596
|
if (opts.out) {
|
|
7405
|
-
|
|
7597
|
+
writeFileSync10(opts.out, bytes);
|
|
7406
7598
|
console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
|
|
7407
7599
|
} else {
|
|
7408
7600
|
process.stdout.write(bytes);
|
|
@@ -8014,7 +8206,7 @@ notes.command("read <storeId> <noteId>").description("print one note").action(
|
|
|
8014
8206
|
notes.command("save <storeId> <file>").description("write a note from a local file: --path creates one, --note saves a new version of one").option("--path <path>", "path of a new note, e.g. /projects/launch.md").option("--note <noteId>", "the note to update").action(
|
|
8015
8207
|
run(async (storeId, file, opts) => {
|
|
8016
8208
|
if (!opts.path === !opts.note) throw new Error("pass exactly one of --path (new note) or --note (update)");
|
|
8017
|
-
const content =
|
|
8209
|
+
const content = readFileSync20(file, "utf8");
|
|
8018
8210
|
const target = `/memory_stores/${encodeURIComponent(storeId)}/memories${opts.note ? `/${encodeURIComponent(opts.note)}` : ""}`;
|
|
8019
8211
|
const { memory: memory2 } = await api("POST", target, { content, ...opts.path ? { path: opts.path } : {} });
|
|
8020
8212
|
console.log(`Saved ${memory2.path} (${memory2.id})`);
|
|
@@ -8114,7 +8306,7 @@ harness.command("connect").description("run an ACP agent (the command after --)
|
|
|
8114
8306
|
}));
|
|
8115
8307
|
var traceCmd = program.command("trace").description("correlate this machine's agent work with the cloud sessions it starts (metadata only unless you choose content)");
|
|
8116
8308
|
traceCmd.command("start").description("start a trace: a grant for this machine, a root span, and the spool the hooks write to").option("--name <name>", "a name for the task").option("--source <source>", "how this machine reports itself", "claude-code").option("--hooks [settings]", "also install the Claude Code hooks (default: ./.claude/settings.local.json)").option("--capture <scopes>", "also send content, redacted on this machine first: any of prompts,tool_output,files").option("--file <path>", "a file the files scope may send (repeatable)", collect).option("--dir <path>", "a folder whose files the files scope may send when a file tool touches them (repeatable)", collect).action(run(async (opts) => {
|
|
8117
|
-
const { readState, writeState, record, installClaudeHooks, parseContentScopes, chosenPaths, fileEvent } = await import("./trace-
|
|
8309
|
+
const { readState, writeState, record, installClaudeHooks, parseContentScopes, chosenPaths, fileEvent } = await import("./trace-HV4E2BPX.js");
|
|
8118
8310
|
if (readState()) throw new Error("a trace is already running here \u2014 `sky trace stop` it first");
|
|
8119
8311
|
const scopes = parseContentScopes(opts.capture);
|
|
8120
8312
|
const chosen = chosenPaths(opts.file ?? [], opts.dir ?? []);
|
|
@@ -8149,7 +8341,7 @@ traceCmd.command("start").description("start a trace: a grant for this machine,
|
|
|
8149
8341
|
}));
|
|
8150
8342
|
traceCmd.command("hook").description("record one Claude Code hook event read from stdin (run by the installed hooks; never fails, prints nothing)").action(async () => {
|
|
8151
8343
|
try {
|
|
8152
|
-
const { readState, record, flush, grantSender, eventsForClaudeHook, contentForClaudeHook, clearState } = await import("./trace-
|
|
8344
|
+
const { readState, record, flush, grantSender, eventsForClaudeHook, contentForClaudeHook, clearState } = await import("./trace-HV4E2BPX.js");
|
|
8153
8345
|
const chunks = [];
|
|
8154
8346
|
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
8155
8347
|
const input = JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}");
|
|
@@ -8162,14 +8354,14 @@ traceCmd.command("hook").description("record one Claude Code hook event read fro
|
|
|
8162
8354
|
}
|
|
8163
8355
|
});
|
|
8164
8356
|
traceCmd.command("flush").description("send what the spool holds, retrying with backoff").action(run(async () => {
|
|
8165
|
-
const { readState, flush, grantSender } = await import("./trace-
|
|
8357
|
+
const { readState, flush, grantSender } = await import("./trace-HV4E2BPX.js");
|
|
8166
8358
|
const state = readState();
|
|
8167
8359
|
if (!state) throw new Error("no trace is running here");
|
|
8168
8360
|
const outcome = await flush(grantSender(state), { attempts: 4 });
|
|
8169
8361
|
console.log(`sent ${outcome.sent}, refused ${outcome.refused}, given up ${outcome.expired}, still pending ${outcome.pending}${outcome.stopped ? ` (stopped: ${outcome.stopped})` : ""}`);
|
|
8170
8362
|
}));
|
|
8171
8363
|
traceCmd.command("status").description("the running trace and its spool").action(run(async () => {
|
|
8172
|
-
const { readState, spoolStatus } = await import("./trace-
|
|
8364
|
+
const { readState, spoolStatus } = await import("./trace-HV4E2BPX.js");
|
|
8173
8365
|
const state = readState();
|
|
8174
8366
|
if (!state) {
|
|
8175
8367
|
console.log("No trace is running here.");
|
|
@@ -8179,7 +8371,7 @@ traceCmd.command("status").description("the running trace and its spool").action
|
|
|
8179
8371
|
console.log(`${state.trace_id} as ${state.source}: ${spool.pending} pending, ${spool.dropped_full} dropped (spool full), ${spool.dropped_expired} given up, ${spool.refused} refused`);
|
|
8180
8372
|
}));
|
|
8181
8373
|
traceCmd.command("show [id]").description("the trace bundle: spans, the sessions they reach, cost counted once per session").option("--json", "print the bundle as JSON").action(run(async (id, opts) => {
|
|
8182
|
-
const { readState } = await import("./trace-
|
|
8374
|
+
const { readState } = await import("./trace-HV4E2BPX.js");
|
|
8183
8375
|
const ref = id ?? readState()?.trace_id;
|
|
8184
8376
|
if (!ref) throw new Error("name a trace, or start one here");
|
|
8185
8377
|
const bundle = await api("GET", `/traces/${ref}`);
|
|
@@ -8206,7 +8398,7 @@ traceCmd.command("show [id]").description("the trace bundle: spans, the sessions
|
|
|
8206
8398
|
for (const gap of bundle.gaps) console.log(` gap: ${gap.span_id} ${gap.reason}`);
|
|
8207
8399
|
}));
|
|
8208
8400
|
traceCmd.command("stop").description("end the root span, send what is left, and revoke this machine's grant").action(run(async () => {
|
|
8209
|
-
const { readState, record, flush, grantSender, clearState } = await import("./trace-
|
|
8401
|
+
const { readState, record, flush, grantSender, clearState } = await import("./trace-HV4E2BPX.js");
|
|
8210
8402
|
const state = readState();
|
|
8211
8403
|
if (!state) throw new Error("no trace is running here");
|
|
8212
8404
|
if (state.root_span) record(() => [{ span_id: state.root_span, kind: "end", outcome: "completed" }]);
|
|
@@ -8216,7 +8408,7 @@ traceCmd.command("stop").description("end the root span, send what is left, and
|
|
|
8216
8408
|
console.log(`Stopped ${state.trace_id}${outcome.pending ? ` (${outcome.pending} events could not be sent)` : ""}`);
|
|
8217
8409
|
}));
|
|
8218
8410
|
traceCmd.command("sync [payload]").description("upload this machine's agent sessions (Claude Code, Codex, Cursor, Gemini CLI and every other agent `--agents` lists) to the matching workspace's trace library, redacted here first").option("--enable", "turn sync on for this machine").option("--disable", "turn sync off; nothing more is uploaded").option("--route <match=workspace>", "send sessions whose folder path contains <match> to <workspace> (repeatable; replaces the saved rules)", collect).option("--default <workspace>", "where a session no rule matches goes").option("--keep-local", "keep sessions no rule matches on this machine (the default)").option("--session <ref>", "only this session: its id or transcript path (repeatable)", collect).option("--import <export>", "add a downloaded cloud export (claude.ai, ChatGPT, Gemini, Grok, DeepSeek \u2026: its .zip, folder or file) so sync uploads it (repeatable)", collect).option("--agents", "list the agents sync reads and which are on this machine").option("--full", "re-read every session, not only files that changed").option("--limit <n>", "at most this many changed sessions this run", (v) => Number.parseInt(v, 10)).option("--dry-run", "show what would be uploaded without uploading").option("--hook", "run from a Claude Code SessionEnd hook or Codex notify: upload that session in the background and return at once").option("--install-schedule", "also sweep every 15 minutes (macOS launchd)").option("--status", "what sync has done on this machine").option("--quiet", "print only failures").action(async (payload, opts) => {
|
|
8219
|
-
const lib = await import("./trace-library-
|
|
8411
|
+
const lib = await import("./trace-library-HJWI7KM7.js");
|
|
8220
8412
|
if (opts.hook) {
|
|
8221
8413
|
try {
|
|
8222
8414
|
let raw = payload ?? "";
|
|
@@ -8288,11 +8480,11 @@ traceCmd.command("sync [payload]").description("upload this machine's agent sess
|
|
|
8288
8480
|
console.log(`Sweeping every 15 minutes (${plist}); a full re-read runs weekly. Log: ${log}`);
|
|
8289
8481
|
}
|
|
8290
8482
|
if (opts.status) {
|
|
8291
|
-
const { readFileSync:
|
|
8483
|
+
const { readFileSync: readFileSync21 } = await import("fs");
|
|
8292
8484
|
const { join: join20 } = await import("path");
|
|
8293
8485
|
let state = { sessions: {} };
|
|
8294
8486
|
try {
|
|
8295
|
-
state = JSON.parse(
|
|
8487
|
+
state = JSON.parse(readFileSync21(join20(lib.syncConfigPath(), "..", "trace-sync-state.json"), "utf8"));
|
|
8296
8488
|
} catch {
|
|
8297
8489
|
}
|
|
8298
8490
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -8331,7 +8523,7 @@ traceCmd.command("search <query...>").description("search every session in a wor
|
|
|
8331
8523
|
console.log(opts.json ? JSON.stringify(page, null, 2) : renderContextPage(page));
|
|
8332
8524
|
}));
|
|
8333
8525
|
traceCmd.command("library").description("list the sessions in a workspace's trace library, most recently updated first").option("--workspace <slug>", "the workspace (default: the current one)").option("--limit <n>", "how many", (v) => Number.parseInt(v, 10), 20).option("--json", "print the page as JSON").action(run(async (opts) => {
|
|
8334
|
-
const { libraryRequest } = await import("./trace-library-
|
|
8526
|
+
const { libraryRequest } = await import("./trace-library-HJWI7KM7.js");
|
|
8335
8527
|
const workspace2 = opts.workspace ?? currentUniverse();
|
|
8336
8528
|
if (!workspace2) throw new Error("name a workspace with --workspace");
|
|
8337
8529
|
const page = await libraryRequest("GET", `/trace-library?limit=${opts.limit}`, workspace2);
|