@kikimoradev/kcloud 1.5.2 → 1.5.4

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.
Files changed (2) hide show
  1. package/dist/main.js +80 -13
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -839,6 +839,7 @@ const errorCodes = Object.keys({
839
839
  "infrastructure.provider_error": "internal",
840
840
  "infrastructure.operation_in_progress": "conflict",
841
841
  "infrastructure.host_ops_disabled": "rule_violation",
842
+ "platform.isolated": "rule_violation",
842
843
  "backup.not_found": "not_found",
843
844
  "backup.in_progress": "conflict",
844
845
  "backup.unavailable": "rule_violation",
@@ -1130,7 +1131,9 @@ const agentProvisionSchema = z.object({
1130
1131
  "ok",
1131
1132
  "fetch_failed",
1132
1133
  "clone_failed"
1133
- ])
1134
+ ]),
1135
+ brokenCloneMovedTo: z.string().optional(),
1136
+ locksKeptForSandbox: z.array(z.string()).optional()
1134
1137
  })),
1135
1138
  docker: z.enum([
1136
1139
  "ready",
@@ -1151,6 +1154,10 @@ const agentProgressSchema = z.object({
1151
1154
  layersTotal: z.int().nonnegative().nullable(),
1152
1155
  updatedAt: z.iso.datetime()
1153
1156
  }).meta({ id: "AgentProgress" });
1157
+ const agentClaudeCodeSchema = z.object({
1158
+ version: z.string().nullable(),
1159
+ source: z.enum(["release", "host"])
1160
+ }).meta({ id: "AgentClaudeCode" });
1154
1161
  const storageStates = [
1155
1162
  "ok",
1156
1163
  "warning",
@@ -1593,10 +1600,17 @@ z.object({
1593
1600
  monitor: sessionSlotCountSchema.nullable(),
1594
1601
  executor: sessionSlotCountSchema.nullable()
1595
1602
  }).meta({ id: "UpdateSessionSlotsBody" });
1603
+ const admissionWaitReasonSchema = z.enum([
1604
+ "slot",
1605
+ "pool",
1606
+ "earlier_run",
1607
+ "renewal"
1608
+ ]);
1596
1609
  const agentAdmissionStateSchema = z.discriminatedUnion("state", [z.object({
1597
1610
  state: z.literal("waiting"),
1598
1611
  since: z.iso.datetime(),
1599
- position: z.int().positive()
1612
+ position: z.int().positive(),
1613
+ reason: admissionWaitReasonSchema
1600
1614
  }), z.object({ state: z.literal("holding") })]).meta({ id: "AgentAdmissionState" });
1601
1615
  const agentAdmissionSchema = z.object({
1602
1616
  monitor: agentAdmissionStateSchema.nullable(),
@@ -1816,6 +1830,8 @@ const nodeAgentSchema = z.object({
1816
1830
  projectId: idSchema,
1817
1831
  projectName: z.string(),
1818
1832
  state: agentStateSchema,
1833
+ failureReason: z.string().nullable(),
1834
+ retryAt: z.iso.datetime().nullable(),
1819
1835
  poolLimit: poolLimitSchema.nullable()
1820
1836
  }).meta({ id: "NodeAgent" });
1821
1837
  const nodeRuntimeSchema = z.object({
@@ -2131,7 +2147,10 @@ const cliTokenReadySchema = z.object({
2131
2147
  user: meSchema
2132
2148
  }).meta({ id: "CliTokenReady" });
2133
2149
  z.discriminatedUnion("status", [cliTokenWaitingSchema, cliTokenReadySchema]).meta({ id: "ClaimedCliToken" });
2134
- z.object({ version: z.string() }).meta({ id: "PlatformVersion" });
2150
+ z.object({
2151
+ version: z.string(),
2152
+ isolated: z.boolean()
2153
+ }).meta({ id: "PlatformVersion" });
2135
2154
  const auditActionSchema = z.enum([
2136
2155
  "platform.bootstrapped",
2137
2156
  "organization.created",
@@ -2695,7 +2714,8 @@ const agentRuntimeSchema = z.object({
2695
2714
  stopDeadlineAt: z.iso.datetime().nullable(),
2696
2715
  admission: agentAdmissionSchema.nullable(),
2697
2716
  admissionHold: admissionHoldSchema.nullable(),
2698
- poolLimit: poolLimitSchema.nullable()
2717
+ poolLimit: poolLimitSchema.nullable(),
2718
+ claudeCode: agentClaudeCodeSchema.nullable()
2699
2719
  }).meta({ id: "AgentRuntime" });
2700
2720
  const agentListItemSchema = z.object({
2701
2721
  id: idSchema,
@@ -3053,6 +3073,14 @@ pageSchema(z.object({
3053
3073
  }).meta({ id: "Backup" })).meta({ id: "BackupPage" });
3054
3074
  z.object({ id: idSchema });
3055
3075
  z.object({ confirm: z.string().min(1).max(512) }).meta({ id: "RestoreBackupBody" });
3076
+ const syncedBackupCountSchema = z.int().nonnegative();
3077
+ z.object({
3078
+ discovered: syncedBackupCountSchema,
3079
+ vanished: syncedBackupCountSchema,
3080
+ reappeared: syncedBackupCountSchema,
3081
+ finished: syncedBackupCountSchema,
3082
+ abandoned: syncedBackupCountSchema
3083
+ }).meta({ id: "BackupSync" });
3056
3084
  const backupPartSchema = z.object({
3057
3085
  name: z.enum(backupPartNames),
3058
3086
  bytes: byteCountSchema$1,
@@ -3956,12 +3984,14 @@ const createVersionCommand = (adaptersOf, cliVersion) => defineCommand({
3956
3984
  kcloud: cliVersion,
3957
3985
  instance: platform.version,
3958
3986
  origin: session.origin,
3959
- matched
3987
+ matched,
3988
+ isolated: platform.isolated
3960
3989
  });
3961
3990
  return exitCodes.ok;
3962
3991
  }
3963
3992
  context.terminal.line(renderTable([{ header: "WHAT" }, { header: "VERSION" }], [["kcloud", cliVersion], [session.origin, platform.version]]));
3964
3993
  if (!matched) context.terminal.error(context.terminal.errorStyles.warning(`warning kcloud ${cliVersion} is talking to an instance on ${platform.version}.`));
3994
+ if (platform.isolated) context.terminal.error(context.terminal.errorStyles.warning(`warning ${session.origin} is isolated: it reaches no outside service and admits no node.`));
3965
3995
  return exitCodes.ok;
3966
3996
  }
3967
3997
  });
@@ -4047,7 +4077,7 @@ const providerHints = {
4047
4077
  "provider.token_unauthorized": "DigitalOcean refused the token. Create a new one under API, Tokens in its control panel.",
4048
4078
  "concurrency.conflict": "Someone changed the account meanwhile; run the command again."
4049
4079
  };
4050
- const reasonOf$1 = (error) => {
4080
+ const reasonOf$2 = (error) => {
4051
4081
  const reason = error.details.reason;
4052
4082
  return typeof reason === "string" && reason !== "" ? `: ${reason}` : "";
4053
4083
  };
@@ -4063,7 +4093,7 @@ const explained = (error) => {
4063
4093
  const failure = apiErrorOf$1(error);
4064
4094
  switch (failure?.code) {
4065
4095
  case "provider.token_scopes_missing": return new CliError(failure.message, `The token lacks ${missingScopesOf(failure)}. kcloud providers add --help lists every scope it needs.`, { cause: failure });
4066
- case "provider.unavailable": return new CliError(failure.message, `DigitalOcean did not answer as expected${reasonOf$1(failure)}. Try again in a moment.`, { cause: failure });
4096
+ case "provider.unavailable": return new CliError(failure.message, `DigitalOcean did not answer as expected${reasonOf$2(failure)}. Try again in a moment.`, { cause: failure });
4067
4097
  default: return error;
4068
4098
  }
4069
4099
  };
@@ -4713,6 +4743,11 @@ const agentsOf = async (scope, project) => {
4713
4743
  }
4714
4744
  return listed;
4715
4745
  };
4746
+ const changeTakingActions = ["start", "update"];
4747
+ const changeTakerOf = ({ availableActions }) => {
4748
+ const takers = changeTakingActions.filter((action) => availableActions.includes(action)).map((action) => `kcloud agents ${action}`);
4749
+ return takers.length === 0 ? "a restart" : takers.join(" or ");
4750
+ };
4716
4751
  const changedAgent = async (api, agentId, document) => {
4717
4752
  const current = dataOf("describe the agent", await api.GET("/agents/{id}", { params: { path: { id: agentId } } }), agentHints);
4718
4753
  const change = typeof document === "object" && document !== null && "version" in document ? document : {
@@ -4804,7 +4839,7 @@ const configCommands = (adaptersOf) => [
4804
4839
  const file = invocation.values.file;
4805
4840
  if (file === void 0) throw new UsageError("agents set needs --file <path>.", "The file holds the sections to change; kcloud agents show <agent> --json shows the current ones.");
4806
4841
  const agent = await changedAgent(run.api, agentId, agentChangeWithoutLimits(run, await documentOf(run, file)));
4807
- return printed(run, agent, (changed) => changed.restartRequired ? `Changed ${changed.name}; it needs kcloud agents update to take the change.` : `Changed ${changed.name}.`);
4842
+ return printed(run, agent, (changed) => changed.restartRequired ? `Changed ${changed.name}; it needs ${changeTakerOf(changed)} to take the change.` : `Changed ${changed.name}.`);
4808
4843
  }
4809
4844
  }),
4810
4845
  defineCommand({
@@ -4848,9 +4883,25 @@ const admissionRowsOf = (agent) => {
4848
4883
  const { admission } = agent.runtime;
4849
4884
  return admission === null ? [] : [["monitor slot", slotOf(admission.monitor)], ["executor slot", slotOf(admission.executor)]];
4850
4885
  };
4851
- const admissionHoldRowsOf = ({ runtime }) => {
4852
- const hold = runtime.admissionHold;
4853
- if (hold == null) return [];
4886
+ const waitTexts = {
4887
+ slot: "waits for a slot",
4888
+ pool: "held by the pool of the node",
4889
+ earlier_run: "held until the node restarts its run of an earlier task run",
4890
+ renewal: "held while the node restarts the run"
4891
+ };
4892
+ const reasonOf$1 = ({ reason }) => reason ?? "slot";
4893
+ const waitRowsOf = ({ runtime }) => {
4894
+ const { admission } = runtime;
4895
+ if (admission === null) return [];
4896
+ const waits = ["monitor", "executor"].flatMap((role) => {
4897
+ const state = admission[role];
4898
+ return state?.state === "waiting" ? [`${role} ${waitTexts[reasonOf$1(state)]}`] : [];
4899
+ });
4900
+ return waits.length === 0 ? [] : [["admissions", waits.join("; ")]];
4901
+ };
4902
+ const admissionHoldRowsOf = (agent) => {
4903
+ const hold = agent.runtime.admissionHold;
4904
+ if (hold == null) return waitRowsOf(agent);
4854
4905
  if (hold.updating || hold.awaits === "start") return [["admissions", `held while the node updates to ${hold.target ?? "-"}`]];
4855
4906
  const all = hold.pools.includes("monitor");
4856
4907
  const noun = all ? "session" : "executor session";
@@ -4858,6 +4909,15 @@ const admissionHoldRowsOf = ({ runtime }) => {
4858
4909
  return [["admissions", `${all ? "held" : "executor held"} for the node update to ${hold.target ?? "-"}, waiting for ${waits}`]];
4859
4910
  };
4860
4911
  const poolLimitRowsOf = ({ runtime }) => runtime.poolLimit === null ? [] : [["pool limit", poolLimitText(runtime.poolLimit)]];
4912
+ const claudeCodeOf = ({ runtime, release }) => {
4913
+ const running = runtime.claudeCode ?? null;
4914
+ if (running?.source === "host") return "host";
4915
+ return running?.version ?? release?.claudeCodeVersion ?? "unknown";
4916
+ };
4917
+ const failureRowsOf = ({ failureReason, retryAt }) => {
4918
+ if (failureReason === null) return [];
4919
+ return [["failure", retryAt === null ? failureReason : `${failureReason}, retry at ${retryAt}`]];
4920
+ };
4861
4921
  const detailsOf = (agent) => [
4862
4922
  renderTable([{ header: "FIELD" }, { header: "VALUE" }], [
4863
4923
  ["name", agent.name],
@@ -4866,6 +4926,7 @@ const detailsOf = (agent) => [
4866
4926
  ["wanted", agent.desiredState],
4867
4927
  ["observed", agent.observedState],
4868
4928
  ["release", agent.kikimoraVersion],
4929
+ ["claude code", claudeCodeOf(agent)],
4869
4930
  ["node", agent.node === null ? "none" : `${agent.node.name} (${agent.node.state})`],
4870
4931
  ["requires", agent.requiredCapabilities.length === 0 ? "nothing" : agent.requiredCapabilities.join(", ")],
4871
4932
  ["timezone", agent.timezone],
@@ -4874,6 +4935,7 @@ const detailsOf = (agent) => [
4874
4935
  ["browser", agent.machine.browser ? "yes" : "no"],
4875
4936
  ["container", agent.runtime.containerId ?? "none"],
4876
4937
  ["health", agent.runtime.health],
4938
+ ...failureRowsOf(agent),
4877
4939
  ...admissionRowsOf(agent),
4878
4940
  ...admissionHoldRowsOf(agent),
4879
4941
  ...poolLimitRowsOf(agent),
@@ -6695,7 +6757,7 @@ const agentTools = [
6695
6757
  defineTool({
6696
6758
  name: "agent_update",
6697
6759
  title: "Change an agent",
6698
- description: "Change sections of an agent. Without version the change applies to the version read just before it. When restartRequired comes back true, agent_action update applies the change.",
6760
+ description: "Change sections of an agent. Without version the change applies to the version read just before it. When restartRequired comes back true, agent_action start or update applies the change, whichever availableActions offers.",
6699
6761
  operations: ["updateAgent"],
6700
6762
  safety: "write",
6701
6763
  input: z.object({
@@ -6733,7 +6795,7 @@ const agentTools = [
6733
6795
  defineTool({
6734
6796
  name: "agent_action",
6735
6797
  title: "Start, pause, resume, restart or update an agent",
6736
- description: "start lets the agent work, pause holds it between sessions, resume lets a paused agent work again, restart restarts its container, update replaces the container to apply pending changes. The agent returns with the actions it takes next.",
6798
+ description: "start lets the agent work and applies pending changes, pause holds it between sessions, resume lets a paused agent work again, restart restarts its container, update replaces the container to apply pending changes. The agent returns with the actions it takes next.",
6737
6799
  operations: ["runAgentAction"],
6738
6800
  safety: "write",
6739
6801
  input: z.object({
@@ -9957,6 +10019,10 @@ const lastUpdateOf = ({ update }) => {
9957
10019
  const outcome = `${last.outcome} ${last.version ?? "-"} at ${last.at}`;
9958
10020
  return last.reason === null ? outcome : `${outcome}: ${last.reason}`;
9959
10021
  };
10022
+ const agentFailuresOf = ({ agents }) => agents.flatMap(({ slug, failureReason, retryAt }) => {
10023
+ if (failureReason === null) return [];
10024
+ return [`${slug} failure: ${retryAt === null ? failureReason : `${failureReason}, retry at ${retryAt}`}`];
10025
+ });
9960
10026
  const nodeDetailsText = (node) => [
9961
10027
  renderTable([{ header: "FIELD" }, { header: "VALUE" }], [
9962
10028
  ["name", node.name],
@@ -9995,6 +10061,7 @@ const nodeDetailsText = (node) => [
9995
10061
  poolLimitText(agent.poolLimit),
9996
10062
  agent.id
9997
10063
  ])),
10064
+ ...agentFailuresOf(node),
9998
10065
  "",
9999
10066
  ...node.runtime === null ? ["The node has reported no runtime yet."] : [
10000
10067
  renderTable([{ header: "RUNTIME" }, { header: "VALUE" }], runtimeRowsOf(node.runtime, node.engine)),
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "publishConfig": {
16
16
  "access": "public"
17
17
  },
18
- "version": "1.5.2",
18
+ "version": "1.5.4",
19
19
  "dependencies": {
20
20
  "@clack/prompts": "1.8.1",
21
21
  "@modelcontextprotocol/server": "2.1.0",