omnirush 0.8.6 → 0.9.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/assets/CHANGELOG.md +85 -0
- package/assets/extensions/omnirush/agents-lib.ts +134 -13
- package/assets/extensions/omnirush/agents.ts +51 -107
- package/assets/extensions/omnirush/bgshell-lib.ts +400 -0
- package/assets/extensions/omnirush/bgshell.ts +392 -0
- package/assets/extensions/omnirush/collector.ts +72 -11
- package/assets/extensions/omnirush/commands.ts +2 -0
- package/assets/extensions/omnirush/deliveries.ts +145 -0
- package/assets/extensions/omnirush/guard/UPSTREAM +2 -0
- package/assets/extensions/omnirush/guard/git-command-policy.ts +885 -0
- package/assets/extensions/omnirush/guard-lib.ts +230 -0
- package/assets/extensions/omnirush/guard.ts +340 -0
- package/assets/extensions/omnirush/index.ts +12 -0
- package/assets/extensions/omnirush/pi-engine.ts +65 -1
- package/assets/extensions/omnirush/sota.ts +52 -4
- package/assets/extensions/omnirush/status-lib.ts +3 -0
- package/assets/extensions/omnirush/subagents-lib.ts +623 -0
- package/assets/extensions/omnirush/subagents.ts +305 -0
- package/assets/extensions/omnirush/swarm-lib.ts +142 -0
- package/assets/extensions/omnirush/swarm.ts +95 -0
- package/assets/extensions/omnirush/voice/capture.ts +502 -0
- package/assets/extensions/omnirush/voice/core/UPSTREAM +16 -0
- package/assets/extensions/omnirush/voice/core/file-source.ts +70 -0
- package/assets/extensions/omnirush/voice/core/index.ts +21 -0
- package/assets/extensions/omnirush/voice/core/keyterms.ts +117 -0
- package/assets/extensions/omnirush/voice/core/resample.ts +63 -0
- package/assets/extensions/omnirush/voice/core/segmenter.ts +231 -0
- package/assets/extensions/omnirush/voice/core/session.ts +403 -0
- package/assets/extensions/omnirush/voice/core/text.ts +81 -0
- package/assets/extensions/omnirush/voice/core/transcriber.ts +135 -0
- package/assets/extensions/omnirush/voice/core/types.ts +102 -0
- package/assets/extensions/omnirush/voice/core/wav.ts +95 -0
- package/assets/extensions/omnirush/voice/keys.ts +435 -0
- package/assets/extensions/omnirush/voice/kitty.ts +64 -0
- package/assets/extensions/omnirush/voice/pvrecorder-worker.cjs +43 -0
- package/assets/extensions/omnirush/voice/settings.ts +67 -0
- package/assets/extensions/omnirush/voice.ts +838 -0
- package/assets/extensions/omnirush/yolo-lib.ts +80 -0
- package/assets/extensions/omnirush/yolo.ts +85 -0
- package/package.json +7 -3
- package/scripts/brand-engine.js +526 -0
- package/scripts/build-all-packages.py +29 -1
- package/scripts/smoke-packages.py +32 -1
- package/src/bin.js +205 -33
- package/src/compat.js +272 -0
- package/src/lib.js +64 -0
- package/scripts/patch-pi-branding.js +0 -251
package/src/lib.js
CHANGED
|
@@ -403,3 +403,67 @@ export function managedToolTargets({ platform = process.platform, runtimeRoot }
|
|
|
403
403
|
{ tool: "rg", source: `${runtimeRoot}/bin/rg${ext}`, dest: `bin/rg${ext}` },
|
|
404
404
|
];
|
|
405
405
|
}
|
|
406
|
+
|
|
407
|
+
// --- yolo mode ---------------------------------------------------------------
|
|
408
|
+
//
|
|
409
|
+
// `--yolo`, `/yolo on` (saved as "yolo": true in <state dir>/settings.json) or
|
|
410
|
+
// OMNIRUSH_YOLO=1: the project folder is trusted for the run (the core's
|
|
411
|
+
// --approve) and nothing asks for confirmation. Precedence: --yolo/--no-yolo,
|
|
412
|
+
// then OMNIRUSH_YOLO, then the saved setting. Default: off.
|
|
413
|
+
|
|
414
|
+
export const YOLO_BANNER = "yolo mode: no prompts, project trusted";
|
|
415
|
+
|
|
416
|
+
const TRUE_WORDS = new Set(["1", "true", "on", "yes"]);
|
|
417
|
+
const FALSE_WORDS = new Set(["0", "false", "off", "no"]);
|
|
418
|
+
|
|
419
|
+
/** OMNIRUSH_YOLO as true/false, or undefined when unset or unrecognised. */
|
|
420
|
+
export function parseYoloEnv(value) {
|
|
421
|
+
const v = String(value ?? "").trim().toLowerCase();
|
|
422
|
+
if (TRUE_WORDS.has(v)) return true;
|
|
423
|
+
if (FALSE_WORDS.has(v)) return false;
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Resolve yolo mode for one launch. Strips --yolo/--no-yolo from `args`
|
|
429
|
+
* (never past `--`) and, when yolo is on for an agent run, adds the core's
|
|
430
|
+
* --approve unless the user already chose -a/--approve/-na/--no-approve.
|
|
431
|
+
* Returns { yolo, source, trusted, args }: `trusted` is false only when an
|
|
432
|
+
* explicit --no-approve wins over yolo's project trust.
|
|
433
|
+
*/
|
|
434
|
+
export function resolveYolo(args, { env = process.env, setting } = {}) {
|
|
435
|
+
let flag;
|
|
436
|
+
const rest = [];
|
|
437
|
+
let passthrough = false;
|
|
438
|
+
for (const arg of args) {
|
|
439
|
+
if (!passthrough && arg === "--") passthrough = true;
|
|
440
|
+
if (!passthrough && arg === "--yolo") flag = true;
|
|
441
|
+
else if (!passthrough && arg === "--no-yolo") flag = false;
|
|
442
|
+
else rest.push(arg);
|
|
443
|
+
}
|
|
444
|
+
let yolo = false;
|
|
445
|
+
let source = "default";
|
|
446
|
+
const fromEnv = parseYoloEnv(env.OMNIRUSH_YOLO);
|
|
447
|
+
if (flag !== undefined) {
|
|
448
|
+
yolo = flag;
|
|
449
|
+
source = "flag";
|
|
450
|
+
} else if (fromEnv !== undefined) {
|
|
451
|
+
yolo = fromEnv;
|
|
452
|
+
source = "env";
|
|
453
|
+
} else if (setting === true) {
|
|
454
|
+
yolo = true;
|
|
455
|
+
source = "setting";
|
|
456
|
+
}
|
|
457
|
+
const subcommand = rest.length > 0 && PI_SUBCOMMANDS.has(rest[0]);
|
|
458
|
+
if (!yolo || subcommand) return { yolo: yolo && !subcommand, source, trusted: !subcommand && yolo, args: rest };
|
|
459
|
+
const end = rest.indexOf("--");
|
|
460
|
+
const scan = end < 0 ? rest : rest.slice(0, end);
|
|
461
|
+
if (scan.some((a) => a === "--no-approve" || a === "-na")) return { yolo, source, trusted: false, args: rest };
|
|
462
|
+
if (scan.some((a) => a === "--approve" || a === "-a")) return { yolo, source, trusted: true, args: rest };
|
|
463
|
+
return { yolo, source, trusted: true, args: ["--approve", ...rest] };
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** The one-line banner for a resolved yolo launch. */
|
|
467
|
+
export function yoloBanner({ trusted }) {
|
|
468
|
+
return trusted ? YOLO_BANNER : "yolo mode: no prompts (project not trusted: --no-approve)";
|
|
469
|
+
}
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Rebrand the vendored agent core (@earendil-works/pi-coding-agent) so
|
|
3
|
-
// users see "omnirush", never "pi"/"Pi". Runs on postinstall (before the
|
|
4
|
-
// bun download) and is safe to re-run (idempotent).
|
|
5
|
-
//
|
|
6
|
-
// Two mechanisms:
|
|
7
|
-
// 1. package.json `piConfig.name = "omnirush"` — pi's supported rebrand
|
|
8
|
-
// hook. APP_NAME/APP_TITLE (banner logo "omnirush v0.86.1", terminal
|
|
9
|
-
// title, --help usage lines, auth hints, debug-log name, the
|
|
10
|
-
// <APP>_CODING_AGENT_DIR env var) all derive from it, in dist and in
|
|
11
|
-
// the runtime bundle. It also disables pi's official-distribution
|
|
12
|
-
// first-time-setup wizard (upstream treats forks/rebrands that way).
|
|
13
|
-
// 2. Literal string replacements across the installed dist/*.js (the
|
|
14
|
-
// standalone files and the runtime bundle chunks) for the handful of
|
|
15
|
-
// user-visible strings that do not go through APP_NAME.
|
|
16
|
-
//
|
|
17
|
-
// Never renamed: file paths, config/session directory names, function or
|
|
18
|
-
// variable identifiers, env-var names (PI_OFFLINE, PI_TELEMETRY, ... are
|
|
19
|
-
// the core's real env contract), or the `pi` admin-subcommand aliases —
|
|
20
|
-
// only display strings.
|
|
21
|
-
//
|
|
22
|
-
// Fail-soft: a core update that moved a string logs a warning; it never
|
|
23
|
-
// breaks `npm install`.
|
|
24
|
-
|
|
25
|
-
import fs from "node:fs";
|
|
26
|
-
import path from "node:path";
|
|
27
|
-
import { fileURLToPath } from "node:url";
|
|
28
|
-
|
|
29
|
-
const PKG = "@earendil-works/pi-coding-agent";
|
|
30
|
-
const BRAND = "omnirush";
|
|
31
|
-
|
|
32
|
-
// Display strings that do not flow through APP_NAME. `from` must match the
|
|
33
|
-
// installed dist exactly; applied with replaceAll to every dist/**/*.js.
|
|
34
|
-
export const REPLACEMENTS = [
|
|
35
|
-
{
|
|
36
|
-
label: "TUI banner onboarding line",
|
|
37
|
-
from: "Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.",
|
|
38
|
-
to: "Omnirush can explain its own features and look up its docs. Ask it how to use or extend Omnirush.",
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
label: "system prompt persona",
|
|
42
|
-
from: "operating inside pi, a coding agent harness",
|
|
43
|
-
to: "operating inside omnirush, a coding agent harness",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
label: "system prompt docs section header",
|
|
47
|
-
from:
|
|
48
|
-
"Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):",
|
|
49
|
-
to: "Omnirush documentation (read only when the user asks about the agent itself, its SDK, extensions, themes, skills, or TUI):",
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
label: "system prompt docs reading rule",
|
|
53
|
-
from: "When reading pi docs or examples",
|
|
54
|
-
to: "When reading the bundled docs or examples",
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
label: "system prompt packages doc reference",
|
|
58
|
-
from: "pi packages (docs/packages.md)",
|
|
59
|
-
to: "agent packages (docs/packages.md)",
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
label: "system prompt topics rule",
|
|
63
|
-
from: "When working on pi topics, read the docs and examples",
|
|
64
|
-
to: "When working on agent topics, read the docs and examples",
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
label: "system prompt read-fully rule",
|
|
68
|
-
from: "Always read pi .md files completely",
|
|
69
|
-
to: "Always read the agent .md files completely",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
label: "bug report persona",
|
|
73
|
-
from: "about pi, the coding agent they are talking to",
|
|
74
|
-
to: "about omnirush, the coding agent they are talking to",
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
label: "bug report recipient",
|
|
78
|
-
from: "Write a report for the pi developers",
|
|
79
|
-
to: "Write a report for the omnirush developers",
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
label: "--help update line",
|
|
83
|
-
from: "Update pi, extensions, or model catalogs",
|
|
84
|
-
to: "Update the agent, extensions, or model catalogs",
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
label: "--help update alias token",
|
|
88
|
-
from: "[source|self|pi]",
|
|
89
|
-
to: "[source|self]",
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
label: "update subcommand description",
|
|
93
|
-
from: "Update pi only (self works as alias to pi)",
|
|
94
|
-
to: "Update the agent only (self works as an alias)",
|
|
95
|
-
},
|
|
96
|
-
// Belt-and-braces against the pi.dev update banner (Foxtran's 0.73.1
|
|
97
|
-
// report: a stale core showed "Update Available — pi.dev/changelog"
|
|
98
|
-
// even though PI_OFFLINE should suppress the check). PI_OFFLINE=1 in
|
|
99
|
-
// the spawn env stops the check; these rewrites make the banner
|
|
100
|
-
// UNRENDERABLE even where PI_OFFLINE is absent (direct pi spawns,
|
|
101
|
-
// older cores): showNewVersionNotification returns before its body
|
|
102
|
-
// (the parameter is renamed so the replacement stays idempotent and
|
|
103
|
-
// never re-matches), and the pi.dev changelog URL is blanked. The
|
|
104
|
-
// parameter spelling differs between the standalone dist (readable)
|
|
105
|
-
// and the minified runtime bundle chunk, hence the two variants; a
|
|
106
|
-
// future core that renames the parameter just reports "missing"
|
|
107
|
-
// (fail-soft) and we would re-derive the target.
|
|
108
|
-
{
|
|
109
|
-
label: "TUI update banner (standalone dist)",
|
|
110
|
-
from: "showNewVersionNotification(release) {",
|
|
111
|
-
to: "showNewVersionNotification(_release) { return;",
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
label: "TUI update banner (runtime bundle chunk)",
|
|
115
|
-
from: "showNewVersionNotification(release2){",
|
|
116
|
-
to: "showNewVersionNotification(_r){return;",
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
label: "pi.dev changelog URL",
|
|
120
|
-
from: '"https://pi.dev/changelog"',
|
|
121
|
-
to: '""',
|
|
122
|
-
},
|
|
123
|
-
];
|
|
124
|
-
|
|
125
|
-
function findPiRoot(startDir) {
|
|
126
|
-
let dir = startDir;
|
|
127
|
-
for (let i = 0; i < 8; i++) {
|
|
128
|
-
const candidate = path.join(dir, "node_modules", PKG);
|
|
129
|
-
if (fs.existsSync(path.join(candidate, "package.json"))) return candidate;
|
|
130
|
-
const parent = path.dirname(dir);
|
|
131
|
-
if (parent === dir) return null;
|
|
132
|
-
dir = parent;
|
|
133
|
-
}
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function listDistFiles(root) {
|
|
138
|
-
const out = [];
|
|
139
|
-
const stack = [root];
|
|
140
|
-
while (stack.length > 0) {
|
|
141
|
-
const dir = stack.pop();
|
|
142
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
143
|
-
const full = path.join(dir, entry.name);
|
|
144
|
-
if (entry.isDirectory()) stack.push(full);
|
|
145
|
-
else if (entry.isFile() && entry.name.endsWith(".js")) out.push(full);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return out;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Apply the rebrand to the installed core. Returns a report:
|
|
153
|
-
* { piRoot, packageJsonPatched, applied: [{label, files}], missing: [{label, reason}] }
|
|
154
|
-
*/
|
|
155
|
-
export function applyBrandingPatches(startDir) {
|
|
156
|
-
const piRoot = findPiRoot(startDir);
|
|
157
|
-
if (!piRoot) {
|
|
158
|
-
return { piRoot: null, packageJsonPatched: false, applied: [], missing: [{ label: "core", reason: `${PKG} not installed` }] };
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// 1. The supported rebrand hook.
|
|
162
|
-
let packageJsonPatched = false;
|
|
163
|
-
const pkgPath = path.join(piRoot, "package.json");
|
|
164
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
165
|
-
if (pkg.piConfig?.name !== BRAND) {
|
|
166
|
-
pkg.piConfig = { ...(pkg.piConfig || {}), name: BRAND };
|
|
167
|
-
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
168
|
-
packageJsonPatched = true;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// 2. Literal display strings, everywhere under dist/.
|
|
172
|
-
const applied = [];
|
|
173
|
-
const missing = [];
|
|
174
|
-
const files = listDistFiles(path.join(piRoot, "dist"));
|
|
175
|
-
for (const replacement of REPLACEMENTS) {
|
|
176
|
-
let hits = 0;
|
|
177
|
-
for (const file of files) {
|
|
178
|
-
let content;
|
|
179
|
-
try {
|
|
180
|
-
content = fs.readFileSync(file, "utf8");
|
|
181
|
-
} catch {
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
if (!content.includes(replacement.from)) continue;
|
|
185
|
-
fs.writeFileSync(file, content.replaceAll(replacement.from, replacement.to));
|
|
186
|
-
hits++;
|
|
187
|
-
}
|
|
188
|
-
if (hits > 0) applied.push({ label: replacement.label, files: hits });
|
|
189
|
-
else missing.push({ label: replacement.label, reason: "target string not found (already applied or core updated)" });
|
|
190
|
-
}
|
|
191
|
-
return { piRoot, packageJsonPatched, applied, missing };
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function main() {
|
|
195
|
-
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
196
|
-
const report = applyBrandingPatches(repoRoot);
|
|
197
|
-
if (!report.piRoot) {
|
|
198
|
-
console.log("omnirush: agent core not installed; skipped branding patch");
|
|
199
|
-
return;
|
|
200
|
-
// Version alignment: pi's self-reported version (banner/help) reads its
|
|
201
|
-
// own package.json — rewrite it to the omnirush release version so the
|
|
202
|
-
// product version, not upstream's, is what users and support see.
|
|
203
|
-
try {
|
|
204
|
-
const piPkgPath = path.join(report.piRoot, "package.json");
|
|
205
|
-
const piPkg = JSON.parse(fs.readFileSync(piPkgPath, "utf8"));
|
|
206
|
-
const ourVersion = JSON.parse(
|
|
207
|
-
fs.readFileSync(path.join(repoRoot, "package.json"), "utf8"),
|
|
208
|
-
).version;
|
|
209
|
-
if (piPkg.version !== ourVersion) {
|
|
210
|
-
piPkg.version = ourVersion;
|
|
211
|
-
fs.writeFileSync(piPkgPath, JSON.stringify(piPkg, null, 2) + "\n");
|
|
212
|
-
report.versionAligned = ourVersion;
|
|
213
|
-
}
|
|
214
|
-
} catch {
|
|
215
|
-
/* cosmetic — never fail the patch over version alignment */
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Version alignment: pi's self-reported version (banner/help) reads its
|
|
219
|
-
// own package.json — rewrite it to the omnirush release version so the
|
|
220
|
-
// product version, not upstream's, is what users and support see.
|
|
221
|
-
try {
|
|
222
|
-
const piPkgPath = path.join(report.piRoot, "package.json");
|
|
223
|
-
const piPkg = JSON.parse(fs.readFileSync(piPkgPath, "utf8"));
|
|
224
|
-
const ourVersion = JSON.parse(
|
|
225
|
-
fs.readFileSync(path.join(repoRoot, "package.json"), "utf8"),
|
|
226
|
-
).version;
|
|
227
|
-
if (piPkg.version !== ourVersion) {
|
|
228
|
-
piPkg.version = ourVersion;
|
|
229
|
-
fs.writeFileSync(piPkgPath, JSON.stringify(piPkg, null, 2) + "\n");
|
|
230
|
-
report.versionAligned = ourVersion;
|
|
231
|
-
}
|
|
232
|
-
} catch {
|
|
233
|
-
/* cosmetic — never fail the patch over version alignment */
|
|
234
|
-
}
|
|
235
|
-
const patched = report.packageJsonPatched ? "package.json + " : "";
|
|
236
|
-
const ver = report.versionAligned ? `; version aligned to ${report.versionAligned}` : "";
|
|
237
|
-
console.log(
|
|
238
|
-
`omnirush: branding applied (${patched}${report.applied.length} display strings)${ver}` +
|
|
239
|
-
(report.missing.length > 0 ? `; ${report.missing.length} already-applied/absent` : ""),
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// CLI entry (postinstall). Imported as a module by tests — never exit there.
|
|
244
|
-
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
245
|
-
try {
|
|
246
|
-
main();
|
|
247
|
-
} catch (error) {
|
|
248
|
-
// Fail-soft: a cosmetic patch must never break `npm install`.
|
|
249
|
-
console.warn("omnirush: branding patch skipped:", error?.message ?? error);
|
|
250
|
-
}
|
|
251
|
-
}
|