omni-pi 0.2.0 → 0.3.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.
- package/README.md +44 -92
- 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/bin/omni.js +17 -2
- 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 +8 -11
- 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/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,86 @@ 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
|
|
22
|
+
Install the standalone executable:
|
|
33
23
|
|
|
34
24
|
```bash
|
|
35
25
|
npm install -g omni-pi
|
|
36
26
|
```
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
omni --help
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Then open any project directory and start Omni-Pi:
|
|
28
|
+
Then run it in any project:
|
|
45
29
|
|
|
46
30
|
```bash
|
|
47
31
|
cd your-project
|
|
48
32
|
omni
|
|
49
33
|
```
|
|
50
34
|
|
|
51
|
-
|
|
35
|
+
For local development from this checkout:
|
|
52
36
|
|
|
53
37
|
```bash
|
|
54
|
-
|
|
38
|
+
git clone https://github.com/EdGy2k/Omni-Pi.git
|
|
39
|
+
cd Omni-Pi
|
|
40
|
+
npm install
|
|
41
|
+
npm run chat
|
|
55
42
|
```
|
|
56
43
|
|
|
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`
|
|
44
|
+
## Use
|
|
66
45
|
|
|
67
|
-
|
|
46
|
+
Start Pi in the project you want to work on, with Omni-Pi installed, and describe what you want.
|
|
68
47
|
|
|
69
|
-
|
|
70
|
-
- `claude-agent/claude-opus-4-6`
|
|
48
|
+
Example:
|
|
71
49
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- `NVIDIA_API_KEY`, `TOGETHER_API_KEY`, `SYNTHETIC_API_KEY`, `NANO_GPT_API_KEY`
|
|
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`
|
|
80
|
-
|
|
81
|
-
For local providers, Omni-Pi registers models only when the endpoint is reachable:
|
|
82
|
-
|
|
83
|
-
- `OLLAMA_BASE_URL` / `OLLAMA_API_KEY`
|
|
84
|
-
- `LM_STUDIO_BASE_URL` / `LM_STUDIO_API_KEY`
|
|
85
|
-
- `LLAMA_CPP_BASE_URL` / `LLAMA_CPP_API_KEY`
|
|
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
|
|
50
|
+
```text
|
|
51
|
+
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.
|
|
52
|
+
```
|
|
105
53
|
|
|
106
|
-
|
|
54
|
+
Expected behavior:
|
|
107
55
|
|
|
108
|
-
|
|
56
|
+
- Omni-Pi interviews first when the request is underspecified.
|
|
57
|
+
- It writes and updates `.omni/PROJECT.md`, `.omni/SPEC.md`, `.omni/TASKS.md`, `.omni/TESTS.md`, and `.omni/STATE.md`.
|
|
58
|
+
- It hides internal implementation machinery instead of talking about planner/worker/expert handoffs.
|
|
59
|
+
- It implements one bounded slice at a time and runs the planned checks.
|
|
109
60
|
|
|
110
|
-
|
|
61
|
+
## Durable Memory
|
|
111
62
|
|
|
112
|
-
|
|
63
|
+
Omni-Pi keeps its working notes in `.omni/`:
|
|
113
64
|
|
|
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.
|
|
65
|
+
- `PROJECT.md` captures the problem, users, constraints, and success criteria.
|
|
66
|
+
- `SPEC.md` captures the exact requested behavior and implementation shape.
|
|
67
|
+
- `TASKS.md` breaks work into bounded slices.
|
|
68
|
+
- `TESTS.md` records the checks for the current slice.
|
|
69
|
+
- `STATE.md`, `SESSION-SUMMARY.md`, and `DECISIONS.md` keep progress and rationale durable across sessions.
|
|
124
70
|
|
|
125
71
|
## Development
|
|
126
72
|
|
|
127
|
-
|
|
73
|
+
`npm run chat` launches the local `omni` wrapper from this checkout, which in turn starts Pi with this package loaded.
|
|
74
|
+
|
|
75
|
+
For local verification:
|
|
128
76
|
|
|
129
77
|
```bash
|
|
130
|
-
git clone https://github.com/EdGy2k/Omni-Pi.git
|
|
131
|
-
cd Omni-Pi
|
|
132
|
-
npm install
|
|
133
|
-
npm test
|
|
134
78
|
npm run check
|
|
135
79
|
npm run lint
|
|
80
|
+
npm test
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For package verification:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm pack
|
|
87
|
+
npm publish --dry-run
|
|
136
88
|
```
|
|
137
89
|
|
|
138
90
|
## Attribution
|
|
139
91
|
|
|
140
|
-
Omni-Pi builds on the Pi ecosystem. See [CREDITS.md](CREDITS.md)
|
|
92
|
+
Omni-Pi builds on the Pi ecosystem. See [CREDITS.md](CREDITS.md).
|
|
141
93
|
|
|
142
94
|
## License
|
|
143
95
|
|
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
|
|
package/bin/omni.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
|
+
import { realpathSync } from "node:fs";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
|
|
@@ -70,8 +71,22 @@ export async function runOmni(argv = process.argv.slice(2), options = {}) {
|
|
|
70
71
|
});
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
export function isOmniEntrypointInvocation(
|
|
75
|
+
argvPath = process.argv[1],
|
|
76
|
+
moduleUrl = import.meta.url,
|
|
77
|
+
) {
|
|
78
|
+
if (!argvPath) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
return realpathSync(argvPath) === realpathSync(fileURLToPath(moduleUrl));
|
|
84
|
+
} catch {
|
|
85
|
+
return path.resolve(argvPath) === fileURLToPath(moduleUrl);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isOmniEntrypointInvocation()) {
|
|
75
90
|
runOmni().catch((error) => {
|
|
76
91
|
console.error(error instanceof Error ? error.message : String(error));
|
|
77
92
|
process.exit(1);
|
|
@@ -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.1",
|
|
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": {
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"bin": {
|
|
20
|
-
"omni": "
|
|
20
|
+
"omni": "bin/omni.js"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"pi-package",
|
|
24
24
|
"pi",
|
|
25
25
|
"agent",
|
|
26
26
|
"planning",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
27
|
+
"implementation",
|
|
28
|
+
"interview"
|
|
29
29
|
],
|
|
30
30
|
"files": [
|
|
31
31
|
"bin",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"CREDITS.md"
|
|
40
40
|
],
|
|
41
41
|
"scripts": {
|
|
42
|
+
"chat": "node ./bin/omni.js",
|
|
42
43
|
"check": "tsc --noEmit",
|
|
43
44
|
"lint": "biome check .",
|
|
44
45
|
"format": "biome check --write .",
|
|
@@ -54,13 +55,9 @@
|
|
|
54
55
|
},
|
|
55
56
|
"pi": {
|
|
56
57
|
"extensions": [
|
|
57
|
-
"./node_modules/pi-subagents/index.ts",
|
|
58
|
-
"./node_modules/pi-subagents/notify.ts",
|
|
59
58
|
"./extensions/omni-providers/index.ts",
|
|
60
59
|
"./extensions/omni-core/index.ts",
|
|
61
|
-
"./extensions/omni-memory/index.ts"
|
|
62
|
-
"./extensions/omni-skills/index.ts",
|
|
63
|
-
"./extensions/omni-status/index.ts"
|
|
60
|
+
"./extensions/omni-memory/index.ts"
|
|
64
61
|
],
|
|
65
62
|
"skills": [
|
|
66
63
|
"./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
|
+
}
|