pi-ultracode 0.3.2 → 0.5.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 +32 -14
- package/README.zh-CN.md +32 -14
- package/extensions/ultracode.ts +11 -10
- package/package.json +17 -7
- package/src/commands.ts +21 -22
- package/src/depth.ts +38 -0
- package/src/index.ts +9 -1
- package/src/mode.ts +82 -58
- package/src/prompts.ts +65 -32
- package/src/thinking.ts +1 -1
- package/src/workflow/agent-runner.ts +23 -8
- package/src/workflow/agent-types.ts +19 -15
- package/src/workflow/hermetic-git.ts +31 -0
- package/src/workflow/journal.ts +134 -3
- package/src/workflow/parser.ts +254 -38
- package/src/workflow/registry.ts +44 -67
- package/src/workflow/repository-context.ts +76 -0
- package/src/workflow/run-artifacts.ts +60 -14
- package/src/workflow/runtime.ts +380 -180
- package/src/workflow/saved-workflow.ts +37 -0
- package/src/workflow/script-executor.ts +56 -10
- package/src/workflow/script-worker.mjs +65 -19
- package/src/workflow/tool.ts +108 -58
- package/src/workflow/workflow-overlay.ts +4 -4
- package/src/workflow/worktree.ts +1965 -244
- package/types/workflow.d.ts +2 -4
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
|
|
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
|
|
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
|
|
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
|
-
- **
|
|
36
|
+
- **Adaptive semantic depth** — choose `auto`, `focused`, `standard`, or `deep`; `auto` selects the smallest evidence-sufficient depth and `off` restores the previous thinking level.
|
|
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
|
-
|
|
47
|
+
Enable adaptive Ultracode and describe a task:
|
|
48
48
|
|
|
49
49
|
```text
|
|
50
50
|
/ultracode
|
|
@@ -59,19 +59,35 @@ Useful commands:
|
|
|
59
59
|
|
|
60
60
|
| Command | Action |
|
|
61
61
|
| --- | --- |
|
|
62
|
-
| `/ultracode` |
|
|
63
|
-
| `/ultracode
|
|
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 and max effort |
|
|
64
67
|
| `/ultracode off` | Disable it and restore the previous thinking level |
|
|
65
|
-
| `/ultracode status` | Show the
|
|
68
|
+
| `/ultracode status` | Show the configured mode and effective thinking level |
|
|
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
|
+
Focused defaults to medium effort, auto and standard to high, and deep to max; individual workflow agents can still override effort with a model suffix. A separate skeptic or synthesis agent is not automatic.
|
|
87
|
+
|
|
72
88
|
## Workflow example
|
|
73
89
|
|
|
74
|
-
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`.
|
|
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.
|
|
75
91
|
|
|
76
92
|
```js
|
|
77
93
|
export const meta = {
|
|
@@ -107,7 +123,9 @@ Custom agent roles live in:
|
|
|
107
123
|
|
|
108
124
|
```text
|
|
109
125
|
.pi/ultracode/agents/*.md
|
|
126
|
+
.pi/agents/*.md
|
|
110
127
|
~/.pi/ultracode/agents/*.md
|
|
128
|
+
~/.pi/agent/agents/*.md
|
|
111
129
|
```
|
|
112
130
|
|
|
113
131
|
A call can select a role, model, thinking level, or worktree isolation:
|
|
@@ -121,17 +139,17 @@ await agent("Implement and test the fix.", {
|
|
|
121
139
|
});
|
|
122
140
|
```
|
|
123
141
|
|
|
124
|
-
Worktree isolation requires a git repository with at least one commit.
|
|
142
|
+
Worktree isolation requires a git repository with at least one commit and fails closed if the isolated tree cannot be created. Each call receives a unique detached worktree. Integration preserves the user's index and applies only byte-exact patches that pass cached checks in a private, object-format-matched Git index; raw blobs are then materialized without repository attributes, filters, or EOL conversion. A conflicting patch is saved for manual recovery instead of using a destructive three-way fallback. Successful delivery patches are retained so resume can verify that the shared-tree effect still exists. Isolated trees never link the shared writable `node_modules`; install dependencies there when needed, or run final tests after integration. A clean working tree is recommended for predictable patch integration.
|
|
125
143
|
|
|
126
144
|
## Guardrails
|
|
127
145
|
|
|
128
|
-
A workflow defaults to `maxAgents: 128`, supports at most 16 concurrent agent calls, and allows one level of nested workflows. The lifetime agent limit is preserved across resumes; cached replay does not consume it again.
|
|
146
|
+
A workflow defaults to `maxAgents: 128`, supports at most 16 concurrent agent calls, and allows one level of nested workflows. Nested `workflow()` calls accept only trust-aware saved-workflow names, not explicit paths. The lifetime agent limit is preserved across resumes; cached replay does not consume it again.
|
|
129
147
|
|
|
130
|
-
Workflow agent sessions retain project context and ordinary skills, but do not initialize ambient Pi extensions or expose parent orchestration tools and skills (`workflow`, `subagent`, `subagent_wait`, or `pi-subagents`). This keeps orchestration at the parent boundary and allows `pi-ultracode` and `pi-subagents` to coexist in the main session.
|
|
148
|
+
Workflow agent sessions retain project context and ordinary skills, but do not initialize ambient Pi extensions or expose parent orchestration tools and skills (`workflow`, `subagent`, `subagent_wait`, or `pi-subagents`). This keeps orchestration at the parent boundary and allows `pi-ultracode` and `pi-subagents` to coexist in the main session. Project-scoped agents and settings follow Pi's project-trust decision. The built-in Explore and Plan roles have a sealed read-only tool list without shell or write tools.
|
|
131
149
|
|
|
132
|
-
Resume is intentionally immutable: the script, arguments, agent definitions, effective models, and call structure must still match. Changed work starts a new run.
|
|
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.
|
|
133
151
|
|
|
134
|
-
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.
|
|
135
153
|
|
|
136
154
|
## Design inspiration
|
|
137
155
|
|
package/README.zh-CN.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[English](README.md) · **简体中文**
|
|
6
6
|
|
|
7
|
-
`pi-ultracode` 为 Pi
|
|
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
|
|
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` 使用证据充分的最小深度,关闭时恢复之前的思考强度。
|
|
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
|
-
|
|
47
|
+
用主命令开启自适应 Ultracode,然后描述任务:
|
|
48
48
|
|
|
49
49
|
```text
|
|
50
50
|
/ultracode
|
|
@@ -59,19 +59,35 @@ Pi 会自行判断工作流是否有帮助。小任务仍可继续使用普通
|
|
|
59
59
|
|
|
60
60
|
| 命令 | 作用 |
|
|
61
61
|
| --- | --- |
|
|
62
|
-
| `/ultracode` |
|
|
63
|
-
| `/ultracode
|
|
62
|
+
| `/ultracode` | 关闭时开启 `auto`;任一模式已开启时关闭 |
|
|
63
|
+
| `/ultracode auto` | 使用自适应语义深度路由 |
|
|
64
|
+
| `/ultracode focused` | 固定使用轻量、聚焦的分析策略 |
|
|
65
|
+
| `/ultracode standard` | 固定使用平衡策略和条件验证 |
|
|
66
|
+
| `/ultracode deep` | 固定使用高保障深度验证和 max effort |
|
|
64
67
|
| `/ultracode off` | 关闭并恢复之前的思考强度 |
|
|
65
|
-
| `/ultracode status` |
|
|
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
|
+
Focused 默认使用 medium effort,auto 和 standard 默认使用 high,deep 使用 max;单个 workflow agent 仍可通过模型后缀覆盖 effort。skeptic 和独立 synthesis agent 都不是默认步骤。
|
|
87
|
+
|
|
72
88
|
## 工作流示例
|
|
73
89
|
|
|
74
|
-
通常由主代理自动编写工作流。需要复用时,可以保存到 `.pi/ultracode/workflows/*.workflow.js` 或 `~/.pi/ultracode/workflows/*.workflow.js
|
|
90
|
+
通常由主代理自动编写工作流。需要复用时,可以保存到 `.pi/ultracode/workflows/*.workflow.js` 或 `~/.pi/ultracode/workflows/*.workflow.js`。只有 Pi 将项目标记为可信后,才会发现项目级工作流;用户级工作流在未信任项目中仍可使用。
|
|
75
91
|
|
|
76
92
|
```js
|
|
77
93
|
export const meta = {
|
|
@@ -107,7 +123,9 @@ return findings.filter(Boolean);
|
|
|
107
123
|
|
|
108
124
|
```text
|
|
109
125
|
.pi/ultracode/agents/*.md
|
|
126
|
+
.pi/agents/*.md
|
|
110
127
|
~/.pi/ultracode/agents/*.md
|
|
128
|
+
~/.pi/agent/agents/*.md
|
|
111
129
|
```
|
|
112
130
|
|
|
113
131
|
每次调用都可以选择角色、模型、思考强度或 worktree 隔离:
|
|
@@ -121,17 +139,17 @@ await agent("Implement and test the fix.", {
|
|
|
121
139
|
});
|
|
122
140
|
```
|
|
123
141
|
|
|
124
|
-
Worktree 隔离只能在至少有一个 commit 的 Git
|
|
142
|
+
Worktree 隔离只能在至少有一个 commit 的 Git 仓库中使用;隔离树创建失败时会直接失败,不会回退到共享工作目录。每次调用都会获得唯一的 detached worktree。补丁集成不修改用户 index;byte-exact patch 会先在 object format 匹配的私有 Git index 中完成 cached check,再绕开仓库 attributes、filter 与 EOL 转换直接 materialize 原始 blob;冲突补丁会保存供人工恢复,不使用可能破坏 index 的三方合并回退。成功交付的补丁会保留,用于 resume 时校验共享树效果仍然存在。隔离树不会链接共享仓库的可写 `node_modules`;需要时请在隔离树中安装依赖,或在集成后执行最终测试。为保证补丁集成可预测,建议保持工作区干净。
|
|
125
143
|
|
|
126
144
|
## 执行边界
|
|
127
145
|
|
|
128
|
-
工作流默认使用 `maxAgents: 128`,最多并发运行 16
|
|
146
|
+
工作流默认使用 `maxAgents: 128`,最多并发运行 16 个代理,并只允许一层嵌套工作流。嵌套 `workflow()` 只接受经过 trust-aware discovery 的已保存工作流名称,不接受显式路径。累计代理上限会跨 resume 保留,缓存回放不会再次占用额度。
|
|
129
147
|
|
|
130
|
-
Workflow 子代理会保留项目上下文和普通 skills,但不会初始化环境中的 Pi 扩展,也不会暴露父级编排工具与 skill(`workflow`、`subagent`、`subagent_wait` 或 `pi-subagents`)。这样可把编排限制在父会话边界,同时允许 `pi-ultracode` 与 `pi-subagents`
|
|
148
|
+
Workflow 子代理会保留项目上下文和普通 skills,但不会初始化环境中的 Pi 扩展,也不会暴露父级编排工具与 skill(`workflow`、`subagent`、`subagent_wait` 或 `pi-subagents`)。这样可把编排限制在父会话边界,同时允许 `pi-ultracode` 与 `pi-subagents` 在主会话中共存。项目级代理和设置遵循 Pi 的项目信任结果;内置 Explore 与 Plan 角色使用封闭的只读工具列表,不包含 shell 或写入工具。
|
|
131
149
|
|
|
132
|
-
Resume
|
|
150
|
+
Resume 刻意保持不可变:规范化脚本、参数、规范仓库及仓内相对 cwd、项目信任上下文、代理定义、实际模型和调用结构都必须匹配。Worktree 交付会在修改共享仓库前先写入持久恢复意图;中断或冲突的交付会阻止自动回放,并报告恢复补丁。工作内容发生变化时,应启动新的 run。
|
|
133
151
|
|
|
134
|
-
Token 和成本只用于可观测性,不作为执行预算。Worker 与 VM
|
|
152
|
+
Token 和成本只用于可观测性,不作为执行预算。Worker 与 VM 限制用于确定性和存活性保护,不是安全沙箱,也不参与分析深度判断。
|
|
135
153
|
|
|
136
154
|
## 设计参考
|
|
137
155
|
|
package/extensions/ultracode.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* pi-ultracode extension entrypoint.
|
|
3
3
|
*
|
|
4
|
-
* Wires together
|
|
5
|
-
*
|
|
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
8
|
import {
|
|
@@ -17,6 +15,7 @@ import { createWorkflowTool, type WorkflowToolDeps } from "../src/workflow/tool.
|
|
|
17
15
|
import { UltracodeMode, type ThinkingPreferenceStore } from "../src/mode.ts";
|
|
18
16
|
import { isThinkingLevel, piVersionSupportsMaxThinking } from "../src/thinking.ts";
|
|
19
17
|
import { registerCommands } from "../src/commands.ts";
|
|
18
|
+
import { WorkflowRegistry } from "../src/workflow/registry.ts";
|
|
20
19
|
|
|
21
20
|
export interface ThinkingPreferenceContext {
|
|
22
21
|
cwd: string;
|
|
@@ -38,19 +37,21 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
|
|
|
38
37
|
...workflowDeps
|
|
39
38
|
} = extraDeps;
|
|
40
39
|
|
|
40
|
+
const registry = workflowDeps.registry ?? new WorkflowRegistry();
|
|
41
41
|
const workflowTool = createWorkflowTool({
|
|
42
42
|
getThinkingLevel: () => mode.getSubagentThinkingLevel(),
|
|
43
43
|
...workflowDeps,
|
|
44
|
+
registry,
|
|
44
45
|
isExecutionAllowed: () => mode.isEnforcing(),
|
|
45
46
|
});
|
|
46
47
|
pi.registerTool(workflowTool);
|
|
47
48
|
|
|
48
|
-
registerCommands(pi, mode);
|
|
49
|
+
registerCommands(pi, mode, registry);
|
|
49
50
|
|
|
50
51
|
// Opt-in via CLI flag: `pi --ultracode`.
|
|
51
52
|
pi.registerFlag("ultracode", {
|
|
52
53
|
type: "boolean",
|
|
53
|
-
description: "Start the session in
|
|
54
|
+
description: "Start the session in adaptive Ultracode mode.",
|
|
54
55
|
});
|
|
55
56
|
|
|
56
57
|
// SDK-created sessions can prompt without emitting session_start. Sync during
|
|
@@ -65,7 +66,7 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
|
|
|
65
66
|
if (event.toolName === workflowTool.name && !mode.isEnforcing()) {
|
|
66
67
|
return {
|
|
67
68
|
block: true,
|
|
68
|
-
reason: "The workflow tool is disabled. Run /ultracode
|
|
69
|
+
reason: "The workflow tool is disabled. Run /ultracode or select an Ultracode depth before using it.",
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
});
|
|
@@ -89,7 +90,7 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
|
|
|
89
90
|
// ignore
|
|
90
91
|
}
|
|
91
92
|
if (!mode.isEnabled() && pi.getFlag?.("ultracode") === true) {
|
|
92
|
-
mode.enable(pi);
|
|
93
|
+
mode.enable(pi, "auto");
|
|
93
94
|
}
|
|
94
95
|
// Registration makes extension tools discoverable; activation remains opt-in.
|
|
95
96
|
mode.syncWorkflowTool(pi);
|
|
@@ -125,7 +126,7 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
|
|
|
125
126
|
|
|
126
127
|
pi.on("session_shutdown", async () => {
|
|
127
128
|
// Quiesce first so late model/effort events cannot undo restoration. The
|
|
128
|
-
// persisted
|
|
129
|
+
// The persisted configured mode remains active for reload/resume/fork replacements.
|
|
129
130
|
mode.suspend(pi);
|
|
130
131
|
await mode.flushThinkingPreference();
|
|
131
132
|
});
|
|
@@ -134,7 +135,7 @@ export default function extension(pi: ExtensionAPI, extraDeps: UltracodeExtensio
|
|
|
134
135
|
// Reconcile the tool schema and always append the standing block on an
|
|
135
136
|
// enforcing turn, even when another active-tool writer caused drift.
|
|
136
137
|
mode.syncWorkflowTool(pi);
|
|
137
|
-
mode.
|
|
138
|
+
mode.reapplyConfiguredThinking(pi);
|
|
138
139
|
await mode.flushThinkingPreference();
|
|
139
140
|
return mode.beforeAgentStart(event);
|
|
140
141
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-ultracode",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.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",
|
|
@@ -69,10 +69,20 @@
|
|
|
69
69
|
"typebox": "*"
|
|
70
70
|
},
|
|
71
71
|
"peerDependenciesMeta": {
|
|
72
|
-
"@earendil-works/pi-agent-core": {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"@earendil-works/pi-
|
|
76
|
-
|
|
72
|
+
"@earendil-works/pi-agent-core": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"@earendil-works/pi-ai": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"@earendil-works/pi-coding-agent": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"@earendil-works/pi-tui": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"typebox": {
|
|
85
|
+
"optional": true
|
|
86
|
+
}
|
|
77
87
|
}
|
|
78
88
|
}
|
package/src/commands.ts
CHANGED
|
@@ -3,17 +3,18 @@
|
|
|
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
|
-
import {
|
|
8
|
+
import type { WorkflowRegistry } from "./workflow/registry.ts";
|
|
8
9
|
import { workflowRunsDir } from "./workflow/tool.ts";
|
|
9
10
|
import { openWorkflowOverlay } from "./workflow/workflow-overlay.ts";
|
|
10
11
|
|
|
11
|
-
export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode): void {
|
|
12
|
+
export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode, registry: WorkflowRegistry): void {
|
|
12
13
|
pi.registerCommand("ultracode", {
|
|
13
|
-
description: "Toggle
|
|
14
|
+
description: "Toggle adaptive Ultracode, or select a fixed semantic depth: auto|focused|standard|deep|off|status",
|
|
14
15
|
getArgumentCompletions(prefix: string) {
|
|
15
|
-
return [
|
|
16
|
-
.filter((
|
|
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) => {
|
|
@@ -21,32 +22,31 @@ export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode): void {
|
|
|
21
22
|
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
22
23
|
const sub = (parts[0] ?? "").toLowerCase();
|
|
23
24
|
|
|
24
|
-
// Bare `/ultracode`
|
|
25
|
+
// Bare `/ultracode` enables auto from off and disables any active mode.
|
|
25
26
|
if (sub === "") {
|
|
26
27
|
const nowOn = mode.toggle(pi);
|
|
27
28
|
await mode.flushThinkingPreference();
|
|
28
29
|
ctx.ui.notify(
|
|
29
|
-
nowOn
|
|
30
|
+
nowOn
|
|
31
|
+
? `Ultracode auto — ${mode.statusLine()}`
|
|
32
|
+
: "Ultracode off — thinking restored and workflow tool disabled.",
|
|
30
33
|
"info",
|
|
31
34
|
);
|
|
32
35
|
ctx.ui.setStatus("ultracode", nowOn ? mode.statusLine() : undefined);
|
|
33
36
|
return;
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
if (parts.length > 1) {
|
|
40
|
+
ctx.ui.notify(ultracodeUsage(), "error");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
if (sub === "status") {
|
|
37
|
-
if (parts.length > 1) {
|
|
38
|
-
ctx.ui.notify(ultracodeUsage(), "error");
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
45
|
ctx.ui.notify(mode.statusLine(), "info");
|
|
42
46
|
return;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
if (sub === "off") {
|
|
46
|
-
if (parts.length > 1) {
|
|
47
|
-
ctx.ui.notify(ultracodeUsage(), "error");
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
50
|
mode.disable(pi);
|
|
51
51
|
await mode.flushThinkingPreference();
|
|
52
52
|
ctx.ui.notify("Ultracode off — thinking restored and workflow tool disabled.", "info");
|
|
@@ -54,20 +54,19 @@ export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode): void {
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (sub
|
|
57
|
+
if (!isActiveUltracodeMode(sub)) {
|
|
58
58
|
ctx.ui.notify(ultracodeUsage(), "error");
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
mode.enable(pi);
|
|
62
|
+
mode.enable(pi, sub);
|
|
63
63
|
await mode.flushThinkingPreference();
|
|
64
|
-
ctx.ui.notify(`Ultracode
|
|
64
|
+
ctx.ui.notify(`Ultracode ${sub} — ${mode.statusLine()}`, "info");
|
|
65
65
|
ctx.ui.setStatus("ultracode", mode.statusLine());
|
|
66
66
|
},
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
const openWorkflows = async (ctx: any, runId?: string) => {
|
|
70
|
-
const registry = getRegistry();
|
|
71
70
|
registry.restoreRuns(workflowRunsDir(ctx));
|
|
72
71
|
await openWorkflowOverlay(ctx, registry, runId);
|
|
73
72
|
};
|
|
@@ -77,7 +76,7 @@ export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode): void {
|
|
|
77
76
|
getArgumentCompletions(prefix: string) {
|
|
78
77
|
const values = [
|
|
79
78
|
"abort",
|
|
80
|
-
...
|
|
79
|
+
...registry.list().map((handle) => handle.snapshot.runId).filter((runId): runId is string => Boolean(runId)),
|
|
81
80
|
];
|
|
82
81
|
return [...new Set(values)]
|
|
83
82
|
.filter((value) => value.startsWith(prefix))
|
|
@@ -86,7 +85,7 @@ export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode): void {
|
|
|
86
85
|
handler: async (args: string, ctx) => {
|
|
87
86
|
const arg = args.trim();
|
|
88
87
|
if (arg.toLowerCase() === "abort") {
|
|
89
|
-
|
|
88
|
+
registry.abortAll();
|
|
90
89
|
ctx.ui.notify("Requested abort of all active workflow runs.", "warning");
|
|
91
90
|
return;
|
|
92
91
|
}
|
|
@@ -101,5 +100,5 @@ export function registerCommands(pi: ExtensionAPI, mode: UltracodeMode): void {
|
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
function ultracodeUsage(): string {
|
|
104
|
-
return "Usage: /ultracode [
|
|
103
|
+
return "Usage: /ultracode [auto|focused|standard|deep|off|status]";
|
|
105
104
|
}
|
package/src/depth.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Ultracode's configured analysis modes and their default reasoning effort. */
|
|
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
|
+
* Default effort for the parent turn and for child agents that do not override
|
|
22
|
+
* it explicitly. Auto starts from the balanced standard effort; its prompt
|
|
23
|
+
* policy can route individual workflow agents lower or higher as evidence
|
|
24
|
+
* requires. Pi still clamps each request to the selected model's capabilities.
|
|
25
|
+
*/
|
|
26
|
+
export function thinkingLevelForMode(mode: UltracodeModeName): ThinkingLevel | undefined {
|
|
27
|
+
switch (mode) {
|
|
28
|
+
case "focused":
|
|
29
|
+
return "medium";
|
|
30
|
+
case "auto":
|
|
31
|
+
case "standard":
|
|
32
|
+
return "high";
|
|
33
|
+
case "deep":
|
|
34
|
+
return "max";
|
|
35
|
+
case "off":
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
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,
|
|
@@ -41,7 +49,7 @@ export {
|
|
|
41
49
|
type AgentTypeDef,
|
|
42
50
|
} from "./workflow/agent-types.ts";
|
|
43
51
|
export { RunJournal, agentCallKey, hashString, stableStringify } from "./workflow/journal.ts";
|
|
44
|
-
export {
|
|
52
|
+
export { WorkflowRegistry } from "./workflow/registry.ts";
|
|
45
53
|
export {
|
|
46
54
|
createSnapshot,
|
|
47
55
|
recompute,
|