@agentsky/sky 2.7.2 → 2.8.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.
@@ -19028,6 +19028,7 @@ var REASONING_EFFORTS = {
19028
19028
  code_assistant: null,
19029
19029
  docker_cagent: null,
19030
19030
  kiro: null,
19031
+ muse_code: null,
19031
19032
  openhands: null,
19032
19033
  hermes: ["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"],
19033
19034
  claude_code: ["low", "medium", "high", "xhigh", "max"],
@@ -19339,6 +19340,13 @@ var ACP_AGENTS = {
19339
19340
  "version": "2.22.0",
19340
19341
  "website": "https://kiro.dev/docs/cli/acp/"
19341
19342
  },
19343
+ "muse_code": {
19344
+ "registryId": "muse-code",
19345
+ "label": "Muse Code",
19346
+ "description": "Meta's coding agent and CLI",
19347
+ "version": "1.4.3",
19348
+ "website": "https://dev.meta.ai/docs/muse-code/"
19349
+ },
19342
19350
  "openhands": {
19343
19351
  "registryId": "openhands",
19344
19352
  "label": "OpenHands",
@@ -19388,7 +19396,8 @@ var ACP_AGENT_TYPES = [
19388
19396
  "code_assistant",
19389
19397
  "docker_cagent",
19390
19398
  "kiro",
19391
- "openhands"
19399
+ "openhands",
19400
+ "muse_code"
19392
19401
  ];
19393
19402
  function isAcpAgentType(value) {
19394
19403
  return Object.hasOwn(ACP_AGENTS, value);
@@ -20891,6 +20900,35 @@ var ACP_ACCOUNT_PROFILES = {
20891
20900
  "https://kiro.dev/docs/getting-started/authentication/"
20892
20901
  ]
20893
20902
  },
20903
+ "muse_code": {
20904
+ "name": "Muse Code",
20905
+ "version": "1.4.3",
20906
+ "status": "documented",
20907
+ "setupModes": [
20908
+ {
20909
+ "id": "api_key",
20910
+ "label": "API key",
20911
+ "fields": [
20912
+ {
20913
+ "key": "META_API_KEY",
20914
+ "label": "Meta API key",
20915
+ "kind": "secret",
20916
+ "required": true,
20917
+ "source": "https://dev.meta.ai/docs/muse-code/"
20918
+ }
20919
+ ],
20920
+ "source": "https://dev.meta.ai/docs/muse-code/"
20921
+ }
20922
+ ],
20923
+ "files": [],
20924
+ "notes": [
20925
+ "Muse Code runs through a community ACP adapter in front of Meta's own host binary. An authenticated turn has not been exercised."
20926
+ ],
20927
+ "sources": [
20928
+ "https://dev.meta.ai/docs/muse-code/",
20929
+ "https://github.com/bex-co/muse-code-acp"
20930
+ ]
20931
+ },
20894
20932
  "openhands": {
20895
20933
  "name": "OpenHands",
20896
20934
  "version": "1.16.0",
@@ -21935,6 +21973,7 @@ var GATEWAY_CAPABILITY_IDS = [
21935
21973
  "wan.image"
21936
21974
  ];
21937
21975
  var CAPABILITY_IDS = [...LEGACY_CAPABILITY_IDS, ...GATEWAY_CAPABILITY_IDS];
21976
+ var PLATFORM_CAPABILITY_IDS = ["platform.orchestration"];
21938
21977
  var allowedLlms = {
21939
21978
  jev: ["typesafe/jev-1.13"],
21940
21979
  agoragentic_acp: ["harness-default"],
@@ -21977,6 +22016,7 @@ var allowedLlms = {
21977
22016
  code_assistant: [...ACP_PLATFORM_MODELS.code_assistant, "harness-default"],
21978
22017
  docker_cagent: [...ACP_PLATFORM_MODELS.docker_cagent, "harness-default"],
21979
22018
  kiro: ["harness-default"],
22019
+ muse_code: ["harness-default"],
21980
22020
  openhands: [...ACP_PLATFORM_MODELS.openhands, "harness-default"],
21981
22021
  hermes: [
21982
22022
  "deepseek-v4-pro",
@@ -22177,19 +22217,22 @@ function modelSubscriptionProviderFor(agentType, llm) {
22177
22217
  if (agentType === "codex" && CHATGPT_PLAN_MODELS.has(llm)) return "openai";
22178
22218
  if (agentType === "cursor" && llm === "harness-default") return "cursor";
22179
22219
  if (agentType === "grok_build" && llm === "harness-default") return "xai";
22220
+ if (agentType === "muse_code" && llm === "harness-default") return "meta";
22180
22221
  return null;
22181
22222
  }
22182
22223
  var MODEL_SUBSCRIPTION_PROVIDER_NAME = {
22183
22224
  anthropic: "Claude",
22184
22225
  openai: "ChatGPT",
22185
22226
  cursor: "Cursor",
22186
- xai: "Grok"
22227
+ xai: "Grok",
22228
+ meta: "Muse"
22187
22229
  };
22188
22230
  var MODEL_SUBSCRIPTION_PLAN_PHRASE = {
22189
22231
  anthropic: "Claude subscription",
22190
22232
  openai: "ChatGPT plan",
22191
22233
  cursor: "Cursor plan",
22192
- xai: "Grok subscription"
22234
+ xai: "Grok subscription",
22235
+ meta: "Muse subscription"
22193
22236
  };
22194
22237
  var AGENT_TYPE_META = {
22195
22238
  ...Object.fromEntries(ACP_AGENT_TYPES.map((agentType) => [agentType, {
@@ -22362,8 +22405,10 @@ var spendCapPolicyConfigSchema = external_exports.object({
22362
22405
  });
22363
22406
  var callCountPolicyConfigSchema = external_exports.object({ limitPerSession: external_exports.number().int().min(1).max(1e5) }).strict();
22364
22407
  var capabilityPolicyConfigSchema = external_exports.record(external_exports.string(), external_exports.enum(POLICY_ACTIONS)).superRefine((obj, ctx) => {
22365
- for (const k of Object.keys(obj)) {
22366
- if (!CAPABILITY_IDS.includes(k)) {
22408
+ for (const [k, action] of Object.entries(obj)) {
22409
+ if (PLATFORM_CAPABILITY_IDS.includes(k)) {
22410
+ if (action === "ask") ctx.addIssue({ code: "custom", message: `${k} accepts allow or deny`, path: [k] });
22411
+ } else if (!CAPABILITY_IDS.includes(k)) {
22367
22412
  ctx.addIssue({ code: "custom", message: `unknown capability id: ${k}`, path: [k] });
22368
22413
  }
22369
22414
  }
package/dist/index.js CHANGED
@@ -16,10 +16,10 @@ import {
16
16
  skillRefSchema,
17
17
  splitMcpServers,
18
18
  supersededBy
19
- } from "./chunk-IC4N2ZPL.js";
19
+ } from "./chunk-WFTZR5YO.js";
20
20
 
21
21
  // src/index.ts
22
- import { existsSync as existsSync7, writeFileSync as writeFileSync6 } from "fs";
22
+ import { existsSync as existsSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
23
23
  import { basename as basename3, resolve as resolve4 } from "path";
24
24
  import { createInterface as createInterface4 } from "readline";
25
25
  import { Command } from "commander";
@@ -64,7 +64,7 @@ function currentUniverse() {
64
64
  }
65
65
 
66
66
  // src/version.ts
67
- var CLI_VERSION = "2.7.2";
67
+ var CLI_VERSION = "2.8.0";
68
68
  var USER_AGENT = `sky-cli/${CLI_VERSION} (${process.platform}; node/${process.versions.node})`;
69
69
 
70
70
  // src/api.ts
@@ -148,6 +148,24 @@ async function downloadFile(fileId) {
148
148
  if (!res.ok) await parseError(res);
149
149
  return { bytes: new Uint8Array(await res.arrayBuffer()), mediaType: res.headers.get("content-type") ?? "application/octet-stream" };
150
150
  }
151
+ async function apiBytes(method, path, body) {
152
+ const res = await fetch(`${apiBase()}${path}`, {
153
+ method,
154
+ headers: {
155
+ "user-agent": USER_AGENT,
156
+ ...authHeaders(),
157
+ ...body ? { "content-type": body.mediaType } : {}
158
+ },
159
+ body: body ? new Uint8Array(body.bytes) : void 0
160
+ });
161
+ if (!res.ok) await parseError(res);
162
+ const bytes = new Uint8Array(await res.arrayBuffer());
163
+ return {
164
+ bytes,
165
+ mediaType: res.headers.get("content-type") ?? "application/octet-stream",
166
+ json: () => JSON.parse(new TextDecoder().decode(bytes))
167
+ };
168
+ }
151
169
  async function resolveSessionRef(ref) {
152
170
  if (ref.startsWith("sess-")) return ref;
153
171
  const { agent: agent2 } = await api(
@@ -167,7 +185,7 @@ async function resolveSessionRef(ref) {
167
185
  return agent2.defaultSessionId;
168
186
  }
169
187
  async function* streamEvents(sessionId, signal) {
170
- const { parseSseStream } = await import("./src-S76Y7GHZ.js");
188
+ const { parseSseStream } = await import("./src-2DLGPJB6.js");
171
189
  const res = await fetch(
172
190
  `${apiBase()}/sessions/${encodeURIComponent(sessionId)}/stream`,
173
191
  {
@@ -1977,6 +1995,144 @@ async function importToWorkspace(key, held, skills, instructions, emit) {
1977
1995
  if (!finished.ok) emit({ type: "error", code: finished.code, message: finished.message });
1978
1996
  }
1979
1997
 
1998
+ // src/task-files.ts
1999
+ function encodePath(path) {
2000
+ return path.replace(/^\/+/, "").split("/").map(encodeURIComponent).join("/");
2001
+ }
2002
+ var filesPath = (task2) => `/tasks/${encodeURIComponent(task2)}/files`;
2003
+ async function listTaskFiles(task2) {
2004
+ return (await api("GET", filesPath(task2))).files;
2005
+ }
2006
+ async function readTaskFile(task2, path) {
2007
+ return (await apiBytes("GET", `${filesPath(task2)}/${encodePath(path)}`)).bytes;
2008
+ }
2009
+ async function writeTaskFile(task2, path, bytes, mediaType) {
2010
+ return (await apiBytes("PUT", `${filesPath(task2)}/${encodePath(path)}`, { bytes, mediaType })).json();
2011
+ }
2012
+ async function deleteTaskFile(task2, path) {
2013
+ await api("DELETE", `${filesPath(task2)}/${encodePath(path)}`);
2014
+ }
2015
+ async function listArtifacts(task2) {
2016
+ const query = task2 ? `?task_id=${encodeURIComponent(task2)}` : "";
2017
+ return (await api("GET", `/artifacts${query}`)).artifacts;
2018
+ }
2019
+ function publishBody(task2, options) {
2020
+ return { task_id: task2, name: options.name, paths: options.path, ...options.entry ? { entry: options.entry } : {} };
2021
+ }
2022
+ async function publishArtifact(task2, options) {
2023
+ return (await api("POST", "/artifacts", publishBody(task2, options))).artifact;
2024
+ }
2025
+ async function readArtifactFile(id, path) {
2026
+ return (await apiBytes("GET", `/artifacts/${encodeURIComponent(id)}/files/${encodePath(path)}`)).bytes;
2027
+ }
2028
+ async function shareArtifact(id, enabled) {
2029
+ return (await api("POST", `/artifacts/${encodeURIComponent(id)}/share`, { enabled })).share_url;
2030
+ }
2031
+ async function deleteArtifact(id) {
2032
+ await api("DELETE", `/artifacts/${encodeURIComponent(id)}`);
2033
+ }
2034
+ function renderTaskFile(file) {
2035
+ return `${file.path} ${file.size_bytes} bytes ${file.updated_at}${file.updated_by_session ? ` by ${file.updated_by_session}` : ""}`;
2036
+ }
2037
+ function renderArtifact(artifact2) {
2038
+ const files2 = `${artifact2.files.length} ${artifact2.files.length === 1 ? "file" : "files"}`;
2039
+ return `${artifact2.id} ${artifact2.name} v${artifact2.version} ${files2} entry ${artifact2.entry}${artifact2.share_url ? ` shared ${artifact2.share_url}` : ""}`;
2040
+ }
2041
+
2042
+ // src/workspace.ts
2043
+ var KINDS = ["TOOL_CALL", "SPEND_CAP", "CALL_COUNT", "CAPABILITY"];
2044
+ async function workspaceSlug(explicit) {
2045
+ if (explicit) return explicit;
2046
+ const current = currentUniverse();
2047
+ if (current) return current;
2048
+ return (await api("GET", "/whoami")).universe.slug;
2049
+ }
2050
+ var workspacePath = (slug) => `/universes/${encodeURIComponent(slug)}`;
2051
+ async function listMembers(slug) {
2052
+ return api("GET", `${workspacePath(slug)}/members`);
2053
+ }
2054
+ function findMember(members, ref) {
2055
+ const needle = ref.toLowerCase();
2056
+ const found = members.find((m) => m.user_id === ref || m.email?.toLowerCase() === needle);
2057
+ if (!found) throw new ApiError(404, "not_found", `no member ${ref} in this workspace`);
2058
+ return found;
2059
+ }
2060
+ function inviteBody(emails, options) {
2061
+ if (options.role && options.role !== "admin" && options.role !== "member") {
2062
+ throw new ApiError(400, "invalid_request", "--role is admin or member");
2063
+ }
2064
+ return {
2065
+ emails,
2066
+ ...options.role ? { role: options.role } : {},
2067
+ ...options.sendEmail ? { send_email: true } : {}
2068
+ };
2069
+ }
2070
+ async function invite(slug, emails, options) {
2071
+ return api("POST", `${workspacePath(slug)}/invites`, inviteBody(emails, options));
2072
+ }
2073
+ async function withdrawInvite(slug, inviteId) {
2074
+ await api("DELETE", `${workspacePath(slug)}/invites/${encodeURIComponent(inviteId)}`);
2075
+ }
2076
+ async function setRole(slug, memberRef, role) {
2077
+ if (role !== "admin" && role !== "member") throw new ApiError(400, "invalid_request", "a role is admin or member");
2078
+ const member = findMember((await listMembers(slug)).members, memberRef);
2079
+ await api("PATCH", `${workspacePath(slug)}/members/${encodeURIComponent(member.user_id)}`, { role });
2080
+ return member;
2081
+ }
2082
+ async function removeMember(slug, memberRef) {
2083
+ const member = findMember((await listMembers(slug)).members, memberRef);
2084
+ await api("DELETE", `${workspacePath(slug)}/members/${encodeURIComponent(member.user_id)}`);
2085
+ return member;
2086
+ }
2087
+ async function joinWorkspace(token) {
2088
+ return (await api("POST", `/invites/${encodeURIComponent(token)}`)).workspace;
2089
+ }
2090
+ function renderMembers(page) {
2091
+ const lines = page.members.map((m) => `${m.role.padEnd(6)} ${m.email ?? m.user_id}${m.name ? ` (${m.name})` : ""} ${m.user_id}`);
2092
+ for (const i of page.invites) lines.push(`invited ${i.email} as ${i.role} by ${i.invited_by} until ${i.expires_at.slice(0, 10)} ${i.id}`);
2093
+ return lines;
2094
+ }
2095
+ function policyRuleBody(options) {
2096
+ const kind = options.kind.toUpperCase().replace(/-/g, "_");
2097
+ if (!KINDS.includes(kind)) throw new ApiError(400, "invalid_request", `--kind is one of ${KINDS.join(", ")}`);
2098
+ let config;
2099
+ try {
2100
+ config = JSON.parse(options.config);
2101
+ } catch {
2102
+ throw new ApiError(400, "invalid_request", "--config must be a JSON object");
2103
+ }
2104
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
2105
+ throw new ApiError(400, "invalid_request", "--config must be a JSON object");
2106
+ }
2107
+ const position = options.position === void 0 ? void 0 : Number(options.position);
2108
+ if (position !== void 0 && !Number.isInteger(position)) throw new ApiError(400, "invalid_request", "--position is a whole number");
2109
+ return {
2110
+ name: options.name,
2111
+ kind,
2112
+ config,
2113
+ ...position !== void 0 ? { position } : {},
2114
+ ...options.disabled ? { enabled: false } : {}
2115
+ };
2116
+ }
2117
+ var policiesPath = (scope) => "session" in scope ? `/sessions/${encodeURIComponent(scope.session)}/policies` : `${workspacePath(scope.slug)}/policies`;
2118
+ async function listPolicies(scope, effective = false) {
2119
+ if (effective && "session" in scope) return api("GET", `/sessions/${encodeURIComponent(scope.session)}/effective-policy`);
2120
+ return api("GET", policiesPath(scope));
2121
+ }
2122
+ async function addPolicy(scope, options) {
2123
+ return (await api("POST", policiesPath(scope), policyRuleBody(options))).rule;
2124
+ }
2125
+ async function setPolicyEnabled(scope, ruleId, enabled) {
2126
+ return (await api("PATCH", `${policiesPath(scope)}/${encodeURIComponent(ruleId)}`, { enabled })).rule;
2127
+ }
2128
+ async function removePolicy(scope, ruleId) {
2129
+ await api("DELETE", `${policiesPath(scope)}/${encodeURIComponent(ruleId)}`);
2130
+ }
2131
+ function renderPolicy(rule) {
2132
+ const state = rule.enabled ? "on " : "off";
2133
+ return `${state} ${rule.layer.padEnd(9)} ${rule.kind.padEnd(10)} ${rule.name} ${JSON.stringify(rule.config)} ${rule.id}`;
2134
+ }
2135
+
1980
2136
  // src/index.ts
1981
2137
  function printModelBilling(session2) {
1982
2138
  if (session2.modelBilling !== "account") return;
@@ -2055,6 +2211,84 @@ universe.command("show").action(
2055
2211
  }
2056
2212
  })
2057
2213
  );
2214
+ universe.command("members [slug]").description("who is in the workspace, and who is invited (owners and admins)").action(
2215
+ run(async (slug) => {
2216
+ for (const line of renderMembers(await listMembers(await workspaceSlug(slug)))) console.log(line);
2217
+ })
2218
+ );
2219
+ universe.command("invite <emails...>").description("invite people by email; prints each person's join link token").option("--role <role>", "admin | member (default member; admin needs the owner)").option("--send-email", "also email each invitation").option("--universe <slug>", "the workspace (default: the current one)").action(
2220
+ run(async (emails, opts) => {
2221
+ const result = await invite(await workspaceSlug(opts.universe), emails, opts);
2222
+ for (const i of result.invites) console.log(`invited ${i.email} as ${i.role} ${i.id}`);
2223
+ for (const link of result.links) console.log(` ${link.email} joins with: sky universe join ${link.token}`);
2224
+ if (!result.invites.length) console.log("nobody new to invite \u2014 everyone listed is already a member");
2225
+ })
2226
+ );
2227
+ universe.command("uninvite <inviteId>").description("withdraw an invitation that has not been taken up").option("--universe <slug>", "the workspace (default: the current one)").action(
2228
+ run(async (inviteId, opts) => {
2229
+ await withdrawInvite(await workspaceSlug(opts.universe), inviteId);
2230
+ console.log(`Withdrew ${inviteId}`);
2231
+ })
2232
+ );
2233
+ universe.command("role <member> <role>").description("make a member (user id or email) an admin or a member (owner only)").option("--universe <slug>", "the workspace (default: the current one)").action(
2234
+ run(async (memberRef, role, opts) => {
2235
+ const member = await setRole(await workspaceSlug(opts.universe), memberRef, role);
2236
+ console.log(`${member.email ?? member.user_id} is now ${role}`);
2237
+ })
2238
+ );
2239
+ universe.command("remove <member>").description("remove a member (user id or email) from the workspace (owner only)").option("--universe <slug>", "the workspace (default: the current one)").action(
2240
+ run(async (memberRef, opts) => {
2241
+ const member = await removeMember(await workspaceSlug(opts.universe), memberRef);
2242
+ console.log(`Removed ${member.email ?? member.user_id}`);
2243
+ })
2244
+ );
2245
+ universe.command("join <token>").description("accept an invitation sent to your verified email").action(
2246
+ run(async (token) => {
2247
+ const workspace = await joinWorkspace(token);
2248
+ console.log(`Joined ${workspace.slug} (${workspace.name}) \u2014 sky universe switch ${workspace.slug}`);
2249
+ })
2250
+ );
2251
+ var policy = program.command("policy").description("policy rules: tool calls, spend caps, call counts, capabilities");
2252
+ async function policyScope(opts) {
2253
+ return opts.session ? { session: await resolveSessionRef(opts.session) } : { slug: await workspaceSlug(opts.universe) };
2254
+ }
2255
+ var scopeOptions = (command) => command.option("--session <ref>", "one session's rules instead of the workspace's").option("--universe <slug>", "the workspace (default: the current one)");
2256
+ scopeOptions(
2257
+ policy.command("list").description("the workspace's rules, or one session's; --effective merges every layer").option("--effective", "with --session: every rule the session runs under")
2258
+ ).action(
2259
+ run(async (opts) => {
2260
+ const { rules, note } = await listPolicies(await policyScope(opts), opts.effective);
2261
+ if (!rules.length) console.log("no policy rules");
2262
+ for (const rule of rules) console.log(renderPolicy(rule));
2263
+ if (note) console.log(note);
2264
+ })
2265
+ );
2266
+ scopeOptions(
2267
+ policy.command("add").description("add a rule (workspace owner, or the session's owner with --session)").requiredOption("--name <name>", "what the rule is for").requiredOption("--kind <kind>", "TOOL_CALL | SPEND_CAP | CALL_COUNT | CAPABILITY").requiredOption(
2268
+ "--config <json>",
2269
+ `e.g. '{"action":"deny","matcher":"Bash","commandPatterns":["rm -rf *"]}', '{"hardCapUsdMicros":5000000}', '{"limitPerSession":200}', '{"platform.orchestration":"deny"}'`
2270
+ ).option("--position <n>", "evaluation order, lowest first (default 0)").option("--disabled", "create it switched off")
2271
+ ).action(
2272
+ run(async (opts) => {
2273
+ console.log(renderPolicy(await addPolicy(await policyScope(opts), opts)));
2274
+ })
2275
+ );
2276
+ for (const [verb, enabled, description] of [
2277
+ ["enable", true, "switch a rule on"],
2278
+ ["disable", false, "switch a rule off (kept, so it can be switched on again)"]
2279
+ ]) {
2280
+ scopeOptions(policy.command(`${verb} <ruleId>`).description(description)).action(
2281
+ run(async (ruleId, opts) => {
2282
+ console.log(renderPolicy(await setPolicyEnabled(await policyScope(opts), ruleId, enabled)));
2283
+ })
2284
+ );
2285
+ }
2286
+ scopeOptions(policy.command("rm <ruleId>").description("delete a rule")).action(
2287
+ run(async (ruleId, opts) => {
2288
+ await removePolicy(await policyScope(opts), ruleId);
2289
+ console.log(`Deleted ${ruleId}`);
2290
+ })
2291
+ );
2058
2292
  var agent = program.command("agent").description("agent specs: create, inspect, talk (via the default session)");
2059
2293
  agent.command("create").description("create an agent spec \u2014 no runtime; `sky session create` starts one").option("--type <type>", "hermes | claude_code | codex | openclaw | pi | dsh | kimi_code | opencode").option("--llm <llm>", "model id (defaults per type)").option(
2060
2294
  "--reasoning-effort <level>",
@@ -2700,6 +2934,69 @@ files.command("download <id>").description("download a session file's bytes").re
2700
2934
  console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
2701
2935
  })
2702
2936
  );
2937
+ var task = program.command("task").description("a task's shared files (the task is its first session's id)");
2938
+ task.command("files <task>").description("list the task's current files").action(
2939
+ run(async (taskId) => {
2940
+ const list = await listTaskFiles(taskId);
2941
+ if (!list.length) console.log("no files");
2942
+ for (const file of list) console.log(renderTaskFile(file));
2943
+ })
2944
+ );
2945
+ task.command("get <task> <path>").description("read one task file; prints it, or writes it with -o").option("-o, --out <path>", "where to write the bytes").action(
2946
+ run(async (taskId, path, opts) => {
2947
+ const bytes = await readTaskFile(taskId, path);
2948
+ if (opts.out) {
2949
+ writeFileSync6(opts.out, bytes);
2950
+ console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
2951
+ } else process.stdout.write(bytes);
2952
+ })
2953
+ );
2954
+ 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(
2955
+ run(async (taskId, path, local) => {
2956
+ const { file, conflict } = await writeTaskFile(taskId, path, readFileSync10(local), mediaTypeFor(local));
2957
+ console.log(`${renderTaskFile(file)}${conflict ? " (replaced a version you had not seen)" : ""}`);
2958
+ })
2959
+ );
2960
+ task.command("rm <task> <path>").description("remove a path from the task's files (its history is kept)").action(
2961
+ run(async (taskId, path) => {
2962
+ await deleteTaskFile(taskId, path);
2963
+ console.log(`Removed ${path}`);
2964
+ })
2965
+ );
2966
+ var artifact = program.command("artifact").description("artifacts: publish a task's files as a named, shareable result");
2967
+ artifact.command("list").description("the workspace's artifacts, or one task's with --task").option("--task <task>", "only this task's artifacts").action(
2968
+ run(async (opts) => {
2969
+ const list = await listArtifacts(opts.task);
2970
+ if (!list.length) console.log("no artifacts");
2971
+ for (const a of list) console.log(renderArtifact(a));
2972
+ })
2973
+ );
2974
+ artifact.command("publish <task>").description("publish paths from the task's files as a new version of the named artifact").requiredOption("--name <name>", "the artifact's name; publishing the same name again adds a version").requiredOption("--path <path...>", "task file paths to include").option("--entry <path>", "the file a viewer opens first (default: the first path)").action(
2975
+ run(async (taskId, opts) => {
2976
+ console.log(renderArtifact(await publishArtifact(taskId, opts)));
2977
+ })
2978
+ );
2979
+ artifact.command("get <id> <path>").description("read one file of an artifact; prints it, or writes it with -o").option("-o, --out <path>", "where to write the bytes").action(
2980
+ run(async (id, path, opts) => {
2981
+ const bytes = await readArtifactFile(id, path);
2982
+ if (opts.out) {
2983
+ writeFileSync6(opts.out, bytes);
2984
+ console.log(`Wrote ${bytes.length} bytes to ${opts.out}`);
2985
+ } else process.stdout.write(bytes);
2986
+ })
2987
+ );
2988
+ artifact.command("share <id>").description("turn on a public link anyone can open; --off turns it off (the old link stops working)").option("--off", "stop sharing").action(
2989
+ run(async (id, opts) => {
2990
+ const url = await shareArtifact(id, !opts.off);
2991
+ console.log(url ?? `Stopped sharing ${id}`);
2992
+ })
2993
+ );
2994
+ artifact.command("rm <id>").description("delete an artifact").action(
2995
+ run(async (id) => {
2996
+ await deleteArtifact(id);
2997
+ console.log(`Deleted ${id}`);
2998
+ })
2999
+ );
2703
3000
  function routineLine(r) {
2704
3001
  const target = r.target.type === "session" ? `\u2192 ${r.target.session_id}` : `+ ${r.target.agent}`;
2705
3002
  const cron = r.schedule ? `${r.schedule.expression} ${r.schedule.timezone}` : "manual-only";
@@ -2870,4 +3167,5 @@ program.command("config").description("show the CLI config location and current
2870
3167
  console.log(` token: ${config.token ? `${config.token.slice(0, 10)}\u2026` : "(none)"}`);
2871
3168
  console.log(` universe: ${config.currentUniverse ?? "(personal)"}`);
2872
3169
  });
2873
- program.parseAsync().catch(fail);
3170
+ var ARGUMENTS_FOLLOW_THE_SCRIPT_PATH_ON_EVERY_RUNTIME = { from: "node" };
3171
+ program.parseAsync(process.argv, ARGUMENTS_FOLLOW_THE_SCRIPT_PATH_ON_EVERY_RUNTIME).catch(fail);
package/dist/products.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  skillsArraySchema,
9
9
  systemMessageEventSchema,
10
10
  userMessageEventSchema
11
- } from "./chunk-IC4N2ZPL.js";
11
+ } from "./chunk-WFTZR5YO.js";
12
12
 
13
13
  // ../../packages/spec/src/compatibility.ts
14
14
  var capabilityInputsSchema = capabilitiesSchema;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  external_exports,
3
3
  messagePartSchema
4
- } from "./chunk-IC4N2ZPL.js";
4
+ } from "./chunk-WFTZR5YO.js";
5
5
 
6
6
  // ../../packages/chat/src/stream.ts
7
7
  async function* parseSseStream(body) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentsky/sky",
3
- "version": "2.7.2",
3
+ "version": "2.8.0",
4
4
  "description": "sky — the AgentSky developer CLI: launch and talk to long-lived agents from your terminal.",
5
5
  "license": "MIT",
6
6
  "type": "module",