@super-one/cli 0.73.0 → 0.74.0-alpha.1

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 +1308 -218
  3. package/package.json +10 -10
package/lib/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- process.env.SUPERONE_VARIANT = "stable";
1
+ process.env.SUPERONE_VARIANT = "alpha";
2
2
  import { createRequire as __superoneCreateRequire } from 'node:module';
3
3
  import { fileURLToPath as __superoneFileURLToPath } from 'node:url';
4
4
  import { dirname as __superoneDirname } from 'node:path';
@@ -137,8 +137,8 @@ import { fileURLToPath } from "node:url";
137
137
  function resolveCliReleaseVersion() {
138
138
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
139
139
  if (fromEnv) return fromEnv;
140
- if ("0.73.0".trim()) {
141
- return "0.73.0".trim();
140
+ if ("0.74.0-alpha.1".trim()) {
141
+ return "0.74.0-alpha.1".trim();
142
142
  }
143
143
  const fromDist = readDistManifestVersion();
144
144
  if (fromDist) return fromDist;
@@ -409,7 +409,7 @@ var init_interaction_memory = __esm({
409
409
  });
410
410
 
411
411
  // ../../packages/shared/src/superone-tool-descriptions.ts
412
- var MANUAL_READ_DESCRIPTION, SETUP_MINI_APP_DEV_DESCRIPTION, REGISTER_DEV_MINIAPP_DESCRIPTION, PACK_MINI_APP_DESCRIPTION, UPDATE_SUPERONE_TYPES_DESCRIPTION, MINIAPP_DEV_PREVIEW_DESCRIPTION, MINIAPP_DEV_RELOAD_DESCRIPTION, MINIAPP_DEV_PREVIEW_INPUT_SCHEMA, MINIAPP_DEV_RELOAD_INPUT_SCHEMA, RENAME_SESSION_DESCRIPTION, SESSION_TAG_DESCRIPTION, SESSION_TAG_LIST_DESCRIPTION, PROJECT_LIST_DESCRIPTION, SESSION_LIST_DESCRIPTION, SESSION_SEARCH_DESCRIPTION, SESSION_READ_DESCRIPTION, SESSION_READ_MESSAGE_ID_DESCRIPTION, SESSION_READ_AROUND_DESCRIPTION, SESSION_READ_CURSOR_DESCRIPTION, SESSION_READ_LIMIT_DESCRIPTION, SESSION_READ_THINKING_DESCRIPTION, SESSION_TAGS_FILTER_DESCRIPTION, SESSION_TAG_MATCH_DESCRIPTION, SESSION_CLEANUP_DESCRIPTION, CONFIG_READ_DESCRIPTION, CONFIG_APPLY_DESCRIPTION, LIST_MEDIA_PROVIDERS_DESCRIPTION, GENERATE_IMAGE_DESCRIPTION, GENERATE_VIDEO_DESCRIPTION, VIDEO_STATUS_DESCRIPTION, SESSION_LIST_AGENTS_DESCRIPTION, SESSION_REQUEST_AGENTS_DESCRIPTION, LAUNCH_SUMMARY_DESCRIPTION, START_LAUNCH_ID_DESCRIPTION, LAUNCH_TASK_DESCRIPTION, LAUNCH_MODE_DESCRIPTION, LAUNCH_SESSION_ID_DESCRIPTION, LAUNCH_PERMISSION_MODE_DESCRIPTION, LAUNCH_ENVIRONMENT_DESCRIPTION, LAUNCH_CWD_DESCRIPTION, LAUNCH_WORKTREE_DESCRIPTION, LAUNCH_BRANCH_NAME_DESCRIPTION, SESSION_START_DESCRIPTION, SESSION_SEND_DESCRIPTION, SESSION_SEND_TO_DESCRIPTION, SESSION_SEND_CONTENT_DESCRIPTION, SESSION_RETRIEVE_DESCRIPTION, SESSION_RETRIEVE_FROM_DESCRIPTION, SESSION_SUGGEST_TASK_DESCRIPTION, SUGGEST_TASK_TITLE_DESCRIPTION, SUGGEST_TASK_TLDR_DESCRIPTION, SUGGEST_TASK_PROMPT_DESCRIPTION, SUGGEST_TASK_CWD_DESCRIPTION, AUTOMATION_LIST_DESCRIPTION, AUTOMATION_APPLY_DESCRIPTION, AUTOMATION_DELETE_DESCRIPTION, TERMINAL_TABS_DESCRIPTION, TERMINAL_SNAPSHOT_DESCRIPTION, TERMINAL_ACT_DESCRIPTION, TERMINAL_WAIT_FOR_DESCRIPTION, ENVIRONMENT_GET_INFO_DESCRIPTION, ENVIRONMENT_GET_INFO_IDS_DESCRIPTION, ENVIRONMENT_GET_INFO_INCLUDE_DESCRIPTION, ARCHIVE_ENVIRONMENT_DESCRIPTION;
412
+ var MANUAL_READ_DESCRIPTION, SETUP_MINI_APP_DEV_DESCRIPTION, REGISTER_DEV_MINIAPP_DESCRIPTION, PACK_MINI_APP_DESCRIPTION, UPDATE_SUPERONE_TYPES_DESCRIPTION, MINIAPP_LIST_DESCRIPTION, MINIAPP_LIST_APP_ID_DESCRIPTION, MINIAPP_LIST_INCLUDE_SCHEMA_DESCRIPTION, MINIAPP_CALL_DESCRIPTION, MINIAPP_CALL_APP_ID_DESCRIPTION, MINIAPP_CALL_TOOL_DESCRIPTION, MINIAPP_CALL_INPUT_DESCRIPTION, MINIAPP_OPEN_DESCRIPTION, MINIAPP_OPEN_APP_ID_DESCRIPTION, MINIAPP_DEV_PREVIEW_DESCRIPTION, MINIAPP_DEV_RELOAD_DESCRIPTION, MINIAPP_DEV_PREVIEW_INPUT_SCHEMA, MINIAPP_DEV_RELOAD_INPUT_SCHEMA, RENAME_SESSION_DESCRIPTION, SESSION_TAG_DESCRIPTION, SESSION_TAG_LIST_DESCRIPTION, PROJECT_LIST_DESCRIPTION, SESSION_LIST_DESCRIPTION, SESSION_SEARCH_DESCRIPTION, SESSION_READ_DESCRIPTION, SESSION_READ_MESSAGE_ID_DESCRIPTION, SESSION_READ_AROUND_DESCRIPTION, SESSION_READ_CURSOR_DESCRIPTION, SESSION_READ_LIMIT_DESCRIPTION, SESSION_READ_THINKING_DESCRIPTION, SESSION_TAGS_FILTER_DESCRIPTION, SESSION_TAG_MATCH_DESCRIPTION, SESSION_CLEANUP_DESCRIPTION, CONFIG_READ_DESCRIPTION, CONFIG_APPLY_DESCRIPTION, LIST_MEDIA_PROVIDERS_DESCRIPTION, GENERATE_IMAGE_DESCRIPTION, GENERATE_VIDEO_DESCRIPTION, VIDEO_STATUS_DESCRIPTION, SESSION_LIST_AGENTS_DESCRIPTION, SESSION_REQUEST_AGENTS_DESCRIPTION, LAUNCH_SUMMARY_DESCRIPTION, START_LAUNCH_ID_DESCRIPTION, LAUNCH_TASK_DESCRIPTION, LAUNCH_MODE_DESCRIPTION, LAUNCH_SESSION_ID_DESCRIPTION, LAUNCH_PERMISSION_MODE_DESCRIPTION, LAUNCH_ENVIRONMENT_DESCRIPTION, LAUNCH_CWD_DESCRIPTION, LAUNCH_WORKTREE_DESCRIPTION, LAUNCH_BRANCH_NAME_DESCRIPTION, SESSION_START_DESCRIPTION, SESSION_SEND_DESCRIPTION, SESSION_SEND_TO_DESCRIPTION, SESSION_SEND_CONTENT_DESCRIPTION, SESSION_RETRIEVE_DESCRIPTION, SESSION_RETRIEVE_FROM_DESCRIPTION, SESSION_SUGGEST_TASK_DESCRIPTION, SUGGEST_TASK_TITLE_DESCRIPTION, SUGGEST_TASK_TLDR_DESCRIPTION, SUGGEST_TASK_PROMPT_DESCRIPTION, SUGGEST_TASK_CWD_DESCRIPTION, AUTOMATION_LIST_DESCRIPTION, AUTOMATION_APPLY_DESCRIPTION, AUTOMATION_DELETE_DESCRIPTION, AGENT_PROFILE_LIST_DESCRIPTION, AGENT_PROFILE_APPLY_DESCRIPTION, AGENT_PROFILE_DELETE_DESCRIPTION, TERMINAL_TABS_DESCRIPTION, TERMINAL_SNAPSHOT_DESCRIPTION, TERMINAL_ACT_DESCRIPTION, TERMINAL_WAIT_FOR_DESCRIPTION, ENVIRONMENT_GET_INFO_DESCRIPTION, ENVIRONMENT_GET_INFO_IDS_DESCRIPTION, ENVIRONMENT_GET_INFO_INCLUDE_DESCRIPTION, ARCHIVE_ENVIRONMENT_DESCRIPTION, LAYOUT_SNAPSHOT_DESCRIPTION, LAYOUT_ACT_DESCRIPTION, LAYOUT_ACT_PATH_DESCRIPTION, LAYOUT_ACT_LINE_DESCRIPTION, LAYOUT_ACT_TAB_DESCRIPTION, LAYOUT_ACT_GROUP_DESCRIPTION, LAYOUT_ACT_DIRECTION_DESCRIPTION, LAYOUT_ACT_INDEX_DESCRIPTION, LAYOUT_ACT_WIDTH_DESCRIPTION, LAYOUT_ACT_HEIGHT_DESCRIPTION, LAYOUT_ACT_MODE_DESCRIPTION, LAYOUT_ACT_POSITION_DESCRIPTION, LAYOUT_ACT_SESSION_DESCRIPTION;
413
413
  var init_superone_tool_descriptions = __esm({
414
414
  "../../packages/shared/src/superone-tool-descriptions.ts"() {
415
415
  "use strict";
@@ -418,6 +418,15 @@ var init_superone_tool_descriptions = __esm({
418
418
  REGISTER_DEV_MINIAPP_DESCRIPTION = "Register an existing mini-app directory without modifying its source files. Reads manifest.json from the directory or dist, updates dev-registry.json in the variant-specific personal data root, and optionally writes a project- or user-scoped .s1-dev.json pointer.";
419
419
  PACK_MINI_APP_DESCRIPTION = "Package a mini-app directory into a .s1app file for distribution. The app directory must contain a valid manifest.json with a version field. Generates integrity checksums and creates a compressed archive.";
420
420
  UPDATE_SUPERONE_TYPES_DESCRIPTION = "Update the superone.d.ts type definitions in an existing mini-app project to the latest version. Use this when the mini-app needs access to newly added SuperOne APIs.";
421
+ MINIAPP_LIST_DESCRIPTION = "List the mini-apps installed for this session's project and their tools. Omit appId for a compact catalog (tool names + one-line descriptions). Pass appId to inspect one app; includeSchema defaults true for that app's full tool definitions including inputSchema. Call this before miniapp_call when you do not know the tool names or parameters.";
422
+ MINIAPP_LIST_APP_ID_DESCRIPTION = "Optional mini-app id. When set, returns that app's tools only.";
423
+ MINIAPP_LIST_INCLUDE_SCHEMA_DESCRIPTION = "When appId is set, include full tool definitions with inputSchema (default true). Ignored when listing all apps.";
424
+ MINIAPP_CALL_DESCRIPTION = "Execute a tool of an installed mini-app. Pass appId + tool name from miniapp_list, and tool arguments as input. Tools run in the app's host without its UI; show the UI with miniapp_open. Do not invent tools \u2014 call miniapp_list first when unsure.";
425
+ MINIAPP_CALL_APP_ID_DESCRIPTION = "Mini-app id from miniapp_list.";
426
+ MINIAPP_CALL_TOOL_DESCRIPTION = "Tool name declared by that app's manifest.";
427
+ MINIAPP_CALL_INPUT_DESCRIPTION = "Arguments for the app tool. Validated against the tool's inputSchema at dispatch time.";
428
+ MINIAPP_OPEN_DESCRIPTION = "Open an installed mini-app's UI as a tab in your activity panel, in the background: the result says whether the user sees it and how to bring it forward. Use when the user wants to see or use the app itself; its tools run without the UI through miniapp_call.";
429
+ MINIAPP_OPEN_APP_ID_DESCRIPTION = "Mini-app id from miniapp_list.";
421
430
  MINIAPP_DEV_PREVIEW_DESCRIPTION = "Render a development mini-app tool's chat UI (intercept, result, or standalone template) from fixture input/result without running the tool. Returns a view id to pass as tab to browser_* tools for snapshots, clicks, screenshots, and console. Intercept submit/cancel and result close are logged as info console entries instead of executing. A new call replaces the app's previous preview. Workflow: read_manual miniapp/debugging.";
422
431
  MINIAPP_DEV_RELOAD_DESCRIPTION = "Reload a development mini-app after editing it (build first if it has a build step): restarts its MiniApp Host so changed main code loads, refreshes manifest tools and templates, and reloads its open WebViews. Then inspect them with browser_* tools via miniapp: view ids.";
423
432
  MINIAPP_DEV_PREVIEW_INPUT_SCHEMA = {
@@ -463,7 +472,7 @@ var init_superone_tool_descriptions = __esm({
463
472
  GENERATE_IMAGE_DESCRIPTION = "Generate or edit an image; pass source files in reference_image_paths for edits. Discover configured providers with media_list_providers when not already known. Read the matching media provider-task topic for unfamiliar options. Inspect previewPaths; savedPaths holds originals for export or edits. Check warnings for ignored options. Results display automatically; do not embed them again.";
464
473
  GENERATE_VIDEO_DESCRIPTION = "Submit a video generation; the tool opens a parameter review for user approval. Stop on cancelled or error; use returned feedback before retrying. Poll media_video_status about every 30s until generated or error. Results display automatically. Use media_list_providers for configured providers and the matching media provider-task manual for unfamiliar options.";
465
474
  VIDEO_STATUS_DESCRIPTION = "Advance a submitted video job and read its status: running, generated with savedPaths, or error with message. Poll about every 30 seconds while running: these calls download and save the completed video. Report it ready only after generated; stop on error.";
466
- SESSION_LIST_AGENTS_DESCRIPTION = "List the agent profiles available for user-approved child sessions. Only launchable agents are returned. Agents on other connected machines are listed under environments[] with the environmentId to launch them with. defaultConfig is the user's launch setup for the agent (model, effort, permission, sandbox, apiProviderId); leave out the config fields it already covers. apiProviders lists the subscription accounts and API keys it can run on. You may reuse one agentId for multiple launches. Skip this call when the user already named an agent with @ \u2014 that mention carries its agentId.";
475
+ SESSION_LIST_AGENTS_DESCRIPTION = "List the agents available for user-approved child sessions (launchable ones only): id, name, harness, description. Agents on other connected machines are listed under environments[] with the environmentId to launch them with. A launch without config runs on the user's setup for that agent. To set config, pass id (and environment for another machine): returns its defaultConfig, models with their efforts, and the apiProviders (accounts, API keys) it can run on. You may reuse one agentId for multiple launches. Skip this call when the user already named an agent with @ \u2014 that mention carries its agentId.";
467
476
  SESSION_REQUEST_AGENTS_DESCRIPTION = 'Request user approval for collaboration launches. See the mode field for spawn vs handoff vs link. Spawn/handoff: pick an agentId from session_collab_list_agents; require name, role, summary. Link: require sessionId + summary. Read read_manual({ domain: "product", topic: "collaboration" }) before the first launch in a session. User must approve; returns a launchId per launch. Pass the task to session_collab_start, not here.';
468
477
  LAUNCH_SUMMARY_DESCRIPTION = "Short 2\u20133 sentence summary the user approves in the confirm dialog. The full brief goes to session_collab_start.";
469
478
  START_LAUNCH_ID_DESCRIPTION = "A launchId returned by session_collab_request in this session.";
@@ -481,7 +490,7 @@ var init_superone_tool_descriptions = __esm({
481
490
  SESSION_SEND_CONTENT_DESCRIPTION = "Mailbox message body in Markdown. Prefer structured Markdown (headings, lists, code fences) for agent-to-agent handoffs; the SuperOne UI renders it as a Markdown preview.";
482
491
  SESSION_RETRIEVE_DESCRIPTION = 'Read queued Markdown messages from your collaboration peers and list those peers (session id, name, relation). Child peers may also report state (running, awaiting_approval, stalled, idle, error), lastActivityAt, and runningTool. Call after a collaboration wake, before acting on peer input, or to find out who you can message. 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.';
483
492
  SESSION_RETRIEVE_FROM_DESCRIPTION = "Only read messages from these peer session ids. Omit to read from every peer.";
484
- SESSION_SUGGEST_TASK_DESCRIPTION = "Suggest a side task the user can launch later as its own session. Use when you notice a real issue outside the current task (a bug, cleanup, or follow-up) that should not derail it. Returns a taskId at once, without an approval prompt; keep working. The user sees a card and may launch it as a new top-level session or dismiss it; if it goes stale, say so in your reply. To hand work over now, use session_collab_request instead.";
493
+ SESSION_SUGGEST_TASK_DESCRIPTION = "Suggest a side task the user can launch later as its own session. Use when you notice a real issue outside the current task (a bug, cleanup, or follow-up) that should not derail it. Returns a taskId at once, without an approval prompt; keep working. The user sees a card and may launch it as a new top-level session; if it goes stale, say so in your reply. To hand work over now, use session_collab_request instead.";
485
494
  SUGGEST_TASK_TITLE_DESCRIPTION = "Card title, starting with a verb.";
486
495
  SUGGEST_TASK_TLDR_DESCRIPTION = "One or two sentences shown on the card.";
487
496
  SUGGEST_TASK_PROMPT_DESCRIPTION = "Markdown brief delivered as the new session's opening turn. The receiver cannot ask you anything, so include the context, file paths, and what done looks like.";
@@ -489,6 +498,9 @@ var init_superone_tool_descriptions = __esm({
489
498
  AUTOMATION_LIST_DESCRIPTION = "List project automations with schedule and last/next run. Pass id for full prompt, agentConfig, and schedule; filter by query or enabled. Find unknown ids here before automation_apply or automation_delete; check for duplicates before creation when needed.";
490
499
  AUTOMATION_APPLY_DESCRIPTION = 'Create or update a project automation. create needs name, prompt, schedule; update needs id plus any field (pause via enabled=false). Call automation_list first for ids; remove with automation_delete. Always opens a user confirmation dialog and applies nothing without approval. For schedule and agentConfig shapes see read_manual({ domain: "product", topic: "automation" }).';
491
500
  AUTOMATION_DELETE_DESCRIPTION = "Permanently delete project automations by id (from automation_list). Always opens a user confirmation dialog. Current project only. Prefer automation_list to choose ids first.";
501
+ AGENT_PROFILE_LIST_DESCRIPTION = "List agent profiles: named agents that session_collab_list_agents offers for delegation, plus the built-in <harness>-base rows. Without id: one row per profile (id, name, harness, base, short description). Pass id for its full description and instructions, runtime, launch defaults, and what that harness accepts: models, their efforts, permission modes, and its own options (each harness has different ones). Read this before agent_profile_apply or agent_profile_delete.";
502
+ AGENT_PROFILE_APPLY_DESCRIPTION = "Create or update an agent profile. create needs harnessId, name, description; update needs id plus the fields to change (empty string clears model, effort, permissionMode or instructions; null clears an option). description is what other agents read to pick a delegate, so say what this agent is for. model, effort, permissionMode and options must be ones the harness accepts: read agent_profile_list with the <harness>-base id first. Built-in <harness>-base rows are read-only; remove profiles with agent_profile_delete. Always opens a user confirmation dialog, where the user may edit a new profile before approving; applies nothing without approval.";
503
+ AGENT_PROFILE_DELETE_DESCRIPTION = "Permanently delete agent profiles by id (from agent_profile_list). Sessions already started on one fall back to its built-in harness agent. Built-in <harness>-base rows cannot be deleted. Always opens a user confirmation dialog.";
492
504
  TERMINAL_TABS_DESCRIPTION = "Only for commands that run until stopped (servers, watchers) or need keyboard input (REPLs, TUIs, ssh, wizards). Non-interactive commands that finish (build, test, install, git) use your shell tool, even if slow. action=list (default) returns this session's tabs plus the user's as a TOON table; other sessions' tabs are hidden. action=run asks to approve `command`, types it into a new or idle tab, and returns the screen; you control the tab only while that command is in the foreground. action=attach asks to control a command already running in a user tab. action=close kills a tab you opened, never one the user is using. For open tabs: terminal_act / terminal_wait_for / terminal_snapshot.";
493
505
  TERMINAL_SNAPSHOT_DESCRIPTION = "Read a terminal tab as rendered text. `include` picks sections: screen (visible rows, default), scrollback (last `tail` lines including scrolled-off output), cursor, meta (title, cwd, status, foreground command, control). Use screen for prompts and full-screen programs, scrollback for server logs. Output over the tail cap is spilled to a file and returned as path + preview. Prefer this before terminal_act; use terminal_wait_for instead of polling.";
494
506
  TERMINAL_ACT_DESCRIPTION = 'Send input to a terminal tab you control. actions is an array, e.g. [{type:"type",text:"yes"}] or [{type:"key",key:"Ctrl+C"}]; types: type (Enter by default), key (Enter, Tab, Escape, Up, Ctrl+C, F1\u2026), raw, resize, wait. ONE action per call by default; batch 2\u201320 only for an uninterruptible sequence (answer a wizard). Fail-fast. expect holds the call open until a screen condition is met (text, textGone, idleMs, exited); the screen after the batch is returned. Rejected with status=rejected when the approved command has exited or the user took over \u2014 do not retry, call terminal_tabs run again or ask. description is shown to the user instead of raw keystrokes.';
@@ -497,15 +509,36 @@ var init_superone_tool_descriptions = __esm({
497
509
  ENVIRONMENT_GET_INFO_IDS_DESCRIPTION = "Environments to read; omit for all.";
498
510
  ENVIRONMENT_GET_INFO_INCLUDE_DESCRIPTION = 'Detail groups to add. Default ["hardware"]; [] returns IDs, labels and state only.';
499
511
  ARCHIVE_ENVIRONMENT_DESCRIPTION = "Target environment ID from environment_get_info. Omit or use localhost for the calling session host.";
512
+ LAYOUT_SNAPSHOT_DESCRIPTION = "Read the SuperOne desktop layout around your session: whether the user can see your chat, the sidebar, your activity panel (open, side, maximized), its tab groups (index and px box, so you can tell top/bottom from side by side) and tabs (id, kind, title, active, group, openedBy), your bottom terminal, the split view, chatMode and chatPosition, and sizes: px widths of the window, sidebar, panel and chat, with the min/max each column can take. Call it for tab and group ids before layout_act, for sizes before a resize, or to check what the user is looking at.";
513
+ LAYOUT_ACT_DESCRIPTION = "Arrange the SuperOne desktop for the user: open a file as a tab; focus or close tabs, move one beside or into a group or reorder it (move_tab), resize a group; show, hide, maximize, move or resize your activity panel; show or hide your terminal; show, hide or resize the sidebar (widen a column to narrow the chat); dock, float or iconify the chat; put a session you launched beside yours. Open browser and terminal tabs with browser_tabs / terminal_tabs. You can close only tabs and panes you opened. It never moves the user: in the background your own layout changes wait for them (status queued) and window-wide ones are skipped. `visible` says whether the user sees the result now.";
514
+ LAYOUT_ACT_PATH_DESCRIPTION = "open_file: the file, absolute or relative to your working folder.";
515
+ LAYOUT_ACT_LINE_DESCRIPTION = "open_file: 1-based line to reveal.";
516
+ LAYOUT_ACT_TAB_DESCRIPTION = "Tab id from layout_snapshot (browser_tabs / terminal_tabs ids work too). focus_tab, close_tab, move_tab; maximize_panel defaults to the active tab.";
517
+ LAYOUT_ACT_GROUP_DESCRIPTION = "Group index from layout_snapshot groups. resize_group; move_tab target, default the tab's own group (a tab alone there goes beside the group before it).";
518
+ LAYOUT_ACT_DIRECTION_DESCRIPTION = "move_tab: right / down / left / up of the group as a new group, or into it. split_session: any side. Default right.";
519
+ LAYOUT_ACT_INDEX_DESCRIPTION = "move_tab: 0-based position among the destination group's tabs; with into and your own group it reorders.";
520
+ LAYOUT_ACT_WIDTH_DESCRIPTION = "resize_sidebar / resize_panel / resize_group: target width in px. Sidebar and panel clamp to layout_snapshot sizes; the result has the applied size.";
521
+ LAYOUT_ACT_HEIGHT_DESCRIPTION = "resize_group: target height in px.";
522
+ LAYOUT_ACT_MODE_DESCRIPTION = "chat_mode: docked (a column beside the panel), floating (a movable window over the panel, which then fills the window) or icon (that window collapsed).";
523
+ LAYOUT_ACT_POSITION_DESCRIPTION = "chat_mode: where the floating chat or its icon snaps. Alone it moves the chat without changing mode; while docked it is kept for the next float.";
524
+ LAYOUT_ACT_SESSION_DESCRIPTION = "split_session / close_split: a session you launched with session_collab_*.";
500
525
  }
501
526
  });
502
527
 
503
528
  // ../../packages/shared/src/environment/host-action-collaboration-descriptors.ts
504
- var SESSION_SUGGEST_TASK_INPUT_SCHEMA, HOST_ACTION_COLLABORATION_DESCRIPTORS;
529
+ var SESSION_LIST_AGENTS_INPUT_SCHEMA, SESSION_SUGGEST_TASK_INPUT_SCHEMA, HOST_ACTION_COLLABORATION_DESCRIPTORS;
505
530
  var init_host_action_collaboration_descriptors = __esm({
506
531
  "../../packages/shared/src/environment/host-action-collaboration-descriptors.ts"() {
507
532
  "use strict";
508
533
  init_superone_tool_descriptions();
534
+ SESSION_LIST_AGENTS_INPUT_SCHEMA = {
535
+ type: "object",
536
+ properties: {
537
+ id: { type: "string", description: "An agent id from the list. Returns what a launch of that agent can set." },
538
+ environment: { type: "string", description: "With id: the environmentId the agent is listed under in environments[]." }
539
+ },
540
+ additionalProperties: false
541
+ };
509
542
  SESSION_SUGGEST_TASK_INPUT_SCHEMA = {
510
543
  type: "object",
511
544
  properties: {
@@ -521,11 +554,7 @@ var init_host_action_collaboration_descriptors = __esm({
521
554
  {
522
555
  "name": "session_collab_list_agents",
523
556
  "description": SESSION_LIST_AGENTS_DESCRIPTION,
524
- "inputSchema": {
525
- "type": "object",
526
- "properties": {},
527
- "additionalProperties": false
528
- }
557
+ "inputSchema": SESSION_LIST_AGENTS_INPUT_SCHEMA
529
558
  },
530
559
  {
531
560
  "name": "session_collab_request",
@@ -2668,50 +2697,44 @@ var HOST_ACTION_MINIAPP_DESCRIPTORS;
2668
2697
  var init_host_action_miniapp_descriptors = __esm({
2669
2698
  "../../packages/shared/src/environment/host-action-miniapp-descriptors.ts"() {
2670
2699
  "use strict";
2700
+ init_superone_tool_descriptions();
2671
2701
  HOST_ACTION_MINIAPP_DESCRIPTORS = [
2672
2702
  {
2673
- "name": "miniapp_list",
2674
- "description": "List mini-apps authorized for this session and their tools. Omit appId for a compact catalog (tool names + one-line descriptions). Pass appId to inspect one app; includeSchema defaults true for that app's full tool definitions including inputSchema. Call this before miniapp_call when you do not know the tool names or parameters.",
2675
- "inputSchema": {
2676
- "type": "object",
2677
- "properties": {
2678
- "appId": {
2679
- "type": "string",
2680
- "description": "Optional mini-app id. When set, returns that app's tools only."
2681
- },
2682
- "includeSchema": {
2683
- "type": "boolean",
2684
- "description": "When appId is set, include full tool definitions with inputSchema (default true). Ignored when listing all apps."
2685
- }
2703
+ name: "miniapp_list",
2704
+ description: MINIAPP_LIST_DESCRIPTION,
2705
+ inputSchema: {
2706
+ type: "object",
2707
+ properties: {
2708
+ appId: { type: "string", description: MINIAPP_LIST_APP_ID_DESCRIPTION },
2709
+ includeSchema: { type: "boolean", description: MINIAPP_LIST_INCLUDE_SCHEMA_DESCRIPTION }
2686
2710
  },
2687
- "additionalProperties": false
2711
+ additionalProperties: false
2688
2712
  }
2689
2713
  },
2690
2714
  {
2691
- "name": "miniapp_call",
2692
- "description": "Execute a tool on a session-authorized mini-app. Pass appId + tool name from miniapp_list, and tool arguments as input. Panel open/close is implicit: non-standalone tools lazy-open the panel; standalone tools run without a panel. Do not invent tools \u2014 call miniapp_list first when unsure.",
2693
- "inputSchema": {
2694
- "type": "object",
2695
- "properties": {
2696
- "appId": {
2697
- "type": "string",
2698
- "description": "Mini-app id (from miniapp_list or user @-mention)."
2699
- },
2700
- "tool": {
2701
- "type": "string",
2702
- "description": "Tool name declared by that app's manifest."
2703
- },
2704
- "input": {
2705
- "type": "object",
2706
- "additionalProperties": true,
2707
- "description": "Arguments for the app tool. Validated against the tool's inputSchema at dispatch time."
2708
- }
2715
+ name: "miniapp_call",
2716
+ description: MINIAPP_CALL_DESCRIPTION,
2717
+ inputSchema: {
2718
+ type: "object",
2719
+ properties: {
2720
+ appId: { type: "string", description: MINIAPP_CALL_APP_ID_DESCRIPTION },
2721
+ tool: { type: "string", description: MINIAPP_CALL_TOOL_DESCRIPTION },
2722
+ input: { type: "object", additionalProperties: true, description: MINIAPP_CALL_INPUT_DESCRIPTION }
2709
2723
  },
2710
- "required": [
2711
- "appId",
2712
- "tool"
2713
- ],
2714
- "additionalProperties": false
2724
+ required: ["appId", "tool"],
2725
+ additionalProperties: false
2726
+ }
2727
+ },
2728
+ {
2729
+ name: "miniapp_open",
2730
+ description: MINIAPP_OPEN_DESCRIPTION,
2731
+ inputSchema: {
2732
+ type: "object",
2733
+ properties: {
2734
+ appId: { type: "string", description: MINIAPP_OPEN_APP_ID_DESCRIPTION }
2735
+ },
2736
+ required: ["appId"],
2737
+ additionalProperties: false
2715
2738
  }
2716
2739
  }
2717
2740
  ];
@@ -3616,6 +3639,85 @@ var init_host_action_automation_descriptors = __esm({
3616
3639
  }
3617
3640
  });
3618
3641
 
3642
+ // ../../packages/shared/src/environment/host-action-agent-profile-descriptors.ts
3643
+ var AGENT_PROFILE_LIST_INPUT_SCHEMA, AGENT_PROFILE_APPLY_INPUT_SCHEMA, AGENT_PROFILE_DELETE_INPUT_SCHEMA, HOST_ACTION_AGENT_PROFILE_DESCRIPTORS;
3644
+ var init_host_action_agent_profile_descriptors = __esm({
3645
+ "../../packages/shared/src/environment/host-action-agent-profile-descriptors.ts"() {
3646
+ "use strict";
3647
+ init_superone_tool_descriptions();
3648
+ AGENT_PROFILE_LIST_INPUT_SCHEMA = {
3649
+ type: "object",
3650
+ properties: {
3651
+ id: {
3652
+ type: "string",
3653
+ description: "Profile id. Returns full instructions, launch defaults, and the harness model options."
3654
+ }
3655
+ },
3656
+ additionalProperties: false
3657
+ };
3658
+ AGENT_PROFILE_APPLY_INPUT_SCHEMA = {
3659
+ type: "object",
3660
+ properties: {
3661
+ action: { type: "string", enum: ["create", "update"], description: "create a new profile, or update an existing one." },
3662
+ id: { type: "string", description: "Required for update. Profile id from agent_profile_list." },
3663
+ harnessId: {
3664
+ type: "string",
3665
+ enum: ["claude", "codex", "acp", "opencode", "cursor", "dsh"],
3666
+ description: "Required for create; fixed afterwards."
3667
+ },
3668
+ name: { type: "string", description: "Display name and @-mention label. Required for create." },
3669
+ description: { type: "string", description: "What this agent is for, read by other agents choosing a delegate. Required for create." },
3670
+ instructions: { type: "string", description: "Added to the agent's system prompt on every launch." },
3671
+ model: { type: "string", description: "Base model id from the harness catalog. Omit to follow the user's default." },
3672
+ effort: { type: "string", description: "Effort level the model supports." },
3673
+ permissionMode: {
3674
+ type: "string",
3675
+ description: "Permission mode new sessions start in; one of the harness's modes (agent_profile_list({ id }) lists them). Omit to follow the user's default."
3676
+ },
3677
+ options: {
3678
+ type: "object",
3679
+ description: "The harness's own settings; agent_profile_list({ id }) lists which ones its models accept. null clears one.",
3680
+ properties: {
3681
+ ultracode: { type: ["boolean", "null"], description: "Claude: Ultracode, on models with xhigh effort." },
3682
+ fastMode: { type: ["boolean", "null"], description: "Codex: the model's Fast service tier." },
3683
+ contextWindow: { type: ["integer", "null"], description: "ACP: one of the model's context windows, in tokens." },
3684
+ mode: { type: ["string", "null"], description: "ACP: a session mode the agent lists." },
3685
+ agent: { type: ["string", "null"], description: "OpenCode: native agent id." },
3686
+ agentPreset: { type: ["string", "null"], description: "DeepSeek: agent preset id." },
3687
+ modelParams: {
3688
+ type: ["object", "null"],
3689
+ additionalProperties: { type: "string" },
3690
+ description: "Cursor: model parameter values by parameter id."
3691
+ }
3692
+ },
3693
+ additionalProperties: false
3694
+ }
3695
+ },
3696
+ required: ["action"],
3697
+ additionalProperties: false
3698
+ };
3699
+ AGENT_PROFILE_DELETE_INPUT_SCHEMA = {
3700
+ type: "object",
3701
+ properties: {
3702
+ ids: {
3703
+ type: "array",
3704
+ items: { type: "string" },
3705
+ minItems: 1,
3706
+ maxItems: 20,
3707
+ description: "Profile ids from agent_profile_list."
3708
+ }
3709
+ },
3710
+ required: ["ids"],
3711
+ additionalProperties: false
3712
+ };
3713
+ HOST_ACTION_AGENT_PROFILE_DESCRIPTORS = [
3714
+ { name: "agent_profile_list", description: AGENT_PROFILE_LIST_DESCRIPTION, inputSchema: AGENT_PROFILE_LIST_INPUT_SCHEMA },
3715
+ { name: "agent_profile_apply", description: AGENT_PROFILE_APPLY_DESCRIPTION, inputSchema: AGENT_PROFILE_APPLY_INPUT_SCHEMA },
3716
+ { name: "agent_profile_delete", description: AGENT_PROFILE_DELETE_DESCRIPTION, inputSchema: AGENT_PROFILE_DELETE_INPUT_SCHEMA }
3717
+ ];
3718
+ }
3719
+ });
3720
+
3619
3721
  // ../../packages/shared/src/environment/host-action-device-descriptors.ts
3620
3722
  var HOST_ACTION_DEVICE_DESCRIPTORS;
3621
3723
  var init_host_action_device_descriptors = __esm({
@@ -4468,6 +4570,79 @@ var init_host_action_terminal_descriptors = __esm({
4468
4570
  }
4469
4571
  });
4470
4572
 
4573
+ // ../../packages/shared/src/layout-control.ts
4574
+ var LAYOUT_ACT_ACTIONS, LAYOUT_DIRECTIONS, LAYOUT_CHAT_MODES, LAYOUT_CHAT_POSITIONS;
4575
+ var init_layout_control = __esm({
4576
+ "../../packages/shared/src/layout-control.ts"() {
4577
+ "use strict";
4578
+ LAYOUT_ACT_ACTIONS = [
4579
+ "open_file",
4580
+ "focus_tab",
4581
+ "close_tab",
4582
+ "move_tab",
4583
+ "resize_group",
4584
+ "show_panel",
4585
+ "hide_panel",
4586
+ "maximize_panel",
4587
+ "restore_panel",
4588
+ "panel_side",
4589
+ "show_sidebar",
4590
+ "hide_sidebar",
4591
+ "resize_sidebar",
4592
+ "resize_panel",
4593
+ "chat_mode",
4594
+ "show_terminal",
4595
+ "hide_terminal",
4596
+ "split_session",
4597
+ "close_split"
4598
+ ];
4599
+ LAYOUT_DIRECTIONS = ["right", "down", "left", "up", "into"];
4600
+ LAYOUT_CHAT_MODES = ["docked", "floating", "icon"];
4601
+ LAYOUT_CHAT_POSITIONS = ["top-left", "top", "top-right", "right", "bottom-right", "bottom", "bottom-left", "left"];
4602
+ }
4603
+ });
4604
+
4605
+ // ../../packages/shared/src/environment/host-action-layout-descriptors.ts
4606
+ var HOST_ACTION_LAYOUT_DESCRIPTORS;
4607
+ var init_host_action_layout_descriptors = __esm({
4608
+ "../../packages/shared/src/environment/host-action-layout-descriptors.ts"() {
4609
+ "use strict";
4610
+ init_layout_control();
4611
+ init_superone_tool_descriptions();
4612
+ HOST_ACTION_LAYOUT_DESCRIPTORS = [
4613
+ {
4614
+ name: "layout_snapshot",
4615
+ description: LAYOUT_SNAPSHOT_DESCRIPTION,
4616
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
4617
+ },
4618
+ {
4619
+ name: "layout_act",
4620
+ description: LAYOUT_ACT_DESCRIPTION,
4621
+ inputSchema: {
4622
+ type: "object",
4623
+ properties: {
4624
+ action: { type: "string", enum: [...LAYOUT_ACT_ACTIONS] },
4625
+ path: { type: "string", description: LAYOUT_ACT_PATH_DESCRIPTION },
4626
+ line: { type: "integer", minimum: 1, description: LAYOUT_ACT_LINE_DESCRIPTION },
4627
+ tab: { type: "string", description: LAYOUT_ACT_TAB_DESCRIPTION },
4628
+ group: { type: "integer", minimum: 0, description: LAYOUT_ACT_GROUP_DESCRIPTION },
4629
+ direction: { type: "string", enum: [...LAYOUT_DIRECTIONS], description: LAYOUT_ACT_DIRECTION_DESCRIPTION },
4630
+ index: { type: "integer", minimum: 0, description: LAYOUT_ACT_INDEX_DESCRIPTION },
4631
+ side: { type: "string", enum: ["left", "right"], description: "panel_side." },
4632
+ sessionId: { type: "string", description: LAYOUT_ACT_SESSION_DESCRIPTION },
4633
+ width: { type: "integer", minimum: 1, description: LAYOUT_ACT_WIDTH_DESCRIPTION },
4634
+ height: { type: "integer", minimum: 1, description: LAYOUT_ACT_HEIGHT_DESCRIPTION },
4635
+ mode: { type: "string", enum: [...LAYOUT_CHAT_MODES], description: LAYOUT_ACT_MODE_DESCRIPTION },
4636
+ position: { type: "string", enum: [...LAYOUT_CHAT_POSITIONS], description: LAYOUT_ACT_POSITION_DESCRIPTION }
4637
+ },
4638
+ required: ["action"],
4639
+ additionalProperties: false
4640
+ }
4641
+ }
4642
+ ];
4643
+ }
4644
+ });
4645
+
4471
4646
  // ../../packages/shared/src/environment/host-action-superone-descriptors.ts
4472
4647
  var HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS;
4473
4648
  var init_host_action_superone_descriptors = __esm({
@@ -4483,9 +4658,11 @@ var init_host_action_superone_descriptors = __esm({
4483
4658
  init_host_action_computer_descriptors();
4484
4659
  init_host_action_widget_descriptors();
4485
4660
  init_host_action_automation_descriptors();
4661
+ init_host_action_agent_profile_descriptors();
4486
4662
  init_host_action_device_descriptors();
4487
4663
  init_host_action_browser_perf_descriptors();
4488
4664
  init_host_action_terminal_descriptors();
4665
+ init_host_action_layout_descriptors();
4489
4666
  HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS = [
4490
4667
  ...INTERACTION_MEMORY_TOOL_DEFS,
4491
4668
  ...HOST_ACTION_COLLABORATION_DESCRIPTORS,
@@ -4497,7 +4674,9 @@ var init_host_action_superone_descriptors = __esm({
4497
4674
  ...HOST_ACTION_COMPUTER_DESCRIPTORS,
4498
4675
  ...HOST_ACTION_WIDGET_DESCRIPTORS,
4499
4676
  ...HOST_ACTION_AUTOMATION_DESCRIPTORS,
4677
+ ...HOST_ACTION_AGENT_PROFILE_DESCRIPTORS,
4500
4678
  ...HOST_ACTION_TERMINAL_DESCRIPTORS,
4679
+ ...HOST_ACTION_LAYOUT_DESCRIPTORS,
4501
4680
  ...HOST_ACTION_DEVICE_DESCRIPTORS,
4502
4681
  ...HOST_ACTION_BROWSER_PERF_DESCRIPTORS
4503
4682
  ];
@@ -4508,6 +4687,9 @@ var init_host_action_superone_descriptors = __esm({
4508
4687
  function isNodeLocalSuperoneTool(name) {
4509
4688
  return NODE_LOCAL_SUPERONE_TOOL_NAMES.includes(name);
4510
4689
  }
4690
+ function isLocalSessionOnlySuperoneTool(name) {
4691
+ return LOCAL_SESSION_ONLY_SUPERONE_TOOL_NAMES.includes(name);
4692
+ }
4511
4693
  function classifyHostActionTool(name) {
4512
4694
  if (BROWSER_READ_NAMES.has(name)) {
4513
4695
  return {
@@ -4537,7 +4719,7 @@ function classifyHostActionTool(name) {
4537
4719
  function listHostActionSuperoneTools() {
4538
4720
  return HOST_ACTION_SUPERONE_TOOL_CATALOG;
4539
4721
  }
4540
- var BROWSER_READ_NAMES, BROWSER_ACT_PREFIX, COMPUTER_PREFIX, NODE_LOCAL_SUPERONE_TOOL_NAMES, SUPERONE_READ_NAMES, HOST_ACTION_BROWSER_TOOL_CATALOG, HOST_ACTION_SUPERONE_TOOL_CATALOG;
4722
+ var BROWSER_READ_NAMES, BROWSER_ACT_PREFIX, COMPUTER_PREFIX, NODE_LOCAL_SUPERONE_TOOL_NAMES, LOCAL_SESSION_ONLY_SUPERONE_TOOL_NAMES, SUPERONE_READ_NAMES, HOST_ACTION_BROWSER_TOOL_CATALOG, HOST_ACTION_SUPERONE_TOOL_CATALOG;
4541
4723
  var init_host_action_browser_catalog = __esm({
4542
4724
  "../../packages/shared/src/environment/host-action-browser-catalog.ts"() {
4543
4725
  "use strict";
@@ -4572,6 +4754,11 @@ var init_host_action_browser_catalog = __esm({
4572
4754
  "session_collab_retrieve",
4573
4755
  "session_suggest_task"
4574
4756
  ];
4757
+ LOCAL_SESSION_ONLY_SUPERONE_TOOL_NAMES = [
4758
+ "agent_profile_list",
4759
+ "agent_profile_apply",
4760
+ "agent_profile_delete"
4761
+ ];
4575
4762
  SUPERONE_READ_NAMES = /* @__PURE__ */ new Set([
4576
4763
  "read_manual",
4577
4764
  "config_read",
@@ -4580,6 +4767,7 @@ var init_host_action_browser_catalog = __esm({
4580
4767
  "widget_list_templates",
4581
4768
  "miniapp_list",
4582
4769
  "automation_list",
4770
+ "agent_profile_list",
4583
4771
  "device_list",
4584
4772
  "device_snapshot",
4585
4773
  "device_query",
@@ -4591,7 +4779,7 @@ var init_host_action_browser_catalog = __esm({
4591
4779
  "computer_query",
4592
4780
  "computer_wait_for"
4593
4781
  ]);
4594
- HOST_ACTION_BROWSER_TOOL_CATALOG = HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS.filter((d) => !isNodeLocalSuperoneTool(d.name)).map(
4782
+ HOST_ACTION_BROWSER_TOOL_CATALOG = HOST_ACTION_SUPERONE_TOOL_DESCRIPTORS.filter((d) => !isNodeLocalSuperoneTool(d.name) && !isLocalSessionOnlySuperoneTool(d.name)).map(
4595
4783
  (d) => {
4596
4784
  const cls = classifyHostActionTool(d.name);
4597
4785
  return {
@@ -9302,7 +9490,7 @@ function isStaticHostOwnedSuperoneToolQualified(qualifiedName) {
9302
9490
  function isNeverAutoAllowSuperoneBareName(bare) {
9303
9491
  return NEVER_AUTO_ALLOW_SUPERONE_BARE_NAMES.includes(bare);
9304
9492
  }
9305
- var MCP_SUPERONE_TOOL_PREFIX, BROWSER_PRIMITIVE_TOOL_NAMES, BROWSER_ACTION_TOOL_NAMES, BROWSER_LEGACY_TOOL_NAMES, BROWSER_COMPACT_TOOL_NAMES, BROWSER_TOOL_NAMES, COMPUTER_USE_TOOL_NAMES, DEVICE_AGENT_TOOL_NAMES, TERMINAL_TOOL_NAMES, BUILT_IN_SUPERONE_TOOL_NAMES, MINIAPP_LIST_BARE_NAME, MINIAPP_CALL_BARE_NAME, NEVER_AUTO_ALLOW_SUPERONE_BARE_NAMES, STATIC_HOST_OWNED_SUPERONE_QUALIFIED_TOOL_NAMES;
9493
+ var MCP_SUPERONE_TOOL_PREFIX, BROWSER_PRIMITIVE_TOOL_NAMES, BROWSER_ACTION_TOOL_NAMES, BROWSER_LEGACY_TOOL_NAMES, BROWSER_COMPACT_TOOL_NAMES, BROWSER_TOOL_NAMES, COMPUTER_USE_TOOL_NAMES, DEVICE_AGENT_TOOL_NAMES, TERMINAL_TOOL_NAMES, LAYOUT_TOOL_NAMES, BUILT_IN_SUPERONE_TOOL_NAMES, MINIAPP_LIST_BARE_NAME, MINIAPP_CALL_BARE_NAME, NEVER_AUTO_ALLOW_SUPERONE_BARE_NAMES, STATIC_HOST_OWNED_SUPERONE_QUALIFIED_TOOL_NAMES;
9306
9494
  var init_superone_host_owned_tools = __esm({
9307
9495
  "../../packages/shared/src/superone-host-owned-tools.ts"() {
9308
9496
  "use strict";
@@ -9398,6 +9586,7 @@ var init_superone_host_owned_tools = __esm({
9398
9586
  "terminal_act",
9399
9587
  "terminal_wait_for"
9400
9588
  ];
9589
+ LAYOUT_TOOL_NAMES = ["layout_snapshot", "layout_act"];
9401
9590
  BUILT_IN_SUPERONE_TOOL_NAMES = [
9402
9591
  "browser_memory_read",
9403
9592
  "browser_memory_write",
@@ -9438,9 +9627,13 @@ var init_superone_host_owned_tools = __esm({
9438
9627
  "automation_list",
9439
9628
  "automation_apply",
9440
9629
  "automation_delete",
9630
+ "agent_profile_list",
9631
+ "agent_profile_apply",
9632
+ "agent_profile_delete",
9441
9633
  ...BROWSER_TOOL_NAMES,
9442
9634
  ...DEVICE_AGENT_TOOL_NAMES,
9443
- ...TERMINAL_TOOL_NAMES
9635
+ ...TERMINAL_TOOL_NAMES,
9636
+ ...LAYOUT_TOOL_NAMES
9444
9637
  ];
9445
9638
  MINIAPP_LIST_BARE_NAME = "miniapp_list";
9446
9639
  MINIAPP_CALL_BARE_NAME = "miniapp_call";
@@ -9947,6 +10140,9 @@ var init_tool_ui = __esm({
9947
10140
  HIDDEN_SUPERONE_MCP_TOOLS = /* @__PURE__ */ new Set([
9948
10141
  "session_rename",
9949
10142
  "session_tag_list",
10143
+ // Layout changes show on screen; a row for them reads as plumbing.
10144
+ "layout_snapshot",
10145
+ "layout_act",
9950
10146
  "session_collab_list_agents",
9951
10147
  "session_list_agents",
9952
10148
  "miniapp_list"
@@ -11589,6 +11785,42 @@ var init_artifact_wakes = __esm({
11589
11785
  }
11590
11786
  });
11591
11787
 
11788
+ // ../../packages/runtime/src/session/input-admission.ts
11789
+ var InputAdmission;
11790
+ var init_input_admission = __esm({
11791
+ "../../packages/runtime/src/session/input-admission.ts"() {
11792
+ "use strict";
11793
+ InputAdmission = class {
11794
+ constructor(delivery) {
11795
+ this.delivery = delivery;
11796
+ this.promise = new Promise((resolve21, reject) => {
11797
+ this.resolve = resolve21;
11798
+ this.rejectPromise = reject;
11799
+ });
11800
+ }
11801
+ delivery;
11802
+ promise;
11803
+ resolve;
11804
+ rejectPromise;
11805
+ settled = false;
11806
+ accept() {
11807
+ if (this.settled) return;
11808
+ this.delivery.onInputAccepted();
11809
+ this.settled = true;
11810
+ this.resolve();
11811
+ }
11812
+ beforeInput() {
11813
+ this.delivery.beforeInput?.();
11814
+ }
11815
+ reject(error51) {
11816
+ if (this.settled) return;
11817
+ this.settled = true;
11818
+ this.rejectPromise(error51);
11819
+ }
11820
+ };
11821
+ }
11822
+ });
11823
+
11592
11824
  // ../../packages/shared/src/codex-accounts.ts
11593
11825
  function isCodexAccountProvider(id) {
11594
11826
  return !!id?.startsWith(CODEX_ACCOUNT_PREFIX);
@@ -12932,7 +13164,11 @@ function createNodeSessionEventMapper(ctx) {
12932
13164
  }
12933
13165
  const interruptedId = lastAssistantId ?? asString2(payload.messageId);
12934
13166
  if (interruptedId) {
12935
- push({ type: "message_interrupted", messageId: interruptedId });
13167
+ push({
13168
+ type: "message_interrupted",
13169
+ messageId: interruptedId,
13170
+ ...typeof payload.reason === "string" ? { reason: payload.reason } : {}
13171
+ });
12936
13172
  }
12937
13173
  lastAssistantId = null;
12938
13174
  push({ type: "status_change", status: "idle" });
@@ -15043,6 +15279,7 @@ var init_session_runtime = __esm({
15043
15279
  init_mcp_apps_index();
15044
15280
  init_attachment_state();
15045
15281
  init_artifact_wakes();
15282
+ init_input_admission();
15046
15283
  init_codex_accounts();
15047
15284
  init_session_send();
15048
15285
  init_send_failure();
@@ -15781,7 +16018,7 @@ var init_session_runtime = __esm({
15781
16018
  * Host-initiated turn without a control lease (collaboration initial task).
15782
16019
  * Still rejects closed/disposing sessions. Falls back to durable session settings.
15783
16020
  */
15784
- async sendWithoutLease(input) {
16021
+ async sendWithoutLease(input, delivery) {
15785
16022
  if (this.disposing) {
15786
16023
  throw Object.assign(new Error("runtime is shutting down"), { code: "failed_precondition" });
15787
16024
  }
@@ -15796,7 +16033,9 @@ var init_session_runtime = __esm({
15796
16033
  if (typeof stored === "string" && stored.trim()) return stored.trim();
15797
16034
  return stored ?? void 0;
15798
16035
  };
16036
+ const admission = delivery ? new InputAdmission(delivery) : void 0;
15799
16037
  const turnOpts = {
16038
+ inputAdmission: admission,
15800
16039
  text: input.text,
15801
16040
  requestId: input.requestId,
15802
16041
  model: pick4(input.model, session.model),
@@ -15825,12 +16064,15 @@ var init_session_runtime = __esm({
15825
16064
  turnOpts.turnKind = "steer";
15826
16065
  }
15827
16066
  this.beginTurn(session, turnOpts);
16067
+ if (admission) await admission.promise;
15828
16068
  return this.clone(session);
15829
16069
  }
15830
16070
  this.enqueueTurn(session, turnOpts);
16071
+ if (admission) await admission.promise;
15831
16072
  return this.clone(session);
15832
16073
  }
15833
16074
  this.beginTurn(session, turnOpts);
16075
+ if (admission) await admission.promise;
15834
16076
  return this.clone(session);
15835
16077
  }
15836
16078
  /**
@@ -16109,12 +16351,15 @@ var init_session_runtime = __esm({
16109
16351
  const requestId = opts.requestId;
16110
16352
  let started = false;
16111
16353
  const markStarted = () => {
16354
+ opts.inputAdmission?.accept();
16112
16355
  started = true;
16113
16356
  };
16357
+ let inputFailure = new Error("Harness did not accept notification input");
16114
16358
  const permissionMode = typeof opts.permissionMode === "string" && opts.permissionMode.trim() ? opts.permissionMode.trim() : void 0;
16115
16359
  const sandboxMode = typeof opts.sandboxMode === "string" && opts.sandboxMode.trim() ? opts.sandboxMode.trim() : void 0;
16116
16360
  try {
16117
16361
  const modelInput = mcpAppModelInput({ text: opts.text, images: opts.images?.map((image) => ({ ...image, name: image.name ?? "Attachment" })) }, this.mcpAppContextInput(session.sessionId));
16362
+ opts.inputAdmission?.beforeInput();
16118
16363
  const result3 = await this.turnRunner({
16119
16364
  session: this.clone(session),
16120
16365
  messageId: assistantId,
@@ -16144,7 +16389,7 @@ var init_session_runtime = __esm({
16144
16389
  this.persist(session);
16145
16390
  },
16146
16391
  onDelta: (delta) => {
16147
- if (delta) started = true;
16392
+ if (delta) markStarted();
16148
16393
  if (abort.signal.aborted) return;
16149
16394
  assistantText += delta;
16150
16395
  this.events.appendSession({
@@ -16155,13 +16400,13 @@ var init_session_runtime = __esm({
16155
16400
  });
16156
16401
  },
16157
16402
  onEvent: (event) => {
16158
- if (event.kind !== "status") started = true;
16403
+ if (event.kind !== "status") markStarted();
16159
16404
  this.projectOnEvent(session, event, abort.signal, requestId, (delta) => {
16160
16405
  assistantText += delta;
16161
16406
  });
16162
16407
  },
16163
16408
  onAgentEvent: (event) => {
16164
- if (isAgentOutputEvent(event)) started = true;
16409
+ if (isAgentOutputEvent(event)) markStarted();
16165
16410
  if (abort.signal.aborted) return;
16166
16411
  this.appendAgentEvent(session.sessionId, event, requestId);
16167
16412
  if (session.harnessId === "opencode" && event.type === "message_interrupted" && event.messageId === assistantId) abort.abort();
@@ -16187,6 +16432,8 @@ var init_session_runtime = __esm({
16187
16432
  onQuestion: (interaction) => (markStarted(), this.waitForQuestionDecision(session, interaction, abort.signal, requestId)),
16188
16433
  onPlan: (interaction) => (markStarted(), this.waitForPlanDecision(session, interaction, abort.signal, requestId))
16189
16434
  });
16435
+ if (result3.finalText) markStarted();
16436
+ if (opts.inputAdmission && !started) throw inputFailure;
16190
16437
  if (session.closed) {
16191
16438
  } else if (abort.signal.aborted) {
16192
16439
  session.status = "interrupted";
@@ -16228,6 +16475,7 @@ var init_session_runtime = __esm({
16228
16475
  }
16229
16476
  }
16230
16477
  } catch (err) {
16478
+ inputFailure = err;
16231
16479
  if (session.closed) {
16232
16480
  } else if (abort.signal.aborted) {
16233
16481
  session.status = "interrupted";
@@ -16261,6 +16509,7 @@ var init_session_runtime = __esm({
16261
16509
  }
16262
16510
  }
16263
16511
  } finally {
16512
+ if (!started) opts.inputAdmission?.reject(inputFailure);
16264
16513
  const sid = session.sessionId;
16265
16514
  const remainingAfter = Math.max(0, (this.activeTurnCounts.get(sid) ?? 1) - 1);
16266
16515
  if (remainingAfter <= 0) this.activeTurnCounts.delete(sid);
@@ -16294,6 +16543,7 @@ var init_session_runtime = __esm({
16294
16543
  } else if (session.closed || session.status === "interrupted" || session.status === "error") {
16295
16544
  const dropped = this.turnQueues.get(sid) ?? [];
16296
16545
  this.turnQueues.delete(sid);
16546
+ for (const item of dropped) item.inputAdmission?.reject(new Error(QUEUED_SEND_DROPPED));
16297
16547
  if (!session.closed) {
16298
16548
  const marked = dropped.filter((item) => this.markSendFailed(session, item.userBlockId, QUEUED_SEND_DROPPED));
16299
16549
  if (marked.length > 0) this.persist(session);
@@ -20706,6 +20956,521 @@ var init_session_provider_definitions = __esm({
20706
20956
  }
20707
20957
  });
20708
20958
 
20959
+ // ../../packages/shared/src/launch-options.ts
20960
+ var HARNESS_LAUNCH_OPTIONS;
20961
+ var init_launch_options = __esm({
20962
+ "../../packages/shared/src/launch-options.ts"() {
20963
+ "use strict";
20964
+ HARNESS_LAUNCH_OPTIONS = {
20965
+ claude: { permissionModes: ["default", "plan", "auto", "acceptEdits", "dontAsk", "bypassPermissions"], sandboxModes: ["off", "on", "auto"], defaultPermissionMode: "default" },
20966
+ codex: { permissionModes: ["default", "auto", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" },
20967
+ acp: { permissionModes: ["default", "plan", "auto", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" },
20968
+ // OpenCode selects native agents; permissions come from its own configuration.
20969
+ opencode: { permissionModes: [], sandboxModes: [], defaultPermissionMode: "default" },
20970
+ cursor: { permissionModes: ["agent", "plan", "bypassPermissions"], sandboxModes: ["off", "on"], defaultPermissionMode: "agent" },
20971
+ // Read-only first for display; dsh's own default preset is `workspace-write` (`default`).
20972
+ dsh: { permissionModes: ["plan", "default", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" }
20973
+ };
20974
+ }
20975
+ });
20976
+
20977
+ // ../../packages/shared/src/codex-fast-mode.ts
20978
+ function findCodexFastServiceTier(model) {
20979
+ return model?.serviceTiers?.find((tier) => tier.id === "fast" || tier.id === "priority" || tier.name.trim().toLowerCase() === "fast");
20980
+ }
20981
+ var init_codex_fast_mode = __esm({
20982
+ "../../packages/shared/src/codex-fast-mode.ts"() {
20983
+ "use strict";
20984
+ }
20985
+ });
20986
+
20987
+ // ../../packages/shared/src/model-option-params.ts
20988
+ function isEffortCatalogParam(param) {
20989
+ if (param.id === "thinking" || /^thinking$/i.test(param.displayName ?? "")) return false;
20990
+ return /^(effort|reasoning)$/i.test(param.id) || /effort|reasoning/i.test(param.displayName ?? "");
20991
+ }
20992
+ function findEffortCatalogParam(parameters) {
20993
+ const candidates = parameters.filter(isEffortCatalogParam);
20994
+ return candidates.find((param) => param.id === "effort") ?? candidates.find((param) => param.id === "reasoning") ?? candidates[0];
20995
+ }
20996
+ function isToggleCatalogParam(param) {
20997
+ const values = new Set(param.values.map((value) => value.value));
20998
+ return values.size === 2 && values.has("true") && values.has("false");
20999
+ }
21000
+ function normalizeCatalogEffortValue(raw) {
21001
+ const value = raw.trim().toLowerCase();
21002
+ if (EFFORT_VALUES.has(value)) return value;
21003
+ if (value === "extra high" || value === "extra_high" || value === "extra-high" || value === "ultrathink") return "xhigh";
21004
+ if (value === "minimal" || value === "min") return "low";
21005
+ return null;
21006
+ }
21007
+ function parseCatalogContextWindow(raw) {
21008
+ if (!raw) return null;
21009
+ const match = /^(\d+(?:\.\d+)?)\s*([km])?$/i.exec(raw.trim());
21010
+ if (!match) return null;
21011
+ const amount = Number(match[1]);
21012
+ if (!Number.isFinite(amount) || amount <= 0) return null;
21013
+ const unit = match[2]?.toLowerCase();
21014
+ return Math.round(amount * (unit === "m" ? 1e6 : unit === "k" ? 1e3 : 1));
21015
+ }
21016
+ function firstParseableContextValue(values) {
21017
+ for (const item of values ?? []) {
21018
+ if (parseCatalogContextWindow(item.value) != null) return item.value;
21019
+ }
21020
+ return null;
21021
+ }
21022
+ function defaultCatalogContextWindow(modelId) {
21023
+ return modelId && GPT_5_6_MODEL_RE.test(modelId) ? CODEX_GPT_5_6_CONTEXT_WINDOW : DEFAULT_CONTEXT_WINDOW;
21024
+ }
21025
+ function selectedCatalogContextWindow(selected, model) {
21026
+ const parsed = parseCatalogContextWindow(selected);
21027
+ if (parsed != null) return parsed;
21028
+ return parseCatalogContextWindow(
21029
+ firstParseableContextValue(model?.parameters?.find((param) => param.id === "context")?.values)
21030
+ );
21031
+ }
21032
+ function resolveCatalogContextWindow(selected, model, modelId) {
21033
+ return selectedCatalogContextWindow(selected, model) ?? defaultCatalogContextWindow(modelId);
21034
+ }
21035
+ function catalogParamLabel(param) {
21036
+ if (param.displayName?.trim()) return param.displayName.trim();
21037
+ if (param.id === "optimize_for") return "Optimize for";
21038
+ if (param.id === "context") return "Context";
21039
+ if (param.id === "thinking") return "Thinking";
21040
+ if (param.id === "fast") return "Fast";
21041
+ if (param.id === "effort") return "Effort";
21042
+ if (param.id === "reasoning") return "Reasoning";
21043
+ return param.id.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
21044
+ }
21045
+ function catalogParamValueLabel(value, displayName) {
21046
+ if (displayName?.trim()) return displayName.trim();
21047
+ if (value === "extra-high" || value === "extra_high") return "Extra High";
21048
+ if (value === "1m") return "1M";
21049
+ if (value === "300k") return "300K";
21050
+ if (value === "272k") return "272K";
21051
+ if (value === "200k") return "200K";
21052
+ return value.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
21053
+ }
21054
+ function defaultCatalogParams(model) {
21055
+ const out = {};
21056
+ for (const param of model?.parameters ?? []) {
21057
+ if (!param.values.length) continue;
21058
+ if (param.id === "optimize_for") {
21059
+ out[param.id] = param.values.find((value) => value.value === "balanced")?.value ?? param.values[0].value;
21060
+ continue;
21061
+ }
21062
+ if (isEffortCatalogParam(param)) {
21063
+ out[param.id] = param.values.find((value) => normalizeCatalogEffortValue(value.value) === "medium")?.value ?? param.values.find((value) => normalizeCatalogEffortValue(value.value) != null)?.value ?? param.values[0].value;
21064
+ continue;
21065
+ }
21066
+ if (isToggleCatalogParam(param)) {
21067
+ out[param.id] = param.values.find((value) => value.value === "false")?.value ?? param.values[0].value;
21068
+ continue;
21069
+ }
21070
+ if (param.id === "context") {
21071
+ out[param.id] = firstParseableContextValue(param.values) ?? param.values[0].value;
21072
+ continue;
21073
+ }
21074
+ out[param.id] = param.values[0].value;
21075
+ }
21076
+ return out;
21077
+ }
21078
+ function selectorCatalogParams(model, selected = {}) {
21079
+ const parameters = model?.parameters ?? [];
21080
+ const effortParam = findEffortCatalogParam(parameters);
21081
+ const defaults2 = defaultCatalogParams(model);
21082
+ return parameters.filter((param) => !isEffortCatalogParam(param) && param.id !== effortParam?.id).filter((param) => param.values.length > 0).map((param) => ({
21083
+ id: param.id,
21084
+ label: catalogParamLabel(param),
21085
+ kind: isToggleCatalogParam(param) ? "toggle" : "choice",
21086
+ values: param.values.map((value) => ({
21087
+ value: value.value,
21088
+ label: catalogParamValueLabel(value.value, value.displayName)
21089
+ })),
21090
+ selected: selected[param.id] ?? defaults2[param.id] ?? param.values[0].value
21091
+ }));
21092
+ }
21093
+ var EFFORT_VALUES, GPT_5_6_MODEL_RE;
21094
+ var init_model_option_params = __esm({
21095
+ "../../packages/shared/src/model-option-params.ts"() {
21096
+ "use strict";
21097
+ init_agent_types();
21098
+ EFFORT_VALUES = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
21099
+ GPT_5_6_MODEL_RE = /(^|[/-])gpt-5\.6(?:$|-)/i;
21100
+ }
21101
+ });
21102
+
21103
+ // ../../packages/shared/src/agent-profile-options.ts
21104
+ function isModelBoundOption(key) {
21105
+ return MODEL_BOUND.has(key);
21106
+ }
21107
+ function formatContextWindow(tokens2) {
21108
+ if (tokens2 >= 1e6 && tokens2 % 1e6 === 0) return `${tokens2 / 1e6}M`;
21109
+ if (tokens2 >= 1e3) return `${Math.round(tokens2 / 1e3)}K`;
21110
+ return String(tokens2);
21111
+ }
21112
+ function choicesFor(key, model, host) {
21113
+ switch (key) {
21114
+ case "ultracode":
21115
+ return model.supportedEffortLevels?.includes("xhigh") ? { kind: "toggle" } : null;
21116
+ case "fastMode":
21117
+ return findCodexFastServiceTier(model) ? { kind: "toggle" } : null;
21118
+ case "contextWindow": {
21119
+ const windows = model.contextWindows ?? [];
21120
+ return windows.length > 1 ? { kind: "choice", values: windows.map((value) => ({ value, label: formatContextWindow(value) })) } : null;
21121
+ }
21122
+ case "modelParams": {
21123
+ const params = selectorCatalogParams(model);
21124
+ return params.length ? { kind: "params", params } : null;
21125
+ }
21126
+ case "mode":
21127
+ case "agent":
21128
+ case "agentPreset": {
21129
+ const list = host.lists?.[key];
21130
+ if (!list) return { kind: "unlisted" };
21131
+ return list.length ? { kind: "choice", values: [...list] } : null;
21132
+ }
21133
+ }
21134
+ }
21135
+ function agentProfileOptionChoices(harnessId, models, host = {}) {
21136
+ const out = {};
21137
+ for (const key of HARNESS_PROFILE_OPTIONS[harnessId]) {
21138
+ if (host.appliable && !host.appliable.includes(key)) {
21139
+ out[key] = null;
21140
+ continue;
21141
+ }
21142
+ if (!isModelBoundOption(key)) {
21143
+ out[key] = choicesFor(key, { id: "" }, host);
21144
+ continue;
21145
+ }
21146
+ out[key] = models.map((model) => choicesFor(key, model, host)).find((choice) => choice !== null) ?? null;
21147
+ }
21148
+ return out;
21149
+ }
21150
+ function optionValueError(key, value, choices) {
21151
+ if (choices.kind === "toggle" || choices.kind === "unlisted") return null;
21152
+ if (choices.kind === "choice") {
21153
+ if (choices.values.some((choice) => choice.value === value)) return null;
21154
+ return `options.${key} ${JSON.stringify(value)} is not one of: ${choices.values.map((choice) => JSON.stringify(choice.value)).join(", ")}.`;
21155
+ }
21156
+ const params = value;
21157
+ for (const [id, raw] of Object.entries(params)) {
21158
+ const param = choices.params.find((candidate) => candidate.id === id);
21159
+ if (!param) return `options.modelParams.${id} is not a parameter of this model (parameters: ${choices.params.map((p3) => p3.id).join(", ")}).`;
21160
+ if (!param.values.some((candidate) => candidate.value === raw)) {
21161
+ return `options.modelParams.${id} "${raw}" is not one of: ${param.values.map((candidate) => candidate.value).join(", ")}.`;
21162
+ }
21163
+ }
21164
+ return null;
21165
+ }
21166
+ function optionShapeError(key, value) {
21167
+ const kind = OPTION_KINDS[key];
21168
+ if (!kind) return `profile.runtime.options has unknown field: ${key}.`;
21169
+ const label = `profile.runtime.options.${key}`;
21170
+ switch (kind) {
21171
+ case "boolean":
21172
+ return typeof value === "boolean" ? null : `${label} must be a boolean.`;
21173
+ case "number":
21174
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? null : `${label} must be a positive integer.`;
21175
+ case "string":
21176
+ return typeof value === "string" && value.trim() ? null : `${label} must be a non-empty string.`;
21177
+ case "params": {
21178
+ const ok = !!value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length > 0 && Object.values(value).every((entry3) => typeof entry3 === "string" && entry3.length > 0);
21179
+ return ok ? null : `${label} must map parameter ids to non-empty string values.`;
21180
+ }
21181
+ }
21182
+ }
21183
+ var HARNESS_PROFILE_OPTIONS, MODEL_BOUND, MODEL_REQUIRED_OPTIONS, OPTION_KINDS, AGENT_PROFILE_OPTION_KEYS;
21184
+ var init_agent_profile_options = __esm({
21185
+ "../../packages/shared/src/agent-profile-options.ts"() {
21186
+ "use strict";
21187
+ init_codex_fast_mode();
21188
+ init_model_option_params();
21189
+ HARNESS_PROFILE_OPTIONS = {
21190
+ claude: ["ultracode"],
21191
+ codex: ["fastMode"],
21192
+ acp: ["contextWindow", "mode"],
21193
+ opencode: ["agent"],
21194
+ cursor: ["modelParams"],
21195
+ dsh: ["agentPreset"]
21196
+ };
21197
+ MODEL_BOUND = /* @__PURE__ */ new Set(["ultracode", "fastMode", "contextWindow", "modelParams"]);
21198
+ MODEL_REQUIRED_OPTIONS = /* @__PURE__ */ new Set(["contextWindow", "modelParams"]);
21199
+ OPTION_KINDS = {
21200
+ ultracode: "boolean",
21201
+ fastMode: "boolean",
21202
+ contextWindow: "number",
21203
+ mode: "string",
21204
+ agent: "string",
21205
+ agentPreset: "string",
21206
+ modelParams: "params"
21207
+ };
21208
+ AGENT_PROFILE_OPTION_KEYS = Object.keys(OPTION_KINDS);
21209
+ }
21210
+ });
21211
+
21212
+ // ../../packages/shared/src/agent-profile.ts
21213
+ function isRecord2(value) {
21214
+ return !!value && typeof value === "object" && !Array.isArray(value);
21215
+ }
21216
+ function nonEmpty(value) {
21217
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
21218
+ }
21219
+ function parseOptions2(raw, harnessId) {
21220
+ if (raw === void 0) return { ok: true, value: void 0 };
21221
+ if (!isRecord2(raw)) return { ok: false, error: "profile.runtime.options must be an object." };
21222
+ const allowed = harnessId ? HARNESS_PROFILE_OPTIONS[harnessId] : void 0;
21223
+ const options = {};
21224
+ for (const [key, value] of Object.entries(raw)) {
21225
+ const shape = optionShapeError(key, value);
21226
+ if (shape) return { ok: false, error: shape };
21227
+ if (allowed && !allowed.includes(key)) {
21228
+ return { ok: false, error: `profile.runtime.options.${key} is not a ${harnessId} setting (${harnessId} has: ${allowed.join(", ") || "none"}).` };
21229
+ }
21230
+ options[key] = typeof value === "string" ? value.trim() : value;
21231
+ }
21232
+ return { ok: true, value: Object.keys(options).length ? options : void 0 };
21233
+ }
21234
+ function parseRuntime(raw, harnessId) {
21235
+ if (raw === void 0) return { ok: true, value: void 0 };
21236
+ if (!isRecord2(raw)) return { ok: false, error: "profile.runtime must be an object." };
21237
+ const unknown2 = Object.keys(raw).filter((key) => !["model", "effort", "options", "permissionMode"].includes(key));
21238
+ if (unknown2.length) return { ok: false, error: `profile.runtime has unknown field(s): ${unknown2.join(", ")}.` };
21239
+ const runtime = {};
21240
+ if (raw.model !== void 0) {
21241
+ const model = nonEmpty(raw.model);
21242
+ if (!model) return { ok: false, error: "profile.runtime.model must be a non-empty string." };
21243
+ runtime.model = model;
21244
+ }
21245
+ if (raw.effort !== void 0) {
21246
+ const effort = nonEmpty(raw.effort);
21247
+ if (!effort) return { ok: false, error: "profile.runtime.effort must be a non-empty string." };
21248
+ runtime.effort = effort;
21249
+ }
21250
+ if (raw.permissionMode !== void 0) {
21251
+ const mode = nonEmpty(raw.permissionMode);
21252
+ if (!mode) return { ok: false, error: "profile.runtime.permissionMode must be a non-empty string." };
21253
+ if (harnessId) {
21254
+ const offered = HARNESS_LAUNCH_OPTIONS[harnessId].permissionModes;
21255
+ if (!offered.includes(mode)) {
21256
+ return {
21257
+ ok: false,
21258
+ error: offered.length ? `profile.runtime.permissionMode "${mode}" is not a ${harnessId} mode (${harnessId} has: ${offered.join(", ")}).` : `profile.runtime.permissionMode is not supported by ${harnessId}: it runs its own permission configuration.`
21259
+ };
21260
+ }
21261
+ }
21262
+ runtime.permissionMode = mode;
21263
+ }
21264
+ const options = parseOptions2(raw.options, harnessId);
21265
+ if (!options.ok) return options;
21266
+ if (options.value) {
21267
+ const needsModel = Object.keys(options.value).find((key) => MODEL_REQUIRED_OPTIONS.has(key));
21268
+ if (needsModel && !runtime.model) return { ok: false, error: `profile.runtime.options.${needsModel} requires profile.runtime.model.` };
21269
+ runtime.options = options.value;
21270
+ }
21271
+ return { ok: true, value: Object.keys(runtime).length ? runtime : void 0 };
21272
+ }
21273
+ function parseAgentProfileSpec(raw, harnessId) {
21274
+ if (!isRecord2(raw)) return { ok: false, error: "profile must be an object." };
21275
+ if (raw.version !== AGENT_PROFILE_VERSION) {
21276
+ return { ok: false, error: `profile.version must be ${AGENT_PROFILE_VERSION}.` };
21277
+ }
21278
+ const unknown2 = Object.keys(raw).filter((key) => !["version", "identity", "instructions", "runtime"].includes(key));
21279
+ if (unknown2.length) return { ok: false, error: `profile has unknown field(s): ${unknown2.join(", ")}.` };
21280
+ const identity = isRecord2(raw.identity) ? raw.identity : null;
21281
+ const name = nonEmpty(identity?.name);
21282
+ if (!name) return { ok: false, error: "profile.identity.name must be a non-empty string." };
21283
+ if (name.length > AGENT_PROFILE_NAME_MAX) {
21284
+ return { ok: false, error: `profile.identity.name must be at most ${AGENT_PROFILE_NAME_MAX} characters.` };
21285
+ }
21286
+ const description = nonEmpty(identity?.description);
21287
+ if (!description) return { ok: false, error: "profile.identity.description must be a non-empty string." };
21288
+ if (description.length > AGENT_PROFILE_DESCRIPTION_MAX) {
21289
+ return { ok: false, error: `profile.identity.description must be at most ${AGENT_PROFILE_DESCRIPTION_MAX} characters.` };
21290
+ }
21291
+ let instructions;
21292
+ if (raw.instructions !== void 0) {
21293
+ if (typeof raw.instructions !== "string") return { ok: false, error: "profile.instructions must be a string." };
21294
+ instructions = raw.instructions.trim() || void 0;
21295
+ if (instructions && instructions.length > AGENT_PROFILE_INSTRUCTIONS_MAX) {
21296
+ return { ok: false, error: `profile.instructions must be at most ${AGENT_PROFILE_INSTRUCTIONS_MAX} characters.` };
21297
+ }
21298
+ }
21299
+ const runtime = parseRuntime(raw.runtime, harnessId);
21300
+ if (!runtime.ok) return runtime;
21301
+ return {
21302
+ ok: true,
21303
+ value: {
21304
+ version: AGENT_PROFILE_VERSION,
21305
+ identity: { name, description },
21306
+ ...instructions ? { instructions } : {},
21307
+ ...runtime.value ? { runtime: runtime.value } : {}
21308
+ }
21309
+ };
21310
+ }
21311
+ function readAgentProfile(config2) {
21312
+ if (!isRecord2(config2) || config2.profile === void 0) return null;
21313
+ const parsed = parseAgentProfileSpec(config2.profile);
21314
+ return parsed.ok ? parsed.value : null;
21315
+ }
21316
+ function providerLaunchRuntime(config2) {
21317
+ const profile = readAgentProfile(config2);
21318
+ if (profile) return profile.runtime;
21319
+ if (!isRecord2(config2)) return void 0;
21320
+ const model = nonEmpty(config2.model);
21321
+ const effort = nonEmpty(config2.effort) ?? nonEmpty(config2.reasoningEffort);
21322
+ const runtime = {
21323
+ ...model ? { model } : {},
21324
+ ...effort ? { effort } : {},
21325
+ ...typeof config2.fastMode === "boolean" ? { options: { fastMode: config2.fastMode } } : {}
21326
+ };
21327
+ return Object.keys(runtime).length ? runtime : void 0;
21328
+ }
21329
+ function composeSystemPromptAppend(...parts) {
21330
+ const text2 = parts.map((part) => part?.trim()).filter(Boolean).join("\n\n");
21331
+ return text2 || void 0;
21332
+ }
21333
+ function agentProfilePrompt(profile) {
21334
+ const { name, description } = profile.identity;
21335
+ return [
21336
+ "<superone-agent-profile>",
21337
+ `You are running as "${name}", an agent profile the user saved in SuperOne. What it is for: ${description}`,
21338
+ ...profile.instructions ? [
21339
+ "Follow the profile instructions below for this whole session.",
21340
+ "<instructions>",
21341
+ profile.instructions,
21342
+ "</instructions>"
21343
+ ] : [],
21344
+ "</superone-agent-profile>"
21345
+ ].join("\n");
21346
+ }
21347
+ function providerSystemPromptAppend(config2, protocol) {
21348
+ const profile = readAgentProfile(config2);
21349
+ return composeSystemPromptAppend(profile ? agentProfilePrompt(profile) : void 0, protocol);
21350
+ }
21351
+ function findModel(catalog, id) {
21352
+ return id ? catalog.models.find((model) => model.id === id) : void 0;
21353
+ }
21354
+ function modelEfforts(catalog, model) {
21355
+ if (model?.supportedEffortLevels) return [...model.supportedEffortLevels];
21356
+ if (model?.supportedReasoningEfforts) return model.supportedReasoningEfforts.map((effort) => effort.value);
21357
+ return [...catalog.efforts ?? []];
21358
+ }
21359
+ function validateAgentProfileRuntime(runtime, catalog, harness) {
21360
+ if (!runtime) return [];
21361
+ const optionKeys = Object.keys(runtime.options ?? {});
21362
+ const needsCatalog = !!runtime.model || !!runtime.effort || optionKeys.some(isModelBoundOption);
21363
+ if (needsCatalog && catalog.models.length === 0) {
21364
+ return [`${harness.name} has no model catalog yet. Open a ${harness.name} session once, or leave runtime out.`];
21365
+ }
21366
+ const errors = [];
21367
+ const model = findModel(catalog, runtime.model);
21368
+ if (runtime.model && !model) {
21369
+ const ids = catalog.models.map((option) => option.id);
21370
+ return [`runtime.model "${runtime.model}" is not in the ${harness.name} catalog. Available: ${ids.slice(0, 30).join(", ")}.`];
21371
+ }
21372
+ const label = model ? `${harness.name} model "${model.id}"` : harness.name;
21373
+ if (runtime.effort) {
21374
+ const efforts = model ? modelEfforts(catalog, model) : [...new Set(catalog.models.flatMap((option) => modelEfforts(catalog, option)))];
21375
+ if (!efforts.includes(runtime.effort)) {
21376
+ errors.push(efforts.length ? `runtime.effort "${runtime.effort}" is not supported by ${model ? label : `any ${harness.name} model`} (supported: ${efforts.join(", ")}).` : `runtime.effort is not supported by ${label}.`);
21377
+ }
21378
+ }
21379
+ const choices = agentProfileOptionChoices(harness.id, model ? [model] : catalog.models, catalog.host);
21380
+ for (const key of optionKeys) {
21381
+ const choice = choices[key];
21382
+ if (choice === void 0) {
21383
+ errors.push(`options.${key} is not a ${harness.name} setting.`);
21384
+ } else if (choice === null) {
21385
+ errors.push(`options.${key} is not supported by ${label}.`);
21386
+ } else if (choice.kind === "unlisted") {
21387
+ errors.push(`${harness.name} has not listed its ${key} values yet. Open a ${harness.name} session once, or leave options.${key} out.`);
21388
+ } else {
21389
+ const invalid11 = optionValueError(key, runtime.options[key], choice);
21390
+ if (invalid11) errors.push(invalid11);
21391
+ }
21392
+ }
21393
+ return errors;
21394
+ }
21395
+ function fallbackEffort(model, supported) {
21396
+ if (model?.defaultReasoningEffort && supported.includes(model.defaultReasoningEffort)) return model.defaultReasoningEffort;
21397
+ if (supported.includes("high")) return "high";
21398
+ if (supported.includes("medium")) return "medium";
21399
+ return supported[0];
21400
+ }
21401
+ function resolveAgentLaunchDefaults(input) {
21402
+ const { harnessId, catalog, base, profile } = input;
21403
+ const launch2 = input.launch ?? {};
21404
+ const appliable = catalog.host?.appliable;
21405
+ const uncatalogued = catalog.models.length === 0 || !!launch2.model && !findModel(catalog, launch2.model);
21406
+ const model = uncatalogued ? void 0 : findModel(catalog, launch2.model) ?? findModel(catalog, profile?.model) ?? findModel(catalog, base.model);
21407
+ const choices = agentProfileOptionChoices(harnessId, model ? [model] : [], catalog.host);
21408
+ const options = {};
21409
+ for (const key of HARNESS_PROFILE_OPTIONS[harnessId]) {
21410
+ if (launch2.options?.[key] !== void 0) {
21411
+ options[key] = launch2.options[key];
21412
+ continue;
21413
+ }
21414
+ const value = profile?.options?.[key] ?? base.options?.[key];
21415
+ if (value === void 0 || appliable && !appliable.includes(key)) continue;
21416
+ const choice = model || !isModelBoundOption(key) ? choices[key] : { kind: "unlisted" };
21417
+ if (choice && !optionValueError(key, value, choice)) options[key] = value;
21418
+ }
21419
+ const offeredModes = HARNESS_LAUNCH_OPTIONS[harnessId].permissionModes;
21420
+ const permissionMode = [launch2.permissionMode, profile?.permissionMode, base.permissionMode].find((mode) => mode && offeredModes.includes(mode));
21421
+ const result3 = (modelId, effort2) => ({
21422
+ ...modelId ? { model: modelId } : {},
21423
+ ...effort2 ? { effort: effort2 } : {},
21424
+ ...Object.keys(options).length ? { options } : {},
21425
+ ...permissionMode ? { permissionMode } : {}
21426
+ });
21427
+ if (uncatalogued) {
21428
+ return result3(launch2.model ?? profile?.model ?? base.model, launch2.effort ?? profile?.effort ?? base.effort);
21429
+ }
21430
+ const supported = modelEfforts(catalog, model);
21431
+ const effort = launch2.effort ?? [profile?.effort, base.effort].find((value) => value && supported.includes(value)) ?? fallbackEffort(model, supported);
21432
+ return result3(model?.id ?? base.model, effort);
21433
+ }
21434
+ function agentLaunchErrors(harness, catalog, model, launch2) {
21435
+ const options = launch2.options && Object.keys(launch2.options).length ? launch2.options : void 0;
21436
+ if (!model || !findModel(catalog, model) || !launch2.effort && !options) return [];
21437
+ return validateAgentProfileRuntime({
21438
+ model,
21439
+ ...launch2.effort ? { effort: launch2.effort } : {},
21440
+ ...options ? { options } : {}
21441
+ }, catalog, harness).map((message) => message.replace(/^runtime\./, "config.").replace(/^options\.fastMode/, "config.fastMode").replace(/^options\./, "config.options."));
21442
+ }
21443
+ function launchConfigFromDefaults(defaults2) {
21444
+ const { fastMode, ...options } = defaults2.options ?? {};
21445
+ return {
21446
+ ...defaults2.model ? { model: defaults2.model } : {},
21447
+ ...defaults2.effort ? { effort: defaults2.effort } : {},
21448
+ ...fastMode !== void 0 ? { fastMode } : {},
21449
+ ...Object.keys(options).length ? { options } : {},
21450
+ ...defaults2.permissionMode ? { permissionMode: defaults2.permissionMode } : {}
21451
+ };
21452
+ }
21453
+ function launchDefaultsFromConfig(config2) {
21454
+ const options = { ...config2?.options, ...typeof config2?.fastMode === "boolean" ? { fastMode: config2.fastMode } : {} };
21455
+ return {
21456
+ ...config2?.model ? { model: config2.model } : {},
21457
+ ...config2?.effort ? { effort: config2.effort } : {},
21458
+ ...Object.keys(options).length ? { options } : {}
21459
+ };
21460
+ }
21461
+ var AGENT_PROFILE_VERSION, AGENT_PROFILE_NAME_MAX, AGENT_PROFILE_DESCRIPTION_MAX, AGENT_PROFILE_INSTRUCTIONS_MAX;
21462
+ var init_agent_profile = __esm({
21463
+ "../../packages/shared/src/agent-profile.ts"() {
21464
+ "use strict";
21465
+ init_launch_options();
21466
+ init_agent_profile_options();
21467
+ AGENT_PROFILE_VERSION = 1;
21468
+ AGENT_PROFILE_NAME_MAX = 60;
21469
+ AGENT_PROFILE_DESCRIPTION_MAX = 500;
21470
+ AGENT_PROFILE_INSTRUCTIONS_MAX = 2e4;
21471
+ }
21472
+ });
21473
+
20709
21474
  // ../../packages/runtime/src/session/session-provider-store.ts
20710
21475
  import { randomUUID as randomUUID5 } from "node:crypto";
20711
21476
  function assertHarnessId(raw) {
@@ -20714,12 +21479,25 @@ function assertHarnessId(raw) {
20714
21479
  }
20715
21480
  return raw;
20716
21481
  }
20717
- function normalizeConfig(config2) {
21482
+ function normalizeConfig(harnessId, config2) {
20718
21483
  if (config2 === void 0 || config2 === null) return {};
20719
21484
  if (typeof config2 !== "object" || Array.isArray(config2)) {
20720
21485
  throw Object.assign(new Error("config must be an object"), { code: "invalid_argument" });
20721
21486
  }
20722
- return config2;
21487
+ const profile = config2.profile;
21488
+ if (profile === void 0) return config2;
21489
+ const parsed = parseAgentProfileSpec(profile, harnessId);
21490
+ if (!parsed.ok) throw Object.assign(new Error(parsed.error), { code: "invalid_argument" });
21491
+ return { ...config2, profile: parsed.value };
21492
+ }
21493
+ function hasProfile(config2) {
21494
+ return !!config2 && typeof config2 === "object" && config2.profile !== void 0;
21495
+ }
21496
+ function profileWriteRefused() {
21497
+ return Object.assign(
21498
+ new Error("Agent profiles change only through agent_profile_apply / agent_profile_delete, which ask the user first."),
21499
+ { code: "failed_precondition" }
21500
+ );
20723
21501
  }
20724
21502
  function rowToProvider(row2) {
20725
21503
  let config2 = {};
@@ -20776,9 +21554,12 @@ function settingsFromSessionProviderConfig(config2) {
20776
21554
  const v3 = c[key];
20777
21555
  return typeof v3 === "string" && v3.trim() ? v3.trim() : void 0;
20778
21556
  };
21557
+ const runtime = providerLaunchRuntime(config2);
21558
+ const model = runtime?.model;
21559
+ const effort = runtime?.effort;
20779
21560
  return {
20780
- ...str5("model") ? { model: str5("model") } : {},
20781
- ...str5("effort") || str5("reasoningEffort") ? { effort: str5("effort") ?? str5("reasoningEffort") } : {},
21561
+ ...model ? { model } : {},
21562
+ ...effort ? { effort } : {},
20782
21563
  ...str5("permissionMode") ? { permissionMode: str5("permissionMode") } : {},
20783
21564
  ...str5("sandboxMode") ? { sandboxMode: str5("sandboxMode") } : {}
20784
21565
  };
@@ -20786,7 +21567,7 @@ function settingsFromSessionProviderConfig(config2) {
20786
21567
  function createSessionProviderStore(db, options = {}) {
20787
21568
  ensureSessionProvidersTable(db);
20788
21569
  const validConfig = (harnessId, config2) => {
20789
- const normalized = normalizeConfig(config2);
21570
+ const normalized = normalizeConfig(harnessId, config2);
20790
21571
  if (!options.validateConfig) return normalized;
20791
21572
  try {
20792
21573
  return options.validateConfig(harnessId, normalized);
@@ -20819,7 +21600,7 @@ function createSessionProviderStore(db, options = {}) {
20819
21600
  }
20820
21601
  return p3;
20821
21602
  };
20822
- const create = (input) => {
21603
+ const insert = (input) => {
20823
21604
  const harnessId = assertHarnessId(String(input.harnessId ?? ""));
20824
21605
  const name = String(input.name ?? "").trim();
20825
21606
  if (!name) {
@@ -20839,35 +21620,66 @@ function createSessionProviderStore(db, options = {}) {
20839
21620
  if (!created) throw Object.assign(new Error(`Failed to create provider: ${id}`), { code: "internal" });
20840
21621
  return created;
20841
21622
  };
20842
- const update = (id, patch) => {
21623
+ const existingCustom = (id, action) => {
20843
21624
  const existing = get3(id);
20844
21625
  if (!existing) {
21626
+ if (action === "delete") return null;
20845
21627
  throw Object.assign(new Error(`Provider not found: ${id}`), { code: "not_found" });
20846
21628
  }
20847
21629
  if (existing.isBase) {
20848
- throw Object.assign(new Error(`Cannot update base provider: ${id}`), {
21630
+ throw Object.assign(new Error(`Cannot ${action} base provider: ${id}`), {
20849
21631
  code: "failed_precondition"
20850
21632
  });
20851
21633
  }
21634
+ return existing;
21635
+ };
21636
+ const write = (existing, patch) => {
20852
21637
  const name = patch.name !== void 0 ? String(patch.name).trim() || existing.name : existing.name;
20853
21638
  const config2 = patch.config !== void 0 ? validConfig(existing.harnessId, patch.config) : existing.config;
20854
21639
  const now = (/* @__PURE__ */ new Date()).toISOString();
20855
21640
  db.prepare(
20856
21641
  "UPDATE session_providers SET name = ?, config_json = ?, updated_at = ? WHERE id = ?"
20857
- ).run(name, JSON.stringify(config2), now, id);
20858
- return get3(id);
21642
+ ).run(name, JSON.stringify(config2), now, existing.id);
21643
+ return get3(existing.id);
21644
+ };
21645
+ const remove = (id) => {
21646
+ db.prepare("DELETE FROM session_providers WHERE id = ?").run(id);
21647
+ };
21648
+ const assertUnchanged = (current, expected) => {
21649
+ if (current.name === expected.name && JSON.stringify(current.config) === JSON.stringify(expected.config)) return;
21650
+ throw Object.assign(new Error(`Agent profile ${current.id} changed while waiting for confirmation.`), { code: "aborted" });
21651
+ };
21652
+ const create = (input) => {
21653
+ if (hasProfile(input.config)) throw profileWriteRefused();
21654
+ return insert(input);
21655
+ };
21656
+ const update = (id, patch) => {
21657
+ const existing = existingCustom(id, "update");
21658
+ if (hasProfile(existing.config) || hasProfile(patch.config)) throw profileWriteRefused();
21659
+ return write(existing, patch);
20859
21660
  };
20860
21661
  const del = (id) => {
20861
- const existing = get3(id);
21662
+ const existing = existingCustom(id, "delete");
20862
21663
  if (!existing) return false;
20863
- if (existing.isBase) {
20864
- throw Object.assign(new Error(`Cannot delete base provider: ${id}`), {
20865
- code: "failed_precondition"
20866
- });
20867
- }
20868
- db.prepare("DELETE FROM session_providers WHERE id = ?").run(id);
21664
+ if (hasProfile(existing.config)) throw profileWriteRefused();
21665
+ remove(id);
20869
21666
  return true;
20870
21667
  };
21668
+ const profiles = {
21669
+ create: insert,
21670
+ update: (id, patch, expected) => {
21671
+ const existing = existingCustom(id, "update");
21672
+ assertUnchanged(existing, expected);
21673
+ return write(existing, patch);
21674
+ },
21675
+ delete: (id, expected) => {
21676
+ const existing = existingCustom(id, "delete");
21677
+ if (!existing) return false;
21678
+ assertUnchanged(existing, expected);
21679
+ remove(id);
21680
+ return true;
21681
+ }
21682
+ };
20871
21683
  return {
20872
21684
  list,
20873
21685
  listByHarness,
@@ -20875,7 +21687,8 @@ function createSessionProviderStore(db, options = {}) {
20875
21687
  getBase,
20876
21688
  create,
20877
21689
  update,
20878
- delete: del
21690
+ delete: del,
21691
+ profiles
20879
21692
  };
20880
21693
  }
20881
21694
  var VALID_HARNESS_IDS;
@@ -20883,6 +21696,7 @@ var init_session_provider_store = __esm({
20883
21696
  "../../packages/runtime/src/session/session-provider-store.ts"() {
20884
21697
  "use strict";
20885
21698
  init_session_provider_definitions();
21699
+ init_agent_profile();
20886
21700
  VALID_HARNESS_IDS = new Set(
20887
21701
  BASE_SESSION_PROVIDER_DEFINITIONS.map((provider2) => provider2.harnessId)
20888
21702
  );
@@ -30467,13 +31281,13 @@ var require_public_api = __commonJS({
30467
31281
  var identity = require_identity();
30468
31282
  var lineCounter = require_line_counter();
30469
31283
  var parser = require_parser();
30470
- function parseOptions2(options) {
31284
+ function parseOptions3(options) {
30471
31285
  const prettyErrors = options.prettyErrors !== false;
30472
31286
  const lineCounter$1 = options.lineCounter || prettyErrors && new lineCounter.LineCounter() || null;
30473
31287
  return { lineCounter: lineCounter$1, prettyErrors };
30474
31288
  }
30475
31289
  function parseAllDocuments(source, options = {}) {
30476
- const { lineCounter: lineCounter2, prettyErrors } = parseOptions2(options);
31290
+ const { lineCounter: lineCounter2, prettyErrors } = parseOptions3(options);
30477
31291
  const parser$1 = new parser.Parser(lineCounter2?.addNewLine);
30478
31292
  const composer$1 = new composer.Composer(options);
30479
31293
  const docs = Array.from(composer$1.compose(parser$1.parse(source)));
@@ -30487,7 +31301,7 @@ var require_public_api = __commonJS({
30487
31301
  return Object.assign([], { empty: true }, composer$1.streamInfo());
30488
31302
  }
30489
31303
  function parseDocument2(source, options = {}) {
30490
- const { lineCounter: lineCounter2, prettyErrors } = parseOptions2(options);
31304
+ const { lineCounter: lineCounter2, prettyErrors } = parseOptions3(options);
30491
31305
  const parser$1 = new parser.Parser(lineCounter2?.addNewLine);
30492
31306
  const composer$1 = new composer.Composer(options);
30493
31307
  let doc = null;
@@ -32110,8 +32924,9 @@ async function readClaudeRateLimits(credentialDir, opts = {}) {
32110
32924
  resp = await fetchUsage(refreshed);
32111
32925
  }
32112
32926
  if (resp.status === 429) {
32113
- log2.warn("[claude-usage] rate limited (429)");
32114
- return { fingerprint: claudeCredentialFingerprint(creds), rateLimitedForMs: retryAfterMs(resp) ?? 0 };
32927
+ const retryMs = retryAfterMs(resp);
32928
+ log2.warn("[claude-usage] rate limited (429) retryAfterMs=%s", retryMs ?? "none");
32929
+ return { fingerprint: claudeCredentialFingerprint(creds), rateLimitedForMs: retryMs ?? 0 };
32115
32930
  }
32116
32931
  const fingerprint = claudeCredentialFingerprint(creds);
32117
32932
  if (!resp.ok) return { fingerprint, error: `Claude usage request failed (HTTP ${resp.status}).` };
@@ -33069,9 +33884,9 @@ var init_server_request = __esm({
33069
33884
  });
33070
33885
 
33071
33886
  // ../../packages/codex/src/sandbox-policy.ts
33072
- import { isAbsolute as isAbsolute5, resolve as resolve13 } from "node:path";
33887
+ import { isAbsolute as isAbsolute6, resolve as resolve13 } from "node:path";
33073
33888
  function resolveCodexWritableRoots(cwd, additionalDirectories = []) {
33074
- const roots = [cwd, ...additionalDirectories].filter((dir) => dir.trim().length > 0).map((dir) => isAbsolute5(dir) ? resolve13(dir) : resolve13(cwd, dir));
33889
+ const roots = [cwd, ...additionalDirectories].filter((dir) => dir.trim().length > 0).map((dir) => isAbsolute6(dir) ? resolve13(dir) : resolve13(cwd, dir));
33075
33890
  return Array.from(new Set(roots));
33076
33891
  }
33077
33892
  function buildCodexWorkspaceWriteSandboxPolicy(cwd, additionalDirectories = [], options = {}) {
@@ -44722,7 +45537,7 @@ var init_managed_official = __esm({
44722
45537
  "../../packages/runtime/src/harness/managed-official.ts"() {
44723
45538
  "use strict";
44724
45539
  init_managed_layout();
44725
- OFFICIAL_CLAUDE_SDK_VERSION = "0.3.296";
45540
+ OFFICIAL_CLAUDE_SDK_VERSION = "0.3.300";
44726
45541
  OFFICIAL_CODEX_NPM_VERSION = "0.162.1";
44727
45542
  OFFICIAL_CODEX_PACKAGE = "@openai/codex";
44728
45543
  }
@@ -48651,7 +49466,7 @@ var init_runtime_ready = __esm({
48651
49466
 
48652
49467
  // ../../packages/runtime/src/harness/enable.ts
48653
49468
  import { accessSync as accessSync3, constants as constants3, existsSync as existsSync40, realpathSync as realpathSync10, statSync as statSync15 } from "node:fs";
48654
- import { isAbsolute as isAbsolute6, resolve as resolve16 } from "node:path";
49469
+ import { isAbsolute as isAbsolute7, resolve as resolve16 } from "node:path";
48655
49470
  async function enableHarness(manager, input, deps) {
48656
49471
  const id = input.harnessId;
48657
49472
  if (!isNodeHarnessId(id)) throw new Error(`unknown harnessId: ${id}`);
@@ -48866,7 +49681,7 @@ function enableAcpGrok(manager, opts) {
48866
49681
  });
48867
49682
  }
48868
49683
  function requireRegularReadableFile(path) {
48869
- if (!isAbsolute6(path)) {
49684
+ if (!isAbsolute7(path)) {
48870
49685
  throw new Error(`path must be absolute: ${path}`);
48871
49686
  }
48872
49687
  const abs = resolve16(path);
@@ -48878,7 +49693,7 @@ function requireRegularReadableFile(path) {
48878
49693
  }
48879
49694
  function resolveExternalCommand(explicit, searchNames, options = {}) {
48880
49695
  if (explicit) {
48881
- const abs = isAbsolute6(explicit) ? explicit : resolve16(explicit);
49696
+ const abs = isAbsolute7(explicit) ? explicit : resolve16(explicit);
48882
49697
  if (!existsSync40(abs)) return null;
48883
49698
  try {
48884
49699
  if (!statSync15(abs).isFile()) return null;
@@ -65868,17 +66683,17 @@ function isResponseMessage(value) {
65868
66683
  function isNotificationMessage(value) {
65869
66684
  return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
65870
66685
  }
65871
- function isRecord2(value) {
66686
+ function isRecord3(value) {
65872
66687
  return typeof value === "object" && value !== null;
65873
66688
  }
65874
66689
  function isJsonRpcEnvelope(value) {
65875
- return isRecord2(value) && value["jsonrpc"] === "2.0";
66690
+ return isRecord3(value) && value["jsonrpc"] === "2.0";
65876
66691
  }
65877
66692
  function isJsonRpcId(value) {
65878
66693
  return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
65879
66694
  }
65880
66695
  function isResponseShapedMessage(value) {
65881
- return isRecord2(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
66696
+ return isRecord3(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
65882
66697
  }
65883
66698
  function isResponseBatch(batch) {
65884
66699
  let hasValidCall = false;
@@ -65888,7 +66703,7 @@ function isResponseBatch(batch) {
65888
66703
  for (const entry3 of batch) {
65889
66704
  hasValidCall ||= isRequestMessage(entry3) || isNotificationMessage(entry3);
65890
66705
  hasValidResponse ||= isResponseMessage(entry3);
65891
- if (!isRecord2(entry3)) {
66706
+ if (!isRecord3(entry3)) {
65892
66707
  continue;
65893
66708
  }
65894
66709
  hasCallShape ||= "method" in entry3;
@@ -65903,13 +66718,13 @@ function isResponseBatch(batch) {
65903
66718
  return hasResponseShape && !hasCallShape;
65904
66719
  }
65905
66720
  function cancelRequestId(params) {
65906
- if (!isRecord2(params) || !isJsonRpcId(params["requestId"])) {
66721
+ if (!isRecord3(params) || !isJsonRpcId(params["requestId"])) {
65907
66722
  return void 0;
65908
66723
  }
65909
66724
  return params["requestId"];
65910
66725
  }
65911
66726
  function isErrorResponse(value) {
65912
- return isRecord2(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
66727
+ return isRecord3(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
65913
66728
  }
65914
66729
  function rejectedPromise(error51) {
65915
66730
  const promise2 = Promise.reject(error51);
@@ -66465,7 +67280,7 @@ var init_jsonrpc = __esm({
66465
67280
  if (this.abortController.signal.aborted) {
66466
67281
  return Promise.resolve();
66467
67282
  }
66468
- if (!isRecord2(message)) {
67283
+ if (!isRecord3(message)) {
66469
67284
  console.error("Invalid message", { message });
66470
67285
  return Promise.resolve();
66471
67286
  }
@@ -66868,7 +67683,7 @@ function ndJsonStream(output, input) {
66868
67683
  await writeJson(protocolErrorResponse(RequestError.parseError()));
66869
67684
  return;
66870
67685
  }
66871
- if (isRecord2(message) || Array.isArray(message)) {
67686
+ if (isRecord3(message) || Array.isArray(message)) {
66872
67687
  controller.enqueue(message);
66873
67688
  } else {
66874
67689
  await writeJson(protocolErrorResponse(RequestError.invalidRequest(message)));
@@ -82455,7 +83270,7 @@ var init_sqlite_backup = __esm({
82455
83270
  import { createHash as createHash16, randomUUID as randomUUID14 } from "node:crypto";
82456
83271
  import { existsSync as existsSync45, mkdirSync as mkdirSync22, readdirSync as readdirSync15, renameSync as renameSync8, rmSync as rmSync10, chmodSync as chmodSync2 } from "node:fs";
82457
83272
  import { homedir as homedir15 } from "node:os";
82458
- import { isAbsolute as isAbsolute7, join as join41 } from "node:path";
83273
+ import { isAbsolute as isAbsolute8, join as join41 } from "node:path";
82459
83274
  import Database3 from "better-sqlite3";
82460
83275
  function nativeDatabasePath(home, sessionId) {
82461
83276
  return join41(home, "databases", `${createHash16("sha256").update(sessionId).digest("hex")}.db`);
@@ -82503,7 +83318,7 @@ function prepareNativeDatabase(home, sessionId, env, nativeId) {
82503
83318
  }
82504
83319
  const data = join41(env.XDG_DATA_HOME ?? process.env.XDG_DATA_HOME ?? join41(homedir15(), ".local", "share"), "opencode");
82505
83320
  const configured = env.OPENCODE_DB ?? process.env.OPENCODE_DB;
82506
- const originals = configured && configured !== ":memory:" ? [isAbsolute7(configured) ? configured : join41(data, configured)] : existsSync45(data) ? readdirSync15(data).filter((name) => /^opencode(?:-[\w.-]+)?\.db$/.test(name)).map((name) => join41(data, name)) : [];
83321
+ const originals = configured && configured !== ":memory:" ? [isAbsolute8(configured) ? configured : join41(data, configured)] : existsSync45(data) ? readdirSync15(data).filter((name) => /^opencode(?:-[\w.-]+)?\.db$/.test(name)).map((name) => join41(data, name)) : [];
82507
83322
  const caches = readdirSync15(directory).filter((name) => name.endsWith(".db")).map((name) => join41(directory, name));
82508
83323
  const sources = [...originals, ...caches].filter((path) => path !== target && existsSync45(path));
82509
83324
  const source = nativeId ? sources.find((path) => containsSession(path, nativeId)) : originals.find((path) => existsSync45(path));
@@ -85809,44 +86624,6 @@ var init_cursor_sdk = __esm({
85809
86624
  }
85810
86625
  });
85811
86626
 
85812
- // ../../packages/shared/src/model-option-params.ts
85813
- function parseCatalogContextWindow(raw) {
85814
- if (!raw) return null;
85815
- const match = /^(\d+(?:\.\d+)?)\s*([km])?$/i.exec(raw.trim());
85816
- if (!match) return null;
85817
- const amount = Number(match[1]);
85818
- if (!Number.isFinite(amount) || amount <= 0) return null;
85819
- const unit = match[2]?.toLowerCase();
85820
- return Math.round(amount * (unit === "m" ? 1e6 : unit === "k" ? 1e3 : 1));
85821
- }
85822
- function firstParseableContextValue(values) {
85823
- for (const item of values ?? []) {
85824
- if (parseCatalogContextWindow(item.value) != null) return item.value;
85825
- }
85826
- return null;
85827
- }
85828
- function defaultCatalogContextWindow(modelId) {
85829
- return modelId && GPT_5_6_MODEL_RE.test(modelId) ? CODEX_GPT_5_6_CONTEXT_WINDOW : DEFAULT_CONTEXT_WINDOW;
85830
- }
85831
- function selectedCatalogContextWindow(selected, model) {
85832
- const parsed = parseCatalogContextWindow(selected);
85833
- if (parsed != null) return parsed;
85834
- return parseCatalogContextWindow(
85835
- firstParseableContextValue(model?.parameters?.find((param) => param.id === "context")?.values)
85836
- );
85837
- }
85838
- function resolveCatalogContextWindow(selected, model, modelId) {
85839
- return selectedCatalogContextWindow(selected, model) ?? defaultCatalogContextWindow(modelId);
85840
- }
85841
- var GPT_5_6_MODEL_RE;
85842
- var init_model_option_params = __esm({
85843
- "../../packages/shared/src/model-option-params.ts"() {
85844
- "use strict";
85845
- init_agent_types();
85846
- GPT_5_6_MODEL_RE = /(^|[/-])gpt-5\.6(?:$|-)/i;
85847
- }
85848
- });
85849
-
85850
86627
  // ../../packages/cursor/src/cursor-model-selection.ts
85851
86628
  function resolveCursorContextWindow(selected, model, modelId) {
85852
86629
  return resolveCatalogContextWindow(selected, model, modelId);
@@ -97854,11 +98631,14 @@ var SUPERONE_TOOL_SUMMARY_FIELDS = {
97854
98631
  read_manual: ["domain", "topic"],
97855
98632
  // The card, never the brief: the phone cannot launch it.
97856
98633
  session_suggest_task: ["title", "tldr"],
98634
+ // The layout row's verb and subject; the row reads file names out of `tab`.
98635
+ layout_act: ["action", "path", "line", "side", "tab", "width", "height", "mode", "position"],
97857
98636
  miniapp_dev_register: ["name", "directory", "appDir"],
97858
98637
  miniapp_dev_update_types: ["appDir"],
97859
98638
  miniapp_dev_setup: ["name", "directory", "description"],
97860
98639
  miniapp_dev_preview: ["tool", "phase"],
97861
- miniapp_dev_reload: ["appId"]
98640
+ miniapp_dev_reload: ["appId"],
98641
+ miniapp_open: ["appId"]
97862
98642
  };
97863
98643
  function sanitizeSessionTagInput(source) {
97864
98644
  const safe = {};
@@ -97892,6 +98672,9 @@ function sanitizeWorkflowInput(toolName, input) {
97892
98672
  "automation_list",
97893
98673
  "automation_apply",
97894
98674
  "automation_delete",
98675
+ "agent_profile_list",
98676
+ "agent_profile_apply",
98677
+ "agent_profile_delete",
97895
98678
  "config_apply",
97896
98679
  "environment_get_info",
97897
98680
  "project_list",
@@ -97918,6 +98701,12 @@ function sanitizeWorkflowInput(toolName, input) {
97918
98701
  copyDefined(source, safe, ["action", "name", "enabled"]);
97919
98702
  } else if (bare === "automation_delete" && Array.isArray(source.ids)) {
97920
98703
  safe.ids = source.ids.map(() => "");
98704
+ } else if (bare === "agent_profile_list") {
98705
+ copyDefined(source, safe, ["id"]);
98706
+ } else if (bare === "agent_profile_apply") {
98707
+ copyDefined(source, safe, ["action", "name", "harnessId"]);
98708
+ } else if (bare === "agent_profile_delete" && Array.isArray(source.ids)) {
98709
+ safe.ids = source.ids.map(() => "");
97921
98710
  } else if (bare === "config_apply") {
97922
98711
  const resource = source.resource && typeof source.resource === "object" && !Array.isArray(source.resource) ? source.resource : null;
97923
98712
  if (resource && typeof resource.operation === "string") {
@@ -100950,7 +101739,7 @@ var SESSION_OPERATION_HANDLERS = Object.fromEntries([
100950
101739
  ]);
100951
101740
 
100952
101741
  // ../../packages/runtime/src/server/rpc-dispatch.ts
100953
- import { dirname as configDirname, join as pathJoin, resolve as pathResolve2, sep as sep5 } from "node:path";
101742
+ import { dirname as configDirname, isAbsolute as isAbsolute5, join as pathJoin, resolve as pathResolve2, sep as sep5 } from "node:path";
100954
101743
 
100955
101744
  // ../../packages/runtime/src/server/rpc-session-create.ts
100956
101745
  init_environment();
@@ -107553,7 +108342,15 @@ function handleSessionSetUiFlags(payload, ctx) {
107553
108342
  return mapThrown(err);
107554
108343
  }
107555
108344
  }
107556
- function attachmentOriginal(zone, sessionId, path) {
108345
+ function attachmentOriginal(ctx, sessionId, path) {
108346
+ if (ctx.sameHost) {
108347
+ try {
108348
+ return typeof path === "string" && isAbsolute5(path) && statSync9(path).isFile() ? path : null;
108349
+ } catch {
108350
+ return null;
108351
+ }
108352
+ }
108353
+ const zone = ctx.artifacts;
107557
108354
  if (!zone) return null;
107558
108355
  const prefix = pathJoin(zone.syncRoot, sessionId) + sep5;
107559
108356
  if (typeof path !== "string" || !path.startsWith(prefix)) return null;
@@ -107601,7 +108398,7 @@ async function handleSessionSend(payload, ctx) {
107601
108398
  }).filter((x2) => x2 != null).slice(0, 8);
107602
108399
  for (const image of images) {
107603
108400
  if (image.originalPath === void 0) continue;
107604
- const original = attachmentOriginal(ctx.artifacts, String(p3.sessionId ?? ""), image.originalPath);
108401
+ const original = attachmentOriginal(ctx, String(p3.sessionId ?? ""), image.originalPath);
107605
108402
  if (!original) return { error: { code: "invalid_argument", message: "attachment original must be a file in this session's sync zone" } };
107606
108403
  image.originalPath = original;
107607
108404
  }
@@ -108222,8 +109019,191 @@ import Database5 from "better-sqlite3";
108222
109019
  import { mkdirSync as mkdirSync24 } from "node:fs";
108223
109020
  import { dirname as dirname20 } from "node:path";
108224
109021
 
109022
+ // ../../packages/shared/src/session-interruption.ts
109023
+ function isNodeRestartInterruption(reason) {
109024
+ return reason === "node_restart" || reason === "node_restart_non_reattachable";
109025
+ }
109026
+
109027
+ // ../../packages/runtime/src/collaboration/wake-queue.ts
109028
+ var COLLABORATION_WAKE_TABLE_DDL = `
109029
+ CREATE TABLE IF NOT EXISTS collaboration_wakes (
109030
+ session_id TEXT NOT NULL,
109031
+ notification_id TEXT NOT NULL,
109032
+ content TEXT NOT NULL,
109033
+ state TEXT NOT NULL DEFAULT 'queued',
109034
+ attempts INTEGER NOT NULL DEFAULT 0,
109035
+ next_attempt_at INTEGER NOT NULL DEFAULT 0,
109036
+ last_error TEXT,
109037
+ created_at INTEGER NOT NULL,
109038
+ PRIMARY KEY (session_id, notification_id)
109039
+ );
109040
+ CREATE INDEX IF NOT EXISTS idx_collaboration_wakes_pending
109041
+ ON collaboration_wakes(state, next_attempt_at);
109042
+ CREATE TABLE IF NOT EXISTS collaboration_wake_recipients (
109043
+ session_id TEXT PRIMARY KEY NOT NULL,
109044
+ paused INTEGER NOT NULL DEFAULT 0
109045
+ );
109046
+ `;
109047
+ var COLLABORATION_WAKE_MAX_ATTEMPTS = 3;
109048
+ var RETRY_DELAYS_MS = [1e4, 3e4];
109049
+ var CollaborationWakeDeferredError = class extends Error {
109050
+ };
109051
+ var CollaborationWakeQueue = class {
109052
+ constructor(db, deps) {
109053
+ this.db = db;
109054
+ this.deps = deps;
109055
+ db.exec(COLLABORATION_WAKE_TABLE_DDL);
109056
+ db.prepare(`INSERT INTO collaboration_wake_recipients (session_id, paused)
109057
+ SELECT DISTINCT session_id, 1 FROM collaboration_wakes WHERE state = 'dispatching'
109058
+ ON CONFLICT (session_id) DO UPDATE SET paused = 1`).run();
109059
+ db.prepare(`UPDATE collaboration_wakes SET state = 'uncertain',
109060
+ last_error = 'Notification admission interrupted before acknowledgement; automatic replay paused'
109061
+ WHERE state = 'dispatching'`).run();
109062
+ db.prepare("UPDATE collaboration_wakes SET state = 'queued' WHERE state = 'preparing'").run();
109063
+ for (const row2 of db.prepare("SELECT session_id FROM collaboration_wake_recipients WHERE paused = 1").all()) {
109064
+ this.paused.add(row2.session_id);
109065
+ }
109066
+ }
109067
+ db;
109068
+ deps;
109069
+ delivering = /* @__PURE__ */ new Set();
109070
+ paused = /* @__PURE__ */ new Set();
109071
+ timer = null;
109072
+ closed = false;
109073
+ scheduled = false;
109074
+ enqueue(sessionId, notificationId, content) {
109075
+ if (this.closed) throw new Error("Collaboration notification queue is closed");
109076
+ if (!sessionId || !notificationId || !content.trim()) throw new Error("Invalid collaboration notification");
109077
+ this.db.prepare(`
109078
+ INSERT INTO collaboration_wakes (session_id, notification_id, content, created_at)
109079
+ VALUES (?, ?, ?, ?) ON CONFLICT (session_id, notification_id) DO NOTHING
109080
+ `).run(sessionId, notificationId, content, this.now());
109081
+ this.start();
109082
+ }
109083
+ /** Resume queued admission attempts, retaining their budget across restarts. */
109084
+ start() {
109085
+ if (this.closed || this.scheduled) return;
109086
+ this.scheduled = true;
109087
+ queueMicrotask(() => {
109088
+ this.scheduled = false;
109089
+ if (!this.closed) this.flush();
109090
+ });
109091
+ }
109092
+ now() {
109093
+ return (this.deps.now ?? Date.now)();
109094
+ }
109095
+ /** Runtime errors and human stops pause consumption, without rejecting new mail. */
109096
+ observe(sessionId, event) {
109097
+ if (this.closed) return;
109098
+ if (event.type === "message_interrupted" && isNodeRestartInterruption(event.reason)) return;
109099
+ if (event.type === "message_error" || event.type === "message_interrupted") {
109100
+ this.pause(sessionId);
109101
+ } else if (event.type === "content_delta" || event.type === "message_complete") {
109102
+ if (!this.paused.has(sessionId)) return;
109103
+ this.db.prepare("UPDATE collaboration_wake_recipients SET paused = 0 WHERE session_id = ?").run(sessionId);
109104
+ this.paused.delete(sessionId);
109105
+ this.start();
109106
+ }
109107
+ }
109108
+ pause(sessionId) {
109109
+ if (this.paused.has(sessionId)) return;
109110
+ this.db.prepare(`INSERT INTO collaboration_wake_recipients (session_id, paused)
109111
+ VALUES (?, 1) ON CONFLICT (session_id) DO UPDATE SET paused = 1`).run(sessionId);
109112
+ this.paused.add(sessionId);
109113
+ }
109114
+ flush() {
109115
+ if (this.closed) return;
109116
+ if (this.timer) clearTimeout(this.timer);
109117
+ this.timer = null;
109118
+ const rows = this.db.prepare(`
109119
+ SELECT session_id, notification_id, content, attempts, next_attempt_at
109120
+ FROM collaboration_wakes w WHERE state = 'queued' AND NOT EXISTS (
109121
+ SELECT 1 FROM collaboration_wake_recipients r WHERE r.session_id = w.session_id AND r.paused = 1
109122
+ ) ORDER BY created_at, rowid
109123
+ `).all();
109124
+ let nextAttemptAt = Infinity;
109125
+ for (const row2 of rows) {
109126
+ if (this.delivering.has(row2.session_id) || this.paused.has(row2.session_id)) continue;
109127
+ if (this.deps.canAdmit?.(row2.session_id) === false) continue;
109128
+ if (row2.attempts >= COLLABORATION_WAKE_MAX_ATTEMPTS) {
109129
+ this.db.prepare(`UPDATE collaboration_wakes SET state = 'failed'
109130
+ WHERE session_id = ? AND notification_id = ?`).run(row2.session_id, row2.notification_id);
109131
+ this.pause(row2.session_id);
109132
+ continue;
109133
+ }
109134
+ if (row2.next_attempt_at > this.now()) {
109135
+ nextAttemptAt = Math.min(nextAttemptAt, row2.next_attempt_at);
109136
+ continue;
109137
+ }
109138
+ this.delivering.add(row2.session_id);
109139
+ this.db.prepare(`UPDATE collaboration_wakes SET state = 'preparing', attempts = attempts + 1
109140
+ WHERE session_id = ? AND notification_id = ?`).run(row2.session_id, row2.notification_id);
109141
+ void this.admit(row2);
109142
+ }
109143
+ if (Number.isFinite(nextAttemptAt)) {
109144
+ this.timer = setTimeout(() => {
109145
+ this.timer = null;
109146
+ this.flush();
109147
+ }, Math.max(1, nextAttemptAt - this.now()));
109148
+ this.timer.unref?.();
109149
+ }
109150
+ }
109151
+ async admit(row2) {
109152
+ let admitted = false;
109153
+ let deferred = false;
109154
+ const confirm = () => {
109155
+ if (admitted) return;
109156
+ this.db.prepare(`UPDATE collaboration_wakes SET state = 'dispatching'
109157
+ WHERE session_id = ? AND notification_id = ?`).run(row2.session_id, row2.notification_id);
109158
+ admitted = true;
109159
+ try {
109160
+ this.db.prepare(`UPDATE collaboration_wakes SET state = 'admitted', last_error = NULL
109161
+ WHERE session_id = ? AND notification_id = ?`).run(row2.session_id, row2.notification_id);
109162
+ } catch (error51) {
109163
+ this.paused.add(row2.session_id);
109164
+ this.deps.warn(`[collaboration-wake] accepted input receipt failed sid=${row2.session_id}: ${String(error51)}`);
109165
+ }
109166
+ };
109167
+ try {
109168
+ await this.deps.admit(row2.session_id, row2.content, row2.notification_id, confirm, () => {
109169
+ if (this.closed || this.paused.has(row2.session_id)) throw new CollaborationWakeDeferredError("Notification recipient is paused or shutting down");
109170
+ });
109171
+ confirm();
109172
+ } catch (error51) {
109173
+ if (!admitted) {
109174
+ const message = error51 instanceof Error ? error51.message : String(error51);
109175
+ deferred = this.closed || error51 instanceof CollaborationWakeDeferredError;
109176
+ const attempts = row2.attempts + (deferred ? 0 : 1);
109177
+ this.db.prepare(`UPDATE collaboration_wakes SET state = ?, attempts = ?, next_attempt_at = ?, last_error = ?
109178
+ WHERE session_id = ? AND notification_id = ?`).run(
109179
+ attempts >= COLLABORATION_WAKE_MAX_ATTEMPTS ? "failed" : "queued",
109180
+ attempts,
109181
+ deferred ? 0 : this.now() + (RETRY_DELAYS_MS[attempts - 1] ?? 0),
109182
+ message,
109183
+ row2.session_id,
109184
+ row2.notification_id
109185
+ );
109186
+ if (attempts >= COLLABORATION_WAKE_MAX_ATTEMPTS) {
109187
+ this.pause(row2.session_id);
109188
+ }
109189
+ if (!deferred) this.deps.warn(`[collaboration-wake] admission failed sid=${row2.session_id} attempt=${attempts}/${COLLABORATION_WAKE_MAX_ATTEMPTS}: ${message}`);
109190
+ }
109191
+ } finally {
109192
+ this.delivering.delete(row2.session_id);
109193
+ if (!this.closed && !deferred) this.start();
109194
+ }
109195
+ }
109196
+ /** Leave durable work and attempt counts intact when the host shuts down. */
109197
+ dispose() {
109198
+ this.closed = true;
109199
+ if (this.timer) clearTimeout(this.timer);
109200
+ this.timer = null;
109201
+ }
109202
+ };
109203
+
108225
109204
  // ../../packages/runtime/src/db/schema.ts
108226
109205
  var SCHEMA_SQL = `
109206
+ ${COLLABORATION_WAKE_TABLE_DDL}
108227
109207
  PRAGMA foreign_keys = ON;
108228
109208
 
108229
109209
  CREATE TABLE IF NOT EXISTS meta (
@@ -110818,7 +111798,7 @@ async function handleHarnessResources(payload, ctx) {
110818
111798
  ctx.projects.touch(projectId);
110819
111799
  const harnessId = typeof p3.harnessId === "string" && p3.harnessId.trim() ? p3.harnessId.trim() : null;
110820
111800
  const apiProviderId = typeof p3.apiProviderId === "string" && p3.apiProviderId.trim() ? p3.apiProviderId.trim() : p3.apiProviderId === null ? null : void 0;
110821
- const providerOptions = {
111801
+ const providerOptions2 = {
110822
111802
  experimentalClaudeOpenAiChatEnabled: ctx.experimentalClaudeOpenAiChatEnabled ?? false
110823
111803
  };
110824
111804
  const openCodeProvider = !harnessId || harnessId === "opencode" ? resolveNodeOpenCodeProvider(ctx.providers, apiProviderId) : null;
@@ -110829,7 +111809,7 @@ async function handleHarnessResources(payload, ctx) {
110829
111809
  ctx.providers,
110830
111810
  hid,
110831
111811
  apiId ?? null,
110832
- providerOptions
111812
+ providerOptions2
110833
111813
  );
110834
111814
  };
110835
111815
  const probeModels = async (hid) => {
@@ -110844,7 +111824,7 @@ async function handleHarnessResources(payload, ctx) {
110844
111824
  ctx.providers,
110845
111825
  hid,
110846
111826
  apiProviderId ?? null,
110847
- providerOptions
111827
+ providerOptions2
110848
111828
  );
110849
111829
  };
110850
111830
  const bundle = await collectHarnessResources({
@@ -111702,6 +112682,9 @@ init_codex_turn_runner();
111702
112682
  // src/session/harness-manager.ts
111703
112683
  init_harness();
111704
112684
 
112685
+ // src/session/collaboration.ts
112686
+ init_environment();
112687
+
111705
112688
  // ../../packages/runtime/src/collaboration/errors.ts
111706
112689
  var CollaborationError = class extends Error {
111707
112690
  constructor(message, code) {
@@ -112106,6 +113089,13 @@ var CollaborationStore = class {
112106
113089
  WHERE child_session_id IS NOT NULL AND COALESCE(kind, 'spawn') = 'spawn'
112107
113090
  `).all();
112108
113091
  }
113092
+ /** Started handoff grants; the session each created is `config_json.handoffSessionId`. */
113093
+ startedHandoffGrants() {
113094
+ return this.db.prepare(`
113095
+ SELECT ${GRANT_COLUMNS} FROM session_collaboration_grants
113096
+ WHERE kind = 'handoff' AND started_at IS NOT NULL
113097
+ `).all();
113098
+ }
112109
113099
  /**
112110
113100
  * Open mailbox channels of `sessionId`: spawn grants with a bound child and
112111
113101
  * started link grants, oldest first. Handoff grants are never channels.
@@ -112343,30 +113333,29 @@ init_text();
112343
113333
  function sessionTitle(ctx) {
112344
113334
  return (sessionId) => ctx.deps.sessions.get(sessionId)?.title ?? null;
112345
113335
  }
112346
- async function wakePeer(ctx, sessionId, fromSessionId) {
112347
- if (!ctx.deps.sessions.get(sessionId)) return;
113336
+ function wakePeer(ctx, sessionId, fromSessionId, messageId) {
112348
113337
  const fromTitle = ctx.deps.sessions.get(fromSessionId)?.title?.trim() || fromSessionId.slice(0, 8);
112349
- try {
112350
- await ctx.deps.sessions.sendWithoutLease({
112351
- sessionId,
112352
- text: mailboxWakeText({ sessionId: fromSessionId, title: fromTitle }),
112353
- source: "task-notification",
112354
- requestId: `collab-wake-${fromSessionId.slice(0, 8)}-${Date.now()}`
112355
- });
112356
- } catch {
112357
- }
113338
+ ctx.wakes.enqueue(
113339
+ sessionId,
113340
+ `collab-message:${messageId}`,
113341
+ mailboxWakeText({ sessionId: fromSessionId, title: fromTitle })
113342
+ );
112358
113343
  }
112359
113344
  function sendCollaborationMessage(ctx, input) {
112360
113345
  const channel = resolveSendChannel(ctx.store, input.sessionId, input.to, sessionTitle(ctx));
112361
113346
  const content = normalizeMailboxContent(input.content);
112362
113347
  const recipientSessionId = channel.peer.sessionId;
112363
- const insert = ctx.store.appendMessage({
112364
- grantId: channel.grant.grant_id,
112365
- senderSessionId: input.sessionId,
112366
- recipientSessionId,
112367
- clientMessageId: input.clientMessageId,
112368
- content
112369
- });
113348
+ const insert = ctx.deps.db.transaction(() => {
113349
+ const inserted = ctx.store.appendMessage({
113350
+ grantId: channel.grant.grant_id,
113351
+ senderSessionId: input.sessionId,
113352
+ recipientSessionId,
113353
+ clientMessageId: input.clientMessageId,
113354
+ content
113355
+ });
113356
+ wakePeer(ctx, recipientSessionId, input.sessionId, inserted.row.id);
113357
+ return inserted;
113358
+ })();
112370
113359
  if (!insert.reused) {
112371
113360
  ctx.deps.events.append({
112372
113361
  aggregateType: "session",
@@ -112379,7 +113368,6 @@ function sendCollaborationMessage(ctx, input) {
112379
113368
  sequence: insert.row.sequence
112380
113369
  }
112381
113370
  });
112382
- void wakePeer(ctx, recipientSessionId, input.sessionId);
112383
113371
  }
112384
113372
  return {
112385
113373
  status: "sent",
@@ -112402,57 +113390,77 @@ function retrieveCollaborationMessages(ctx, input) {
112402
113390
  }
112403
113391
 
112404
113392
  // src/session/collaboration-profiles.ts
113393
+ init_agent_profile();
112405
113394
  init_environment();
113395
+ init_harness_capabilities();
112406
113396
 
112407
113397
  // ../../packages/shared/src/acp-brand.ts
112408
113398
  init_acp_brand();
112409
113399
 
112410
113400
  // src/session/collaboration-profiles.ts
112411
113401
  init_resolve_service();
113402
+ function providerOptions(deps) {
113403
+ return { experimentalClaudeOpenAiChatEnabled: deps.experimentalClaudeOpenAiChatEnabled?.() ?? false };
113404
+ }
113405
+ var NODE_APPLIABLE_OPTIONS = ["agent"];
113406
+ function launchResolution(deps, harnessId, config2, launch2) {
113407
+ const harnessModels = listHarnessModels(deps.providers, harnessId, null, providerOptions(deps));
113408
+ const defaultModel = harnessModels.find((m3) => m3.isDefault) ?? harnessModels[0];
113409
+ const efforts = /* @__PURE__ */ new Set();
113410
+ for (const m3 of harnessModels) {
113411
+ for (const e of m3.supportedEffortLevels ?? []) efforts.add(e);
113412
+ }
113413
+ const catalog = { models: harnessModels, host: { appliable: NODE_APPLIABLE_OPTIONS } };
113414
+ const defaults2 = resolveAgentLaunchDefaults({
113415
+ harnessId,
113416
+ catalog,
113417
+ base: {
113418
+ model: defaultModel?.id,
113419
+ effort: efforts.has("high") ? "high" : efforts.has("medium") ? "medium" : [...efforts][0]
113420
+ },
113421
+ profile: providerLaunchRuntime(config2),
113422
+ launch: launch2
113423
+ });
113424
+ return { harnessModels, efforts, catalog, defaults: defaults2 };
113425
+ }
113426
+ function collaborationLaunchDefaults(deps, profile, launch2) {
113427
+ const explicit = launchDefaultsFromConfig(launch2);
113428
+ if (!Object.keys(explicit).length) return profile.defaultConfig;
113429
+ const { catalog, defaults: defaults2 } = launchResolution(deps, profile.harnessId, deps.sessionProviders?.get(profile.id)?.config, explicit);
113430
+ const harness = { id: profile.harnessId, name: HARNESS_CAPABILITIES[profile.harnessId]?.displayName ?? profile.harnessId };
113431
+ const errors = agentLaunchErrors(harness, catalog, defaults2.model, explicit);
113432
+ if (errors.length) throw new CollaborationError(errors.join(" "), "invalid_argument");
113433
+ return launchConfigFromDefaults(defaults2);
113434
+ }
112412
113435
  function listCollaborationProfiles(deps) {
112413
113436
  const { harnesses, providers, sessions, sessionProviders } = deps;
112414
113437
  const profiles = [];
112415
113438
  const seen = /* @__PURE__ */ new Set();
112416
- const providerOptions = {
112417
- experimentalClaudeOpenAiChatEnabled: deps.experimentalClaudeOpenAiChatEnabled?.() ?? false
112418
- };
112419
113439
  const pushProfile = (profileId, harnessId, name, description, profileConfig) => {
112420
113440
  if (seen.has(profileId)) return;
112421
113441
  if (!harnesses.isSessionHarnessRunnable(harnessId)) return;
112422
113442
  seen.add(profileId);
112423
- const harnessModels = listHarnessModels(providers, harnessId, null, providerOptions);
113443
+ const { harnessModels, efforts, defaults: defaults2 } = launchResolution(deps, harnessId, profileConfig);
112424
113444
  const models = harnessModels.map((m3) => ({
112425
113445
  id: m3.id,
112426
113446
  name: m3.name || m3.id,
112427
113447
  ...m3.description ? { description: m3.description } : {},
112428
113448
  ...m3.serviceTiers?.length ? { serviceTiers: m3.serviceTiers } : {}
112429
113449
  }));
112430
- const defaultModel = harnessModels.find((m3) => m3.isDefault) ?? harnessModels[0];
112431
- const efforts = /* @__PURE__ */ new Set();
112432
- for (const m3 of harnessModels) {
112433
- for (const e of m3.supportedEffortLevels ?? []) efforts.add(e);
112434
- }
112435
113450
  const cfg = profileConfig && typeof profileConfig === "object" && !Array.isArray(profileConfig) ? profileConfig : {};
112436
- const cfgModel = typeof cfg.model === "string" && cfg.model.trim() ? cfg.model.trim() : void 0;
112437
- const cfgEffort = typeof cfg.effort === "string" && cfg.effort.trim() ? cfg.effort.trim() : typeof cfg.reasoningEffort === "string" && cfg.reasoningEffort.trim() ? cfg.reasoningEffort.trim() : void 0;
112438
113451
  const acpAgentId = harnessId === "acp" && typeof cfg.agentId === "string" && cfg.agentId.trim() ? cfg.agentId.trim() : null;
112439
- const modelDefault = cfgModel ?? defaultModel?.id;
112440
- const effortDefault = cfgEffort ?? (efforts.has("high") ? "high" : efforts.has("medium") ? "medium" : efforts.size > 0 ? [...efforts][0] : void 0);
113452
+ const profile = readAgentProfile(profileConfig);
112441
113453
  profiles.push({
112442
113454
  id: profileId,
112443
- name: harnessId === "acp" ? acpAgentDisplayName(acpAgentId) : name,
113455
+ name: profile ? name : harnessId === "acp" ? acpAgentDisplayName(acpAgentId) : name,
112444
113456
  harnessId,
112445
113457
  ...acpAgentId ? { acpAgentId } : {},
112446
113458
  brandKey: resolveHarnessBrandKey(harnessId, acpAgentId),
112447
- description,
112448
- defaultConfig: {
112449
- ...modelDefault ? { model: modelDefault } : {},
112450
- ...effortDefault ? { effort: effortDefault } : {},
112451
- ...harnessId === "codex" ? { fastMode: typeof cfg.fastMode === "boolean" ? cfg.fastMode : false } : {}
112452
- },
113459
+ description: profile?.identity.description ?? description,
113460
+ defaultConfig: launchConfigFromDefaults(defaults2),
112453
113461
  models: models.length > 0 ? models : [{ id: "default", name: "Default" }],
112454
113462
  efforts: [...efforts],
112455
- apiProviders: listHarnessApiProviders(providers, harnessId, providerOptions)
113463
+ apiProviders: listHarnessApiProviders(providers, harnessId, providerOptions(deps))
112456
113464
  });
112457
113465
  };
112458
113466
  if (sessionProviders) {
@@ -112478,6 +113486,16 @@ function listCollaborationProfiles(deps) {
112478
113486
  }
112479
113487
  return profiles;
112480
113488
  }
113489
+ function collaborationAgentPromptAppend(deps, agentId, protocol) {
113490
+ return providerSystemPromptAppend(deps.sessionProviders?.get(agentId)?.config, protocol);
113491
+ }
113492
+ function launchedSessionPromptAppend(deps, grant) {
113493
+ return collaborationAgentPromptAppend(
113494
+ deps,
113495
+ grant.agent_id,
113496
+ grant.kind === "handoff" ? void 0 : collaborationSystemPrompt(grant.parent_session_id)
113497
+ );
113498
+ }
112481
113499
 
112482
113500
  // src/session/collaboration-request.ts
112483
113501
  import { randomUUID as randomUUID21 } from "node:crypto";
@@ -112559,7 +113577,7 @@ function normalizeLaunches(ctx, input, profileList) {
112559
113577
  name,
112560
113578
  role,
112561
113579
  config: {
112562
- ...profile.defaultConfig,
113580
+ ...collaborationLaunchDefaults(ctx.deps, profile, safe),
112563
113581
  ...safe,
112564
113582
  permissionMode: "default",
112565
113583
  sandboxMode: "off",
@@ -112667,21 +113685,16 @@ async function deliverInitialTask(ctx, grant, childSessionId) {
112667
113685
  }
112668
113686
  ctx.store.markTaskSent(grant.grant_id);
112669
113687
  }
112670
- async function wakeLinkPeer(ctx, sessionId, grant, hasOpening) {
112671
- if (!ctx.deps.sessions.get(sessionId)) return;
112672
- try {
112673
- await ctx.deps.sessions.sendWithoutLease({
112674
- sessionId,
112675
- text: linkActivationWakeText({
112676
- initiatorSessionId: grant.parent_session_id,
112677
- initiatorTitle: initiatorTitleOf(ctx, grant),
112678
- hasOpening
112679
- }),
112680
- source: "task-notification",
112681
- requestId: `collab-link-wake-${grant.grant_id.slice(0, 12)}-${Date.now()}`
112682
- });
112683
- } catch {
112684
- }
113688
+ function wakeLinkPeer(ctx, sessionId, grant, hasOpening) {
113689
+ ctx.wakes.enqueue(
113690
+ sessionId,
113691
+ `collab-link:${grant.grant_id}`,
113692
+ linkActivationWakeText({
113693
+ initiatorSessionId: grant.parent_session_id,
113694
+ initiatorTitle: initiatorTitleOf(ctx, grant),
113695
+ hasOpening
113696
+ })
113697
+ );
112685
113698
  }
112686
113699
  async function startLink(ctx, grant) {
112687
113700
  if (!grant.child_session_id) {
@@ -112730,12 +113743,7 @@ async function startCollaboration(ctx, input) {
112730
113743
  if (isHandoff2 && !existing) {
112731
113744
  throw new CollaborationError(`The handoff session no longer exists: ${existingSessionId}`, "not_found");
112732
113745
  }
112733
- if (existing && !isHandoff2) {
112734
- ctx.deps.sessions.setSystemPromptAppend(
112735
- existing.sessionId,
112736
- collaborationSystemPrompt(grant.parent_session_id)
112737
- );
112738
- }
113746
+ if (existing) ctx.deps.sessions.setSystemPromptAppend(existing.sessionId, launchedSessionPromptAppend(ctx.deps, grant));
112739
113747
  if (existing) await deliverInitialTask(ctx, grant, existingSessionId);
112740
113748
  const peer = describeLaunchedPeer(grant);
112741
113749
  return {
@@ -112781,9 +113789,10 @@ async function startCollaboration(ctx, input) {
112781
113789
  permissionMode: config2.permissionMode ?? null,
112782
113790
  sandboxMode: config2.sandboxMode ?? null,
112783
113791
  apiProviderId: config2.apiProviderId ?? null,
113792
+ // The one profile option this node's runtime takes (see NODE_APPLIABLE_OPTIONS).
113793
+ agent: config2.options?.agent ?? null,
112784
113794
  controllerClientSessionId: input.controllerClientSessionId ?? parent.controllerClientSessionId,
112785
- // Handoff is one-way by construction: the receiver gets no collaboration prompt.
112786
- ...isHandoff2 ? {} : { systemPromptAppend: collaborationSystemPrompt(grant.parent_session_id) }
113795
+ systemPromptAppend: launchedSessionPromptAppend(ctx.deps, grant) ?? null
112787
113796
  });
112788
113797
  ctx.store.bindStartedSession(grant, child.sessionId, config2);
112789
113798
  } catch (err) {
@@ -112831,14 +113840,59 @@ async function startCollaboration(ctx, input) {
112831
113840
  var CollaborationService = class {
112832
113841
  constructor(deps) {
112833
113842
  this.deps = deps;
113843
+ const wakes = new CollaborationWakeQueue(deps.db, {
113844
+ canAdmit: (sessionId) => {
113845
+ const session = deps.sessions.get(sessionId);
113846
+ if (!session) return true;
113847
+ if (session.status === "error" || session.status === "streaming" || session.pendingInteraction) return false;
113848
+ if (session.status !== "interrupted") return true;
113849
+ const latest = deps.db.prepare(`SELECT payload_json FROM environment_events
113850
+ WHERE aggregate_type = 'session' AND aggregate_id = ? AND event_type = ?
113851
+ ORDER BY sequence DESC LIMIT 1`).get(sessionId, SESSION_DURABLE_EVENT.turnInterrupted);
113852
+ if (!latest) return false;
113853
+ try {
113854
+ return isNodeRestartInterruption(JSON.parse(latest.payload_json)?.reason);
113855
+ } catch {
113856
+ return false;
113857
+ }
113858
+ },
113859
+ admit: (sessionId, text2, requestId, onInputAccepted, beforeInput) => deps.sessions.sendWithoutLease({
113860
+ sessionId,
113861
+ text: text2,
113862
+ requestId,
113863
+ source: "task-notification"
113864
+ }, { onInputAccepted, beforeInput }),
113865
+ warn: (message) => console.warn(message)
113866
+ });
112834
113867
  this.ctx = {
112835
113868
  deps,
112836
113869
  store: new CollaborationStore(deps.db),
113870
+ wakes,
112837
113871
  listProfiles: () => this.listProfiles()
112838
113872
  };
113873
+ this.unsubscribe = deps.events.onAppend((event) => {
113874
+ if (event.aggregateType !== "session") return;
113875
+ const agentEvent = event.payload?.event;
113876
+ if (agentEvent) wakes.observe(event.aggregateId, agentEvent);
113877
+ if (event.eventType === SESSION_DURABLE_EVENT.turnError) {
113878
+ wakes.observe(event.aggregateId, { type: "message_error", messageId: "", error: "turn failed" });
113879
+ } else if (event.eventType === SESSION_DURABLE_EVENT.turnInterrupted) {
113880
+ const reason = event.payload?.reason;
113881
+ wakes.observe(event.aggregateId, { type: "message_interrupted", messageId: "", reason });
113882
+ } else if (event.eventType === SESSION_DURABLE_EVENT.turnCompleted) {
113883
+ wakes.observe(event.aggregateId, { type: "message_complete", messageId: "" });
113884
+ }
113885
+ if (!event.ephemeral) wakes.start();
113886
+ });
113887
+ wakes.start();
112839
113888
  }
112840
113889
  deps;
112841
113890
  ctx;
113891
+ unsubscribe;
113892
+ dispose() {
113893
+ this.unsubscribe();
113894
+ this.ctx.wakes.dispose();
113895
+ }
112842
113896
  /** Agent profiles from session_providers (+ ready-harness fallback). */
112843
113897
  isSpawnChild(sessionId) {
112844
113898
  return this.ctx.store.isSpawnChild(sessionId);
@@ -112858,11 +113912,18 @@ var CollaborationService = class {
112858
113912
  retrieve(input) {
112859
113913
  return retrieveCollaborationMessages(this.ctx, input);
112860
113914
  }
112861
- /** Reconstruct system-prompt append for spawn children after restart (never link). */
113915
+ /** Reconstruct the system-prompt append of launched sessions after restart (never link). */
112862
113916
  rehydrateSystemPrompts() {
112863
- for (const grant of this.ctx.store.startedSpawnGrants()) {
112864
- if (!grant.child_session_id || !this.deps.sessions.get(grant.child_session_id)) continue;
112865
- this.deps.sessions.setSystemPromptAppend(grant.child_session_id, collaborationSystemPrompt(grant.parent_session_id));
113917
+ const launched = [
113918
+ ...this.ctx.store.startedSpawnGrants().map((grant) => ({ grant, sessionId: grant.child_session_id })),
113919
+ ...this.ctx.store.startedHandoffGrants().map((grant) => ({
113920
+ grant,
113921
+ sessionId: parseGrantConfig(grant.config_json).handoffSessionId
113922
+ }))
113923
+ ];
113924
+ for (const { grant, sessionId } of launched) {
113925
+ if (!sessionId || !this.deps.sessions.get(sessionId)) continue;
113926
+ this.deps.sessions.setSystemPromptAppend(sessionId, launchedSessionPromptAppend(this.deps, grant));
112866
113927
  }
112867
113928
  }
112868
113929
  };
@@ -125143,6 +126204,24 @@ function widgetShowShortContent(args) {
125143
126204
  ];
125144
126205
  }
125145
126206
 
126207
+ // ../../packages/shared/src/collab-agent-catalog.ts
126208
+ function collabAgentSummary(profile) {
126209
+ return {
126210
+ id: profile.id,
126211
+ name: profile.name,
126212
+ harnessId: profile.harnessId,
126213
+ ...profile.acpAgentId ? { acpAgentId: profile.acpAgentId } : {},
126214
+ ...profile.description ? { description: profile.description } : {}
126215
+ };
126216
+ }
126217
+ function collabAgentDetail(profile) {
126218
+ const { brandKey: _brandKey, ...detail } = profile;
126219
+ return detail;
126220
+ }
126221
+ function unknownCollabAgentMessage(id, environment) {
126222
+ return environment ? `Agent ${id} is not available on environment ${environment}. Call session_collab_list_agents without id and pick one from environments[].agents.` : `Unknown agent ${id}. Call session_collab_list_agents without id to see the available agents.`;
126223
+ }
126224
+
125146
126225
  // src/session/json-schema-to-zod.ts
125147
126226
  function numberConstraint(value) {
125148
126227
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
@@ -125338,12 +126417,22 @@ function registerNodeCollabTools(server, superoneSessionId, collab) {
125338
126417
  "session_collab_list_agents",
125339
126418
  {
125340
126419
  description: listDesc.description,
125341
- inputSchema: {}
126420
+ inputSchema: jsonSchemaToZodShape(listDesc.inputSchema)
125342
126421
  },
125343
- async () => {
126422
+ async (args) => {
125344
126423
  try {
126424
+ const { id, environment } = args ?? {};
126425
+ if (environment?.trim()) {
126426
+ return collabErrorResult(Object.assign(
126427
+ new Error("Agents on other machines are only listed from the SuperOne desktop app."),
126428
+ { code: "failed_precondition" }
126429
+ ));
126430
+ }
125345
126431
  const agents = await collab.listAgents(superoneSessionId);
125346
- return toolResultJson({ agents });
126432
+ const wanted = id?.trim();
126433
+ if (!wanted) return toolResultJson({ agents: agents.map(collabAgentSummary) });
126434
+ const agent = agents.find((profile) => profile.id === wanted);
126435
+ return agent ? toolResultJson(collabAgentDetail(agent)) : collabErrorResult(Object.assign(new Error(unknownCollabAgentMessage(wanted)), { code: "not_found" }));
125347
126436
  } catch (err) {
125348
126437
  return collabErrorResult(err);
125349
126438
  }
@@ -127248,6 +128337,7 @@ async function startNodeRuntime(partial2 = {}) {
127248
128337
  startedAt,
127249
128338
  async stop() {
127250
128339
  automationService.stop();
128340
+ collaboration.dispose();
127251
128341
  const disposePromise = sessions.dispose();
127252
128342
  await server.close();
127253
128343
  await disposePromise;
@@ -127430,7 +128520,7 @@ init_environment();
127430
128520
  init_config();
127431
128521
  init_harness();
127432
128522
  import { accessSync as accessSync4, constants as constants6, existsSync as existsSync55, realpathSync as realpathSync13, statSync as statSync19 } from "node:fs";
127433
- import { isAbsolute as isAbsolute8, resolve as resolve19 } from "node:path";
128523
+ import { isAbsolute as isAbsolute9, resolve as resolve19 } from "node:path";
127434
128524
  import { homedir as homedir18 } from "node:os";
127435
128525
 
127436
128526
  // src/session/managed-harness-release.ts
@@ -127928,7 +129018,7 @@ function buildPublicConfigSummary(id, configJson, status2) {
127928
129018
  }
127929
129019
  const out = {};
127930
129020
  if (id === "claude" || id === "codex") {
127931
- if (typeof parsed.artifactPath === "string" && isAbsolute8(parsed.artifactPath)) {
129021
+ if (typeof parsed.artifactPath === "string" && isAbsolute9(parsed.artifactPath)) {
127932
129022
  out.artifactPath = parsed.artifactPath;
127933
129023
  }
127934
129024
  if (parsed.source === "offline-artifact") out.source = "offline-artifact";
@@ -127938,14 +129028,14 @@ function buildPublicConfigSummary(id, configJson, status2) {
127938
129028
  out.digestSha256 = parsed.digestSha256;
127939
129029
  }
127940
129030
  } else if (id === "opencode") {
127941
- if (typeof parsed.command === "string" && isAbsolute8(parsed.command)) {
129031
+ if (typeof parsed.command === "string" && isAbsolute9(parsed.command)) {
127942
129032
  out.command = parsed.command;
127943
129033
  }
127944
129034
  if (typeof parsed.serverUrl === "string") {
127945
129035
  out.serverUrl = redactServerUrlForDisplay(parsed.serverUrl);
127946
129036
  }
127947
129037
  } else if (id === "acp-grok") {
127948
- if (typeof parsed.command === "string" && isAbsolute8(parsed.command)) {
129038
+ if (typeof parsed.command === "string" && isAbsolute9(parsed.command)) {
127949
129039
  out.command = parsed.command;
127950
129040
  }
127951
129041
  if (Array.isArray(parsed.args)) {
@@ -127959,7 +129049,7 @@ function buildPublicConfigSummary(id, configJson, status2) {
127959
129049
  }
127960
129050
  function resolveExternalCommand2(explicit, pathCandidates) {
127961
129051
  if (explicit) {
127962
- if (!isAbsolute8(explicit)) {
129052
+ if (!isAbsolute9(explicit)) {
127963
129053
  return null;
127964
129054
  }
127965
129055
  return isUsableExecutable(explicit);