@solar_orb/agent_orb 0.1.0 → 0.1.2

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 CHANGED
@@ -23,7 +23,7 @@ npm --prefix packages/agent_orb run package-runtime
23
23
  npx --yes ./packages/agent_orb setup --yes
24
24
  ```
25
25
 
26
- If `packages/agent_orb/releases` contains a matching native bundle, setup installs that bundle directly with SHA256 verification. Otherwise it falls back to source build.
26
+ If `packages/agent_orb/releases` contains a matching native bundle, setup installs that bundle directly with SHA256 verification. Otherwise it falls back to source build. On Windows, setup also adds the runtime bin directory to the user PATH so a new terminal can run `agent_orb-codex`, `agent_orb-claude`, `agent_orb`, `codex-orb`, and `claude-orb` directly. The adapter launchers start the orb UI if needed before running the target CLI.
27
27
 
28
28
  ## Windows local path
29
29
 
@@ -55,5 +55,5 @@ For Windows-host testing, prefer either:
55
55
 
56
56
  ```powershell
57
57
  cd $env:TEMP\agent-orb-npx
58
- npx --yes .\agent_orb-0.1.0.tgz --help
58
+ npx --yes .\solar_orb-agent_orb-0.1.2.tgz --help
59
59
  ```
package/dist/adapter.js CHANGED
@@ -5,6 +5,7 @@ export const adapters = [
5
5
  displayName: 'Codex CLI',
6
6
  binaryCandidates: process.platform === 'win32' ? ['codex.exe', 'codex'] : ['codex'],
7
7
  wrapperCommand: process.platform === 'win32' ? 'codex-orb.cmd' : 'codex-orb',
8
+ launcherCommand: process.platform === 'win32' ? 'agent_orb-codex.cmd' : 'agent_orb-codex',
8
9
  promptPatterns: ['approve', 'permission', 'continue?', 'yes/no'],
9
10
  },
10
11
  {
@@ -12,6 +13,7 @@ export const adapters = [
12
13
  displayName: 'Claude Code CLI',
13
14
  binaryCandidates: process.platform === 'win32' ? ['claude.exe', 'claude'] : ['claude'],
14
15
  wrapperCommand: process.platform === 'win32' ? 'claude-orb.cmd' : 'claude-orb',
16
+ launcherCommand: process.platform === 'win32' ? 'agent_orb-claude.cmd' : 'agent_orb-claude',
15
17
  promptPatterns: ['continue?', 'permission', 'press enter', 'approve'],
16
18
  },
17
19
  ];
package/dist/config.js CHANGED
@@ -14,7 +14,7 @@ export function writeConfig(configDir, selectedAdapters, runtime = runtimeConfig
14
14
  fs.mkdirSync(configDir, { recursive: true });
15
15
  const configPath = path.join(configDir, 'config.toml');
16
16
  const enabled = new Set(selectedAdapters.map((adapter) => adapter.name));
17
- const content = `# Generated by npx agent_orb\n\n[install]\nmethod = "npx"\nversion = "0.1.0"\n\n[adapters.codex]\nenabled = ${enabled.has('codex')}\nbinary = "codex"\nwrapper = "codex-orb"\n\n[adapters.claude]\nenabled = ${enabled.has('claude')}\nbinary = "claude"\nwrapper = "claude-orb"\n\n[daemon]\nhost = "${runtime.daemonHost}"\nport = ${runtime.daemonPort}\nauto_start = true\n\n[orb]\nposition = "top-right"\nsize = 36\nopacity = 0.88\nalways_on_top = true\nclick_through = false\n\n[colors]\ndisconnected = "#6B7280"\nidle = "#9CA3AF"\nstarting = "#60A5FA"\nactive = "#3B82F6"\nthinking_like = "#8B5CF6"\nwaiting_input = "#FBBF24"\ncompleted = "#22C55E"\nerror = "#EF4444"\nwarning = "#F97316"\n\n[behavior]\nsilent_threshold_seconds = 20\nstuck_threshold_seconds = 180\ncompleted_hold_seconds = 10\nerror_requires_click_to_clear = true\n\n[privacy]\ninclude_output_sample = false\nmax_sample_chars = 512\n`;
17
+ const content = `# Generated by npx agent_orb\n\n[install]\nmethod = "npx"\nversion = "0.1.2"\n\n[adapters.codex]\nenabled = ${enabled.has('codex')}\nbinary = "codex"\nwrapper = "agent_orb-codex"\n\n[adapters.claude]\nenabled = ${enabled.has('claude')}\nbinary = "claude"\nwrapper = "agent_orb-claude"\n\n[daemon]\nhost = "${runtime.daemonHost}"\nport = ${runtime.daemonPort}\nauto_start = true\n\n[orb]\nposition = "top-right"\nsize = 36\nopacity = 0.88\nalways_on_top = true\nclick_through = false\n\n[colors]\ndisconnected = "#6B7280"\nidle = "#9CA3AF"\nstarting = "#60A5FA"\nactive = "#3B82F6"\nthinking_like = "#8B5CF6"\nwaiting_input = "#FBBF24"\ncompleted = "#22C55E"\nerror = "#EF4444"\nwarning = "#F97316"\n\n[behavior]\nsilent_threshold_seconds = 20\nstuck_threshold_seconds = 180\ncompleted_hold_seconds = 10\nerror_requires_click_to_clear = true\n\n[privacy]\ninclude_output_sample = false\nmax_sample_chars = 512\n`;
18
18
  fs.writeFileSync(configPath, content, 'utf8');
19
19
  return configPath;
20
20
  }
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ async function main() {
24
24
  case 'version':
25
25
  case '--version':
26
26
  case '-v':
27
- console.log('agent_orb bootstrapper 0.1.0');
27
+ console.log('agent_orb bootstrapper 0.1.2');
28
28
  break;
29
29
  case 'help':
30
30
  case '--help':
package/dist/setup.js CHANGED
@@ -7,7 +7,7 @@ import { detectAdapters } from './adapter.js';
7
7
  import { runtimeConfigFromEnv, writeConfig } from './config.js';
8
8
  import { installRuntimeBundle } from './download.js';
9
9
  import { detectPlatform } from './platform.js';
10
- import { commandExists, run, spawnDetached } from './shell.js';
10
+ import { commandExists, getPathEnv, run, setPathEnv, spawnDetached } from './shell.js';
11
11
  export async function setup(options = {}) {
12
12
  const platform = detectPlatform();
13
13
  const runtime = runtimeConfigFromEnv();
@@ -39,17 +39,24 @@ export async function setup(options = {}) {
39
39
  }
40
40
  const configPath = writeConfig(platform.configDir, selectedAdapters, runtime);
41
41
  createAdapterShims(platform, selectedAdapters);
42
- ensurePathHint(platform);
42
+ ensurePathConfigured(platform);
43
43
  await ensureDaemon(platform, runtime);
44
+ const orbStarted = startOrbUiIfAvailable(platform);
44
45
  if (options.smoke ?? true) {
45
46
  smokeTest(platform);
46
47
  }
47
48
  console.log('\n✓ Agent Orb setup complete');
48
49
  console.log(`Config: ${configPath}`);
49
- console.log(`Try: ${runtimeExe(platform, 'agent_orb')} run -- ${platform.platform === 'windows' ? 'cmd /C echo hello' : 'echo hello'}`);
50
+ console.log(`Try: agent_orb run -- ${platform.platform === 'windows' ? 'cmd /C echo hello' : 'echo hello'}`);
51
+ if (selectedAdapters.some((adapter) => adapter.name === 'codex')) {
52
+ console.log('Codex: agent_orb-codex');
53
+ }
54
+ if (selectedAdapters.some((adapter) => adapter.name === 'claude')) {
55
+ console.log('Claude: agent_orb-claude');
56
+ }
50
57
  const orb = runtimeExe(platform, 'agent-orb-ui');
51
58
  if (fs.existsSync(orb)) {
52
- console.log(`Orb: ${orb}`);
59
+ console.log(`Orb: ${orbStarted ? 'started' : orb}`);
53
60
  }
54
61
  }
55
62
  function installRuntimeFromSource(platform) {
@@ -188,32 +195,128 @@ function createAdapterShims(platform, adapters) {
188
195
  return;
189
196
  console.log('\n==> Creating adapter shims');
190
197
  for (const adapter of adapters) {
191
- const shimPath = path.join(platform.runtimeDir, adapter.wrapperCommand);
192
- if (platform.platform === 'windows') {
193
- const target = adapter.name;
194
- fs.writeFileSync(shimPath, `@echo off\r\n"%~dp0agent_orb.exe" run -- ${target} %*\r\n`, 'ascii');
198
+ const commands = uniqueStrings([adapter.launcherCommand, adapter.wrapperCommand]);
199
+ for (const command of commands) {
200
+ const shimPath = path.join(platform.runtimeDir, command);
201
+ if (platform.platform === 'windows') {
202
+ fs.writeFileSync(shimPath, windowsAdapterShim(adapter.name), 'ascii');
203
+ }
204
+ else {
205
+ fs.writeFileSync(shimPath, unixAdapterShim(adapter.name), 'utf8');
206
+ fs.chmodSync(shimPath, 0o755);
207
+ }
208
+ console.log(`✓ ${shimPath}`);
195
209
  }
196
- else {
197
- fs.writeFileSync(shimPath, `#!/usr/bin/env sh\n"$(dirname "$0")/agent_orb" run -- ${adapter.name} "$@"\n`, 'utf8');
198
- fs.chmodSync(shimPath, 0o755);
199
- }
200
- console.log(`✓ ${shimPath}`);
201
210
  }
202
211
  }
203
- function ensurePathHint(platform) {
204
- const currentPath = process.env.PATH ?? '';
212
+ function uniqueStrings(values) {
213
+ return [...new Set(values)];
214
+ }
215
+ function windowsAdapterShim(adapterName) {
216
+ return `@echo off\r\nsetlocal\r\nset "ORB_UI=%~dp0agent-orb-ui.exe"\r\nif exist "%ORB_UI%" (\r\n tasklist /FI "IMAGENAME eq agent-orb-ui.exe" 2>NUL | find /I "agent-orb-ui.exe" >NUL\r\n if errorlevel 1 start "" "%ORB_UI%"\r\n)\r\n"%~dp0agent_orb.exe" run -- ${adapterName} %*\r\nexit /b %ERRORLEVEL%\r\n`;
217
+ }
218
+ function unixAdapterShim(adapterName) {
219
+ return `#!/usr/bin/env sh\nset -eu\nDIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)\nORB_UI="$DIR/agent-orb-ui"\nif [ -x "$ORB_UI" ] && { [ -n "\${DISPLAY:-}" ] || [ -n "\${WAYLAND_DISPLAY:-}" ]; }; then\n running=0\n if command -v pgrep >/dev/null 2>&1 && pgrep -x agent-orb-ui >/dev/null 2>&1; then\n running=1\n fi\n if [ "$running" = "0" ]; then\n "$ORB_UI" >/dev/null 2>&1 &\n fi\nfi\nexec "$DIR/agent_orb" run -- ${adapterName} "$@"\n`;
220
+ }
221
+ function ensurePathConfigured(platform) {
222
+ const currentPath = getPathEnv();
205
223
  const parts = currentPath.split(platform.pathDelimiter).filter(Boolean);
206
- if (parts.includes(platform.runtimeDir))
224
+ if (pathPartsContain(parts, platform.runtimeDir, platform)) {
225
+ console.log(`✓ runtime dir already on PATH: ${platform.runtimeDir}`);
207
226
  return;
227
+ }
228
+ setPathEnv(`${platform.runtimeDir}${platform.pathDelimiter}${currentPath}`);
208
229
  console.log('\nPATH note:');
209
230
  if (platform.platform === 'windows') {
210
- console.log(` Add to user PATH if needed: ${platform.runtimeDir}`);
211
- console.log(' Or open a new terminal if installer/script already added it.');
231
+ if (addWindowsUserPath(platform.runtimeDir)) {
232
+ console.log(` added runtime dir to user PATH: ${platform.runtimeDir}`);
233
+ console.log(' Open a new terminal to use agent_orb-codex, agent_orb-claude, and agent_orb globally.');
234
+ }
235
+ else {
236
+ console.log(` Could not update user PATH automatically. Add manually if needed: ${platform.runtimeDir}`);
237
+ }
212
238
  }
213
239
  else {
214
240
  console.log(` export PATH="${platform.runtimeDir}:$PATH"`);
215
241
  }
216
242
  }
243
+ function pathPartsContain(parts, target, platform) {
244
+ const normalizedTarget = normalizePathForCompare(target, platform);
245
+ return parts.some((part) => normalizePathForCompare(part, platform) === normalizedTarget);
246
+ }
247
+ function normalizePathForCompare(value, platform) {
248
+ const trimmed = value.trim().replace(/[\\/]+$/, '');
249
+ return platform.platform === 'windows' ? trimmed.toLowerCase() : trimmed;
250
+ }
251
+ function addWindowsUserPath(targetDir) {
252
+ const script = [
253
+ '$target = $env:AGENT_ORB_TARGET_PATH',
254
+ "$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')",
255
+ '$parts = @()',
256
+ 'if ($userPath) { $parts = $userPath -split \';\' | Where-Object { $_ } }',
257
+ '$normalizedTarget = $target.TrimEnd("\\").ToLowerInvariant()',
258
+ '$exists = $false',
259
+ 'foreach ($part in $parts) {',
260
+ ' if ($part.TrimEnd("\\").ToLowerInvariant() -eq $normalizedTarget) { $exists = $true; break }',
261
+ '}',
262
+ 'if (-not $exists) {',
263
+ " [Environment]::SetEnvironmentVariable('Path', (($parts + $target) -join ';'), 'User')",
264
+ '}',
265
+ ].join('; ');
266
+ try {
267
+ run('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', script], {
268
+ env: {
269
+ ...process.env,
270
+ AGENT_ORB_TARGET_PATH: targetDir,
271
+ },
272
+ });
273
+ return true;
274
+ }
275
+ catch {
276
+ return false;
277
+ }
278
+ }
279
+ function startOrbUiIfAvailable(platform) {
280
+ const orb = runtimeExe(platform, 'agent-orb-ui');
281
+ if (!fs.existsSync(orb))
282
+ return false;
283
+ if (platform.platform === 'windows') {
284
+ if (isWindowsProcessRunning('agent-orb-ui.exe'))
285
+ return true;
286
+ spawnDetached(orb, []);
287
+ return true;
288
+ }
289
+ if (!process.env.DISPLAY && !process.env.WAYLAND_DISPLAY)
290
+ return false;
291
+ if (isUnixProcessRunning('agent-orb-ui'))
292
+ return true;
293
+ spawnDetached(orb, []);
294
+ return true;
295
+ }
296
+ function isWindowsProcessRunning(imageName) {
297
+ try {
298
+ const result = run('tasklist', ['/FI', `IMAGENAME eq ${imageName}`], {
299
+ allowFailure: true,
300
+ });
301
+ return result.stdout.toLowerCase().includes(imageName.toLowerCase());
302
+ }
303
+ catch {
304
+ return false;
305
+ }
306
+ }
307
+ function isUnixProcessRunning(processName) {
308
+ if (!commandExists('pgrep'))
309
+ return false;
310
+ try {
311
+ const result = run('pgrep', ['-x', processName], {
312
+ allowFailure: true,
313
+ });
314
+ return result.status === 0;
315
+ }
316
+ catch {
317
+ return false;
318
+ }
319
+ }
217
320
  async function ensureDaemon(platform, runtime) {
218
321
  console.log('\n==> Starting daemon');
219
322
  const tokenPath = path.join(platform.configDir, 'token');
package/dist/shell.js CHANGED
@@ -5,7 +5,7 @@ export function commandExists(command) {
5
5
  return findCommand(command) !== undefined;
6
6
  }
7
7
  export function findCommand(command) {
8
- const pathEnv = process.env.PATH ?? '';
8
+ const pathEnv = getPathEnv();
9
9
  const searchDirs = pathEnv.split(process.platform === 'win32' ? ';' : ':').filter(Boolean);
10
10
  const candidates = process.platform === 'win32'
11
11
  ? commandCandidates(command)
@@ -19,6 +19,21 @@ export function findCommand(command) {
19
19
  }
20
20
  return undefined;
21
21
  }
22
+ export function getPathEnv() {
23
+ if (process.platform !== 'win32')
24
+ return process.env.PATH ?? '';
25
+ const pathKey = Object.keys(process.env).find((key) => key.toLowerCase() === 'path');
26
+ return pathKey ? process.env[pathKey] ?? '' : process.env.PATH ?? '';
27
+ }
28
+ export function setPathEnv(value) {
29
+ if (process.platform !== 'win32') {
30
+ process.env.PATH = value;
31
+ return;
32
+ }
33
+ const pathKey = Object.keys(process.env).find((key) => key.toLowerCase() === 'path') ?? 'Path';
34
+ process.env[pathKey] = value;
35
+ process.env.PATH = value;
36
+ }
22
37
  export function run(command, args, options = {}) {
23
38
  const result = spawnSync(command, args, {
24
39
  cwd: options.cwd,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solar_orb/agent_orb",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Agent Orb local bootstrapper",
5
5
  "type": "module",
6
6
  "config": {