omnirush 0.10.3 → 0.10.4
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.
|
@@ -199,11 +199,18 @@ export const ROLE_PRESETS: Record<AgentRole, RolePreset> = {
|
|
|
199
199
|
},
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
-
/**
|
|
203
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Resolve the child entry: the core's entry as the launcher started it
|
|
204
|
+
* (OMNIRUSH_CORE_ENTRY: through <package>/engine, so process listings name
|
|
205
|
+
* omnirush; the runtime reports the resolved path in argv[1]), else this
|
|
206
|
+
* running script, with the current runtime.
|
|
207
|
+
*/
|
|
208
|
+
export function childInvocation(args: string[], env: NodeJS.ProcessEnv = process.env): {
|
|
204
209
|
command: string;
|
|
205
210
|
args: string[];
|
|
206
211
|
} {
|
|
212
|
+
const launched = (env.OMNIRUSH_CORE_ENTRY || "").trim();
|
|
213
|
+
if (launched && existsSync(launched)) return { command: process.execPath, args: [launched, ...args] };
|
|
207
214
|
const currentScript = process.argv[1];
|
|
208
215
|
const isBunVirtualScript = currentScript?.startsWith("/$bunfs/root/");
|
|
209
216
|
if (currentScript && !isBunVirtualScript && existsSync(currentScript)) {
|
|
@@ -214,8 +221,8 @@ export function childInvocation(args: string[]): {
|
|
|
214
221
|
if (!isGenericRuntime) {
|
|
215
222
|
return { command: process.execPath, args };
|
|
216
223
|
}
|
|
217
|
-
// Packaged bun builds: fall back to the
|
|
218
|
-
return { command: "
|
|
224
|
+
// Packaged bun builds: fall back to the omnirush on PATH (it forwards core flags).
|
|
225
|
+
return { command: "omnirush", args };
|
|
219
226
|
}
|
|
220
227
|
|
|
221
228
|
/** The folder, inside a session dir, that holds its sub-agents' sessions. */
|
|
@@ -5,11 +5,55 @@ const SECRET_ENV_NAMES = new Set([
|
|
|
5
5
|
"OMNIRUSH_APPROVAL_TOKEN",
|
|
6
6
|
]);
|
|
7
7
|
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* The agent core's own PI_<NAME> variables (src/compat.js
|
|
10
|
+
* CORE_ONLY_ENV_NAMES; a test keeps the lists equal). Shell commands and
|
|
11
|
+
* MCP servers see their OMNIRUSH_<NAME> copies only; any other PI_*
|
|
12
|
+
* variable (a user's own) passes through.
|
|
13
|
+
*/
|
|
14
|
+
export const CORE_ONLY_ENV_NAMES = [
|
|
15
|
+
"CODING_AGENT",
|
|
16
|
+
"CODING_AGENT_DIR",
|
|
17
|
+
"CODING_AGENT_SESSION_DIR",
|
|
18
|
+
"SESSION_ID",
|
|
19
|
+
"SESSION_FILE",
|
|
20
|
+
"PROVIDER",
|
|
21
|
+
"MODEL",
|
|
22
|
+
"REASONING_LEVEL",
|
|
23
|
+
"OFFLINE",
|
|
24
|
+
"TELEMETRY",
|
|
25
|
+
"INSTALLER_API_BASE",
|
|
26
|
+
"MANAGED_INSTALL_ROOT",
|
|
27
|
+
"CACHE_RETENTION",
|
|
28
|
+
"CLEAR_ON_SHRINK",
|
|
29
|
+
"EXPERIMENTAL",
|
|
30
|
+
"HARDWARE_CURSOR",
|
|
31
|
+
"HYPERLINKS",
|
|
32
|
+
"IMAGE_PROTOCOL",
|
|
33
|
+
"OAUTH_CALLBACK_HOST",
|
|
34
|
+
"PACKAGE_DIR",
|
|
35
|
+
"RADIUS_GATEWAY",
|
|
36
|
+
"SHARE_VIEWER_URL",
|
|
37
|
+
"SKIP_VERSION_CHECK",
|
|
38
|
+
"STARTUP_BENCHMARK",
|
|
39
|
+
"TIMING",
|
|
40
|
+
"TRUE_COLOR",
|
|
41
|
+
"TUI_DEBUG",
|
|
42
|
+
"TUI_DEBUG_REDRAW",
|
|
43
|
+
"TUI_ESC_TIMEOUT",
|
|
44
|
+
"TUI_WRITE_LOG",
|
|
45
|
+
];
|
|
46
|
+
const CORE_ONLY_ENV = new Set(CORE_ONLY_ENV_NAMES.map((name) => `PI_${name}`));
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Keep provider credentials in the agent process, never in shell/MCP
|
|
50
|
+
* children; the core's PI_* variables stay there too (the children get the
|
|
51
|
+
* OMNIRUSH_* spellings).
|
|
52
|
+
*/
|
|
9
53
|
export function sanitizeToolEnvironment(input: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
|
|
10
54
|
const output: NodeJS.ProcessEnv = {};
|
|
11
55
|
for (const [key, value] of Object.entries(input)) {
|
|
12
|
-
if (!SECRET_ENV_NAMES.has(key) && value !== undefined) output[key] = value;
|
|
56
|
+
if (!SECRET_ENV_NAMES.has(key) && !CORE_ONLY_ENV.has(key) && value !== undefined) output[key] = value;
|
|
13
57
|
}
|
|
14
58
|
return output;
|
|
15
59
|
}
|
package/package.json
CHANGED
package/scripts/brand-engine.js
CHANGED
|
@@ -23,10 +23,16 @@
|
|
|
23
23
|
// folders), OMNIRUSH_* copies of the env the core exports to shell
|
|
24
24
|
// commands, AI_AGENT, the HTTP User-Agent and temp-file names.
|
|
25
25
|
//
|
|
26
|
+
// 4. <package>/engine, a link to the core (src/compat.js
|
|
27
|
+
// ensureEngineLink): the launcher runs the core through it, so process
|
|
28
|
+
// listings and the doc paths in the system prompt name omnirush, not
|
|
29
|
+
// the core's npm package.
|
|
30
|
+
//
|
|
26
31
|
// Not renamed (internal, never shown): package ids and imports, code
|
|
27
32
|
// identifiers, session entry/customType ids, telemetry attribute keys,
|
|
28
33
|
// protocol values third-party providers expect, and the PI_* env names the
|
|
29
|
-
// core reads (the launcher maps OMNIRUSH_* spellings onto them
|
|
34
|
+
// core reads (the launcher maps OMNIRUSH_* spellings onto them; shells the
|
|
35
|
+
// core starts get the OMNIRUSH_* copies only).
|
|
30
36
|
//
|
|
31
37
|
// Maintenance: after bumping the core, run `node scripts/brand-engine.js`
|
|
32
38
|
// and `node --test test/branding.test.js`; a target that moved is reported
|
|
@@ -38,11 +44,16 @@ import fs from "node:fs";
|
|
|
38
44
|
import path from "node:path";
|
|
39
45
|
import { fileURLToPath } from "node:url";
|
|
40
46
|
|
|
47
|
+
import { CORE_ONLY_ENV_NAMES, ensureEngineLink } from "../src/compat.js";
|
|
48
|
+
|
|
41
49
|
const PKG = "@earendil-works/pi-coding-agent";
|
|
42
50
|
const BRAND = "omnirush";
|
|
43
51
|
export const BRAND_CONFIG_DIR = ".omnirush";
|
|
44
52
|
const OUR_CHANGELOG = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "assets", "CHANGELOG.md");
|
|
45
53
|
|
|
54
|
+
/** Matches the core's own PI_<NAME> variables (src/compat.js CORE_ONLY_ENV_NAMES), as JS regex source. */
|
|
55
|
+
export const CORE_ENV_PATTERN = `/^PI_(${CORE_ONLY_ENV_NAMES.join("|")})$/`;
|
|
56
|
+
|
|
46
57
|
// `from` must match the installed dist exactly; applied with replaceAll to
|
|
47
58
|
// every dist/**/*.js. A `to` must never contain its own `from` (idempotency).
|
|
48
59
|
export const REPLACEMENTS = [
|
|
@@ -157,13 +168,37 @@ export const REPLACEMENTS = [
|
|
|
157
168
|
{
|
|
158
169
|
label: "/bug disclaimer",
|
|
159
170
|
from: "This report goes to the Pi developers (Earendil) and is not shared publicly. It includes your pi version,",
|
|
160
|
-
to: "This report
|
|
171
|
+
to: "This report is not shared publicly. It includes your omnirush version,",
|
|
161
172
|
},
|
|
162
173
|
{
|
|
163
174
|
label: "announcement easter egg",
|
|
164
175
|
from: '"pi has joined Earendil"',
|
|
165
|
-
to: '"
|
|
176
|
+
to: '"omnirush"',
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
// Upstream easter eggs typed as commands (/arminsayshi, /dementedelves;
|
|
180
|
+
// the third only fires for one third-party model): shown nothing.
|
|
181
|
+
label: "hidden /arminsayshi is inert (bundle)",
|
|
182
|
+
from: "handleArminSaysHi(){",
|
|
183
|
+
to: "handleArminSaysHi(_off){return;",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
label: "hidden /dementedelves is inert (bundle)",
|
|
187
|
+
from: "handleDementedDelves(){",
|
|
188
|
+
to: "handleDementedDelves(_off){return;",
|
|
166
189
|
},
|
|
190
|
+
{ label: "upstream easter egg is inert (bundle)", from: "handleDaxnuts(){", to: "handleDaxnuts(_off){return;" },
|
|
191
|
+
{
|
|
192
|
+
label: "hidden /arminsayshi is inert (dist)",
|
|
193
|
+
from: " handleArminSaysHi() {",
|
|
194
|
+
to: " handleArminSaysHi(_off) { return;",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
label: "hidden /dementedelves is inert (dist)",
|
|
198
|
+
from: " handleDementedDelves() {",
|
|
199
|
+
to: " handleDementedDelves(_off) { return;",
|
|
200
|
+
},
|
|
201
|
+
{ label: "upstream easter egg is inert (dist)", from: " handleDaxnuts() {", to: " handleDaxnuts(_off) { return;" },
|
|
167
202
|
{
|
|
168
203
|
label: "external editor note",
|
|
169
204
|
from: "Pi will resume when the editor exits.",
|
|
@@ -345,7 +380,20 @@ export const REPLACEMENTS = [
|
|
|
345
380
|
label: "OMNIRUSH_* session env for shell commands",
|
|
346
381
|
from: "ctx.thinkingLevel&&(env2.PI_REASONING_LEVEL=ctx.thinkingLevel)}let baseContext={command,cwd,env:env2}",
|
|
347
382
|
to:
|
|
348
|
-
'ctx.thinkingLevel&&(env2.PI_REASONING_LEVEL=ctx.thinkingLevel)}for(let k of["SESSION_ID","SESSION_FILE","PROVIDER","MODEL","REASONING_LEVEL"])env2["PI_"+k]===void 0?delete env2["OMNIRUSH_"+k]:env2["OMNIRUSH_"+k]=env2["PI_"+k];let baseContext={command,cwd,env:env2}',
|
|
383
|
+
'ctx.thinkingLevel&&(env2.PI_REASONING_LEVEL=ctx.thinkingLevel)}for(let k of["SESSION_ID","SESSION_FILE","PROVIDER","MODEL","REASONING_LEVEL"])env2["PI_"+k]===void 0?delete env2["OMNIRUSH_"+k]:(env2["OMNIRUSH_"+k]=env2["PI_"+k],delete env2["PI_"+k]);let baseContext={command,cwd,env:env2}',
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
// The env every shell the core starts inherits (the bash tool, `!`
|
|
387
|
+
// commands, package installs): the core's own PI_* variables stay in
|
|
388
|
+
// the agent process; their OMNIRUSH_* copies are what commands see.
|
|
389
|
+
label: "no core PI_* variables in shell commands (bundle)",
|
|
390
|
+
from: "return{...process.env,[pathKey]:updatedPath}}function sanitizeBinaryOutput",
|
|
391
|
+
to: `let _env={...process.env,[pathKey]:updatedPath};for(let k of Object.keys(_env))${CORE_ENV_PATTERN}.test(k)&&delete _env[k];return _env}function sanitizeBinaryOutput`,
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
label: "no core PI_* variables in shell commands (dist)",
|
|
395
|
+
from: " return {\n ...process.env,\n [pathKey]: updatedPath,\n };\n}",
|
|
396
|
+
to: ` const _env = { ...process.env, [pathKey]: updatedPath };\n for (const k of Object.keys(_env)) if (${CORE_ENV_PATTERN}.test(k)) delete _env[k];\n return _env;\n}`,
|
|
349
397
|
},
|
|
350
398
|
|
|
351
399
|
// --- HTTP User-Agent (the omnirush gateway sees it) --------------------
|
|
@@ -377,6 +425,9 @@ export const REPLACEMENTS = [
|
|
|
377
425
|
{ label: "bug report zip", from: "`pi-bug-report-${id}.zip`", to: "`omnirush-bug-report-${id}.zip`" },
|
|
378
426
|
{ label: "TUI crash log", from: '"pi-tui-crash.log"', to: '"omnirush-tui-crash.log"' },
|
|
379
427
|
{ label: "TUI debug log", from: '"pi-tui-debug.log"', to: '"omnirush-tui-debug.log"' },
|
|
428
|
+
{ label: "git package update marker", from: ".pi-update-incomplete", to: ".omnirush-update-incomplete" },
|
|
429
|
+
{ label: "native module quarantine dir", from: '".pi-native-quarantine"', to: '".omnirush-native-quarantine"' },
|
|
430
|
+
{ label: "package install root package.json name", from: '"pi-extensions"', to: '"omnirush-extensions"' },
|
|
380
431
|
|
|
381
432
|
// --- update banner (belt-and-braces; the launcher sets PI_OFFLINE) -----
|
|
382
433
|
// showNewVersionNotification returns before its body (the parameter is
|
|
@@ -507,6 +558,9 @@ function main() {
|
|
|
507
558
|
console.log("omnirush: agent core not installed; skipped branding patch");
|
|
508
559
|
return;
|
|
509
560
|
}
|
|
561
|
+
// <package>/engine -> the core (what process listings and the system
|
|
562
|
+
// prompt's doc paths show; the launcher re-creates it when missing).
|
|
563
|
+
ensureEngineLink(repoRoot, report.piRoot);
|
|
510
564
|
const patched = report.packageJsonPatched ? "package.json + " : "";
|
|
511
565
|
const notes = report.changelogReplaced ? " + release notes" : "";
|
|
512
566
|
console.log(
|
package/src/bin.js
CHANGED
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
yoloBanner,
|
|
55
55
|
} from "./lib.js";
|
|
56
56
|
import { installManagedTools } from "./tools.js";
|
|
57
|
-
import { engineEnvAliases, migrateAgentDir, projectConfigDirName, resolveAgentDir } from "./compat.js";
|
|
57
|
+
import { engineEnvAliases, ensureEngineLink, migrateAgentDir, projectConfigDirName, resolveAgentDir } from "./compat.js";
|
|
58
58
|
import { customSessionDir, moveLegacySubagentSessions } from "./sessions.js";
|
|
59
59
|
import { ensureRuntime, managedBunPath } from "../scripts/postinstall.js";
|
|
60
60
|
import {
|
|
@@ -144,12 +144,31 @@ function piPackage() {
|
|
|
144
144
|
return null;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
// The core as users see it (process listings, the doc paths in the system
|
|
148
|
+
// prompt, sub-agent command lines): <package>/engine, a link to the core's
|
|
149
|
+
// folder (src/compat.js ensureEngineLink); null when the link cannot be made.
|
|
150
|
+
let ENGINE_LINK_DIR = null;
|
|
151
|
+
let ENGINE_ENTRY = null;
|
|
152
|
+
|
|
147
153
|
function piEntry() {
|
|
148
154
|
const found = piPackage();
|
|
149
|
-
if (found?.pkg?.bin?.pi)
|
|
155
|
+
if (found?.pkg?.bin?.pi) {
|
|
156
|
+
const dir = ensureEngineLink(path.resolve(__dirname, ".."), found.dir);
|
|
157
|
+
ENGINE_LINK_DIR = dir === path.resolve(found.dir) ? null : dir;
|
|
158
|
+
ENGINE_ENTRY = path.join(dir, found.pkg.bin.pi);
|
|
159
|
+
return ENGINE_ENTRY;
|
|
160
|
+
}
|
|
150
161
|
throw new Error("could not locate the pinned agent core (broken install). Fix: npm install -g omnirush@latest");
|
|
151
162
|
}
|
|
152
163
|
|
|
164
|
+
/** The core's package dir as the link, unless the user points it elsewhere. */
|
|
165
|
+
function engineDirEnv(env = process.env) {
|
|
166
|
+
const env2 = {};
|
|
167
|
+
if (ENGINE_ENTRY) env2.OMNIRUSH_CORE_ENTRY = ENGINE_ENTRY; // sub-agents start the core through the same path
|
|
168
|
+
if (ENGINE_LINK_DIR && !env.PI_PACKAGE_DIR && !env.OMNIRUSH_PACKAGE_DIR) env2.PI_PACKAGE_DIR = ENGINE_LINK_DIR;
|
|
169
|
+
return env2;
|
|
170
|
+
}
|
|
171
|
+
|
|
153
172
|
function ensureDirs() {
|
|
154
173
|
fs.mkdirSync(OMNI_DIR, { recursive: true, mode: 0o700 });
|
|
155
174
|
migrateLegacyAgentData();
|
|
@@ -875,6 +894,7 @@ function childEnv(auth) {
|
|
|
875
894
|
const origin = (process.env.OMNIRUSH_ORIGIN || "").trim().replace(/\/+$/, "") ||
|
|
876
895
|
gateway.replace(/\/+$/, "").replace(/\/v1$/, ""); // provider base -> manager origin
|
|
877
896
|
return {
|
|
897
|
+
...engineDirEnv(process.env),
|
|
878
898
|
// OMNIRUSH_* spellings of the core's own settings (PI_* still work).
|
|
879
899
|
...engineEnvAliases(process.env),
|
|
880
900
|
// Bootstrap values only: the agent (and every sub-agent it spawns)
|
|
@@ -1090,8 +1110,7 @@ Environment:
|
|
|
1090
1110
|
(default 50% of RAM), and none start below this
|
|
1091
1111
|
(default 10%); e.g. 25% or 6G. OMNIRUSH_AGENT_MEMORY=off
|
|
1092
1112
|
starts them without checking memory
|
|
1093
|
-
OMNIRUSH_<SETTING> the agent core's own settings (e.g. OMNIRUSH_CACHE_RETENTION
|
|
1094
|
-
the older PI_<SETTING> names still work)
|
|
1113
|
+
OMNIRUSH_<SETTING> the agent core's own settings (e.g. OMNIRUSH_CACHE_RETENTION)
|
|
1095
1114
|
|
|
1096
1115
|
Docs: https://omnirush.ai/omnirush — state is stored 0600 in ~/.omnirush`);
|
|
1097
1116
|
}
|
package/src/compat.js
CHANGED
|
@@ -270,3 +270,68 @@ export function engineEnvAliases(env = process.env) {
|
|
|
270
270
|
}
|
|
271
271
|
return out;
|
|
272
272
|
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* The core's own variables the launcher and the core set for themselves
|
|
276
|
+
* (PI_<NAME>). Shell commands the agent runs, background jobs and MCP
|
|
277
|
+
* servers see their OMNIRUSH_<NAME> copies only; a PI_ variable that is
|
|
278
|
+
* not on this list (a user's own) passes through. Mirrored in
|
|
279
|
+
* scripts/brand-engine.js (the core's shell env) and
|
|
280
|
+
* assets/extensions/omnirush/secret-env.ts (tests keep them equal).
|
|
281
|
+
*/
|
|
282
|
+
export const CORE_ONLY_ENV_NAMES = [
|
|
283
|
+
"CODING_AGENT",
|
|
284
|
+
"CODING_AGENT_DIR",
|
|
285
|
+
"CODING_AGENT_SESSION_DIR",
|
|
286
|
+
"SESSION_ID",
|
|
287
|
+
"SESSION_FILE",
|
|
288
|
+
"PROVIDER",
|
|
289
|
+
"MODEL",
|
|
290
|
+
"REASONING_LEVEL",
|
|
291
|
+
"OFFLINE",
|
|
292
|
+
"TELEMETRY",
|
|
293
|
+
"INSTALLER_API_BASE",
|
|
294
|
+
"MANAGED_INSTALL_ROOT",
|
|
295
|
+
...ENGINE_ENV_NAMES,
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
/** Folder, in the omnirush package, that links to the installed agent core. */
|
|
299
|
+
export const ENGINE_LINK = "engine";
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* The agent core as users see it: <package root>/engine, a link to the
|
|
303
|
+
* core's folder in node_modules (a junction on Windows). The launcher runs
|
|
304
|
+
* the core through it and hands it over as the core's package dir, so
|
|
305
|
+
* process listings, the doc paths in the system prompt and the sub-agent
|
|
306
|
+
* command lines name omnirush instead of the core's npm package. Made by
|
|
307
|
+
* the branding step at install and, when missing (archives, a read-only
|
|
308
|
+
* reinstall), here at launch. Never replaces a real folder. Returns the
|
|
309
|
+
* link, or the core's own folder when the link cannot be made.
|
|
310
|
+
*/
|
|
311
|
+
export function ensureEngineLink(packageRoot, coreDir, { fsImpl = fs, platform = process.platform } = {}) {
|
|
312
|
+
const link = path.join(packageRoot, ENGINE_LINK);
|
|
313
|
+
const real = path.resolve(coreDir);
|
|
314
|
+
const points = () => {
|
|
315
|
+
try {
|
|
316
|
+
return fsImpl.realpathSync(link) === fsImpl.realpathSync(real);
|
|
317
|
+
} catch {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
if (points()) return link;
|
|
322
|
+
try {
|
|
323
|
+
let stat = null;
|
|
324
|
+
try {
|
|
325
|
+
stat = fsImpl.lstatSync(link);
|
|
326
|
+
} catch {
|
|
327
|
+
/* absent */
|
|
328
|
+
}
|
|
329
|
+
if (stat && !stat.isSymbolicLink()) return real;
|
|
330
|
+
if (stat) fsImpl.unlinkSync(link); // a stale link (the core moved)
|
|
331
|
+
if (platform === "win32") fsImpl.symlinkSync(real, link, "junction");
|
|
332
|
+
else fsImpl.symlinkSync(path.relative(path.dirname(link), real) || ".", link, "dir");
|
|
333
|
+
} catch {
|
|
334
|
+
/* read-only install or a concurrent launch: checked below */
|
|
335
|
+
}
|
|
336
|
+
return points() ? link : real;
|
|
337
|
+
}
|