@super-one/cli 0.50.3-alpha → 0.50.5-alpha

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 (3) hide show
  1. package/MANIFEST.json +2 -2
  2. package/lib/cli.mjs +459 -302
  3. package/package.json +1 -1
package/MANIFEST.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@super-one/cli",
3
- "version": "0.50.3-alpha",
3
+ "version": "0.50.5-alpha",
4
4
  "kind": "npm",
5
5
  "minNodeMajor": 20,
6
- "builtAt": "2026-08-07T01:09:21.908Z"
6
+ "builtAt": "2026-08-07T07:57:09.216Z"
7
7
  }
package/lib/cli.mjs CHANGED
@@ -170,7 +170,7 @@ var init_host_action_superone_descriptors = __esm({
170
170
  HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS = [
171
171
  {
172
172
  "name": "session_collab_list_agents",
173
- "description": "List the built-in agent profiles (harness + config) available for user-approved child sessions. Each profile includes defaultConfig with the model/effort inherited when a request omits them. Call this before session_collab_request. The same profile may be requested more than once.",
173
+ "description": "List the agent profiles available for user-approved child sessions. Inspect each profile's harness and defaultConfig before session_collab_request. You may reuse one agentId for multiple launches.",
174
174
  "inputSchema": {
175
175
  "type": "object",
176
176
  "properties": {},
@@ -179,7 +179,7 @@ var init_host_action_superone_descriptors = __esm({
179
179
  },
180
180
  {
181
181
  "name": "session_collab_request",
182
- "description": 'Request approval for one or more child-agent launches. Repeat an agentId to launch multiple sessions from one profile. Every launch must include name (an agent-chosen human label, not the harness name) and role (for example, Reviewer or Implementer). config is optional; omitted model/effort fields inherit the selected profile defaultConfig, while explicit values override it. Session title becomes "Name - Role". The user reviews and may edit model/effort/AI provider/permission/sandbox (task, name, role, agent profile, cwd, worktree stay as requested). On approval each launch returns a bearer credential. Each credential can create exactly one session and must be kept private.',
182
+ "description": 'Request user approval for one or more child sessions. Call session_collab_list_agents first; repeat an agentId to reuse a profile. Invent a human-friendly name and a task-specific role for every launch. Omitted config fields inherit profile defaults. Before setting config.cwd or config.worktree, call read_manual({ domain: "product", topic: "collaboration" }); same-repo isolation belongs in config.worktree, not a worktree-leaf cwd. The user may edit model, effort, provider, permission, and sandbox settings. Each approved launch returns a private one-shot credential for session_collab_start.',
183
183
  "inputSchema": {
184
184
  "type": "object",
185
185
  "properties": {
@@ -251,10 +251,12 @@ var init_host_action_superone_descriptors = __esm({
251
251
  ]
252
252
  },
253
253
  "cwd": {
254
- "type": "string"
254
+ "type": "string",
255
+ "description": 'Set only to a genuinely different project root. Omit for the current project. Never pass ~/.worktrees/... or another same-repo worktree leaf; use config.worktree for same-repo isolation. See read_manual({ domain: "product", topic: "collaboration" }).'
255
256
  },
256
257
  "worktree": {
257
258
  "type": "object",
259
+ "description": 'Request a host-managed worktree for same-repo isolation while cwd stays omitted or at the project root. Set enabled, baseBranch, and mode; use a unique branchName with branch. See read_manual({ domain: "product", topic: "collaboration" }) for implementer and reviewer recipes.',
258
260
  "properties": {
259
261
  "enabled": {
260
262
  "type": "boolean"
@@ -272,7 +274,7 @@ var init_host_action_superone_descriptors = __esm({
272
274
  },
273
275
  "branchName": {
274
276
  "type": "string",
275
- "description": "Branch to create for this worktree. Must be unique across launches \u2014 git cannot check out one branch in two worktrees."
277
+ "description": 'With mode "branch", create this unique branch. Git cannot check out one branch in two worktrees.'
276
278
  },
277
279
  "carryLocalChanges": {
278
280
  "type": "boolean"
@@ -310,7 +312,7 @@ var init_host_action_superone_descriptors = __esm({
310
312
  },
311
313
  {
312
314
  "name": "session_collab_start",
313
- "description": "Create the real, user-visible collaboration child session authorized by one credential and deliver the approved launch task. Returns as soon as the child agent begins replying (does not wait for the full first turn). A credential creates at most one session; repeated calls are idempotent and return the same session id. The child then works asynchronously \u2014 start every child you need back to back, and never block on one before starting the next.",
315
+ "description": "Start the approved child session for one credential and deliver its task. The call returns when the child begins replying, not when its first turn finishes. A credential starts at most one session; retries return the same session id. Start all approved children back-to-back, then continue other work while they run asynchronously.",
314
316
  "inputSchema": {
315
317
  "type": "object",
316
318
  "properties": {
@@ -326,7 +328,7 @@ var init_host_action_superone_descriptors = __esm({
326
328
  },
327
329
  {
328
330
  "name": "session_collab_send",
329
- "description": "Send a persistent mailbox message between the parent and child sessions authorized by a credential. Direction is derived from the calling session. Write content as Markdown (headings, lists, code fences, emphasis, tables when useful) so peer agents and the SuperOne UI can render a structured handoff. Use clientMessageId for retry-safe idempotency. Delivery is push-based both ways: the peer is woken by a task notification (even mid-turn), and when it replies the host wakes you the same way \u2014 a fresh turn starts, telling you to call session_collab_retrieve. So after sending, move on to other work or end your turn; ending the turn IS how you wait here, and no reply is missed. Never sleep, re-send, or poll session_collab_retrieve while waiting.",
331
+ "description": "Send a persistent Markdown message through one parent-child mailbox. Use clientMessageId for retry-safe delivery. The host wakes the peer and later wakes you when it replies. After sending, continue other work or end your turn. Never sleep, resend, or poll session_collab_retrieve while waiting.",
330
332
  "inputSchema": {
331
333
  "type": "object",
332
334
  "properties": {
@@ -351,7 +353,7 @@ var init_host_action_superone_descriptors = __esm({
351
353
  },
352
354
  {
353
355
  "name": "session_collab_retrieve",
354
- "description": 'Retrieve persistent mailbox messages addressed to this session. Non-blocking single read: returns the messages already waiting (status "messages") or nothing (status "empty"). Each message content is Markdown written by the peer \u2014 parse structure (headings, lists, code) rather than treating it as plain text. Pass multiple credentials to drain several parent/child mailboxes in one call. Returned messages advance only this agent endpoint cursor. Call it when a collaboration wake notification arrives, or once to drain the inbox before you act on peer input. Status "empty" means no peer has replied yet \u2014 it is NOT a retry signal: do not call again, do not sleep, do not spin. End your turn and the wake notification will start a new one the moment a message actually arrives.',
356
+ "description": 'Retrieve queued Markdown messages for this session from one or more parent-child mailboxes. Call after a collaboration wake, or once before acting on peer input. This is a non-blocking read: status "empty" is not a retry signal. Do not sleep or poll; end your turn and wait for the next wake.',
355
357
  "inputSchema": {
356
358
  "type": "object",
357
359
  "properties": {
@@ -3268,7 +3270,13 @@ var init_auth = __esm({
3268
3270
  /** WebSocket ticket: 30 seconds, single /ws upgrade. */
3269
3271
  wsTicketMs: 30 * 1e3,
3270
3272
  /** Refresh family expires after 90 days of inactivity. */
3271
- refreshInactivityMs: 90 * 24 * 60 * 60 * 1e3
3273
+ refreshInactivityMs: 90 * 24 * 60 * 60 * 1e3,
3274
+ /**
3275
+ * Immediately-previous refresh token remains redeemable this long after
3276
+ * rotation. Mitigates lost-response / concurrent-refresh races without
3277
+ * disabling reuse detection for older generations (RFC 6819 §5.2.2.3).
3278
+ */
3279
+ refreshReuseGraceMs: 60 * 1e3
3272
3280
  };
3273
3281
  OPERATION_SCOPES = {
3274
3282
  readEnvironment: ["environment:read"],
@@ -40133,6 +40141,265 @@ var init_slash_filter = __esm({
40133
40141
  }
40134
40142
  });
40135
40143
 
40144
+ // ../../packages/shared/src/tool-ui.ts
40145
+ function normalizeToolIdKey(id) {
40146
+ return id.trim().toLowerCase().replace(/[\s-]+/g, "_");
40147
+ }
40148
+ function uiToolNameFromId(id) {
40149
+ if (!id || typeof id !== "string") return null;
40150
+ if (/[\s`/:]/.test(id) && !TOOL_ID_TO_UI_NAME[normalizeToolIdKey(id)]) return null;
40151
+ const key = normalizeToolIdKey(id);
40152
+ return TOOL_ID_TO_UI_NAME[key] ?? null;
40153
+ }
40154
+ function bytesOrStringToText(value) {
40155
+ if (typeof value === "string") return value;
40156
+ if (Array.isArray(value) && value.length > 0 && value.every((n) => typeof n === "number")) {
40157
+ try {
40158
+ return new TextDecoder("utf-8", { fatal: false }).decode(Uint8Array.from(value));
40159
+ } catch {
40160
+ return "";
40161
+ }
40162
+ }
40163
+ return "";
40164
+ }
40165
+ function formatSearchToolPayload(obj) {
40166
+ let data = obj;
40167
+ if (typeof obj.content === "string" && obj.content.trim()) {
40168
+ try {
40169
+ data = JSON.parse(obj.content);
40170
+ } catch {
40171
+ if (!obj.results) return obj.content;
40172
+ }
40173
+ }
40174
+ if (!data || typeof data !== "object") return null;
40175
+ const root = data;
40176
+ const results = root.results;
40177
+ if (!Array.isArray(results)) {
40178
+ if (typeof root.content === "string") return root.content;
40179
+ return null;
40180
+ }
40181
+ const lines = [];
40182
+ const count = typeof obj.result_count === "number" ? obj.result_count : results.length;
40183
+ lines.push(`Found ${count} tool${count === 1 ? "" : "s"}`);
40184
+ for (const entry of results) {
40185
+ if (!entry || typeof entry !== "object") continue;
40186
+ const group = entry;
40187
+ const server = typeof group.server === "string" ? group.server : "MCP";
40188
+ lines.push("");
40189
+ lines.push(`[${server}]`);
40190
+ const tools = group.tools;
40191
+ if (!Array.isArray(tools)) continue;
40192
+ for (const tool of tools) {
40193
+ if (!tool || typeof tool !== "object") continue;
40194
+ const t = tool;
40195
+ const name = typeof t.tool_name === "string" ? t.tool_name : typeof t.name === "string" ? t.name : "tool";
40196
+ const desc = typeof t.description === "string" ? t.description : "";
40197
+ const score = typeof t.score === "number" ? ` \xB7 ${t.score.toFixed(1)}` : "";
40198
+ lines.push(desc ? ` ${name}${score} \u2014 ${desc}` : ` ${name}${score}`);
40199
+ }
40200
+ }
40201
+ if (typeof root.note === "string" && root.note.trim()) {
40202
+ lines.push("");
40203
+ lines.push(root.note);
40204
+ }
40205
+ return lines.join("\n").trim() || null;
40206
+ }
40207
+ function isAgentOutputEnvelope(obj) {
40208
+ const t = obj.type;
40209
+ return t === "MCP" || t === "ListDir" || t === "list_dir" || t === "LS" || t === "Todo" || t === "SearchTool" || t === "GrepSearch" || t === "grep" || obj.TodosUpdated != null || obj.Content != null && typeof obj.Content === "object" || Array.isArray(obj.results) || obj.action != null && typeof obj.action === "object";
40210
+ }
40211
+ function formatAgentToolOutput(raw) {
40212
+ if (raw == null) return "";
40213
+ if (typeof raw === "string") {
40214
+ const trimmed = raw.trim();
40215
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
40216
+ try {
40217
+ const parsed = JSON.parse(trimmed);
40218
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && isAgentOutputEnvelope(parsed)) {
40219
+ return formatAgentToolOutput(parsed);
40220
+ }
40221
+ return raw;
40222
+ } catch {
40223
+ return raw;
40224
+ }
40225
+ }
40226
+ return raw;
40227
+ }
40228
+ if (typeof raw !== "object") return String(raw);
40229
+ const obj = raw;
40230
+ if (obj.type === "MCP" && obj.output != null) {
40231
+ if (typeof obj.output === "string") return obj.output;
40232
+ if (typeof obj.output === "object") {
40233
+ const values = Object.values(obj.output);
40234
+ if (values.length === 1 && typeof values[0] === "string") return values[0];
40235
+ }
40236
+ }
40237
+ const listContent = obj.Content ?? obj.content;
40238
+ if ((obj.type === "ListDir" || obj.type === "list_dir" || obj.type === "LS") && listContent && typeof listContent === "object") {
40239
+ const body = listContent;
40240
+ if (typeof body.content === "string" && body.content.trim()) return body.content;
40241
+ if (typeof body.text === "string" && body.text.trim()) return body.text;
40242
+ }
40243
+ if ((obj.type === "ListDir" || obj.type === "list_dir") && typeof obj.Content === "string") {
40244
+ return obj.Content;
40245
+ }
40246
+ if (typeof obj.content === "string" && obj.content.includes("\n") && (obj.type === "ListDir" || obj.absolute_root_path != null)) {
40247
+ return obj.content;
40248
+ }
40249
+ if (obj.type === "Todo" || obj.TodosUpdated != null) {
40250
+ const todos = obj.TodosUpdated;
40251
+ if (todos && typeof todos === "object") {
40252
+ const t = todos;
40253
+ if (typeof t.summary_for_prompt === "string" && t.summary_for_prompt.trim()) return t.summary_for_prompt;
40254
+ if (typeof t.summary === "string" && t.summary.trim()) return t.summary;
40255
+ }
40256
+ }
40257
+ if (obj.type === "SearchTool" || Array.isArray(obj.results) || obj.result_count != null && (obj.content != null || obj.results != null)) {
40258
+ const formatted = formatSearchToolPayload(obj);
40259
+ if (formatted) return formatted;
40260
+ }
40261
+ if (obj.type === "GrepSearch" || obj.type === "grep" || Array.isArray(obj.stdout)) {
40262
+ const text = bytesOrStringToText(obj.stdout ?? obj.content ?? obj.output);
40263
+ if (text) return text;
40264
+ }
40265
+ const action = obj.action;
40266
+ if (action && typeof action === "object") {
40267
+ const a = action;
40268
+ if (a.type === "search") {
40269
+ const lines = [];
40270
+ if (typeof a.query === "string") lines.push(`Query: ${a.query}`);
40271
+ const sources = a.sources;
40272
+ if (Array.isArray(sources)) {
40273
+ for (const s2 of sources) {
40274
+ if (s2 && typeof s2 === "object") {
40275
+ const src = s2;
40276
+ if (typeof src.url === "string") lines.push(src.url);
40277
+ else if (typeof src.title === "string") lines.push(src.title);
40278
+ }
40279
+ }
40280
+ }
40281
+ if (typeof a.result === "string") lines.push(a.result);
40282
+ if (typeof a.snippet === "string") lines.push(a.snippet);
40283
+ if (lines.length > 0) return lines.join("\n");
40284
+ }
40285
+ }
40286
+ if (listContent && typeof listContent === "object") {
40287
+ const body = listContent;
40288
+ for (const key of ["content", "text", "output", "result"]) {
40289
+ if (typeof body[key] === "string" && body[key].trim()) {
40290
+ if (obj.type === "ListDir" || obj.type === "list_dir" || obj.type === "LS" || body.absolute_root_path != null || /^[\s-]*\//.test(body[key])) {
40291
+ return body[key];
40292
+ }
40293
+ }
40294
+ }
40295
+ }
40296
+ if (typeof obj.run_id === "string" || typeof obj.runId === "string") {
40297
+ try {
40298
+ return JSON.stringify(raw);
40299
+ } catch {
40300
+ return String(raw);
40301
+ }
40302
+ }
40303
+ for (const key of ["result", "output", "text", "stdout", "message", "summary"]) {
40304
+ const v2 = obj[key];
40305
+ if (typeof v2 === "string" && v2.trim()) return v2;
40306
+ }
40307
+ if (listContent && typeof listContent === "object") {
40308
+ const body = listContent;
40309
+ for (const key of ["content", "text", "output", "result"]) {
40310
+ if (typeof body[key] === "string" && body[key].trim()) return body[key];
40311
+ }
40312
+ }
40313
+ try {
40314
+ return JSON.stringify(raw, null, 2);
40315
+ } catch {
40316
+ return String(raw);
40317
+ }
40318
+ }
40319
+ var TOOL_ID_TO_UI_NAME;
40320
+ var init_tool_ui = __esm({
40321
+ "../../packages/shared/src/tool-ui.ts"() {
40322
+ "use strict";
40323
+ TOOL_ID_TO_UI_NAME = {
40324
+ read: "Read",
40325
+ read_file: "Read",
40326
+ readfile: "Read",
40327
+ edit: "Edit",
40328
+ search_replace: "Edit",
40329
+ str_replace: "Edit",
40330
+ apply_patch: "Edit",
40331
+ write: "Write",
40332
+ write_file: "Write",
40333
+ writefile: "Write",
40334
+ create_file: "Write",
40335
+ bash: "Bash",
40336
+ shell: "Bash",
40337
+ run_terminal_command: "Bash",
40338
+ run_terminal_cmd: "Bash",
40339
+ run_command: "Bash",
40340
+ execute: "Bash",
40341
+ command: "Bash",
40342
+ grep: "Grep",
40343
+ search: "Grep",
40344
+ ripgrep: "Grep",
40345
+ glob: "Glob",
40346
+ find_files: "Glob",
40347
+ list_dir: "LS",
40348
+ listdir: "LS",
40349
+ ls: "LS",
40350
+ web_fetch: "WebFetch",
40351
+ webfetch: "WebFetch",
40352
+ fetch: "WebFetch",
40353
+ open_page: "WebFetch",
40354
+ open_page_with_find: "WebFetch",
40355
+ web_search: "WebSearch",
40356
+ websearch: "WebSearch",
40357
+ todo_write: "TodoWrite",
40358
+ todowrite: "TodoWrite",
40359
+ todo: "TodoWrite",
40360
+ search_tool: "SearchTools",
40361
+ searchtool: "SearchTools",
40362
+ tool_search: "SearchTools",
40363
+ toolsearch: "SearchTools",
40364
+ use_tool: "UseTool",
40365
+ usetool: "UseTool",
40366
+ call_tool: "UseTool",
40367
+ spawn_subagent: "Agent",
40368
+ spawn_agent: "Agent",
40369
+ agent: "Agent",
40370
+ task: "Task",
40371
+ workflow: "Workflow",
40372
+ run_workflow: "Workflow",
40373
+ memory_search: "MemorySearch",
40374
+ memorysearch: "MemorySearch",
40375
+ search_memory: "MemorySearch",
40376
+ ask_user_question: "AskUserQuestion",
40377
+ askuserquestion: "AskUserQuestion",
40378
+ get_task_output: "TaskOutput",
40379
+ get_command_or_subagent_output: "TaskOutput",
40380
+ get_terminal_command_output: "TaskOutput",
40381
+ wait_tasks: "TaskOutput",
40382
+ wait_commands_or_subagents: "TaskOutput",
40383
+ kill_task: "KillTask",
40384
+ kill_command_or_subagent: "KillTask",
40385
+ kill_terminal_command: "KillTask",
40386
+ enter_plan_mode: "EnterPlanMode",
40387
+ exit_plan_mode: "ExitPlanMode",
40388
+ skill: "Skill",
40389
+ image_gen: "ImageGen",
40390
+ image_edit: "ImageEdit",
40391
+ image_to_video: "ImageToVideo",
40392
+ reference_to_video: "ReferenceToVideo",
40393
+ video_gen: "VideoGen",
40394
+ monitor: "Monitor",
40395
+ update_goal: "UpdateGoal",
40396
+ scheduler_create: "SchedulerCreate",
40397
+ scheduler_delete: "SchedulerDelete",
40398
+ scheduler_list: "SchedulerList"
40399
+ };
40400
+ }
40401
+ });
40402
+
40136
40403
  // ../../packages/acp/src/tool-normalization.ts
40137
40404
  function textFromContent(content) {
40138
40405
  if (!content) return "";
@@ -40201,14 +40468,8 @@ function extractFilePath(tool, raw, diffs) {
40201
40468
  "to"
40202
40469
  ]);
40203
40470
  }
40204
- function normalizeToolId(id) {
40205
- return id.trim().toLowerCase().replace(/[\s-]+/g, "_");
40206
- }
40207
40471
  function nameFromToolId(id) {
40208
- if (!id || typeof id !== "string") return null;
40209
- if (/[\s`/:]/.test(id) && !TOOL_ID_TO_NAME[normalizeToolId(id)]) return null;
40210
- const key = normalizeToolId(id);
40211
- return TOOL_ID_TO_NAME[key] ?? null;
40472
+ return uiToolNameFromId(id);
40212
40473
  }
40213
40474
  function nameFromVariant(raw) {
40214
40475
  const variant = pickString(raw, ["variant", "tool", "name", "toolName", "tool_name"]);
@@ -40484,12 +40745,17 @@ function normalizeInput(toolName, kind, raw, filePath, diffs, terminalCommand) {
40484
40745
  if (raw.limit != null) out.limit = raw.limit;
40485
40746
  return Object.keys(out).length > 0 ? out : { ...raw };
40486
40747
  }
40748
+ case "Agent":
40487
40749
  case "Task": {
40488
40750
  const out = {};
40489
40751
  const desc = pickString(raw, ["description", "prompt", "name", "task", "objective"]);
40490
40752
  if (desc) out.description = desc;
40491
40753
  const sub = pickString(raw, ["subagent_type", "agent_type", "agent", "type"]);
40492
40754
  if (sub) out.subagent_type = sub;
40755
+ const prompt = pickString(raw, ["prompt"]);
40756
+ if (prompt) out.prompt = prompt;
40757
+ const model = pickString(raw, ["model"]);
40758
+ if (model) out.model = model;
40493
40759
  if (raw.run_in_background === true || raw.background === true) out.run_in_background = true;
40494
40760
  return Object.keys(out).length > 0 ? out : { ...raw };
40495
40761
  }
@@ -40585,87 +40851,11 @@ function toolUseBlock(tool, opts) {
40585
40851
  toolFilePath: normalized.toolFilePath
40586
40852
  };
40587
40853
  }
40588
- var TOOL_ID_TO_NAME, GREP_NON_PATTERN_TITLES;
40854
+ var GREP_NON_PATTERN_TITLES;
40589
40855
  var init_tool_normalization = __esm({
40590
40856
  "../../packages/acp/src/tool-normalization.ts"() {
40591
40857
  "use strict";
40592
- TOOL_ID_TO_NAME = {
40593
- read: "Read",
40594
- read_file: "Read",
40595
- readfile: "Read",
40596
- edit: "Edit",
40597
- search_replace: "Edit",
40598
- str_replace: "Edit",
40599
- apply_patch: "Edit",
40600
- write: "Write",
40601
- write_file: "Write",
40602
- writefile: "Write",
40603
- create_file: "Write",
40604
- bash: "Bash",
40605
- shell: "Bash",
40606
- run_terminal_command: "Bash",
40607
- run_terminal_cmd: "Bash",
40608
- run_command: "Bash",
40609
- execute: "Bash",
40610
- command: "Bash",
40611
- grep: "Grep",
40612
- search: "Grep",
40613
- ripgrep: "Grep",
40614
- glob: "Glob",
40615
- find_files: "Glob",
40616
- list_dir: "LS",
40617
- listdir: "LS",
40618
- ls: "LS",
40619
- web_fetch: "WebFetch",
40620
- webfetch: "WebFetch",
40621
- fetch: "WebFetch",
40622
- open_page: "WebFetch",
40623
- open_page_with_find: "WebFetch",
40624
- web_search: "WebSearch",
40625
- websearch: "WebSearch",
40626
- todo_write: "TodoWrite",
40627
- todowrite: "TodoWrite",
40628
- todo: "TodoWrite",
40629
- search_tool: "SearchTools",
40630
- searchtool: "SearchTools",
40631
- tool_search: "SearchTools",
40632
- toolsearch: "SearchTools",
40633
- use_tool: "UseTool",
40634
- usetool: "UseTool",
40635
- call_tool: "UseTool",
40636
- spawn_subagent: "Task",
40637
- spawn_agent: "Task",
40638
- task: "Task",
40639
- agent: "Task",
40640
- workflow: "Workflow",
40641
- run_workflow: "Workflow",
40642
- memory_search: "MemorySearch",
40643
- memorysearch: "MemorySearch",
40644
- search_memory: "MemorySearch",
40645
- ask_user_question: "AskUserQuestion",
40646
- askuserquestion: "AskUserQuestion",
40647
- get_task_output: "TaskOutput",
40648
- get_command_or_subagent_output: "TaskOutput",
40649
- get_terminal_command_output: "TaskOutput",
40650
- wait_tasks: "TaskOutput",
40651
- wait_commands_or_subagents: "TaskOutput",
40652
- kill_task: "KillTask",
40653
- kill_command_or_subagent: "KillTask",
40654
- kill_terminal_command: "KillTask",
40655
- enter_plan_mode: "EnterPlanMode",
40656
- exit_plan_mode: "ExitPlanMode",
40657
- skill: "Skill",
40658
- image_gen: "ImageGen",
40659
- image_edit: "ImageEdit",
40660
- image_to_video: "ImageToVideo",
40661
- reference_to_video: "ReferenceToVideo",
40662
- video_gen: "VideoGen",
40663
- monitor: "Monitor",
40664
- update_goal: "UpdateGoal",
40665
- scheduler_create: "SchedulerCreate",
40666
- scheduler_delete: "SchedulerDelete",
40667
- scheduler_list: "SchedulerList"
40668
- };
40858
+ init_tool_ui();
40669
40859
  GREP_NON_PATTERN_TITLES = /* @__PURE__ */ new Set([
40670
40860
  "grep",
40671
40861
  "Grep",
@@ -40679,170 +40869,8 @@ var init_tool_normalization = __esm({
40679
40869
  });
40680
40870
 
40681
40871
  // ../../packages/acp/src/tool-result-map.ts
40682
- function bytesOrStringToText(value) {
40683
- if (typeof value === "string") return value;
40684
- if (Array.isArray(value) && value.every((n) => typeof n === "number")) {
40685
- try {
40686
- return Buffer.from(value).toString("utf8");
40687
- } catch {
40688
- return "";
40689
- }
40690
- }
40691
- return "";
40692
- }
40693
- function formatSearchToolPayload(obj) {
40694
- let data = obj;
40695
- if (typeof obj.content === "string" && obj.content.trim()) {
40696
- try {
40697
- data = JSON.parse(obj.content);
40698
- } catch {
40699
- if (!obj.results) return obj.content;
40700
- }
40701
- }
40702
- if (!data || typeof data !== "object") return null;
40703
- const root = data;
40704
- const results = root.results;
40705
- if (!Array.isArray(results)) {
40706
- if (typeof root.content === "string") return root.content;
40707
- return null;
40708
- }
40709
- const lines = [];
40710
- const count = typeof obj.result_count === "number" ? obj.result_count : results.length;
40711
- lines.push(`Found ${count} tool${count === 1 ? "" : "s"}`);
40712
- for (const entry of results) {
40713
- if (!entry || typeof entry !== "object") continue;
40714
- const group = entry;
40715
- const server = typeof group.server === "string" ? group.server : "MCP";
40716
- lines.push("");
40717
- lines.push(`[${server}]`);
40718
- const tools = group.tools;
40719
- if (!Array.isArray(tools)) continue;
40720
- for (const tool of tools) {
40721
- if (!tool || typeof tool !== "object") continue;
40722
- const t = tool;
40723
- const name = typeof t.tool_name === "string" ? t.tool_name : typeof t.name === "string" ? t.name : "tool";
40724
- const desc = typeof t.description === "string" ? t.description : "";
40725
- const score = typeof t.score === "number" ? ` \xB7 ${t.score.toFixed(1)}` : "";
40726
- lines.push(desc ? ` ${name}${score} \u2014 ${desc}` : ` ${name}${score}`);
40727
- }
40728
- }
40729
- if (typeof root.note === "string" && root.note.trim()) {
40730
- lines.push("");
40731
- lines.push(root.note);
40732
- }
40733
- return lines.join("\n").trim() || null;
40734
- }
40735
- function isAgentOutputEnvelope(obj) {
40736
- const t = obj.type;
40737
- return t === "MCP" || t === "ListDir" || t === "list_dir" || t === "LS" || t === "Todo" || t === "SearchTool" || t === "GrepSearch" || t === "grep" || obj.TodosUpdated != null || obj.Content != null && typeof obj.Content === "object" || Array.isArray(obj.results) || obj.action != null && typeof obj.action === "object";
40738
- }
40739
40872
  function formatAcpRawOutput(raw) {
40740
- if (raw == null) return "";
40741
- if (typeof raw === "string") {
40742
- const trimmed = raw.trim();
40743
- if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
40744
- try {
40745
- const parsed = JSON.parse(trimmed);
40746
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && isAgentOutputEnvelope(parsed)) {
40747
- return formatAcpRawOutput(parsed);
40748
- }
40749
- return raw;
40750
- } catch {
40751
- return raw;
40752
- }
40753
- }
40754
- return raw;
40755
- }
40756
- if (typeof raw !== "object") return String(raw);
40757
- const obj = raw;
40758
- if (obj.type === "MCP" && obj.output != null) {
40759
- if (typeof obj.output === "string") return obj.output;
40760
- if (typeof obj.output === "object") {
40761
- const values = Object.values(obj.output);
40762
- if (values.length === 1 && typeof values[0] === "string") return values[0];
40763
- }
40764
- }
40765
- const listContent = obj.Content ?? obj.content;
40766
- if ((obj.type === "ListDir" || obj.type === "list_dir" || obj.type === "LS") && listContent && typeof listContent === "object") {
40767
- const body = listContent;
40768
- if (typeof body.content === "string" && body.content.trim()) return body.content;
40769
- if (typeof body.text === "string" && body.text.trim()) return body.text;
40770
- }
40771
- if ((obj.type === "ListDir" || obj.type === "list_dir") && typeof obj.Content === "string") {
40772
- return obj.Content;
40773
- }
40774
- if (typeof obj.content === "string" && obj.content.includes("\n") && (obj.type === "ListDir" || obj.absolute_root_path != null)) {
40775
- return obj.content;
40776
- }
40777
- if (obj.type === "Todo" || obj.TodosUpdated != null) {
40778
- const todos = obj.TodosUpdated;
40779
- if (todos && typeof todos === "object") {
40780
- const t = todos;
40781
- if (typeof t.summary_for_prompt === "string" && t.summary_for_prompt.trim()) return t.summary_for_prompt;
40782
- if (typeof t.summary === "string" && t.summary.trim()) return t.summary;
40783
- }
40784
- }
40785
- if (obj.type === "SearchTool" || Array.isArray(obj.results) || obj.result_count != null && (obj.content != null || obj.results != null)) {
40786
- const formatted = formatSearchToolPayload(obj);
40787
- if (formatted) return formatted;
40788
- }
40789
- if (obj.type === "GrepSearch" || obj.type === "grep" || Array.isArray(obj.stdout)) {
40790
- const text = bytesOrStringToText(obj.stdout ?? obj.content ?? obj.output);
40791
- if (text) return text;
40792
- }
40793
- const action = obj.action;
40794
- if (action && typeof action === "object") {
40795
- const a = action;
40796
- if (a.type === "search") {
40797
- const lines = [];
40798
- if (typeof a.query === "string") lines.push(`Query: ${a.query}`);
40799
- const sources = a.sources;
40800
- if (Array.isArray(sources)) {
40801
- for (const s2 of sources) {
40802
- if (s2 && typeof s2 === "object") {
40803
- const src = s2;
40804
- if (typeof src.url === "string") lines.push(src.url);
40805
- else if (typeof src.title === "string") lines.push(src.title);
40806
- }
40807
- }
40808
- }
40809
- if (typeof a.result === "string") lines.push(a.result);
40810
- if (typeof a.snippet === "string") lines.push(a.snippet);
40811
- if (lines.length > 0) return lines.join("\n");
40812
- }
40813
- }
40814
- if (listContent && typeof listContent === "object") {
40815
- const body = listContent;
40816
- for (const key of ["content", "text", "output", "result"]) {
40817
- if (typeof body[key] === "string" && body[key].trim()) {
40818
- if (obj.type === "ListDir" || obj.type === "list_dir" || obj.type === "LS" || body.absolute_root_path != null || /^[\s-]*\//.test(body[key])) {
40819
- return body[key];
40820
- }
40821
- }
40822
- }
40823
- }
40824
- if (typeof obj.run_id === "string" || typeof obj.runId === "string") {
40825
- try {
40826
- return JSON.stringify(raw);
40827
- } catch {
40828
- return String(raw);
40829
- }
40830
- }
40831
- for (const key of ["result", "output", "text", "stdout", "message", "summary"]) {
40832
- const v2 = obj[key];
40833
- if (typeof v2 === "string" && v2.trim()) return v2;
40834
- }
40835
- if (listContent && typeof listContent === "object") {
40836
- const body = listContent;
40837
- for (const key of ["content", "text", "output", "result"]) {
40838
- if (typeof body[key] === "string" && body[key].trim()) return body[key];
40839
- }
40840
- }
40841
- try {
40842
- return JSON.stringify(raw, null, 2);
40843
- } catch {
40844
- return String(raw);
40845
- }
40873
+ return formatAgentToolOutput(raw);
40846
40874
  }
40847
40875
  function mediaGenGallerySummary(raw) {
40848
40876
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
@@ -40957,6 +40985,7 @@ var init_tool_result_map = __esm({
40957
40985
  "../../packages/acp/src/tool-result-map.ts"() {
40958
40986
  "use strict";
40959
40987
  init_capability_prompt_tags();
40988
+ init_tool_ui();
40960
40989
  init_tool_normalization();
40961
40990
  }
40962
40991
  });
@@ -40968,6 +40997,8 @@ function createXaiCorrelationState() {
40968
40997
  workflowRevision: /* @__PURE__ */ new Map(),
40969
40998
  workflowStarted: /* @__PURE__ */ new Set(),
40970
40999
  workflowOwnedSubagents: /* @__PURE__ */ new Set(),
41000
+ smokeWorkflowToolIds: /* @__PURE__ */ new Set(),
41001
+ pendingToolNamesById: /* @__PURE__ */ new Map(),
40971
41002
  subagentToolById: /* @__PURE__ */ new Map(),
40972
41003
  subagentStarted: /* @__PURE__ */ new Set(),
40973
41004
  bgTaskById: /* @__PURE__ */ new Map(),
@@ -40977,6 +41008,27 @@ function createXaiCorrelationState() {
40977
41008
  lastMessageId: null
40978
41009
  };
40979
41010
  }
41011
+ function isSubagentLaunchToolName(name) {
41012
+ if (!name) return false;
41013
+ const n = name.toLowerCase();
41014
+ return n === "agent" || n === "task" || n === "spawn_subagent" || n === "spawn_agent";
41015
+ }
41016
+ function bindSubagentToolId(state, subagentId, toolUseId, description, migrateOut) {
41017
+ if (state.workflowOwnedSubagents.has(subagentId)) return;
41018
+ const existing = state.subagentToolById.get(subagentId);
41019
+ if (existing && existing !== toolUseId) return;
41020
+ const isNew = !existing;
41021
+ if (isNew) state.subagentToolById.set(subagentId, toolUseId);
41022
+ if (isNew && state.subagentStarted.has(subagentId)) {
41023
+ migrateOut.push({
41024
+ type: "task_progress",
41025
+ taskId: subagentId,
41026
+ toolUseId,
41027
+ description: description ?? subagentId,
41028
+ usage: { totalTokens: 0, toolUses: 0, durationMs: 0 }
41029
+ });
41030
+ }
41031
+ }
40980
41032
  function asRecord7(v2) {
40981
41033
  if (!v2 || typeof v2 !== "object" || Array.isArray(v2)) return null;
40982
41034
  return v2;
@@ -41023,7 +41075,22 @@ function parseXaiSessionNotificationEnvelope(raw) {
41023
41075
  function parseXaiExtParams(raw) {
41024
41076
  return asRecord7(raw) ?? {};
41025
41077
  }
41078
+ function parsePlainTextTaskAck(text) {
41079
+ const subagentId = text.match(/subagent_id:\s*(\S+)/i)?.[1] ?? text.match(/task_ids?\s*=\s*\[\s*"([^"]+)"/i)?.[1];
41080
+ const taskId = text.match(/(?:^|\n)\s*task_id:\s*(\S+)/i)?.[1] ?? subagentId;
41081
+ const outputFile = text.match(/output_file:\s*(\S+)/i)?.[1];
41082
+ const description = text.match(/(?:^|\n)\s*description:\s*(.+)$/im)?.[1]?.trim();
41083
+ const subagentType = text.match(/(?:^|\n)\s*(?:type|subagent_type):\s*(\S+)/i)?.[1];
41084
+ return {
41085
+ ...subagentId ? { subagentId } : {},
41086
+ ...taskId ? { taskId } : {},
41087
+ ...outputFile ? { outputFile } : {},
41088
+ ...description ? { description } : {},
41089
+ ...subagentType ? { subagentType } : {}
41090
+ };
41091
+ }
41026
41092
  function noteToolCorrelationFromAgentEvents(events, state) {
41093
+ const migrate = [];
41027
41094
  for (const event of events) {
41028
41095
  if (event.type === "message_usage") {
41029
41096
  state.lastMessageId = event.messageId;
@@ -41032,32 +41099,79 @@ function noteToolCorrelationFromAgentEvents(events, state) {
41032
41099
  if (event.type !== "content_delta") continue;
41033
41100
  const d = event.delta;
41034
41101
  if (d.type === "tool_use") {
41102
+ if (d.toolUseId && d.toolName) {
41103
+ state.pendingToolNamesById.set(d.toolUseId, d.toolName);
41104
+ }
41105
+ const toolName = (d.toolName ?? "").toLowerCase();
41106
+ if ((toolName === "workflow" || toolName === "run_workflow") && d.toolUseId && isValidateOnlyToolInput(d.input)) {
41107
+ state.smokeWorkflowToolIds.add(d.toolUseId);
41108
+ }
41035
41109
  continue;
41036
41110
  }
41037
41111
  if (d.type !== "tool_result" || !d.summary) continue;
41038
41112
  const toolUseId = d.toolUseId;
41113
+ const launchName = state.pendingToolNamesById.get(toolUseId);
41114
+ const isSpawnLaunch = isSubagentLaunchToolName(launchName);
41039
41115
  const parsed = tryParseJsonObject(d.summary);
41040
- if (!parsed) continue;
41041
- const runId = strField(parsed, "run_id", "runId");
41042
- if (runId) {
41043
- state.workflowToolByRunId.set(runId, toolUseId);
41044
- }
41045
- const subagentId = strField(parsed, "subagent_id", "subagentId") ?? strField(parsed, "agent_id", "agentId") ?? strField(parsed, "task_id", "taskId");
41046
- if (subagentId && (strField(parsed, "subagent_id", "subagentId") || strField(parsed, "subagent_type", "subagentType"))) {
41047
- state.subagentToolById.set(subagentId, toolUseId);
41048
- } else if (subagentId && strField(parsed, "agent_id", "agentId") && !runId) {
41049
- state.subagentToolById.set(subagentId, toolUseId);
41050
- }
41051
- const taskId = strField(parsed, "task_id", "taskId");
41052
- if (taskId && !runId) {
41053
- const existing = state.bgTaskById.get(taskId);
41054
- state.bgTaskById.set(taskId, {
41055
- toolUseId: toolUseId ?? existing?.toolUseId,
41056
- description: existing?.description ?? strField(parsed, "description", "name") ?? taskId,
41057
- outputFile: strField(parsed, "output_file", "outputFile") ?? existing?.outputFile
41058
- });
41116
+ if (parsed) {
41117
+ const runId = strField(parsed, "run_id", "runId");
41118
+ if (runId && toolUseId && !state.smokeWorkflowToolIds.has(toolUseId)) {
41119
+ state.workflowToolByRunId.set(runId, toolUseId);
41120
+ }
41121
+ const explicitSubagentId = strField(parsed, "subagent_id", "subagentId");
41122
+ const agentId = strField(parsed, "agent_id", "agentId");
41123
+ const hasSubagentShape = !!(explicitSubagentId || strField(parsed, "subagent_type", "subagentType") || agentId && !runId);
41124
+ const subagentId = explicitSubagentId ?? agentId ?? strField(parsed, "task_id", "taskId");
41125
+ if (subagentId && (explicitSubagentId || strField(parsed, "subagent_type", "subagentType"))) {
41126
+ if (isSpawnLaunch || !launchName) {
41127
+ bindSubagentToolId(state, subagentId, toolUseId, strField(parsed, "description", "name"), migrate);
41128
+ }
41129
+ } else if (subagentId && agentId && !runId) {
41130
+ if (isSpawnLaunch || !launchName) {
41131
+ bindSubagentToolId(state, subagentId, toolUseId, strField(parsed, "description", "name"), migrate);
41132
+ }
41133
+ }
41134
+ const taskId = strField(parsed, "task_id", "taskId");
41135
+ if (taskId && !runId && !hasSubagentShape) {
41136
+ const existing = state.bgTaskById.get(taskId);
41137
+ if (!existing?.toolUseId || existing.toolUseId === toolUseId) {
41138
+ state.bgTaskById.set(taskId, {
41139
+ toolUseId: toolUseId ?? existing?.toolUseId,
41140
+ description: existing?.description ?? strField(parsed, "description", "name") ?? taskId,
41141
+ outputFile: strField(parsed, "output_file", "outputFile") ?? existing?.outputFile
41142
+ });
41143
+ }
41144
+ }
41145
+ continue;
41146
+ }
41147
+ const plain = parsePlainTextTaskAck(d.summary);
41148
+ const allowPlain = isSpawnLaunch || /started in background/i.test(d.summary);
41149
+ if (allowPlain && plain.subagentId) {
41150
+ bindSubagentToolId(state, plain.subagentId, toolUseId, plain.description, migrate);
41151
+ }
41152
+ const explicitTaskId = d.summary.match(/(?:^|\n)\s*task_id:\s*(\S+)/i)?.[1];
41153
+ const bgTaskId = plain.outputFile ? explicitTaskId ?? plain.taskId : explicitTaskId && explicitTaskId !== plain.subagentId ? explicitTaskId : explicitTaskId && !plain.subagentId ? explicitTaskId : void 0;
41154
+ if (allowPlain && bgTaskId) {
41155
+ const existing = state.bgTaskById.get(bgTaskId);
41156
+ if (!existing?.toolUseId || existing.toolUseId === toolUseId) {
41157
+ state.bgTaskById.set(bgTaskId, {
41158
+ toolUseId: toolUseId ?? existing?.toolUseId,
41159
+ description: plain.description ?? existing?.description ?? bgTaskId,
41160
+ outputFile: plain.outputFile ?? existing?.outputFile
41161
+ });
41162
+ }
41059
41163
  }
41060
41164
  }
41165
+ return migrate;
41166
+ }
41167
+ function isValidateOnlyToolInput(input) {
41168
+ if (!input) return false;
41169
+ try {
41170
+ const o = tryParseJsonObject(input);
41171
+ if (o) return o.validate_only === true || o.validateOnly === true;
41172
+ } catch {
41173
+ }
41174
+ return /"validate_only"\s*:\s*true/.test(input) || /"validateOnly"\s*:\s*true/.test(input);
41061
41175
  }
41062
41176
  function tryParseJsonObject(text) {
41063
41177
  const trimmed = text.trim();
@@ -41380,16 +41494,22 @@ function mapSubagentProgress(u, state) {
41380
41494
  const durationMs = numField(u, "duration_ms", "durationMs") ?? 0;
41381
41495
  const toolCalls = numField(u, "tool_call_count", "toolCallCount") ?? 0;
41382
41496
  const tokens = numField(u, "tokens_used", "tokensUsed") ?? 0;
41383
- const toolsUsed = arrField(u, "tools_used", "toolsUsed");
41384
- const activityText = toolsUsed?.filter((t) => typeof t === "string").slice(-5).join(", ");
41497
+ const toolsUsed = (arrField(u, "tools_used", "toolsUsed") ?? []).filter((t) => typeof t === "string" && t.length > 0);
41498
+ const recent = toolsUsed.slice(-8);
41499
+ const lastTool = recent[recent.length - 1];
41500
+ const activityText = recent.length ? recent.join(", ") : void 0;
41501
+ const toolEntries = recent.map((toolName) => ({ toolName, description: "" }));
41385
41502
  const toolUseId = state.subagentToolById.get(id);
41386
41503
  events.push({
41387
41504
  type: "task_progress",
41388
41505
  taskId: id,
41389
41506
  ...toolUseId ? { toolUseId } : {},
41390
- description: id,
41507
+ // Prefer last tool name as description so reducer toolHistory advances.
41508
+ description: lastTool ?? id,
41509
+ ...lastTool ? { lastToolName: lastTool } : {},
41391
41510
  usage: { totalTokens: tokens, toolUses: toolCalls, durationMs },
41392
- ...activityText ? { activityText } : {}
41511
+ ...activityText ? { activityText } : {},
41512
+ ...toolEntries.length ? { toolEntries } : {}
41393
41513
  });
41394
41514
  return events;
41395
41515
  }
@@ -42215,7 +42335,7 @@ function createAcpAgentEventMapper(options) {
42215
42335
  });
42216
42336
  }
42217
42337
  trackOpenAcpTools(openTools, events);
42218
- noteToolCorrelationFromAgentEvents(events, xaiCorrelation);
42338
+ const migrate = noteToolCorrelationFromAgentEvents(events, xaiCorrelation);
42219
42339
  let textDelta = "";
42220
42340
  for (const event of events) {
42221
42341
  if (event.type === "content_delta" && event.delta.type === "text" && !event.delta.parentToolUseId) {
@@ -42223,6 +42343,7 @@ function createAcpAgentEventMapper(options) {
42223
42343
  }
42224
42344
  options.emit(event);
42225
42345
  }
42346
+ for (const event of migrate) options.emit(event);
42226
42347
  return { textDelta: textDelta || null };
42227
42348
  },
42228
42349
  applyXaiNotification(method, params) {
@@ -42233,8 +42354,9 @@ function createAcpAgentEventMapper(options) {
42233
42354
  { messageId: currentMessageId }
42234
42355
  );
42235
42356
  trackOpenAcpTools(openTools, events);
42236
- noteToolCorrelationFromAgentEvents(events, xaiCorrelation);
42357
+ const migrate = noteToolCorrelationFromAgentEvents(events, xaiCorrelation);
42237
42358
  for (const event of events) options.emit(event);
42359
+ for (const event of migrate) options.emit(event);
42238
42360
  },
42239
42361
  complete(stopReason = "end_turn") {
42240
42362
  if (terminal) return;
@@ -57179,8 +57301,8 @@ import { fileURLToPath } from "node:url";
57179
57301
  function resolveCliReleaseVersion() {
57180
57302
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
57181
57303
  if (fromEnv) return fromEnv;
57182
- if ("0.50.3-alpha".trim()) {
57183
- return "0.50.3-alpha".trim();
57304
+ if ("0.50.5-alpha".trim()) {
57305
+ return "0.50.5-alpha".trim();
57184
57306
  }
57185
57307
  const fromDist = readDistManifestVersion();
57186
57308
  if (fromDist) return fromDist;
@@ -57525,26 +57647,52 @@ var AuthService = class {
57525
57647
  return exchange();
57526
57648
  }
57527
57649
  /**
57528
- * Rotate refresh credential; reuse of an old refresh hash revokes the family.
57529
- * Requires proof signature over `proofPayload` with the registered device key
57530
- * (caller validates signature separately or passes already-verified flag).
57650
+ * Rotate refresh credential.
57651
+ *
57652
+ * Reuse of a rotated refresh hash outside
57653
+ * {@link AUTH_CREDENTIAL_LIFETIMES.refreshReuseGraceMs} is treated as theft
57654
+ * and permanently revokes the family. Inside the grace window, presenting any
57655
+ * previously rotated hash re-rotates the *current* session and returns a fresh
57656
+ * pair (lost-response / concurrent-refresh races — RFC 6819 §5.2.2.3 style).
57657
+ *
57658
+ * Requires proof signature over `proofPayload` with the registered device key.
57531
57659
  */
57532
57660
  refreshAccess(input) {
57533
57661
  const refreshHash = this.hashSecret(input.refreshToken);
57534
57662
  const now = Date.now();
57535
- const row = this.db.prepare(
57663
+ const loadByHash = (hash2) => this.db.prepare(
57536
57664
  `SELECT client_session_id, device_public_key_pem, device_public_key_fingerprint,
57537
- scopes_json, refresh_family_id, refresh_hash, refresh_expires_at, revoked_at
57538
- FROM client_sessions WHERE refresh_hash = ?`
57539
- ).get(refreshHash);
57665
+ scopes_json, refresh_family_id, refresh_hash, refresh_expires_at, revoked_at
57666
+ FROM client_sessions WHERE refresh_hash = ?`
57667
+ ).get(hash2);
57668
+ const loadBySessionId = (clientSessionId) => this.db.prepare(
57669
+ `SELECT client_session_id, device_public_key_pem, device_public_key_fingerprint,
57670
+ scopes_json, refresh_family_id, refresh_hash, refresh_expires_at, revoked_at
57671
+ FROM client_sessions WHERE client_session_id = ?`
57672
+ ).get(clientSessionId);
57673
+ let row = loadByHash(refreshHash);
57540
57674
  if (!row) {
57541
- const reused = this.db.prepare("SELECT client_session_id FROM refresh_reuse_log WHERE refresh_hash = ?").get(refreshHash);
57542
- if (reused) {
57543
- this.db.prepare("UPDATE client_sessions SET revoked_at = ? WHERE client_session_id = ? AND revoked_at IS NULL").run(now, reused.client_session_id);
57675
+ const reused = this.db.prepare(
57676
+ `SELECT client_session_id, seen_at FROM refresh_reuse_log WHERE refresh_hash = ?`
57677
+ ).get(refreshHash);
57678
+ if (!reused) {
57679
+ throw Object.assign(new Error("invalid refresh token"), { code: "unauthorized" });
57680
+ }
57681
+ const withinGrace = now - reused.seen_at <= AUTH_CREDENTIAL_LIFETIMES.refreshReuseGraceMs;
57682
+ if (withinGrace) {
57683
+ row = loadBySessionId(reused.client_session_id);
57684
+ if (!row) {
57685
+ throw Object.assign(new Error("invalid refresh token"), { code: "unauthorized" });
57686
+ }
57687
+ } else {
57688
+ this.db.prepare(
57689
+ "UPDATE client_sessions SET revoked_at = ? WHERE client_session_id = ? AND revoked_at IS NULL"
57690
+ ).run(now, reused.client_session_id);
57544
57691
  this.onRevoke?.(reused.client_session_id);
57545
- throw Object.assign(new Error("refresh token reuse detected; session revoked"), { code: "unauthorized" });
57692
+ throw Object.assign(new Error("refresh token reuse detected; session revoked"), {
57693
+ code: "unauthorized"
57694
+ });
57546
57695
  }
57547
- throw Object.assign(new Error("invalid refresh token"), { code: "unauthorized" });
57548
57696
  }
57549
57697
  if (row.revoked_at) throw Object.assign(new Error("client session revoked"), { code: "unauthorized" });
57550
57698
  if (row.refresh_expires_at < now) {
@@ -57566,20 +57714,21 @@ var AuthService = class {
57566
57714
  if (!Number.isFinite(proofTs) || Math.abs(now - proofTs) > 12e4) {
57567
57715
  throw Object.assign(new Error("proof timestamp out of window"), { code: "unauthorized" });
57568
57716
  }
57717
+ const session = row;
57569
57718
  return this.db.transaction(() => {
57570
- const scopes = parseScopes(row.scopes_json);
57719
+ const scopes = parseScopes(session.scopes_json);
57571
57720
  const newRefresh = randomToken(32);
57572
57721
  const newRefreshHash = this.hashSecret(newRefresh);
57573
57722
  const refreshExpiresAt = now + AUTH_CREDENTIAL_LIFETIMES.refreshInactivityMs;
57574
57723
  this.db.prepare(
57575
57724
  `INSERT OR IGNORE INTO refresh_reuse_log (refresh_hash, client_session_id, seen_at)
57576
57725
  VALUES (?, ?, ?)`
57577
- ).run(row.refresh_hash, row.client_session_id, now);
57726
+ ).run(session.refresh_hash, session.client_session_id, now);
57578
57727
  const updated = this.db.prepare(
57579
57728
  `UPDATE client_sessions
57580
57729
  SET refresh_hash = ?, refresh_expires_at = ?, last_used_at = ?
57581
57730
  WHERE client_session_id = ? AND refresh_hash = ? AND revoked_at IS NULL`
57582
- ).run(newRefreshHash, refreshExpiresAt, now, row.client_session_id, row.refresh_hash);
57731
+ ).run(newRefreshHash, refreshExpiresAt, now, session.client_session_id, session.refresh_hash);
57583
57732
  if (updated.changes !== 1) {
57584
57733
  throw Object.assign(new Error("refresh race; retry"), { code: "conflict" });
57585
57734
  }
@@ -57589,15 +57738,15 @@ var AuthService = class {
57589
57738
  aud: "superone",
57590
57739
  exp: expiresAt,
57591
57740
  iat: now,
57592
- clientSessionId: row.client_session_id,
57741
+ clientSessionId: session.client_session_id,
57593
57742
  scopes,
57594
- proofKeyThumbprint: row.device_public_key_fingerprint
57743
+ proofKeyThumbprint: session.device_public_key_fingerprint
57595
57744
  });
57596
57745
  return {
57597
57746
  accessToken,
57598
57747
  expiresAt,
57599
57748
  scopes,
57600
- clientSessionId: row.client_session_id,
57749
+ clientSessionId: session.client_session_id,
57601
57750
  refreshToken: newRefresh
57602
57751
  };
57603
57752
  })();
@@ -61195,7 +61344,12 @@ function defaultProbeModels(ctx) {
61195
61344
  return async (harnessId, cwd) => {
61196
61345
  if (harnessId !== "claude") return [];
61197
61346
  const binaryPath = resolveClaudeBinaryPath({ harnesses: ctx.harnesses });
61198
- if (!binaryPath) return [];
61347
+ if (!binaryPath) {
61348
+ console.warn(
61349
+ "[harness.resources] claude model probe skipped: no Agent SDK binary on this node (reinstall the optional platform package or set SUPERONE_CLAUDE_BINARY)"
61350
+ );
61351
+ return [];
61352
+ }
61199
61353
  return getNodeClaudeModelCatalog({ cwd, binaryPath });
61200
61354
  };
61201
61355
  }
@@ -61233,6 +61387,9 @@ async function handleHarnessResources(payload, ctx) {
61233
61387
  const probe = ctx.probeModels ?? defaultProbeModels(ctx);
61234
61388
  const probed = await probe(hid, project.path);
61235
61389
  if (probed.length > 0) return probed;
61390
+ console.warn(
61391
+ `[harness.resources] ${hid} probe returned no models; serving the built-in fallback table`
61392
+ );
61236
61393
  return listHarnessModels(ctx.providers, hid, apiProviderId ?? null);
61237
61394
  };
61238
61395
  const bundle = await collectHarnessResources({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@super-one/cli",
3
- "version": "0.50.3-alpha",
3
+ "version": "0.50.5-alpha",
4
4
  "description": "SuperOne headless node CLI — remote execution environment (RPC, workspaces, sessions).",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",