omni-pi 0.2.0 → 0.3.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 +48 -93
- package/agents/brain.md +7 -7
- package/agents/expert.md +3 -3
- package/agents/planner.md +3 -3
- package/agents/worker.md +3 -3
- package/extensions/omni-core/index.ts +18 -15
- package/extensions/omni-memory/index.ts +2 -2
- package/extensions/omni-providers/index.ts +2 -6
- package/extensions/omni-skills/index.ts +2 -8
- package/extensions/omni-status/index.ts +2 -8
- package/package.json +7 -14
- package/src/brain.ts +117 -0
- package/src/commands.ts +2 -530
- package/src/config.ts +2 -2
- package/src/model-setup.ts +1064 -0
- package/src/planning.ts +15 -15
- package/src/provider-catalog.json +20391 -0
- package/src/providers.ts +374 -361
- package/src/status.ts +82 -24
- package/src/tasks.ts +6 -6
- package/src/templates.ts +13 -57
- package/src/work.ts +21 -21
- package/src/workflow.ts +11 -12
- package/templates/omni/STATE.md +2 -2
- package/templates/omni/TESTS.md +3 -3
- package/bin/omni.js +0 -79
- package/templates/pi/agents/omni-expert.md +0 -13
- package/templates/pi/agents/omni-worker.md +0 -13
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Omni-Pi
|
|
2
2
|
|
|
3
|
-
Omni-Pi
|
|
3
|
+
Omni-Pi is a Pi package built around one user-facing brain.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The goal is simple: talk to a helpful agent, let it interview you until the request is precise, have it write the spec and task breakdown into `.omni/`, then implement the work in bounded slices with explicit verification and progress notes.
|
|
6
6
|
|
|
7
7
|
Requires Node.js 22 or newer.
|
|
8
8
|
|
|
@@ -10,134 +10,89 @@ Requires Node.js 22 or newer.
|
|
|
10
10
|
[](https://www.npmjs.com/package/omni-pi)
|
|
11
11
|
[](https://github.com/EdGy2k/Omni-Pi/actions/workflows/ci.yml)
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## What It Does
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
## Quick Start
|
|
21
|
-
|
|
22
|
-
Install Omni-Pi from npm, then run it in your project:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npm install -g omni-pi
|
|
26
|
-
cd your-project
|
|
27
|
-
omni
|
|
28
|
-
```
|
|
15
|
+
- One friendly brain talks to the user.
|
|
16
|
+
- `.omni/` remains the durable memory layer for goals, specs, tasks, checks, progress, and decisions.
|
|
17
|
+
- Work is still broken into small, verifiable slices before code changes happen.
|
|
18
|
+
- Verification remains explicit and should be recorded alongside implementation progress.
|
|
29
19
|
|
|
30
20
|
## Install
|
|
31
21
|
|
|
32
|
-
Install the
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm install -g omni-pi
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Confirm the launcher is available:
|
|
22
|
+
Install the package into Pi:
|
|
39
23
|
|
|
40
24
|
```bash
|
|
41
|
-
omni
|
|
25
|
+
pi install npm:omni-pi
|
|
42
26
|
```
|
|
43
27
|
|
|
44
|
-
|
|
28
|
+
For a project-local install instead of a global one:
|
|
45
29
|
|
|
46
30
|
```bash
|
|
47
|
-
|
|
48
|
-
omni
|
|
31
|
+
pi install -l npm:omni-pi
|
|
49
32
|
```
|
|
50
33
|
|
|
51
|
-
|
|
34
|
+
For local development from this checkout:
|
|
52
35
|
|
|
53
36
|
```bash
|
|
54
|
-
|
|
37
|
+
pi install /Users/edgy/personal/Omni-Pi
|
|
55
38
|
```
|
|
56
39
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
## Model Providers
|
|
60
|
-
|
|
61
|
-
Omni-Pi now ships the upstream provider mix needed for practical multi-provider use on top of Pi.
|
|
62
|
-
|
|
63
|
-
- Built into the underlying Pi runtime: `anthropic`, `openai`, `openai-codex`, `google`, `google-vertex`, `amazon-bedrock`, `azure-openai-responses`, `openrouter`, `xai`, `zai`, `mistral`, `groq`, `cerebras`, `huggingface`, `github-copilot`, `kimi-coding`, `minimax`, `minimax-cn`, `opencode`, `opencode-go`
|
|
64
|
-
- Added by Omni-Pi: `nvidia`, `together`, `synthetic`, `nanogpt`, `xiaomi`, `moonshot`, `venice`, `kilo`, `gitlab-duo`, `qwen-portal`, `qianfan`, `cloudflare-ai-gateway`
|
|
65
|
-
- Auto-discovered when running locally: `ollama`, `lm-studio`, `llama.cpp`, `litellm`, `vllm`
|
|
66
|
-
|
|
67
|
-
For users who do not want to rely on Anthropic OAuth inside Pi, Omni-Pi also exposes opt-in Claude Agent SDK model aliases:
|
|
68
|
-
|
|
69
|
-
- `claude-agent/claude-sonnet-4-6`
|
|
70
|
-
- `claude-agent/claude-opus-4-6`
|
|
71
|
-
|
|
72
|
-
These are intended for Omni-Pi's worker and expert subagents. Configure a role with `/omni-model` and Omni-Pi will run that subagent through the Claude Agent SDK instead of Pi's normal Anthropic provider path.
|
|
73
|
-
|
|
74
|
-
Common provider env vars:
|
|
40
|
+
## Use
|
|
75
41
|
|
|
76
|
-
-
|
|
77
|
-
- `XIAOMI_API_KEY`, `MOONSHOT_API_KEY`, `VENICE_API_KEY`, `KILO_API_KEY`
|
|
78
|
-
- `GITLAB_TOKEN`, `QWEN_OAUTH_TOKEN` or `QWEN_PORTAL_API_KEY`, `QIANFAN_API_KEY`
|
|
79
|
-
- `CLOUDFLARE_AI_GATEWAY_API_KEY` and `CLOUDFLARE_AI_GATEWAY_BASE_URL`
|
|
42
|
+
Start Pi in the project you want to work on, with Omni-Pi installed, and describe what you want.
|
|
80
43
|
|
|
81
|
-
|
|
44
|
+
Example:
|
|
82
45
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- `LITELLM_BASE_URL` / `LITELLM_API_KEY`
|
|
87
|
-
- `VLLM_BASE_URL` / `VLLM_API_KEY`
|
|
88
|
-
|
|
89
|
-
## Commands
|
|
90
|
-
|
|
91
|
-
| Command | Description |
|
|
92
|
-
|---------|-------------|
|
|
93
|
-
| `/omni-init` | Initialize `.omni/` project memory, run quick-start wizard, scan repo signals, run health checks (`--quick` to skip wizard) |
|
|
94
|
-
| `/omni-plan` | Create or refresh spec, tasks, and tests (supports `--preset bugfix/feature/refactor/spike/security-audit`) |
|
|
95
|
-
| `/omni-work` | Run the next task through worker, verifier, and expert fallback |
|
|
96
|
-
| `/omni-status` | Show current phase, task, blockers, next step (add `metrics` for agent stats) |
|
|
97
|
-
| `/omni-sync` | Update durable memory files from recent progress |
|
|
98
|
-
| `/omni-skills` | Inspect installed, recommended, deferred, and rejected skills |
|
|
99
|
-
| `/omni-explain` | Explain what Omni-Pi is doing in simple language |
|
|
100
|
-
| `/omni-model` | Interactively select the model for a specific agent role, or enter any canonical `provider/model` reference |
|
|
101
|
-
| `/omni-commit` | Create a branch and commit for the last completed task |
|
|
102
|
-
| `/omni-doctor` | Run diagnostic health checks and detect stuck tasks |
|
|
103
|
-
|
|
104
|
-
## How It Works
|
|
46
|
+
```text
|
|
47
|
+
Build a small CLI notes app for me. I want add, list, and search commands. Store data locally in JSON. Ask me any questions you need before you start coding.
|
|
48
|
+
```
|
|
105
49
|
|
|
106
|
-
|
|
50
|
+
Expected behavior:
|
|
107
51
|
|
|
108
|
-
|
|
52
|
+
- Omni-Pi interviews first when the request is underspecified.
|
|
53
|
+
- It writes and updates `.omni/PROJECT.md`, `.omni/SPEC.md`, `.omni/TASKS.md`, `.omni/TESTS.md`, and `.omni/STATE.md`.
|
|
54
|
+
- It hides internal implementation machinery instead of talking about planner/worker/expert handoffs.
|
|
55
|
+
- It implements one bounded slice at a time and runs the planned checks.
|
|
109
56
|
|
|
110
|
-
|
|
57
|
+
## Durable Memory
|
|
111
58
|
|
|
112
|
-
|
|
59
|
+
Omni-Pi keeps its working notes in `.omni/`:
|
|
113
60
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
- Context-aware file selection for different workflow phases.
|
|
120
|
-
- Subagent integration for worker and expert execution with raw output persistence and model overrides.
|
|
121
|
-
- Persistent dashboard state for phase, task, blockers, next step, and health status.
|
|
122
|
-
- Git integration for branch creation and task-derived commits.
|
|
123
|
-
- Interactive planning for constraints, user context, and skill install tracking.
|
|
61
|
+
- `PROJECT.md` captures the problem, users, constraints, and success criteria.
|
|
62
|
+
- `SPEC.md` captures the exact requested behavior and implementation shape.
|
|
63
|
+
- `TASKS.md` breaks work into bounded slices.
|
|
64
|
+
- `TESTS.md` records the checks for the current slice.
|
|
65
|
+
- `STATE.md`, `SESSION-SUMMARY.md`, and `DECISIONS.md` keep progress and rationale durable across sessions.
|
|
124
66
|
|
|
125
67
|
## Development
|
|
126
68
|
|
|
127
|
-
For local checkout development, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
128
|
-
|
|
129
69
|
```bash
|
|
130
70
|
git clone https://github.com/EdGy2k/Omni-Pi.git
|
|
131
71
|
cd Omni-Pi
|
|
132
72
|
npm install
|
|
133
|
-
npm
|
|
73
|
+
npm run chat
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`npm run chat` launches Pi with this package loaded from the local checkout.
|
|
77
|
+
|
|
78
|
+
For local verification:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
134
81
|
npm run check
|
|
135
82
|
npm run lint
|
|
83
|
+
npm test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For package verification:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm pack
|
|
90
|
+
npm publish --dry-run
|
|
136
91
|
```
|
|
137
92
|
|
|
138
93
|
## Attribution
|
|
139
94
|
|
|
140
|
-
Omni-Pi builds on the Pi ecosystem. See [CREDITS.md](CREDITS.md)
|
|
95
|
+
Omni-Pi builds on the Pi ecosystem. See [CREDITS.md](CREDITS.md).
|
|
141
96
|
|
|
142
97
|
## License
|
|
143
98
|
|
package/agents/brain.md
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: brain
|
|
3
3
|
model: friendly-primary-model
|
|
4
|
-
description: User-facing
|
|
4
|
+
description: User-facing agent for Omni-Pi.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Brain
|
|
8
8
|
|
|
9
|
-
You are the user-facing
|
|
9
|
+
You are the single user-facing brain for Omni-Pi.
|
|
10
10
|
|
|
11
11
|
## Responsibilities
|
|
12
12
|
|
|
13
13
|
- Talk to the user in plain English.
|
|
14
|
-
-
|
|
14
|
+
- Interview the user until the requested behavior, constraints, and success criteria are exact.
|
|
15
15
|
- Update durable project memory through the `.omni/` file model.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- Break the work into bounded, verifiable slices before changing code.
|
|
17
|
+
- Implement the slices and report progress without exposing internal machinery unless asked.
|
|
18
18
|
|
|
19
19
|
## Rules
|
|
20
20
|
|
|
21
21
|
- Prefer clarity over jargon.
|
|
22
|
-
- Keep tasks small before
|
|
22
|
+
- Keep tasks small before implementing them.
|
|
23
23
|
- Record important changes in `.omni/STATE.md`, `.omni/SESSION-SUMMARY.md`, and `.omni/DECISIONS.md`.
|
|
24
|
-
-
|
|
24
|
+
- Use only the skills that materially help the current slice.
|
package/agents/expert.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: expert
|
|
3
3
|
model: strongest-implementation-model
|
|
4
|
-
description:
|
|
4
|
+
description: Archived recovery notes for Omni-Pi.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Recovery Notes
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This file is retained as recovery guidance, but Omni-Pi now exposes a single brain to the user instead of separate expert agents.
|
|
10
10
|
|
|
11
11
|
## Responsibilities
|
|
12
12
|
|
package/agents/planner.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: planner
|
|
3
3
|
model: strongest-reasoning-model
|
|
4
|
-
description:
|
|
4
|
+
description: Archived planner notes for Omni-Pi.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Planner
|
|
7
|
+
# Planner Notes
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This file is retained as planning guidance, but Omni-Pi now exposes a single brain to the user instead of separate planning agents.
|
|
10
10
|
|
|
11
11
|
## Responsibilities
|
|
12
12
|
|
package/agents/worker.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: worker
|
|
3
3
|
model: cheap-fast-model
|
|
4
|
-
description:
|
|
4
|
+
description: Archived implementation notes for Omni-Pi.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Implementation Notes
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This file is retained as implementation guidance, but Omni-Pi now exposes a single brain to the user instead of separate worker agents.
|
|
10
10
|
|
|
11
11
|
## Responsibilities
|
|
12
12
|
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
|
|
3
|
-
import { createOmniCommands } from "../../src/commands.js";
|
|
4
3
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "../../src/
|
|
4
|
+
buildBrainSystemPromptSuffix,
|
|
5
|
+
ensureOmniInitialized,
|
|
6
|
+
} from "../../src/brain.js";
|
|
7
|
+
import { registerOmniMessageRenderer } from "../../src/pi.js";
|
|
8
8
|
|
|
9
9
|
export default function omniCoreExtension(api: ExtensionAPI): void {
|
|
10
10
|
registerOmniMessageRenderer(api);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
|
|
12
|
+
api.on("session_start", async (_event, ctx) => {
|
|
13
|
+
await ensureOmniInitialized(ctx.cwd);
|
|
14
|
+
ctx.ui.setStatus("omni", undefined);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
api.on("before_agent_start", async (event, ctx) => {
|
|
18
|
+
await ensureOmniInitialized(ctx.cwd);
|
|
19
|
+
const brainPrompt = await buildBrainSystemPromptSuffix(ctx.cwd);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
systemPrompt: `${event.systemPrompt}\n\n${brainPrompt}`,
|
|
23
|
+
};
|
|
24
|
+
});
|
|
22
25
|
}
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
|
|
9
9
|
import type { OmniState } from "../../src/contracts.js";
|
|
10
10
|
import { runDoctor } from "../../src/doctor.js";
|
|
11
|
-
import {
|
|
11
|
+
import { renderCompactStatusWidget } from "../../src/status.js";
|
|
12
12
|
|
|
13
13
|
async function readState(cwd: string): Promise<OmniState | null> {
|
|
14
14
|
try {
|
|
@@ -49,7 +49,7 @@ async function updateWidget(ctx: ExtensionContext): Promise<void> {
|
|
|
49
49
|
const report = await runDoctor(ctx.cwd);
|
|
50
50
|
ctx.ui.setWidget(
|
|
51
51
|
"omni-dashboard",
|
|
52
|
-
|
|
52
|
+
(_tui, theme) => renderCompactStatusWidget(state, theme, report.overall),
|
|
53
53
|
{ placement: "aboveEditor" },
|
|
54
54
|
);
|
|
55
55
|
} else {
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
|
|
3
|
-
import { registerOmniProviders } from "../../src/providers.js";
|
|
4
|
-
|
|
5
1
|
export default async function omniProvidersExtension(
|
|
6
|
-
|
|
2
|
+
_api: unknown,
|
|
7
3
|
): Promise<void> {
|
|
8
|
-
|
|
4
|
+
return;
|
|
9
5
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default function omniSkillsExtension(api: ExtensionAPI): void {
|
|
7
|
-
const commands = createOmniCommands().filter((command) =>
|
|
8
|
-
["omni-skills"].includes(command.name),
|
|
9
|
-
);
|
|
10
|
-
registerPiCommands(api, commands);
|
|
3
|
+
export default function omniSkillsExtension(_api: ExtensionAPI): void {
|
|
4
|
+
// The simplified single-agent flow no longer exposes slash commands.
|
|
11
5
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default function omniStatusExtension(api: ExtensionAPI): void {
|
|
7
|
-
const commands = createOmniCommands().filter((command) =>
|
|
8
|
-
["omni-status", "omni-explain", "omni-doctor"].includes(command.name),
|
|
9
|
-
);
|
|
10
|
-
registerPiCommands(api, commands);
|
|
3
|
+
export default function omniStatusExtension(_api: ExtensionAPI): void {
|
|
4
|
+
// The simplified single-agent flow no longer exposes slash commands.
|
|
11
5
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omni-pi",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Single-agent Pi package that interviews the user, documents the spec, and implements work in bounded slices.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Eduard-David Gyarmati",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/EdGy2k/Omni-Pi.git"
|
|
10
|
+
"url": "git+https://github.com/EdGy2k/Omni-Pi.git"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://github.com/EdGy2k/Omni-Pi#readme",
|
|
13
13
|
"bugs": {
|
|
@@ -16,19 +16,15 @@
|
|
|
16
16
|
"engines": {
|
|
17
17
|
"node": ">=22"
|
|
18
18
|
},
|
|
19
|
-
"bin": {
|
|
20
|
-
"omni": "./bin/omni.js"
|
|
21
|
-
},
|
|
22
19
|
"keywords": [
|
|
23
20
|
"pi-package",
|
|
24
21
|
"pi",
|
|
25
22
|
"agent",
|
|
26
23
|
"planning",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
24
|
+
"implementation",
|
|
25
|
+
"interview"
|
|
29
26
|
],
|
|
30
27
|
"files": [
|
|
31
|
-
"bin",
|
|
32
28
|
"agents",
|
|
33
29
|
"extensions",
|
|
34
30
|
"prompts",
|
|
@@ -39,6 +35,7 @@
|
|
|
39
35
|
"CREDITS.md"
|
|
40
36
|
],
|
|
41
37
|
"scripts": {
|
|
38
|
+
"chat": "node ./node_modules/@mariozechner/pi-coding-agent/dist/cli.js -e .",
|
|
42
39
|
"check": "tsc --noEmit",
|
|
43
40
|
"lint": "biome check .",
|
|
44
41
|
"format": "biome check --write .",
|
|
@@ -54,13 +51,9 @@
|
|
|
54
51
|
},
|
|
55
52
|
"pi": {
|
|
56
53
|
"extensions": [
|
|
57
|
-
"./node_modules/pi-subagents/index.ts",
|
|
58
|
-
"./node_modules/pi-subagents/notify.ts",
|
|
59
54
|
"./extensions/omni-providers/index.ts",
|
|
60
55
|
"./extensions/omni-core/index.ts",
|
|
61
|
-
"./extensions/omni-memory/index.ts"
|
|
62
|
-
"./extensions/omni-skills/index.ts",
|
|
63
|
-
"./extensions/omni-status/index.ts"
|
|
56
|
+
"./extensions/omni-memory/index.ts"
|
|
64
57
|
],
|
|
65
58
|
"skills": [
|
|
66
59
|
"./skills"
|
package/src/brain.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { OmniState } from "./contracts.js";
|
|
5
|
+
import { initializeOmniProject, readOmniStatus } from "./workflow.js";
|
|
6
|
+
|
|
7
|
+
const BRAIN_SYSTEM_APPEND = `## Omni-Pi Single-Brain Mode
|
|
8
|
+
|
|
9
|
+
You are Omni-Pi's only user-facing brain.
|
|
10
|
+
|
|
11
|
+
Your workflow is mandatory:
|
|
12
|
+
1. Interview the user until the requested behavior, constraints, and success criteria are concrete enough to implement safely.
|
|
13
|
+
2. Before editing code, make sure the durable project notes in .omni/ reflect the current understanding.
|
|
14
|
+
3. Break the requested work into bounded, verifiable slices in .omni/TASKS.md before implementation.
|
|
15
|
+
4. Implement one slice at a time.
|
|
16
|
+
5. Run the planned checks, record progress in .omni/STATE.md and .omni/SESSION-SUMMARY.md, and tighten the plan if a slice fails.
|
|
17
|
+
|
|
18
|
+
Behavior rules:
|
|
19
|
+
- Stay friendly, plain-spoken, and direct.
|
|
20
|
+
- Do not expose planner/worker/expert role handoffs. Everything happens behind the scenes.
|
|
21
|
+
- Ask targeted follow-up questions when the request is underspecified.
|
|
22
|
+
- Do not start editing code until the spec is explicit enough to avoid guessing.
|
|
23
|
+
- Keep documentation current in .omni/PROJECT.md, .omni/SPEC.md, .omni/TASKS.md, .omni/TESTS.md, .omni/STATE.md, and .omni/DECISIONS.md when relevant.
|
|
24
|
+
- When the user request is clear and bounded, move from interview to implementation without asking unnecessary extra questions.
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
async function fileExists(filePath: string): Promise<boolean> {
|
|
28
|
+
try {
|
|
29
|
+
await access(filePath);
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function readOptional(filePath: string): Promise<string | null> {
|
|
37
|
+
try {
|
|
38
|
+
return await readFile(filePath, "utf8");
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function renderStateSummary(state: OmniState | null): string {
|
|
45
|
+
if (!state) {
|
|
46
|
+
return "No durable Omni-Pi state exists yet.";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return [
|
|
50
|
+
`Current phase: ${state.currentPhase}`,
|
|
51
|
+
`Active task: ${state.activeTask}`,
|
|
52
|
+
`Status summary: ${state.statusSummary}`,
|
|
53
|
+
`Blockers: ${state.blockers.length > 0 ? state.blockers.join("; ") : "None"}`,
|
|
54
|
+
`Next step: ${state.nextStep}`,
|
|
55
|
+
].join("\n");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function clipSection(value: string | null, maxChars: number): string {
|
|
59
|
+
if (!value) {
|
|
60
|
+
return "- Missing";
|
|
61
|
+
}
|
|
62
|
+
const trimmed = value.trim();
|
|
63
|
+
if (trimmed.length <= maxChars) {
|
|
64
|
+
return trimmed;
|
|
65
|
+
}
|
|
66
|
+
return `${trimmed.slice(0, maxChars)}…`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function ensureOmniInitialized(
|
|
70
|
+
cwd: string,
|
|
71
|
+
): Promise<"initialized" | "existing"> {
|
|
72
|
+
const statePath = path.join(cwd, ".omni", "STATE.md");
|
|
73
|
+
if (await fileExists(statePath)) {
|
|
74
|
+
return "existing";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
await initializeOmniProject(cwd);
|
|
78
|
+
return "initialized";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function buildBrainSystemPromptSuffix(
|
|
82
|
+
cwd: string,
|
|
83
|
+
): Promise<string> {
|
|
84
|
+
const projectPath = path.join(cwd, ".omni", "PROJECT.md");
|
|
85
|
+
const specPath = path.join(cwd, ".omni", "SPEC.md");
|
|
86
|
+
const tasksPath = path.join(cwd, ".omni", "TASKS.md");
|
|
87
|
+
const testsPath = path.join(cwd, ".omni", "TESTS.md");
|
|
88
|
+
|
|
89
|
+
const state = await readOmniStatus(cwd).catch(() => null);
|
|
90
|
+
const [project, spec, tasks, tests] = await Promise.all([
|
|
91
|
+
readOptional(projectPath),
|
|
92
|
+
readOptional(specPath),
|
|
93
|
+
readOptional(tasksPath),
|
|
94
|
+
readOptional(testsPath),
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
return `${BRAIN_SYSTEM_APPEND}
|
|
98
|
+
|
|
99
|
+
## Current Durable State
|
|
100
|
+
|
|
101
|
+
${renderStateSummary(state)}
|
|
102
|
+
|
|
103
|
+
## Current Omni Files
|
|
104
|
+
|
|
105
|
+
### .omni/PROJECT.md
|
|
106
|
+
${clipSection(project, 1600)}
|
|
107
|
+
|
|
108
|
+
### .omni/SPEC.md
|
|
109
|
+
${clipSection(spec, 1600)}
|
|
110
|
+
|
|
111
|
+
### .omni/TASKS.md
|
|
112
|
+
${clipSection(tasks, 1600)}
|
|
113
|
+
|
|
114
|
+
### .omni/TESTS.md
|
|
115
|
+
${clipSection(tests, 1200)}
|
|
116
|
+
`;
|
|
117
|
+
}
|