@agentsky/sky 2.22.0 → 2.23.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-YMYQT6KR.js → chunk-HDPDY77W.js} +5 -5
- package/dist/{chunk-EBH3KXSU.js → chunk-HQPOCQRQ.js} +2 -2
- package/dist/{chunk-XT3W75V3.js → chunk-V5XLV37X.js} +1 -1
- package/dist/index.js +584 -52
- package/dist/{src-TGRDQ5XR.js → src-UMT6FHLG.js} +1 -1
- package/dist/{trace-PDIOL2TC.js → trace-ZRU624EY.js} +2 -2
- package/dist/{trace-library-TA3QUBHJ.js → trace-library-QOQUAL5H.js} +3 -3
- package/package.json +1 -1
|
@@ -18978,7 +18978,7 @@ var CATALOG_MODELS = [
|
|
|
18978
18978
|
"maxPromptTokens": 1048576,
|
|
18979
18979
|
"input": 0.09284,
|
|
18980
18980
|
"output": 0.58025,
|
|
18981
|
-
"cachedInput":
|
|
18981
|
+
"cachedInput": 9284e-6
|
|
18982
18982
|
}
|
|
18983
18983
|
],
|
|
18984
18984
|
"maxPrice": {
|
|
@@ -22372,7 +22372,7 @@ var ACP_AGENTS = {
|
|
|
22372
22372
|
"registryId": "grok-build",
|
|
22373
22373
|
"label": "Grok Build",
|
|
22374
22374
|
"description": "xAI's coding agent and CLI",
|
|
22375
|
-
"version": "1.0.
|
|
22375
|
+
"version": "1.0.70",
|
|
22376
22376
|
"website": "https://x.ai/cli"
|
|
22377
22377
|
},
|
|
22378
22378
|
"harn": {
|
|
@@ -22563,7 +22563,7 @@ var MINIMAX = ["minimax-m3", "minimax-m3.1-flash"];
|
|
|
22563
22563
|
var GEMINI = ["gemini-4-argon", "gemini-3.8-flash", "gemini-3.5-flash-lite"];
|
|
22564
22564
|
var CLAUDE_5_5 = ["claude-sonnet-5-5", "claude-haiku-5-5"];
|
|
22565
22565
|
var HARNESS_MODEL_ADDITIONS = {
|
|
22566
|
-
claude_code: [{ models: CLAUDE_5_5, releases: ["2.1.295", "2.1.296", "2.1.303"] }, {
|
|
22566
|
+
claude_code: [{ models: CLAUDE_5_5, releases: ["2.1.295", "2.1.296", "2.1.303", "2.1.310"] }, {
|
|
22567
22567
|
models: [
|
|
22568
22568
|
"gpt-6.1-sol",
|
|
22569
22569
|
"gpt-6-sol",
|
|
@@ -22585,7 +22585,7 @@ var HARNESS_MODEL_ADDITIONS = {
|
|
|
22585
22585
|
...MINIMAX,
|
|
22586
22586
|
...CATALOG_IDS
|
|
22587
22587
|
],
|
|
22588
|
-
releases: ["2.1.303"]
|
|
22588
|
+
releases: ["2.1.303", "2.1.310"]
|
|
22589
22589
|
}],
|
|
22590
22590
|
codex: [{ models: [...CLAUDE_5_5, ...GEMINI, "grok-4.7", ...MUSE, ...MINIMAX, ...CATALOG_IDS], releases: ["0.163.0"] }],
|
|
22591
22591
|
hermes: [
|
|
@@ -22606,7 +22606,7 @@ var HARNESS_MODEL_ADDITIONS = {
|
|
|
22606
22606
|
kilo: [{ models: ["grok-4.7"], releases: ["7.8.8", "7.8.12", "7.8.15", "7.8.17"] }, { models: ["claude-sonnet-5-5", "claude-haiku-5-5"], releases: ["7.8.8", "7.8.12", "7.8.15", "7.8.17"] }],
|
|
22607
22607
|
docker_cagent: [{ 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"] }],
|
|
22608
22608
|
cline: [{ models: ["grok-4.7"], releases: ["3.0.70", "3.0.73"] }],
|
|
22609
|
-
grok_build: [{ models: ["grok-4.7"], releases: ["1.0.50", "1.0.62", "1.0.67"] }],
|
|
22609
|
+
grok_build: [{ models: ["grok-4.7"], releases: ["1.0.50", "1.0.62", "1.0.67", "1.0.70"] }],
|
|
22610
22610
|
mistral_vibe: [{ models: ["grok-4.7"], releases: ["2.26.1"] }],
|
|
22611
22611
|
sigit: [{ models: ["grok-4.7"], releases: ["1.6.5", "1.7.2", "1.7.3", "1.7.4"] }],
|
|
22612
22612
|
cursor: [{ models: ["kimi-k2.7-code"], releases: ["2026.10.01"] }],
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
apiBase,
|
|
4
4
|
apiToken,
|
|
5
5
|
currentUniverse
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-V5XLV37X.js";
|
|
7
7
|
|
|
8
8
|
// src/api.ts
|
|
9
9
|
import { createWriteStream, writeFileSync } from "fs";
|
|
@@ -145,7 +145,7 @@ async function resolveSessionRef(ref) {
|
|
|
145
145
|
return agent.defaultSessionId;
|
|
146
146
|
}
|
|
147
147
|
async function* streamEvents(sessionId, signal) {
|
|
148
|
-
const { parseSseStream } = await import("./src-
|
|
148
|
+
const { parseSseStream } = await import("./src-UMT6FHLG.js");
|
|
149
149
|
const res = await fetch(
|
|
150
150
|
`${apiBase()}/sessions/${encodeURIComponent(sessionId)}/stream`,
|
|
151
151
|
{
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
resolveSessionRef,
|
|
10
10
|
streamEvents,
|
|
11
11
|
uploadFile
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HQPOCQRQ.js";
|
|
13
13
|
import {
|
|
14
14
|
CLI_VERSION,
|
|
15
15
|
USER_AGENT,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
currentUniverse,
|
|
21
21
|
loadConfig,
|
|
22
22
|
saveConfig
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-V5XLV37X.js";
|
|
24
24
|
import {
|
|
25
25
|
AGENT_TYPES,
|
|
26
26
|
MODEL_SUBSCRIPTION_PLAN_PHRASE,
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
skillRefSchema,
|
|
43
43
|
splitMcpServers,
|
|
44
44
|
supersededBy
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-HDPDY77W.js";
|
|
46
46
|
import "./chunk-MLKGABMK.js";
|
|
47
47
|
|
|
48
48
|
// src/index.ts
|
|
@@ -410,6 +410,52 @@ function renderApiKey(key) {
|
|
|
410
410
|
return `${key.id} ${key.token_prefix}\u2026 ${key.status.padEnd(7)} ${key.scopes.join(",").padEnd(16)} ${where} ${used} ${key.name}${key.current ? " (this key)" : ""}`;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
+
// src/account-access.ts
|
|
414
|
+
function linkToken(ref) {
|
|
415
|
+
const fromUrl = /\/s\/([A-Za-z0-9_-]+)\/?(?:[?#].*)?$/.exec(ref.trim());
|
|
416
|
+
const token = fromUrl ? fromUrl[1] : ref.trim();
|
|
417
|
+
if (!/^[A-Za-z0-9_-]{16,64}$/.test(token)) throw new ApiError(400, "invalid_request", "a share link is a /s/<token> URL or its token");
|
|
418
|
+
return token;
|
|
419
|
+
}
|
|
420
|
+
async function sendViaLink(ref, text, idempotencyKey) {
|
|
421
|
+
await api("POST", `/links/${encodeURIComponent(linkToken(ref))}/messages`, { text }, { idempotencyKey });
|
|
422
|
+
}
|
|
423
|
+
async function stopViaLink(ref) {
|
|
424
|
+
await api("POST", `/links/${encodeURIComponent(linkToken(ref))}/interrupt`);
|
|
425
|
+
}
|
|
426
|
+
function inviteCode(ref) {
|
|
427
|
+
const fromUrl = /\/i\/([^/?#]+)\/?(?:[?#].*)?$/.exec(ref.trim());
|
|
428
|
+
const code = fromUrl ? decodeURIComponent(fromUrl[1]) : ref.trim();
|
|
429
|
+
if (!code) throw new ApiError(400, "invalid_request", "a credit invite is an /i/<code> URL or its code");
|
|
430
|
+
return code;
|
|
431
|
+
}
|
|
432
|
+
async function claimCreditInvite(ref) {
|
|
433
|
+
return api("POST", "/billing/credit-invites/claim", { code: inviteCode(ref) });
|
|
434
|
+
}
|
|
435
|
+
function renderCreditInviteClaim(claim) {
|
|
436
|
+
const amount = `$${claim.amount_usd.toFixed(2)}`;
|
|
437
|
+
return claim.status === "granted" ? `Added ${amount} of credit to your balance` : `Already claimed: this link added ${amount} to your balance`;
|
|
438
|
+
}
|
|
439
|
+
async function listAppGrants() {
|
|
440
|
+
return (await api("GET", "/oauth_grants")).oauth_grants;
|
|
441
|
+
}
|
|
442
|
+
async function revokeAppGrant(clientId) {
|
|
443
|
+
await api("DELETE", `/oauth_grants/${encodeURIComponent(clientId)}`);
|
|
444
|
+
}
|
|
445
|
+
function renderAppGrant(grant) {
|
|
446
|
+
const since = grant.allowed_at ? ` since ${grant.allowed_at.slice(0, 10)}` : "";
|
|
447
|
+
const review = grant.review_status === "approved" ? "" : " (unreviewed)";
|
|
448
|
+
return `${grant.client_id} ${grant.name || "(unnamed)"} ${grant.scopes.join(" ")}${since}${review}`;
|
|
449
|
+
}
|
|
450
|
+
async function unsubscribeMarketing() {
|
|
451
|
+
const { notification_preferences } = await api(
|
|
452
|
+
"PATCH",
|
|
453
|
+
"/notification-preferences",
|
|
454
|
+
{ email: { marketing: false } }
|
|
455
|
+
);
|
|
456
|
+
return { marketing: notification_preferences.email.marketing };
|
|
457
|
+
}
|
|
458
|
+
|
|
413
459
|
// src/context.ts
|
|
414
460
|
function memoryBody(operation, version) {
|
|
415
461
|
return { ...operation, expectedVersion: version };
|
|
@@ -682,9 +728,9 @@ function readClaudeCode() {
|
|
|
682
728
|
sources.push("global CLAUDE.md");
|
|
683
729
|
}
|
|
684
730
|
for (const name of ["CLAUDE.md", "AGENTS.md"]) {
|
|
685
|
-
const
|
|
686
|
-
if (
|
|
687
|
-
parts.push({ label: `Project ${name}`, content:
|
|
731
|
+
const project2 = readIfExists(join3(process.cwd(), name));
|
|
732
|
+
if (project2?.trim()) {
|
|
733
|
+
parts.push({ label: `Project ${name}`, content: project2 });
|
|
688
734
|
sources.push(`project ${name}`);
|
|
689
735
|
break;
|
|
690
736
|
}
|
|
@@ -739,11 +785,11 @@ function linkPath(configRoot) {
|
|
|
739
785
|
return join3(configRoot, "agentsky-link.json");
|
|
740
786
|
}
|
|
741
787
|
function readLink(configRoot) {
|
|
742
|
-
const
|
|
743
|
-
return
|
|
788
|
+
const link2 = readJson(linkPath(configRoot));
|
|
789
|
+
return link2?.agentId ? link2 : void 0;
|
|
744
790
|
}
|
|
745
|
-
function writeLink(configRoot,
|
|
746
|
-
writeFileSync3(linkPath(configRoot), `${JSON.stringify(
|
|
791
|
+
function writeLink(configRoot, link2) {
|
|
792
|
+
writeFileSync3(linkPath(configRoot), `${JSON.stringify(link2, null, 2)}
|
|
747
793
|
`);
|
|
748
794
|
}
|
|
749
795
|
var DEFAULT_VAULT_NAME = "default";
|
|
@@ -909,14 +955,14 @@ async function createClone(local, opts) {
|
|
|
909
955
|
await confirmAndVaultSecrets(local.secretCandidates, opts.yes ?? false);
|
|
910
956
|
if (opts.open) openBrowser(url);
|
|
911
957
|
}
|
|
912
|
-
async function syncClone(local,
|
|
913
|
-
const since =
|
|
958
|
+
async function syncClone(local, link2, opts) {
|
|
959
|
+
const since = link2.lastSyncedAt ?? link2.clonedAt;
|
|
914
960
|
console.log(
|
|
915
|
-
`Syncing ${
|
|
961
|
+
`Syncing ${link2.agentId} from ${local.configRoot} (last synced ${since ? new Date(since).toLocaleDateString() : "never"})`
|
|
916
962
|
);
|
|
917
963
|
if (opts.dryRun) {
|
|
918
964
|
console.log(
|
|
919
|
-
` would push prompt (${kb(local.prompt)}) to ${
|
|
965
|
+
` would push prompt (${kb(local.prompt)}) to ${link2.agentId}. Dry run \u2014 nothing sent.`
|
|
920
966
|
);
|
|
921
967
|
return;
|
|
922
968
|
}
|
|
@@ -924,24 +970,24 @@ async function syncClone(local, link, opts) {
|
|
|
924
970
|
try {
|
|
925
971
|
({ agent: agent2 } = await api(
|
|
926
972
|
"GET",
|
|
927
|
-
`/agents/${encodeURIComponent(
|
|
973
|
+
`/agents/${encodeURIComponent(link2.agentId)}`
|
|
928
974
|
));
|
|
929
975
|
} catch (error) {
|
|
930
976
|
if (error instanceof ApiError && error.status === 404) {
|
|
931
977
|
throw new Error(
|
|
932
|
-
`linked agent ${
|
|
978
|
+
`linked agent ${link2.agentId} no longer exists \u2014 run \`sky clone --new\` to launch a fresh one`
|
|
933
979
|
);
|
|
934
980
|
}
|
|
935
981
|
throw error;
|
|
936
982
|
}
|
|
937
983
|
if (agent2.agentType !== local.harness) {
|
|
938
984
|
throw new Error(
|
|
939
|
-
`linked agent ${
|
|
985
|
+
`linked agent ${link2.agentId} is ${agent2.agentType}, this machine runs ${local.harness} \u2014 run \`sky clone --new\` to launch a fresh agent`
|
|
940
986
|
);
|
|
941
987
|
}
|
|
942
988
|
const result = await api(
|
|
943
989
|
"PUT",
|
|
944
|
-
`/agents/${encodeURIComponent(
|
|
990
|
+
`/agents/${encodeURIComponent(link2.agentId)}/prompt`,
|
|
945
991
|
{ prompt: local.prompt }
|
|
946
992
|
);
|
|
947
993
|
console.log(
|
|
@@ -949,11 +995,11 @@ async function syncClone(local, link, opts) {
|
|
|
949
995
|
);
|
|
950
996
|
const drift = [];
|
|
951
997
|
const localModel = local.model ?? null;
|
|
952
|
-
const linkedModel =
|
|
998
|
+
const linkedModel = link2.llm ?? agent2.llm;
|
|
953
999
|
if (localModel && linkedModel && localModel !== linkedModel) {
|
|
954
1000
|
drift.push(`model changed ${linkedModel} \u2192 ${localModel}`);
|
|
955
1001
|
}
|
|
956
|
-
const before = new Set(
|
|
1002
|
+
const before = new Set(link2.mcpServers ?? []);
|
|
957
1003
|
const nowKept = Object.keys(local.keptServers);
|
|
958
1004
|
const newServers = nowKept.filter((n) => !before.has(n));
|
|
959
1005
|
const goneServers = [...before].filter((n) => !nowKept.includes(n));
|
|
@@ -968,16 +1014,16 @@ async function syncClone(local, link, opts) {
|
|
|
968
1014
|
` left out of clone (secret-bearing): ${local.droppedServers.map((d) => `${d.name} MCP`).join(", ")}`
|
|
969
1015
|
);
|
|
970
1016
|
}
|
|
971
|
-
writeLink(local.configRoot, { ...
|
|
972
|
-
console.log(`Synced ${
|
|
1017
|
+
writeLink(local.configRoot, { ...link2, lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1018
|
+
console.log(`Synced ${link2.agentId}.`);
|
|
973
1019
|
await confirmAndVaultSecrets(local.secretCandidates, opts.yes ?? false);
|
|
974
|
-
if (opts.open) openBrowser(`${apiBase()}/agents/${
|
|
1020
|
+
if (opts.open) openBrowser(`${apiBase()}/agents/${link2.agentId}`);
|
|
975
1021
|
}
|
|
976
1022
|
async function clone(opts) {
|
|
977
1023
|
const harness2 = detectHarness(opts.harness);
|
|
978
1024
|
const local = readLocal(harness2);
|
|
979
|
-
const
|
|
980
|
-
if (
|
|
1025
|
+
const link2 = opts.new ? void 0 : readLink(local.configRoot);
|
|
1026
|
+
if (link2) await syncClone(local, link2, opts);
|
|
981
1027
|
else await createClone(local, opts);
|
|
982
1028
|
}
|
|
983
1029
|
|
|
@@ -1000,7 +1046,7 @@ import { homedir as homedir2 } from "os";
|
|
|
1000
1046
|
import { basename as basename4, dirname as dirname3, join as join4, relative, sep } from "path";
|
|
1001
1047
|
import { parse as parseToml2 } from "smol-toml";
|
|
1002
1048
|
var MAX_TREE = 5e3;
|
|
1003
|
-
var SKILL_LINE = /Base directory for this skill: (\/[^\
|
|
1049
|
+
var SKILL_LINE = /Base directory for this skill: (\/[^\n\r"'\\<>]+)/g;
|
|
1004
1050
|
function git(cwd, ...args) {
|
|
1005
1051
|
const run2 = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf8", timeout: 1e4, maxBuffer: 32 * 1024 * 1024 });
|
|
1006
1052
|
return run2.status === 0 ? run2.stdout : null;
|
|
@@ -1046,8 +1092,7 @@ function skillRoots(cwd, home) {
|
|
|
1046
1092
|
];
|
|
1047
1093
|
}
|
|
1048
1094
|
function pluginSkill(plugin, skill, home) {
|
|
1049
|
-
const
|
|
1050
|
-
const walk = (dir, depth) => {
|
|
1095
|
+
const walk = (dir, depth, underPlugin) => {
|
|
1051
1096
|
if (depth > 7) return null;
|
|
1052
1097
|
let entries;
|
|
1053
1098
|
try {
|
|
@@ -1058,13 +1103,13 @@ function pluginSkill(plugin, skill, home) {
|
|
|
1058
1103
|
for (const entry2 of entries) {
|
|
1059
1104
|
if (!entry2.isDirectory() || entry2.name === "node_modules" || entry2.name === ".git") continue;
|
|
1060
1105
|
const path = join4(dir, entry2.name);
|
|
1061
|
-
if (entry2.name === skill && basename4(dir) === "skills" && path.includes(`${sep}${plugin}${sep}`) && isFile(join4(path, "SKILL.md"))) return path;
|
|
1062
|
-
const found = walk(path, depth + 1);
|
|
1106
|
+
if (entry2.name === skill && basename4(dir) === "skills" && (underPlugin || path.includes(`${sep}${plugin}${sep}`)) && isFile(join4(path, "SKILL.md"))) return realpathSync(path);
|
|
1107
|
+
const found = walk(path, depth + 1, underPlugin);
|
|
1063
1108
|
if (found) return found;
|
|
1064
1109
|
}
|
|
1065
1110
|
return null;
|
|
1066
1111
|
};
|
|
1067
|
-
return walk(
|
|
1112
|
+
return walk(join4(process.env.CLAUDE_CONFIG_DIR ?? join4(home, ".claude"), "plugins"), 0, false) ?? walk(join4(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions", "skills-plugin"), 0, true);
|
|
1068
1113
|
}
|
|
1069
1114
|
function findSkill(name, cwd, home) {
|
|
1070
1115
|
const [scope, skill] = name.includes(":") ? name.split(":", 2) : [null, name];
|
|
@@ -1084,23 +1129,24 @@ function loadedSkills(records, touched, cwd, home = homedir2()) {
|
|
|
1084
1129
|
if (![...dirs.values()].includes(real)) dirs.set(name, real);
|
|
1085
1130
|
return true;
|
|
1086
1131
|
};
|
|
1132
|
+
const called = [];
|
|
1087
1133
|
for (const record of records) {
|
|
1088
1134
|
const texts = [];
|
|
1089
1135
|
strings(record, texts);
|
|
1090
|
-
for (const text of texts) for (const match of text.matchAll(SKILL_LINE)) add(match[1].replace(/[.,;:)]+$/, ""));
|
|
1136
|
+
for (const text of texts) for (const match of text.matchAll(SKILL_LINE)) add(match[1].trim().replace(/[.,;:)]+$/, ""));
|
|
1091
1137
|
const content = record?.message?.content;
|
|
1092
1138
|
if (!Array.isArray(content)) continue;
|
|
1093
1139
|
for (const block of content) {
|
|
1094
1140
|
const b = block;
|
|
1095
|
-
if (b?.type
|
|
1096
|
-
const name = b.input.skill.replace(/^\//, "");
|
|
1097
|
-
if (!name || dirs.has(name) || [...dirs.keys()].some((key) => key.endsWith(`:${name}`) || name.endsWith(`:${key}`))) continue;
|
|
1098
|
-
const dir = findSkill(name, cwd, home);
|
|
1099
|
-
if (!dir || !add(dir, name)) missing.add(name);
|
|
1141
|
+
if (b?.type === "tool_use" && b.name === "Skill" && typeof b.input?.skill === "string") called.push(b.input.skill.replace(/^\//, ""));
|
|
1100
1142
|
}
|
|
1101
1143
|
}
|
|
1102
1144
|
for (const path of touched) if (basename4(path) === "SKILL.md") add(dirname3(path));
|
|
1103
|
-
for (const name of
|
|
1145
|
+
for (const name of called) {
|
|
1146
|
+
if (!name || dirs.has(name) || [...dirs.keys()].some((key) => key.endsWith(`:${name}`) || name.endsWith(`:${key}`))) continue;
|
|
1147
|
+
const dir = findSkill(name, cwd, home);
|
|
1148
|
+
if (!dir || !add(dir, name)) missing.add(name);
|
|
1149
|
+
}
|
|
1104
1150
|
return { found: [...dirs].map(([name, dir]) => ({ name: name.replace(/[^A-Za-z0-9._:-]/g, "-"), dir })), missing: [...missing] };
|
|
1105
1151
|
}
|
|
1106
1152
|
function readJson2(path) {
|
|
@@ -4961,6 +5007,44 @@ function renderBrowserProfile(profile) {
|
|
|
4961
5007
|
return lines.join("\n");
|
|
4962
5008
|
}
|
|
4963
5009
|
|
|
5010
|
+
// src/mac.ts
|
|
5011
|
+
var REACH_KINDS = ["folder", "browser", "screen", "host"];
|
|
5012
|
+
var OPEN = /* @__PURE__ */ new Set(["pending", "asking"]);
|
|
5013
|
+
var MAX_WAIT_SECONDS = 25;
|
|
5014
|
+
async function listMacs() {
|
|
5015
|
+
return (await api("GET", "/desktop/machines")).machines;
|
|
5016
|
+
}
|
|
5017
|
+
async function askMac(machine, kind, reason) {
|
|
5018
|
+
if (!REACH_KINDS.includes(kind)) throw new Error(`kind must be one of ${REACH_KINDS.join(", ")}`);
|
|
5019
|
+
return api("POST", `/desktop/machines/${encodeURIComponent(machine)}/reach-requests`, { kind, reason });
|
|
5020
|
+
}
|
|
5021
|
+
async function readReachRequest(id, waitSeconds = 0) {
|
|
5022
|
+
const wait = Math.min(Math.max(Math.floor(waitSeconds), 0), MAX_WAIT_SECONDS);
|
|
5023
|
+
return (await api("GET", `/desktop/reach-requests/${encodeURIComponent(id)}${wait ? `?wait=${wait}` : ""}`)).reach_request;
|
|
5024
|
+
}
|
|
5025
|
+
async function waitForAnswer(id, budgetSeconds) {
|
|
5026
|
+
const until = Date.now() + budgetSeconds * 1e3;
|
|
5027
|
+
for (; ; ) {
|
|
5028
|
+
const left = Math.ceil((until - Date.now()) / 1e3);
|
|
5029
|
+
const request = await readReachRequest(id, Math.max(left, 0));
|
|
5030
|
+
if (!OPEN.has(request.status) || left <= 0) return request;
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
async function takeBack(mount) {
|
|
5034
|
+
await api("DELETE", `/desktop/mounts/${encodeURIComponent(mount)}`);
|
|
5035
|
+
}
|
|
5036
|
+
function renderMac(mac2) {
|
|
5037
|
+
const lends = mac2.reach ? mac2.reach.kinds.join(", ") || "nothing" : "unknown (update the Mac app)";
|
|
5038
|
+
const screen = mac2.reach && !mac2.reach.kinds.includes("screen") ? ` screen: ${mac2.reach.screen}` : "";
|
|
5039
|
+
const lines = [`${mac2.id} ${mac2.name} ${mac2.online ? "online" : "offline"} can lend: ${lends}${screen}`];
|
|
5040
|
+
for (const mount of mac2.mounts ?? []) lines.push(` ${mount.id} ${mount.kind.padEnd(7)} ${mount.root ?? mount.label}`);
|
|
5041
|
+
return lines.join("\n");
|
|
5042
|
+
}
|
|
5043
|
+
function renderReachRequest(request) {
|
|
5044
|
+
if (request.status === "granted" && request.mount) return `${request.id} granted ${request.mount.id} (${request.mount.kind}${request.mount.root ? ` ${request.mount.root}` : ""})`;
|
|
5045
|
+
return `${request.id} ${request.status}${request.error ? ` ${request.error.code}: ${request.error.message}` : ""}`;
|
|
5046
|
+
}
|
|
5047
|
+
|
|
4964
5048
|
// src/compare.ts
|
|
4965
5049
|
async function listComparisons(opts = {}) {
|
|
4966
5050
|
const qs = opts.archived ? "?archived=true" : "";
|
|
@@ -4981,6 +5065,53 @@ async function listThreads2(opts = {}) {
|
|
|
4981
5065
|
const { threads } = await api("GET", `/threads${qs}`);
|
|
4982
5066
|
return threads;
|
|
4983
5067
|
}
|
|
5068
|
+
async function startThread(body) {
|
|
5069
|
+
return api("POST", "/threads", body);
|
|
5070
|
+
}
|
|
5071
|
+
var threadPath = (id) => `/threads/${encodeURIComponent(id)}`;
|
|
5072
|
+
async function getThread(id) {
|
|
5073
|
+
return api("GET", threadPath(id));
|
|
5074
|
+
}
|
|
5075
|
+
async function organizeThread(id, change) {
|
|
5076
|
+
return api("PATCH", threadPath(id), change);
|
|
5077
|
+
}
|
|
5078
|
+
async function deleteThread(id) {
|
|
5079
|
+
return api("DELETE", threadPath(id));
|
|
5080
|
+
}
|
|
5081
|
+
async function sendThreadMessage(id, body) {
|
|
5082
|
+
return api("POST", `${threadPath(id)}/messages`, body);
|
|
5083
|
+
}
|
|
5084
|
+
async function addThreadAgent(id, body) {
|
|
5085
|
+
return api("POST", `${threadPath(id)}/agents`, body);
|
|
5086
|
+
}
|
|
5087
|
+
async function removeThreadAgent(id, columnId) {
|
|
5088
|
+
return api("DELETE", `${threadPath(id)}/agents/${encodeURIComponent(columnId)}`);
|
|
5089
|
+
}
|
|
5090
|
+
async function interruptThread(id, columnId) {
|
|
5091
|
+
return api("POST", `${threadPath(id)}/interrupt`, columnId ? { columnId } : {});
|
|
5092
|
+
}
|
|
5093
|
+
async function forkThread(id, body) {
|
|
5094
|
+
return api("POST", `${threadPath(id)}/fork`, body);
|
|
5095
|
+
}
|
|
5096
|
+
async function changeThreadModel(id, change, columnId) {
|
|
5097
|
+
return api("PATCH", `${threadPath(id)}/engine${columnId ? `?column=${encodeURIComponent(columnId)}` : ""}`, change);
|
|
5098
|
+
}
|
|
5099
|
+
async function searchThreads(q, opts = {}) {
|
|
5100
|
+
const params = new URLSearchParams({ q, ...opts.threads ? { threads: opts.threads } : {}, ...opts.cursor ? { cursor: opts.cursor } : {} });
|
|
5101
|
+
return api("GET", `/threads/search?${params}`);
|
|
5102
|
+
}
|
|
5103
|
+
async function threadOptions() {
|
|
5104
|
+
return api("GET", "/threads/options");
|
|
5105
|
+
}
|
|
5106
|
+
async function joinThread(sessionId) {
|
|
5107
|
+
return api("POST", "/threads/joinable", { sessionId });
|
|
5108
|
+
}
|
|
5109
|
+
async function listProjects() {
|
|
5110
|
+
return api("GET", "/projects");
|
|
5111
|
+
}
|
|
5112
|
+
async function rememberProject(project2) {
|
|
5113
|
+
return api("PUT", "/projects", { project: project2 });
|
|
5114
|
+
}
|
|
4984
5115
|
function renderComparisonSummary(c) {
|
|
4985
5116
|
const agents = c.agents.map((a) => `${a.agentType}/${a.llm}`).join(" vs ");
|
|
4986
5117
|
const status = c.statusLine ?? c.attention ?? (c.archived ? "archived" : "active");
|
|
@@ -4993,6 +5124,115 @@ function renderThreadSummary(t) {
|
|
|
4993
5124
|
return `${t.id.slice(0, 12)} ${flag}${t.title.slice(0, 40).padEnd(44)} [${agents}] ${status}`;
|
|
4994
5125
|
}
|
|
4995
5126
|
|
|
5127
|
+
// src/library.ts
|
|
5128
|
+
var artifactPath = (id) => `/library/artifacts/${encodeURIComponent(id)}`;
|
|
5129
|
+
async function listLibrary(query = {}) {
|
|
5130
|
+
const params = new URLSearchParams(Object.entries(query).filter((entry2) => Boolean(entry2[1])));
|
|
5131
|
+
const qs = params.size ? `?${params}` : "";
|
|
5132
|
+
return api("GET", `/library/artifacts${qs}`);
|
|
5133
|
+
}
|
|
5134
|
+
async function uploadToLibrary(file, requestId, workspace2) {
|
|
5135
|
+
const form = new FormData();
|
|
5136
|
+
form.append("file", new Blob([new Uint8Array(file.bytes)], { type: file.mediaType }), file.name);
|
|
5137
|
+
form.append("requestId", requestId);
|
|
5138
|
+
if (workspace2) form.append("workspace", workspace2);
|
|
5139
|
+
return apiForm("POST", "/library/artifacts", form);
|
|
5140
|
+
}
|
|
5141
|
+
async function getLibraryArtifact(id) {
|
|
5142
|
+
return api("GET", artifactPath(id));
|
|
5143
|
+
}
|
|
5144
|
+
async function deleteLibraryArtifact(id, revision) {
|
|
5145
|
+
return api("DELETE", artifactPath(id), { revision });
|
|
5146
|
+
}
|
|
5147
|
+
async function shareLibraryArtifact(id, enabled) {
|
|
5148
|
+
const { currentVersion } = await getLibraryArtifact(id);
|
|
5149
|
+
return api("PATCH", `${artifactPath(id)}/share`, { enabled, revision: currentVersion });
|
|
5150
|
+
}
|
|
5151
|
+
async function placeLibraryArtifact(id, workspace2) {
|
|
5152
|
+
return api("PATCH", `${artifactPath(id)}/workspace`, { workspace: workspace2 });
|
|
5153
|
+
}
|
|
5154
|
+
async function downloadLibraryArtifact(id, version) {
|
|
5155
|
+
return apiBytes("GET", `${artifactPath(id)}/download${version ? `?version=${version}` : ""}`);
|
|
5156
|
+
}
|
|
5157
|
+
function renderLibraryArtifact(artifact2) {
|
|
5158
|
+
const version = artifact2.currentVersion ? `v${artifact2.currentVersion}` : "";
|
|
5159
|
+
return `${artifact2.id} ${artifact2.name} ${version}${artifact2.shared ? " shared" : ""}`;
|
|
5160
|
+
}
|
|
5161
|
+
|
|
5162
|
+
// src/billing-plans.ts
|
|
5163
|
+
var readCodingPlan = () => api("GET", "/billing/coding-plan");
|
|
5164
|
+
function joinCodingPlan(dollars2, requestId) {
|
|
5165
|
+
const amount = Number(dollars2.trim().replace(/^\$/, ""));
|
|
5166
|
+
if (!Number.isInteger(amount) || amount <= 0) throw new Error(`<dollars> must be whole dollars, got ${JSON.stringify(dollars2)}`);
|
|
5167
|
+
return api("POST", "/billing/coding-plan", { amount_usd: amount, request_id: requestId });
|
|
5168
|
+
}
|
|
5169
|
+
var cancelCodingPlan = () => api("DELETE", "/billing/coding-plan");
|
|
5170
|
+
function renderCodingPlan(plan) {
|
|
5171
|
+
if (!plan.active) {
|
|
5172
|
+
const lines2 = [`coding plan: not a member (enrollment ${plan.enrollment}; monthly amounts $${plan.amounts_usd.join(", $")})`];
|
|
5173
|
+
if (plan.charge_failure) lines2.push(` last charge failed: ${plan.charge_failure}`);
|
|
5174
|
+
return lines2.join("\n");
|
|
5175
|
+
}
|
|
5176
|
+
const until = plan.current_period_end?.slice(0, 10) ?? "?";
|
|
5177
|
+
const lines = [`coding plan: $${plan.monthly_credit_usd}/month, paid until ${until}, ${plan.renews ? "renews" : "does not renew"}`];
|
|
5178
|
+
if (plan.charge_failure) lines.push(` last charge failed: ${plan.charge_failure}`);
|
|
5179
|
+
return lines.join("\n");
|
|
5180
|
+
}
|
|
5181
|
+
function readRequestUsage(opts) {
|
|
5182
|
+
const query = usageQuery(opts);
|
|
5183
|
+
const cursor = opts.cursor ? `${query ? "&" : "?"}cursor=${encodeURIComponent(opts.cursor)}` : "";
|
|
5184
|
+
return api("GET", `/billing/usage/requests${query}${cursor}`);
|
|
5185
|
+
}
|
|
5186
|
+
function renderRequestUsage(page) {
|
|
5187
|
+
const lines = page.rows.map((row) => `${row.at.slice(0, 19).replace("T", " ")} ${(row.apiKeyName ?? "").padEnd(16).slice(0, 16)} ${(row.model ?? "-").padEnd(28).slice(0, 28)} ${String(row.httpStatus ?? "-").padStart(3)} ${String(row.inputTokens ?? 0).padStart(9)} in ${String(row.outputTokens ?? 0).padStart(8)} out ${`$${(row.billedCostUsd ?? 0).toFixed(6)}`.padStart(11)}`);
|
|
5188
|
+
if (!lines.length) lines.push("no API requests in this range");
|
|
5189
|
+
if (page.nextCursor) lines.push(`more: --cursor ${page.nextCursor}`);
|
|
5190
|
+
return lines.join("\n");
|
|
5191
|
+
}
|
|
5192
|
+
var readReferralLinks = () => api("GET", "/billing/referral-links");
|
|
5193
|
+
function referralLinkBody(opts) {
|
|
5194
|
+
if (opts.price === void 0 === !opts.sku?.length) throw new Error("pass --price for every model, or --sku id=multiplier for each SKU, not both");
|
|
5195
|
+
const body = {};
|
|
5196
|
+
if (opts.price !== void 0) body.customer_multiplier = multiplier("--price", opts.price);
|
|
5197
|
+
if (opts.sku?.length) {
|
|
5198
|
+
body.sku_prices = opts.sku.map((pair) => {
|
|
5199
|
+
const at = pair.lastIndexOf("=");
|
|
5200
|
+
if (at <= 0) throw new Error(`--sku must be id=multiplier, got ${JSON.stringify(pair)}`);
|
|
5201
|
+
return { sku_id: pair.slice(0, at), multiplier: multiplier("--sku", pair.slice(at + 1)) };
|
|
5202
|
+
});
|
|
5203
|
+
}
|
|
5204
|
+
if (opts.email) body.audience_email = opts.email;
|
|
5205
|
+
if (opts.uses) body.max_redemptions = wholeNumber2("--uses", opts.uses);
|
|
5206
|
+
if (opts.days) body.expires_in_days = wholeNumber2("--days", opts.days);
|
|
5207
|
+
return body;
|
|
5208
|
+
}
|
|
5209
|
+
var createReferralLink = (opts) => api("POST", "/billing/referral-links", referralLinkBody(opts));
|
|
5210
|
+
var disableReferralLink = (id) => api("POST", `/billing/referral-links/${encodeURIComponent(id)}/disable`);
|
|
5211
|
+
function renderReferralLinks(dashboard) {
|
|
5212
|
+
const lines = [`priced from ${dashboard.source_plan.name}: customers pay at least ${Math.round(dashboard.source_plan.multiplier * 100)}% of public price`];
|
|
5213
|
+
for (const link2 of dashboard.links) {
|
|
5214
|
+
const state = link2.disabled_at ? "disabled" : `expires ${link2.expires_at.slice(0, 10)}`;
|
|
5215
|
+
const audience = link2.audience_email ? ` for ${link2.audience_email} (${link2.email_status})` : "";
|
|
5216
|
+
lines.push(` ${link2.id} ${Math.round(link2.customer_multiplier * 100)}% ${link2.redeemed_count}/${link2.max_redemptions} used ${state}${audience}`);
|
|
5217
|
+
lines.push(` ${link2.url}`);
|
|
5218
|
+
}
|
|
5219
|
+
if (!dashboard.links.length) lines.push(" no links yet");
|
|
5220
|
+
const earned = dashboard.earnings.reduce((sum, earning) => sum + earning.amount_usd, 0);
|
|
5221
|
+
lines.push(`earned $${earned.toFixed(2)} from ${dashboard.earnings.length} customer${dashboard.earnings.length === 1 ? "" : "s"}`);
|
|
5222
|
+
return lines.join("\n");
|
|
5223
|
+
}
|
|
5224
|
+
function multiplier(flag, value) {
|
|
5225
|
+
const trimmed = value.trim();
|
|
5226
|
+
const percent = trimmed.endsWith("%");
|
|
5227
|
+
const number = Number(percent ? trimmed.slice(0, -1) : trimmed);
|
|
5228
|
+
if (!Number.isFinite(number) || number <= 0) throw new Error(`${flag} must be a share of public price like 0.8 or 80%, got ${JSON.stringify(value)}`);
|
|
5229
|
+
return percent ? number / 100 : number;
|
|
5230
|
+
}
|
|
5231
|
+
function wholeNumber2(flag, value) {
|
|
5232
|
+
if (!/^\d+$/.test(value.trim())) throw new Error(`${flag} must be a whole number, got ${JSON.stringify(value)}`);
|
|
5233
|
+
return Number(value.trim());
|
|
5234
|
+
}
|
|
5235
|
+
|
|
4996
5236
|
// src/harness.ts
|
|
4997
5237
|
import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "fs";
|
|
4998
5238
|
import { dirname as dirname9, join as join18, resolve as resolve8 } from "path";
|
|
@@ -5231,6 +5471,19 @@ auth.command("usage <provider>").description("plan allowance left on a connected
|
|
|
5231
5471
|
auth.command("switch-to-credits <provider>").description("move the agents on a model subscription onto platform credits (do this before disconnecting)").option("--account <id>", "an additional account (default: the provider's first account)").option("-y, --yes", "skip the confirmation prompt").action(run(async (name, opts) => switchToCredits(name, opts)));
|
|
5232
5472
|
auth.command("accounts").description("list connected model subscriptions and the agents they power").action(run(async () => listSubscriptions()));
|
|
5233
5473
|
auth.command("disconnect <provider>").description("disconnect a model subscription (agents on it fail until switched)").option("-y, --yes", "skip the confirmation prompt").action(run(async (name, opts) => disconnect(name, opts)));
|
|
5474
|
+
auth.command("apps").description("the registered apps you let into your account, with the scopes you allowed").action(
|
|
5475
|
+
run(async () => {
|
|
5476
|
+
const grants = await listAppGrants();
|
|
5477
|
+
if (!grants.length) console.log("No apps have access to your account.");
|
|
5478
|
+
for (const grant of grants) console.log(renderAppGrant(grant));
|
|
5479
|
+
})
|
|
5480
|
+
);
|
|
5481
|
+
auth.command("revoke-app <clientId>").description("remove an app's access to your account; its tokens stop working at once (admin scope)").action(
|
|
5482
|
+
run(async (clientId) => {
|
|
5483
|
+
await revokeAppGrant(clientId);
|
|
5484
|
+
console.log(`Removed ${clientId}'s access to your account`);
|
|
5485
|
+
})
|
|
5486
|
+
);
|
|
5234
5487
|
var universe = program.command("universe").description("grouping boundary for agents");
|
|
5235
5488
|
universe.command("list").action(
|
|
5236
5489
|
run(async () => {
|
|
@@ -5277,7 +5530,7 @@ universe.command("invite <emails...>").description("invite people by email; prin
|
|
|
5277
5530
|
run(async (emails, opts) => {
|
|
5278
5531
|
const result = await invite(await workspaceSlug(opts.universe), emails, opts);
|
|
5279
5532
|
for (const i of result.invites) console.log(`invited ${i.email} as ${i.role} ${i.id}`);
|
|
5280
|
-
for (const
|
|
5533
|
+
for (const link2 of result.links) console.log(` ${link2.email} joins with: sky universe join ${link2.token}`);
|
|
5281
5534
|
if (!result.invites.length) console.log("nobody new to invite \u2014 everyone listed is already a member");
|
|
5282
5535
|
})
|
|
5283
5536
|
);
|
|
@@ -5594,12 +5847,12 @@ session.command("share <ref>").description("print the session's share link, turn
|
|
|
5594
5847
|
console.log(`Sharing is off for ${id}`);
|
|
5595
5848
|
return;
|
|
5596
5849
|
}
|
|
5597
|
-
const
|
|
5850
|
+
const link2 = await api("POST", path, {
|
|
5598
5851
|
access: opts.view ? "view" : "prompt",
|
|
5599
5852
|
...opts.rotate ? { rotate: true } : {}
|
|
5600
5853
|
});
|
|
5601
|
-
if (
|
|
5602
|
-
else console.log(`view-only token: ${
|
|
5854
|
+
if (link2.shareUrl) console.log(link2.shareUrl);
|
|
5855
|
+
else console.log(`view-only token: ${link2.token} \u2014 read with GET /links/${link2.token}/events`);
|
|
5603
5856
|
})
|
|
5604
5857
|
);
|
|
5605
5858
|
session.command("usage <ref>").description("what the session has cost so far, and its newest billed entries").option("--limit <n>", "entries to list (default 20)").option("--json", "print the API's answer as JSON").action(
|
|
@@ -6416,6 +6669,56 @@ reflections.command("list").description("the workspace's proposals, newest first
|
|
|
6416
6669
|
);
|
|
6417
6670
|
reflections.command("approve <id>").description("write the proposal through the skill or memory store").action(run(async (id) => decideReflection(id, "approve")));
|
|
6418
6671
|
reflections.command("reject <id>").description("decline the proposal; nothing is written").action(run(async (id) => decideReflection(id, "reject")));
|
|
6672
|
+
var library = program.command("library").description("your artifact Library on agentsky.dev: files and sites your agents saved or you uploaded");
|
|
6673
|
+
library.command("list").description("your Library, newest first").option("--search <text>", "only names that match").option("--cursor <cursor>", "the next page").option("--json", "print as JSON").action(
|
|
6674
|
+
run(async (opts) => {
|
|
6675
|
+
const page = await listLibrary({ q: opts.search, cursor: opts.cursor });
|
|
6676
|
+
if (opts.json) {
|
|
6677
|
+
console.log(JSON.stringify(page, null, 2));
|
|
6678
|
+
return;
|
|
6679
|
+
}
|
|
6680
|
+
if (!page.artifacts.length) console.log("no artifacts");
|
|
6681
|
+
for (const a of page.artifacts) console.log(renderLibraryArtifact(a));
|
|
6682
|
+
if (page.nextCursor) console.log(`more: --cursor ${page.nextCursor}`);
|
|
6683
|
+
})
|
|
6684
|
+
);
|
|
6685
|
+
library.command("upload <path>").description("save a file from this computer to your Library").option("--workspace <key>", "place it in this workspace").action(
|
|
6686
|
+
run(async (path, opts) => {
|
|
6687
|
+
const bytes = readFileSync17(path);
|
|
6688
|
+
const { artifact: artifact2 } = await uploadToLibrary({ bytes, name: basename9(path), mediaType: "application/octet-stream" }, `sky-upload-${crypto.randomUUID()}`, opts.workspace);
|
|
6689
|
+
console.log(renderLibraryArtifact(artifact2));
|
|
6690
|
+
})
|
|
6691
|
+
);
|
|
6692
|
+
library.command("show <id>").description("one artifact and its saved versions").action(run(async (id) => {
|
|
6693
|
+
console.log(JSON.stringify(await getLibraryArtifact(id), null, 2));
|
|
6694
|
+
}));
|
|
6695
|
+
library.command("delete <id>").description("delete your artifact with all its versions").action(
|
|
6696
|
+
run(async (id) => {
|
|
6697
|
+
const { currentVersion } = await getLibraryArtifact(id);
|
|
6698
|
+
await deleteLibraryArtifact(id, currentVersion ?? 0);
|
|
6699
|
+
console.log(`deleted ${id}`);
|
|
6700
|
+
})
|
|
6701
|
+
);
|
|
6702
|
+
for (const [verb, enabled, description] of [
|
|
6703
|
+
["share", true, "turn on the artifact's public link"],
|
|
6704
|
+
["unshare", false, "turn off the artifact's public link"]
|
|
6705
|
+
]) {
|
|
6706
|
+
library.command(`${verb} <id>`).description(description).action(run(async (id) => {
|
|
6707
|
+
const state = await shareLibraryArtifact(id, enabled);
|
|
6708
|
+
console.log(state.url ?? `${verb}: ${id}`);
|
|
6709
|
+
}));
|
|
6710
|
+
}
|
|
6711
|
+
library.command("place <id> <workspace>").description('place your artifact in a workspace, or "me" to take it back to you alone').action(run(async (id, workspace2) => {
|
|
6712
|
+
await placeLibraryArtifact(id, workspace2 === "me" ? null : workspace2);
|
|
6713
|
+
console.log(`placed ${id}`);
|
|
6714
|
+
}));
|
|
6715
|
+
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(
|
|
6716
|
+
run(async (id, out, opts) => {
|
|
6717
|
+
const { bytes } = await downloadLibraryArtifact(id, opts.version ? Number(opts.version) : void 0);
|
|
6718
|
+
writeFileSync10(out, bytes);
|
|
6719
|
+
console.log(`wrote ${bytes.length} bytes to ${out}`);
|
|
6720
|
+
})
|
|
6721
|
+
);
|
|
6419
6722
|
var artifact = program.command("artifact").description("artifacts: publish a task's files as a named, shareable result");
|
|
6420
6723
|
artifact.command("list").description("the workspace's artifacts, or one task's with --task").option("--task <task>", "only this task's artifacts").action(
|
|
6421
6724
|
run(async (opts) => {
|
|
@@ -6683,6 +6986,19 @@ program.command("config").description("show the CLI config location and current
|
|
|
6683
6986
|
console.log(` token: ${config.token ? `${config.token.slice(0, 10)}\u2026` : "(none)"}`);
|
|
6684
6987
|
console.log(` universe: ${config.currentUniverse ?? "(default)"}`);
|
|
6685
6988
|
});
|
|
6989
|
+
var link = program.command("link").description("a session someone shared with you by a guest link: send to it and stop it");
|
|
6990
|
+
link.command("send <link> <text...>").description("send a message through a guest link (/s/<token> URL or token); it runs and bills as the session's owner").option("--idempotency-key <key>", "repeat a send without sending twice (default: a new key)").action(
|
|
6991
|
+
run(async (ref, words, opts) => {
|
|
6992
|
+
await sendViaLink(ref, words.join(" "), opts.idempotencyKey ?? `sky-${crypto.randomUUID()}`);
|
|
6993
|
+
console.log("Sent. Read the reply with GET /links/<token>/events.");
|
|
6994
|
+
})
|
|
6995
|
+
);
|
|
6996
|
+
link.command("stop <link>").description("stop the turn running on the session a guest link opens").action(
|
|
6997
|
+
run(async (ref) => {
|
|
6998
|
+
await stopViaLink(ref);
|
|
6999
|
+
console.log("Stopped.");
|
|
7000
|
+
})
|
|
7001
|
+
);
|
|
6686
7002
|
var billing = program.command("billing").description("your balance, auto top-up, usage across sessions and API keys, and buying credit");
|
|
6687
7003
|
billing.command("show").description("balance, whether a card is saved, and auto top-up").action(
|
|
6688
7004
|
run(async () => {
|
|
@@ -6709,6 +7025,11 @@ billing.command("topup <dollars>").description("buy credit with your saved card:
|
|
|
6709
7025
|
console.log(renderTopup(result));
|
|
6710
7026
|
})
|
|
6711
7027
|
);
|
|
7028
|
+
billing.command("claim <link>").description("claim a credit invite link (agentsky.dev/i/<code>, or just the code) for your own balance").action(
|
|
7029
|
+
run(async (link2) => {
|
|
7030
|
+
console.log(renderCreditInviteClaim(await claimCreditInvite(link2)));
|
|
7031
|
+
})
|
|
7032
|
+
);
|
|
6712
7033
|
billing.command("auto-topup").description("show auto top-up, or change it: --on/--off, --threshold <5|10|20>, --amount <10|20|50|100>").option("--on", "charge the saved card when the balance falls under the threshold").option("--off", "stop charging automatically").option("--threshold <dollars>", "the balance that triggers a charge").option("--amount <dollars>", "the credit each charge adds").action(
|
|
6713
7034
|
run(async (opts) => {
|
|
6714
7035
|
const body = autoTopupBody(opts);
|
|
@@ -6738,6 +7059,35 @@ usageOptions(
|
|
|
6738
7059
|
}
|
|
6739
7060
|
})
|
|
6740
7061
|
);
|
|
7062
|
+
billing.command("requests").description("one row per API request your developer API keys made, newest first, a page at a time").option("--from <day>", "first UTC day, YYYY-MM-DD (default: 29 days ago)").option("--to <day>", "first UTC day not included (default: tomorrow)").option("--key <id>", "only this API key").option("--cursor <cursor>", "the next page, as printed after the previous one").option("--json", "print the API's answer as JSON").action(
|
|
7063
|
+
run(async (opts) => {
|
|
7064
|
+
const page = await readRequestUsage(opts);
|
|
7065
|
+
console.log(opts.json ? JSON.stringify(page, null, 2) : renderRequestUsage(page));
|
|
7066
|
+
})
|
|
7067
|
+
);
|
|
7068
|
+
var codingPlan = billing.command("coding-plan").description("the coding plan: monthly credit on your saved card, API gateway calls billed at cost");
|
|
7069
|
+
codingPlan.command("show").description("whether you are a member, the monthly amount, and whether it renews").action(run(async () => console.log(renderCodingPlan(await readCodingPlan()))));
|
|
7070
|
+
codingPlan.command("join <dollars>").description("join with your saved card (charged now), or change your monthly amount from the next renewal").option("--request-id <id>", "repeat a request without charging twice (default: a new id)").action(
|
|
7071
|
+
run(async (dollars2, opts) => {
|
|
7072
|
+
console.log(renderCodingPlan(await joinCodingPlan(dollars2, opts.requestId ?? `sky-${crypto.randomUUID()}`)));
|
|
7073
|
+
})
|
|
7074
|
+
);
|
|
7075
|
+
codingPlan.command("cancel").description("stop the plan renewing; the paid month stays").action(run(async () => console.log(renderCodingPlan(await cancelCodingPlan()))));
|
|
7076
|
+
var referralLinks = billing.command("referral-links").description("customer discount links for the API gateway (accounts on a discount plan)");
|
|
7077
|
+
referralLinks.command("list").description("your links, their use, and what referred customers earned you").action(run(async () => console.log(renderReferralLinks(await readReferralLinks()))));
|
|
7078
|
+
referralLinks.command("create").description("create a link priced at no less than your own price; --email sends it to one customer").option("--price <share>", "what the customer pays for every model, as a share of public price: 0.8 or 80%").option("--sku <id=share>", "a price for one SKU; repeat for several", collect).option("--email <address>", "email the link to this customer; it then redeems once").option("--uses <n>", "how many customers can redeem it (default 100)").option("--days <n>", "days until it expires (default 30)").action(
|
|
7079
|
+
run(async (opts) => {
|
|
7080
|
+
const { url, email_status: emailStatus } = await createReferralLink(opts);
|
|
7081
|
+
console.log(emailStatus ? `${url}
|
|
7082
|
+
email: ${emailStatus}` : url);
|
|
7083
|
+
})
|
|
7084
|
+
);
|
|
7085
|
+
referralLinks.command("disable <id>").description("stop a link being redeemed; customers already enrolled keep their price").action(
|
|
7086
|
+
run(async (id) => {
|
|
7087
|
+
await disableReferralLink(id);
|
|
7088
|
+
console.log(`Disabled ${id}`);
|
|
7089
|
+
})
|
|
7090
|
+
);
|
|
6741
7091
|
var keys = program.command("keys").description("your own API keys: list, create, revoke, restore (admin scope)");
|
|
6742
7092
|
keys.command("list").action(
|
|
6743
7093
|
run(async () => {
|
|
@@ -7058,6 +7408,48 @@ vendor.command("usage <id>").description("the agents and tasks that used this ve
|
|
|
7058
7408
|
for (const t of tasks) console.log(` task ${t.session_id} ${t.title ?? "(untitled)"} ${t.last_used_at.slice(0, 10)}`);
|
|
7059
7409
|
})
|
|
7060
7410
|
);
|
|
7411
|
+
var mac = program.command("mac").description("your Macs: what each lends to agents now, and asking one for a folder, a browser window, its screen or its apps and files");
|
|
7412
|
+
mac.command("list").description("your Macs: online or not, what each can lend, and the folders, browser windows and screens lent now").option("--json", "print as JSON").action(
|
|
7413
|
+
run(async (opts) => {
|
|
7414
|
+
const macs = await listMacs();
|
|
7415
|
+
if (opts.json) {
|
|
7416
|
+
console.log(JSON.stringify(macs, null, 2));
|
|
7417
|
+
return;
|
|
7418
|
+
}
|
|
7419
|
+
if (!macs.length) console.log("no Macs connected; sign in to the AgentSky Mac app");
|
|
7420
|
+
for (const entry2 of macs) console.log(renderMac(entry2));
|
|
7421
|
+
})
|
|
7422
|
+
);
|
|
7423
|
+
mac.command("ask <machine> <kind>").description("ask a Mac to lend a folder, a browser window, its screen or its apps and files (host: local chats, call notes, uploads, saves, local git); the person answers on the Mac. Prints the MCP URL a session attaches once it is granted").requiredOption("--reason <text>", "why, in one sentence the person reads on their Mac").option("--no-wait", "return as soon as the Mac has the ask").option("--json", "print as JSON").action(
|
|
7424
|
+
run(async (machine, kind, opts) => {
|
|
7425
|
+
const asked = await askMac(machine, kind, opts.reason);
|
|
7426
|
+
const answer = opts.wait ? await waitForAnswer(asked.reach_request.id, 240) : asked.reach_request;
|
|
7427
|
+
if (opts.json) {
|
|
7428
|
+
console.log(JSON.stringify({ reach_request: answer, mcp_url: asked.mcp_url }, null, 2));
|
|
7429
|
+
return;
|
|
7430
|
+
}
|
|
7431
|
+
console.log(renderReachRequest(answer));
|
|
7432
|
+
console.log(`mcp_url: ${asked.mcp_url}`);
|
|
7433
|
+
if (answer.status === "granted") console.log("attach it as an MCP server: mcp_servers on POST /v1/sessions (MCP start_session: sources), or PATCH /v1/sessions/{id}");
|
|
7434
|
+
else if (!["pending", "asking"].includes(answer.status)) process.exitCode = 1;
|
|
7435
|
+
})
|
|
7436
|
+
);
|
|
7437
|
+
mac.command("ask-status <id>").description("where an ask stands: pending, asking, granted, denied, unavailable or expired").option("--wait <seconds>", "wait up to this long (at most 25) for the person to answer", "0").option("--json", "print as JSON").action(
|
|
7438
|
+
run(async (id, opts) => {
|
|
7439
|
+
const answer = await readReachRequest(id, Number(opts.wait) || 0);
|
|
7440
|
+
if (opts.json) {
|
|
7441
|
+
console.log(JSON.stringify(answer, null, 2));
|
|
7442
|
+
return;
|
|
7443
|
+
}
|
|
7444
|
+
console.log(renderReachRequest(answer));
|
|
7445
|
+
})
|
|
7446
|
+
);
|
|
7447
|
+
mac.command("take-back <mount>").description("end a folder, browser window, screen or apps and files lent from a Mac; every later call to it fails").action(
|
|
7448
|
+
run(async (mount) => {
|
|
7449
|
+
await takeBack(mount);
|
|
7450
|
+
console.log(`took back ${mount}`);
|
|
7451
|
+
})
|
|
7452
|
+
);
|
|
7061
7453
|
var browserProfile = program.command("browser-profile").description("saved-login profiles: the sites your agents stay signed in to");
|
|
7062
7454
|
browserProfile.command("list").description("your workspace's browser profiles: the sites your agents stay signed in to").option("--json", "print as JSON").action(
|
|
7063
7455
|
run(async (opts) => {
|
|
@@ -7121,10 +7513,16 @@ notifications.command("get").description("show the current notification preferen
|
|
|
7121
7513
|
console.log(JSON.stringify(prefs, null, 2));
|
|
7122
7514
|
return;
|
|
7123
7515
|
}
|
|
7124
|
-
console.log(`email: needs_you=${prefs.email.needs_you} done=${prefs.email.done}`);
|
|
7516
|
+
console.log(`email: needs_you=${prefs.email.needs_you} done=${prefs.email.done} marketing=${prefs.email.marketing}`);
|
|
7125
7517
|
console.log(`push: needs_you=${prefs.push.needs_you} done=${prefs.push.done}`);
|
|
7126
7518
|
})
|
|
7127
7519
|
);
|
|
7520
|
+
notifications.command("unsubscribe-marketing").description("stop AgentSky marketing email to your address; login and account email continue").action(
|
|
7521
|
+
run(async () => {
|
|
7522
|
+
const { marketing } = await unsubscribeMarketing();
|
|
7523
|
+
console.log(marketing ? "Marketing email is still on." : "Unsubscribed from AgentSky marketing email.");
|
|
7524
|
+
})
|
|
7525
|
+
);
|
|
7128
7526
|
notifications.command("set").description("update notification preferences (pass at least one flag)").option("--email-needs-you <bool>", "email when the task needs your input: true or false").option("--email-done <bool>", "email when the task finishes: true or false").option("--push-needs-you <bool>", "push notification when the task needs your input: true or false").option("--push-done <bool>", "push notification when the task finishes: true or false").action(
|
|
7129
7527
|
run(async (opts) => {
|
|
7130
7528
|
const parseBool = (v) => v === void 0 ? void 0 : v === "true" ? true : v === "false" ? false : (() => {
|
|
@@ -7282,7 +7680,7 @@ harness.command("connect").description("run an ACP agent (the command after --)
|
|
|
7282
7680
|
}));
|
|
7283
7681
|
var traceCmd = program.command("trace").description("correlate this machine's agent work with the cloud sessions it starts (metadata only unless you choose content)");
|
|
7284
7682
|
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) => {
|
|
7285
|
-
const { readState, writeState, record, installClaudeHooks, parseContentScopes, chosenPaths, fileEvent } = await import("./trace-
|
|
7683
|
+
const { readState, writeState, record, installClaudeHooks, parseContentScopes, chosenPaths, fileEvent } = await import("./trace-ZRU624EY.js");
|
|
7286
7684
|
if (readState()) throw new Error("a trace is already running here \u2014 `sky trace stop` it first");
|
|
7287
7685
|
const scopes = parseContentScopes(opts.capture);
|
|
7288
7686
|
const chosen = chosenPaths(opts.file ?? [], opts.dir ?? []);
|
|
@@ -7317,7 +7715,7 @@ traceCmd.command("start").description("start a trace: a grant for this machine,
|
|
|
7317
7715
|
}));
|
|
7318
7716
|
traceCmd.command("hook").description("record one Claude Code hook event read from stdin (run by the installed hooks; never fails, prints nothing)").action(async () => {
|
|
7319
7717
|
try {
|
|
7320
|
-
const { readState, record, flush, grantSender, eventsForClaudeHook, contentForClaudeHook, clearState } = await import("./trace-
|
|
7718
|
+
const { readState, record, flush, grantSender, eventsForClaudeHook, contentForClaudeHook, clearState } = await import("./trace-ZRU624EY.js");
|
|
7321
7719
|
const chunks = [];
|
|
7322
7720
|
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
7323
7721
|
const input = JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}");
|
|
@@ -7330,14 +7728,14 @@ traceCmd.command("hook").description("record one Claude Code hook event read fro
|
|
|
7330
7728
|
}
|
|
7331
7729
|
});
|
|
7332
7730
|
traceCmd.command("flush").description("send what the spool holds, retrying with backoff").action(run(async () => {
|
|
7333
|
-
const { readState, flush, grantSender } = await import("./trace-
|
|
7731
|
+
const { readState, flush, grantSender } = await import("./trace-ZRU624EY.js");
|
|
7334
7732
|
const state = readState();
|
|
7335
7733
|
if (!state) throw new Error("no trace is running here");
|
|
7336
7734
|
const outcome = await flush(grantSender(state), { attempts: 4 });
|
|
7337
7735
|
console.log(`sent ${outcome.sent}, refused ${outcome.refused}, given up ${outcome.expired}, still pending ${outcome.pending}${outcome.stopped ? ` (stopped: ${outcome.stopped})` : ""}`);
|
|
7338
7736
|
}));
|
|
7339
7737
|
traceCmd.command("status").description("the running trace and its spool").action(run(async () => {
|
|
7340
|
-
const { readState, spoolStatus } = await import("./trace-
|
|
7738
|
+
const { readState, spoolStatus } = await import("./trace-ZRU624EY.js");
|
|
7341
7739
|
const state = readState();
|
|
7342
7740
|
if (!state) {
|
|
7343
7741
|
console.log("No trace is running here.");
|
|
@@ -7347,7 +7745,7 @@ traceCmd.command("status").description("the running trace and its spool").action
|
|
|
7347
7745
|
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`);
|
|
7348
7746
|
}));
|
|
7349
7747
|
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) => {
|
|
7350
|
-
const { readState } = await import("./trace-
|
|
7748
|
+
const { readState } = await import("./trace-ZRU624EY.js");
|
|
7351
7749
|
const ref = id ?? readState()?.trace_id;
|
|
7352
7750
|
if (!ref) throw new Error("name a trace, or start one here");
|
|
7353
7751
|
const bundle = await api("GET", `/traces/${ref}`);
|
|
@@ -7374,7 +7772,7 @@ traceCmd.command("show [id]").description("the trace bundle: spans, the sessions
|
|
|
7374
7772
|
for (const gap of bundle.gaps) console.log(` gap: ${gap.span_id} ${gap.reason}`);
|
|
7375
7773
|
}));
|
|
7376
7774
|
traceCmd.command("stop").description("end the root span, send what is left, and revoke this machine's grant").action(run(async () => {
|
|
7377
|
-
const { readState, record, flush, grantSender, clearState } = await import("./trace-
|
|
7775
|
+
const { readState, record, flush, grantSender, clearState } = await import("./trace-ZRU624EY.js");
|
|
7378
7776
|
const state = readState();
|
|
7379
7777
|
if (!state) throw new Error("no trace is running here");
|
|
7380
7778
|
if (state.root_span) record(() => [{ span_id: state.root_span, kind: "end", outcome: "completed" }]);
|
|
@@ -7384,7 +7782,7 @@ traceCmd.command("stop").description("end the root span, send what is left, and
|
|
|
7384
7782
|
console.log(`Stopped ${state.trace_id}${outcome.pending ? ` (${outcome.pending} events could not be sent)` : ""}`);
|
|
7385
7783
|
}));
|
|
7386
7784
|
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) => {
|
|
7387
|
-
const lib = await import("./trace-library-
|
|
7785
|
+
const lib = await import("./trace-library-QOQUAL5H.js");
|
|
7388
7786
|
if (opts.hook) {
|
|
7389
7787
|
try {
|
|
7390
7788
|
let raw = payload ?? "";
|
|
@@ -7493,7 +7891,7 @@ traceCmd.command("sync [payload]").description("upload this machine's agent sess
|
|
|
7493
7891
|
})();
|
|
7494
7892
|
});
|
|
7495
7893
|
traceCmd.command("search <query...>").description("search every session in a workspace's trace library (literal substring)").option("--workspace <slug>", "the workspace to search (default: the current one)").option("--limit <n>", "hits per page", (v) => Number.parseInt(v, 10), 20).option("--cursor <cursor>", "the next page of an earlier search").option("--json", "print the page as JSON").action(run(async (words, opts) => {
|
|
7496
|
-
const { libraryRequest } = await import("./trace-library-
|
|
7894
|
+
const { libraryRequest } = await import("./trace-library-QOQUAL5H.js");
|
|
7497
7895
|
const workspace2 = opts.workspace ?? currentUniverse();
|
|
7498
7896
|
if (!workspace2) throw new Error("name a workspace with --workspace");
|
|
7499
7897
|
const params = new URLSearchParams({ q: words.join(" "), scope: "traces", limit: String(opts.limit), ...opts.cursor ? { cursor: opts.cursor } : {} });
|
|
@@ -7510,7 +7908,7 @@ traceCmd.command("search <query...>").description("search every session in a wor
|
|
|
7510
7908
|
if (page.nextCursor) console.log(`More: sky trace search ${JSON.stringify(words.join(" "))} --workspace ${workspace2} --cursor ${page.nextCursor}`);
|
|
7511
7909
|
}));
|
|
7512
7910
|
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) => {
|
|
7513
|
-
const { libraryRequest } = await import("./trace-library-
|
|
7911
|
+
const { libraryRequest } = await import("./trace-library-QOQUAL5H.js");
|
|
7514
7912
|
const workspace2 = opts.workspace ?? currentUniverse();
|
|
7515
7913
|
if (!workspace2) throw new Error("name a workspace with --workspace");
|
|
7516
7914
|
const page = await libraryRequest("GET", `/trace-library?limit=${opts.limit}`, workspace2);
|
|
@@ -7626,6 +8024,140 @@ thread.command("list").description("your workspace threads, most recently update
|
|
|
7626
8024
|
for (const t of threads) console.log(renderThreadSummary(t));
|
|
7627
8025
|
})
|
|
7628
8026
|
);
|
|
8027
|
+
thread.command("start <text>").description("start a thread and send it its first message, as the web composer does").requiredOption("--agent <type>", "the agent's harness type (e.g. claude_code, codex)").option("--llm <model>", "the model (the harness default when omitted)").option("--effort <level>", "thinking level").option("--vs <type:model...>", "more agents that get the same message, side by side", (val, acc) => [...acc, val], []).option("--saved-agent <id>", "run on one of your saved agents").option("--workspace <slug>", "start it in this team workspace").option("--plan", "send the first message in Plan mode").option("--json", "print the new thread as JSON").action(
|
|
8028
|
+
run(async (text, opts) => {
|
|
8029
|
+
const compared = (opts.vs ?? []).map((v) => {
|
|
8030
|
+
const [agentType, llm] = v.split(":");
|
|
8031
|
+
if (!agentType) throw new ApiError(400, "invalid_request", `--vs must be type[:model], got "${v}"`);
|
|
8032
|
+
return { agentType, ...llm ? { llm } : {} };
|
|
8033
|
+
});
|
|
8034
|
+
const result = await startThread({
|
|
8035
|
+
requestId: `sky-thread-${crypto.randomUUID()}`,
|
|
8036
|
+
agentType: opts.agent,
|
|
8037
|
+
text,
|
|
8038
|
+
...opts.llm ? { llm: opts.llm } : {},
|
|
8039
|
+
...opts.effort ? { reasoningEffort: opts.effort } : {},
|
|
8040
|
+
...compared.length ? { compare: compared } : {},
|
|
8041
|
+
...opts.savedAgent ? { agentId: opts.savedAgent } : {},
|
|
8042
|
+
...opts.workspace ? { workspace: opts.workspace } : {},
|
|
8043
|
+
...opts.plan ? { interactionMode: "plan" } : {}
|
|
8044
|
+
});
|
|
8045
|
+
if (opts.json) {
|
|
8046
|
+
console.log(JSON.stringify(result, null, 2));
|
|
8047
|
+
return;
|
|
8048
|
+
}
|
|
8049
|
+
console.log(`started ${result.playgroundId}`);
|
|
8050
|
+
for (const col of result.columns) console.log(` agent ${col.columnId} session ${col.sessionId}`);
|
|
8051
|
+
})
|
|
8052
|
+
);
|
|
8053
|
+
thread.command("show <id>").description("one thread with every agent and the session each one runs in").option("--json", "print as JSON").action(
|
|
8054
|
+
run(async (id, opts) => {
|
|
8055
|
+
const detail = await getThread(id);
|
|
8056
|
+
if (opts.json) {
|
|
8057
|
+
console.log(JSON.stringify(detail, null, 2));
|
|
8058
|
+
return;
|
|
8059
|
+
}
|
|
8060
|
+
console.log(`thread ${detail.id} ${detail.title}`);
|
|
8061
|
+
for (const col of detail.columns) console.log(` agent ${col.id} session ${col.sessionId} ${col.blind ? "(hidden until the vote)" : `${col.agentType}/${col.llm}`} ${col.status ?? col.podStatus ?? ""}`);
|
|
8062
|
+
})
|
|
8063
|
+
);
|
|
8064
|
+
thread.command("rename <id> <title>").description("rename a thread").action(run(async (id, title) => {
|
|
8065
|
+
await organizeThread(id, { title });
|
|
8066
|
+
console.log(`renamed ${id}`);
|
|
8067
|
+
}));
|
|
8068
|
+
for (const [verb, change, description] of [
|
|
8069
|
+
["pin", { pinned: true }, "pin a thread to the top of the rail"],
|
|
8070
|
+
["unpin", { pinned: false }, "unpin a thread"],
|
|
8071
|
+
["archive", { archived: true }, "put a thread away"],
|
|
8072
|
+
["unarchive", { archived: false }, "bring an archived thread back"],
|
|
8073
|
+
["mark-read", { seen: true }, "mark a thread read"],
|
|
8074
|
+
["mark-unread", { seen: false }, "mark a thread unread"]
|
|
8075
|
+
]) {
|
|
8076
|
+
thread.command(`${verb} <id>`).description(description).action(run(async (id) => {
|
|
8077
|
+
await organizeThread(id, change);
|
|
8078
|
+
console.log(`${verb}: ${id}`);
|
|
8079
|
+
}));
|
|
8080
|
+
}
|
|
8081
|
+
thread.command("delete <id>").description("delete a thread with its sessions").action(run(async (id) => {
|
|
8082
|
+
await deleteThread(id);
|
|
8083
|
+
console.log(`deleted ${id}`);
|
|
8084
|
+
}));
|
|
8085
|
+
thread.command("send <id> <text>").description("send one message to every agent of the thread, or to the ones --agent names").option("--agent <columnId...>", "only these agents (column ids from `sky thread show`)").option("--json", "print each agent's outcome as JSON").action(
|
|
8086
|
+
run(async (id, text, opts) => {
|
|
8087
|
+
const { results } = await sendThreadMessage(id, { text, deliveryId: crypto.randomUUID(), ...opts.agent?.length ? { columnIds: opts.agent } : {} });
|
|
8088
|
+
if (opts.json) {
|
|
8089
|
+
console.log(JSON.stringify(results, null, 2));
|
|
8090
|
+
return;
|
|
8091
|
+
}
|
|
8092
|
+
for (const [column, outcome] of Object.entries(results)) console.log(` ${column} ${outcome.ok ? "sent" : `not sent: ${outcome.error ?? "refused"}`}`);
|
|
8093
|
+
})
|
|
8094
|
+
);
|
|
8095
|
+
thread.command("add-agent <id>").description("add an agent to the thread, in a session of its own").requiredOption("--agent <type>", "the agent's harness type").option("--llm <model>", "the model").option("--effort <level>", "thinking level").action(
|
|
8096
|
+
run(async (id, opts) => {
|
|
8097
|
+
const { columns } = await addThreadAgent(id, { requestId: `sky-agent-${crypto.randomUUID()}`, agentType: opts.agent, ...opts.llm ? { llm: opts.llm } : {}, ...opts.effort ? { reasoningEffort: opts.effort } : {} });
|
|
8098
|
+
for (const col of columns) console.log(`added agent ${col.columnId} session ${col.sessionId}`);
|
|
8099
|
+
})
|
|
8100
|
+
);
|
|
8101
|
+
thread.command("remove-agent <id> <columnId>").description("take one agent out of the thread; its session is left as it is").action(run(async (id, columnId) => {
|
|
8102
|
+
await removeThreadAgent(id, columnId);
|
|
8103
|
+
console.log(`removed ${columnId}`);
|
|
8104
|
+
}));
|
|
8105
|
+
thread.command("stop <id>").description("stop what the thread's agents are doing").option("--agent <columnId>", "stop only this agent").action(run(async (id, opts) => {
|
|
8106
|
+
await interruptThread(id, opts.agent);
|
|
8107
|
+
console.log(`stopped ${id}`);
|
|
8108
|
+
}));
|
|
8109
|
+
thread.command("fork <id>").description("continue one agent's conversation in a thread of its own").option("--agent <columnId>", "the agent to fork (the first when omitted)").option("--at <messageId>", "carry the conversation only up to this message").option("--to <type:model>", "continue on another agent or model").action(
|
|
8110
|
+
run(async (id, opts) => {
|
|
8111
|
+
const [agentType, llm] = (opts.to ?? "").split(":");
|
|
8112
|
+
const { playgroundId } = await forkThread(id, {
|
|
8113
|
+
requestId: `sky-fork-${crypto.randomUUID()}`,
|
|
8114
|
+
...opts.agent ? { columnId: opts.agent } : {},
|
|
8115
|
+
...opts.at ? { messageId: opts.at } : {},
|
|
8116
|
+
...agentType ? { target: { agentType, ...llm ? { llm } : {} } } : {}
|
|
8117
|
+
});
|
|
8118
|
+
console.log(`forked into ${playgroundId}`);
|
|
8119
|
+
})
|
|
8120
|
+
);
|
|
8121
|
+
thread.command("model <id>").description("change the model or thinking level one agent of the thread runs on, from its next turn").option("--agent <columnId>", "the agent (the first when omitted)").option("--llm <model>", "the new model").option("--effort <level>", 'the new thinking level, or "default"').action(
|
|
8122
|
+
run(async (id, opts) => {
|
|
8123
|
+
if (!opts.llm && !opts.effort) throw new ApiError(400, "invalid_request", "Provide --llm or --effort.");
|
|
8124
|
+
const result = await changeThreadModel(id, { ...opts.llm ? { llm: opts.llm } : {}, ...opts.effort ? { reasoningEffort: opts.effort === "default" ? null : opts.effort } : {} }, opts.agent);
|
|
8125
|
+
console.log(`now ${result.llm}${result.reasoningEffort ? ` (${result.reasoningEffort})` : ""}`);
|
|
8126
|
+
})
|
|
8127
|
+
);
|
|
8128
|
+
thread.command("search <query>").description("search the words of your conversations").option("--archived", "search archived threads only").option("--all", "search active and archived threads").option("--cursor <cursor>", "the next page").action(
|
|
8129
|
+
run(async (query, opts) => {
|
|
8130
|
+
const threads = opts.all ? "all" : opts.archived ? "archived" : void 0;
|
|
8131
|
+
console.log(JSON.stringify(await searchThreads(query, { ...threads ? { threads } : {}, ...opts.cursor ? { cursor: opts.cursor } : {} }), null, 2));
|
|
8132
|
+
})
|
|
8133
|
+
);
|
|
8134
|
+
thread.command("options").description("what a new thread can start on: agents, models, thinking levels and grantable tools").action(run(async () => {
|
|
8135
|
+
console.log(JSON.stringify(await threadOptions(), null, 2));
|
|
8136
|
+
}));
|
|
8137
|
+
thread.command("join <sessionId>").description("open a teammate's thread, or one shared with you, as the session link does").action(
|
|
8138
|
+
run(async (sessionId) => {
|
|
8139
|
+
const opened = await joinThread(sessionId);
|
|
8140
|
+
console.log(opened.readOnly ? `read-only: session ${opened.sessionId}` : `opened ${opened.playgroundId}`);
|
|
8141
|
+
})
|
|
8142
|
+
);
|
|
8143
|
+
var project = program.command("project").description("the GitHub repositories a new thread can start on");
|
|
8144
|
+
project.command("list").description("repositories a new thread can start on, and the one you chose last").option("--json", "print as JSON").action(
|
|
8145
|
+
run(async (opts) => {
|
|
8146
|
+
const listed = await listProjects();
|
|
8147
|
+
if (opts.json) {
|
|
8148
|
+
console.log(JSON.stringify(listed, null, 2));
|
|
8149
|
+
return;
|
|
8150
|
+
}
|
|
8151
|
+
if (listed.unavailable) console.log(listed.unavailable.message);
|
|
8152
|
+
for (const repo of listed.repos) console.log(`${repo.fullName === listed.last?.repoFullName ? "* " : " "}${repo.fullName}`);
|
|
8153
|
+
})
|
|
8154
|
+
);
|
|
8155
|
+
project.command("use [repo]").description("remember a repository (owner/name) for your next new thread, or none when omitted").option("--branch <branch>", "the branch", "main").action(
|
|
8156
|
+
run(async (repo, opts) => {
|
|
8157
|
+
const { project: remembered } = await rememberProject(repo ? { repoFullName: repo, branch: opts.branch } : null);
|
|
8158
|
+
console.log(remembered ? `next thread starts on ${remembered.repoFullName}@${remembered.branch}` : "next thread starts on no repository");
|
|
8159
|
+
})
|
|
8160
|
+
);
|
|
7629
8161
|
session.command("feedback <id>").description("read the thumbs-up/down feedback on this session's messages").option("--json", "print as JSON").action(
|
|
7630
8162
|
run(async (id, opts) => {
|
|
7631
8163
|
const result = await api(
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
USER_AGENT,
|
|
3
3
|
configPath
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-V5XLV37X.js";
|
|
5
5
|
import {
|
|
6
6
|
TRACE_CONTENT_SCOPES,
|
|
7
7
|
redactTraceText
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HDPDY77W.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-
|
|
3
|
+
} from "./chunk-HQPOCQRQ.js";
|
|
4
4
|
import {
|
|
5
5
|
USER_AGENT,
|
|
6
6
|
apiBase,
|
|
7
7
|
apiToken
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-V5XLV37X.js";
|
|
9
9
|
import {
|
|
10
10
|
SessionSourceCollector,
|
|
11
11
|
publicRemote,
|
|
12
12
|
redactTraceText
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-HDPDY77W.js";
|
|
14
14
|
import "./chunk-MLKGABMK.js";
|
|
15
15
|
|
|
16
16
|
// src/trace-library.ts
|