@agentsky/sky 2.8.0 → 2.9.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.
@@ -545,7 +545,7 @@ __export(core_exports2, {
545
545
  parseAsync: () => parseAsync,
546
546
  parseURLObject: () => parseURLObject,
547
547
  prettifyError: () => prettifyError,
548
- process: () => process,
548
+ process: () => process2,
549
549
  regexes: () => regexes_exports,
550
550
  registry: () => registry,
551
551
  safeDecode: () => safeDecode,
@@ -15149,7 +15149,7 @@ function handleUnrepresentable(schema, ctx, json2, params, message) {
15149
15149
  Object.assign(json2, result);
15150
15150
  return true;
15151
15151
  }
15152
- function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
15152
+ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
15153
15153
  var _a3;
15154
15154
  const def = schema._zod.def;
15155
15155
  const seen = ctx.seen.get(schema);
@@ -15188,7 +15188,7 @@ function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
15188
15188
  if (parent) {
15189
15189
  if (!result.ref)
15190
15190
  result.ref = parent;
15191
- process(parent, ctx, params);
15191
+ process2(parent, ctx, params);
15192
15192
  ctx.seen.get(parent).isParent = true;
15193
15193
  }
15194
15194
  }
@@ -15623,14 +15623,14 @@ function isTransforming(_schema, _ctx) {
15623
15623
  }
15624
15624
  var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
15625
15625
  const ctx = initializeContext({ ...params, processors });
15626
- process(schema, ctx);
15626
+ process2(schema, ctx);
15627
15627
  extractDefs(ctx, schema);
15628
15628
  return finalize(ctx, schema);
15629
15629
  };
15630
15630
  var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
15631
15631
  const { libraryOptions, target } = params ?? {};
15632
15632
  const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
15633
- process(schema, ctx);
15633
+ process2(schema, ctx);
15634
15634
  extractDefs(ctx, schema);
15635
15635
  return finalize(ctx, schema);
15636
15636
  };
@@ -15862,7 +15862,7 @@ var arrayProcessor = (schema, ctx, _json, params) => {
15862
15862
  if (typeof maximum === "number")
15863
15863
  json2.maxItems = maximum;
15864
15864
  json2.type = "array";
15865
- json2.items = process(def.element, ctx, {
15865
+ json2.items = process2(def.element, ctx, {
15866
15866
  ...params,
15867
15867
  path: [...params.path, "items"]
15868
15868
  });
@@ -15888,7 +15888,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
15888
15888
  json2.type = "object";
15889
15889
  json2.properties = {};
15890
15890
  for (const key in shape) {
15891
- assignProp(json2.properties, key, process(shape[key], ctx, {
15891
+ assignProp(json2.properties, key, process2(shape[key], ctx, {
15892
15892
  ...params,
15893
15893
  path: [...params.path, "properties", key]
15894
15894
  }));
@@ -15911,7 +15911,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
15911
15911
  if (ctx.io === "output")
15912
15912
  json2.additionalProperties = false;
15913
15913
  } else if (def.catchall) {
15914
- json2.additionalProperties = process(def.catchall, ctx, {
15914
+ json2.additionalProperties = process2(def.catchall, ctx, {
15915
15915
  ...params,
15916
15916
  path: [...params.path, "additionalProperties"]
15917
15917
  });
@@ -15920,7 +15920,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
15920
15920
  var unionProcessor = (schema, ctx, json2, params) => {
15921
15921
  const def = schema._zod.def;
15922
15922
  const isExclusive = def.inclusive === false;
15923
- const options = def.options.map((x, i) => process(x, ctx, {
15923
+ const options = def.options.map((x, i) => process2(x, ctx, {
15924
15924
  ...params,
15925
15925
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
15926
15926
  }));
@@ -15932,11 +15932,11 @@ var unionProcessor = (schema, ctx, json2, params) => {
15932
15932
  };
15933
15933
  var intersectionProcessor = (schema, ctx, json2, params) => {
15934
15934
  const def = schema._zod.def;
15935
- const a = process(def.left, ctx, {
15935
+ const a = process2(def.left, ctx, {
15936
15936
  ...params,
15937
15937
  path: [...params.path, "allOf", 0]
15938
15938
  });
15939
- const b = process(def.right, ctx, {
15939
+ const b = process2(def.right, ctx, {
15940
15940
  ...params,
15941
15941
  path: [...params.path, "allOf", 1]
15942
15942
  });
@@ -15954,11 +15954,11 @@ var tupleProcessor = (schema, ctx, _json, params) => {
15954
15954
  json2.type = "array";
15955
15955
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
15956
15956
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
15957
- const prefixItems = def.items.map((x, i) => process(x, ctx, {
15957
+ const prefixItems = def.items.map((x, i) => process2(x, ctx, {
15958
15958
  ...params,
15959
15959
  path: [...params.path, prefixPath, i]
15960
15960
  }));
15961
- const rest = def.rest ? process(def.rest, ctx, {
15961
+ const rest = def.rest ? process2(def.rest, ctx, {
15962
15962
  ...params,
15963
15963
  path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
15964
15964
  }) : null;
@@ -16083,7 +16083,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
16083
16083
  const keyBag = keyType._zod.bag;
16084
16084
  const patterns = keyBag?.patterns;
16085
16085
  if (def.mode === "loose" && patterns && patterns.size > 0) {
16086
- const valueSchema = process(def.valueType, ctx, {
16086
+ const valueSchema = process2(def.valueType, ctx, {
16087
16087
  ...params,
16088
16088
  path: [...params.path, "patternProperties", "*"]
16089
16089
  });
@@ -16093,7 +16093,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
16093
16093
  }
16094
16094
  } else {
16095
16095
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
16096
- json2.propertyNames = process(def.keyType, ctx, {
16096
+ json2.propertyNames = process2(def.keyType, ctx, {
16097
16097
  ...params,
16098
16098
  path: [...params.path, "propertyNames"]
16099
16099
  });
@@ -16105,7 +16105,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
16105
16105
  }
16106
16106
  pending.push(schema);
16107
16107
  }
16108
- json2.additionalProperties = process(def.valueType, ctx, {
16108
+ json2.additionalProperties = process2(def.valueType, ctx, {
16109
16109
  ...params,
16110
16110
  path: [...params.path, "additionalProperties"]
16111
16111
  });
@@ -16121,7 +16121,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
16121
16121
  };
16122
16122
  var nullableProcessor = (schema, ctx, json2, params) => {
16123
16123
  const def = schema._zod.def;
16124
- const inner = process(def.innerType, ctx, params);
16124
+ const inner = process2(def.innerType, ctx, params);
16125
16125
  const seen = ctx.seen.get(schema);
16126
16126
  if (ctx.target === "openapi-3.0") {
16127
16127
  seen.ref = def.innerType;
@@ -16132,7 +16132,7 @@ var nullableProcessor = (schema, ctx, json2, params) => {
16132
16132
  };
16133
16133
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
16134
16134
  const def = schema._zod.def;
16135
- process(def.innerType, ctx, params);
16135
+ process2(def.innerType, ctx, params);
16136
16136
  const seen = ctx.seen.get(schema);
16137
16137
  seen.ref = def.innerType;
16138
16138
  };
@@ -16152,7 +16152,7 @@ function serializeDefaultValue(value, schema, ctx, json2, params) {
16152
16152
  }
16153
16153
  var defaultProcessor = (schema, ctx, json2, params) => {
16154
16154
  const def = schema._zod.def;
16155
- process(def.innerType, ctx, params);
16155
+ process2(def.innerType, ctx, params);
16156
16156
  const seen = ctx.seen.get(schema);
16157
16157
  seen.ref = def.innerType;
16158
16158
  const value = serializeDefaultValue(def.defaultValue, schema, ctx, json2, params);
@@ -16161,7 +16161,7 @@ var defaultProcessor = (schema, ctx, json2, params) => {
16161
16161
  };
16162
16162
  var prefaultProcessor = (schema, ctx, json2, params) => {
16163
16163
  const def = schema._zod.def;
16164
- process(def.innerType, ctx, params);
16164
+ process2(def.innerType, ctx, params);
16165
16165
  const seen = ctx.seen.get(schema);
16166
16166
  seen.ref = def.innerType;
16167
16167
  if (ctx.io !== "input")
@@ -16172,7 +16172,7 @@ var prefaultProcessor = (schema, ctx, json2, params) => {
16172
16172
  };
16173
16173
  var catchProcessor = (schema, ctx, json2, params) => {
16174
16174
  const def = schema._zod.def;
16175
- process(def.innerType, ctx, params);
16175
+ process2(def.innerType, ctx, params);
16176
16176
  const seen = ctx.seen.get(schema);
16177
16177
  seen.ref = def.innerType;
16178
16178
  let catchValue;
@@ -16188,32 +16188,32 @@ var pipeProcessor = (schema, ctx, _json, params) => {
16188
16188
  const def = schema._zod.def;
16189
16189
  const inIsTransform = def.in._zod.traits.has("$ZodTransform");
16190
16190
  const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
16191
- process(innerType, ctx, params);
16191
+ process2(innerType, ctx, params);
16192
16192
  const seen = ctx.seen.get(schema);
16193
16193
  seen.ref = innerType;
16194
16194
  };
16195
16195
  var readonlyProcessor = (schema, ctx, json2, params) => {
16196
16196
  const def = schema._zod.def;
16197
- process(def.innerType, ctx, params);
16197
+ process2(def.innerType, ctx, params);
16198
16198
  const seen = ctx.seen.get(schema);
16199
16199
  seen.ref = def.innerType;
16200
16200
  json2.readOnly = true;
16201
16201
  };
16202
16202
  var promiseProcessor = (schema, ctx, _json, params) => {
16203
16203
  const def = schema._zod.def;
16204
- process(def.innerType, ctx, params);
16204
+ process2(def.innerType, ctx, params);
16205
16205
  const seen = ctx.seen.get(schema);
16206
16206
  seen.ref = def.innerType;
16207
16207
  };
16208
16208
  var optionalProcessor = (schema, ctx, _json, params) => {
16209
16209
  const def = schema._zod.def;
16210
- process(def.innerType, ctx, params);
16210
+ process2(def.innerType, ctx, params);
16211
16211
  const seen = ctx.seen.get(schema);
16212
16212
  seen.ref = def.innerType;
16213
16213
  };
16214
16214
  var lazyProcessor = (schema, ctx, _json, params) => {
16215
16215
  const innerType = schema._zod.innerType;
16216
- process(innerType, ctx, params);
16216
+ process2(innerType, ctx, params);
16217
16217
  const seen = ctx.seen.get(schema);
16218
16218
  seen.ref = innerType;
16219
16219
  };
@@ -16265,7 +16265,7 @@ function toJSONSchema(input2, params) {
16265
16265
  const defs = {};
16266
16266
  for (const entry of registry2._idmap.entries()) {
16267
16267
  const [_, schema] = entry;
16268
- process(schema, ctx2);
16268
+ process2(schema, ctx2);
16269
16269
  }
16270
16270
  const schemas = {};
16271
16271
  const external = {
@@ -16288,7 +16288,7 @@ function toJSONSchema(input2, params) {
16288
16288
  return { schemas };
16289
16289
  }
16290
16290
  const ctx = initializeContext({ ...params, processors: allProcessors });
16291
- process(input2, ctx);
16291
+ process2(input2, ctx);
16292
16292
  extractDefs(ctx, input2);
16293
16293
  return finalize(ctx, input2);
16294
16294
  }
@@ -16347,7 +16347,7 @@ var JSONSchemaGenerator = class {
16347
16347
  * This must be called before emit().
16348
16348
  */
16349
16349
  process(schema, _params = { path: [], schemaPath: [] }) {
16350
- return process(schema, this.ctx, _params);
16350
+ return process2(schema, this.ctx, _params);
16351
16351
  }
16352
16352
  /**
16353
16353
  * Emit the final JSON Schema after processing.
@@ -19024,7 +19024,6 @@ var REASONING_EFFORTS = {
19024
19024
  sigit: null,
19025
19025
  stakpak: null,
19026
19026
  vtcode: null,
19027
- agentpool: null,
19028
19027
  code_assistant: null,
19029
19028
  docker_cagent: null,
19030
19029
  kiro: null,
@@ -19197,7 +19196,7 @@ var ACP_AGENTS = {
19197
19196
  "registryId": "antigravity-acp",
19198
19197
  "label": "Google Antigravity",
19199
19198
  "description": "Google\u2019s AI coding agent",
19200
- "version": "1.1.1",
19199
+ "version": "1.3.0",
19201
19200
  "website": "https://antigravity.google/docs/ide/extensions"
19202
19201
  },
19203
19202
  "goose": {
@@ -19312,13 +19311,6 @@ var ACP_AGENTS = {
19312
19311
  "version": "0.96.14",
19313
19312
  "website": "https://github.com/vinhnx/VTCode/blob/main/docs/guides/zed-acp.md"
19314
19313
  },
19315
- "agentpool": {
19316
- "registryId": "agentpool",
19317
- "label": "AgentPool",
19318
- "description": "Agent pools configured through YAML and served over ACP.",
19319
- "version": "2.9.18",
19320
- "website": "https://phil65.github.io/agentpool/"
19321
- },
19322
19314
  "code_assistant": {
19323
19315
  "registryId": "code-assistant",
19324
19316
  "label": "Code Assistant",
@@ -19392,7 +19384,6 @@ var ACP_AGENT_TYPES = [
19392
19384
  "sigit",
19393
19385
  "stakpak",
19394
19386
  "vtcode",
19395
- "agentpool",
19396
19387
  "code_assistant",
19397
19388
  "docker_cagent",
19398
19389
  "kiro",
@@ -19405,7 +19396,6 @@ function isAcpAgentType(value) {
19405
19396
 
19406
19397
  // ../../packages/spec/src/acp-platform.ts
19407
19398
  var ACP_PLATFORM_MODELS = {
19408
- agentpool: ["deepseek-v4-pro", "deepseek-flash", "gpt-5.6-sol", "gpt-6-astra", "glm-5.3", "glm-5.3-flash", "kimi-k3", "kimi-k2.7-code", "grok-4.6", "claude-fable-5-1", "claude-sonnet-5", "claude-haiku-4-5"],
19409
19399
  cline: ["deepseek-v4-pro", "deepseek-flash", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-6-astra", "glm-5.3", "glm-5.3-flash", "kimi-k3", "kimi-k2.7-code", "grok-4.6"],
19410
19400
  code_assistant: ["deepseek-v4-pro", "deepseek-flash", "gpt-5.6-sol", "gpt-5.6-luna", "glm-5.3", "glm-5.3-flash", "kimi-k3", "kimi-k2.7-code", "grok-4.6", "claude-opus-5", "claude-fable-5-1", "claude-sonnet-5", "claude-haiku-4-5"],
19411
19401
  crow_cli: ["deepseek-v4-pro"],
@@ -20122,7 +20112,7 @@ var ACP_ACCOUNT_PROFILES = {
20122
20112
  },
20123
20113
  "antigravity_acp": {
20124
20114
  "name": "Google Antigravity",
20125
- "version": "1.1.1",
20115
+ "version": "1.3.0",
20126
20116
  "status": "documented",
20127
20117
  "setupModes": [
20128
20118
  {
@@ -20158,8 +20148,8 @@ var ACP_ACCOUNT_PROFILES = {
20158
20148
  }
20159
20149
  ],
20160
20150
  "notes": [
20161
- "The pinned ACP binary was initialized locally on Linux ARM64. Its authentication error documents this exact settings path and GEMINI_API_KEY input. Real provider authentication has not been tested.",
20162
- "The pinned binary requires IPv6 loopback (::1). Local initialization passed after enabling IPv6 loopback; sandbox-provider compatibility remains unverified."
20151
+ "The pinned ACP 1.3.0 binary passed local Linux ARM64 initialization and a real Gemini API-key acceptance: two paid turns, a native file-tool round trip, same-session resume, and memory recall.",
20152
+ "The pinned binary requires IPv6 loopback (::1). Local initialization and authenticated acceptance passed after enabling IPv6 loopback; sandbox-provider compatibility still requires release-template evidence."
20163
20153
  ],
20164
20154
  "sources": [
20165
20155
  "https://antigravity.google/docs/ide/extensions",
@@ -20500,43 +20490,6 @@ var ACP_ACCOUNT_PROFILES = {
20500
20490
  "https://github.com/mistralai/mistral-vibe/blob/main/README.md"
20501
20491
  ]
20502
20492
  },
20503
- "nova": {
20504
- "name": "Nova",
20505
- "version": "1.1.38",
20506
- "status": "documented",
20507
- "setupModes": [
20508
- {
20509
- "id": "anthropic",
20510
- "label": "Anthropic",
20511
- "fields": [
20512
- {
20513
- "key": "ANTHROPIC_API_KEY",
20514
- "label": "Anthropic API key",
20515
- "kind": "secret",
20516
- "required": true,
20517
- "source": "https://www.npmjs.com/package/@compass-ai/nova/v/1.1.38"
20518
- },
20519
- {
20520
- "key": "COMPASS_MODEL",
20521
- "label": "Model",
20522
- "kind": "string",
20523
- "required": true,
20524
- "source": "https://www.npmjs.com/package/@compass-ai/nova/v/1.1.38"
20525
- }
20526
- ],
20527
- "source": "https://www.npmjs.com/package/@compass-ai/nova/v/1.1.38",
20528
- "instructions": "Use a model from Nova\u2019s documentation. Nova may require first-time consent before it can run."
20529
- }
20530
- ],
20531
- "files": [],
20532
- "notes": [
20533
- "Provider environment configuration is documented. Authenticated ACP startup and first-run consent behavior require runtime verification."
20534
- ],
20535
- "sources": [
20536
- "https://github.com/Compass-Agentic-Platform/nova",
20537
- "https://www.npmjs.com/package/@compass-ai/nova/v/1.1.38"
20538
- ]
20539
- },
20540
20493
  "poolside": {
20541
20494
  "name": "Poolside",
20542
20495
  "version": "1.0.16",
@@ -20716,52 +20669,6 @@ var ACP_ACCOUNT_PROFILES = {
20716
20669
  "https://raw.githubusercontent.com/vinhnx/VTCode/main/docs/config/CONFIG_FIELD_REFERENCE.md"
20717
20670
  ]
20718
20671
  },
20719
- "agentpool": {
20720
- "name": "AgentPool",
20721
- "version": "2.9.18",
20722
- "status": "documented",
20723
- "setupModes": [
20724
- {
20725
- "id": "configuration",
20726
- "label": "Native configuration",
20727
- "fields": [
20728
- {
20729
- "key": "file:.config/agentpool/agentpool.yml",
20730
- "label": "AgentPool agents and provider configuration",
20731
- "kind": "yaml",
20732
- "required": true,
20733
- "file": ".config/agentpool/agentpool.yml",
20734
- "source": "https://pypi.org/project/agentpool/2.9.18/"
20735
- },
20736
- {
20737
- "key": "provider_environment",
20738
- "label": "Provider environment JSON",
20739
- "kind": "json",
20740
- "required": false,
20741
- "source": "https://github.com/phil65/agentpool",
20742
- "environment": true
20743
- }
20744
- ],
20745
- "source": "https://pypi.org/project/agentpool/2.9.18/",
20746
- "instructions": "Import the agents and model configuration. If your selected provider uses environment credentials, include its documented variables as a JSON object of string values."
20747
- }
20748
- ],
20749
- "files": [
20750
- {
20751
- "path": ".config/agentpool/agentpool.yml",
20752
- "format": "yaml",
20753
- "required": true,
20754
- "source": "https://pypi.org/project/agentpool/2.9.18/"
20755
- }
20756
- ],
20757
- "notes": [
20758
- "The pinned 2.9.18 wheel confirms the native default path and explicit serve-acp config argument. The supplied YAML must select the intended agent and model."
20759
- ],
20760
- "sources": [
20761
- "https://github.com/phil65/agentpool",
20762
- "https://pypi.org/project/agentpool/2.9.18/"
20763
- ]
20764
- },
20765
20672
  "blackbox": {
20766
20673
  "name": "Blackbox AI",
20767
20674
  "version": null,
@@ -21175,6 +21082,13 @@ var MAX_FILESYSTEM_COMPONENT_BYTES = 255;
21175
21082
  var MAX_STAGED_COMPONENT_BYTES = MAX_FILESYSTEM_COMPONENT_BYTES - 13;
21176
21083
 
21177
21084
  // ../../packages/spec/src/usage.ts
21085
+ var rateLimitWindowSchema = external_exports.object({
21086
+ /** The vendor's window name: `five_hour`, `seven_day`, `primary`, ... */
21087
+ window: external_exports.string().min(1).max(64),
21088
+ usedPercent: external_exports.number().min(0).max(100),
21089
+ resetsAt: external_exports.iso.datetime({ offset: true }).nullish(),
21090
+ windowMinutes: external_exports.number().int().positive().nullish()
21091
+ });
21178
21092
  var usageReportSchema = external_exports.object({
21179
21093
  idempotencyKey: external_exports.string().min(1).max(128),
21180
21094
  /** "turn" = pod self-report (one per turn); "model-gateway" = RFC-0071
@@ -21197,6 +21111,8 @@ var usageReportSchema = external_exports.object({
21197
21111
  basis: external_exports.enum(["provider", "estimated"]).default("provider"),
21198
21112
  interrupted: external_exports.boolean().default(false),
21199
21113
  durationMs: external_exports.number().int().min(0).nullish(),
21114
+ /** Plan allowance windows observed during a subscription turn (pod reports only). */
21115
+ rateLimits: external_exports.array(rateLimitWindowSchema).max(16).optional(),
21200
21116
  /** Supplier request start, set by the trusted model gateway. */
21201
21117
  occurredAt: external_exports.iso.datetime({ offset: true }).nullish(),
21202
21118
  /** Trusted product origin captured by the model gateway at call start. */
@@ -21212,6 +21128,17 @@ var usageReportSchema = external_exports.object({
21212
21128
  usageRaw: external_exports.unknown().nullish()
21213
21129
  });
21214
21130
 
21131
+ // ../../packages/spec/src/subscription-limits.ts
21132
+ var observedWindowSchema = rateLimitWindowSchema.extend({
21133
+ /** When this window was last reported; windows are reported one at a time. */
21134
+ observedAt: external_exports.iso.datetime({ offset: true })
21135
+ });
21136
+ var observedLimitsSchema = external_exports.object({
21137
+ observedAt: external_exports.iso.datetime({ offset: true }),
21138
+ windows: external_exports.array(observedWindowSchema).max(16)
21139
+ });
21140
+ var WEEK_MINUTES = 7 * 24 * 60;
21141
+
21215
21142
  // ../../packages/spec/src/connection-support.ts
21216
21143
  var CHANNEL_IDS = ["slack", "telegram", "whatsapp", "imessage", "discord", "lark", "teams", "x", "email", "gchat", "line", "buzz"];
21217
21144
  var connectionSupportSchema = external_exports.object({
@@ -21220,7 +21147,7 @@ var connectionSupportSchema = external_exports.object({
21220
21147
  }).strict();
21221
21148
 
21222
21149
  // ../../packages/spec/src/question.ts
21223
- var QUESTION_REQUEST_KINDS = ["connect_app"];
21150
+ var QUESTION_REQUEST_KINDS = ["connect_app", "connect_account", "spend"];
21224
21151
  var questionSchema = external_exports.object({
21225
21152
  requestId: external_exports.string().min(1),
21226
21153
  question: external_exports.string().trim().min(1),
@@ -21246,7 +21173,7 @@ var questionSchema = external_exports.object({
21246
21173
  /** What the platform is asking for when the question is one of its own
21247
21174
  * requests rather than an agent's free question. Absent on an ordinary question. */
21248
21175
  kind: external_exports.enum(QUESTION_REQUEST_KINDS).optional(),
21249
- /** What the request is about: the app to connect, for `connect_app`. */
21176
+ /** What the request is about: the app to connect for `connect_app`, the vendor for `connect_account`, the agent's handle for `spend`. */
21250
21177
  subject: external_exports.string().trim().min(1).max(200).optional()
21251
21178
  }).superRefine((value, context) => {
21252
21179
  if (new Set(value.options.map((option) => option.id)).size !== value.options.length) {
@@ -21906,6 +21833,24 @@ function isFilePayload(node2) {
21906
21833
  return typeof node2.data === "string" && node2.data !== "" && (typeof node2.media_type === "string" || typeof node2.mime_type === "string" || node2.type === "import.resource" || node2.type === "base64");
21907
21834
  }
21908
21835
 
21836
+ // ../../packages/spec/src/code-review.ts
21837
+ var codeReviewTargetSchema = external_exports.string().trim().max(2048).transform((value, ctx) => {
21838
+ try {
21839
+ const url2 = new URL(value);
21840
+ const match = /^\/([\w.-]+)\/([\w.-]+)\/pull\/([1-9]\d*)(?:\/.*)?$/.exec(url2.pathname);
21841
+ if (url2.protocol !== "https:" || url2.hostname !== "github.com" || url2.port || url2.username || url2.password || !match || !Number.isSafeInteger(Number(match[3]))) throw new Error();
21842
+ return { owner: match[1], repo: match[2], number: Number(match[3]), url: `https://github.com/${match[1]}/${match[2]}/pull/${match[3]}` };
21843
+ } catch {
21844
+ ctx.addIssue({ code: "custom", message: "Enter a GitHub pull request URL." });
21845
+ return external_exports.NEVER;
21846
+ }
21847
+ });
21848
+ var codeReviewRequestSchema = external_exports.discriminatedUnion("action", [
21849
+ external_exports.object({ action: external_exports.literal("read"), url: codeReviewTargetSchema }).strict(),
21850
+ external_exports.object({ action: external_exports.literal("open"), url: codeReviewTargetSchema }).strict(),
21851
+ external_exports.object({ action: external_exports.literal("review"), url: codeReviewTargetSchema, head: external_exports.string().regex(/^[a-f0-9]{40}$/i), body: external_exports.string().trim().max(65536), event: external_exports.enum(["COMMENT", "APPROVE", "REQUEST_CHANGES"]) }).strict().refine((request) => request.event === "APPROVE" || request.body.length > 0, { path: ["body"], message: "Add a review comment." })
21852
+ ]);
21853
+
21909
21854
  // ../../packages/spec/src/index.ts
21910
21855
  var NATIVE_AGENT_TYPES = [
21911
21856
  "hermes",
@@ -22012,7 +21957,6 @@ var allowedLlms = {
22012
21957
  sigit: [...ACP_PLATFORM_MODELS.sigit, "harness-default"],
22013
21958
  stakpak: [...ACP_PLATFORM_MODELS.stakpak, "harness-default"],
22014
21959
  vtcode: [...ACP_PLATFORM_MODELS.vtcode, "harness-default"],
22015
- agentpool: [...ACP_PLATFORM_MODELS.agentpool, "harness-default"],
22016
21960
  code_assistant: [...ACP_PLATFORM_MODELS.code_assistant, "harness-default"],
22017
21961
  docker_cagent: [...ACP_PLATFORM_MODELS.docker_cagent, "harness-default"],
22018
21962
  kiro: ["harness-default"],
@@ -22064,6 +22008,16 @@ var allowedLlms = {
22064
22008
  "gpt-6-astra",
22065
22009
  "deepseek-v4-pro",
22066
22010
  "deepseek-flash",
22011
+ "claude-opus-5-5",
22012
+ "claude-opus-5",
22013
+ "claude-fable-5-1",
22014
+ "claude-sonnet-5",
22015
+ "claude-haiku-4-5",
22016
+ "kimi-k3",
22017
+ "kimi-k2.7-code",
22018
+ "glm-5.3",
22019
+ "glm-5.3-flash",
22020
+ "grok-4.6",
22067
22021
  "gpt-5.5",
22068
22022
  "deepseek-v4-flash"
22069
22023
  ],
@@ -22072,6 +22026,9 @@ var allowedLlms = {
22072
22026
  "gpt-5.6-terra",
22073
22027
  "gpt-5.6-luna",
22074
22028
  "gpt-6-astra",
22029
+ "gpt-6.1-sol",
22030
+ "gpt-6-sol",
22031
+ "gpt-6-luna",
22075
22032
  "deepseek-v4-pro",
22076
22033
  "deepseek-flash",
22077
22034
  "gemini-3.8-flash",
@@ -22095,6 +22052,10 @@ var allowedLlms = {
22095
22052
  "gpt-5.6-terra",
22096
22053
  "gpt-5.6-luna",
22097
22054
  "gpt-6-astra",
22055
+ "gpt-6.1-sol",
22056
+ "gpt-6-sol",
22057
+ "gpt-6-luna",
22058
+ "gemini-3.8-flash",
22098
22059
  "deepseek-v4-pro",
22099
22060
  "deepseek-flash",
22100
22061
  "glm-5.3",
@@ -22133,6 +22094,9 @@ var allowedLlms = {
22133
22094
  "gpt-5.6-terra",
22134
22095
  "gpt-5.6-luna",
22135
22096
  "gpt-6-astra",
22097
+ "gpt-6.1-sol",
22098
+ "gpt-6-sol",
22099
+ "gpt-6-luna",
22136
22100
  "glm-5.3",
22137
22101
  "glm-5.3-flash",
22138
22102
  "grok-4.6",
@@ -22150,6 +22114,9 @@ var allowedLlms = {
22150
22114
  "gpt-5.6-terra",
22151
22115
  "gpt-5.6-luna",
22152
22116
  "gpt-6-astra",
22117
+ "gpt-6.1-sol",
22118
+ "gpt-6-sol",
22119
+ "gpt-6-luna",
22153
22120
  "deepseek-v4-pro",
22154
22121
  "deepseek-flash",
22155
22122
  "glm-5.3",
@@ -22203,6 +22170,7 @@ var CHATGPT_PLAN_MODELS = /* @__PURE__ */ new Set([
22203
22170
  "gpt-5.6-luna",
22204
22171
  "gpt-5.5"
22205
22172
  ]);
22173
+ var CHATGPT_PLAN_HARNESSES = /* @__PURE__ */ new Set(["codex", "pi", "hermes", "opencode", "openclaw"]);
22206
22174
  var CLAUDE_PLAN_MODELS = /* @__PURE__ */ new Set([
22207
22175
  "claude-opus-5",
22208
22176
  "claude-fable-5-1",
@@ -22214,7 +22182,7 @@ var CLAUDE_PLAN_MODELS = /* @__PURE__ */ new Set([
22214
22182
  ]);
22215
22183
  function modelSubscriptionProviderFor(agentType, llm) {
22216
22184
  if (agentType === "claude_code" && CLAUDE_PLAN_MODELS.has(llm)) return "anthropic";
22217
- if (agentType === "codex" && CHATGPT_PLAN_MODELS.has(llm)) return "openai";
22185
+ if (CHATGPT_PLAN_HARNESSES.has(agentType) && CHATGPT_PLAN_MODELS.has(llm)) return "openai";
22218
22186
  if (agentType === "cursor" && llm === "harness-default") return "cursor";
22219
22187
  if (agentType === "grok_build" && llm === "harness-default") return "xai";
22220
22188
  if (agentType === "muse_code" && llm === "harness-default") return "meta";
@@ -22254,7 +22222,7 @@ var AGENT_TYPE_META = {
22254
22222
  },
22255
22223
  codex: {
22256
22224
  label: "Codex",
22257
- blurb: "OpenAI's coding agent. Uses GPT models."
22225
+ blurb: "OpenAI's coding agent. Works with GPT, Claude, DeepSeek, Kimi, GLM and Grok."
22258
22226
  },
22259
22227
  openclaw: {
22260
22228
  label: "OpenClaw",
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  skillRefSchema,
17
17
  splitMcpServers,
18
18
  supersededBy
19
- } from "./chunk-WFTZR5YO.js";
19
+ } from "./chunk-NRTKH367.js";
20
20
 
21
21
  // src/index.ts
22
22
  import { existsSync as existsSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
@@ -64,7 +64,7 @@ function currentUniverse() {
64
64
  }
65
65
 
66
66
  // src/version.ts
67
- var CLI_VERSION = "2.8.0";
67
+ var CLI_VERSION = "2.9.0";
68
68
  var USER_AGENT = `sky-cli/${CLI_VERSION} (${process.platform}; node/${process.versions.node})`;
69
69
 
70
70
  // src/api.ts
@@ -185,7 +185,7 @@ async function resolveSessionRef(ref) {
185
185
  return agent2.defaultSessionId;
186
186
  }
187
187
  async function* streamEvents(sessionId, signal) {
188
- const { parseSseStream } = await import("./src-2DLGPJB6.js");
188
+ const { parseSseStream } = await import("./src-OEZ7BT2L.js");
189
189
  const res = await fetch(
190
190
  `${apiBase()}/sessions/${encodeURIComponent(sessionId)}/stream`,
191
191
  {
@@ -408,7 +408,7 @@ function scaffoldAgentFile(path, name) {
408
408
  path,
409
409
  `# agent.toml \u2014 everything the create wizard can set. Only \`name\` is required.
410
410
  name = "${name}"
411
- # type = "hermes" # hermes | claude_code | codex | openclaw | pi | dsh | kimi_code | opencode
411
+ # type = "pi" # pi (default) | hermes | claude_code | codex | openclaw | pi | dsh | kimi_code | opencode
412
412
  # llm = "deepseek-flash" # must be compatible with type
413
413
  # reasoning_effort = "high" # per harness \u2014 ${reasoningEffortDocLine()}
414
414
  # capabilities = []
@@ -626,7 +626,7 @@ async function createClone(local, opts) {
626
626
  if (local.truncated) console.log(" note: instructions exceeded 100k chars and were truncated");
627
627
  if (local.droppedServers.length) {
628
628
  console.log(
629
- `Dropped (need credentials \u2014 not supported yet): ${local.droppedServers.map((n) => `${n} MCP`).join(", ")}`
629
+ `Left out (need a key): ${local.droppedServers.map((n) => `${n} MCP`).join(", ")}. Run \`sky setup secrets\` to choose which keys to save to your vault.`
630
630
  );
631
631
  }
632
632
  if (opts.dryRun) {
@@ -740,7 +740,7 @@ async function syncClone(local, link, opts) {
740
740
  }
741
741
  if (local.droppedServers.length) {
742
742
  console.log(
743
- ` dropped (need credentials \u2014 not supported yet): ${local.droppedServers.map((n) => `${n} MCP`).join(", ")}`
743
+ ` left out (need a key): ${local.droppedServers.map((n) => `${n} MCP`).join(", ")}. Run \`sky setup secrets\` to choose which keys to save to your vault.`
744
744
  );
745
745
  }
746
746
  writeLink(local.configRoot, { ...link, lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString() });
@@ -845,10 +845,10 @@ function listClaudeCodeSessions(limit) {
845
845
  continue;
846
846
  }
847
847
  const workspace = decodeWorkspace(encoded);
848
- for (const entry of entries) {
849
- if (!entry.endsWith(".jsonl")) continue;
850
- const sessionId = entry.slice(0, -6);
851
- const mainFile = join3(projectDir, entry);
848
+ for (const entry2 of entries) {
849
+ if (!entry2.endsWith(".jsonl")) continue;
850
+ const sessionId = entry2.slice(0, -6);
851
+ const mainFile = join3(projectDir, entry2);
852
852
  let stat;
853
853
  try {
854
854
  stat = statSync(mainFile);
@@ -894,13 +894,13 @@ function listCodexSessions(limit) {
894
894
  } catch {
895
895
  return;
896
896
  }
897
- for (const entry of entries) {
898
- const full = join3(dir, entry.name);
899
- if (entry.isDirectory()) {
897
+ for (const entry2 of entries) {
898
+ const full = join3(dir, entry2.name);
899
+ if (entry2.isDirectory()) {
900
900
  walk(full);
901
901
  continue;
902
902
  }
903
- if (!entry.isFile() || !entry.name.startsWith("rollout-") || !entry.name.endsWith(".jsonl")) continue;
903
+ if (!entry2.isFile() || !entry2.name.startsWith("rollout-") || !entry2.name.endsWith(".jsonl")) continue;
904
904
  try {
905
905
  const first = readPrefix(full).split("\n", 1)[0];
906
906
  const meta = JSON.parse(first);
@@ -1269,92 +1269,179 @@ import { mkdirSync as mkdirSync3, readFileSync as readFileSync9, writeFileSync a
1269
1269
  import { dirname as dirname4, join as join8 } from "path";
1270
1270
  import { createInterface as createInterface3 } from "readline";
1271
1271
 
1272
- // src/setup-local.ts
1273
- import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
1274
- import { homedir as homedir5 } from "os";
1275
- import { dirname as dirname3, isAbsolute, join as join6, resolve as resolve3 } from "path";
1276
- import { parse as parseToml2 } from "smol-toml";
1272
+ // src/mcp-register.ts
1273
+ import { spawnSync } from "child_process";
1277
1274
 
1278
1275
  // src/skill.ts
1279
1276
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
1280
1277
  import { join as join5 } from "path";
1278
+
1279
+ // src/catalog-file.ts
1280
+ var CATALOG_FILE = "catalog.md";
1281
+ var CATEGORY_ORDER = ["websites", "content", "video", "code", "research", "general"];
1282
+ function categoryOf(agent2) {
1283
+ return CATEGORY_ORDER.find((category) => agent2.categories.includes(category)) ?? agent2.categories[0] ?? "general";
1284
+ }
1285
+ function describe(value) {
1286
+ const parts = Object.entries(value).filter(([, item]) => item !== null && item !== void 0 && item !== false && item !== "").map(([key, item]) => item === true ? key : `${key}: ${typeof item === "string" ? item : JSON.stringify(item)}`);
1287
+ return parts.length ? parts.join(", ") : null;
1288
+ }
1289
+ function entry(agent2) {
1290
+ const engine = agent2.engine_type ? ` \xB7 engine ${agent2.engine_type}` : "";
1291
+ const lines = [`### @${agent2.handle} \u2014 ${agent2.name}${engine}`, "", agent2.tagline];
1292
+ if (agent2.does.length) lines.push("", `Does: ${agent2.does.join("; ")}`);
1293
+ if (agent2.does_not.length) lines.push(`Does not: ${agent2.does_not.join("; ")}`);
1294
+ const { mcp_servers: mcpServers, ...rest } = agent2.requirements;
1295
+ if (typeof mcpServers === "boolean") lines.push(mcpServers ? "Can use MCP servers." : "Cannot use MCP servers.");
1296
+ const details = describe(rest);
1297
+ if (details) lines.push(`Details: ${details}`);
1298
+ const pricing = describe(agent2.pricing);
1299
+ if (pricing) lines.push(`Pricing: ${pricing}`);
1300
+ return lines.join("\n");
1301
+ }
1302
+ function renderCatalog(agents, generatedAt) {
1303
+ const header = [
1304
+ "# AgentSky agent catalog",
1305
+ "",
1306
+ `Every agent you can hire, as of ${generatedAt.toISOString()}. Start one with \`start_session\` and its handle, written with the @.`,
1307
+ "Run `npx @agentsky/sky setup` again to refresh this file; `search_catalog` always has the current list."
1308
+ ];
1309
+ if (!agents.length) return [...header, "", "The catalog was empty when this file was written. Use `search_catalog`.", ""].join("\n");
1310
+ const own = agents.filter((agent2) => agent2.visibility === "workspace");
1311
+ const shared = agents.filter((agent2) => agent2.visibility !== "workspace");
1312
+ const sections = [];
1313
+ if (own.length) sections.push(["## Your workspace's agents", ...own.map(entry)].join("\n\n"));
1314
+ const groups = /* @__PURE__ */ new Map();
1315
+ for (const agent2 of shared) groups.set(categoryOf(agent2), [...groups.get(categoryOf(agent2)) ?? [], agent2]);
1316
+ const ordered = [...groups.keys()].sort((a, b) => {
1317
+ const rank = (category) => CATEGORY_ORDER.includes(category) ? CATEGORY_ORDER.indexOf(category) : CATEGORY_ORDER.length;
1318
+ return rank(a) - rank(b) || a.localeCompare(b);
1319
+ });
1320
+ for (const category of ordered) {
1321
+ const title = category.charAt(0).toUpperCase() + category.slice(1);
1322
+ sections.push([`## ${title}`, ...groups.get(category).map(entry)].join("\n\n"));
1323
+ }
1324
+ return [...header, "", sections.join("\n\n"), ""].join("\n");
1325
+ }
1326
+
1327
+ // src/skill.ts
1281
1328
  var SKILL_NAME = "agentsky";
1282
1329
  var SKILL_MARKER = ".agentsky.json";
1283
1330
  function skillDocument() {
1284
1331
  return `---
1285
1332
  name: ${SKILL_NAME}
1286
- description: Hand part of a job to another agent running in the cloud through AgentSky, and bring its result back. Use when the person asks for another agent or a named engine (Claude Code, Codex, Hermes, OpenClaw and others) to do, test or review something, or when independent work could run in parallel.
1333
+ description: "Hire cloud agents from the AgentSky catalog (included as ${CATALOG_FILE}) and coordinate them on one task. Use when the person names an agent by @handle, asks to have another agent (or another engine such as Codex, Claude Code, Gemini or Hermes) do, test or review part of the work, wants work to keep running in the cloud, or the work splits into independent parts that can run at the same time. Works through the agentsky MCP server, or the sky command where those tools are missing."
1287
1334
  ---
1288
1335
 
1289
1336
  # Working with other agents through AgentSky
1290
1337
 
1291
- AgentSky runs long-lived agents in the cloud. With the \`sky\` command you can
1292
- find one, give it a job, and read what it produced. You stay responsible for
1293
- the result.
1294
-
1295
- If the \`agentsky\` MCP tools are available in this session (\`search_catalog\`,
1296
- \`start_session\`, \`read_session\`, \`send_message\`), use them instead of the
1297
- commands below; they do the same things.
1338
+ AgentSky runs long-lived agents in the cloud. You can hire them from its
1339
+ catalog, give each a part of the work, and collect what they produce. Agents you
1340
+ hire for the same piece of work share one task: a shared \`task/\` folder they all
1341
+ read and write, listed as one task in the person's AgentSky account. You stay
1342
+ responsible for the result.
1298
1343
 
1299
- ## Before you start
1344
+ Everything below is a tool of the \`agentsky\` MCP server. If those tools are
1345
+ missing in this session, use the \`sky\` commands under "Without the MCP tools"
1346
+ at the end; they do the same things, one agent at a time.
1300
1347
 
1301
- Run \`sky auth whoami\`. If it says you are not logged in, ask the person to run
1302
- \`sky auth login\` and stop there. Never ask them for a token.
1348
+ ## When to hire
1303
1349
 
1304
- ## When to hand work over
1305
-
1306
- - When the person asks another agent to do, test or review something, do that.
1307
- Honor an agent or engine they name.
1308
- - Otherwise, hand over work another agent is better suited to, or independent
1309
- parts that can run at the same time as your own.
1310
- - Do the work yourself when it is small, when it depends on what you already
1311
- have in front of you, or when explaining it would take as long as doing it.
1350
+ - When the person names an agent (\`@handle\`) or an engine, or asks another agent
1351
+ to test, review or do part of the work, do that. Do not substitute another one
1352
+ silently.
1353
+ - Otherwise hire for work another agent is better suited to than you are, for
1354
+ independent parts that can run at the same time, or for work that should keep
1355
+ going after this conversation ends.
1356
+ - Do the work yourself when it is small, when it depends on what you already have
1357
+ in front of you, or when explaining it would take as long as doing it.
1358
+ - Every hire spends the person's AgentSky balance. Say what you are about to hire
1359
+ and roughly what it may cost before the first one, unless they already asked
1360
+ for it.
1312
1361
 
1313
1362
  ## How to pick
1314
1363
 
1315
- \`sky catalog search <words for the work> --json\`
1364
+ Read \`${CATALOG_FILE}\` in this skill's folder. It lists every agent you can hire,
1365
+ your own workspace's first, then by category: its \`@handle\`, its engine, what it
1366
+ does and does not do, whether it can use MCP servers, and how it is paid. Pick by
1367
+ the work, not by the name, and respect what an agent says it does not do.
1316
1368
 
1317
- Each result has a \`handle\`, what the agent does, its \`engine_type\`, its
1318
- categories, how it is paid, and what it needs. If the person names an engine,
1319
- match its \`engine_type\` and do not substitute another one silently. Run the
1320
- command with no words to see every agent. If nothing fits, do the work
1321
- yourself and say so.
1369
+ Call \`search_catalog\` (with words for the work, or none to list everything)
1370
+ when \`${CATALOG_FILE}\` is missing, when nothing in it fits, or when the person names
1371
+ a handle it does not list: the catalog file is a snapshot from when the skill
1372
+ was installed. If nothing fits, do the work yourself and say so.
1322
1373
 
1323
1374
  ## How to brief
1324
1375
 
1325
- \`sky session create @<handle> --title "<short name>" --message "<brief>" --json\`
1376
+ Start the first agent with \`start_session\`:
1326
1377
 
1327
- It prints the new session's \`id\`. The agent starts working at once, on its own
1328
- computer in the cloud. It cannot see this conversation or this machine, so a
1329
- brief is one self-contained message that states:
1378
+ - \`agent_id\`: the handle, with its \`@\`.
1379
+ - \`message\`: the brief.
1380
+ - \`title\`: a short name for its part.
1381
+ - \`budget_cents\`: the most it may spend, in US cents. Always set one. When it is
1382
+ reached the agent pauses instead of spending more.
1383
+ - \`idempotency_key\`: a new unique value for this hire. Reuse it only to retry
1384
+ the exact same call after a timeout.
1330
1385
 
1331
- 1. what to produce,
1332
- 2. what "done" means,
1333
- 3. anything it must not do.
1386
+ The agent cannot see this conversation or your files. A brief is one
1387
+ self-contained paragraph that says:
1334
1388
 
1335
- To give it a file, add \`--file <path>\`. Never put a password, key or token in a
1336
- brief.
1389
+ 1. what to produce;
1390
+ 2. where to write it: a path under \`task/<its part>/\`;
1391
+ 3. what "done" means;
1392
+ 4. anything it must not do.
1337
1393
 
1338
- ## How to collect
1394
+ Never put a password, key or token in a brief.
1339
1395
 
1340
- \`sky session read <session id> --wait --json\`
1396
+ Its task id is the first session's id. Start every other agent for the same work
1397
+ with that \`task_id\`, so it sees the same \`task/\` folder and the person sees one
1398
+ task. To hand an agent a file, write it with \`write_task_file\` before you brief
1399
+ it, and name its path in the brief.
1341
1400
 
1342
- It waits until the agent finishes its turn and prints its messages, with
1343
- \`finished\` true or false. If \`finished\` is false the wait timed out: run it
1344
- again. A first turn can take a minute to begin while the agent's computer
1345
- starts.
1401
+ ## How to supervise
1346
1402
 
1347
- To correct it, answer it or ask for more:
1403
+ - Call \`read_session\` with the \`session_id\`, \`cursor\` and \`message_id\` that
1404
+ \`start_session\` or \`send_message\` returned and \`wait_seconds: 50\`. Call again
1405
+ with the returned cursor until \`turn_finished\` is true, and at once whenever
1406
+ \`has_more\` is true. The first turn also boots the agent's sandbox, which can
1407
+ take a minute.
1408
+ - Run independent agents at the same time: start them all, then read each.
1409
+ - To steer or answer an agent, \`send_message\` once its turn is finished.
1410
+ - If \`get_task\` shows a request waiting on the person (a question, an approval,
1411
+ or an app to connect with its link), show it to them and pass their answer with
1412
+ \`answer_request\`. Never approve spending or access on their behalf.
1413
+ - An agent that finishes its first turn with no reply did not start properly:
1414
+ \`stop_session\` it and hire again, or do that part yourself.
1348
1415
 
1349
- \`sky session message <session id> "<text>" --detach\`
1416
+ ## How to finish
1350
1417
 
1351
- then read again. An agent saying it is done is not evidence: check what it
1352
- produced before you rely on it.
1418
+ 1. \`collect_result\` for each agent: its last reply and the files it wrote.
1419
+ 2. Read the files with \`read_task_file\` and check each one exists and does what
1420
+ was asked. An agent saying "done" is not evidence.
1421
+ 3. Put the pieces together.
1422
+ 4. If the person should be able to open or share the result, \`publish_artifact\`
1423
+ the files; \`share_artifact\` only when they asked for a link.
1424
+ 5. \`stop_session\` every agent you no longer need.
1425
+ 6. Tell the person what was done, which agent did which part, and what it cost
1426
+ (\`get_task\` reports the task's cost).
1353
1427
 
1354
- ## How to finish
1428
+ ## Without the MCP tools
1355
1429
 
1356
- Tell the person what was done and which agent did which part. Every agent you
1357
- start is paid for by the person, so start only what the job needs.
1430
+ Run \`sky auth whoami\`. If it says you are not logged in, ask the person to run
1431
+ \`sky auth login\` and stop there. Never ask them for a token.
1432
+
1433
+ - Pick: \`sky catalog search <words for the work> --json\`. Each result has a
1434
+ \`handle\`, what the agent does, its \`engine_type\`, its categories, how it is
1435
+ paid, and what it needs. Run it with no words to see every agent.
1436
+ - Brief: \`sky session create @<handle> --title "<short name>" --message "<brief>" --json\`
1437
+ prints the new session's \`id\`. To give it a file, add \`--file <path>:/<name>\`:
1438
+ the file is in the agent's working directory under that name, read-only, so
1439
+ call it by that name in the brief.
1440
+ - Collect: \`sky session read <session id> --wait --json\` waits until the agent
1441
+ finishes its turn and prints its messages, with \`finished\` true or false. If
1442
+ \`finished\` is false the wait timed out: run it again. To correct it, answer it
1443
+ or ask for more, \`sky session message <session id> "<text>" --detach\`, then
1444
+ read again.
1358
1445
  `;
1359
1446
  }
1360
1447
  function installedVersion(dir) {
@@ -1372,16 +1459,71 @@ function installSkill(agent2, opts = {}) {
1372
1459
  const dir = join5(agent2.skillsDir, SKILL_NAME);
1373
1460
  const previous = installedVersion(dir);
1374
1461
  const outcome = previous === CLI_VERSION ? "current" : previous ? "updated" : "installed";
1375
- if (outcome !== "current" && !opts.dryRun) {
1462
+ if (opts.dryRun) return { agent: agent2.id, path: dir, outcome };
1463
+ if (outcome !== "current") {
1376
1464
  mkdirSync2(dir, { recursive: true });
1377
1465
  writeFileSync4(join5(dir, "SKILL.md"), skillDocument());
1378
1466
  writeFileSync4(join5(dir, SKILL_MARKER), `${JSON.stringify({ version: CLI_VERSION }, null, 2)}
1379
1467
  `);
1380
1468
  }
1469
+ if (opts.catalog) {
1470
+ mkdirSync2(dir, { recursive: true });
1471
+ writeFileSync4(join5(dir, CATALOG_FILE), renderCatalog(opts.catalog, opts.now ?? /* @__PURE__ */ new Date()));
1472
+ }
1381
1473
  return { agent: agent2.id, path: dir, outcome };
1382
1474
  }
1383
1475
 
1476
+ // src/mcp-register.ts
1477
+ var MCP_SERVER_NAME = SKILL_NAME;
1478
+ var CODEX_TOKEN_ENV = "AGENTSKY_API_KEY";
1479
+ function systemCommandRunner() {
1480
+ return {
1481
+ has: (command) => spawnSync(command, ["--version"], { stdio: "ignore" }).status === 0,
1482
+ run: (command, args) => {
1483
+ const result = spawnSync(command, args, { encoding: "utf8" });
1484
+ return { status: result.status, stderr: result.stderr ?? "" };
1485
+ }
1486
+ };
1487
+ }
1488
+ function mcpUrlFor(apiBase2) {
1489
+ return `${apiBase2.replace(/\/$/, "")}/mcp`;
1490
+ }
1491
+ function mcpCommands(agent2, opts) {
1492
+ if (agent2 === "claude_code") {
1493
+ return {
1494
+ command: "claude",
1495
+ remove: ["mcp", "remove", "--scope", "user", MCP_SERVER_NAME],
1496
+ add: ["mcp", "add", "--scope", "user", "--transport", "http", MCP_SERVER_NAME, opts.mcpUrl, "--header", `Authorization: Bearer ${opts.token}`]
1497
+ };
1498
+ }
1499
+ if (agent2 === "codex") {
1500
+ return {
1501
+ command: "codex",
1502
+ remove: ["mcp", "remove", MCP_SERVER_NAME],
1503
+ add: ["mcp", "add", MCP_SERVER_NAME, "--url", opts.mcpUrl, "--bearer-token-env-var", CODEX_TOKEN_ENV]
1504
+ };
1505
+ }
1506
+ return null;
1507
+ }
1508
+ function redact(text, token) {
1509
+ return text.split(token).join(`${token.slice(0, 10)}\u2026`);
1510
+ }
1511
+ function registerMcpServer(agent2, opts, runner = systemCommandRunner()) {
1512
+ const commands = mcpCommands(agent2.id, opts);
1513
+ if (!commands) return { agent: agent2.id, outcome: "unsupported" };
1514
+ if (!runner.has(commands.command)) return { agent: agent2.id, outcome: "no_command", detail: `${commands.command} is not on PATH` };
1515
+ if (opts.dryRun) return { agent: agent2.id, outcome: "planned", detail: redact([commands.command, ...commands.add].join(" "), opts.token) };
1516
+ runner.run(commands.command, commands.remove);
1517
+ const added = runner.run(commands.command, commands.add);
1518
+ if (added.status !== 0) return { agent: agent2.id, outcome: "failed", detail: redact(added.stderr.trim() || `exit ${added.status}`, opts.token) };
1519
+ return agent2.id === "codex" ? { agent: agent2.id, outcome: "registered", detail: `set ${CODEX_TOKEN_ENV} to an AgentSky API token in the shell that runs codex` } : { agent: agent2.id, outcome: "registered" };
1520
+ }
1521
+
1384
1522
  // src/setup-local.ts
1523
+ import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
1524
+ import { homedir as homedir5 } from "os";
1525
+ import { dirname as dirname3, isAbsolute, join as join6, resolve as resolve3 } from "path";
1526
+ import { parse as parseToml2 } from "smol-toml";
1385
1527
  var MAX_SKILL_FILE_BYTES = 1024 * 1024;
1386
1528
  var MAX_IMPORT_DEPTH = 5;
1387
1529
  var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules"]);
@@ -1395,12 +1537,12 @@ function sensitive(name) {
1395
1537
  }
1396
1538
  function skillFiles(root, prefix) {
1397
1539
  const files2 = [];
1398
- for (const entry of readdirSync2(root, { withFileTypes: true })) {
1399
- const path = join6(root, entry.name);
1400
- if (entry.isDirectory()) {
1401
- if (!SKIPPED_DIRS.has(entry.name)) files2.push(...skillFiles(path, `${prefix}/${entry.name}`));
1402
- } else if (entry.isFile() && !sensitive(entry.name) && statSync2(path).size <= MAX_SKILL_FILE_BYTES) {
1403
- files2.push({ path: `${prefix}/${entry.name}`, bytes: new Uint8Array(readFileSync7(path)) });
1540
+ for (const entry2 of readdirSync2(root, { withFileTypes: true })) {
1541
+ const path = join6(root, entry2.name);
1542
+ if (entry2.isDirectory()) {
1543
+ if (!SKIPPED_DIRS.has(entry2.name)) files2.push(...skillFiles(path, `${prefix}/${entry2.name}`));
1544
+ } else if (entry2.isFile() && !sensitive(entry2.name) && statSync2(path).size <= MAX_SKILL_FILE_BYTES) {
1545
+ files2.push({ path: `${prefix}/${entry2.name}`, bytes: new Uint8Array(readFileSync7(path)) });
1404
1546
  }
1405
1547
  }
1406
1548
  return files2;
@@ -1410,10 +1552,10 @@ function readLocalSkills(agents) {
1410
1552
  const ignored = [];
1411
1553
  for (const agent2 of agents) {
1412
1554
  if (!existsSync5(agent2.skillsDir)) continue;
1413
- for (const entry of readdirSync2(agent2.skillsDir, { withFileTypes: true })) {
1414
- const dir = join6(agent2.skillsDir, entry.name);
1415
- let isDir = entry.isDirectory();
1416
- if (entry.isSymbolicLink()) {
1555
+ for (const entry2 of readdirSync2(agent2.skillsDir, { withFileTypes: true })) {
1556
+ const dir = join6(agent2.skillsDir, entry2.name);
1557
+ let isDir = entry2.isDirectory();
1558
+ if (entry2.isSymbolicLink()) {
1417
1559
  try {
1418
1560
  isDir = statSync2(dir).isDirectory();
1419
1561
  } catch {
@@ -1431,7 +1573,7 @@ function readLocalSkills(agents) {
1431
1573
  ignored.push({ agent: agent2.id, dir, reason: `${taken.agent} already has a skill named ${name}` });
1432
1574
  continue;
1433
1575
  }
1434
- const files2 = skillFiles(dir, entry.name);
1576
+ const files2 = skillFiles(dir, entry2.name);
1435
1577
  skills.push({ name, agent: agent2.id, dir, files: files2, bytes: files2.reduce((sum, file) => sum + file.bytes.length, 0) });
1436
1578
  }
1437
1579
  }
@@ -1497,8 +1639,8 @@ function bearerOf(def) {
1497
1639
  if (typeof def.bearer_token === "string" && def.bearer_token.trim()) return def.bearer_token.trim();
1498
1640
  const headers = def.headers ?? def.http_headers;
1499
1641
  if (!headers || typeof headers !== "object") return null;
1500
- const entry = Object.entries(headers).find(([name]) => name.toLowerCase() === "authorization");
1501
- const match = typeof entry?.[1] === "string" ? /^Bearer\s+(\S+)$/i.exec(entry[1].trim()) : null;
1642
+ const entry2 = Object.entries(headers).find(([name]) => name.toLowerCase() === "authorization");
1643
+ const match = typeof entry2?.[1] === "string" ? /^Bearer\s+(\S+)$/i.exec(entry2[1].trim()) : null;
1502
1644
  return match?.[1] ?? null;
1503
1645
  }
1504
1646
  function serversOf(agent2, home) {
@@ -1743,12 +1885,25 @@ function confirm3(question) {
1743
1885
  function kb2(bytes) {
1744
1886
  return `${Math.max(1, Math.round(bytes / 1024))} KB`;
1745
1887
  }
1746
- function describe(event) {
1888
+ function describe2(event) {
1747
1889
  switch (event.type) {
1748
1890
  case "agents":
1749
1891
  return event.agents.length ? `Found on this computer: ${event.agents.map((agent2) => agent2.name).join(", ")}` : "No agent found on this computer (looked for Claude Code, Codex and Cursor).";
1892
+ case "catalog":
1893
+ return event.outcome === "read" ? ` agent catalog: ${event.agents} agent${event.agents === 1 ? "" : "s"}` : ` agent catalog: not read${event.detail ? ` (${event.detail})` : ""}; the skill looks agents up with search_catalog`;
1750
1894
  case "skill":
1751
1895
  return ` AgentSky skill ${event.outcome === "current" ? "already up to date" : event.outcome} for ${event.agent}`;
1896
+ case "mcp":
1897
+ switch (event.outcome) {
1898
+ case "registered":
1899
+ return ` agentsky MCP server registered for ${event.agent}${event.detail ? ` (${event.detail})` : ""}`;
1900
+ case "planned":
1901
+ return ` would run: ${event.detail}`;
1902
+ case "unsupported":
1903
+ return null;
1904
+ default:
1905
+ return ` agentsky MCP server not registered for ${event.agent}: ${event.detail ?? event.outcome}`;
1906
+ }
1752
1907
  case "plan":
1753
1908
  return ` ${event.provider} plan: ${event.outcome === "already" ? "already connected" : event.outcome}${event.detail ? ` (${event.detail})` : ""}`;
1754
1909
  case "found": {
@@ -1799,22 +1954,40 @@ async function connectedProviders() {
1799
1954
  const { modelSubscriptions } = await api("GET", "/model-subscriptions");
1800
1955
  return new Set(modelSubscriptions.map((subscription) => subscription.provider));
1801
1956
  }
1802
- async function defaultVaultId() {
1957
+ var WORKSPACE_VAULT_NAME = "default";
1958
+ async function findWorkspaceVault() {
1803
1959
  const { vaults } = await api("GET", "/vaults");
1804
- const existing = vaults.find((vault) => vault.display_name === "default");
1805
- if (existing) return existing.id;
1806
- return (await api("POST", "/vaults", { display_name: "default" })).vault.id;
1960
+ return vaults.find((vault) => vault.display_name === WORKSPACE_VAULT_NAME)?.id ?? null;
1961
+ }
1962
+ async function workspaceVaultId() {
1963
+ const existing = await findWorkspaceVault();
1964
+ if (existing) return existing;
1965
+ try {
1966
+ return (await api("POST", "/vaults", { display_name: WORKSPACE_VAULT_NAME })).vault.id;
1967
+ } catch (error) {
1968
+ const raced = error instanceof ApiError && error.status === 409 ? await findWorkspaceVault() : null;
1969
+ if (!raced) throw error;
1970
+ return raced;
1971
+ }
1807
1972
  }
1808
1973
  function message(error) {
1809
1974
  return error instanceof Error ? error.message : String(error);
1810
1975
  }
1976
+ async function readCatalog() {
1977
+ if (!apiToken()) return { catalog: null, detail: "not logged in" };
1978
+ try {
1979
+ return { catalog: (await api("GET", "/catalog/agents")).agents };
1980
+ } catch (error) {
1981
+ return { catalog: null, detail: message(error) };
1982
+ }
1983
+ }
1811
1984
  async function runSetup(opts) {
1812
1985
  const steps = opts.steps?.length ? opts.steps : [...SETUP_STEPS];
1813
1986
  const interactive = !opts.json && !opts.yes && !opts.dryRun;
1814
1987
  const emit = (event) => {
1815
1988
  if (opts.json) console.log(JSON.stringify(event));
1816
1989
  else {
1817
- const line = describe(event);
1990
+ const line = describe2(event);
1818
1991
  if (line) console.log(line);
1819
1992
  }
1820
1993
  };
@@ -1822,7 +1995,7 @@ async function runSetup(opts) {
1822
1995
  const has = (step) => steps.includes(step);
1823
1996
  const agents = selectLocalAgents(opts.agents);
1824
1997
  emit({ type: "agents", agents: agents.map((agent2) => ({ id: agent2.id, name: agent2.name })) });
1825
- const needsToken = !opts.dryRun && (has("logins") || has("secrets") || has("import") && !opts.key);
1998
+ const needsToken = !opts.dryRun && (has("skill") || has("logins") || has("secrets") || has("import") && !opts.key);
1826
1999
  if (needsToken && !apiToken()) {
1827
2000
  if (opts.json) throw new ApiError(401, "not_logged_in", "not logged in \u2014 run `sky auth login`");
1828
2001
  console.log("First, sign this computer in to AgentSky.");
@@ -1843,17 +2016,23 @@ async function runSetup(opts) {
1843
2016
  held = new Map((claimed.body.skills ?? []).map((skill) => [skill.name, skill.fingerprint]));
1844
2017
  };
1845
2018
  await tell();
1846
- if (has("skill") && agents.length && await agreed("Add the AgentSky skill to these agents, so they can hand work to others?")) {
2019
+ if (has("skill") && agents.length && await agreed("Add the AgentSky skill and MCP server to these agents, so they can hand work to others?")) {
2020
+ const { catalog: catalog2, detail } = await readCatalog();
2021
+ emit(catalog2 ? { type: "catalog", outcome: "read", agents: catalog2.length } : { type: "catalog", outcome: "unavailable", ...detail ? { detail } : {} });
2022
+ const token = apiToken();
1847
2023
  for (const agent2 of agents) {
1848
2024
  try {
1849
- const installed = installSkill(agent2, { dryRun: opts.dryRun });
2025
+ const installed = installSkill(agent2, { dryRun: opts.dryRun, catalog: catalog2 });
1850
2026
  emit({ type: "skill", agent: agent2.id, outcome: installed.outcome, path: installed.path });
1851
2027
  if (!opts.dryRun) run2.agents.push({ id: agent2.id, skill: installed.outcome });
1852
2028
  } catch (error) {
1853
2029
  emit({ type: "skill", agent: agent2.id, outcome: "failed", path: agent2.skillsDir });
1854
2030
  emit({ type: "error", code: "skill_install_failed", message: message(error) });
1855
2031
  run2.agents.push({ id: agent2.id, skill: "failed" });
2032
+ continue;
1856
2033
  }
2034
+ const registered = token ? registerMcpServer(agent2, { token, mcpUrl: mcpUrlFor(apiBase()), dryRun: opts.dryRun }) : { agent: agent2.id, outcome: "skipped", detail: "not logged in" };
2035
+ emit({ type: "mcp", agent: agent2.id, outcome: registered.outcome, ...registered.detail ? { detail: registered.detail } : {} });
1857
2036
  }
1858
2037
  await tell();
1859
2038
  }
@@ -1947,7 +2126,7 @@ async function saveSecrets(found, opts, interactive, emit) {
1947
2126
  continue;
1948
2127
  }
1949
2128
  try {
1950
- vaultId ??= await defaultVaultId();
2129
+ vaultId ??= await workspaceVaultId();
1951
2130
  await api("POST", `/vaults/${encodeURIComponent(vaultId)}/secrets`, {
1952
2131
  display_name: secret.name,
1953
2132
  auth: { type: "static_bearer", mcp_server_url: secret.url, token: secret.token }
@@ -2683,7 +2862,7 @@ program.command("skill").description("the AgentSky skill for the agents on this
2683
2862
  for (const i of installs) console.log(`${i.agent.padEnd(12)} ${verb[i.outcome].padEnd(14)} ${i.path}`);
2684
2863
  })
2685
2864
  );
2686
- program.command("setup [steps...]").description("bring this machine's agents to AgentSky: the skill, your plans, your skills and instructions, your tool keys").addHelpText("after", `
2865
+ program.command("setup [steps...]").description("bring this machine's agents to AgentSky: the skill and its MCP server, your plans, your skills and instructions, your tool keys").addHelpText("after", `
2687
2866
  Steps (all when none is named): ${SETUP_STEPS.join(" | ")}`).option("--key <key>", "a setup key from agentsky.dev/setup").option("--agent <id...>", "only these agents: claude_code | codex | cursor").option("--secret <name...>", "save these tool keys to your vault (asked one by one when omitted)").option("--no-claude", "leave the Claude plan alone").option("--plan <name...>", "connect only these plans: claude | chatgpt | cursor").option("--dry-run", "say what would be done; write and send nothing").option("-y, --yes", "do not ask before each step").option("--json", "print progress as one JSON object per line; never asks").action(
2688
2867
  run(async (steps, opts) => {
2689
2868
  const unknown = steps.find((step) => !SETUP_STEPS.includes(step));
package/dist/products.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  skillsArraySchema,
9
9
  systemMessageEventSchema,
10
10
  userMessageEventSchema
11
- } from "./chunk-WFTZR5YO.js";
11
+ } from "./chunk-NRTKH367.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-WFTZR5YO.js";
4
+ } from "./chunk-NRTKH367.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.8.0",
3
+ "version": "2.9.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",