@agentsky/sky 2.29.0 → 2.30.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.
@@ -19069,14 +19069,14 @@ var CATALOG_MODELS = [
19069
19069
  "tiers": [
19070
19070
  {
19071
19071
  "maxPromptTokens": 1048576,
19072
- "input": 0.967857,
19073
- "output": 2.902411,
19074
- "cachedInput": 0.048741
19072
+ "input": 0.871072,
19073
+ "output": 2.61217,
19074
+ "cachedInput": 0.043867
19075
19075
  }
19076
19076
  ],
19077
19077
  "maxPrice": {
19078
- "prompt": 0.9174,
19079
- "completion": 2.7511
19078
+ "prompt": 0.82566,
19079
+ "completion": 2.47599
19080
19080
  },
19081
19081
  "reasoningEfforts": [
19082
19082
  "none",
@@ -19101,14 +19101,14 @@ var CATALOG_MODELS = [
19101
19101
  "tiers": [
19102
19102
  {
19103
19103
  "maxPromptTokens": 1048576,
19104
- "input": 0.06963,
19105
- "output": 0.20889,
19106
- "cachedInput": 0.017408
19104
+ "input": 0.062297,
19105
+ "output": 0.186888,
19106
+ "cachedInput": 1983e-6
19107
19107
  }
19108
19108
  ],
19109
19109
  "maxPrice": {
19110
- "prompt": 0.066,
19111
- "completion": 0.198
19110
+ "prompt": 0.059048,
19111
+ "completion": 0.177144
19112
19112
  },
19113
19113
  "reasoningEfforts": [
19114
19114
  "none",
@@ -19134,14 +19134,14 @@ var CATALOG_MODELS = [
19134
19134
  "tiers": [
19135
19135
  {
19136
19136
  "maxPromptTokens": 262144,
19137
- "input": 0.153186,
19138
- "output": 0.612744,
19139
- "cachedInput": 0.038297
19137
+ "input": 0.095742,
19138
+ "output": 0.382965,
19139
+ "cachedInput": 0.023936
19140
19140
  }
19141
19141
  ],
19142
19142
  "maxPrice": {
19143
- "prompt": 0.1452,
19144
- "completion": 0.5808
19143
+ "prompt": 0.09075,
19144
+ "completion": 0.363
19145
19145
  },
19146
19146
  "reasoningEfforts": [
19147
19147
  "none",
@@ -19773,7 +19773,7 @@ var CATALOG_MODELS = [
19773
19773
  "maxOutputTokens": 131072,
19774
19774
  "tiers": [
19775
19775
  {
19776
- "maxPromptTokens": 2e5,
19776
+ "maxPromptTokens": 202752,
19777
19777
  "input": 1.04445,
19778
19778
  "output": 3.36545,
19779
19779
  "cachedInput": 0.189268
@@ -19808,8 +19808,8 @@ var CATALOG_MODELS = [
19808
19808
  }
19809
19809
  ],
19810
19810
  "maxPrice": {
19811
- "prompt": 0.674366,
19812
- "completion": 2.119436
19811
+ "prompt": 0.1936,
19812
+ "completion": 1.6984
19813
19813
  },
19814
19814
  "reasoningEfforts": [
19815
19815
  "none",
@@ -20070,14 +20070,14 @@ var CATALOG_MODELS = [
20070
20070
  "tiers": [
20071
20071
  {
20072
20072
  "maxPromptTokens": 1048576,
20073
- "input": 1.57828,
20074
- "output": 4.85089,
20075
- "cachedInput": 0.16247
20073
+ "input": 0.81235,
20074
+ "output": 2.43705,
20075
+ "cachedInput": 0.081235
20076
20076
  }
20077
20077
  ],
20078
20078
  "maxPrice": {
20079
- "prompt": 1.496,
20080
- "completion": 4.598
20079
+ "prompt": 0.77,
20080
+ "completion": 2.31
20081
20081
  },
20082
20082
  "reasoningEfforts": [
20083
20083
  "none",
@@ -20100,7 +20100,7 @@ var CATALOG_MODELS = [
20100
20100
  "maxOutputTokens": 235929,
20101
20101
  "tiers": [
20102
20102
  {
20103
- "maxPromptTokens": 262144,
20103
+ "maxPromptTokens": 1e6,
20104
20104
  "input": 0.087038,
20105
20105
  "output": 0.261113,
20106
20106
  "cachedInput": 0.017408
@@ -20502,14 +20502,14 @@ var CATALOG_MODELS = [
20502
20502
  "tiers": [
20503
20503
  {
20504
20504
  "maxPromptTokens": 1048576,
20505
- "input": 0.449114,
20506
- "output": 0.908672,
20507
- "cachedInput": 3761e-6
20505
+ "input": 0.429096,
20506
+ "output": 0.858191,
20507
+ "cachedInput": 3946e-6
20508
20508
  }
20509
20509
  ],
20510
20510
  "maxPrice": {
20511
- "prompt": 0.4257,
20512
- "completion": 0.8613
20511
+ "prompt": 0.406725,
20512
+ "completion": 0.81345
20513
20513
  },
20514
20514
  "reasoningEfforts": [],
20515
20515
  "quantizations": [
@@ -21365,6 +21365,42 @@ var CATALOG_MODELS = [
21365
21365
  "xhigh",
21366
21366
  "max"
21367
21367
  ]
21368
+ },
21369
+ {
21370
+ "id": "particle-ai/particle-1",
21371
+ "openRouterId": "particle-ai/particle-1",
21372
+ "label": "Particle-1",
21373
+ "maker": "Particle AI",
21374
+ "contextLength": 1048576,
21375
+ "maxOutputTokens": 131072,
21376
+ "tiers": [
21377
+ {
21378
+ "maxPromptTokens": 1048576,
21379
+ "input": 0.290125,
21380
+ "output": 1.1605,
21381
+ "cachedInput": 0.034815
21382
+ }
21383
+ ],
21384
+ "maxPrice": {
21385
+ "prompt": 0.275,
21386
+ "completion": 1.1
21387
+ },
21388
+ "reasoningEfforts": [
21389
+ "none",
21390
+ "minimal",
21391
+ "low",
21392
+ "medium",
21393
+ "high",
21394
+ "xhigh",
21395
+ "max"
21396
+ ],
21397
+ "quantizations": [
21398
+ "fp8",
21399
+ "fp16",
21400
+ "bf16",
21401
+ "fp32",
21402
+ "unknown"
21403
+ ]
21368
21404
  }
21369
21405
  ];
21370
21406
 
@@ -22437,7 +22473,7 @@ var ACP_AGENTS = {
22437
22473
  "registryId": "goose",
22438
22474
  "label": "goose",
22439
22475
  "description": "A local, extensible, open source AI agent that automates engineering tasks",
22440
- "version": "1.54.0",
22476
+ "version": "1.57.0",
22441
22477
  "website": "https://block.github.io/goose/"
22442
22478
  },
22443
22479
  "grok_build": {
@@ -22479,7 +22515,7 @@ var ACP_AGENTS = {
22479
22515
  "registryId": "minimax-code",
22480
22516
  "label": "MiniMax Code",
22481
22517
  "description": "MiniMax Code is an AI coding agent with Agent Client Protocol support.",
22482
- "version": "0.7.0",
22518
+ "version": "0.7.1",
22483
22519
  "website": "https://agent.minimax.io"
22484
22520
  },
22485
22521
  "minion_code": {
@@ -22556,7 +22592,7 @@ var ACP_AGENTS = {
22556
22592
  "registryId": "docker-cagent",
22557
22593
  "label": "Docker Agent",
22558
22594
  "description": "Docker's agent runtime configured through an agent YAML file.",
22559
- "version": "1.152.0",
22595
+ "version": "1.154.0",
22560
22596
  "website": "https://docs.docker.com/ai/docker-agent/features/acp/"
22561
22597
  },
22562
22598
  "kiro": {
@@ -22636,7 +22672,7 @@ var GEMINI = ["gemini-4-argon", "gemini-3.8-flash", "gemini-3.5-flash-lite"];
22636
22672
  var CLAUDE_5_5 = ["claude-sonnet-5-5", "claude-haiku-5-5"];
22637
22673
  var KIMI_K3_1 = ["kimi-k3.1-pro"];
22638
22674
  var HARNESS_MODEL_ADDITIONS = {
22639
- claude_code: [{ models: CLAUDE_5_5, releases: ["2.1.295", "2.1.296", "2.1.303", "2.1.310", "2.1.311"] }, {
22675
+ claude_code: [{ models: CLAUDE_5_5, releases: ["2.1.295", "2.1.296", "2.1.303", "2.1.310", "2.1.311", "2.1.312"] }, {
22640
22676
  models: [
22641
22677
  "gpt-6.1-sol",
22642
22678
  "gpt-6-sol",
@@ -22659,7 +22695,7 @@ var HARNESS_MODEL_ADDITIONS = {
22659
22695
  ...MINIMAX,
22660
22696
  ...CATALOG_IDS
22661
22697
  ],
22662
- releases: ["2.1.303", "2.1.310", "2.1.311"]
22698
+ releases: ["2.1.303", "2.1.310", "2.1.311", "2.1.312"]
22663
22699
  }],
22664
22700
  codex: [{ models: KIMI_K3_1, releases: ["0.163.0"] }, { models: [...CLAUDE_5_5, ...GEMINI, "grok-4.7", ...MUSE, ...MINIMAX, ...CATALOG_IDS], releases: ["0.163.0"] }],
22665
22701
  hermes: [
@@ -22672,23 +22708,23 @@ var HARNESS_MODEL_ADDITIONS = {
22672
22708
  pi: [{ models: KIMI_K3_1, releases: ["1.3.0"] }, { models: [...CLAUDE_5_5, "grok-4.7", ...MINIMAX], releases: ["1.3.0"] }],
22673
22709
  kimi_code: [{ models: KIMI_K3_1, releases: ["2.2.0"] }, { models: [...CLAUDE_5_5, ...GEMINI, "grok-4.7", ...MUSE, ...MINIMAX, ...CATALOG_IDS], releases: ["2.2.0"] }],
22674
22710
  opencode: [
22675
- { models: KIMI_K3_1, releases: ["1.19.4"] },
22676
- { models: ["grok-4.7"], releases: ["1.18.35", "1.19.3", "1.19.4"] },
22677
- { models: CLAUDE_5_5, releases: ["1.18.35", "1.19.3", "1.19.4"] },
22678
- { models: [...GEMINI, ...MINIMAX], releases: ["1.19.3", "1.19.4"] }
22711
+ { models: KIMI_K3_1, releases: ["1.19.4", "1.19.5"] },
22712
+ { models: ["grok-4.7"], releases: ["1.18.35", "1.19.3", "1.19.4", "1.19.5"] },
22713
+ { models: CLAUDE_5_5, releases: ["1.18.35", "1.19.3", "1.19.4", "1.19.5"] },
22714
+ { models: [...GEMINI, ...MINIMAX], releases: ["1.19.3", "1.19.4", "1.19.5"] }
22679
22715
  ],
22680
22716
  fast_agent: [{ models: KIMI_K3_1, releases: ["0.10.46"] }, { models: ["grok-4.7"], releases: ["0.10.43", "0.10.46"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["0.10.43", "0.10.46"] }],
22681
- goose: [{ models: KIMI_K3_1, releases: ["1.54.0"] }, { models: ["grok-4.7"], releases: ["1.54.0"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["1.54.0"] }],
22717
+ goose: [{ models: KIMI_K3_1, releases: ["1.54.0", "1.57.0"] }, { models: ["grok-4.7"], releases: ["1.54.0", "1.57.0"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["1.54.0", "1.57.0"] }],
22682
22718
  kilo: [{ models: KIMI_K3_1, releases: ["7.8.17", "7.8.18"] }, { models: ["grok-4.7"], releases: ["7.8.8", "7.8.12", "7.8.15", "7.8.17", "7.8.18"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["7.8.8", "7.8.12", "7.8.15", "7.8.17", "7.8.18"] }],
22683
- docker_cagent: [{ models: KIMI_K3_1, releases: ["1.152.0"] }, { models: ["grok-4.7"], releases: ["1.150.0", "1.151.0", "1.152.0"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["1.150.0", "1.151.0", "1.152.0"] }],
22719
+ docker_cagent: [{ models: KIMI_K3_1, releases: ["1.152.0", "1.153.0", "1.154.0"] }, { models: ["grok-4.7"], releases: ["1.150.0", "1.151.0", "1.152.0", "1.153.0", "1.154.0"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["1.150.0", "1.151.0", "1.152.0", "1.153.0", "1.154.0"] }],
22684
22720
  cline: [{ models: KIMI_K3_1, releases: ["3.0.73", "3.0.74"] }, { models: ["grok-4.7"], releases: ["3.0.70", "3.0.73", "3.0.74"] }],
22685
22721
  grok_build: [{ models: KIMI_K3_1, releases: ["1.0.70"] }, { models: ["grok-4.7"], releases: ["1.0.50", "1.0.62", "1.0.67", "1.0.70"] }],
22686
22722
  mistral_vibe: [{ models: ["grok-4.7"], releases: ["2.26.1"] }],
22687
22723
  sigit: [{ models: KIMI_K3_1, releases: ["1.7.4", "1.7.5"] }, { models: ["grok-4.7"], releases: ["1.6.5", "1.7.2", "1.7.3", "1.7.4", "1.7.5"] }],
22688
22724
  cursor: [{ models: ["kimi-k2.7-code"], releases: ["2026.10.01"] }],
22689
- minimax_code: [{ models: KIMI_K3_1, releases: ["0.6.12", "0.7.0"] }, { models: ["grok-4.7"], releases: ["0.6.5", "0.6.12", "0.7.0"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["0.6.5", "0.6.12", "0.7.0"] }, {
22725
+ minimax_code: [{ models: KIMI_K3_1, releases: ["0.6.12", "0.7.0", "0.7.1"] }, { models: ["grok-4.7"], releases: ["0.6.5", "0.6.12", "0.7.0", "0.7.1"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["0.6.5", "0.6.12", "0.7.0", "0.7.1"] }, {
22690
22726
  models: ["gpt-6.1-sol", "gpt-6-sol", "gpt-6-luna", "gpt-5.6-sol", "claude-opus-5", "claude-opus-5-5"],
22691
- releases: ["0.6.2", "0.6.3", "0.6.4", "0.6.5", "0.6.12", "0.7.0"]
22727
+ releases: ["0.6.2", "0.6.3", "0.6.4", "0.6.5", "0.6.12", "0.7.0", "0.7.1"]
22692
22728
  }],
22693
22729
  dsh: [{ models: KIMI_K3_1, releases: ["0.1.5rc1"] }, {
22694
22730
  models: [
@@ -38,7 +38,7 @@ function currentUniverse() {
38
38
  }
39
39
 
40
40
  // src/version.ts
41
- var CLI_VERSION = "2.29.0";
41
+ var CLI_VERSION = "2.30.0";
42
42
  var USER_AGENT = `sky-cli/${CLI_VERSION} (${process.platform}; node/${process.versions.node})`;
43
43
 
44
44
  export {
@@ -3,7 +3,7 @@ import {
3
3
  apiBase,
4
4
  apiToken,
5
5
  currentUniverse
6
- } from "./chunk-QZLKHGX6.js";
6
+ } from "./chunk-KNGZR3CX.js";
7
7
 
8
8
  // src/api.ts
9
9
  import { createWriteStream, writeFileSync } from "fs";
@@ -149,7 +149,7 @@ async function resolveSessionRef(ref) {
149
149
  return agent.defaultSessionId;
150
150
  }
151
151
  async function* streamEvents(sessionId, signal) {
152
- const { parseSseStream } = await import("./src-XQQXF3IG.js");
152
+ const { parseSseStream } = await import("./src-FUNAJY2H.js");
153
153
  const res = await fetch(
154
154
  `${apiBase()}/sessions/${encodeURIComponent(sessionId)}/stream`,
155
155
  {
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  streamEvents,
12
12
  uploadFile,
13
13
  writeResponseFile
14
- } from "./chunk-GEL5GWF2.js";
14
+ } from "./chunk-TIFRDEFP.js";
15
15
  import {
16
16
  CLI_VERSION,
17
17
  USER_AGENT,
@@ -22,7 +22,7 @@ import {
22
22
  currentUniverse,
23
23
  loadConfig,
24
24
  saveConfig
25
- } from "./chunk-QZLKHGX6.js";
25
+ } from "./chunk-KNGZR3CX.js";
26
26
  import {
27
27
  AGENT_TYPES,
28
28
  MODEL_SUBSCRIPTION_PLAN_PHRASE,
@@ -44,11 +44,11 @@ import {
44
44
  skillRefSchema,
45
45
  splitMcpServers,
46
46
  supersededBy
47
- } from "./chunk-ISORBGQX.js";
47
+ } from "./chunk-JOLDBZV3.js";
48
48
  import "./chunk-MLKGABMK.js";
49
49
 
50
50
  // src/index.ts
51
- import { existsSync as existsSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync10 } from "fs";
51
+ import { existsSync as existsSync14, readFileSync as readFileSync21, writeFileSync as writeFileSync11 } from "fs";
52
52
  import { basename as basename9, resolve as resolve9 } from "path";
53
53
  import { createInterface as createInterface6 } from "readline";
54
54
  import { Command } from "commander";
@@ -3440,8 +3440,10 @@ async function triggerRequest(id, resource, change) {
3440
3440
  // src/session-workspace.ts
3441
3441
  import { spawnSync as spawnSync4 } from "child_process";
3442
3442
  import { createHash as createHash5, randomUUID } from "crypto";
3443
- import { readdirSync as readdirSync5, statSync as statSync6 } from "fs";
3444
- import { basename as basename7, join as join12, relative as relative3, resolve as resolve5 } from "path";
3443
+ import { existsSync as existsSync10, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as readFileSync12, renameSync, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
3444
+ import { homedir as homedir8, hostname as hostname2, tmpdir as tmpdir2 } from "os";
3445
+ import { basename as basename7, dirname as dirname6, join as join12, relative as relative3, resolve as resolve5 } from "path";
3446
+ import { inflateRawSync } from "zlib";
3445
3447
  var SINGLE_IMPORT_MAX = 25 * 1024 * 1024;
3446
3448
  var PART_SIZE = 8 * 1024 * 1024;
3447
3449
  var SKIPPED2 = /* @__PURE__ */ new Set([".git", "node_modules"]);
@@ -3561,6 +3563,97 @@ async function handoff(id, targetAgent, opts = {}) {
3561
3563
  }
3562
3564
  return h;
3563
3565
  }
3566
+ function zipEntries(archive) {
3567
+ let end = archive.length - 22;
3568
+ while (end >= 0 && archive.readUInt32LE(end) !== 101010256) end -= 1;
3569
+ if (end < 0) throw new ApiError(422, "checkpoint_invalid", "the downloaded conversation is not a readable archive");
3570
+ const entries = /* @__PURE__ */ new Map();
3571
+ let at = archive.readUInt32LE(end + 16);
3572
+ for (let index = archive.readUInt16LE(end + 10); index > 0; index -= 1) {
3573
+ const method = archive.readUInt16LE(at + 10);
3574
+ const size = archive.readUInt32LE(at + 20);
3575
+ const nameLength = archive.readUInt16LE(at + 28);
3576
+ const local = archive.readUInt32LE(at + 42);
3577
+ const start = local + 30 + archive.readUInt16LE(local + 26) + archive.readUInt16LE(local + 28);
3578
+ const packed = archive.subarray(start, start + size);
3579
+ if (method !== 0 && method !== 8) throw new ApiError(422, "checkpoint_invalid", "the downloaded conversation uses an unsupported compression");
3580
+ entries.set(archive.subarray(at + 46, at + 46 + nameLength).toString("utf8"), method === 8 ? inflateRawSync(packed) : Buffer.from(packed));
3581
+ at += 46 + nameLength + archive.readUInt16LE(at + 30) + archive.readUInt16LE(at + 32);
3582
+ }
3583
+ return entries;
3584
+ }
3585
+ function conversationFiles(archive, harness2) {
3586
+ const entries = zipEntries(archive);
3587
+ const manifest = JSON.parse(entries.get("manifest.json")?.toString("utf8") ?? "null");
3588
+ const nativeId = manifest?.metadata?.native_session_id ?? "";
3589
+ if (manifest?.format !== "asteroids.native-checkpoint" || manifest.source_harness !== harness2 || !Array.isArray(manifest.files) || !/^[A-Za-z0-9_-]{1,200}$/.test(nativeId)) {
3590
+ throw new ApiError(422, "checkpoint_invalid", "the downloaded conversation is not one this computer can continue");
3591
+ }
3592
+ const ours = (path) => {
3593
+ const parts = path.split("/");
3594
+ if (parts.some((part) => !part || part === "." || part === "..")) return false;
3595
+ if (harness2 === "claude_code") return parts[0] === "projects" && parts.length >= 3 && (parts[2] === `${nativeId}.jsonl` || parts[2] === nativeId);
3596
+ return parts[0] === "sessions" && parts.at(-1).startsWith("rollout-") && parts.at(-1).endsWith(`${nativeId}.jsonl`);
3597
+ };
3598
+ const files2 = manifest.files.filter((file) => ours(file.path)).map((file) => {
3599
+ const data = entries.get(`files/${file.path}`);
3600
+ if (!data || data.length !== file.size || createHash5("sha256").update(data).digest("hex") !== file.sha256) {
3601
+ throw new ApiError(422, "checkpoint_invalid", "the downloaded conversation is incomplete; try again");
3602
+ }
3603
+ return { path: file.path, data };
3604
+ });
3605
+ if (!files2.length) throw new ApiError(422, "checkpoint_invalid", "the downloaded conversation has no transcript");
3606
+ return { nativeId, files: files2 };
3607
+ }
3608
+ async function verifiedDownload(path) {
3609
+ const res = await apiRaw("GET", path);
3610
+ if (!res.ok) {
3611
+ const body = await res.json().catch(() => null);
3612
+ throw new ApiError(res.status, body?.error?.code ?? "request_failed", body?.error?.message ?? `AgentSky answered ${res.status}`);
3613
+ }
3614
+ const bytes = Buffer.from(await res.arrayBuffer());
3615
+ const expected = res.headers.get("x-content-sha256");
3616
+ if (expected && createHash5("sha256").update(bytes).digest("hex") !== expected) throw new ApiError(502, "download_corrupt", "the download was damaged; try again");
3617
+ return bytes;
3618
+ }
3619
+ async function continueHere(id, dir, opts = {}) {
3620
+ const session2 = (await api("GET", `/sessions/${encodeURIComponent(id)}`)).session;
3621
+ const harness2 = session2.agentType;
3622
+ if (harness2 !== "claude_code" && harness2 !== "codex") throw new ApiError(409, "harness_unsupported", "only Claude Code and Codex sessions can continue on a computer");
3623
+ let { handoff: h } = await api("POST", `/sessions/${encodeURIComponent(id)}/local-handoff`, { machine: hostname2().slice(0, 120) }, { idempotencyKey: opts.idempotencyKey ?? randomUUID() });
3624
+ opts.onStatus?.(h);
3625
+ while (!TERMINAL.has(h.status)) {
3626
+ await new Promise((r) => setTimeout(r, opts.pollMs ?? 2e3));
3627
+ const next = (await api("GET", `/session-handoffs/${encodeURIComponent(h.id)}`)).handoff;
3628
+ if (next.status !== h.status) opts.onStatus?.(next);
3629
+ h = next;
3630
+ }
3631
+ if (h.status !== "completed") throw new ApiError(422, h.error?.code ?? "handoff_failed", h.error?.message ?? "the session could not be moved; it stays in the cloud");
3632
+ const { nativeId, files: files2 } = conversationFiles(await verifiedDownload(`/session-handoffs/${encodeURIComponent(h.id)}/checkpoint`), harness2);
3633
+ const root = harness2 === "codex" ? process.env.CODEX_HOME || join12(homedir8(), ".codex") : process.env.CLAUDE_CONFIG_DIR || join12(homedir8(), ".claude");
3634
+ const stamp = Date.now();
3635
+ for (const file of files2) {
3636
+ const target = join12(root, file.path);
3637
+ mkdirSync4(dirname6(target), { recursive: true });
3638
+ if (existsSync10(target)) {
3639
+ if (!lstatSync2(target).isFile()) throw new ApiError(409, "restore_blocked", `something other than a file is in the way at ${target}`);
3640
+ if (readFileSync12(target).equals(file.data)) continue;
3641
+ renameSync(target, `${target}.before-agentsky-${stamp}`);
3642
+ }
3643
+ writeFileSync7(target, file.data, { mode: 384 });
3644
+ }
3645
+ const folder = resolve5(dir);
3646
+ mkdirSync4(folder, { recursive: true });
3647
+ const carried = h.workspace_carried === true;
3648
+ if (carried) {
3649
+ const archive = join12(tmpdir2(), `agentsky-workspace-${h.id}.tar.gz`);
3650
+ writeFileSync7(archive, await verifiedDownload(`/session-handoffs/${encodeURIComponent(h.id)}/workspace`), { mode: 384 });
3651
+ const tar = spawnSync4("tar", ["-xzf", archive, "-C", folder]);
3652
+ if (tar.status !== 0) throw new ApiError(422, "workspace_unpack_failed", `tar failed: ${tar.stderr.toString().trim()}`);
3653
+ }
3654
+ const resume = harness2 === "codex" ? `cd ${JSON.stringify(folder)} && codex resume ${nativeId}` : `cd ${JSON.stringify(folder)} && claude --resume ${nativeId}`;
3655
+ return { harness: harness2, nativeId, folder, workspaceCarried: carried, resume };
3656
+ }
3564
3657
 
3565
3658
  // src/render.ts
3566
3659
  var dim = (s) => `\x1B[2m${s}\x1B[0m`;
@@ -3682,15 +3775,15 @@ async function readTurn(sessionId, opts = {}) {
3682
3775
  }
3683
3776
 
3684
3777
  // src/setup.ts
3685
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
3686
- import { dirname as dirname7, join as join15 } from "path";
3778
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
3779
+ import { dirname as dirname8, join as join15 } from "path";
3687
3780
  import { createInterface as createInterface3 } from "readline";
3688
3781
 
3689
3782
  // src/setup-local.ts
3690
3783
  import { isUtf8 as isUtf83 } from "buffer";
3691
- import { existsSync as existsSync10, readdirSync as readdirSync6, readFileSync as readFileSync12, statSync as statSync7 } from "fs";
3692
- import { homedir as homedir8 } from "os";
3693
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join13, resolve as resolve6 } from "path";
3784
+ import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync13, statSync as statSync7 } from "fs";
3785
+ import { homedir as homedir9 } from "os";
3786
+ import { dirname as dirname7, isAbsolute as isAbsolute2, join as join13, resolve as resolve6 } from "path";
3694
3787
  import { parse as parseToml4 } from "smol-toml";
3695
3788
  var MAX_SKILL_FILE_BYTES = 1024 * 1024;
3696
3789
  var MAX_IMPORT_DEPTH = 5;
@@ -3719,7 +3812,7 @@ function skillFiles2(root, prefix) {
3719
3812
  if (entry2.isDirectory()) {
3720
3813
  if (!SKIPPED_DIRS.has(entry2.name)) files2.push(...skillFiles2(path, `${prefix}/${entry2.name}`));
3721
3814
  } else if (entry2.isFile() && !sensitive(entry2.name) && statSync7(path).size <= MAX_SKILL_FILE_BYTES) {
3722
- const bytes = redacted(readFileSync12(path));
3815
+ const bytes = redacted(readFileSync13(path));
3723
3816
  if (bytes) files2.push({ path: `${prefix}/${entry2.name}`, bytes });
3724
3817
  }
3725
3818
  }
@@ -3729,7 +3822,7 @@ function readLocalSkills(agents) {
3729
3822
  const skills2 = [];
3730
3823
  const ignored = [];
3731
3824
  for (const agent2 of agents) {
3732
- if (!existsSync10(agent2.skillsDir)) continue;
3825
+ if (!existsSync11(agent2.skillsDir)) continue;
3733
3826
  for (const entry2 of readdirSync6(agent2.skillsDir, { withFileTypes: true })) {
3734
3827
  const dir = join13(agent2.skillsDir, entry2.name);
3735
3828
  let isDir2 = entry2.isDirectory();
@@ -3740,8 +3833,8 @@ function readLocalSkills(agents) {
3740
3833
  isDir2 = false;
3741
3834
  }
3742
3835
  }
3743
- if (!isDir2 || !existsSync10(join13(dir, "SKILL.md")) || isInstalledSkill(dir)) continue;
3744
- const name = frontmatterName(readFileSync12(join13(dir, "SKILL.md"), "utf8"));
3836
+ if (!isDir2 || !existsSync11(join13(dir, "SKILL.md")) || isInstalledSkill(dir)) continue;
3837
+ const name = frontmatterName(readFileSync13(join13(dir, "SKILL.md"), "utf8"));
3745
3838
  if (!name) {
3746
3839
  ignored.push({ agent: agent2.id, dir, reason: "SKILL.md has no name" });
3747
3840
  continue;
@@ -3769,11 +3862,11 @@ function inlineImports(content, from, home, depth, seen) {
3769
3862
  }
3770
3863
  const target = fence ? void 0 : line.match(/^@(\S+\.(?:md|markdown|txt))$/i)?.[1];
3771
3864
  if (!target || depth >= MAX_IMPORT_DEPTH) return line;
3772
- const path = target.startsWith("~/") ? join13(home, target.slice(2)) : isAbsolute2(target) ? target : resolve6(dirname6(from), target);
3865
+ const path = target.startsWith("~/") ? join13(home, target.slice(2)) : isAbsolute2(target) ? target : resolve6(dirname7(from), target);
3773
3866
  if (seen.includes(path)) return "";
3774
3867
  let imported;
3775
3868
  try {
3776
- imported = readFileSync12(path, "utf8");
3869
+ imported = readFileSync13(path, "utf8");
3777
3870
  } catch {
3778
3871
  return line;
3779
3872
  }
@@ -3781,7 +3874,7 @@ function inlineImports(content, from, home, depth, seen) {
3781
3874
  return inlineImports(imported, path, home, depth + 1, seen).trim();
3782
3875
  }).join("\n");
3783
3876
  }
3784
- function readGlobalInstructions(agents, home = homedir8()) {
3877
+ function readGlobalInstructions(agents, home = homedir9()) {
3785
3878
  const found = [];
3786
3879
  for (const agent2 of agents) {
3787
3880
  const file = INSTRUCTION_FILES2[agent2.id];
@@ -3789,7 +3882,7 @@ function readGlobalInstructions(agents, home = homedir8()) {
3789
3882
  const path = join13(agent2.root, file);
3790
3883
  let raw;
3791
3884
  try {
3792
- raw = readFileSync12(path, "utf8");
3885
+ raw = readFileSync13(path, "utf8");
3793
3886
  } catch {
3794
3887
  continue;
3795
3888
  }
@@ -3808,7 +3901,7 @@ ${item.content.trim()}`).join("\n\n");
3808
3901
  }
3809
3902
  function readJson3(path) {
3810
3903
  try {
3811
- return JSON.parse(readFileSync12(path, "utf8"));
3904
+ return JSON.parse(readFileSync13(path, "utf8"));
3812
3905
  } catch {
3813
3906
  return void 0;
3814
3907
  }
@@ -3825,12 +3918,12 @@ function serversOf(agent2, home) {
3825
3918
  if (agent2.id === "claude_code") return readJson3(join13(home, ".claude.json"))?.mcpServers ?? {};
3826
3919
  if (agent2.id === "cursor") return readJson3(join13(agent2.root, "mcp.json"))?.mcpServers ?? {};
3827
3920
  try {
3828
- return parseToml4(readFileSync12(join13(agent2.root, "config.toml"), "utf8")).mcp_servers ?? {};
3921
+ return parseToml4(readFileSync13(join13(agent2.root, "config.toml"), "utf8")).mcp_servers ?? {};
3829
3922
  } catch {
3830
3923
  return {};
3831
3924
  }
3832
3925
  }
3833
- function findLocalSecrets(agents, home = homedir8()) {
3926
+ function findLocalSecrets(agents, home = homedir9()) {
3834
3927
  const secrets2 = [];
3835
3928
  for (const agent2 of agents) {
3836
3929
  for (const [name, def] of Object.entries(serversOf(agent2, home))) {
@@ -3847,8 +3940,8 @@ function findLocalSecrets(agents, home = homedir8()) {
3847
3940
 
3848
3941
  // src/subscriptions.ts
3849
3942
  import { spawn as spawn3 } from "child_process";
3850
- import { existsSync as existsSync11, readFileSync as readFileSync13 } from "fs";
3851
- import { homedir as homedir9 } from "os";
3943
+ import { existsSync as existsSync12, readFileSync as readFileSync14 } from "fs";
3944
+ import { homedir as homedir10 } from "os";
3852
3945
  import { join as join14 } from "path";
3853
3946
  import { createInterface as createInterface2 } from "readline";
3854
3947
  var ALIASES = {
@@ -3944,12 +4037,12 @@ async function connectClaude() {
3944
4037
  const expiry = sub.expiresAt ? ` (expires ~${sub.expiresAt.slice(0, 10)})` : "";
3945
4038
  console.log(`Connected Claude subscription${expiry}. Powers new eligible agents.`);
3946
4039
  }
3947
- function codexSignIn(env = process.env, home = homedir9()) {
4040
+ function codexSignIn(env = process.env, home = homedir10()) {
3948
4041
  const path = join14(env.CODEX_HOME || join14(home, ".codex"), "auth.json");
3949
- if (!existsSync11(path)) {
4042
+ if (!existsSync12(path)) {
3950
4043
  throw new ApiError(404, "no_codex_auth", `no ${path} \u2014 run \`codex login\` first`);
3951
4044
  }
3952
- const raw = readFileSync13(path, "utf8");
4045
+ const raw = readFileSync14(path, "utf8");
3953
4046
  try {
3954
4047
  const parsed = JSON.parse(raw);
3955
4048
  return { path, raw, account: parsed.tokens?.account_id };
@@ -3957,12 +4050,12 @@ function codexSignIn(env = process.env, home = homedir9()) {
3957
4050
  throw new ApiError(400, "invalid_codex_auth", `${path} isn't valid JSON \u2014 re-run \`codex login\``);
3958
4051
  }
3959
4052
  }
3960
- function cursorSignIn(env = process.env, home = homedir9()) {
4053
+ function cursorSignIn(env = process.env, home = homedir10()) {
3961
4054
  const path = join14(env.XDG_CONFIG_HOME || join14(home, ".config"), "cursor", "auth.json");
3962
- if (!existsSync11(path)) {
4055
+ if (!existsSync12(path)) {
3963
4056
  throw new ApiError(404, "no_cursor_auth", `no ${path} \u2014 run \`cursor-agent login\` first`);
3964
4057
  }
3965
- const raw = readFileSync13(path, "utf8");
4058
+ const raw = readFileSync14(path, "utf8");
3966
4059
  try {
3967
4060
  const parsed = JSON.parse(raw);
3968
4061
  if (typeof parsed.accessToken !== "string" || typeof parsed.refreshToken !== "string") throw new Error("shape");
@@ -4123,11 +4216,11 @@ function planProviders(names2) {
4123
4216
  }));
4124
4217
  }
4125
4218
  function reportPath() {
4126
- return join15(dirname7(configPath()), "setup.json");
4219
+ return join15(dirname8(configPath()), "setup.json");
4127
4220
  }
4128
4221
  function loadReport() {
4129
4222
  try {
4130
- const saved = JSON.parse(readFileSync14(reportPath(), "utf8"));
4223
+ const saved = JSON.parse(readFileSync15(reportPath(), "utf8"));
4131
4224
  return { agents: saved.agents ?? [], plans: saved.plans ?? [], ...saved.secrets ? { secrets: saved.secrets } : {} };
4132
4225
  } catch {
4133
4226
  return { agents: [], plans: [] };
@@ -4140,8 +4233,8 @@ function mergeReport(base, next) {
4140
4233
  return { agents, plans, ...secrets2 ? { secrets: secrets2 } : {} };
4141
4234
  }
4142
4235
  function saveReport(report) {
4143
- mkdirSync4(dirname7(reportPath()), { recursive: true });
4144
- writeFileSync7(reportPath(), `${JSON.stringify(report, null, 2)}
4236
+ mkdirSync5(dirname8(reportPath()), { recursive: true });
4237
+ writeFileSync8(reportPath(), `${JSON.stringify(report, null, 2)}
4145
4238
  `, { mode: 384 });
4146
4239
  }
4147
4240
  function confirm3(question) {
@@ -4512,7 +4605,7 @@ function renderArtifact(artifact2) {
4512
4605
  }
4513
4606
 
4514
4607
  // src/skills-store.ts
4515
- import { readdirSync as readdirSync7, readFileSync as readFileSync15, statSync as statSync8 } from "fs";
4608
+ import { readdirSync as readdirSync7, readFileSync as readFileSync16, statSync as statSync8 } from "fs";
4516
4609
  import { basename as basename8, join as join16, relative as relative4, resolve as resolve7 } from "path";
4517
4610
  function skillBundle(dir) {
4518
4611
  const root = resolve7(dir);
@@ -4522,7 +4615,7 @@ function skillBundle(dir) {
4522
4615
  for (const name of readdirSync7(path).sort()) {
4523
4616
  const full = join16(path, name);
4524
4617
  if (statSync8(full).isDirectory()) walk(full);
4525
- else files2.push({ path: `${top}/${relative4(root, full)}`, bytes: readFileSync15(full) });
4618
+ else files2.push({ path: `${top}/${relative4(root, full)}`, bytes: readFileSync16(full) });
4526
4619
  }
4527
4620
  };
4528
4621
  walk(root);
@@ -4574,8 +4667,8 @@ async function setAgentSkill(agentId, skillId, verb) {
4574
4667
 
4575
4668
  // src/task-export.ts
4576
4669
  import { createHash as createHash6 } from "crypto";
4577
- import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync8 } from "fs";
4578
- import { dirname as dirname8, join as join17 } from "path";
4670
+ import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "fs";
4671
+ import { dirname as dirname9, join as join17 } from "path";
4579
4672
  import { stringify as stringifyToml } from "smol-toml";
4580
4673
  var TEXT_MAX = 2e4;
4581
4674
  function scrub(text, names2) {
@@ -4866,8 +4959,8 @@ async function exportTaskHarbor(taskRef, outDir, opts) {
4866
4959
  const written2 = [];
4867
4960
  for (const [path, content] of files2) {
4868
4961
  const target = join17(outDir, path);
4869
- mkdirSync5(dirname8(target), { recursive: true });
4870
- writeFileSync8(target, content, typeof content === "string" ? { mode: path.endsWith(".sh") || path.endsWith(".py") ? 493 : 420 } : void 0);
4962
+ mkdirSync6(dirname9(target), { recursive: true });
4963
+ writeFileSync9(target, content, typeof content === "string" ? { mode: path.endsWith(".sh") || path.endsWith(".py") ? 493 : 420 } : void 0);
4871
4964
  written2.push(path);
4872
4965
  }
4873
4966
  return { written: written2, record };
@@ -5359,14 +5452,14 @@ function renderThreadSummary(t) {
5359
5452
  }
5360
5453
 
5361
5454
  // src/library.ts
5362
- import { readFileSync as readFileSync17 } from "fs";
5455
+ import { readFileSync as readFileSync18 } from "fs";
5363
5456
 
5364
5457
  // src/api-command.ts
5365
- import { readFileSync as readFileSync16 } from "fs";
5458
+ import { readFileSync as readFileSync17 } from "fs";
5366
5459
  var API_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
5367
- function readData(data, stdin = () => readFileSync16(0, "utf8")) {
5460
+ function readData(data, stdin = () => readFileSync17(0, "utf8")) {
5368
5461
  if (data === void 0) return void 0;
5369
- const raw = data === "-" ? stdin() : data.startsWith("@") ? readFileSync16(data.slice(1), "utf8") : data;
5462
+ const raw = data === "-" ? stdin() : data.startsWith("@") ? readFileSync17(data.slice(1), "utf8") : data;
5370
5463
  try {
5371
5464
  JSON.parse(raw);
5372
5465
  } catch {
@@ -5572,7 +5665,7 @@ function registerLibraryLinkCommands(library2) {
5572
5665
  });
5573
5666
  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) => {
5574
5667
  if (opts.file !== void 0 === (opts.data !== void 0)) throw new Error("Choose exactly one of --file or --data.");
5575
- const body = opts.file !== void 0 ? { text: new TextDecoder("utf-8", { fatal: true }).decode(readFileSync17(opts.file)) } : JSON.parse(readData(opts.data));
5668
+ const body = opts.file !== void 0 ? { text: new TextDecoder("utf-8", { fatal: true }).decode(readFileSync18(opts.file)) } : JSON.parse(readData(opts.data));
5576
5669
  if (!body || typeof body !== "object" || Array.isArray(body)) throw new Error("--data must be a JSON object with one native save field.");
5577
5670
  if ("revision" in body && body.revision !== opts.revision) throw new Error("--data revision must match --revision.");
5578
5671
  console.log(JSON.stringify(await saveSharedLibraryFile(opts.token, sharedLibrarySaveSchema.parse({ ...body, revision: opts.revision })), null, 2));
@@ -5615,7 +5708,7 @@ function renderTodo(todo) {
5615
5708
  }
5616
5709
 
5617
5710
  // src/design-systems.ts
5618
- import { readdirSync as readdirSync8, readFileSync as readFileSync18, statSync as statSync9 } from "fs";
5711
+ import { readdirSync as readdirSync8, readFileSync as readFileSync19, statSync as statSync9 } from "fs";
5619
5712
  import { join as join18, relative as relative5, sep as sep3 } from "path";
5620
5713
  var TEXT2 = /\.(mdx?|markdown|txt|json|m?js|cjs|jsx|tsx?|css|html?|svg|xml|csv|ya?ml|toml)$/i;
5621
5714
  var MEDIA = {
@@ -5666,7 +5759,7 @@ function fileTableFrom(dir) {
5666
5759
  continue;
5667
5760
  }
5668
5761
  const key = relative5(dir, path).split(sep3).join("/");
5669
- const bytes = readFileSync18(path);
5762
+ const bytes = readFileSync19(path);
5670
5763
  files2[key] = TEXT2.test(name) ? bytes.toString("utf8") : `data:${MEDIA[name.split(".").pop()?.toLowerCase() ?? ""] ?? "application/octet-stream"};base64,${bytes.toString("base64")}`;
5671
5764
  }
5672
5765
  };
@@ -5775,19 +5868,19 @@ function workspaceFlagIsCommands(argv, commandPath) {
5775
5868
  }
5776
5869
 
5777
5870
  // src/harness.ts
5778
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync19, writeFileSync as writeFileSync9 } from "fs";
5779
- import { dirname as dirname9, join as join19, resolve as resolve8 } from "path";
5871
+ import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync20, writeFileSync as writeFileSync10 } from "fs";
5872
+ import { dirname as dirname10, join as join19, resolve as resolve8 } from "path";
5780
5873
  var HARNESS_FILE = "harness.json";
5781
5874
  function harnessFilePath(dir) {
5782
5875
  return join19(resolve8(dir), HARNESS_FILE);
5783
5876
  }
5784
5877
  function readHarnessFile(dir) {
5785
5878
  const path = harnessFilePath(dir);
5786
- if (!existsSync12(path)) {
5879
+ if (!existsSync13(path)) {
5787
5880
  throw new Error(`no ${HARNESS_FILE} found in ${resolve8(dir)} \u2014 run \`sky harness init\` first`);
5788
5881
  }
5789
5882
  try {
5790
- return JSON.parse(readFileSync19(path, "utf8"));
5883
+ return JSON.parse(readFileSync20(path, "utf8"));
5791
5884
  } catch (err) {
5792
5885
  throw new Error(`could not parse ${path}: ${err instanceof Error ? err.message : String(err)}`);
5793
5886
  }
@@ -5814,11 +5907,11 @@ var INIT_COMMENT = `# harness.json \u2014 workspace harness profile skeleton
5814
5907
  `;
5815
5908
  function harnessInit(dir) {
5816
5909
  const path = harnessFilePath(dir);
5817
- if (existsSync12(path)) {
5910
+ if (existsSync13(path)) {
5818
5911
  throw new Error(`${path} already exists \u2014 delete it to re-init`);
5819
5912
  }
5820
- mkdirSync6(dirname9(path), { recursive: true });
5821
- writeFileSync9(path, `${JSON.stringify(INIT_SKELETON, null, 2)}
5913
+ mkdirSync7(dirname10(path), { recursive: true });
5914
+ writeFileSync10(path, `${JSON.stringify(INIT_SKELETON, null, 2)}
5822
5915
  `);
5823
5916
  console.log(`Created ${path}`);
5824
5917
  console.log(INIT_COMMENT);
@@ -6575,6 +6668,14 @@ session.command("handoff <ref> <targetAgent>").description("hand the session's c
6575
6668
  if (done.target_session) console.log(`${done.target_session} (${done.resolved_mode === "native_fork" ? "forked" : "from a written summary"})`);
6576
6669
  })
6577
6670
  );
6671
+ session.command("continue-here <ref>").description("move an idle Claude Code or Codex session you own onto this computer and print how to resume it; the cloud session then takes no more turns").option("--dir <folder>", "where the session's workspace goes", ".").action(
6672
+ run(async (ref, opts) => {
6673
+ const id = await resolveSessionRef(ref);
6674
+ const moved = await continueHere(id, opts.dir, { onStatus: (h) => console.error(`${h.id}: ${h.status}`) });
6675
+ if (!moved.workspaceCarried) console.error("The workspace was not copied with this move; copy what you need with sky session workspace ls and cat.");
6676
+ console.log(moved.resume);
6677
+ })
6678
+ );
6578
6679
  session.command("cloud-copy <ref>").description("what is kept in the cloud for a chat synced from your own computer: its working folder and native session").option("--json", "print the raw answer").action(
6579
6680
  run(async (ref, opts) => {
6580
6681
  const id = await resolveSessionRef(ref);
@@ -6608,7 +6709,7 @@ sessionWorkspace.command("cat <ref> <path>").description("print a file (up to 1
6608
6709
  run(async (ref, path, opts) => {
6609
6710
  const bytes = await readFile(await resolveSessionRef(ref), path);
6610
6711
  if (opts.out) {
6611
- writeFileSync10(opts.out, bytes);
6712
+ writeFileSync11(opts.out, bytes);
6612
6713
  console.error(`saved ${bytes.length} bytes to ${opts.out}`);
6613
6714
  } else process.stdout.write(bytes);
6614
6715
  })
@@ -6625,7 +6726,7 @@ sessionWorkspace.command("patch <ref> [repo]").description("the work in a reposi
6625
6726
  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)})`);
6626
6727
  if (!patch.length) console.error("nothing changed");
6627
6728
  else if (opts.out) {
6628
- writeFileSync10(opts.out, patch);
6729
+ writeFileSync11(opts.out, patch);
6629
6730
  console.error(`wrote ${opts.out} \u2014 apply with: git apply ${opts.out}`);
6630
6731
  } else process.stdout.write(patch);
6631
6732
  })
@@ -6859,7 +6960,7 @@ async function launchFromFile(path, spec, opts) {
6859
6960
  program.command("launch").description("scaffold ./agent.toml if absent, create the agent and its first session (idle until the first message), print its address").option("-f, --file <path>", "agent file", "agent.toml").option("--type <type>", "override the file's harness: hermes | claude_code | codex | openclaw | pi | dsh | kimi_code | opencode").option("--llm <llm>", "override the file's model (must suit the harness)").option("--start", "boot the first session now instead of on the first message").action(
6860
6961
  run(async (opts) => {
6861
6962
  const path = resolve9(opts.file);
6862
- if (!existsSync13(path)) {
6963
+ if (!existsSync14(path)) {
6863
6964
  const name = basename9(process.cwd()).replace(/[^a-zA-Z0-9 _-]/g, "") || "my-agent";
6864
6965
  scaffoldAgentFile(path, name);
6865
6966
  console.log(`Scaffolded ${opts.file} \u2014 edit it anytime; re-apply with \`sky deploy\`.`);
@@ -7130,14 +7231,14 @@ task.command("get <task> <path>").description("read one task file; prints it, or
7130
7231
  run(async (taskId, path, opts) => {
7131
7232
  const bytes = await readTaskFile(taskId, path);
7132
7233
  if (opts.out) {
7133
- writeFileSync10(opts.out, bytes);
7234
+ writeFileSync11(opts.out, bytes);
7134
7235
  console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
7135
7236
  } else process.stdout.write(bytes);
7136
7237
  })
7137
7238
  );
7138
7239
  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(
7139
7240
  run(async (taskId, path, local) => {
7140
- const { file, conflict } = await writeTaskFile(taskId, path, readFileSync20(local), mediaTypeFor(local));
7241
+ const { file, conflict } = await writeTaskFile(taskId, path, readFileSync21(local), mediaTypeFor(local));
7141
7242
  console.log(`${renderTaskFile(file)}${conflict ? " (replaced a version you had not seen)" : ""}`);
7142
7243
  })
7143
7244
  );
@@ -7375,7 +7476,7 @@ library.command("list").description("your Library, newest first").option("--sear
7375
7476
  );
7376
7477
  library.command("upload <path>").description("save a file from this computer to your Library").option("--workspace <key>", "place it in this workspace").action(
7377
7478
  run(async (path, opts) => {
7378
- const bytes = readFileSync20(path);
7479
+ const bytes = readFileSync21(path);
7379
7480
  const { artifact: artifact2 } = await uploadToLibrary({ bytes, name: basename9(path), mediaType: "application/octet-stream" }, `sky-upload-${crypto.randomUUID()}`, opts.workspace);
7380
7481
  console.log(renderLibraryArtifact(artifact2));
7381
7482
  })
@@ -7406,7 +7507,7 @@ library.command("place <id> <workspace>").description('place your artifact in a
7406
7507
  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(
7407
7508
  run(async (id, out, opts) => {
7408
7509
  const { bytes } = await downloadLibraryArtifact(id, opts.version ? Number(opts.version) : void 0);
7409
- writeFileSync10(out, bytes);
7510
+ writeFileSync11(out, bytes);
7410
7511
  console.log(`wrote ${bytes.length} bytes to ${out}`);
7411
7512
  })
7412
7513
  );
@@ -7449,7 +7550,7 @@ artifact.command("get <id> <path>").description("read one file of an artifact; p
7449
7550
  run(async (id, path, opts) => {
7450
7551
  const bytes = await readArtifactFile(id, path);
7451
7552
  if (opts.out) {
7452
- writeFileSync10(opts.out, bytes);
7553
+ writeFileSync11(opts.out, bytes);
7453
7554
  console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
7454
7555
  } else process.stdout.write(bytes);
7455
7556
  })
@@ -7487,14 +7588,14 @@ designSystem.command("import <task> <folder>").description("import a local desig
7487
7588
  );
7488
7589
  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(
7489
7590
  run(async (id, file, opts) => {
7490
- const tokens = JSON.parse(readFileSync20(resolve9(file), "utf8"));
7591
+ const tokens = JSON.parse(readFileSync21(resolve9(file), "utf8"));
7491
7592
  console.log(renderArtifact(await saveDesignTokens(id, opts.base, tokens, opts.note)));
7492
7593
  })
7493
7594
  );
7494
7595
  designSystem.command("write <id> <path> [file]").description("save one of the system's editable files (path such as project/README.md) from a local file as its next version, or put back an earlier version's copy with --restore").requiredOption("--base <version>", "the version the file was edited from", (value) => Number(value)).option("--restore <version>", "restore the file as it was in this version instead of reading [file]", (value) => Number(value)).option("--note <note>", "one line saying what changed").action(
7495
7596
  run(async (id, path, file, opts) => {
7496
7597
  if (file === void 0 === (opts.restore === void 0)) throw Error("Give a local [file] to save, or --restore <version>.");
7497
- const change = opts.restore === void 0 ? { content: readFileSync20(resolve9(file), "utf8") } : { restore_version: opts.restore };
7598
+ const change = opts.restore === void 0 ? { content: readFileSync21(resolve9(file), "utf8") } : { restore_version: opts.restore };
7498
7599
  console.log(renderArtifact(await saveDesignSystemFile(id, path, opts.base, change, opts.note)));
7499
7600
  })
7500
7601
  );
@@ -7807,7 +7908,7 @@ usageOptions(
7807
7908
  run(async (opts) => {
7808
7909
  const { bytes } = await apiBytes("GET", `/billing/usage/export${usageQuery(opts)}`);
7809
7910
  if (opts.out) {
7810
- writeFileSync10(opts.out, bytes);
7911
+ writeFileSync11(opts.out, bytes);
7811
7912
  console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
7812
7913
  } else {
7813
7914
  process.stdout.write(bytes);
@@ -8429,7 +8530,7 @@ notes.command("read <storeId> <noteId>").description("print one note").action(
8429
8530
  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(
8430
8531
  run(async (storeId, file, opts) => {
8431
8532
  if (!opts.path === !opts.note) throw new Error("pass exactly one of --path (new note) or --note (update)");
8432
- const content = readFileSync20(file, "utf8");
8533
+ const content = readFileSync21(file, "utf8");
8433
8534
  const target = `/memory_stores/${encodeURIComponent(storeId)}/memories${opts.note ? `/${encodeURIComponent(opts.note)}` : ""}`;
8434
8535
  const { memory: memory2 } = await api("POST", target, { content, ...opts.path ? { path: opts.path } : {} });
8435
8536
  console.log(`Saved ${memory2.path} (${memory2.id})`);
@@ -8529,7 +8630,7 @@ harness.command("connect").description("run an ACP agent (the command after --)
8529
8630
  }));
8530
8631
  var traceCmd = program.command("trace").description("correlate this machine's agent work with the cloud sessions it starts (metadata only unless you choose content)");
8531
8632
  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) => {
8532
- const { readState, writeState, record, installClaudeHooks, parseContentScopes, chosenPaths, fileEvent } = await import("./trace-RUZF6QL6.js");
8633
+ const { readState, writeState, record, installClaudeHooks, parseContentScopes, chosenPaths, fileEvent } = await import("./trace-5SW4YMCC.js");
8533
8634
  if (readState()) throw new Error("a trace is already running here \u2014 `sky trace stop` it first");
8534
8635
  const scopes = parseContentScopes(opts.capture);
8535
8636
  const chosen = chosenPaths(opts.file ?? [], opts.dir ?? []);
@@ -8564,7 +8665,7 @@ traceCmd.command("start").description("start a trace: a grant for this machine,
8564
8665
  }));
8565
8666
  traceCmd.command("hook").description("record one Claude Code hook event read from stdin (run by the installed hooks; never fails, prints nothing)").action(async () => {
8566
8667
  try {
8567
- const { readState, record, flush, grantSender, eventsForClaudeHook, contentForClaudeHook, clearState } = await import("./trace-RUZF6QL6.js");
8668
+ const { readState, record, flush, grantSender, eventsForClaudeHook, contentForClaudeHook, clearState } = await import("./trace-5SW4YMCC.js");
8568
8669
  const chunks = [];
8569
8670
  for await (const chunk of process.stdin) chunks.push(chunk);
8570
8671
  const input = JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}");
@@ -8577,14 +8678,14 @@ traceCmd.command("hook").description("record one Claude Code hook event read fro
8577
8678
  }
8578
8679
  });
8579
8680
  traceCmd.command("flush").description("send what the spool holds, retrying with backoff").action(run(async () => {
8580
- const { readState, flush, grantSender } = await import("./trace-RUZF6QL6.js");
8681
+ const { readState, flush, grantSender } = await import("./trace-5SW4YMCC.js");
8581
8682
  const state = readState();
8582
8683
  if (!state) throw new Error("no trace is running here");
8583
8684
  const outcome = await flush(grantSender(state), { attempts: 4 });
8584
8685
  console.log(`sent ${outcome.sent}, refused ${outcome.refused}, given up ${outcome.expired}, still pending ${outcome.pending}${outcome.stopped ? ` (stopped: ${outcome.stopped})` : ""}`);
8585
8686
  }));
8586
8687
  traceCmd.command("status").description("the running trace and its spool").action(run(async () => {
8587
- const { readState, spoolStatus } = await import("./trace-RUZF6QL6.js");
8688
+ const { readState, spoolStatus } = await import("./trace-5SW4YMCC.js");
8588
8689
  const state = readState();
8589
8690
  if (!state) {
8590
8691
  console.log("No trace is running here.");
@@ -8594,7 +8695,7 @@ traceCmd.command("status").description("the running trace and its spool").action
8594
8695
  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`);
8595
8696
  }));
8596
8697
  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) => {
8597
- const { readState } = await import("./trace-RUZF6QL6.js");
8698
+ const { readState } = await import("./trace-5SW4YMCC.js");
8598
8699
  const ref = id ?? readState()?.trace_id;
8599
8700
  if (!ref) throw new Error("name a trace, or start one here");
8600
8701
  const bundle = await api("GET", `/traces/${ref}`);
@@ -8621,7 +8722,7 @@ traceCmd.command("show [id]").description("the trace bundle: spans, the sessions
8621
8722
  for (const gap of bundle.gaps) console.log(` gap: ${gap.span_id} ${gap.reason}`);
8622
8723
  }));
8623
8724
  traceCmd.command("stop").description("end the root span, send what is left, and revoke this machine's grant").action(run(async () => {
8624
- const { readState, record, flush, grantSender, clearState } = await import("./trace-RUZF6QL6.js");
8725
+ const { readState, record, flush, grantSender, clearState } = await import("./trace-5SW4YMCC.js");
8625
8726
  const state = readState();
8626
8727
  if (!state) throw new Error("no trace is running here");
8627
8728
  if (state.root_span) record(() => [{ span_id: state.root_span, kind: "end", outcome: "completed" }]);
@@ -8631,7 +8732,7 @@ traceCmd.command("stop").description("end the root span, send what is left, and
8631
8732
  console.log(`Stopped ${state.trace_id}${outcome.pending ? ` (${outcome.pending} events could not be sent)` : ""}`);
8632
8733
  }));
8633
8734
  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) => {
8634
- const lib = await import("./trace-library-5Y63PZAD.js");
8735
+ const lib = await import("./trace-library-RKZNJ5O5.js");
8635
8736
  if (opts.hook) {
8636
8737
  try {
8637
8738
  let raw = payload ?? "";
@@ -8691,9 +8792,9 @@ traceCmd.command("sync [payload]").description("upload this machine's agent sess
8691
8792
  }
8692
8793
  if (opts.installSchedule) {
8693
8794
  const { join: join20 } = await import("path");
8694
- const { homedir: homedir10 } = await import("os");
8795
+ const { homedir: homedir11 } = await import("os");
8695
8796
  const { execFileSync } = await import("child_process");
8696
- const log = join20(homedir10(), ".config", "sky", "trace-sync.log");
8797
+ const log = join20(homedir11(), ".config", "sky", "trace-sync.log");
8697
8798
  const plist = lib.installLaunchd([process.execPath, process.argv[1], "trace", "sync", "--quiet"], log);
8698
8799
  try {
8699
8800
  execFileSync("launchctl", ["unload", plist], { stdio: "ignore" });
@@ -8703,11 +8804,11 @@ traceCmd.command("sync [payload]").description("upload this machine's agent sess
8703
8804
  console.log(`Sweeping every 15 minutes (${plist}); a full re-read runs weekly. Log: ${log}`);
8704
8805
  }
8705
8806
  if (opts.status) {
8706
- const { readFileSync: readFileSync21 } = await import("fs");
8807
+ const { readFileSync: readFileSync22 } = await import("fs");
8707
8808
  const { join: join20 } = await import("path");
8708
8809
  let state = { sessions: {} };
8709
8810
  try {
8710
- state = JSON.parse(readFileSync21(join20(lib.syncConfigPath(), "..", "trace-sync-state.json"), "utf8"));
8811
+ state = JSON.parse(readFileSync22(join20(lib.syncConfigPath(), "..", "trace-sync-state.json"), "utf8"));
8711
8812
  } catch {
8712
8813
  }
8713
8814
  const counts = /* @__PURE__ */ new Map();
@@ -8746,7 +8847,7 @@ traceCmd.command("search <query...>").description("search every session in a wor
8746
8847
  console.log(opts.json ? JSON.stringify(page, null, 2) : renderContextPage(page));
8747
8848
  }));
8748
8849
  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) => {
8749
- const { libraryRequest } = await import("./trace-library-5Y63PZAD.js");
8850
+ const { libraryRequest } = await import("./trace-library-RKZNJ5O5.js");
8750
8851
  const workspace2 = opts.workspace ?? currentUniverse();
8751
8852
  if (!workspace2) throw new Error("name a workspace with --workspace");
8752
8853
  const page = await libraryRequest("GET", `/trace-library?limit=${opts.limit}`, workspace2);
@@ -2,7 +2,7 @@ import {
2
2
  admittedInputScopeSchema,
3
3
  external_exports,
4
4
  messagePartSchema
5
- } from "./chunk-ISORBGQX.js";
5
+ } from "./chunk-JOLDBZV3.js";
6
6
  import "./chunk-MLKGABMK.js";
7
7
 
8
8
  // ../../packages/chat/src/stream.ts
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  USER_AGENT,
3
3
  configPath
4
- } from "./chunk-QZLKHGX6.js";
4
+ } from "./chunk-KNGZR3CX.js";
5
5
  import {
6
6
  TRACE_CONTENT_SCOPES,
7
7
  redactTraceText
8
- } from "./chunk-ISORBGQX.js";
8
+ } from "./chunk-JOLDBZV3.js";
9
9
  import "./chunk-MLKGABMK.js";
10
10
 
11
11
  // src/trace.ts
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  ApiError
3
- } from "./chunk-GEL5GWF2.js";
3
+ } from "./chunk-TIFRDEFP.js";
4
4
  import {
5
5
  USER_AGENT,
6
6
  apiBase,
7
7
  apiToken
8
- } from "./chunk-QZLKHGX6.js";
8
+ } from "./chunk-KNGZR3CX.js";
9
9
  import {
10
10
  SessionSourceCollector,
11
11
  publicRemote,
12
12
  redactTraceText
13
- } from "./chunk-ISORBGQX.js";
13
+ } from "./chunk-JOLDBZV3.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // src/trace-library.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentsky/sky",
3
- "version": "2.29.0",
3
+ "version": "2.30.0",
4
4
  "description": "sky \u2014 the AgentSky developer CLI: launch and talk to long-lived agents from your terminal.",
5
5
  "license": "MIT",
6
6
  "type": "module",