@skrr-ai/cli 0.1.40 → 0.1.42

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 (120) hide show
  1. package/dist/base-command.d.ts +9 -0
  2. package/dist/base-command.js +18 -3
  3. package/dist/commands/agent-shares/list-for.js +4 -11
  4. package/dist/commands/agent-shares/received.js +4 -11
  5. package/dist/commands/agent-shares/sent.js +4 -11
  6. package/dist/commands/agent-shares/with.js +3 -10
  7. package/dist/commands/agents/activity.js +1 -1
  8. package/dist/commands/agents/api-actions/add.js +6 -0
  9. package/dist/commands/agents/chat.js +6 -1
  10. package/dist/commands/agents/create.js +6 -1
  11. package/dist/commands/agents/manager/ensure.d.ts +18 -0
  12. package/dist/commands/agents/manager/ensure.js +56 -0
  13. package/dist/commands/agents/show.js +4 -0
  14. package/dist/commands/agents/tools/auth.d.ts +6 -0
  15. package/dist/commands/agents/tools/auth.js +27 -1
  16. package/dist/commands/agents/tools/index.js +11 -1
  17. package/dist/commands/agents/update.js +6 -1
  18. package/dist/commands/code/install.d.ts +4 -2
  19. package/dist/commands/code/install.js +15 -14
  20. package/dist/commands/convos/list.js +1 -3
  21. package/dist/commands/convos/show.js +4 -11
  22. package/dist/commands/daemon/index.js +3 -3
  23. package/dist/commands/daemon/install.js +4 -4
  24. package/dist/commands/daemon/login.js +1 -1
  25. package/dist/commands/daemon/logs.d.ts +3 -1
  26. package/dist/commands/daemon/logs.js +16 -1
  27. package/dist/commands/daemon/start.js +3 -3
  28. package/dist/commands/daemon/status.d.ts +9 -0
  29. package/dist/commands/daemon/status.js +22 -0
  30. package/dist/commands/dm/messages.js +1 -11
  31. package/dist/commands/followups/cancel.js +1 -1
  32. package/dist/commands/followups/remind.js +4 -0
  33. package/dist/commands/followups/resolve.js +1 -1
  34. package/dist/commands/followups/show.js +16 -0
  35. package/dist/commands/harnesses/forget.js +20 -3
  36. package/dist/commands/harnesses/install.d.ts +18 -0
  37. package/dist/commands/harnesses/install.js +146 -25
  38. package/dist/commands/harnesses/installers.d.ts +1 -1
  39. package/dist/commands/harnesses/installers.js +36 -12
  40. package/dist/commands/harnesses/list.d.ts +74 -2
  41. package/dist/commands/harnesses/list.js +231 -15
  42. package/dist/commands/harnesses/ping.d.ts +2 -0
  43. package/dist/commands/harnesses/ping.js +21 -0
  44. package/dist/commands/harnesses/show.d.ts +22 -0
  45. package/dist/commands/harnesses/show.js +116 -17
  46. package/dist/commands/harnesses/update.d.ts +8 -0
  47. package/dist/commands/harnesses/update.js +25 -1
  48. package/dist/commands/harnesses/usage.d.ts +2 -0
  49. package/dist/commands/harnesses/usage.js +7 -2
  50. package/dist/commands/instructions/status.js +13 -0
  51. package/dist/commands/instructions/update-target.d.ts +1 -0
  52. package/dist/commands/instructions/update-target.js +11 -3
  53. package/dist/commands/login.js +5 -5
  54. package/dist/commands/machines/list.js +8 -9
  55. package/dist/commands/machines/show.js +46 -17
  56. package/dist/commands/messages/show.js +3 -10
  57. package/dist/commands/shares/get.js +2 -9
  58. package/dist/commands/shares/list.js +1 -9
  59. package/dist/commands/shortcuts/show.js +4 -11
  60. package/dist/commands/skills/import-as-actions.js +6 -15
  61. package/dist/commands/skills/local.js +6 -0
  62. package/dist/commands/spaces/actions/run.js +3 -4
  63. package/dist/commands/spaces/briefs/get.js +2 -9
  64. package/dist/commands/spaces/briefs/list.js +1 -9
  65. package/dist/commands/spaces/conversations.js +1 -9
  66. package/dist/commands/spaces/heartbeats/list.js +1 -9
  67. package/dist/commands/spaces/heartbeats/status.js +2 -9
  68. package/dist/commands/tasks/activity.js +1 -10
  69. package/dist/commands/tasks/approvals/list.js +1 -9
  70. package/dist/commands/tasks/attachments/list.js +1 -9
  71. package/dist/commands/tasks/comments/list.js +1 -9
  72. package/dist/commands/tasks/complete.js +13 -0
  73. package/dist/commands/tasks/dri-status.js +2 -9
  74. package/dist/commands/tasks/events/append.js +9 -7
  75. package/dist/commands/tasks/execution-timeline.js +1 -9
  76. package/dist/commands/tasks/monitor.js +1 -9
  77. package/dist/commands/tasks/result/submit.js +14 -0
  78. package/dist/commands/tasks/runs.js +1 -9
  79. package/dist/commands/tasks/show.js +5 -12
  80. package/dist/commands/token/list.d.ts +8 -0
  81. package/dist/commands/token/list.js +51 -6
  82. package/dist/help.js +8 -12
  83. package/dist/lib/agent-home-workspace.d.ts +19 -0
  84. package/dist/lib/agent-home-workspace.js +39 -0
  85. package/dist/lib/agent-resolver.js +2 -2
  86. package/dist/lib/agentic-stream.d.ts +22 -1
  87. package/dist/lib/agentic-stream.js +48 -7
  88. package/dist/lib/cli-installers.d.ts +124 -2
  89. package/dist/lib/cli-installers.js +196 -13
  90. package/dist/lib/command-miss.d.ts +22 -0
  91. package/dist/lib/command-miss.js +78 -0
  92. package/dist/lib/daemon-setup.js +2 -2
  93. package/dist/lib/daemon-target.d.ts +14 -0
  94. package/dist/lib/daemon-target.js +32 -0
  95. package/dist/lib/daemonBroker.js +1 -1
  96. package/dist/lib/daemonHandoff.js +1 -1
  97. package/dist/lib/exec-runtime-binary.js +2 -2
  98. package/dist/lib/followups.d.ts +12 -0
  99. package/dist/lib/followups.js +14 -1
  100. package/dist/lib/format.d.ts +11 -0
  101. package/dist/lib/format.js +21 -0
  102. package/dist/lib/harness-labels.d.ts +39 -0
  103. package/dist/lib/harness-labels.js +60 -0
  104. package/dist/lib/harnesses.d.ts +6 -0
  105. package/dist/lib/instruction-input.d.ts +13 -0
  106. package/dist/lib/instruction-input.js +20 -1
  107. package/dist/lib/local-skills.d.ts +44 -1
  108. package/dist/lib/local-skills.js +58 -2
  109. package/dist/lib/login.js +5 -5
  110. package/dist/lib/machines.d.ts +6 -0
  111. package/dist/lib/machines.js +68 -2
  112. package/dist/lib/runtime-tool-support.d.ts +34 -0
  113. package/dist/lib/runtime-tool-support.js +77 -0
  114. package/dist/lib/share-rows.d.ts +17 -0
  115. package/dist/lib/share-rows.js +35 -0
  116. package/dist/lib/task-closure.d.ts +13 -0
  117. package/dist/lib/task-closure.js +17 -0
  118. package/dist/node_modules/@skrr-ai/data-provider/index.js +5066 -5033
  119. package/oclif.manifest.json +33472 -33360
  120. package/package.json +6 -3
@@ -5,6 +5,7 @@ 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 message_provenance_1 = require("../../lib/message-provenance");
8
+ const format_1 = require("../../lib/format");
8
9
  /** The detail endpoint preserves the legacy raw-array response while the list
9
10
  * endpoint returns an envelope. Accept both so an ID emitted by messages list
10
11
  * is always usable by messages show. */
@@ -59,9 +60,9 @@ class MessagesShow extends base_command_1.BaseCommand {
59
60
  this.log(`Model: ${msg.model ?? '-'}`);
60
61
  this.log(`Endpoint: ${msg.endpoint ?? '-'}`);
61
62
  if (msg.createdAt)
62
- this.log(`Created: ${formatTime(msg.createdAt)}`);
63
+ this.log(`Created: ${(0, format_1.localTime)(msg.createdAt)}`);
63
64
  if (msg.updatedAt)
64
- this.log(`Updated: ${formatTime(msg.updatedAt)}`);
65
+ this.log(`Updated: ${(0, format_1.localTime)(msg.updatedAt)}`);
65
66
  if (msg.tokenCount !== undefined)
66
67
  this.log(`Tokens: ${msg.tokenCount}`);
67
68
  // OSK-7682 — an unattended run persists no user message, so this row is the
@@ -79,11 +80,3 @@ class MessagesShow extends base_command_1.BaseCommand {
79
80
  }
80
81
  }
81
82
  exports.default = MessagesShow;
82
- function formatTime(value) {
83
- try {
84
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
85
- }
86
- catch {
87
- return String(value);
88
- }
89
- }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
+ const format_1 = require("../../lib/format");
6
7
  class SharesGet extends base_command_1.BaseCommand {
7
8
  static description = 'Show messages for a shared link by share ID';
8
9
  static examples = [
@@ -37,7 +38,7 @@ class SharesGet extends base_command_1.BaseCommand {
37
38
  this.log(`Public: ${r.isPublic === true ? 'yes' : 'no'}`);
38
39
  this.log(`Message count: ${messages.length}`);
39
40
  if (r.createdAt)
40
- this.log(`Created: ${formatTime(r.createdAt)}`);
41
+ this.log(`Created: ${(0, format_1.localTime)(r.createdAt)}`);
41
42
  if (messages.length > 0) {
42
43
  this.log('');
43
44
  messages.forEach((msg, i) => {
@@ -49,14 +50,6 @@ class SharesGet extends base_command_1.BaseCommand {
49
50
  }
50
51
  }
51
52
  exports.default = SharesGet;
52
- function formatTime(value) {
53
- try {
54
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
55
- }
56
- catch {
57
- return String(value);
58
- }
59
- }
60
53
  function truncateText(s, max) {
61
54
  if (s.length <= max)
62
55
  return s;
@@ -58,7 +58,7 @@ class SharesList extends base_command_1.BaseCommand {
58
58
  conversationId: String(link.conversationId ?? '-'),
59
59
  title: String(link.title ?? '-'),
60
60
  isPublic: link.isPublic ? 'yes' : 'no',
61
- createdAt: formatTime(link.createdAt),
61
+ createdAt: (0, format_1.localTime)(link.createdAt),
62
62
  }));
63
63
  (0, format_1.renderTable)(rows, [
64
64
  { key: 'shareId', header: 'SHARE ID' },
@@ -74,11 +74,3 @@ class SharesList extends base_command_1.BaseCommand {
74
74
  }
75
75
  }
76
76
  exports.default = SharesList;
77
- function formatTime(value) {
78
- try {
79
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
80
- }
81
- catch {
82
- return String(value);
83
- }
84
- }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
+ const format_1 = require("../../lib/format");
6
7
  class ShortcutsShow extends base_command_1.BaseCommand {
7
8
  static description = 'Show details for a single shortcut';
8
9
  static examples = [
@@ -43,13 +44,13 @@ class ShortcutsShow extends base_command_1.BaseCommand {
43
44
  this.log(`Order: ${s.order ?? 0}`);
44
45
  this.log(`Triggers: ${s.triggerCount ?? 0}`);
45
46
  if (s.lastTriggeredAt)
46
- this.log(`Last fired: ${formatTime(s.lastTriggeredAt)}`);
47
+ this.log(`Last fired: ${(0, format_1.localTime)(s.lastTriggeredAt)}`);
47
48
  this.log(`Author: ${s.author ?? '-'}`);
48
49
  this.log(`Assignees: ${agents.length} agent(s)${agents.length > 0 ? ` — ${agents.join(', ')}` : ''}`);
49
50
  if (s.createdAt)
50
- this.log(`Created: ${formatTime(s.createdAt)}`);
51
+ this.log(`Created: ${(0, format_1.localTime)(s.createdAt)}`);
51
52
  if (s.updatedAt)
52
- this.log(`Updated: ${formatTime(s.updatedAt)}`);
53
+ this.log(`Updated: ${(0, format_1.localTime)(s.updatedAt)}`);
53
54
  if (s.description) {
54
55
  this.log('');
55
56
  this.log('Description:');
@@ -69,11 +70,3 @@ class ShortcutsShow extends base_command_1.BaseCommand {
69
70
  }
70
71
  }
71
72
  exports.default = ShortcutsShow;
72
- function formatTime(value) {
73
- try {
74
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
75
- }
76
- catch {
77
- return String(value);
78
- }
79
- }
@@ -140,35 +140,26 @@ class SkillsImportAsActions extends base_command_1.BaseCommand {
140
140
  this.handleApiError(err);
141
141
  return;
142
142
  }
143
- const failed = result.results.filter((r) => r.status === 'failed');
143
+ const { rows, summary, failed } = (0, local_skills_1.summarizeSkillActionImport)(result);
144
144
  if (flags.json) {
145
145
  this.log(JSON.stringify(result, null, 2));
146
146
  }
147
147
  else {
148
- (0, format_1.renderTable)(result.results.map((r) => ({
149
- skill: r.name,
150
- import: r.status,
151
- action: r.actionCreated
152
- ? 'created'
153
- : (r.actionSkippedReason ??
154
- r.actionError ??
155
- (r.status === 'failed' ? '-' : 'not added')),
156
- detail: r.error ?? '',
157
- })), [
148
+ (0, format_1.renderTable)(rows, [
158
149
  { key: 'skill', header: 'SKILL' },
159
150
  { key: 'import', header: 'IMPORT' },
160
151
  { key: 'action', header: 'ACTION' },
161
152
  { key: 'detail', header: 'DETAIL' },
162
153
  ], (line) => this.log(line));
163
- this.log(`${result.actionsCreated} action(s) created on ${result.targetAgentId}; ` +
164
- `${failed.length} skill(s) failed.`);
154
+ this.log(summary);
165
155
  if (result.actionsError) {
166
156
  this.log(`The skills imported, but their actions could not be added: ${result.actionsError.message}`);
167
157
  }
168
158
  }
169
159
  // Partial success is normal and reported above; exit non-zero only when
170
- // something the caller asked for did not happen.
171
- if (failed.length > 0 || result.actionsError)
160
+ // something the caller asked for did not happen — including an action the
161
+ // full library could not take.
162
+ if (failed)
172
163
  this.exit(1);
173
164
  }
174
165
  }
@@ -148,6 +148,12 @@ class SkillsLocal extends base_command_1.BaseCommand {
148
148
  this.log(`${skills.length} skill${skills.length === 1 ? '' : 's'} on ${daemonId}` +
149
149
  (response.deviceName ? ` (${response.deviceName})` : '') +
150
150
  (response.online ? '' : ' — NOT CONNECTED, this inventory may be stale'));
151
+ if (response.online && response.cwdResolved !== true) {
152
+ // The list is the daemon's registration snapshot. A skill added to the
153
+ // machine since then is not in it until the daemon reconnects, and it
154
+ // read as "not on this machine" (OSK-10080).
155
+ this.log(`(as this daemon reported when it last connected — a skill added since appears after \`${(0, local_skills_1.daemonRestartCommand)(daemonId)}\` on that machine)`);
156
+ }
151
157
  (0, format_1.renderTable)(rows, [
152
158
  { key: 'name', header: 'NAME' },
153
159
  { key: 'root', header: 'ROOT' },
@@ -114,6 +114,8 @@ class SpacesActionsRun extends base_command_1.BaseCommand {
114
114
  ...spec,
115
115
  spaceId: space.id,
116
116
  assigneeAgentIds: [assigneeAgentId],
117
+ // The server hides an ephemeral action's task once it completes.
118
+ hideWhenDone: outcome !== 'durable',
117
119
  });
118
120
  }
119
121
  catch (err) {
@@ -133,10 +135,7 @@ class SpacesActionsRun extends base_command_1.BaseCommand {
133
135
  if (created.conversationId)
134
136
  this.log(`Conversation: ${created.conversationId}`);
135
137
  if (created.started && outcome === 'ephemeral') {
136
- // The web hides an ephemeral action's task when the run finishes, from
137
- // the tab that fired it. The CLI does not wait for the run, so say what
138
- // will be different rather than let the task's staying look like a bug.
139
- this.log(`This action is ephemeral. The web app hides its task when the run finishes; from the CLI it stays until you hide it: \`${bin} tasks move ${created.task.id} --status hidden\`.`);
138
+ this.log('This action is ephemeral: its task is hidden once the run finishes.');
140
139
  }
141
140
  }
142
141
  if (!created.started)
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
6
  const space_output_1 = require("../../../lib/space-output");
7
+ const format_1 = require("../../../lib/format");
7
8
  class SpacesBriefsGet extends base_command_1.BaseCommand {
8
9
  static description = 'Get a specific member brief from a space';
9
10
  static examples = [
@@ -39,7 +40,7 @@ class SpacesBriefsGet extends base_command_1.BaseCommand {
39
40
  const b = result;
40
41
  this.log(`Principal Type: ${b.principalType ?? flags.principal}`);
41
42
  this.log(`Principal ID: ${b.principalId ?? flags.id}`);
42
- this.log(`Updated: ${b.updatedAt ? formatTime(b.updatedAt) : '-'}`);
43
+ this.log(`Updated: ${b.updatedAt ? (0, format_1.localTime)(b.updatedAt) : '-'}`);
43
44
  this.log('');
44
45
  this.log('Content:');
45
46
  const content = typeof b.content === 'string' ? b.content : '';
@@ -49,11 +50,3 @@ class SpacesBriefsGet extends base_command_1.BaseCommand {
49
50
  }
50
51
  }
51
52
  exports.default = SpacesBriefsGet;
52
- function formatTime(value) {
53
- try {
54
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
55
- }
56
- catch {
57
- return String(value);
58
- }
59
- }
@@ -40,7 +40,7 @@ class SpacesBriefsList extends base_command_1.BaseCommand {
40
40
  principalType: String(b.principalType ?? '-'),
41
41
  principalId: String(b.principalId ?? '-'),
42
42
  length: String(typeof b.content === 'string' ? b.content.length : 0),
43
- updated: b.updatedAt ? formatTime(b.updatedAt) : '-',
43
+ updated: b.updatedAt ? (0, format_1.localTime)(b.updatedAt) : '-',
44
44
  }));
45
45
  (0, format_1.renderTable)(rows, [
46
46
  { key: 'principalType', header: 'PRINCIPAL TYPE' },
@@ -51,11 +51,3 @@ class SpacesBriefsList extends base_command_1.BaseCommand {
51
51
  }
52
52
  }
53
53
  exports.default = SpacesBriefsList;
54
- function formatTime(value) {
55
- try {
56
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
57
- }
58
- catch {
59
- return String(value);
60
- }
61
- }
@@ -59,7 +59,7 @@ class SpacesConversations extends base_command_1.BaseCommand {
59
59
  title: String(c.title ?? '-'),
60
60
  linkedTask: linked,
61
61
  own,
62
- updated: c.updatedAt ? formatTime(c.updatedAt) : '-',
62
+ updated: c.updatedAt ? (0, format_1.localTime)(c.updatedAt) : '-',
63
63
  };
64
64
  });
65
65
  (0, format_1.renderTable)(rows, [
@@ -76,11 +76,3 @@ class SpacesConversations extends base_command_1.BaseCommand {
76
76
  }
77
77
  }
78
78
  exports.default = SpacesConversations;
79
- function formatTime(value) {
80
- try {
81
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
82
- }
83
- catch {
84
- return String(value);
85
- }
86
- }
@@ -33,7 +33,7 @@ function heartbeatRow(h) {
33
33
  pattern: (0, format_1.formatCell)(pattern),
34
34
  timezone: (0, format_1.formatCell)(schedule?.timezone),
35
35
  enabled: h.enabled === true ? 'yes' : 'no',
36
- updated: h.updatedAt ? formatTime(h.updatedAt) : '-',
36
+ updated: h.updatedAt ? (0, format_1.localTime)(h.updatedAt) : '-',
37
37
  };
38
38
  }
39
39
  class SpacesHeartbeatsList extends base_command_1.BaseCommand {
@@ -91,11 +91,3 @@ class SpacesHeartbeatsList extends base_command_1.BaseCommand {
91
91
  }
92
92
  }
93
93
  exports.default = SpacesHeartbeatsList;
94
- function formatTime(value) {
95
- try {
96
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
97
- }
98
- catch {
99
- return String(value);
100
- }
101
- }
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
6
  const space_output_1 = require("../../../lib/space-output");
7
+ const format_1 = require("../../../lib/format");
7
8
  class SpacesHeartbeatsStatus extends base_command_1.BaseCommand {
8
9
  static description = 'Get the live status of a heartbeat for an agent in a space';
9
10
  static examples = [
@@ -45,16 +46,8 @@ class SpacesHeartbeatsStatus extends base_command_1.BaseCommand {
45
46
  // `running`/`nextRun`/`jobKey` which always rendered "no" / "-".
46
47
  const s = result;
47
48
  this.log(`Running: ${s.isRunning === true ? 'yes' : 'no'}`);
48
- this.log(`Next Run: ${s.nextRunAt ? formatTime(s.nextRunAt) : '-'}`);
49
+ this.log(`Next Run: ${s.nextRunAt ? (0, format_1.localTime)(s.nextRunAt) : '-'}`);
49
50
  this.log(`BullMQ Job Key: ${s.bullmqJobKey ?? '-'}`);
50
51
  }
51
52
  }
52
53
  exports.default = SpacesHeartbeatsStatus;
53
- function formatTime(value) {
54
- try {
55
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
56
- }
57
- catch {
58
- return String(value);
59
- }
60
- }
@@ -19,7 +19,7 @@ function activityRow(entry) {
19
19
  : `system:${actor.service}`
20
20
  : (entry.userId ?? entry.actorId);
21
21
  return {
22
- time: formatTime(entry.occurredAt ?? entry.timestamp ?? entry.createdAt),
22
+ time: (0, format_1.localTime)(entry.occurredAt ?? entry.timestamp ?? entry.createdAt),
23
23
  event: (0, format_1.formatCell)(entry.action ?? entry.event ?? entry.type),
24
24
  actor: (0, format_1.formatCell)(actorText),
25
25
  details: (0, format_1.formatCell)(entry.data ?? entry.details ?? entry.metadata),
@@ -71,15 +71,6 @@ function runFailuresFromActivity(entries) {
71
71
  }
72
72
  return out;
73
73
  }
74
- /** Same contract as `tasks monitor`'s timestamp column — never throws, never prints "undefined". */
75
- function formatTime(value) {
76
- if (!value)
77
- return '-';
78
- const date = new Date(String(value));
79
- if (Number.isNaN(date.getTime()))
80
- return String(value);
81
- return date.toISOString().slice(0, 19).replace('T', ' ');
82
- }
83
74
  class TasksActivity extends base_command_1.BaseCommand {
84
75
  static description = 'Show the immutable, multi-actor Activity ledger for a Task';
85
76
  static examples = [
@@ -5,14 +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
- function formatTime(value) {
9
- try {
10
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
11
- }
12
- catch {
13
- return String(value);
14
- }
15
- }
16
8
  /**
17
9
  * One approval document → one table row.
18
10
  *
@@ -27,7 +19,7 @@ function approvalRow(a) {
27
19
  type: (0, format_1.formatCell)(a.type),
28
20
  status: (0, format_1.formatCell)(a.status),
29
21
  approver: (0, format_1.formatCell)(a.approverAgentId ?? a.approverUserId ?? a.approver),
30
- created: a.createdAt ? formatTime(a.createdAt) : '-',
22
+ created: a.createdAt ? (0, format_1.localTime)(a.createdAt) : '-',
31
23
  };
32
24
  }
33
25
  class TasksApprovalsList extends base_command_1.BaseCommand {
@@ -5,14 +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
- function formatTime(value) {
9
- try {
10
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
11
- }
12
- catch {
13
- return String(value);
14
- }
15
- }
16
8
  function humanBytes(bytes) {
17
9
  const n = Number(bytes);
18
10
  if (!Number.isFinite(n))
@@ -41,7 +33,7 @@ function attachmentRow(a) {
41
33
  filename: (0, format_1.formatCell)(a.originalName ?? a.filename ?? a.name),
42
34
  size: humanBytes(a.size ?? a.fileSize),
43
35
  mime: (0, format_1.formatCell)(a.mimeType ?? a.contentType),
44
- uploaded: a.createdAt ? formatTime(a.createdAt) : '-',
36
+ uploaded: a.createdAt ? (0, format_1.localTime)(a.createdAt) : '-',
45
37
  };
46
38
  }
47
39
  class TasksAttachmentsList extends base_command_1.BaseCommand {
@@ -5,14 +5,6 @@ const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
6
  const format_1 = require("../../../lib/format");
7
7
  const task_resolver_1 = require("../../../lib/task-resolver");
8
- function formatTime(value) {
9
- try {
10
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
11
- }
12
- catch {
13
- return String(value);
14
- }
15
- }
16
8
  class TasksCommentsList extends base_command_1.BaseCommand {
17
9
  static description = 'List comments on a task';
18
10
  static examples = [
@@ -76,7 +68,7 @@ class TasksCommentsList extends base_command_1.BaseCommand {
76
68
  return;
77
69
  }
78
70
  const rows = items.map((c) => ({
79
- time: formatTime(c.createdAt),
71
+ time: (0, format_1.localTime)(c.createdAt),
80
72
  author: String(c.authorAgentId ?? c.authorUserId ?? c.author ?? '-'),
81
73
  body: (0, format_1.truncate)(String(c.body ?? c.content ?? '-'), 60),
82
74
  id: String(c.id ?? c._id ?? '-'),
@@ -255,6 +255,19 @@ class TasksComplete extends base_command_1.BaseCommand {
255
255
  });
256
256
  }
257
257
  catch (error) {
258
+ // Completing records a Result, so a closed Task refuses it the same way
259
+ // `tasks result submit` is refused, with the same way forward.
260
+ const refusal = (0, base_command_1.apiRefusal)(error);
261
+ if (refusal.code === 'TASK_REOPEN_REQUIRED') {
262
+ this.error([
263
+ refusal.message ?? 'This Task is closed.',
264
+ ...(0, task_closure_1.reopenRequiredLines)({
265
+ bin: this.config.bin,
266
+ task: identity.id,
267
+ command: 'complete',
268
+ }),
269
+ ].join('\n'), { exit: 1, code: 'TASK_REOPEN_REQUIRED' });
270
+ }
258
271
  this.handleApiError(error);
259
272
  }
260
273
  const url = (0, web_url_1.taskUrlFrom)(this.cliConfig.baseURL, { id: taskId });
@@ -3,14 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
- function formatTime(value) {
7
- try {
8
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
9
- }
10
- catch {
11
- return String(value);
12
- }
13
- }
6
+ const format_1 = require("../../lib/format");
14
7
  class TasksDriStatus extends base_command_1.BaseCommand {
15
8
  static description = 'Show DRI agent status for a task';
16
9
  static examples = [
@@ -40,7 +33,7 @@ class TasksDriStatus extends base_command_1.BaseCommand {
40
33
  const s = result;
41
34
  this.log(`Status: ${s.status ?? '-'}`);
42
35
  this.log(`Mode: ${s.mode ?? '-'}`);
43
- this.log(`Started At: ${s.startedAt ? formatTime(s.startedAt) : '-'}`);
36
+ this.log(`Started At: ${s.startedAt ? (0, format_1.localTime)(s.startedAt) : '-'}`);
44
37
  this.log(`Total: ${s.totalSubtasks ?? s.total ?? '-'}`);
45
38
  this.log(`Done: ${s.doneCount ?? s.done ?? '-'}`);
46
39
  this.log(`In Progress: ${s.inProgressCount ?? s.inProgress ?? '-'}`);
@@ -18,15 +18,17 @@ class TasksEventsAppend extends base_command_1.BaseCommand {
18
18
  static summary = 'DEPRECATED compatibility spelling for `tasks updates add` — append a legacy task event';
19
19
  // The FULL mapping, not a sample of it. The previous description named
20
20
  // `handoff`/`checkpoint` and `started|lifecycle` and stopped — so a caller
21
- // passing `--kind evidence` had no way to learn, before writing, that it
22
- // becomes a `verification` Update. Those are different claims: `evidence`
23
- // says a flow was exercised, `verification` says a claim was CHECKED, and the
24
- // typed-Update vocabulary exists precisely so the two cannot be confused.
21
+ // passing `--kind evidence` had no way to learn, before writing, what it
22
+ // became. It used to become a `verification` with an invented `inconclusive`
23
+ // result; `evidence` says a flow was exercised, `verification` says a claim was
24
+ // CHECKED, so it now becomes `progress` and keeps the evidence as a reference
25
+ // (OSK-9312).
25
26
  // Mirrors `LEGACY_KIND_TO_UPDATE_TYPE` in `api/server/services/TaskWorkEvent.js`.
26
27
  static description = 'DEPRECATED compatibility adapter for the historical Event vocabulary. Every kind is ' +
27
28
  'stored as a canonical Update of a DIFFERENT name, so read this before relying on one: ' +
28
- '`evidence` and `verification` both become `verification`; `checkpoint`, `changed`, ' +
29
- '`completed` and `handoff` all become `progress`; `input_requested` and `failed` become ' +
29
+ '`verification` becomes a passed `verification`; `evidence`, `checkpoint`, `changed`, ' +
30
+ "`completed` and `handoff` all become `progress` (evidence text is kept as the Update's reference, " +
31
+ 'with no invented result); `input_requested` and `failed` become ' +
30
32
  '`blocker`; `decision` stays `decision`. `--kind started|lifecycle` writes only to the ' +
31
33
  'Activity ledger and will NOT appear in `tasks updates list`. Use `tasks updates add` ' +
32
34
  'instead, which writes the type you name.';
@@ -129,7 +131,7 @@ class TasksEventsAppend extends base_command_1.BaseCommand {
129
131
  * where it happens to be true. `finding` and `progress` exist only on the
130
132
  * canonical command; `evidence`, `checkpoint` and the rest only here.
131
133
  */
132
- this.log(`\`tasks events append --kind ${written.canonicalType}\` maps onto ` +
134
+ this.log(`\`tasks events append --kind ${flags.kind}\` maps onto ` +
133
135
  `\`${this.config.bin} tasks updates add --type ${written.canonicalType}\`, which is the ` +
134
136
  'canonical command. Their vocabularies differ otherwise — `--type ' +
135
137
  'progress|finding` exist only there — and `tasks updates list` reads them back.');
@@ -4,14 +4,6 @@ const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
6
  const format_1 = require("../../lib/format");
7
- function formatTime(value) {
8
- try {
9
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
10
- }
11
- catch {
12
- return String(value);
13
- }
14
- }
15
7
  class TasksExecutionTimeline extends base_command_1.BaseCommand {
16
8
  static description = 'Show execution timeline for a task';
17
9
  static examples = [
@@ -49,7 +41,7 @@ class TasksExecutionTimeline extends base_command_1.BaseCommand {
49
41
  return;
50
42
  }
51
43
  const rows = items.map((entry) => ({
52
- timestamp: formatTime(entry.timestamp ?? entry.createdAt),
44
+ timestamp: (0, format_1.localTime)(entry.timestamp ?? entry.createdAt),
53
45
  event: String(entry.event ?? entry.type ?? '-'),
54
46
  duration: entry.durationMs != null ? `${entry.durationMs}ms` : '-',
55
47
  tokens: String(entry.tokens ?? entry.totalTokens ?? '-'),
@@ -205,7 +205,7 @@ async function fetchRecentEvents(tasks, limit) {
205
205
  ref: String(task.identifier ?? task.taskNumber ?? '-'),
206
206
  taskId: (0, tasks_1.taskId)(task),
207
207
  event: String(record.event ?? record.type ?? '-'),
208
- time: formatTime(record.timestamp ?? record.createdAt),
208
+ time: (0, format_1.localTime)(record.timestamp ?? record.createdAt),
209
209
  run: String(record.runId ?? '-'),
210
210
  };
211
211
  });
@@ -216,11 +216,3 @@ async function fetchRecentEvents(tasks, limit) {
216
216
  }));
217
217
  return responses.flat();
218
218
  }
219
- function formatTime(value) {
220
- if (!value)
221
- return '-';
222
- const date = new Date(String(value));
223
- if (Number.isNaN(date.getTime()))
224
- return String(value);
225
- return date.toISOString().slice(0, 19).replace('T', ' ');
226
- }
@@ -122,6 +122,20 @@ class TasksResultSubmit extends base_command_1.BaseCommand {
122
122
  : await data_provider_1.dataService.submitTaskResult({ taskId: task.id, data });
123
123
  }
124
124
  catch (error) {
125
+ // A closed Task refuses a Result. Name the way forward here, where the
126
+ // commands are known: the API's own message stays surface-neutral
127
+ // (OSK-10031).
128
+ const refusal = (0, base_command_1.apiRefusal)(error);
129
+ if (refusal.code === 'TASK_REOPEN_REQUIRED') {
130
+ this.error([
131
+ refusal.message ?? 'This Task is closed.',
132
+ ...(0, task_closure_1.reopenRequiredLines)({
133
+ bin: this.config.bin,
134
+ task: task.id,
135
+ command: 'result submit',
136
+ }),
137
+ ].join('\n'), { exit: 1, code: 'TASK_REOPEN_REQUIRED' });
138
+ }
125
139
  this.handleApiError(error);
126
140
  }
127
141
  const url = (0, web_url_1.taskUrlFrom)(this.cliConfig.baseURL, { id: task.id });
@@ -10,14 +10,6 @@ const data_provider_1 = require("@skrr-ai/data-provider");
10
10
  const base_command_1 = require("../../base-command");
11
11
  const format_1 = require("../../lib/format");
12
12
  const activity_1 = require("./activity");
13
- function formatTime(value) {
14
- try {
15
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
16
- }
17
- catch {
18
- return String(value);
19
- }
20
- }
21
13
  /**
22
14
  * OSK-4836 — say WHERE a run executed. A named daemon wins over the environment
23
15
  * label; an environment with no daemon is the cloud worker (or a runtime whose
@@ -163,7 +155,7 @@ class TasksRuns extends base_command_1.BaseCommand {
163
155
  runId: String(run.runId ?? run.id ?? run._id ?? '-'),
164
156
  status: String(run.status ?? '-'),
165
157
  executor: formatRunExecutor(run),
166
- started: run.startedAt ? formatTime(run.startedAt) : '-',
158
+ started: run.startedAt ? (0, format_1.localTime)(run.startedAt) : '-',
167
159
  duration: run.durationMs != null ? `${run.durationMs}ms` : '-',
168
160
  tokens: String(run.totalTokens ?? run.tokens ?? '-'),
169
161
  }));
@@ -11,6 +11,7 @@ const task_closure_1 = require("../../lib/task-closure");
11
11
  const task_resolver_1 = require("../../lib/task-resolver");
12
12
  const web_url_1 = require("../../lib/web-url");
13
13
  const html_text_1 = require("../../lib/html-text");
14
+ const format_1 = require("../../lib/format");
14
15
  /**
15
16
  * Where to look next — as COMMANDS, not as facts about the task.
16
17
  *
@@ -67,7 +68,7 @@ function taskPointerLines(t, ref, bin = 'skrr') {
67
68
  */
68
69
  function taskFailureLines(t, bin = 'skrr') {
69
70
  const error = typeof t.executionError === 'string' ? t.executionError.trim() : '';
70
- const failedAt = t.lastFailedAt ? formatTime(t.lastFailedAt) : null;
71
+ const failedAt = t.lastFailedAt ? (0, format_1.localTime)(t.lastFailedAt) : null;
71
72
  const isFailed = t.status === 'failed';
72
73
  if (!error && !failedAt && !isFailed)
73
74
  return [];
@@ -335,7 +336,7 @@ class TasksShow extends base_command_1.BaseCommand {
335
336
  this.log(`Previews: ${delivery.previewLinks.length}`);
336
337
  }
337
338
  if (delivery.prStateUpdatedAt)
338
- this.log(`PR updated: ${formatTime(delivery.prStateUpdatedAt)}`);
339
+ this.log(`PR updated: ${(0, format_1.localTime)(delivery.prStateUpdatedAt)}`);
339
340
  }
340
341
  // Prefer server-enriched names; fall back to bare ids under --no-enrich.
341
342
  const enrichedSkills = Array.isArray(t._pinnedSkills)
@@ -369,9 +370,9 @@ class TasksShow extends base_command_1.BaseCommand {
369
370
  .join(', ')} (attached; injected on every run)`);
370
371
  }
371
372
  if (t.createdAt)
372
- this.log(`Created: ${formatTime(t.createdAt)}`);
373
+ this.log(`Created: ${(0, format_1.localTime)(t.createdAt)}`);
373
374
  if (t.updatedAt)
374
- this.log(`Updated: ${formatTime(t.updatedAt)}`);
375
+ this.log(`Updated: ${(0, format_1.localTime)(t.updatedAt)}`);
375
376
  /**
376
377
  * Say which Task model this row belongs to, on the one surface everybody
377
378
  * reads first.
@@ -434,11 +435,3 @@ class TasksShow extends base_command_1.BaseCommand {
434
435
  }
435
436
  }
436
437
  exports.default = TasksShow;
437
- function formatTime(value) {
438
- try {
439
- return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
440
- }
441
- catch {
442
- return String(value);
443
- }
444
- }