@kikimoradev/kcloud 1.0.3 → 1.1.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.
Files changed (2) hide show
  1. package/dist/main.js +282 -37
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -781,9 +781,13 @@ const errorCodes = Object.keys({
781
781
  "runtime.monitor_draining": "conflict",
782
782
  "runtime.monitor_limited": "conflict",
783
783
  "runtime.monitor_check_unsupported": "rule_violation",
784
+ "runtime.task_deletion_unsupported": "rule_violation",
785
+ "task.not_found": "not_found",
786
+ "task.not_finished": "conflict",
784
787
  "node.not_found": "not_found",
785
788
  "node.name_taken": "conflict",
786
789
  "node.offline": "rule_violation",
790
+ "node.outdated": "rule_violation",
787
791
  "node.not_registered": "rule_violation",
788
792
  "node.registration_invalid": "unauthenticated",
789
793
  "node.registration_used": "conflict",
@@ -1235,10 +1239,16 @@ const agentEventSummarySchema = z.object({
1235
1239
  durationMs: z.int().nullable(),
1236
1240
  payload: z.record(z.string(), z.unknown())
1237
1241
  }).meta({ id: "AgentEventSummary" });
1242
+ const agentEventLimitSchema = z.coerce.number().int().min(1).max(500).default(200);
1238
1243
  z.object({
1239
1244
  since: z.string().max(64).optional(),
1240
- limit: z.coerce.number().int().min(1).max(500).default(200)
1245
+ limit: agentEventLimitSchema
1241
1246
  });
1247
+ z.object({
1248
+ before: z.string().max(64).optional(),
1249
+ limit: agentEventLimitSchema
1250
+ });
1251
+ pageSchema(agentEventSummarySchema).meta({ id: "LiveHistoryPage" });
1242
1252
  const taskStatuses = [
1243
1253
  "pending",
1244
1254
  "in_progress",
@@ -1247,6 +1257,13 @@ const taskStatuses = [
1247
1257
  "cancelled"
1248
1258
  ];
1249
1259
  const taskStatusSchema = z.enum(taskStatuses);
1260
+ const finalTaskStatuses = [
1261
+ "done",
1262
+ "failed",
1263
+ "cancelled"
1264
+ ];
1265
+ const finalTaskStatusSchema = z.enum(finalTaskStatuses);
1266
+ const taskDeletionKikimoraVersion = "0.14.0";
1250
1267
  const maxTaskDescriptionLength = 4e3;
1251
1268
  const agentTaskSchema = z.object({
1252
1269
  id: z.string(),
@@ -1262,15 +1279,31 @@ const agentTaskSchema = z.object({
1262
1279
  startedAt: z.iso.datetime().nullable(),
1263
1280
  finishedAt: z.iso.datetime().nullable()
1264
1281
  }).meta({ id: "AgentTask" });
1282
+ const agentTaskSourceSchema = z.enum(["worker", "projection"]);
1283
+ const agentTaskStaleReasonSchema = z.enum([
1284
+ "unreachable",
1285
+ "timeout",
1286
+ "stopped"
1287
+ ]).nullable();
1288
+ const taskCountsSchema = z.object({
1289
+ pending: z.int().nonnegative(),
1290
+ in_progress: z.int().nonnegative(),
1291
+ done: z.int().nonnegative(),
1292
+ failed: z.int().nonnegative(),
1293
+ cancelled: z.int().nonnegative()
1294
+ }).meta({ id: "TaskCounts" });
1265
1295
  z.object({
1266
1296
  items: z.array(agentTaskSchema),
1267
- source: z.enum(["worker", "projection"]),
1268
- staleReason: z.enum([
1269
- "unreachable",
1270
- "timeout",
1271
- "stopped"
1272
- ]).nullable()
1297
+ nextCursor: z.string().nullable(),
1298
+ counts: taskCountsSchema.nullable(),
1299
+ source: agentTaskSourceSchema,
1300
+ staleReason: agentTaskStaleReasonSchema
1273
1301
  }).meta({ id: "AgentTaskList" });
1302
+ z.object({
1303
+ task: agentTaskSchema,
1304
+ source: agentTaskSourceSchema,
1305
+ staleReason: agentTaskStaleReasonSchema
1306
+ }).meta({ id: "AgentTaskView" });
1274
1307
  z.object({
1275
1308
  title: z.string().trim().min(1).max(200).optional(),
1276
1309
  description: z.string().trim().min(1).max(maxTaskDescriptionLength)
@@ -1279,7 +1312,9 @@ z.object({
1279
1312
  state: z.enum(["requested", "running"]),
1280
1313
  cycle: z.int().nonnegative().nullable()
1281
1314
  }).meta({ id: "MonitorCheck" });
1282
- z.object({ status: taskStatusSchema.optional() });
1315
+ cursorQuerySchema.extend({ status: taskStatusSchema.optional() });
1316
+ z.object({ status: finalTaskStatusSchema });
1317
+ z.object({ deleted: z.array(z.string()) }).meta({ id: "AgentTasksDeleted" });
1283
1318
  z.object({
1284
1319
  id: idSchema,
1285
1320
  taskId: z.string().min(1).max(128)
@@ -2030,6 +2065,7 @@ const auditActionSchema = z.enum([
2030
2065
  "agent.action",
2031
2066
  "agent.backup_requested",
2032
2067
  "agent.restored",
2068
+ "agent.tasks_deleted",
2033
2069
  "platform.settings_updated",
2034
2070
  "runtime.sessions_updated",
2035
2071
  "platform.upgrade_requested",
@@ -2687,6 +2723,7 @@ z.object({
2687
2723
  //#endregion
2688
2724
  //#region ../../packages/contracts/src/agent-backups.ts
2689
2725
  const agentBackupTriggers = ["nightly", "manual"];
2726
+ const agentBackupUnavailableReasons = ["release_without_export"];
2690
2727
  const agentBackupSchema = z.object({
2691
2728
  id: idSchema,
2692
2729
  agentId: idSchema,
@@ -2699,9 +2736,15 @@ const agentBackupSchema = z.object({
2699
2736
  createdAt: z.iso.datetime(),
2700
2737
  expiresAt: z.iso.datetime()
2701
2738
  }).meta({ id: "AgentBackup" });
2739
+ const agentBackupUnavailableSchema = z.object({
2740
+ reason: z.enum(agentBackupUnavailableReasons),
2741
+ kikimoraVersion: z.string(),
2742
+ requiredVersion: z.string()
2743
+ }).meta({ id: "AgentBackupUnavailable" });
2702
2744
  z.object({
2703
2745
  items: z.array(agentBackupSchema),
2704
- retentionDays: z.int().positive()
2746
+ retentionDays: z.int().positive(),
2747
+ unavailable: agentBackupUnavailableSchema.nullable()
2705
2748
  }).meta({ id: "AgentBackupList" });
2706
2749
  z.object({ state: z.literal("requested") }).meta({ id: "AgentBackupRequested" });
2707
2750
  z.object({
@@ -2774,6 +2817,7 @@ const archiveSkipReasons = [
2774
2817
  "special_file",
2775
2818
  "unreadable"
2776
2819
  ];
2820
+ const omittedAgentReasons = ["remote_node", "unplaced"];
2777
2821
  const maxBackupRetentionDays = 3650;
2778
2822
  const maxPlatformSecretLength = 4096;
2779
2823
  const maxHostOperationOutputLength = 4096;
@@ -2968,6 +3012,12 @@ const archivedAgentSchema = z.object({
2968
3012
  message: "expected no more listed skipped files than skippedTotal",
2969
3013
  path: ["skippedTotal"]
2970
3014
  });
3015
+ const omittedAgentSchema = z.object({
3016
+ agentId: idSchema,
3017
+ slug: slugSchema,
3018
+ nodeId: idSchema.nullable(),
3019
+ reason: z.enum(omittedAgentReasons)
3020
+ });
2971
3021
  z.object({
2972
3022
  version: z.literal(1),
2973
3023
  backupId: idSchema,
@@ -2980,7 +3030,8 @@ z.object({
2980
3030
  cipher: z.literal(backupCipher),
2981
3031
  parts: z.array(backupPartSchema).refine(everyPartOnce, { message: `expected exactly the parts ${backupPartNames.join(", ")}` }),
2982
3032
  database: z.object({ pgVersion: z.string().min(1) }),
2983
- agents: z.array(archivedAgentSchema)
3033
+ agents: z.array(archivedAgentSchema),
3034
+ omitted: z.array(omittedAgentSchema).default([])
2984
3035
  });
2985
3036
  const hostOperationSchema = z.object({
2986
3037
  id: idSchema,
@@ -4247,7 +4298,9 @@ const restoredAgent = async (api, agentId, { backupId, name, node, slug }) => {
4247
4298
  }), restoreHints);
4248
4299
  };
4249
4300
  const keptFor = (days) => `A backup is kept for ${String(days)} ${days === 1 ? "day" : "days"}.`;
4250
- const backupsTable = ({ items, retentionDays }) => items.length === 0 ? `The agent has no backup yet. ${keptFor(retentionDays)}` : [renderTable([
4301
+ const unavailableNote = ({ unavailable }) => unavailable?.reason === "release_without_export" ? [`Kikimora ${unavailable.kikimoraVersion} cannot export the memory of the agent, so its node backs nothing up. Backups need ${unavailable.requiredVersion} or newer: move the agent with kcloud agents set, then kcloud agents update.`] : [];
4302
+ const backupsTable = (list) => [...unavailableNote(list), backupListing(list)].join("\n");
4303
+ const backupListing = ({ items, retentionDays }) => items.length === 0 ? `The agent has no backup yet. ${keptFor(retentionDays)}` : [renderTable([
4251
4304
  { header: "CREATED" },
4252
4305
  { header: "TRIGGER" },
4253
4306
  { header: "NODE" },
@@ -5031,6 +5084,7 @@ const collect = async (page, { limit, all }) => {
5031
5084
  cursor = next.nextCursor;
5032
5085
  }
5033
5086
  return {
5087
+ ...first,
5034
5088
  items,
5035
5089
  nextCursor: null
5036
5090
  };
@@ -5494,42 +5548,67 @@ const streamOptions = {
5494
5548
  default: false
5495
5549
  },
5496
5550
  since: { type: "string" },
5551
+ before: { type: "string" },
5497
5552
  limit: { type: "string" }
5498
5553
  };
5499
5554
  const streamUsage = [
5500
5555
  ...agentUsage,
5501
5556
  ["-f, --follow", "keep the stream open instead of leaving when the output stops"],
5502
5557
  ["--since <id>", "start after this event instead of at the start of the buffer"],
5503
- ["--limit <n>", "how many events to replay before the live ones"]
5558
+ ["--limit <n>", "how many events to replay before the live ones, or the page size with --before"]
5504
5559
  ];
5505
- const lineOf = (frame) => {
5506
- const parsed = agentEventSummarySchema.safeParse(frame.data);
5507
- if (!parsed.success) return JSON.stringify(frame.data);
5560
+ const beforeUsage = ["--before <id>", "print the stored output before this event and leave, oldest first"];
5561
+ const linePrinter = (json) => (data) => {
5562
+ if (json) return JSON.stringify(data);
5563
+ const parsed = agentEventSummarySchema.safeParse(data);
5564
+ if (!parsed.success) return JSON.stringify(data);
5508
5565
  const event = parsed.data;
5509
5566
  const text = "text" in event.payload && typeof event.payload.text === "string" ? event.payload.text : JSON.stringify(event.payload);
5510
5567
  return `${event.ts} ${event.level.padEnd(5)} ${event.agentRole ?? "-"} ${event.event} ${text}`;
5511
5568
  };
5569
+ const earlierOutput = async (session, agentId, before, limit) => dataOf("read the earlier output of the agent", await session.api.GET("/agents/{id}/live/history", { params: {
5570
+ path: { id: agentId },
5571
+ query: {
5572
+ before,
5573
+ ...limit === void 0 ? {} : { limit: Number(limit) }
5574
+ }
5575
+ } }), agentHints);
5576
+ const olderPageCommand = (reference, project, cursor, limit) => [
5577
+ "kcloud agents logs",
5578
+ reference,
5579
+ ...project === void 0 ? [] : ["--project", project],
5580
+ "--before",
5581
+ cursor,
5582
+ ...limit === void 0 ? [] : ["--limit", limit]
5583
+ ].join(" ");
5512
5584
  const streamCommands = (adaptersOf) => [{
5513
5585
  name: "logs",
5514
5586
  path: "/agents/{id}/live",
5515
5587
  summary: "Print what the agent is writing, and keep printing with --follow.",
5516
- resumable: false
5588
+ resumable: false,
5589
+ pagesBack: true
5517
5590
  }, {
5518
5591
  name: "events",
5519
5592
  path: "/agents/{id}/events",
5520
5593
  summary: "Print the stored events of the agent, and keep printing with --follow.",
5521
- resumable: true
5522
- }].map(({ name, path, summary, resumable }) => defineCommand({
5594
+ resumable: true,
5595
+ pagesBack: false
5596
+ }].map(({ name, path, summary, resumable, pagesBack }) => defineCommand({
5523
5597
  name,
5524
5598
  summary,
5525
- usage: `agents ${name} <agent> [--project <name>] [--follow] [--since <id>] [--limit <n>]`,
5526
- optionsUsage: streamUsage,
5599
+ usage: pagesBack ? `agents ${name} <agent> [--project <name>] [--follow] [--since <id>] [--before <id>] [--limit <n>]` : `agents ${name} <agent> [--project <name>] [--follow] [--since <id>] [--limit <n>]`,
5600
+ optionsUsage: pagesBack ? [...streamUsage, beforeUsage] : streamUsage,
5527
5601
  options: streamOptions,
5528
5602
  positionals: {
5529
5603
  min: 1,
5530
5604
  max: 1
5531
5605
  },
5532
5606
  run: async ({ values, positionals, settings, context }) => {
5607
+ const before = values.before;
5608
+ if (before !== void 0 && !pagesBack) throw new UsageError("--before reads the output of kcloud agents logs alone.");
5609
+ if (before !== void 0 && (values.follow || values.since !== void 0)) throw new UsageError("--before reads earlier output; leave out --follow and --since.");
5610
+ const limit = values.limit;
5611
+ if (limit !== void 0 && !/^[0-9]+$/u.test(limit)) throw new UsageError(`--limit ${limit} is not a whole number.`);
5533
5612
  const adapters = adaptersOf(context);
5534
5613
  const session = await openSession({
5535
5614
  settings,
@@ -5538,8 +5617,17 @@ const streamCommands = (adaptersOf) => [{
5538
5617
  });
5539
5618
  const reference = positionals[0] ?? "";
5540
5619
  const agentId = await resolveAgentId(session, reference, values.project);
5541
- const limit = values.limit;
5542
- if (limit !== void 0 && !/^[0-9]+$/u.test(limit)) throw new UsageError(`--limit ${limit} is not a whole number.`);
5620
+ const lineOf = linePrinter(settings.json);
5621
+ if (before !== void 0) {
5622
+ const page = await earlierOutput(session, agentId, before, limit);
5623
+ if (settings.json) {
5624
+ context.terminal.line(JSON.stringify(page));
5625
+ return exitCodes.ok;
5626
+ }
5627
+ for (const event of page.items) context.terminal.line(lineOf(event));
5628
+ context.terminal.error(context.terminal.errorStyles.dim(page.nextCursor === null ? "The stored output begins here." : `older: ${olderPageCommand(reference, values.project, page.nextCursor, limit)}`));
5629
+ return exitCodes.ok;
5630
+ }
5543
5631
  await streamFrames({
5544
5632
  origin: session.origin,
5545
5633
  token: session.token,
@@ -5558,7 +5646,7 @@ const streamCommands = (adaptersOf) => [{
5558
5646
  },
5559
5647
  onFrame: (frame) => {
5560
5648
  if (frame.event === "agent.state") return;
5561
- context.terminal.line(settings.json ? JSON.stringify(frame.data) : lineOf(frame));
5649
+ context.terminal.line(lineOf(frame.data));
5562
5650
  }
5563
5651
  });
5564
5652
  return exitCodes.ok;
@@ -5568,7 +5656,10 @@ const streamCommands = (adaptersOf) => [{
5568
5656
  //#region src/commands/agents/tasks.ts
5569
5657
  const taskHints = {
5570
5658
  ...agentHints,
5571
- "runtime.control_unreachable": "The worker is not answering; kcloud agents show <agent> tells whether it runs."
5659
+ "runtime.control_unreachable": "The worker is not answering; kcloud agents show <agent> tells whether it runs.",
5660
+ "task.not_found": "kcloud agents tasks list <agent> shows the tasks of the agent.",
5661
+ "task.not_finished": "Only done, failed and cancelled tasks can be deleted; kcloud agents tasks cancel <agent> <task> cancels a pending one.",
5662
+ "runtime.task_deletion_unsupported": `Move the agent to Kikimora ${taskDeletionKikimoraVersion} or newer with kcloud agents set, then kcloud agents update.`
5572
5663
  };
5573
5664
  const tasksCommand = (adaptersOf) => defineGroup({
5574
5665
  name: "tasks",
@@ -5578,11 +5669,21 @@ const tasksCommand = (adaptersOf) => defineGroup({
5578
5669
  defineCommand({
5579
5670
  name: "list",
5580
5671
  summary: "List the tasks of an agent.",
5581
- usage: "agents tasks list <agent> [--project <name>] [--status <status>]",
5582
- optionsUsage: [...agentUsage, ["--status <status>", `one of ${taskStatuses.join(", ")}`]],
5672
+ usage: "agents tasks list <agent> [--project <name>] [--status <status>] [--limit <n>] [--all]",
5673
+ optionsUsage: [
5674
+ ...agentUsage,
5675
+ ["--status <status>", `one of ${taskStatuses.join(", ")}`],
5676
+ ["--limit <n>", `how many tasks, newest first (default: 50)`],
5677
+ ["--all", "follow the cursor to the end instead of one page"]
5678
+ ],
5583
5679
  options: {
5584
5680
  ...agentOption,
5585
- status: { type: "string" }
5681
+ status: { type: "string" },
5682
+ limit: { type: "string" },
5683
+ all: {
5684
+ type: "boolean",
5685
+ default: false
5686
+ }
5586
5687
  },
5587
5688
  positionals: {
5588
5689
  min: 1,
@@ -5594,10 +5695,14 @@ const tasksCommand = (adaptersOf) => defineGroup({
5594
5695
  const given = invocation.values.status;
5595
5696
  const status = taskStatuses.find((candidate) => candidate === given);
5596
5697
  if (given !== void 0 && status === void 0) throw new UsageError(`--status ${given} is not a status of a task.`, `The statuses are ${taskStatuses.join(", ")}.`);
5597
- const listed = dataOf("list the tasks of the agent", await run.api.GET("/agents/{id}/tasks", { params: {
5698
+ const listed = await collect(async (cursor, limit) => dataOf("list the tasks of the agent", await run.api.GET("/agents/{id}/tasks", { params: {
5598
5699
  path: { id: agentId },
5599
- ...status === void 0 ? {} : { query: { status } }
5600
- } }), taskHints);
5700
+ query: {
5701
+ limit,
5702
+ ...cursor === null ? {} : { cursor },
5703
+ ...status === void 0 ? {} : { status }
5704
+ }
5705
+ } }), taskHints), windowOf(invocation.values.limit, invocation.values.all));
5601
5706
  return printed(run, listed, (page) => page.items.length === 0 ? "The agent has no task in its queue." : renderTable([
5602
5707
  { header: "STATUS" },
5603
5708
  { header: "TITLE" },
@@ -5610,12 +5715,42 @@ const tasksCommand = (adaptersOf) => defineGroup({
5610
5715
  ], page.items.map((task) => [
5611
5716
  task.status,
5612
5717
  task.title,
5613
- `${String(task.attempt)}/${String(task.maxAttempts)}`,
5718
+ task.attempt === null ? "-" : task.maxAttempts === null ? String(task.attempt) : `${String(task.attempt)}/${String(task.maxAttempts)}`,
5614
5719
  task.costUsd === null ? "-" : task.costUsd.toFixed(2),
5615
5720
  task.id
5616
5721
  ])));
5617
5722
  }
5618
5723
  }),
5724
+ defineCommand({
5725
+ name: "show",
5726
+ summary: "Show one task of an agent with its description and error.",
5727
+ usage: "agents tasks show <agent> <task> [--project <name>]",
5728
+ optionsUsage: agentUsage,
5729
+ options: agentOption,
5730
+ positionals: {
5731
+ min: 2,
5732
+ max: 2
5733
+ },
5734
+ run: async (invocation) => {
5735
+ const run = await runOf(adaptersOf, invocation);
5736
+ const agentId = await agentFrom(run, invocation.positionals[0], invocation.values.project);
5737
+ const taskId = invocation.positionals[1] ?? "";
5738
+ const view = dataOf("read the task", await run.api.GET("/agents/{id}/tasks/{taskId}", { params: { path: {
5739
+ id: agentId,
5740
+ taskId
5741
+ } } }), taskHints);
5742
+ return printed(run, view, ({ task }) => [
5743
+ `${task.title} (${task.id})`,
5744
+ `status ${task.status}`,
5745
+ `attempt ${task.attempt === null ? "-" : String(task.attempt)}${task.maxAttempts === null ? "" : `/${String(task.maxAttempts)}`}`,
5746
+ `created ${task.createdAt ?? "-"}`,
5747
+ `started ${task.startedAt ?? "-"}`,
5748
+ `finished ${task.finishedAt ?? "-"}`,
5749
+ ...task.error === null ? [] : [`error ${task.error}`],
5750
+ ...task.description === null ? [] : ["", task.description]
5751
+ ].join("\n"));
5752
+ }
5753
+ }),
5619
5754
  defineCommand({
5620
5755
  name: "add",
5621
5756
  summary: "Put a task in the queue of an agent.",
@@ -5695,9 +5830,50 @@ const tasksCommand = (adaptersOf) => defineGroup({
5695
5830
  } } }), taskHints);
5696
5831
  return said(run, `Cancelled the task ${taskId}.`);
5697
5832
  }
5833
+ }),
5834
+ defineCommand({
5835
+ name: "delete",
5836
+ summary: "Delete a finished task, or every task of one final status.",
5837
+ usage: "agents tasks delete <agent> <task> [--project <name>] | agents tasks delete <agent> --status <status> [--project <name>]",
5838
+ optionsUsage: [...agentUsage, ["--status <status>", `one of ${finalTaskStatuses.join(", ")}`]],
5839
+ options: {
5840
+ ...agentOption,
5841
+ status: { type: "string" }
5842
+ },
5843
+ positionals: {
5844
+ min: 1,
5845
+ max: 2
5846
+ },
5847
+ run: async (invocation) => {
5848
+ const taskId = invocation.positionals[1];
5849
+ const given = invocation.values.status;
5850
+ if (taskId === void 0 === (given === void 0)) throw new UsageError("agents tasks delete needs either a task or --status, not both.", "kcloud agents tasks delete <agent> <task> deletes one task.");
5851
+ const status = finalTaskStatuses.find((candidate) => candidate === given);
5852
+ if (given !== void 0 && status === void 0) throw new UsageError(`--status ${given} is not a final status of a task.`, `Only ${finalTaskStatuses.join(", ")} tasks can be deleted.`);
5853
+ const run = await runOf(adaptersOf, invocation);
5854
+ const agentId = await agentFrom(run, invocation.positionals[0], invocation.values.project);
5855
+ await confirmed({
5856
+ prompt: run.prompt,
5857
+ settings: run.settings,
5858
+ question: status === void 0 ? `Delete the task ${taskId ?? ""}?` : `Delete every ${status} task of the agent?${status === "done" ? " The monitor may report them again." : ""}`
5859
+ });
5860
+ const answer = dataOf("delete the tasks", status === void 0 ? await run.api.DELETE("/agents/{id}/tasks/{taskId}", { params: { path: {
5861
+ id: agentId,
5862
+ taskId: taskId ?? ""
5863
+ } } }) : await run.api.DELETE("/agents/{id}/tasks", { params: {
5864
+ path: { id: agentId },
5865
+ query: { status }
5866
+ } }), taskHints);
5867
+ return printed(run, answer, ({ deleted }) => deletedSummary(deleted.length, status ?? null, taskId ?? null));
5868
+ }
5698
5869
  })
5699
5870
  ]
5700
5871
  });
5872
+ const deletedSummary = (count, status, taskId) => {
5873
+ if (status === null) return `Deleted the task ${taskId ?? ""}.`;
5874
+ if (count === 0) return `The agent has no ${status} task.`;
5875
+ return `Deleted ${String(count)} ${status} ${count === 1 ? "task" : "tasks"}.`;
5876
+ };
5701
5877
  const descriptionOf = async (run, given) => {
5702
5878
  if (given === "-") {
5703
5879
  const chunks = [];
@@ -6783,7 +6959,7 @@ const agentBackupTools = [
6783
6959
  defineTool({
6784
6960
  name: "agent_backups_list",
6785
6961
  title: "List the backups of an agent",
6786
- description: "List the backups of the memory of an agent, the newest first, with their trigger, node, Kikimora release, entries, size and expiry, and the days a backup is kept.",
6962
+ description: "List the backups of the memory of an agent, the newest first, with their trigger, node, Kikimora release, entries, size and expiry, the days a backup is kept, and in unavailable why the node makes none, such as a Kikimora release that exports no memory.",
6787
6963
  operations: ["listAgentBackups"],
6788
6964
  safety: "read",
6789
6965
  input: z.object(agentFields),
@@ -7203,6 +7379,25 @@ const observabilityTools = [
7203
7379
  }
7204
7380
  } }), agentHints)
7205
7381
  }),
7382
+ defineTool({
7383
+ name: "agent_earlier_output",
7384
+ title: "Read the earlier output of an agent",
7385
+ description: "Read what an agent wrote before an event, oldest first: the newest page without before. Pass nextCursor as before to read the page before that; null means the stored output begins here.",
7386
+ operations: ["listAgentLiveHistory"],
7387
+ safety: "read",
7388
+ input: z.object({
7389
+ ...agentFields,
7390
+ before: z.string().trim().min(1).max(64).optional().describe("End the page before this event id."),
7391
+ limit: z.int().min(1).max(500).optional().describe("How many events to read.")
7392
+ }),
7393
+ run: async ({ before, limit, ...reference }, run) => dataOf("read the earlier output of the agent", await run.api.GET("/agents/{id}/live/history", { params: {
7394
+ path: { id: await agentIdOf(run, reference) },
7395
+ query: {
7396
+ ...before === void 0 ? {} : { before },
7397
+ ...limit === void 0 ? {} : { limit }
7398
+ }
7399
+ } }), agentHints)
7400
+ }),
7206
7401
  defineTool({
7207
7402
  name: "agent_events",
7208
7403
  title: "Read the events of an agent",
@@ -8902,17 +9097,40 @@ const taskTools = [
8902
9097
  defineTool({
8903
9098
  name: "agent_tasks_list",
8904
9099
  title: "List the tasks of an agent",
8905
- description: "List the task queue of an agent, with the status, attempts and cost of each task.",
9100
+ description: "List the task queue of an agent, newest first, with the status, attempts and cost of each task.",
8906
9101
  operations: ["listAgentTasks"],
8907
9102
  safety: "read",
8908
9103
  input: z.object({
8909
9104
  ...agentFields,
9105
+ ...pageFields,
8910
9106
  status: z.enum(taskStatuses).optional()
8911
9107
  }),
8912
- run: async ({ status, ...reference }, run) => dataOf("list the tasks of the agent", await run.api.GET("/agents/{id}/tasks", { params: {
8913
- path: { id: await agentIdOf(run, reference) },
8914
- ...status === void 0 ? {} : { query: { status } }
8915
- } }), taskHints)
9108
+ run: async ({ status, limit, all, ...reference }, run) => {
9109
+ const agentId = await agentIdOf(run, reference);
9110
+ return collect(async (cursor, size) => dataOf("list the tasks of the agent", await run.api.GET("/agents/{id}/tasks", { params: {
9111
+ path: { id: agentId },
9112
+ query: {
9113
+ limit: size,
9114
+ ...cursor === null ? {} : { cursor },
9115
+ ...status === void 0 ? {} : { status }
9116
+ }
9117
+ } }), taskHints), windowOfPage({
9118
+ limit,
9119
+ all
9120
+ }));
9121
+ }
9122
+ }),
9123
+ defineTool({
9124
+ name: "agent_task_show",
9125
+ title: "Show a task",
9126
+ description: "Read one task of an agent with its description, status, attempts, cost and error.",
9127
+ operations: ["getAgentTask"],
9128
+ safety: "read",
9129
+ input: z.object(taskFields),
9130
+ run: async ({ task, ...reference }, run) => dataOf("read the task", await run.api.GET("/agents/{id}/tasks/{taskId}", { params: { path: {
9131
+ id: await agentIdOf(run, reference),
9132
+ taskId: task
9133
+ } } }), taskHints)
8916
9134
  }),
8917
9135
  defineTool({
8918
9136
  name: "agent_task_add",
@@ -8962,6 +9180,33 @@ const taskTools = [
8962
9180
  } } }), taskHints);
8963
9181
  return { cancelled: task };
8964
9182
  }
9183
+ }),
9184
+ defineTool({
9185
+ name: "agent_task_delete",
9186
+ title: "Delete a task",
9187
+ description: "Delete a done, failed or cancelled task of an agent. A monitor may report a deleted done task again.",
9188
+ operations: ["deleteAgentTask"],
9189
+ safety: "destructive",
9190
+ input: z.object(taskFields),
9191
+ run: async ({ task, ...reference }, run) => dataOf("delete the task", await run.api.DELETE("/agents/{id}/tasks/{taskId}", { params: { path: {
9192
+ id: await agentIdOf(run, reference),
9193
+ taskId: task
9194
+ } } }), taskHints)
9195
+ }),
9196
+ defineTool({
9197
+ name: "agent_tasks_delete",
9198
+ title: "Delete the tasks of a status",
9199
+ description: "Delete every task of an agent with one final status: done, failed or cancelled. A monitor may report a deleted done task again.",
9200
+ operations: ["deleteAgentTasks"],
9201
+ safety: "destructive",
9202
+ input: z.object({
9203
+ ...agentFields,
9204
+ status: z.enum(finalTaskStatuses)
9205
+ }),
9206
+ run: async ({ status, ...reference }, run) => dataOf("delete the tasks", await run.api.DELETE("/agents/{id}/tasks", { params: {
9207
+ path: { id: await agentIdOf(run, reference) },
9208
+ query: { status }
9209
+ } }), taskHints)
8965
9210
  })
8966
9211
  ];
8967
9212
  //#endregion
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "publishConfig": {
16
16
  "access": "public"
17
17
  },
18
- "version": "1.0.3",
18
+ "version": "1.1.0",
19
19
  "dependencies": {
20
20
  "@clack/prompts": "1.8.1",
21
21
  "@modelcontextprotocol/server": "2.1.0",