@skrr-ai/cli 0.1.21 → 0.1.23

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 (245) hide show
  1. package/README.md +83 -73
  2. package/bin/dev-fallback.js +221 -0
  3. package/bin/run.js +43 -0
  4. package/dist/base-command.d.ts +15 -0
  5. package/dist/base-command.js +71 -10
  6. package/dist/commands/agents/attach-harness.d.ts +37 -0
  7. package/dist/commands/agents/attach-harness.js +102 -3
  8. package/dist/commands/agents/chat.d.ts +69 -1
  9. package/dist/commands/agents/chat.js +202 -22
  10. package/dist/commands/agents/create.d.ts +38 -0
  11. package/dist/commands/agents/create.js +95 -2
  12. package/dist/commands/agents/schedule-trace.js +11 -0
  13. package/dist/commands/agents/show.js +29 -1
  14. package/dist/commands/api-keys/create.d.ts +24 -0
  15. package/dist/commands/api-keys/create.js +80 -0
  16. package/dist/commands/api-keys/list.d.ts +11 -0
  17. package/dist/commands/api-keys/list.js +42 -0
  18. package/dist/commands/api-keys/revoke.d.ts +14 -0
  19. package/dist/commands/api-keys/revoke.js +33 -0
  20. package/dist/commands/api-keys/rotate.d.ts +19 -0
  21. package/dist/commands/api-keys/rotate.js +42 -0
  22. package/dist/commands/balance/index.d.ts +18 -0
  23. package/dist/commands/balance/index.js +29 -0
  24. package/dist/commands/balance/show.d.ts +25 -0
  25. package/dist/commands/balance/show.js +60 -0
  26. package/dist/commands/balance/statement.d.ts +19 -0
  27. package/dist/commands/balance/statement.js +52 -0
  28. package/dist/commands/browser/doctor.d.ts +11 -0
  29. package/dist/commands/browser/doctor.js +11 -0
  30. package/dist/commands/code/jobs/approve.d.ts +25 -0
  31. package/dist/commands/code/jobs/approve.js +52 -0
  32. package/dist/commands/code/jobs/cancel.d.ts +12 -0
  33. package/dist/commands/code/jobs/cancel.js +39 -0
  34. package/dist/commands/code/jobs/index.d.ts +19 -0
  35. package/dist/commands/code/jobs/index.js +38 -0
  36. package/dist/commands/code/jobs/list.d.ts +12 -0
  37. package/dist/commands/code/jobs/list.js +87 -0
  38. package/dist/commands/code/jobs/run.d.ts +32 -0
  39. package/dist/commands/code/jobs/run.js +151 -0
  40. package/dist/commands/code/jobs/show.d.ts +12 -0
  41. package/dist/commands/code/jobs/show.js +86 -0
  42. package/dist/commands/commitments/create.d.ts +1 -0
  43. package/dist/commands/commitments/create.js +19 -5
  44. package/dist/commands/commitments/preflight.js +18 -4
  45. package/dist/commands/commitments/receipt-metrics.d.ts +39 -0
  46. package/dist/commands/commitments/receipt-metrics.js +78 -0
  47. package/dist/commands/convos/search.js +5 -5
  48. package/dist/commands/harnesses/leases/list.d.ts +3 -0
  49. package/dist/commands/harnesses/leases/list.js +59 -12
  50. package/dist/commands/harnesses/leases/show.js +36 -0
  51. package/dist/commands/harnesses/list.d.ts +18 -0
  52. package/dist/commands/harnesses/list.js +30 -0
  53. package/dist/commands/harnesses/products.js +48 -3
  54. package/dist/commands/harnesses/quota.d.ts +16 -0
  55. package/dist/commands/harnesses/quota.js +26 -1
  56. package/dist/commands/harnesses/usage.js +17 -0
  57. package/dist/commands/inbox/index.d.ts +2 -1
  58. package/dist/commands/inbox/index.js +27 -4
  59. package/dist/commands/login.js +4 -1
  60. package/dist/commands/machines/list.d.ts +1 -0
  61. package/dist/commands/machines/list.js +33 -5
  62. package/dist/commands/memory/approvals/issue.d.ts +18 -0
  63. package/dist/commands/memory/approvals/issue.js +63 -0
  64. package/dist/commands/memory/commit.js +5 -2
  65. package/dist/commands/memory/context.d.ts +3 -2
  66. package/dist/commands/memory/context.js +9 -11
  67. package/dist/commands/memory/delete.d.ts +1 -1
  68. package/dist/commands/memory/list.d.ts +1 -1
  69. package/dist/commands/memory/list.js +1 -1
  70. package/dist/commands/memory/mounts/resolve.d.ts +10 -0
  71. package/dist/commands/memory/mounts/resolve.js +27 -0
  72. package/dist/commands/memory/proposals/commit.d.ts +18 -0
  73. package/dist/commands/memory/proposals/commit.js +32 -0
  74. package/dist/commands/memory/proposals/create.d.ts +18 -0
  75. package/dist/commands/memory/proposals/create.js +56 -0
  76. package/dist/commands/memory/proposals/list.d.ts +13 -0
  77. package/dist/commands/memory/proposals/list.js +31 -0
  78. package/dist/commands/memory/proposals/promote.d.ts +22 -0
  79. package/dist/commands/memory/proposals/promote.js +33 -0
  80. package/dist/commands/memory/proposals/reject.d.ts +16 -0
  81. package/dist/commands/memory/proposals/reject.js +28 -0
  82. package/dist/commands/memory/rebuild-index.d.ts +20 -0
  83. package/dist/commands/memory/rebuild-index.js +25 -0
  84. package/dist/commands/memory/save.d.ts +1 -1
  85. package/dist/commands/memory/save.js +1 -1
  86. package/dist/commands/memory/search.d.ts +6 -3
  87. package/dist/commands/memory/search.js +27 -3
  88. package/dist/commands/memory/show.d.ts +1 -1
  89. package/dist/commands/memory/stores/archive.d.ts +14 -0
  90. package/dist/commands/memory/stores/archive.js +31 -0
  91. package/dist/commands/memory/stores/create.d.ts +12 -0
  92. package/dist/commands/memory/stores/create.js +30 -0
  93. package/dist/commands/memory/stores/delete.d.ts +15 -0
  94. package/dist/commands/memory/stores/delete.js +38 -0
  95. package/dist/commands/memory/stores/list.d.ts +10 -0
  96. package/dist/commands/memory/stores/list.js +29 -0
  97. package/dist/commands/memory/stores/show.d.ts +12 -0
  98. package/dist/commands/memory/stores/show.js +14 -0
  99. package/dist/commands/memory/stores/update.d.ts +15 -0
  100. package/dist/commands/memory/stores/update.js +39 -0
  101. package/dist/commands/memory/sync/delete.d.ts +13 -0
  102. package/dist/commands/memory/sync/delete.js +35 -0
  103. package/dist/commands/memory/sync/pull.d.ts +19 -0
  104. package/dist/commands/memory/sync/pull.js +52 -0
  105. package/dist/commands/memory/sync/push.d.ts +18 -0
  106. package/dist/commands/memory/sync/push.js +115 -0
  107. package/dist/commands/memory/sync/resolve.d.ts +23 -0
  108. package/dist/commands/memory/sync/resolve.js +27 -0
  109. package/dist/commands/memory/sync/status.d.ts +9 -0
  110. package/dist/commands/memory/sync/status.js +22 -0
  111. package/dist/commands/memory/topics/archive.d.ts +20 -0
  112. package/dist/commands/memory/topics/archive.js +29 -0
  113. package/dist/commands/memory/topics/create.d.ts +23 -0
  114. package/dist/commands/memory/topics/create.js +46 -0
  115. package/dist/commands/memory/topics/delete.d.ts +22 -0
  116. package/dist/commands/memory/topics/delete.js +30 -0
  117. package/dist/commands/memory/topics/forget.d.ts +22 -0
  118. package/dist/commands/memory/topics/forget.js +29 -0
  119. package/dist/commands/memory/topics/list.d.ts +13 -0
  120. package/dist/commands/memory/topics/list.js +22 -0
  121. package/dist/commands/memory/topics/move.d.ts +22 -0
  122. package/dist/commands/memory/topics/move.js +26 -0
  123. package/dist/commands/memory/topics/show.d.ts +17 -0
  124. package/dist/commands/memory/topics/show.js +21 -0
  125. package/dist/commands/memory/topics/update.d.ts +23 -0
  126. package/dist/commands/memory/topics/update.js +27 -0
  127. package/dist/commands/memory/tree.d.ts +5 -2
  128. package/dist/commands/memory/tree.js +20 -2
  129. package/dist/commands/memory/update.d.ts +1 -1
  130. package/dist/commands/memory/versions/list.d.ts +16 -0
  131. package/dist/commands/memory/versions/list.js +22 -0
  132. package/dist/commands/memory/versions/redact.d.ts +21 -0
  133. package/dist/commands/memory/versions/redact.js +22 -0
  134. package/dist/commands/memory/versions/restore.d.ts +20 -0
  135. package/dist/commands/memory/versions/restore.js +16 -0
  136. package/dist/commands/memory/versions/show.d.ts +15 -0
  137. package/dist/commands/memory/versions/show.js +17 -0
  138. package/dist/commands/messages/list.js +25 -8
  139. package/dist/commands/messages/show.js +10 -0
  140. package/dist/commands/store/install.js +5 -1
  141. package/dist/commands/store/releases.js +1 -1
  142. package/dist/commands/store/update.js +5 -1
  143. package/dist/commands/subscriptions/cancel.js +5 -1
  144. package/dist/commands/subscriptions/health.js +5 -1
  145. package/dist/commands/subscriptions/status.js +5 -1
  146. package/dist/commands/subscriptions/subscribe.js +5 -1
  147. package/dist/commands/tasks/activity.d.ts +2 -3
  148. package/dist/commands/tasks/activity.js +15 -5
  149. package/dist/commands/tasks/complete.d.ts +18 -150
  150. package/dist/commands/tasks/complete.js +161 -600
  151. package/dist/commands/tasks/create.d.ts +5 -0
  152. package/dist/commands/tasks/create.js +107 -4
  153. package/dist/commands/tasks/deliverable/add.d.ts +8 -0
  154. package/dist/commands/tasks/deliverable/add.js +41 -8
  155. package/dist/commands/tasks/deliverable/confirm.d.ts +5 -5
  156. package/dist/commands/tasks/deliverable/confirm.js +9 -18
  157. package/dist/commands/tasks/deliverable/list.d.ts +12 -0
  158. package/dist/commands/tasks/deliverable/list.js +37 -0
  159. package/dist/commands/tasks/events/append.d.ts +2 -0
  160. package/dist/commands/tasks/events/append.js +11 -4
  161. package/dist/commands/tasks/events/list.d.ts +1 -0
  162. package/dist/commands/tasks/events/list.js +1 -0
  163. package/dist/commands/tasks/events/tail.d.ts +1 -0
  164. package/dist/commands/tasks/events/tail.js +1 -0
  165. package/dist/commands/tasks/expectations/assess.d.ts +21 -0
  166. package/dist/commands/tasks/expectations/assess.js +77 -0
  167. package/dist/commands/tasks/expectations.js +14 -18
  168. package/dist/commands/tasks/judge.d.ts +1 -0
  169. package/dist/commands/tasks/judge.js +2 -1
  170. package/dist/commands/tasks/output.d.ts +2 -11
  171. package/dist/commands/tasks/output.js +64 -145
  172. package/dist/commands/tasks/report.d.ts +3 -3
  173. package/dist/commands/tasks/report.js +64 -41
  174. package/dist/commands/tasks/resource/add.d.ts +23 -0
  175. package/dist/commands/tasks/resource/add.js +76 -0
  176. package/dist/commands/tasks/resource/list.d.ts +13 -0
  177. package/dist/commands/tasks/resource/list.js +41 -0
  178. package/dist/commands/tasks/result/show.d.ts +13 -0
  179. package/dist/commands/tasks/result/show.js +46 -0
  180. package/dist/commands/tasks/result/submit.d.ts +26 -0
  181. package/dist/commands/tasks/result/submit.js +134 -0
  182. package/dist/commands/tasks/resume/save.d.ts +16 -0
  183. package/dist/commands/tasks/resume/save.js +59 -0
  184. package/dist/commands/tasks/resume/show.d.ts +13 -0
  185. package/dist/commands/tasks/resume/show.js +35 -0
  186. package/dist/commands/tasks/review.d.ts +17 -0
  187. package/dist/commands/tasks/review.js +54 -0
  188. package/dist/commands/tasks/runs.js +5 -0
  189. package/dist/commands/tasks/timeline.d.ts +2 -2
  190. package/dist/commands/tasks/timeline.js +10 -23
  191. package/dist/commands/tasks/updates/add.d.ts +22 -0
  192. package/dist/commands/tasks/updates/add.js +101 -0
  193. package/dist/commands/tasks/updates/list.d.ts +15 -0
  194. package/dist/commands/tasks/updates/list.js +57 -0
  195. package/dist/commands/tasks/waive.d.ts +1 -0
  196. package/dist/commands/tasks/waive.js +2 -1
  197. package/dist/lib/agentic-stream.d.ts +257 -0
  198. package/dist/lib/agentic-stream.js +490 -33
  199. package/dist/lib/balance.d.ts +8 -0
  200. package/dist/lib/commitment-product.d.ts +10 -1
  201. package/dist/lib/commitment-product.js +66 -2
  202. package/dist/lib/commitments.d.ts +4 -1
  203. package/dist/lib/commitments.js +32 -1
  204. package/dist/lib/conversation-search.d.ts +3 -0
  205. package/dist/lib/conversation-search.js +75 -0
  206. package/dist/lib/execution-target.d.ts +21 -0
  207. package/dist/lib/execution-target.js +22 -6
  208. package/dist/lib/harnesses.d.ts +82 -6
  209. package/dist/lib/harnesses.js +30 -2
  210. package/dist/lib/hosted-machines.js +9 -0
  211. package/dist/lib/inbox.d.ts +2 -1
  212. package/dist/lib/machines.d.ts +17 -0
  213. package/dist/lib/machines.js +29 -0
  214. package/dist/lib/managed-agent-keys.d.ts +104 -0
  215. package/dist/lib/managed-agent-keys.js +50 -0
  216. package/dist/lib/memory-scope.d.ts +4 -3
  217. package/dist/lib/memory-scope.js +9 -9
  218. package/dist/lib/memory-sync.d.ts +114 -0
  219. package/dist/lib/memory-sync.js +730 -0
  220. package/dist/lib/message-provenance.d.ts +42 -0
  221. package/dist/lib/message-provenance.js +89 -0
  222. package/dist/lib/scoped-memory-command.d.ts +68 -0
  223. package/dist/lib/scoped-memory-command.js +183 -0
  224. package/dist/lib/session-task-endpoints.d.ts +1 -1
  225. package/dist/lib/session-task-endpoints.js +7 -0
  226. package/dist/lib/sky-code-broker.d.ts +47 -0
  227. package/dist/lib/sky-code-broker.js +50 -0
  228. package/dist/lib/sky-code-doctor.js +10 -1
  229. package/dist/lib/task-artifact-flags.d.ts +2 -0
  230. package/dist/lib/task-artifact-flags.js +7 -0
  231. package/dist/lib/task-execution.d.ts +4 -5
  232. package/dist/lib/task-execution.js +4 -5
  233. package/dist/lib/task-extras.d.ts +1 -5
  234. package/dist/lib/task-extras.js +1 -5
  235. package/dist/lib/task-transcript.d.ts +5 -7
  236. package/dist/lib/task-transcript.js +8 -16
  237. package/dist/lib/tasks.d.ts +7 -21
  238. package/dist/lib/tasks.js +17 -20
  239. package/dist/lib/triggers.d.ts +39 -1
  240. package/dist/lib/triggers.js +70 -2
  241. package/dist/lib/usage-discovery.d.ts +17 -1
  242. package/dist/lib/usage-discovery.js +17 -1
  243. package/dist/node_modules/@skrr-ai/data-provider/index.js +3733 -3618
  244. package/oclif.manifest.json +25726 -19886
  245. package/package.json +26 -5
@@ -5,7 +5,6 @@ const core_1 = require("@oclif/core");
5
5
  const data_provider_1 = require("@skrr-ai/data-provider");
6
6
  const base_command_1 = require("../../base-command");
7
7
  const format_1 = require("../../lib/format");
8
- const tasks_1 = require("../../lib/tasks");
9
8
  /**
10
9
  * `<action> (<k=v ...>)`, or just the preview when there is nothing to add.
11
10
  *
@@ -14,11 +13,11 @@ const tasks_1 = require("../../lib/tasks");
14
13
  */
15
14
  function withDetails(item) {
16
15
  const preview = String(item.preview ?? '-');
17
- const details = (0, format_1.formatCell)(item.details, '');
16
+ const details = (0, format_1.formatCell)(item.data ?? item.details, '');
18
17
  return details ? `${preview} (${details})` : preview;
19
18
  }
20
19
  class TasksTimeline extends base_command_1.BaseCommand {
21
- static description = 'Show the unified task timeline: work log, comments, lifecycle, and execution';
20
+ static description = 'Show the immutable multi-actor Task Activity timeline';
22
21
  static args = {
23
22
  id: core_1.Args.string({ description: 'Task ID', required: true, ignoreStdin: true }),
24
23
  };
@@ -26,16 +25,9 @@ class TasksTimeline extends base_command_1.BaseCommand {
26
25
  json: core_1.Flags.boolean({ description: 'Output JSON' }),
27
26
  limit: core_1.Flags.integer({ default: 50 }),
28
27
  cursor: core_1.Flags.string(),
29
- // `--kind` names a typed WORK-EVENT kind, not one of the timeline's four
30
- // sources. Undeclared and undescribed, it read like a source filter and
31
- // silently accepted anything; the server now refuses an unknown kind, and
32
- // declaring the options here refuses a typo before it costs a round trip.
33
- kind: core_1.Flags.string({
34
- description: 'Show only work events of this kind (excludes comments, lifecycle, execution)',
35
- options: [...tasks_1.TASK_WORK_EVENT_KINDS],
36
- }),
37
- run: core_1.Flags.string(),
38
- actor: core_1.Flags.string({ options: ['user', 'agent', 'system'] }),
28
+ type: core_1.Flags.string({ description: 'Exact Activity event type, e.g. task.result.submitted' }),
29
+ execution: core_1.Flags.string({ description: 'Bounded Task execution id' }),
30
+ actor: core_1.Flags.string({ options: ['human', 'agent', 'system', 'integration'] }),
39
31
  };
40
32
  async run() {
41
33
  this.requireAuth();
@@ -45,8 +37,8 @@ class TasksTimeline extends base_command_1.BaseCommand {
45
37
  result = await data_provider_1.dataService.getTaskTimeline(args.id, {
46
38
  limit: flags.limit,
47
39
  cursor: flags.cursor,
48
- kind: flags.kind,
49
- runId: flags.run,
40
+ type: flags.type,
41
+ executionId: flags.execution,
50
42
  actor: flags.actor,
51
43
  });
52
44
  }
@@ -61,12 +53,7 @@ class TasksTimeline extends base_command_1.BaseCommand {
61
53
  time: String(item.occurredAt ?? '-')
62
54
  .replace('T', ' ')
63
55
  .slice(0, 19),
64
- // A work event's own kind is the thing you came to see. Showing the
65
- // source alone collapsed blocker, decision, checkpoint and evidence
66
- // into one indistinguishable `work_event`.
67
- source: item.eventKind
68
- ? `${String(item.kind ?? '-')}:${String(item.eventKind)}`
69
- : String(item.kind ?? '-'),
56
+ source: String(item.type ?? '-'),
70
57
  actor: String(item.actor?.kind ?? '-'),
71
58
  // A lifecycle row's preview is the bare action, so `status_changed`
72
59
  // appeared three times in a row without ever naming a status. The
@@ -75,13 +62,13 @@ class TasksTimeline extends base_command_1.BaseCommand {
75
62
  // substituted: the action is still what happened, `details` is what
76
63
  // it happened to.
77
64
  detail: (0, format_1.truncate)(withDetails(item), 90),
78
- run: String(item.runId ?? '-'),
65
+ run: String(item.executionId ?? '-'),
79
66
  })), [
80
67
  { key: 'time', header: 'TIME' },
81
68
  { key: 'source', header: 'SOURCE' },
82
69
  { key: 'actor', header: 'ACTOR' },
83
70
  { key: 'detail', header: 'DETAIL', maxWidth: 90 },
84
- { key: 'run', header: 'RUN', maxWidth: 24 },
71
+ { key: 'run', header: 'EXECUTION', maxWidth: 24 },
85
72
  ], (line) => this.log(line));
86
73
  if (result.next_cursor)
87
74
  this.log(`Next page: --cursor ${result.next_cursor}`);
@@ -0,0 +1,22 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class TasksUpdatesAdd extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ task: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ task: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ type: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ summary: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ data: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ resume: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ 'run-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ 'spec-version': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ supersedes: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ reference: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ 'idempotency-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const outbox_1 = require("../../../lib/outbox");
7
+ const task_resolver_1 = require("../../../lib/task-resolver");
8
+ const api_fetch_1 = require("../../../lib/api-fetch");
9
+ const session_task_endpoints_1 = require("../../../lib/session-task-endpoints");
10
+ function parseJsonObject(value, label) {
11
+ if (!value)
12
+ return undefined;
13
+ const parsed = JSON.parse(value);
14
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
15
+ throw new Error(`${label} must be a JSON object`);
16
+ }
17
+ return parsed;
18
+ }
19
+ class TasksUpdatesAdd extends base_command_1.BaseCommand {
20
+ static description = 'Record a meaningful Task Update, optionally with recovery state';
21
+ static examples = [
22
+ '<%= config.bin %> tasks updates add <task> --type progress --summary "Migration review complete" --data \'{"completedSinceLast":["Checked migrations 001-014"],"nextActions":["Review authorization"]}\'',
23
+ '<%= config.bin %> tasks updates add <task> --type decision --summary "Use a resource object" --data \'{"decision":"Use WorkResource","rationale":"Identity must survive URL changes"}\'',
24
+ ];
25
+ static args = {
26
+ task: core_1.Args.string({ required: false, ignoreStdin: true, description: 'Task id or ref' }),
27
+ };
28
+ static flags = {
29
+ task: core_1.Flags.string({ description: 'Task id; overrides runtime context' }),
30
+ type: core_1.Flags.string({
31
+ required: true,
32
+ options: ['progress', 'finding', 'decision', 'blocker', 'verification'],
33
+ description: 'What changed in the shared understanding of the Task',
34
+ }),
35
+ summary: core_1.Flags.string({ required: true, description: 'One sentence saying what became true' }),
36
+ data: core_1.Flags.string({ required: true, description: 'Kind-specific JSON payload' }),
37
+ resume: core_1.Flags.string({
38
+ description: 'JSON recovery snapshot; requires --run-id and is committed with the Update',
39
+ }),
40
+ 'run-id': core_1.Flags.string({ description: 'Canonical Task Run that performed this work' }),
41
+ 'spec-version': core_1.Flags.integer({
42
+ description: 'Task specification version this Update concerns',
43
+ }),
44
+ supersedes: core_1.Flags.string({ description: 'Update id this correction supersedes' }),
45
+ reference: core_1.Flags.string({ multiple: true, description: 'Reference as <kind>:<id-or-uri>' }),
46
+ 'idempotency-key': core_1.Flags.string({ description: 'Stable retry key for this exact Update' }),
47
+ json: core_1.Flags.boolean({ description: 'Output JSON' }),
48
+ };
49
+ async run() {
50
+ this.requireAuth();
51
+ const { args, flags } = await this.parse(TasksUpdatesAdd);
52
+ const task = (0, task_resolver_1.resolveTaskIdentity)({ positionalId: args.task, flagTask: flags.task });
53
+ let data;
54
+ let resume;
55
+ try {
56
+ data = parseJsonObject(flags.data, '--data');
57
+ resume = parseJsonObject(flags.resume, '--resume');
58
+ }
59
+ catch (error) {
60
+ this.error(error.message, { exit: 1 });
61
+ }
62
+ const references = (flags.reference || []).map((raw) => {
63
+ const split = raw.indexOf(':');
64
+ if (split < 1)
65
+ this.error('--reference must be <kind>:<id-or-uri>', { exit: 1 });
66
+ const kind = raw.slice(0, split);
67
+ const value = raw.slice(split + 1);
68
+ return /^https?:|^file:/.test(value) ? { kind, uri: value } : { kind, id: value };
69
+ });
70
+ const idempotencyKey = flags['idempotency-key'] ||
71
+ (0, outbox_1.idempotencyKeyFor)('task-update', task.id, JSON.stringify({ type: flags.type, summary: flags.summary, data, resume }));
72
+ let result;
73
+ try {
74
+ const payload = {
75
+ type: flags.type,
76
+ summary: flags.summary,
77
+ data,
78
+ runId: flags['run-id'],
79
+ expectedSpecVersion: flags['spec-version'],
80
+ references,
81
+ supersedesUpdateId: flags.supersedes,
82
+ resume: resume,
83
+ idempotencyKey,
84
+ };
85
+ const sessionPath = await (0, session_task_endpoints_1.sessionScopedTaskPath)('update');
86
+ result = sessionPath
87
+ ? await (0, api_fetch_1.apiFetch)(sessionPath, {
88
+ method: 'POST',
89
+ body: payload,
90
+ })
91
+ : await data_provider_1.dataService.appendTaskUpdate({ taskId: task.id, data: payload });
92
+ }
93
+ catch (error) {
94
+ this.handleApiError(error);
95
+ }
96
+ if (flags.json)
97
+ return this.log(JSON.stringify(result, null, 2));
98
+ this.log(`Recorded ${flags.type} Update on ${task.id}${result?.resumePoint ? ' with a Resume Point' : ''}.`);
99
+ }
100
+ }
101
+ exports.default = TasksUpdatesAdd;
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class TasksUpdatesList extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ task: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ task: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ type: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const task_resolver_1 = require("../../../lib/task-resolver");
7
+ function authorLabel(update) {
8
+ const actor = update.authoredBy || {};
9
+ if (actor.kind === 'agent')
10
+ return `Agent ${actor.agentId}`;
11
+ if (actor.kind === 'human')
12
+ return `Human ${actor.userId}`;
13
+ if (actor.kind === 'integration')
14
+ return `Integration ${actor.provider}`;
15
+ return `System ${actor.service || ''}`.trim();
16
+ }
17
+ class TasksUpdatesList extends base_command_1.BaseCommand {
18
+ static description = 'List meaningful Task Updates (not tool-call telemetry)';
19
+ static args = {
20
+ task: core_1.Args.string({ required: false, ignoreStdin: true, description: 'Task id or ref' }),
21
+ };
22
+ static flags = {
23
+ task: core_1.Flags.string({ description: 'Task id; overrides runtime context' }),
24
+ type: core_1.Flags.string({
25
+ options: ['progress', 'finding', 'decision', 'blocker', 'verification', 'ready_for_review'],
26
+ }),
27
+ limit: core_1.Flags.integer({ default: 50, min: 1, max: 100 }),
28
+ cursor: core_1.Flags.string({ description: 'Opaque cursor returned by the previous page' }),
29
+ json: core_1.Flags.boolean({ description: 'Output JSON' }),
30
+ };
31
+ async run() {
32
+ this.requireAuth();
33
+ const { args, flags } = await this.parse(TasksUpdatesList);
34
+ const task = (0, task_resolver_1.resolveTaskIdentity)({ positionalId: args.task, flagTask: flags.task });
35
+ let result;
36
+ try {
37
+ result = await data_provider_1.dataService.listTaskUpdates(task.id, {
38
+ limit: flags.limit,
39
+ cursor: flags.cursor,
40
+ type: flags.type,
41
+ });
42
+ }
43
+ catch (error) {
44
+ this.handleApiError(error);
45
+ }
46
+ if (flags.json)
47
+ return this.log(JSON.stringify(result, null, 2));
48
+ if (!result?.data.length)
49
+ return this.log('No Updates recorded.');
50
+ for (const update of result.data) {
51
+ this.log(`${update.occurredAt} · ${update.type} · ${authorLabel(update)}\n${update.summary}`);
52
+ }
53
+ if (result.nextCursor)
54
+ this.log(`Next cursor: ${result.nextCursor}`);
55
+ }
56
+ }
57
+ exports.default = TasksUpdatesList;
@@ -11,6 +11,7 @@ import { BaseCommand } from '../../base-command';
11
11
  * indistinguishable from having forgotten.
12
12
  */
13
13
  export default class TasksWaive extends BaseCommand {
14
+ static hidden: boolean;
14
15
  static description: string;
15
16
  static examples: string[];
16
17
  static args: {
@@ -15,7 +15,8 @@ const base_command_1 = require("../../base-command");
15
15
  * indistinguishable from having forgotten.
16
16
  */
17
17
  class TasksWaive extends base_command_1.BaseCommand {
18
- static description = 'Waive an expectation, with a stated reason';
18
+ static hidden = true;
19
+ static description = 'Compatibility alias for `tasks expectations assess --decision waived`';
19
20
  static examples = [
20
21
  '<%= config.bin %> tasks waive <task-id> c1 --reason "superseded by OSK-7000"',
21
22
  ];
@@ -10,6 +10,44 @@ export type AgenticStreamResult = {
10
10
  status: 'completed' | 'aborted' | 'failed';
11
11
  lastEvent?: AgenticStreamEvent;
12
12
  };
13
+ /**
14
+ * What the DURABLE record says about a turn, when the stream will not say it.
15
+ *
16
+ * A run refused during admission is written straight onto the response message
17
+ * (`error: true`, the reason in `metadata.agentic.error`) and the session
18
+ * stream is never closed — so a subscriber that has already emitted
19
+ * `session.joined` waits forever for a terminal event that will not come. Two
20
+ * independent probes measured that as a client that produces no output and does
21
+ * not exit, for a run the server had decided in 89ms and 451ms respectively
22
+ * (OSK-7624, OSK-7635, OSK-7720, OSK-7735). The mirror image is a turn that
23
+ * finished 13 seconds before the client gave up and declared it "may still be
24
+ * executing" (OSK-7660).
25
+ *
26
+ * The fix on this side of the wire is to stop treating the stream as the only
27
+ * witness: when it goes quiet, ask the record. `reconcileTerminal` is that
28
+ * question, supplied by the caller so this module keeps no API dependency.
29
+ */
30
+ export type ReconciledTerminal = {
31
+ status: 'completed' | 'failed';
32
+ /** The answer as persisted, when there is one. */
33
+ text?: string;
34
+ /** The recorded failure reason — `metadata.agentic.error` on the message. */
35
+ error?: string;
36
+ };
37
+ /**
38
+ * Write exactly one complete JSON value on one line.
39
+ *
40
+ * `--jsonl` is the mode automation parses, and its whole contract is one JSON
41
+ * value per physical line. Two things break that if the line is composed by
42
+ * hand: a raw newline inside a string (a multi-line agent answer or tool
43
+ * output) splits one record across many unparseable lines, and routing the line
44
+ * through oclif's `this.log` puts it through `util.format`, which rewrites `%s`
45
+ * / `%d` / `%j` sequences that appear in ordinary shell output. `JSON.stringify`
46
+ * escapes the first and this helper avoids the second by writing to the stream
47
+ * directly, so every JSONL line in the CLI is produced in one place and cannot
48
+ * drift (OSK-7629).
49
+ */
50
+ export declare function writeJsonLine(output: NodeJS.WritableStream, value: unknown): void;
13
51
  export type AgenticStreamOptions = {
14
52
  baseURL: string;
15
53
  token: string;
@@ -29,6 +67,18 @@ export type AgenticStreamOptions = {
29
67
  * suppressed, so the caller prints the final result itself.
30
68
  */
31
69
  quiet?: boolean;
70
+ /**
71
+ * Ask the durable record what happened, when the stream stops talking.
72
+ *
73
+ * Called after {@link AgenticStreamOptions.idleTerminalProbeMs} of silence
74
+ * and again on transport loss. Returning a terminal settles the run with it;
75
+ * returning null re-arms the watchdog, so a genuinely long tool call keeps
76
+ * waiting. Omitting the callback keeps the pre-existing behaviour of trusting
77
+ * the stream alone.
78
+ */
79
+ reconcileTerminal?: () => Promise<ReconciledTerminal | null>;
80
+ /** Silence before the first durable-record probe. Default 20s. */
81
+ idleTerminalProbeMs?: number;
32
82
  };
33
83
  /**
34
84
  * Small Node-side adapter for the existing Agentic Socket.IO contract.
@@ -63,6 +113,138 @@ export declare function envelopeKey(envelope: unknown): string | null;
63
113
  * empty array — the caller drops it as a pure re-delivery (OSK-4834).
64
114
  */
65
115
  export declare function unseenEnvelopes(event: AgenticStreamEvent, seen: Set<string>): unknown[];
116
+ /** A tool event in the CLI's own vocabulary, however the turn was routed. */
117
+ export type ProjectedToolEvent = {
118
+ type: 'tool.started' | 'tool.completed';
119
+ toolUseId?: string;
120
+ toolName?: string;
121
+ toolInput?: unknown;
122
+ toolResponse?: unknown;
123
+ status?: string;
124
+ };
125
+ /**
126
+ * Project daemon `tool-call-start` / `tool-call-end` envelopes into the same
127
+ * `tool.started` / `tool.completed` events a cloud run emits.
128
+ *
129
+ * The CLI used to emit tool events only for cloud-executed turns: a run on a
130
+ * local harness produced three shell commands and ZERO tool events, in both
131
+ * `--jsonl` and the human rendering, while the envelopes carrying them arrived
132
+ * intact inside `session:output` (OSK-7730). Automation counting tool calls
133
+ * concluded a local run used no tools; a human watching one saw nothing at all
134
+ * while commands ran on their own machine (OSK-7773 is the same absence on the
135
+ * web). The harness a turn lands on is a routing decision and must not change
136
+ * the event vocabulary.
137
+ *
138
+ * `tool-call-end` carries no tool name, so the name is correlated on `call`
139
+ * (the tool-use id) through `namesByCall`, which the caller keeps for the life
140
+ * of the run. The pairing is unambiguous within a turn.
141
+ */
142
+ export declare function projectDaemonToolEvents(envelopes: unknown[], namesByCall: Map<string, string>): ProjectedToolEvent[];
143
+ /**
144
+ * The part of a cumulative snapshot that has not been shown yet.
145
+ *
146
+ * The stream carries CUMULATIVE text, and the plain renderer used to redraw
147
+ * each snapshot after a bare carriage return. `\r` returns the cursor to column
148
+ * 0 of the CURRENT line only — it cannot rewind past a newline — so the repaint
149
+ * was correct exactly while the answer was one line, and every snapshot after
150
+ * the model's first `\n` stranded the previous snapshot's earlier lines on
151
+ * screen. One two-line answer printed its first paragraph sixteen times
152
+ * (OSK-7731); another printed the answer twice and fused it into tokens the
153
+ * agent never wrote, `HOSTHOST=e2b.local` (OSK-7701).
154
+ *
155
+ * Printing only the new suffix needs no cursor control at all, which also makes
156
+ * it correct when stdout is a file or a pipe — where nothing consumes `\r` and
157
+ * the redirected capture looked worse than the screen.
158
+ *
159
+ * Returns the text to append, and the new "already shown" watermark. A snapshot
160
+ * that is not an extension of what was shown (a stream reset, or a server that
161
+ * rewrote the answer) is emitted whole on a fresh line rather than diffed.
162
+ */
163
+ export declare function renderableDelta(shown: string, snapshot: string): {
164
+ append: string;
165
+ shown: string;
166
+ };
167
+ /**
168
+ * WHAT THE SERVER ACTUALLY SAID when it refused the socket.
169
+ *
170
+ * OSK-7583 / OSK-7588 / OSK-7604 / OSK-7663 — four findings, one experience:
171
+ * `skrr agents chat` printed three envelopes and no answer, and the only
172
+ * explanation was "Too many concurrent connections for this account". No limit,
173
+ * no current count, no retry-after, and no way to tell whether the cap is 2 or
174
+ * 50 or whether waiting ten seconds helps. The run itself succeeded server-side
175
+ * every time; the only thing that failed was the user's ability to see it.
176
+ *
177
+ * Every one of those facts was already on the wire.
178
+ * `websocket/userConnectionTracking.js` attaches
179
+ * `{code, retryAfterMs, retryable, connectionClass, limit}` to the refusal, and
180
+ * Socket.IO delivers it to the client as `err.data`. The CLI read `err.message`
181
+ * and dropped the rest.
182
+ *
183
+ * The retry is not an embellishment either — it is a contract the server states
184
+ * in its own words: *"Socket.IO destroys a socket that fails middleware and
185
+ * does NOT reconnect it, so a client that ignores this stays disconnected until
186
+ * the page is reloaded. Every first-party client is expected to schedule one
187
+ * retry after this delay, jittered."* The CLI was not honouring it, which is why
188
+ * a refusal was terminal rather than a pause.
189
+ */
190
+ export type TransportRefusal = {
191
+ code?: string;
192
+ limit?: number;
193
+ retryAfterMs?: number;
194
+ connectionClass?: string;
195
+ retryable: boolean;
196
+ };
197
+ /** The user-connection cap, as `userConnectionTracking.js` names it. */
198
+ export declare const USER_CONNECTION_CAP_CODE = "user_connection_cap";
199
+ export declare function transportRefusal(error: unknown): TransportRefusal;
200
+ /**
201
+ * The sentence a person can act on, built from whatever the refusal carried.
202
+ *
203
+ * Degrades one clause at a time: an older server that sends no `data` still
204
+ * gets its own message back unchanged, which is exactly today's behaviour and
205
+ * no worse.
206
+ */
207
+ export declare function transportRefusalMessage(message: string, refusal: TransportRefusal): string;
208
+ /**
209
+ * How long a refusal is worth waiting out.
210
+ *
211
+ * The default 30s attach deadline is exactly the server's own
212
+ * `WS_USER_CAP_RETRY_AFTER_MS`, so a client honouring the retry contract on the
213
+ * default budget gives up in the same instant it is allowed to try again. The
214
+ * window is widened to cover the retry plus a connect, and only when the server
215
+ * named a delay.
216
+ */
217
+ export declare function attachDeadlineFor(timeoutMs: number, refusal: TransportRefusal): number;
218
+ /** Jitter, so a fleet refused together does not return together. */
219
+ export declare function jitteredRetryDelay(retryAfterMs: number, random?: () => number): number;
220
+ /**
221
+ * WHAT THE LIVE STREAM DID NOT DELIVER.
222
+ *
223
+ * OSK-7631 — a cloud Agent Worker turn streamed only `__seq 3`. Seq 1 and 2
224
+ * were never sent: no gap marker, no error, no retransmit. A user watching live
225
+ * saw the answer to "output the numbers 1 through 60" begin at "33", while the
226
+ * persisted message held all sixty. The direction is the exact mirror of
227
+ * OSK-7573, where the stream is right and the durable copy loses text — and it
228
+ * is the more dangerous of the two to leave silent, because a truncated live
229
+ * answer looks like a complete short answer.
230
+ *
231
+ * The web client already detects this (`client_envelope_seq_gap_detected_total`)
232
+ * and rehydrates the missing range from the envelope ring. The CLI had neither
233
+ * the detection nor the backfill, so the only correction it could make was at
234
+ * the terminal — which it does: `run.result` and the persisted message are
235
+ * authoritative and already correct here. What was missing was any admission,
236
+ * WHILE READING, that the text on screen is not all of it.
237
+ *
238
+ * Tracks the highest seq applied and reports the first gap. Deliberately does
239
+ * not try to reconstruct: a client that guesses at missing text is worse than
240
+ * one that says it is missing.
241
+ */
242
+ export type SeqGap = {
243
+ from: number;
244
+ to: number;
245
+ };
246
+ export declare function detectSeqGap(highestApplied: number, incoming: number): SeqGap | null;
247
+ export declare function seqGapNotice(gap: SeqGap): string;
66
248
  export declare class AgenticStreamClient {
67
249
  private readonly options;
68
250
  private socket;
@@ -71,19 +253,94 @@ export declare class AgenticStreamClient {
71
253
  private settled;
72
254
  private closed;
73
255
  private accumulated;
256
+ /** Highest envelope `__seq` folded into `accumulated`, for gap detection. */
257
+ private highestSeq;
258
+ private reportedGap;
74
259
  private readonly seenEnvelopes;
260
+ /**
261
+ * Lifecycle events already emitted, by their own identity (OSK-7632/7689/7709).
262
+ *
263
+ * `session:output` envelopes are deduped by `envelopeKey`, but the lifecycle
264
+ * events do not ride an envelope and were exempt: one turn delivered
265
+ * `run.started` four times byte-identically (76% of a 70KB stream), and one
266
+ * Bash execution arrived as four `tool.started` events sharing one
267
+ * `toolUseId`. Anything counting tool calls from the stream — a timeline, a
268
+ * usage display, an audit log — reported four sandbox commands where one ran.
269
+ * The server fans one broadcast to several rooms the client is in, so the
270
+ * repeat count varies run to run and cannot be inferred by a consumer.
271
+ */
272
+ private readonly seenLifecycle;
273
+ /** `call` → tool name, so a daemon `tool-call-end` can be named (OSK-7730). */
274
+ private readonly toolNamesByCall;
275
+ /** Text already written to the terminal, for suffix-only rendering. */
276
+ private renderedText;
277
+ private idleTimer;
278
+ private reconciling;
75
279
  private responseMessageId;
76
280
  private lastEvent;
281
+ /**
282
+ * The terminal result, once there is one.
283
+ *
284
+ * `run()`'s promise is the normal way to read it, but a caller that raced
285
+ * `run()` against its own detach has already discarded that promise by the
286
+ * time {@link probeTerminal} settles it. Keeping the value here is what lets
287
+ * a reconciled detach report the real outcome instead of the detach.
288
+ */
289
+ private terminalResult;
77
290
  private resolve;
78
291
  private reject;
292
+ /** The terminal result, or null while the run is still in flight. */
293
+ settledResult(): AgenticStreamResult | null;
79
294
  constructor(options: AgenticStreamOptions);
80
295
  run(): Promise<AgenticStreamResult>;
296
+ /**
297
+ * (Re)start the silence watchdog that asks the durable record what happened.
298
+ *
299
+ * Armed on join and reset by every event, so it only fires when the stream
300
+ * has actually gone quiet. A probe that finds the turn still running re-arms
301
+ * rather than giving up — a 200-second tool call is silence, not a failure —
302
+ * so the cost of being wrong is one cheap read, while the cost of not asking
303
+ * was an interactive session that never returned.
304
+ */
305
+ private armIdleProbe;
306
+ /**
307
+ * Settle from the durable record, if it has reached a terminal state.
308
+ *
309
+ * Public so the caller can force one before declaring a detach: a run that
310
+ * finished 13 seconds ago must not be reported as "may still be executing"
311
+ * (OSK-7660).
312
+ */
313
+ probeTerminal(reason: string): Promise<boolean>;
81
314
  cancel(reason?: string): void;
82
315
  close(): void;
316
+ /**
317
+ * Report the first hole in the live envelope sequence, once.
318
+ *
319
+ * Once, not per gap: a stream that has already lost its beginning tends to
320
+ * lose more, and one honest sentence is the useful form of that. The terminal
321
+ * result is authoritative and reconciled separately, so this never changes
322
+ * what the run reports — only what the reader is told while it is happening.
323
+ */
324
+ private reportSeqGap;
83
325
  private installHandlers;
84
326
  private handlePermission;
85
327
  private handleQuestion;
86
328
  private ask;
329
+ /**
330
+ * True the first time this (kind, identity) pair is seen; false afterwards.
331
+ * The identity is the event's OWN — a tool-use id, a message id — never a
332
+ * position in the stream, because the repeat count varies run to run.
333
+ */
334
+ private firstTimeSeen;
335
+ /**
336
+ * Emit a tool event once per tool invocation.
337
+ *
338
+ * Deduped on `toolUseId`, which both paths carry and which is the invocation's
339
+ * real identity: four byte-identical `tool.started` events for one Bash call
340
+ * all shared it (OSK-7632). An event with no id cannot be deduped and is
341
+ * passed through, preserving prior behaviour.
342
+ */
343
+ private emitToolEvent;
87
344
  private emit;
88
345
  private finish;
89
346
  /**