pi-ultracode 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@ Deterministic multi-agent workflows for [Pi](https://github.com/earendil-works/p
4
4
 
5
5
  **English** · [简体中文](https://github.com/ekil1100/pi-ultracode/blob/main/README.zh-CN.md)
6
6
 
7
- `pi-ultracode` adds an opt-in high-effort mode to Pi. When a task benefits from delegation, the main agent can run a bounded JavaScript workflow with parallel subagents, isolated worktrees, structured output, durable resume, and live progress.
7
+ `pi-ultracode` adds opt-in semantic analysis-depth modes to Pi. It can route each task automatically or hold a fixed focused, standard, or deep policy. When delegation adds value, the main agent can run a bounded JavaScript workflow with parallel subagents, isolated worktrees, structured output, durable resume, and live progress.
8
8
 
9
9
  The project combines the terminal-first agentic experience of [Claude Code](https://github.com/anthropics/claude-code) with the explicit workflow and structural-control ideas found in [Grok Build](https://github.com/xai-org/grok-build), while keeping Pi as the runtime.
10
10
 
@@ -14,14 +14,14 @@ The project combines the terminal-first agentic experience of [Claude Code](http
14
14
  pi install npm:pi-ultracode
15
15
  ```
16
16
 
17
- Then reload Pi and toggle Ultracode on:
17
+ Then reload Pi and enable adaptive Ultracode:
18
18
 
19
19
  ```text
20
20
  /reload
21
21
  /ultracode
22
22
  ```
23
23
 
24
- You can also enable it at startup:
24
+ You can also start directly in `auto` mode:
25
25
 
26
26
  ```bash
27
27
  pi --ultracode
@@ -33,7 +33,7 @@ Current releases are tested with Pi 0.84.
33
33
 
34
34
  ## Core features
35
35
 
36
- - **Opt-in high-effort mode** — requests the highest thinking level supported by the current model and restores the previous level when disabled.
36
+ - **Adaptive semantic depth** — choose `auto`, `focused`, `standard`, or `deep`; `auto` selects the smallest evidence-sufficient depth while the parent effort remains under user control.
37
37
  - **Explicit workflows** — compose work with `agent()`, `parallel()`, `pipeline()`, and nested `workflow()` calls.
38
38
  - **Independent subagents** — each agent gets its own Pi session, context, tools, model selection, and optional role.
39
39
  - **Parallel worktree isolation** — writing agents can work in temporary git worktrees before their patches are integrated.
@@ -44,7 +44,7 @@ Current releases are tested with Pi 0.84.
44
44
 
45
45
  ## Quick start
46
46
 
47
- Toggle Ultracode on and describe a substantial task:
47
+ Enable adaptive Ultracode and describe a task:
48
48
 
49
49
  ```text
50
50
  /ultracode
@@ -59,16 +59,32 @@ Useful commands:
59
59
 
60
60
  | Command | Action |
61
61
  | --- | --- |
62
- | `/ultracode` | Toggle Ultracode on or off |
63
- | `/ultracode on` | Explicitly enable it (optional alias) |
64
- | `/ultracode off` | Disable it and restore the previous thinking level |
65
- | `/ultracode status` | Show the current mode and effective thinking level |
62
+ | `/ultracode` | Enable `auto` from off; disable any active mode |
63
+ | `/ultracode auto` | Select adaptive semantic-depth routing |
64
+ | `/ultracode focused` | Fix the lightweight, narrowly scoped policy |
65
+ | `/ultracode standard` | Fix the balanced policy with conditional verification |
66
+ | `/ultracode deep` | Fix the high-assurance policy with deep verification |
67
+ | `/ultracode off` | Disable it without changing the parent effort |
68
+ | `/ultracode status` | Show the configured semantic-depth mode |
66
69
  | `/workflows` or `F6` | Open the workflow browser |
67
70
  | `/workflows <runId>` | Open a specific run |
68
71
  | `/workflows abort` | Abort active runs |
69
72
 
70
73
  Press `Esc` to cancel a running workflow. In Pi's fullscreen TUI, use `Ctrl+PageUp`, `Ctrl+PageDown`, and `Ctrl+End` inside workflow details.
71
74
 
75
+ ## Analysis depth
76
+
77
+ Depth is semantic, not time-based:
78
+
79
+ - **Focused** prefers the parent agent and one bounded line of inquiry. It does not run adversarial verification by default.
80
+ - **Standard** covers the few independent dimensions that can change the answer and verifies only high-risk, conflicting, or weakly evidenced claims.
81
+ - **Deep** uses bounded multi-perspective investigation and adversarial verification for high-risk or explicitly comprehensive work.
82
+ - **Auto** routes to the smallest sufficient level from user intent, consequence risk, scope, ambiguity, available evidence, and conflicts. It escalates only when evidence requires it.
83
+
84
+ Research stops when key claims have direct evidence, no material conflict or unresolved high-risk question remains, and another round would repeat known evidence. Wall-clock time, deadlines, and duration limits are never used to choose or stop analysis depth. `maxAgents` and `reserveAgents` remain structural admission limits.
85
+
86
+ Ultracode never changes the parent session's effort. For workflow children, the parent selects effort per assigned task with a model suffix: typically `:medium` for bounded discovery or synthesis, `:high` for substantive analysis or implementation, and `:max` only for deep or decisive high-risk verification. The workflow UI reports each child's actual model-clamped effort. If no suffix is supplied, the child uses its normal user/model configuration. A separate skeptic or synthesis agent is not automatic.
87
+
72
88
  ## Workflow example
73
89
 
74
90
  The main agent normally writes workflows for you. Reusable workflows can also be saved under `.pi/ultracode/workflows/*.workflow.js` or `~/.pi/ultracode/workflows/*.workflow.js`. Project-scoped workflows are discovered only after Pi marks the project as trusted; user-scoped workflows remain available in untrusted projects.
@@ -133,7 +149,7 @@ Workflow agent sessions retain project context and ordinary skills, but do not i
133
149
 
134
150
  Resume is intentionally immutable: the normalized script, arguments, canonical repository/relative cwd, project-trust context, agent definitions, effective models, and call structure must still match. Worktree delivery writes a durable recovery intent before changing the shared repository; an interrupted or conflicted delivery blocks automatic replay and reports its recovery patch. Changed work starts a new run.
135
151
 
136
- Token and cost data are reported for observability, not enforced as a budget. Worker and VM restrictions are determinism and liveness guards, not a security sandbox.
152
+ Token and cost data are reported for observability, not enforced as a budget. Worker and VM restrictions are determinism and liveness guards, not a security sandbox and not analysis-depth controls.
137
153
 
138
154
  ## Design inspiration
139
155
 
package/README.zh-CN.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [English](README.md) · **简体中文**
6
6
 
7
- `pi-ultracode` 为 Pi 增加一个可选的高强度执行模式。当任务适合拆分时,主代理可以运行有边界的 JavaScript 工作流,使用并行子代理、隔离 worktree、结构化输出、持久恢复和实时进度。
7
+ `pi-ultracode` 为 Pi 增加可选的语义化分析深度模式。它既可以自动判断任务需要的深度,也可以固定使用 focused、standard 或 deep 策略。当委派确有价值时,主代理可以运行有边界的 JavaScript 工作流,使用并行子代理、隔离 worktree、结构化输出、持久恢复和实时进度。
8
8
 
9
9
  项目结合了 [Claude Code](https://github.com/anthropics/claude-code) 的终端 Agentic 体验,以及 [Grok Build](https://github.com/xai-org/grok-build) 的显式工作流和结构控制思路,同时继续使用 Pi 作为运行时。
10
10
 
@@ -14,14 +14,14 @@
14
14
  pi install npm:pi-ultracode
15
15
  ```
16
16
 
17
- 然后重新加载 Pi,并用主命令切换到 Ultracode:
17
+ 然后重新加载 Pi,并用主命令开启自适应 Ultracode:
18
18
 
19
19
  ```text
20
20
  /reload
21
21
  /ultracode
22
22
  ```
23
23
 
24
- 也可以在启动时直接启用:
24
+ 也可以在启动时直接进入 `auto` 模式:
25
25
 
26
26
  ```bash
27
27
  pi --ultracode
@@ -33,7 +33,7 @@ pi --ultracode
33
33
 
34
34
  ## 核心特性
35
35
 
36
- - **可选高强度模式**:请求当前模型支持的最高思考强度,关闭时恢复之前的强度。
36
+ - **自适应语义深度**:可选择 `auto`、`focused`、`standard` 或 `deep`;`auto` 使用证据充分的最小深度,父代理 effort 始终由用户控制。
37
37
  - **显式工作流**:通过 `agent()`、`parallel()`、`pipeline()` 和嵌套 `workflow()` 组合任务。
38
38
  - **独立子代理**:每个代理拥有独立的 Pi 会话、上下文、工具、模型选择和可选角色。
39
39
  - **并行 worktree 隔离**:写入型代理可在临时 git worktree 中工作,再集成补丁。
@@ -44,7 +44,7 @@ pi --ultracode
44
44
 
45
45
  ## 快速开始
46
46
 
47
- 用主命令开启 Ultracode,然后描述一个较复杂的任务:
47
+ 用主命令开启自适应 Ultracode,然后描述任务:
48
48
 
49
49
  ```text
50
50
  /ultracode
@@ -59,16 +59,32 @@ Pi 会自行判断工作流是否有帮助。小任务仍可继续使用普通
59
59
 
60
60
  | 命令 | 作用 |
61
61
  | --- | --- |
62
- | `/ultracode` | 切换 Ultracode 的开启或关闭状态 |
63
- | `/ultracode on` | 显式启用(可选别名) |
64
- | `/ultracode off` | 关闭并恢复之前的思考强度 |
65
- | `/ultracode status` | 查看当前模式和实际思考强度 |
62
+ | `/ultracode` | 关闭时开启 `auto`;任一模式已开启时关闭 |
63
+ | `/ultracode auto` | 使用自适应语义深度路由 |
64
+ | `/ultracode focused` | 固定使用轻量、聚焦的分析策略 |
65
+ | `/ultracode standard` | 固定使用平衡策略和条件验证 |
66
+ | `/ultracode deep` | 固定使用高保障深度验证 |
67
+ | `/ultracode off` | 关闭且不改变父代理 effort |
68
+ | `/ultracode status` | 查看配置的语义深度模式 |
66
69
  | `/workflows` 或 `F6` | 打开工作流浏览器 |
67
70
  | `/workflows <runId>` | 打开指定运行 |
68
71
  | `/workflows abort` | 中止活动运行 |
69
72
 
70
73
  按 `Esc` 可取消正在运行的工作流。在 Pi 的 fullscreen TUI 中,请在工作流详情内使用 `Ctrl+PageUp`、`Ctrl+PageDown` 和 `Ctrl+End`。
71
74
 
75
+ ## 分析深度
76
+
77
+ 深度是语义化质量决策,不按运行时间判断:
78
+
79
+ - **Focused** 优先使用主代理和单一、边界明确的调查路径,默认不做对抗验证。
80
+ - **Standard** 覆盖少量真正会改变结论的独立维度,只验证高风险、冲突或证据薄弱的结论。
81
+ - **Deep** 面向高风险或用户明确要求全面分析的任务,使用有界的多视角调查和对抗验证。
82
+ - **Auto** 根据用户意图、影响风险、范围、歧义、现有证据和结论冲突,选择足够完成任务的最小等级;仅在证据要求升级时加深。
83
+
84
+ 当关键结论已有直接证据、没有实质冲突或未解决的高风险问题,且下一轮只会重复已知证据时停止。墙钟时间、deadline 和 duration limit 不得用于选择或停止分析深度。`maxAgents` 与 `reserveAgents` 继续作为结构性准入限制。
85
+
86
+ Ultracode 不会修改父会话的 effort。对于 workflow 子代理,父代理会按具体任务通过模型后缀选择 effort:边界明确的搜索或汇总通常使用 `:medium`,实质分析或实现使用 `:high`,只有深度调查或决定性的高风险验证才使用 `:max`。Workflow UI 会展示每个子代理经模型裁剪后实际生效的 effort;未指定后缀时,子会话使用正常的用户/模型配置。skeptic 和独立 synthesis agent 都不是默认步骤。
87
+
72
88
  ## 工作流示例
73
89
 
74
90
  通常由主代理自动编写工作流。需要复用时,可以保存到 `.pi/ultracode/workflows/*.workflow.js` 或 `~/.pi/ultracode/workflows/*.workflow.js`。只有 Pi 将项目标记为可信后,才会发现项目级工作流;用户级工作流在未信任项目中仍可使用。
@@ -133,7 +149,7 @@ Workflow 子代理会保留项目上下文和普通 skills,但不会初始化
133
149
 
134
150
  Resume 刻意保持不可变:规范化脚本、参数、规范仓库及仓内相对 cwd、项目信任上下文、代理定义、实际模型和调用结构都必须匹配。Worktree 交付会在修改共享仓库前先写入持久恢复意图;中断或冲突的交付会阻止自动回放,并报告恢复补丁。工作内容发生变化时,应启动新的 run。
135
151
 
136
- Token 和成本只用于可观测性,不作为执行预算。Worker 与 VM 限制用于确定性和存活性保护,不是安全沙箱。
152
+ Token 和成本只用于可观测性,不作为执行预算。Worker 与 VM 限制用于确定性和存活性保护,不是安全沙箱,也不参与分析深度判断。
137
153
 
138
154
  ## 设计参考
139
155
 
@@ -1,21 +1,13 @@
1
1
  /**
2
2
  * pi-ultracode extension entrypoint.
3
3
  *
4
- * Wires together the three pillars of Claude-Code-style "ultracode":
5
- * 1. The ultracode effort mode (max thinking + standing workflow opt-in).
6
- * 2. The full `workflow` orchestration tool.
7
- * 3. The `/ultracode` and `/workflows` commands.
4
+ * Wires together Ultracode's semantic analysis-depth modes, deterministic
5
+ * workflow orchestration, and the `/ultracode` / `/workflows` commands.
8
6
  */
9
7
 
10
- import {
11
- getAgentDir,
12
- SettingsManager,
13
- VERSION as PI_VERSION,
14
- type ExtensionAPI,
15
- } from "@earendil-works/pi-coding-agent";
8
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
16
9
  import { createWorkflowTool, type WorkflowToolDeps } from "../src/workflow/tool.ts";
17
10
  import { UltracodeMode, type ThinkingPreferenceStore } from "../src/mode.ts";
18
- import { isThinkingLevel, piVersionSupportsMaxThinking } from "../src/thinking.ts";
19
11
  import { registerCommands } from "../src/commands.ts";
20
12
  import { WorkflowRegistry } from "../src/workflow/registry.ts";
21
13
 
@@ -25,7 +17,7 @@ export interface ThinkingPreferenceContext {
25
17
  }
26
18
 
27
19
  export interface UltracodeExtensionDeps extends Partial<WorkflowToolDeps> {
28
- /** SDK-host seam when the active profile differs from Pi's ambient agent dir. */
20
+ /** @deprecated Parent effort is user-owned; retained for source compatibility. */
29
21
  createThinkingPreferenceStore?: (
30
22
  context: ThinkingPreferenceContext,
31
23
  ) => ThinkingPreferenceStore | undefined;
@@ -33,15 +25,13 @@ export interface UltracodeExtensionDeps extends Partial<WorkflowToolDeps> {
33
25
 
34
26
  export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensionDeps = {}): void {
35
27
  const mode = new UltracodeMode("workflow");
36
- mode.setRuntimeSupportsMaxThinking(piVersionSupportsMaxThinking(PI_VERSION));
37
28
  const {
38
- createThinkingPreferenceStore = createPiThinkingPreferenceStore,
29
+ createThinkingPreferenceStore: _unusedThinkingPreferenceStore,
39
30
  ...workflowDeps
40
31
  } = extraDeps;
41
32
 
42
33
  const registry = workflowDeps.registry ?? new WorkflowRegistry();
43
34
  const workflowTool = createWorkflowTool({
44
- getThinkingLevel: () => mode.getSubagentThinkingLevel(),
45
35
  ...workflowDeps,
46
36
  registry,
47
37
  isExecutionAllowed: () => mode.isEnforcing(),
@@ -53,7 +43,7 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
53
43
  // Opt-in via CLI flag: `pi --ultracode`.
54
44
  pi.registerFlag("ultracode", {
55
45
  type: "boolean",
56
- description: "Start the session in ultracode mode (max thinking + default workflow orchestration).",
46
+ description: "Start the session in adaptive Ultracode mode.",
57
47
  });
58
48
 
59
49
  // SDK-created sessions can prompt without emitting session_start. Sync during
@@ -68,22 +58,12 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
68
58
  if (event.toolName === workflowTool.name && !mode.isEnforcing()) {
69
59
  return {
70
60
  block: true,
71
- reason: "The workflow tool is disabled. Run /ultracode on before using it.",
61
+ reason: "The workflow tool is disabled. Run /ultracode or select an Ultracode depth before using it.",
72
62
  };
73
63
  }
74
64
  });
75
65
 
76
66
  pi.on("session_start", async (_event, ctx) => {
77
- await mode.flushThinkingPreference();
78
- mode.setCurrentModelSupportsThinking(ctx.model ? Boolean(ctx.model.reasoning) : undefined);
79
- try {
80
- mode.bindThinkingPreferenceStore(createThinkingPreferenceStore({
81
- cwd: ctx.cwd,
82
- projectTrusted: ctx.isProjectTrusted(),
83
- }));
84
- } catch {
85
- mode.bindThinkingPreferenceStore(undefined);
86
- }
87
67
  // Restore persisted mode state across reload / resume / fork.
88
68
  try {
89
69
  // Mode entries are branch-local; discarded future branches must not win.
@@ -92,85 +72,38 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
92
72
  // ignore
93
73
  }
94
74
  if (!mode.isEnabled() && pi.getFlag?.("ultracode") === true) {
95
- mode.enable(pi);
75
+ mode.enable(pi, "auto");
96
76
  }
97
77
  // Registration makes extension tools discoverable; activation remains opt-in.
98
78
  mode.syncWorkflowTool(pi);
99
- await mode.flushThinkingPreference();
100
79
  if (ctx.hasUI) {
101
- ctx.ui.setStatus("ultracode", mode.isEnabled() ? mode.statusLine() : undefined);
80
+ ctx.ui.setStatus(
81
+ "ultracode",
82
+ mode.isEnabled() ? mode.statusLine((label) => ctx.ui.theme.fg("accent", label)) : undefined,
83
+ );
102
84
  }
103
85
  });
104
86
 
105
87
  pi.on("session_tree", async (_event, ctx) => {
106
- await mode.flushThinkingPreference();
107
88
  if (mode.isSuspended()) return;
108
- mode.setCurrentModelSupportsThinking(ctx.model ? Boolean(ctx.model.reasoning) : undefined);
109
89
  mode.restore(pi, ctx.sessionManager.getBranch() as any);
110
- await mode.flushThinkingPreference();
111
90
  if (ctx.hasUI) {
112
- ctx.ui.setStatus("ultracode", mode.isEnabled() ? mode.statusLine() : undefined);
91
+ ctx.ui.setStatus(
92
+ "ultracode",
93
+ mode.isEnabled() ? mode.statusLine((label) => ctx.ui.theme.fg("accent", label)) : undefined,
94
+ );
113
95
  }
114
96
  });
115
97
 
116
- pi.on("model_select", async (event, ctx) => {
117
- mode.setCurrentModelSupportsThinking(Boolean(event.model.reasoning));
118
- const refreshStatus = mode.handleModelSelect(pi);
119
- await mode.flushThinkingPreference();
120
- if (refreshStatus && ctx.hasUI) ctx.ui.setStatus("ultracode", mode.statusLine());
121
- });
122
-
123
- pi.on("thinking_level_select", async (event, ctx) => {
124
- if (!mode.handleThinkingLevelSelect(pi, event.level)) return;
125
- await mode.flushThinkingPreference();
126
- if (ctx.hasUI) ctx.ui.setStatus("ultracode", mode.statusLine());
127
- });
128
-
129
98
  pi.on("session_shutdown", async () => {
130
- // Quiesce first so late model/effort events cannot undo restoration. The
131
- // persisted enabled state remains on for reload/resume/fork replacements.
99
+ // The persisted configured mode remains active for reload/resume/fork replacements.
132
100
  mode.suspend(pi);
133
- await mode.flushThinkingPreference();
134
101
  });
135
102
 
136
103
  pi.on("before_agent_start", async (event) => {
137
- // Reconcile the tool schema and always append the standing block on an
104
+ // Reconcile tool availability and append the standing policy on every
138
105
  // enforcing turn, even when another active-tool writer caused drift.
139
106
  mode.syncWorkflowTool(pi);
140
- mode.reapplyMaximumThinking(pi);
141
- await mode.flushThinkingPreference();
142
107
  return mode.beforeAgentStart(event);
143
108
  });
144
109
  }
145
-
146
- function createPiThinkingPreferenceStore(
147
- context: ThinkingPreferenceContext,
148
- ): ThinkingPreferenceStore {
149
- const createSettings = () => SettingsManager.create(
150
- context.cwd,
151
- getAgentDir(),
152
- { projectTrusted: context.projectTrusted },
153
- );
154
- return {
155
- getThinkingPreference() {
156
- // Use a fresh manager so a selection made after session_start is visible;
157
- // SettingsManager instances intentionally keep their own cached snapshot.
158
- const settings = createSettings();
159
- const global = settings.getGlobalSettings().defaultThinkingLevel;
160
- const effective = settings.getDefaultThinkingLevel();
161
- return {
162
- global: isThinkingLevel(global) ? global : undefined,
163
- effective: isThinkingLevel(effective) ? effective : "medium",
164
- };
165
- },
166
- async setDefaultThinkingLevel(level) {
167
- // Use a fresh queue after the mode's macrotask barrier. This serializes
168
- // behind Pi's already-enqueued writes instead of racing a long-lived peer.
169
- const settings = createSettings();
170
- // An absent setting is semantically Pi's `medium` default. SettingsManager
171
- // has no unset operation, so restore that equivalent value explicitly.
172
- settings.setDefaultThinkingLevel((level ?? "medium") as any);
173
- await settings.flush();
174
- },
175
- };
176
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-ultracode",
3
- "version": "0.4.0",
4
- "description": "Claude-Code-style \"ultracode\" for Pi: an effort mode that defaults to deterministic multi-agent workflow orchestration, with worktree isolation, per-agent model overrides, custom agent types, nested workflows, resumable runs, and a /workflows manager.",
3
+ "version": "0.6.0",
4
+ "description": "Adaptive semantic-depth workflow orchestration for Pi, with focused, standard, and deep modes, isolated subagents, worktree delivery, structured output, and durable resume.",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "pi-package",
package/src/commands.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
+ import { ACTIVE_ULTRACODE_MODES, isActiveUltracodeMode } from "./depth.ts";
6
7
  import type { UltracodeMode } from "./mode.ts";
7
8
  import type { WorkflowRegistry } from "./workflow/registry.ts";
8
9
  import { workflowRunsDir } from "./workflow/tool.ts";
@@ -10,59 +11,60 @@ import { openWorkflowOverlay } from "./workflow/workflow-overlay.ts";
10
11
 
11
12
  export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode, registry: WorkflowRegistry): void {
12
13
  pi.registerCommand("ultracode", {
13
- description: "Toggle ultracode mode (max thinking + default workflow orchestration). Bare /ultracode toggles; subcommands: on|off|status",
14
+ description: "Toggle adaptive Ultracode, or select a fixed semantic depth: auto|focused|standard|deep|off|status",
14
15
  getArgumentCompletions(prefix: string) {
15
- return ["on", "off", "status"]
16
- .filter((s) => s.startsWith(prefix))
16
+ return [...ACTIVE_ULTRACODE_MODES, "off", "status"]
17
+ .filter((value) => value.startsWith(prefix))
17
18
  .map((value) => ({ value, label: value }));
18
19
  },
19
20
  handler: async (args: string, ctx) => {
20
- mode.setCurrentModelSupportsThinking(ctx.model ? Boolean(ctx.model.reasoning) : undefined);
21
21
  const parts = args.trim().split(/\s+/).filter(Boolean);
22
22
  const sub = (parts[0] ?? "").toLowerCase();
23
23
 
24
- // Bare `/ultracode` is a toggle.
24
+ // Bare `/ultracode` enables auto from off and disables any active mode.
25
25
  if (sub === "") {
26
26
  const nowOn = mode.toggle(pi);
27
- await mode.flushThinkingPreference();
28
27
  ctx.ui.notify(
29
- nowOn ? `Ultracode on — ${mode.statusLine()}` : "Ultracode off — thinking restored and workflow tool disabled.",
28
+ nowOn
29
+ ? `Ultracode auto — ${mode.statusLine()}`
30
+ : "Ultracode off — workflow tool disabled; parent effort unchanged.",
30
31
  "info",
31
32
  );
32
- ctx.ui.setStatus("ultracode", nowOn ? mode.statusLine() : undefined);
33
+ ctx.ui.setStatus(
34
+ "ultracode",
35
+ nowOn ? mode.statusLine((label) => ctx.ui.theme.fg("accent", label)) : undefined,
36
+ );
37
+ return;
38
+ }
39
+
40
+ if (parts.length > 1) {
41
+ ctx.ui.notify(ultracodeUsage(), "error");
33
42
  return;
34
43
  }
35
44
 
36
45
  if (sub === "status") {
37
- if (parts.length > 1) {
38
- ctx.ui.notify(ultracodeUsage(), "error");
39
- return;
40
- }
41
46
  ctx.ui.notify(mode.statusLine(), "info");
42
47
  return;
43
48
  }
44
49
 
45
50
  if (sub === "off") {
46
- if (parts.length > 1) {
47
- ctx.ui.notify(ultracodeUsage(), "error");
48
- return;
49
- }
50
51
  mode.disable(pi);
51
- await mode.flushThinkingPreference();
52
- ctx.ui.notify("Ultracode off — thinking restored and workflow tool disabled.", "info");
52
+ ctx.ui.notify("Ultracode off — workflow tool disabled; parent effort unchanged.", "info");
53
53
  ctx.ui.setStatus("ultracode", undefined);
54
54
  return;
55
55
  }
56
56
 
57
- if (sub !== "on" || parts.length > 1) {
57
+ if (!isActiveUltracodeMode(sub)) {
58
58
  ctx.ui.notify(ultracodeUsage(), "error");
59
59
  return;
60
60
  }
61
61
 
62
- mode.enable(pi);
63
- await mode.flushThinkingPreference();
64
- ctx.ui.notify(`Ultracode on — ${mode.statusLine()}`, "info");
65
- ctx.ui.setStatus("ultracode", mode.statusLine());
62
+ mode.enable(pi, sub);
63
+ ctx.ui.notify(`Ultracode ${sub} — ${mode.statusLine()}`, "info");
64
+ ctx.ui.setStatus(
65
+ "ultracode",
66
+ mode.statusLine((label) => ctx.ui.theme.fg("accent", label)),
67
+ );
66
68
  },
67
69
  });
68
70
 
@@ -100,5 +102,5 @@ export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode, registry
100
102
  }
101
103
 
102
104
  function ultracodeUsage(): string {
103
- return "Usage: /ultracode [on|off|status]";
105
+ return "Usage: /ultracode [auto|focused|standard|deep|off|status]";
104
106
  }
package/src/depth.ts ADDED
@@ -0,0 +1,37 @@
1
+ /** Ultracode's configured semantic analysis-depth modes. */
2
+
3
+ import type { ThinkingLevel } from "./thinking.ts";
4
+
5
+ export const ACTIVE_ULTRACODE_MODES = ["auto", "focused", "standard", "deep"] as const;
6
+
7
+ export type ActiveUltracodeMode = (typeof ACTIVE_ULTRACODE_MODES)[number];
8
+ export type UltracodeModeName = "off" | ActiveUltracodeMode;
9
+
10
+ const ACTIVE_MODE_SET = new Set<string>(ACTIVE_ULTRACODE_MODES);
11
+
12
+ export function isActiveUltracodeMode(value: unknown): value is ActiveUltracodeMode {
13
+ return typeof value === "string" && ACTIVE_MODE_SET.has(value);
14
+ }
15
+
16
+ export function isUltracodeModeName(value: unknown): value is UltracodeModeName {
17
+ return value === "off" || isActiveUltracodeMode(value);
18
+ }
19
+
20
+ /**
21
+ * @deprecated Legacy mode-to-effort mapping retained for API compatibility.
22
+ * Ultracode no longer applies it to the parent or as a workflow child default;
23
+ * each child selects effort per task and Pi clamps it to model capabilities.
24
+ */
25
+ export function thinkingLevelForMode(mode: UltracodeModeName): ThinkingLevel | undefined {
26
+ switch (mode) {
27
+ case "focused":
28
+ return "medium";
29
+ case "auto":
30
+ case "standard":
31
+ return "high";
32
+ case "deep":
33
+ return "max";
34
+ case "off":
35
+ return undefined;
36
+ }
37
+ }
package/src/index.ts CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  export { default } from "../extensions/ultracode.ts";
4
4
  export { UltracodeMode, MODE_ENTRY_TYPE } from "./mode.ts";
5
+ export {
6
+ ACTIVE_ULTRACODE_MODES,
7
+ isActiveUltracodeMode,
8
+ isUltracodeModeName,
9
+ thinkingLevelForMode,
10
+ type ActiveUltracodeMode,
11
+ type UltracodeModeName,
12
+ } from "./depth.ts";
5
13
  export { registerCommands } from "./commands.ts";
6
14
  export {
7
15
  ULTRACODE_TAGLINE,