@orbit-intelligence/orbit-agent 0.3.12
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/LICENSE +16 -0
- package/README.md +23 -0
- package/bin/orbit +26 -0
- package/dist/prompts/system.js +80 -0
- package/dist/src/cli/args.js +145 -0
- package/dist/src/cli/orchestrate.js +100 -0
- package/dist/src/cli/run.js +393 -0
- package/dist/src/config/config-schema.js +151 -0
- package/dist/src/config/index.js +57 -0
- package/dist/src/core/agent/agent-loop.js +402 -0
- package/dist/src/core/agents/delegate.js +120 -0
- package/dist/src/core/agents/orchestrator.js +58 -0
- package/dist/src/core/agents/prompts.js +82 -0
- package/dist/src/core/agents/types.js +1 -0
- package/dist/src/core/context/context-manager.js +167 -0
- package/dist/src/core/events.js +23 -0
- package/dist/src/core/llm/http.js +207 -0
- package/dist/src/core/llm/index.js +93 -0
- package/dist/src/core/llm/models.js +228 -0
- package/dist/src/core/llm/providers/gemini.js +211 -0
- package/dist/src/core/llm/providers/openai-compat.js +31 -0
- package/dist/src/core/llm/router.js +125 -0
- package/dist/src/core/llm/secrets.js +121 -0
- package/dist/src/core/llm/types.js +10 -0
- package/dist/src/core/orchestration/dispatcher.js +74 -0
- package/dist/src/core/orchestration/messenger.js +139 -0
- package/dist/src/core/orchestration/roles.js +129 -0
- package/dist/src/core/orchestration/runtime.js +122 -0
- package/dist/src/core/orchestration/session.js +204 -0
- package/dist/src/core/orchestration/shared-context.js +88 -0
- package/dist/src/core/orchestration/tools.js +187 -0
- package/dist/src/core/orchestration/types.js +3 -0
- package/dist/src/core/permissions/index.js +58 -0
- package/dist/src/core/project-context.js +115 -0
- package/dist/src/core/skill-loader.js +31 -0
- package/dist/src/core/tools/edit.js +142 -0
- package/dist/src/core/tools/filesystem.js +203 -0
- package/dist/src/core/tools/git.js +138 -0
- package/dist/src/core/tools/registry.js +73 -0
- package/dist/src/core/tools/search.js +90 -0
- package/dist/src/core/tools/shell.js +65 -0
- package/dist/src/core/tools/types.js +6 -0
- package/dist/src/core/types.js +3 -0
- package/dist/src/index.js +11 -0
- package/dist/src/session/event-log.js +55 -0
- package/dist/src/session/store.js +76 -0
- package/dist/src/setup/wizard.js +401 -0
- package/dist/src/tui/InkApp.js +67 -0
- package/dist/src/tui/ansi.js +142 -0
- package/dist/src/tui/app.js +768 -0
- package/dist/src/tui/colors.js +13 -0
- package/dist/src/tui/components/AgentDock.js +46 -0
- package/dist/src/tui/components/Composer.js +35 -0
- package/dist/src/tui/components/Header.js +23 -0
- package/dist/src/tui/components/ModelPicker.js +23 -0
- package/dist/src/tui/components/PermissionModal.js +29 -0
- package/dist/src/tui/components/SlashMenu.js +15 -0
- package/dist/src/tui/components/StatusLine.js +27 -0
- package/dist/src/tui/components/Transcript.js +31 -0
- package/dist/src/tui/components/WorkingStatus.js +29 -0
- package/dist/src/tui/components/input.js +246 -0
- package/dist/src/tui/components/markdown.js +384 -0
- package/dist/src/tui/components/message.js +105 -0
- package/dist/src/tui/context.js +8 -0
- package/dist/src/tui/geometry.js +40 -0
- package/dist/src/tui/renderer.js +116 -0
- package/dist/src/tui/rows.js +247 -0
- package/dist/src/tui/scheduler.js +32 -0
- package/dist/src/tui/store.js +127 -0
- package/dist/src/tui/style.js +151 -0
- package/dist/src/tui/term.js +309 -0
- package/dist/src/tui/text.js +104 -0
- package/dist/src/tui/themes/index.js +15 -0
- package/dist/src/tui/themes/palettes.js +137 -0
- package/dist/src/tui/themes/types.js +1 -0
- package/dist/src/utils/diff.js +161 -0
- package/dist/src/utils/platform.js +71 -0
- package/dist/src/utils/signals.js +26 -0
- package/dist/src/version.js +4 -0
- package/package.json +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Copyright (c) 2026 orbit-intelligence. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This package is closed source. All rights reserved by orbit-intelligence.
|
|
4
|
+
|
|
5
|
+
No part of this software may be reproduced, distributed, or transmitted in any
|
|
6
|
+
form or by any means without the prior written permission of the author, except
|
|
7
|
+
for the user's own local execution of the unmodified package for its intended
|
|
8
|
+
purpose.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
11
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
12
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
13
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
14
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
15
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
16
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# orbit
|
|
2
|
+
|
|
3
|
+
A premium pure-TypeScript coding-agent TUI for Termux and desktop terminals, powered by Orbit X.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm i -g @orbit-intelligence/orbit-agent
|
|
7
|
+
orbit
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
- Streaming TUI (thinking, tool calls, token counts) — zero native dependencies.
|
|
11
|
+
- Provider keys live only in your private [Orbit X](https://orbit-x-rfj6.onrender.com) gateway; the client keeps a single endpoint token.
|
|
12
|
+
- Auto-routing across Groq, Gemini, OpenRouter with failover: `orbitx/auto`, `groq/llama-3.3-70b-versatile`, `gemini/...`, `openrouter/...`.
|
|
13
|
+
- First-run wizard (`orbit setup`); offline demo via `orbit demo`; `orbit help` for all subcommands.
|
|
14
|
+
- UNLICENSED — closed source, © 2026 [orbit-intelligence](https://www.npmjs.com/~orbit-intelligence).
|
|
15
|
+
|
|
16
|
+
## Docs
|
|
17
|
+
|
|
18
|
+
- [`prompt-1.md`](./prompt-1.md) — agent/system specs
|
|
19
|
+
- `npm run build` / `npm test` / `npm start`
|
|
20
|
+
|
|
21
|
+
## Website
|
|
22
|
+
|
|
23
|
+
[Orbit-agent-intelligence](https://orbit-agent-intelligence.onrender.com)
|
package/bin/orbit
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# orbit-agent bin launcher — works on Termux (no /usr/bin/env), Linux, macOS.
|
|
3
|
+
# Follows npm symlinks to find the real package root, then runs dist/src/index.js.
|
|
4
|
+
|
|
5
|
+
resolve_pkg_dir() {
|
|
6
|
+
_p="$1"
|
|
7
|
+
while [ -L "$_p" ]; do
|
|
8
|
+
_d="$(dirname "$_p")"
|
|
9
|
+
_p="$(readlink "$_p")"
|
|
10
|
+
case "$_p" in
|
|
11
|
+
/*) ;;
|
|
12
|
+
*) _p="$_d/$_p" ;;
|
|
13
|
+
esac
|
|
14
|
+
done
|
|
15
|
+
echo "$(dirname "$_p")"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
PKG_DIR="$(resolve_pkg_dir "$0")"
|
|
19
|
+
NODE_BIN="$(command -v node 2>/dev/null || command -v nodejs 2>/dev/null)"
|
|
20
|
+
|
|
21
|
+
if [ -z "$NODE_BIN" ]; then
|
|
22
|
+
echo "orbit-agent: could not find 'node' on PATH (is Node.js installed?)" >&2
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
exec "$NODE_BIN" "$PKG_DIR/../dist/src/index.js" "$@"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { isTermux, defaultShell, platformLabel } from '../src/utils/platform.js';
|
|
2
|
+
export function buildSystemPrompt(config, cwd, extras) {
|
|
3
|
+
const env = isTermux() ? 'Termux (Android aarch64)' : platformLabel();
|
|
4
|
+
const shell = defaultShell();
|
|
5
|
+
const termuxBlock = isTermux()
|
|
6
|
+
? `
|
|
7
|
+
- This is Termux on Android (aarch64): limited CPU, RAM, battery, and network. Keep command timeouts short; avoid heavy builds, bulk downloads, and long-running daemons.
|
|
8
|
+
- Install packages with \`pkg\` (Termux's package manager). Do NOT use \`apt\`, \`systemctl\`, \`service\`, \`sudo\`, or \`ssh\` unless clearly necessary — most system services do not exist here and will hang or error.
|
|
9
|
+
- Avoid interactive commands (editors, full-screen TUIs, prompts) that can hang a session; use non-interactive flags (-y / --yes / --no-input / \`env CI=1\`).
|
|
10
|
+
- Prefer the built-in file tools (read_file / glob / grep / edit_file) over shell cat/grep/sed for project work — faster and safer on mobile.
|
|
11
|
+
- Mobile screens are small: keep command output short (truncate large dumps) and batch file operations into single commands. Prefer the built-in git tooling over shell git, and keep git output quiet (--no-advice --porcelain) when scripting.
|
|
12
|
+
- Android restricts some kernel features; if a tool fails with EPERM/EACCES, adapt the approach instead of retrying the same call.`
|
|
13
|
+
: '';
|
|
14
|
+
const conventionsBlock = extras?.conventions && extras.conventions.trim().length > 0
|
|
15
|
+
? `
|
|
16
|
+
# Project conventions (loaded from AGENTS.md)
|
|
17
|
+
These are the authoritative rules for this repository. They override generic guidance below when they conflict. Follow them exactly.
|
|
18
|
+
${extras.conventions}`
|
|
19
|
+
: '';
|
|
20
|
+
const skillsBlock = extras?.skills && extras.skills.length > 0
|
|
21
|
+
? `
|
|
22
|
+
# Available skills
|
|
23
|
+
When a user request matches one of these skills, load its instructions before starting. To load a skill body your model can call the \`load_project_skill\` tool; use the skill's name exactly as listed.
|
|
24
|
+
${extras.skills.map((s) => `- \`${s.name}\` — ${s.summary}`).join('\n')}`
|
|
25
|
+
: '';
|
|
26
|
+
return `You are orbit-agent, an interactive terminal agent for software engineering tasks. You help users safely and efficiently, using the tools below and following these instructions strictly.
|
|
27
|
+
|
|
28
|
+
# Operating environment
|
|
29
|
+
- Platform: ${env}
|
|
30
|
+
- Shell: ${shell}
|
|
31
|
+
- Working directory: ${cwd}
|
|
32
|
+
- You are a full agent: read, write, search, run commands, and iterate until the task is complete.
|
|
33
|
+
${termuxBlock}
|
|
34
|
+
${conventionsBlock}
|
|
35
|
+
${skillsBlock}
|
|
36
|
+
|
|
37
|
+
# Core mandates
|
|
38
|
+
- Conventions: Rigorously adhere to existing project conventions when reading or modifying code. Analyze surrounding code, tests, and configuration first.
|
|
39
|
+
- Libraries/frameworks: NEVER assume a library or framework is available. Verify established usage in the project (imports, package.json, Cargo.toml, requirements.txt, etc.) before using anything.
|
|
40
|
+
- Style: Mimic existing style, structure, typing, and architecture. Make the smallest change that satisfies the request.
|
|
41
|
+
- Comments: Add code comments sparingly and only for *why*, not *what*. Never narrate your actions through comments.
|
|
42
|
+
- Proactiveness: Fulfill the request thoroughly, including reasonable, directly implied follow-up actions — but do not take significant actions beyond the request's scope without confirming.
|
|
43
|
+
- Confirm ambiguity: If a request is ambiguous or asks *how*, explain first instead of guessing.
|
|
44
|
+
|
|
45
|
+
# When to use tools
|
|
46
|
+
- Tools exist to get real information and take real actions — not to be used reflexively.
|
|
47
|
+
- Greetings, chit-chat, thanks, and general questions (non-code): respond directly. Do NOT call tools.
|
|
48
|
+
- Anything about this repository, the filesystem, or an actual codebase: inspect with tools (list_dir / glob / grep / read_file) BEFORE answering or acting. Never answer from memory about directories or files.
|
|
49
|
+
- Writing code: read the relevant code first, edit surgically (prefer edit_file), then verify with the project's own checks.
|
|
50
|
+
- If you cannot verify something, say you did not verify it rather than presenting a guess.
|
|
51
|
+
|
|
52
|
+
# How you work
|
|
53
|
+
1. Understand. For a real task, explore first (read_file / list_dir / glob / grep). NEVER hallucinate file contents.
|
|
54
|
+
2. Plan. Prefer a clear, minimal plan, executed in small verifiable steps. A one-line plan stated before you start is fine; don't write an essay.
|
|
55
|
+
3. Implement. Use the appropriate tool (prefer edit_file over write_file for surgical changes).
|
|
56
|
+
4. Verify. Run the project's checks yourself before claiming success: \`npm test\`, \`node --test dist/tests/*.test.js\`, \`npm run typecheck\`, \`npm run build\` — as applicable. NEVER assume test commands; find them in package.json.
|
|
57
|
+
5. Reflect. After a tool returns, read the result, note in one line what it tells you and what you're doing next, then decide: more work, or final answer. Keep working and iterating until the task is verifiably done — you decide when it is done, not a fixed number of steps. If a step yields unexpected results, adapt and continue.
|
|
58
|
+
|
|
59
|
+
# Tool discipline
|
|
60
|
+
- Explore with glob/grep before reading whole files. Use absolute paths with file tools.
|
|
61
|
+
- run_shell: one focused command per call. Before commands that modify files or system state, give a brief explanation of purpose and impact. Avoid interactive commands that can hang; use non-interactive flags instead.
|
|
62
|
+
- If a tool fails, read the error, adapt, and retry — do not repeat the identical failing command.
|
|
63
|
+
- If a user cancels a tool call, respect it; do not retry unless they ask again.
|
|
64
|
+
- Honor the permission policy: never modify files outside the working directory without explicit permission.
|
|
65
|
+
|
|
66
|
+
# Output style
|
|
67
|
+
- Be concise and direct. Keep responses short unless the user asks for detail.
|
|
68
|
+
- Show your working across steps: a one-line intent before a tool call and a one-line finding/next step after each tool result. Do not recap the whole session at the end — just give the final answer.
|
|
69
|
+
- Use Markdown for structure. Quote exact paths (path:line) when referring to code.
|
|
70
|
+
- No emojis unless asked. Do not add code explanations unless asked.
|
|
71
|
+
|
|
72
|
+
# Security
|
|
73
|
+
- Never introduce code that exposes, logs, or commits secrets or API keys.
|
|
74
|
+
- Do not delete, overwrite, or modify files outside the working directory without explicit user permission.
|
|
75
|
+
|
|
76
|
+
# Inability
|
|
77
|
+
- If you cannot or will not do something, say so briefly (1-2 sentences) and offer a helpful alternative; do not lecture.
|
|
78
|
+
|
|
79
|
+
Begin.`;
|
|
80
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export function parseArgs(argv) {
|
|
2
|
+
const args = {
|
|
3
|
+
setup: false,
|
|
4
|
+
run: false,
|
|
5
|
+
noColor: false,
|
|
6
|
+
version: false,
|
|
7
|
+
help: false,
|
|
8
|
+
yes: false,
|
|
9
|
+
yolo: false,
|
|
10
|
+
showKeys: false,
|
|
11
|
+
orchestrate: false,
|
|
12
|
+
};
|
|
13
|
+
const take = (i) => {
|
|
14
|
+
const v = argv[++i];
|
|
15
|
+
if (v === undefined)
|
|
16
|
+
throw new Error(`Missing value for '${argv[i - 1]}'\nRun orbit help for usage.`);
|
|
17
|
+
return v;
|
|
18
|
+
};
|
|
19
|
+
for (let i = 0; i < argv.length; i++) {
|
|
20
|
+
const a = argv[i];
|
|
21
|
+
switch (a) {
|
|
22
|
+
// Flags
|
|
23
|
+
case '--setup':
|
|
24
|
+
args.setup = true;
|
|
25
|
+
break;
|
|
26
|
+
case '--run':
|
|
27
|
+
args.run = true;
|
|
28
|
+
break;
|
|
29
|
+
case '--orchestrate':
|
|
30
|
+
args.orchestrate = true;
|
|
31
|
+
break;
|
|
32
|
+
case '--yes':
|
|
33
|
+
case '-y':
|
|
34
|
+
args.yes = true;
|
|
35
|
+
break;
|
|
36
|
+
case '--yolo':
|
|
37
|
+
args.yolo = true;
|
|
38
|
+
args.yes = true;
|
|
39
|
+
break;
|
|
40
|
+
case '--no-color':
|
|
41
|
+
args.noColor = true;
|
|
42
|
+
break;
|
|
43
|
+
case '--version':
|
|
44
|
+
case '-v':
|
|
45
|
+
args.version = true;
|
|
46
|
+
break;
|
|
47
|
+
case '--help':
|
|
48
|
+
case '-h':
|
|
49
|
+
args.help = true;
|
|
50
|
+
break;
|
|
51
|
+
case '--show-keys':
|
|
52
|
+
args.showKeys = true;
|
|
53
|
+
break;
|
|
54
|
+
case '--theme':
|
|
55
|
+
case 'theme':
|
|
56
|
+
args.theme = take(i);
|
|
57
|
+
i++;
|
|
58
|
+
break;
|
|
59
|
+
case '--provider':
|
|
60
|
+
case 'provider':
|
|
61
|
+
args.provider = take(i);
|
|
62
|
+
i++;
|
|
63
|
+
break;
|
|
64
|
+
case '--model':
|
|
65
|
+
case 'model':
|
|
66
|
+
args.model = take(i);
|
|
67
|
+
i++;
|
|
68
|
+
break;
|
|
69
|
+
case '--session':
|
|
70
|
+
case 'session':
|
|
71
|
+
args.session = take(i);
|
|
72
|
+
i++;
|
|
73
|
+
break;
|
|
74
|
+
case '--cwd':
|
|
75
|
+
case 'cwd':
|
|
76
|
+
args.cwd = take(i);
|
|
77
|
+
i++;
|
|
78
|
+
break;
|
|
79
|
+
case '--log':
|
|
80
|
+
case 'log':
|
|
81
|
+
args.log = take(i);
|
|
82
|
+
i++;
|
|
83
|
+
break;
|
|
84
|
+
// Flagless subcommands
|
|
85
|
+
case 'setup':
|
|
86
|
+
args.setup = true;
|
|
87
|
+
break;
|
|
88
|
+
case 'run':
|
|
89
|
+
args.run = true;
|
|
90
|
+
break;
|
|
91
|
+
case 'orchestrate':
|
|
92
|
+
args.orchestrate = true;
|
|
93
|
+
break;
|
|
94
|
+
case 'version':
|
|
95
|
+
args.version = true;
|
|
96
|
+
break;
|
|
97
|
+
case 'help':
|
|
98
|
+
args.help = true;
|
|
99
|
+
break;
|
|
100
|
+
case 'yes':
|
|
101
|
+
args.yes = true;
|
|
102
|
+
break;
|
|
103
|
+
case 'yolo':
|
|
104
|
+
args.yolo = true;
|
|
105
|
+
args.yes = true;
|
|
106
|
+
break;
|
|
107
|
+
case 'nocolor':
|
|
108
|
+
case 'no-color':
|
|
109
|
+
args.noColor = true;
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
if (a.startsWith('-')) {
|
|
113
|
+
throw new Error(`Unknown flag: ${a}\nRun orbit help for usage.`);
|
|
114
|
+
}
|
|
115
|
+
// Anything else is a bare prompt → single-shot run.
|
|
116
|
+
args.prompt = [args.prompt, a].filter(Boolean).join(' ');
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return args;
|
|
121
|
+
}
|
|
122
|
+
export const HELP = `orbit — a premium coding agent TUI for Termux & desktop terminals.
|
|
123
|
+
|
|
124
|
+
Usage:
|
|
125
|
+
orbit start (setup wizard on first run)
|
|
126
|
+
orbit run "question" single-shot: run one prompt headless, print the answer
|
|
127
|
+
orbit "question" same as run (bare prompt)
|
|
128
|
+
orbit setup re-run the setup wizard
|
|
129
|
+
orbit orchestrate orchestration mode: multiple lead agents collaborate
|
|
130
|
+
orbit theme <name> set theme (tokyonight, catppuccin-mocha, nord, ...)
|
|
131
|
+
orbit provider <id> force provider (orbitx, groq, gemini, openrouter, mock)
|
|
132
|
+
orbit model <id> set primary model id (provider/name)
|
|
133
|
+
orbit cwd <path> working directory (default: cwd)
|
|
134
|
+
orbit log <session-id> print a session's event log (audit trail)
|
|
135
|
+
orbit session <id> resume a prior session (--session)
|
|
136
|
+
orbit yes skip permissions prompts (auto-allow)
|
|
137
|
+
orbit yolo allow everything without asking
|
|
138
|
+
orbit nocolor disable ANSI color
|
|
139
|
+
orbit version print version
|
|
140
|
+
orbit help show this help
|
|
141
|
+
|
|
142
|
+
All subcommands also work with --flag form (e.g. orbit --setup, orbit --help).
|
|
143
|
+
|
|
144
|
+
Keys are read from environment variables (GROQ_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY)
|
|
145
|
+
or from ~/.config/orbit-agent/keys.json. Never from this binary.`;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { ToolRegistry } from '../core/tools/registry.js';
|
|
3
|
+
import { PermissionManager } from '../core/permissions/index.js';
|
|
4
|
+
import { RoleRegistry } from '../core/orchestration/roles.js';
|
|
5
|
+
import { OrchestrationSession } from '../core/orchestration/session.js';
|
|
6
|
+
import { registerOrchestrationTools } from '../core/orchestration/tools.js';
|
|
7
|
+
import { buildSystemPrompt } from '../../prompts/system.js';
|
|
8
|
+
import { TuiApp } from '../tui/app.js';
|
|
9
|
+
import { VERSION } from '../version.js';
|
|
10
|
+
/**
|
|
11
|
+
* Orchestration mode: N lead agents collaborate on the user's turn with
|
|
12
|
+
* real agent→agent messaging, interrupts, shared context, and role delegation.
|
|
13
|
+
*/
|
|
14
|
+
export async function runOrchestrateCmd(opts) {
|
|
15
|
+
const { config, providers, bus, cwd } = opts;
|
|
16
|
+
const maxLeads = config.orchestration?.maxLeadAgents ?? 2;
|
|
17
|
+
const leads = config.orchestration?.leads?.length
|
|
18
|
+
? config.orchestration.leads
|
|
19
|
+
: [
|
|
20
|
+
{ name: 'Atlas', systemPrompt: '', model: config.model },
|
|
21
|
+
{ name: 'Nova', systemPrompt: 'Focused on correctness: verify every claim, prefer small precise edits.', model: config.model },
|
|
22
|
+
];
|
|
23
|
+
if (leads.length > maxLeads) {
|
|
24
|
+
console.error(`⚠ orchestration supports at most ${maxLeads} lead agents (config has ${leads.length}).`);
|
|
25
|
+
console.error(' Reduce orchestration.leads or raise orchestration.maxLeadAgents.');
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
const sessionConfig = {
|
|
29
|
+
leads: leads.map((l) => ({
|
|
30
|
+
name: l.name,
|
|
31
|
+
systemPrompt: l.systemPrompt ?? '',
|
|
32
|
+
model: { primary: l.model.primary, fallback: [...(l.model.fallback ?? [])] },
|
|
33
|
+
})),
|
|
34
|
+
cwd: resolve(cwd),
|
|
35
|
+
maxLeadAgents: maxLeads,
|
|
36
|
+
contextBudgetTokens: config.agent?.contextBudgetTokens ?? 48_000,
|
|
37
|
+
toolTimeoutMs: config.tools?.timeoutMs ?? 30_000,
|
|
38
|
+
streamTimeoutMs: config.runtime?.streamTimeoutMs ?? 120_000,
|
|
39
|
+
};
|
|
40
|
+
const registry = new ToolRegistry({ cwd, canWrite: true, shell: config.tools.shell });
|
|
41
|
+
registerOrchestrationTools(registry);
|
|
42
|
+
const app = new TuiApp({
|
|
43
|
+
config,
|
|
44
|
+
bus,
|
|
45
|
+
onSubmit: (text) => submitQueued(text),
|
|
46
|
+
version: VERSION,
|
|
47
|
+
});
|
|
48
|
+
const permissions = new PermissionManager(config.permissions, {
|
|
49
|
+
ask: (prompt) => app.ask(prompt),
|
|
50
|
+
});
|
|
51
|
+
const session = new OrchestrationSession({
|
|
52
|
+
config: sessionConfig,
|
|
53
|
+
providers,
|
|
54
|
+
strategy: config.routing.strategy,
|
|
55
|
+
registry,
|
|
56
|
+
permissions,
|
|
57
|
+
roles: new RoleRegistry(),
|
|
58
|
+
bus,
|
|
59
|
+
baseSystemPrompt: buildSystemPrompt(config, cwd),
|
|
60
|
+
cwd,
|
|
61
|
+
maxTokensPerSecond: opts.maxTokensPerSecond,
|
|
62
|
+
contextBudgetTokens: config.agent?.contextBudgetTokens ?? 48_000,
|
|
63
|
+
reasoning: config.reasoning,
|
|
64
|
+
});
|
|
65
|
+
let processing = false;
|
|
66
|
+
const queue = [];
|
|
67
|
+
async function submitQueued(text) {
|
|
68
|
+
queue.push(text);
|
|
69
|
+
await drain();
|
|
70
|
+
}
|
|
71
|
+
async function drain() {
|
|
72
|
+
if (processing)
|
|
73
|
+
return;
|
|
74
|
+
processing = true;
|
|
75
|
+
while (queue.length > 0) {
|
|
76
|
+
const text = queue.shift();
|
|
77
|
+
try {
|
|
78
|
+
await session.handleUser(text);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
bus.emit('onError', err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
processing = false;
|
|
85
|
+
}
|
|
86
|
+
bus.emit('onSessionStatus', `orchestration session: ${session.agentIds.length} lead agent(s) ready`);
|
|
87
|
+
app.run();
|
|
88
|
+
return await new Promise((r) => {
|
|
89
|
+
process.once('SIGINT', () => {
|
|
90
|
+
for (const id of session.agentIds)
|
|
91
|
+
session.abortAgent(id);
|
|
92
|
+
app.destroy();
|
|
93
|
+
r(130);
|
|
94
|
+
});
|
|
95
|
+
process.once('SIGTERM', () => {
|
|
96
|
+
app.destroy();
|
|
97
|
+
r(143);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|