@kosuke-ai/kosuke 1.0.47 → 1.0.48

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.48
4
+
5
+ - Command names from before the command grammar no longer run; `kosuke <group> --help` lists the current ones. The MCP server refuses the former toolsets too: a client that requests `deploy`, `members` or `personal-tasks` now gets HTTP 400 and must switch its configuration to `deploys`, `workspaces` or `tasks`. The `user` and `workspaces` toolsets no longer include the tools that moved to `crons`, `files`, `integrations`, `plugins`, `providers`, `sensei` and `skills`: request those toolsets instead.
6
+ - Add `kosuke sensei threads create`, which lets Sensei open a new thread with its own Turn from any point of a Turn.
7
+ - Add `kosuke sessions env sync` to deliver a project's current environment variables to a running session sandbox and restart its services.
8
+ - `kosuke sessions skill-runs --help` now lists every `--result` value `finish` accepts. A marker it rejects, such as `--result pass`, still exits 0 and sends nothing, but prints one line on stderr saying it was not recorded and why.
9
+
3
10
  ## 1.0.47
4
11
 
5
12
  - `kosuke deploys queue steer` now steers on any deploy model whose runtime takes a steer, not Claude only.
package/README.md CHANGED
@@ -40,10 +40,14 @@ kosuke sessions skill-runs finish kosuke:ship --result ready
40
40
 
41
41
  The sandbox supplies the session identity and its Turn credential. The server selects the
42
42
  running Chat Job. These commands accept only known switch names and result values, never
43
- free text. A child skill starts inside its parent and ends before the parent resumes.
43
+ free text. `--result` takes one of `passed`, `failed`, `blocked`, `skipped`, `prototype`,
44
+ `question`, `ready`, `cancelled` or `open_items`, and `--help` lists them. A child skill
45
+ starts inside its parent and ends before the parent resumes.
44
46
 
45
47
  Markers are best effort: one request, a 1.5-second deadline, no retry, and exit status zero
46
- even for invalid input or a tracking failure. They print no success message. Without the
48
+ even for invalid input or a tracking failure. They print no success message. Input they
49
+ reject sends nothing and prints one line on stderr saying the marker was not recorded and
50
+ why, without repeating the input. Without the
47
51
  main-agent marker context, they send no request. Delegated Runs do not record markers.
48
52
  Other commands keep their normal error exit codes. `sessions skill-runs --capabilities`
49
53
  prints `skill-markers-v1` without credentials, so an older CLI never receives an unsupported rule.
@@ -31,6 +31,13 @@ const RESULTS = new Set([
31
31
  ]);
32
32
  const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
33
33
  const DEADLINE_MS = 1500;
34
+ const RESULT_CHOICES = [...RESULTS].join('|');
35
+ // `run` answers --help before Commander, so this is the only help an agent reads: it names
36
+ // every result, or an agent following it must guess one.
37
+ const USAGE = `kosuke sessions skill-runs start <name> [--fix] [--sync] [--no-review]
38
+ kosuke sessions skill-runs finish <name> [--result ${RESULT_CHOICES}]
39
+ Best effort: one request, 1.5-second deadline, always exits 0.
40
+ `;
34
41
  async function appendMarker(path, value) {
35
42
  try {
36
43
  const stat = await lstat(path).catch(() => null);
@@ -91,37 +98,49 @@ export async function runSkillMarkerCommand(args, options = {}) {
91
98
  const [group, noun] = HAND_WRITTEN.sessionsSkillRuns.command;
92
99
  if (args[0] !== group || args[1] !== noun)
93
100
  return false;
94
- const { env = process.env, fetch: request = globalThis.fetch, stdout = (text) => process.stdout.write(text), timeoutMs = DEADLINE_MS, } = options;
101
+ const { env = process.env, fetch: request = globalThis.fetch, stdout = (text) => process.stdout.write(text), stderr = (line) => process.stderr.write(line + '\n'), timeoutMs = DEADLINE_MS, } = options;
102
+ // Still exit 0, but say why, so an agent can correct a rejected marker. Never echo the input:
103
+ // it may be free text.
104
+ const notRecorded = (why) => {
105
+ try {
106
+ stderr(`kosuke: skill marker not recorded: ${why}. See kosuke sessions skill-runs --help.`);
107
+ }
108
+ catch {
109
+ // Reporting is best effort too.
110
+ }
111
+ return true;
112
+ };
95
113
  if (args.length === 3 && args[2] === '--capabilities') {
96
114
  stdout('skill-markers-v1\n');
97
115
  return true;
98
116
  }
99
117
  if (args.includes('--help') || args.includes('-h')) {
100
- stdout('kosuke sessions skill-runs start <name> [--fix] [--sync] [--no-review]\nkosuke sessions skill-runs finish <name> [--result <verdict>]\nBest effort: one request, 1.5-second deadline, always exits 0.\n');
118
+ stdout(USAGE);
101
119
  return true;
102
120
  }
103
121
  const [, , verb, rawName, ...rest] = args;
104
- // Alias: `end`, the verb before the grammar, which older Factory Skills still run.
105
- const action = verb === 'finish' || verb === 'end' ? 'end' : verb;
106
- if ((action !== 'start' && action !== 'end') ||
107
- !rawName ||
108
- !/^(?:kosuke:)?[a-z][a-z0-9-]{0,79}$/.test(rawName))
109
- return true;
122
+ if (verb !== 'start' && verb !== 'finish')
123
+ return notRecorded('use start or finish');
124
+ if (!rawName || !/^(?:kosuke:)?[a-z][a-z0-9-]{0,79}$/.test(rawName))
125
+ return notRecorded('give a skill name, such as kosuke:ship');
110
126
  const flags = [];
127
+ const action = verb === 'finish' ? 'end' : 'start';
111
128
  let result;
112
129
  for (let index = 0; index < rest.length; index++) {
113
130
  const value = rest[index];
114
131
  if (value === '--result' && action === 'end' && result === undefined) {
115
132
  result = rest[++index];
116
133
  if (!result || !RESULTS.has(result))
117
- return true;
134
+ return notRecorded(`--result takes one of ${RESULT_CHOICES}`);
118
135
  }
119
136
  else if (FLAGS.has(value)) {
120
137
  if (!flags.includes(value))
121
138
  flags.push(value);
122
139
  }
140
+ else if (value === '--result')
141
+ return notRecorded(action === 'start' ? 'only finish takes --result' : '--result is given once');
123
142
  else
124
- return true;
143
+ return notRecorded('an argument is not a known switch');
125
144
  }
126
145
  const bridge = env.KOSUKE_SKILL_MARKER_FILE;
127
146
  const clockId = env.KOSUKE_SKILL_CLOCK_ID;
@@ -225,7 +244,7 @@ export function attachSkillMarkerCommands(program, options = {}) {
225
244
  for (const flag of FLAGS)
226
245
  command.option(flag);
227
246
  if (action === 'finish')
228
- command.option('--result <verdict>', 'A known result, such as passed, failed, blocked, or ready.');
247
+ command.option('--result <verdict>', `One known result: ${RESULT_CHOICES}.`);
229
248
  command.action(async (_name, _flags, cmd) => {
230
249
  await runSkillMarkerCommand(cmd.parent.parent.parent.args, options);
231
250
  });
@@ -229,113 +229,115 @@ import { operation as o227 } from './sensei/sessions-assessments-create.js';
229
229
  import { operation as o228 } from './sensei/sessions-facts-get.js';
230
230
  import { operation as o229 } from './sensei/suggestions-create.js';
231
231
  import { operation as o230 } from './sensei/threads-close.js';
232
- import { operation as o231 } from './sensei/threads-get.js';
233
- import { operation as o232 } from './sensei/threads-list.js';
234
- import { operation as o233 } from './sensei/threads-move.js';
235
- import { operation as o234 } from './sensei/threads-split.js';
236
- import { operation as o235 } from './sensei/tickets-merge.js';
237
- import { operation as o236 } from './sensei/watch-reads-finish.js';
238
- import { operation as o237 } from './sensei/widgets-get.js';
239
- import { operation as o238 } from './sensei/writing-get.js';
240
- import { operation as o239 } from './sensei/writing-set.js';
241
- import { operation as o240 } from './sensei/writing-samples-create.js';
242
- import { operation as o241 } from './sessions/app-stack-start.js';
243
- import { operation as o242 } from './sessions/artifacts-create.js';
244
- import { operation as o243 } from './sessions/artifacts-get.js';
245
- import { operation as o244 } from './sessions/artifacts-list.js';
246
- import { operation as o245 } from './sessions/create.js';
247
- import { operation as o246 } from './sessions/delete.js';
248
- import { operation as o247 } from './sessions/desktop-control-set.js';
249
- import { operation as o248 } from './sessions/desktop-get.js';
250
- import { operation as o249 } from './sessions/desktop-start.js';
251
- import { operation as o250 } from './sessions/diff-comments-create.js';
252
- import { operation as o251 } from './sessions/diff-comments-delete.js';
253
- import { operation as o252 } from './sessions/diff-comments-list.js';
254
- import { operation as o253 } from './sessions/diff-comments-update.js';
255
- import { operation as o254 } from './sessions/diff-commits-list.js';
256
- import { operation as o255 } from './sessions/diff-files-list.js';
257
- import { operation as o256 } from './sessions/diff-patch-get.js';
258
- import { operation as o257 } from './sessions/files-get.js';
259
- import { operation as o258 } from './sessions/files-list.js';
260
- import { operation as o259 } from './sessions/files-set.js';
261
- import { operation as o260 } from './sessions/get.js';
262
- import { operation as o261 } from './sessions/git-state-get.js';
263
- import { operation as o262 } from './sessions/go-ahead-delete.js';
264
- import { operation as o263 } from './sessions/go-ahead-set.js';
265
- import { operation as o264 } from './sessions/jobs-cancel.js';
266
- import { operation as o265 } from './sessions/jobs-get.js';
267
- import { operation as o266 } from './sessions/jobs-list.js';
268
- import { operation as o267 } from './sessions/labels-set.js';
269
- import { operation as o268 } from './sessions/labels-update.js';
270
- import { operation as o269 } from './sessions/list.js';
271
- import { operation as o270 } from './sessions/list--all.js';
272
- import { operation as o271 } from './sessions/mark-read.js';
273
- import { operation as o272 } from './sessions/messages-get.js';
274
- import { operation as o273 } from './sessions/messages-list.js';
275
- import { operation as o274 } from './sessions/prompt-update.js';
276
- import { operation as o275 } from './sessions/qa-runs-finish.js';
277
- import { operation as o276 } from './sessions/qa-runs-fixes-create.js';
278
- import { operation as o277 } from './sessions/qa-runs-get.js';
279
- import { operation as o278 } from './sessions/qa-runs-results-create.js';
280
- import { operation as o279 } from './sessions/qa-runs-start.js';
281
- import { operation as o280 } from './sessions/qa-runs-stop.js';
282
- import { operation as o281 } from './sessions/qa-set.js';
283
- import { operation as o282 } from './sessions/queue-delete.js';
284
- import { operation as o283 } from './sessions/queue-list.js';
285
- import { operation as o284 } from './sessions/queue-move.js';
286
- import { operation as o285 } from './sessions/queue-resume.js';
287
- import { operation as o286 } from './sessions/queue-send.js';
288
- import { operation as o287 } from './sessions/queue-steer.js';
289
- import { operation as o288 } from './sessions/queue-update.js';
290
- import { operation as o289 } from './sessions/review-set.js';
291
- import { operation as o290 } from './sessions/runtime-commands-run.js';
292
- import { operation as o291 } from './sessions/search.js';
293
- import { operation as o292 } from './sessions/send.js';
294
- import { operation as o293 } from './sessions/start.js';
295
- import { operation as o294 } from './sessions/steer.js';
296
- import { operation as o295 } from './sessions/update.js';
297
- import { operation as o296 } from './skills/create.js';
298
- import { operation as o297 } from './skills/create--personal.js';
299
- import { operation as o298 } from './skills/delete.js';
300
- import { operation as o299 } from './skills/delete--personal.js';
301
- import { operation as o300 } from './skills/get.js';
302
- import { operation as o301 } from './skills/get--personal.js';
303
- import { operation as o302 } from './skills/list.js';
304
- import { operation as o303 } from './skills/list--personal.js';
305
- import { operation as o304 } from './skills/update.js';
306
- import { operation as o305 } from './skills/update--personal.js';
307
- import { operation as o306 } from './tasks/create.js';
308
- import { operation as o307 } from './tasks/create--personal.js';
309
- import { operation as o308 } from './tasks/delete.js';
310
- import { operation as o309 } from './tasks/delete--personal.js';
311
- import { operation as o310 } from './tasks/get.js';
312
- import { operation as o311 } from './tasks/get--personal.js';
313
- import { operation as o312 } from './tasks/labels-list.js';
314
- import { operation as o313 } from './tasks/list.js';
315
- import { operation as o314 } from './tasks/list--all.js';
316
- import { operation as o315 } from './tasks/list--personal.js';
317
- import { operation as o316 } from './tasks/move.js';
318
- import { operation as o317 } from './tasks/move--personal.js';
319
- import { operation as o318 } from './tasks/start.js';
320
- import { operation as o319 } from './tasks/start--personal.js';
321
- import { operation as o320 } from './tasks/update.js';
322
- import { operation as o321 } from './tasks/update--personal.js';
323
- import { operation as o322 } from './user/api-keys-delete.js';
324
- import { operation as o323 } from './user/profile-get.js';
325
- import { operation as o324 } from './user/push-devices-create.js';
326
- import { operation as o325 } from './user/push-devices-delete.js';
327
- import { operation as o326 } from './user/usage-get.js';
328
- import { operation as o327 } from './workspaces/artifacts-search.js';
329
- import { operation as o328 } from './workspaces/credits-get.js';
330
- import { operation as o329 } from './workspaces/get.js';
331
- import { operation as o330 } from './workspaces/list.js';
332
- import { operation as o331 } from './workspaces/members-list.js';
333
- import { operation as o332 } from './workspaces/members-list--all.js';
334
- import { operation as o333 } from './workspaces/sandbox-limit-get.js';
335
- import { operation as o334 } from './workspaces/sandboxes-stop.js';
336
- import { operation as o335 } from './workspaces/timezone-set.js';
337
- import { operation as o336 } from './workspaces/usage-breakdown-get.js';
338
- import { operation as o337 } from './workspaces/usage-get.js';
232
+ import { operation as o231 } from './sensei/threads-create.js';
233
+ import { operation as o232 } from './sensei/threads-get.js';
234
+ import { operation as o233 } from './sensei/threads-list.js';
235
+ import { operation as o234 } from './sensei/threads-move.js';
236
+ import { operation as o235 } from './sensei/threads-split.js';
237
+ import { operation as o236 } from './sensei/tickets-merge.js';
238
+ import { operation as o237 } from './sensei/watch-reads-finish.js';
239
+ import { operation as o238 } from './sensei/widgets-get.js';
240
+ import { operation as o239 } from './sensei/writing-get.js';
241
+ import { operation as o240 } from './sensei/writing-set.js';
242
+ import { operation as o241 } from './sensei/writing-samples-create.js';
243
+ import { operation as o242 } from './sessions/app-stack-start.js';
244
+ import { operation as o243 } from './sessions/artifacts-create.js';
245
+ import { operation as o244 } from './sessions/artifacts-get.js';
246
+ import { operation as o245 } from './sessions/artifacts-list.js';
247
+ import { operation as o246 } from './sessions/create.js';
248
+ import { operation as o247 } from './sessions/delete.js';
249
+ import { operation as o248 } from './sessions/desktop-control-set.js';
250
+ import { operation as o249 } from './sessions/desktop-get.js';
251
+ import { operation as o250 } from './sessions/desktop-start.js';
252
+ import { operation as o251 } from './sessions/diff-comments-create.js';
253
+ import { operation as o252 } from './sessions/diff-comments-delete.js';
254
+ import { operation as o253 } from './sessions/diff-comments-list.js';
255
+ import { operation as o254 } from './sessions/diff-comments-update.js';
256
+ import { operation as o255 } from './sessions/diff-commits-list.js';
257
+ import { operation as o256 } from './sessions/diff-files-list.js';
258
+ import { operation as o257 } from './sessions/diff-patch-get.js';
259
+ import { operation as o258 } from './sessions/env-sync.js';
260
+ import { operation as o259 } from './sessions/files-get.js';
261
+ import { operation as o260 } from './sessions/files-list.js';
262
+ import { operation as o261 } from './sessions/files-set.js';
263
+ import { operation as o262 } from './sessions/get.js';
264
+ import { operation as o263 } from './sessions/git-state-get.js';
265
+ import { operation as o264 } from './sessions/go-ahead-delete.js';
266
+ import { operation as o265 } from './sessions/go-ahead-set.js';
267
+ import { operation as o266 } from './sessions/jobs-cancel.js';
268
+ import { operation as o267 } from './sessions/jobs-get.js';
269
+ import { operation as o268 } from './sessions/jobs-list.js';
270
+ import { operation as o269 } from './sessions/labels-set.js';
271
+ import { operation as o270 } from './sessions/labels-update.js';
272
+ import { operation as o271 } from './sessions/list.js';
273
+ import { operation as o272 } from './sessions/list--all.js';
274
+ import { operation as o273 } from './sessions/mark-read.js';
275
+ import { operation as o274 } from './sessions/messages-get.js';
276
+ import { operation as o275 } from './sessions/messages-list.js';
277
+ import { operation as o276 } from './sessions/prompt-update.js';
278
+ import { operation as o277 } from './sessions/qa-runs-finish.js';
279
+ import { operation as o278 } from './sessions/qa-runs-fixes-create.js';
280
+ import { operation as o279 } from './sessions/qa-runs-get.js';
281
+ import { operation as o280 } from './sessions/qa-runs-results-create.js';
282
+ import { operation as o281 } from './sessions/qa-runs-start.js';
283
+ import { operation as o282 } from './sessions/qa-runs-stop.js';
284
+ import { operation as o283 } from './sessions/qa-set.js';
285
+ import { operation as o284 } from './sessions/queue-delete.js';
286
+ import { operation as o285 } from './sessions/queue-list.js';
287
+ import { operation as o286 } from './sessions/queue-move.js';
288
+ import { operation as o287 } from './sessions/queue-resume.js';
289
+ import { operation as o288 } from './sessions/queue-send.js';
290
+ import { operation as o289 } from './sessions/queue-steer.js';
291
+ import { operation as o290 } from './sessions/queue-update.js';
292
+ import { operation as o291 } from './sessions/review-set.js';
293
+ import { operation as o292 } from './sessions/runtime-commands-run.js';
294
+ import { operation as o293 } from './sessions/search.js';
295
+ import { operation as o294 } from './sessions/send.js';
296
+ import { operation as o295 } from './sessions/start.js';
297
+ import { operation as o296 } from './sessions/steer.js';
298
+ import { operation as o297 } from './sessions/update.js';
299
+ import { operation as o298 } from './skills/create.js';
300
+ import { operation as o299 } from './skills/create--personal.js';
301
+ import { operation as o300 } from './skills/delete.js';
302
+ import { operation as o301 } from './skills/delete--personal.js';
303
+ import { operation as o302 } from './skills/get.js';
304
+ import { operation as o303 } from './skills/get--personal.js';
305
+ import { operation as o304 } from './skills/list.js';
306
+ import { operation as o305 } from './skills/list--personal.js';
307
+ import { operation as o306 } from './skills/update.js';
308
+ import { operation as o307 } from './skills/update--personal.js';
309
+ import { operation as o308 } from './tasks/create.js';
310
+ import { operation as o309 } from './tasks/create--personal.js';
311
+ import { operation as o310 } from './tasks/delete.js';
312
+ import { operation as o311 } from './tasks/delete--personal.js';
313
+ import { operation as o312 } from './tasks/get.js';
314
+ import { operation as o313 } from './tasks/get--personal.js';
315
+ import { operation as o314 } from './tasks/labels-list.js';
316
+ import { operation as o315 } from './tasks/list.js';
317
+ import { operation as o316 } from './tasks/list--all.js';
318
+ import { operation as o317 } from './tasks/list--personal.js';
319
+ import { operation as o318 } from './tasks/move.js';
320
+ import { operation as o319 } from './tasks/move--personal.js';
321
+ import { operation as o320 } from './tasks/start.js';
322
+ import { operation as o321 } from './tasks/start--personal.js';
323
+ import { operation as o322 } from './tasks/update.js';
324
+ import { operation as o323 } from './tasks/update--personal.js';
325
+ import { operation as o324 } from './user/api-keys-delete.js';
326
+ import { operation as o325 } from './user/profile-get.js';
327
+ import { operation as o326 } from './user/push-devices-create.js';
328
+ import { operation as o327 } from './user/push-devices-delete.js';
329
+ import { operation as o328 } from './user/usage-get.js';
330
+ import { operation as o329 } from './workspaces/artifacts-search.js';
331
+ import { operation as o330 } from './workspaces/credits-get.js';
332
+ import { operation as o331 } from './workspaces/get.js';
333
+ import { operation as o332 } from './workspaces/list.js';
334
+ import { operation as o333 } from './workspaces/members-list.js';
335
+ import { operation as o334 } from './workspaces/members-list--all.js';
336
+ import { operation as o335 } from './workspaces/sandbox-limit-get.js';
337
+ import { operation as o336 } from './workspaces/sandboxes-stop.js';
338
+ import { operation as o337 } from './workspaces/timezone-set.js';
339
+ import { operation as o338 } from './workspaces/usage-breakdown-get.js';
340
+ import { operation as o339 } from './workspaces/usage-get.js';
339
341
  export const operations = [
340
342
  o0,
341
343
  o1,
@@ -675,4 +677,6 @@ export const operations = [
675
677
  o335,
676
678
  o336,
677
679
  o337,
680
+ o338,
681
+ o339,
678
682
  ];
@@ -0,0 +1,35 @@
1
+ export const operation = {
2
+ "method": "post",
3
+ "path": "/api/sensei/thread-create",
4
+ "command": [
5
+ "sensei",
6
+ "threads",
7
+ "create"
8
+ ],
9
+ "summary": "Open a new thread for the member, at any point of this Turn, on a prompt you write. Only Sensei calls it, for a separate topic that should not go on in this thread. Never for the asks of the member’s message that started this thread: `sensei threads split` does that. The new thread gets its own Turn, which may read Queued, and links back here; nothing of this thread goes with it, so the prompt says all it needs. A Turn opens at most 3 threads, and so do the threads opened from one thread in all. Answers the new thread id and turn id: do not do that work here.",
10
+ "pathParams": [],
11
+ "query": [],
12
+ "body": {
13
+ "fields": [
14
+ {
15
+ "name": "prompt",
16
+ "flag": "prompt",
17
+ "kind": "string",
18
+ "required": true,
19
+ "description": "What the new thread’s Turn does, whole, in words that stand without this thread: it reads nothing else of it."
20
+ },
21
+ {
22
+ "name": "title",
23
+ "flag": "title",
24
+ "kind": "string",
25
+ "required": false,
26
+ "description": "A short title for the new thread. Without it, the thread is named by the prompt."
27
+ }
28
+ ],
29
+ "required": true
30
+ },
31
+ "multipart": null,
32
+ "attachments": false,
33
+ "anonymous": false,
34
+ "agents": "all"
35
+ };
@@ -0,0 +1,21 @@
1
+ export const operation = {
2
+ "method": "post",
3
+ "path": "/api/projects/{projectId}/chat-sessions/{sessionId}/env-sync",
4
+ "command": [
5
+ "sessions",
6
+ "env",
7
+ "sync"
8
+ ],
9
+ "summary": "Deliver the project's saved environment variables, with its services and setup commands, to a chat session's running sandbox and restart its setup and services, so a variable added after the sandbox booted reaches them. Answers status synced with the variable names, never their values, once the services answer again, or status running when setup outlasts ten minutes and the sync goes on. Refused, never queued: 409 TURN_RUNNING while a turn runs, SANDBOX_NOT_RUNNING when the sandbox is not up (it is not woken), SANDBOX_PROVISIONING or SANDBOX_NOT_READY while it is created or boots, APP_STACK_STARTING during an App stack start and SANDBOX_BUSY while another update changes it; 422 ENV_SYNC_FAILED when setup or a service did not come back.",
10
+ "pathParams": [
11
+ "projectId",
12
+ "sessionId"
13
+ ],
14
+ "query": [],
15
+ "body": null,
16
+ "multipart": null,
17
+ "attachments": false,
18
+ "answerTimeoutMs": 660000,
19
+ "anonymous": false,
20
+ "agents": "all"
21
+ };
@@ -6,7 +6,7 @@ export const operation = {
6
6
  "qa",
7
7
  "set"
8
8
  ],
9
- "summary": "Record the commit QA passed on as the session's qaPassedSha: a member's override, or the session's own agent. `sessions qa runs finish` records it when the whole checklist passed. A pull request is done when qaPassedSha equals its head.",
9
+ "summary": "Record the commit QA passed on as the session's qaPassedSha: a member's override. `sessions qa runs finish` records it when the whole checklist passed. A pull request is done when qaPassedSha equals its head.",
10
10
  "pathParams": [
11
11
  "projectId",
12
12
  "sessionId"
package/dist/program.js CHANGED
@@ -6,15 +6,13 @@ import { attachIntegrationsCommands } from './commands/integrations.js';
6
6
  import { attachWatchCommand } from './commands/watch.js';
7
7
  import { operations } from './generated/commands/index.js';
8
8
  import { attachCommand } from './runtime/attach.js';
9
- import { attachFormerCommands } from './runtime/former-commands.js';
10
9
  import { formsOf } from './runtime/variants.js';
11
10
  import { agentTokenOf, isReachable } from './runtime/agent-tokens.js';
12
11
  import { createRuntime, ExitSignal } from './runtime/runtime.js';
13
12
  import { version } from './runtime/version.js';
14
13
  /**
15
14
  * The command tree: the commands `commands/hand-written.ts` lists by hand, everything else
16
- * from the generated descriptors, one leaf per command over its forms, then the former
17
- * names as hidden aliases. Global flags are read
15
+ * from the generated descriptors, one leaf per command over its forms. Global flags are read
18
16
  * before any subcommand runs, so the runtime the subcommands share is built once, from them.
19
17
  */
20
18
  export function createProgram(options = {}) {
@@ -61,7 +59,6 @@ export function createProgram(options = {}) {
61
59
  // The job stream admits a member's API key only; it closes 4401 on every narrower token.
62
60
  if (narrowedTo === null)
63
61
  attachWatchCommand(program, lazy, options.watch);
64
- attachFormerCommands(program, operations.filter(reaches), lazy);
65
62
  return program;
66
63
  }
67
64
  /** Run to completion; an ExitSignal has already reported and set the exit code. */
@@ -13,16 +13,13 @@ export function attachCommand(root, forms, runtime, { reachable = () => true } =
13
13
  const [only] = forms;
14
14
  if (forms.length === 1 && !only.variant) {
15
15
  // A hidden operation sits beside a hand-written command in a visible group.
16
- return attachLeaf(root, only.command, only, runtime, {
17
- hidden: only.hidden === true,
18
- groupsHidden: false,
19
- });
16
+ return attachLeaf(root, only.command, only, runtime, only.hidden === true);
20
17
  }
21
18
  return attachForms(root, forms, runtime, reachable);
22
19
  }
23
- /** A single-form leaf: the command as it was before forms, which aliases reuse. */
24
- export function attachLeaf(root, path, operation, runtime, { hidden, groupsHidden = hidden, fixed = {}, formerFlags = {} }) {
25
- const parent = groupFor(root, path.slice(0, -1), { hidden: groupsHidden });
20
+ /** A leaf for an operation with a single form. */
21
+ function attachLeaf(root, path, operation, runtime, hidden) {
22
+ const parent = groupFor(root, path.slice(0, -1));
26
23
  const leaf = parent.command(path[path.length - 1], { hidden });
27
24
  leaf.description(operation.summary);
28
25
  for (const name of operation.pathParams) {
@@ -31,25 +28,13 @@ export function attachLeaf(root, path, operation, runtime, { hidden, groupsHidde
31
28
  const fields = fieldsOf(operation);
32
29
  for (const field of fields)
33
30
  addFieldOptions(leaf, field, field.description ?? '');
34
- for (const [former, current] of Object.entries(formerFlags)) {
35
- const field = fields.find((candidate) => candidate.flag === current);
36
- if (!field) {
37
- throw new Error(`kosuke ${path.join(' ')}: --${former} names --${current}, not a flag.`);
38
- }
39
- const option = new Option(`--${former} <value>`).hideHelp();
40
- // Repeated as it was, `--project-ids a --project-ids b`, or one JSON list.
41
- if (field.repeated)
42
- option.argParser(collect).default(undefined);
43
- leaf.addOption(option);
44
- }
45
31
  addBodyOptions(leaf, operation);
46
32
  leaf.action(async (...args) => {
47
33
  const options = args[args.length - 2];
48
34
  const positionals = args.slice(0, operation.pathParams.length);
49
35
  try {
50
36
  checkFileFlags(options, fields.filter((field) => field.file).map((field) => field.flag));
51
- // `personal` where a workspace id goes, on a command with no personal form. An alias
52
- // leaf runs a personal form by its old path, which takes no workspace id at all.
37
+ // Refuse `personal` where a workspace id goes on a command with no personal form.
53
38
  if (!operation.variant)
54
39
  selectForm([operation], { first: positionals[0], flags: {} });
55
40
  }
@@ -58,19 +43,13 @@ export function attachLeaf(root, path, operation, runtime, { hidden, groupsHidde
58
43
  leaf.error(error.message);
59
44
  throw error;
60
45
  }
61
- const values = Object.fromEntries(fields.map((field) => {
62
- const former = Object.entries(formerFlags).find(([, current]) => current === field.flag);
63
- const formerValue = former
64
- ? formerValueOf(field, options[optionKey(former[0])])
65
- : undefined;
66
- return [
67
- field.name,
68
- options[optionKey(field.flag)] ?? fileValue(field, options) ?? formerValue,
69
- ];
70
- }));
46
+ const values = Object.fromEntries(fields.map((field) => [
47
+ field.name,
48
+ options[optionKey(field.flag)] ?? fileValue(field, options),
49
+ ]));
71
50
  await run(leaf, runtime, operation, {
72
51
  pathParams: Object.fromEntries(operation.pathParams.map((name, i) => [name, positionals[i]])),
73
- fields: { ...values, ...fixed },
52
+ fields: values,
74
53
  wholeBody: readWholeBody({
75
54
  body: options.body,
76
55
  bodyFile: options.bodyFile,
@@ -242,22 +221,6 @@ function parseForForm(field, raw) {
242
221
  return raw === 'true';
243
222
  return field.repeated ? [raw] : raw;
244
223
  }
245
- /** The value of a renamed flag, by the rule its field had: one JSON list, or the values given. */
246
- function formerValueOf(field, raw) {
247
- if (Array.isArray(raw))
248
- return raw.flatMap((value) => formerValueOf(field, value));
249
- if (typeof raw !== 'string')
250
- return raw;
251
- if (!field.repeated)
252
- return field.kind === 'json' ? jsonParser(raw) : raw;
253
- try {
254
- const parsed = JSON.parse(raw);
255
- return Array.isArray(parsed) ? parsed : [raw];
256
- }
257
- catch {
258
- return [raw];
259
- }
260
- }
261
224
  function addFieldOptions(leaf, field, description) {
262
225
  leaf.addOption(optionFor({ ...field, description }));
263
226
  if (field.file) {
@@ -279,13 +242,12 @@ function addBodyOptions(leaf, operation) {
279
242
  leaf.option('--attach <path>', 'Attach a file; repeat for several. Sends the request as multipart.', collect, []);
280
243
  }
281
244
  }
282
- /** A group created here is hidden when asked; one that already exists keeps what it is. */
283
- export function groupFor(root, path, { hidden = false } = {}) {
245
+ /** Find or create the command groups on the way to a leaf. */
246
+ export function groupFor(root, path) {
284
247
  let current = root;
285
248
  for (const segment of path) {
286
249
  const existing = current.commands.find((command) => command.name() === segment);
287
- current =
288
- existing ?? current.command(segment, { hidden }).description(`${humanize(segment)} commands`);
250
+ current = existing ?? current.command(segment).description(`${humanize(segment)} commands`);
289
251
  }
290
252
  return current;
291
253
  }