@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.
Files changed (80) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +23 -0
  3. package/bin/orbit +26 -0
  4. package/dist/prompts/system.js +80 -0
  5. package/dist/src/cli/args.js +145 -0
  6. package/dist/src/cli/orchestrate.js +100 -0
  7. package/dist/src/cli/run.js +393 -0
  8. package/dist/src/config/config-schema.js +151 -0
  9. package/dist/src/config/index.js +57 -0
  10. package/dist/src/core/agent/agent-loop.js +402 -0
  11. package/dist/src/core/agents/delegate.js +120 -0
  12. package/dist/src/core/agents/orchestrator.js +58 -0
  13. package/dist/src/core/agents/prompts.js +82 -0
  14. package/dist/src/core/agents/types.js +1 -0
  15. package/dist/src/core/context/context-manager.js +167 -0
  16. package/dist/src/core/events.js +23 -0
  17. package/dist/src/core/llm/http.js +207 -0
  18. package/dist/src/core/llm/index.js +93 -0
  19. package/dist/src/core/llm/models.js +228 -0
  20. package/dist/src/core/llm/providers/gemini.js +211 -0
  21. package/dist/src/core/llm/providers/openai-compat.js +31 -0
  22. package/dist/src/core/llm/router.js +125 -0
  23. package/dist/src/core/llm/secrets.js +121 -0
  24. package/dist/src/core/llm/types.js +10 -0
  25. package/dist/src/core/orchestration/dispatcher.js +74 -0
  26. package/dist/src/core/orchestration/messenger.js +139 -0
  27. package/dist/src/core/orchestration/roles.js +129 -0
  28. package/dist/src/core/orchestration/runtime.js +122 -0
  29. package/dist/src/core/orchestration/session.js +204 -0
  30. package/dist/src/core/orchestration/shared-context.js +88 -0
  31. package/dist/src/core/orchestration/tools.js +187 -0
  32. package/dist/src/core/orchestration/types.js +3 -0
  33. package/dist/src/core/permissions/index.js +58 -0
  34. package/dist/src/core/project-context.js +115 -0
  35. package/dist/src/core/skill-loader.js +31 -0
  36. package/dist/src/core/tools/edit.js +142 -0
  37. package/dist/src/core/tools/filesystem.js +203 -0
  38. package/dist/src/core/tools/git.js +138 -0
  39. package/dist/src/core/tools/registry.js +73 -0
  40. package/dist/src/core/tools/search.js +90 -0
  41. package/dist/src/core/tools/shell.js +65 -0
  42. package/dist/src/core/tools/types.js +6 -0
  43. package/dist/src/core/types.js +3 -0
  44. package/dist/src/index.js +11 -0
  45. package/dist/src/session/event-log.js +55 -0
  46. package/dist/src/session/store.js +76 -0
  47. package/dist/src/setup/wizard.js +401 -0
  48. package/dist/src/tui/InkApp.js +67 -0
  49. package/dist/src/tui/ansi.js +142 -0
  50. package/dist/src/tui/app.js +768 -0
  51. package/dist/src/tui/colors.js +13 -0
  52. package/dist/src/tui/components/AgentDock.js +46 -0
  53. package/dist/src/tui/components/Composer.js +35 -0
  54. package/dist/src/tui/components/Header.js +23 -0
  55. package/dist/src/tui/components/ModelPicker.js +23 -0
  56. package/dist/src/tui/components/PermissionModal.js +29 -0
  57. package/dist/src/tui/components/SlashMenu.js +15 -0
  58. package/dist/src/tui/components/StatusLine.js +27 -0
  59. package/dist/src/tui/components/Transcript.js +31 -0
  60. package/dist/src/tui/components/WorkingStatus.js +29 -0
  61. package/dist/src/tui/components/input.js +246 -0
  62. package/dist/src/tui/components/markdown.js +384 -0
  63. package/dist/src/tui/components/message.js +105 -0
  64. package/dist/src/tui/context.js +8 -0
  65. package/dist/src/tui/geometry.js +40 -0
  66. package/dist/src/tui/renderer.js +116 -0
  67. package/dist/src/tui/rows.js +247 -0
  68. package/dist/src/tui/scheduler.js +32 -0
  69. package/dist/src/tui/store.js +127 -0
  70. package/dist/src/tui/style.js +151 -0
  71. package/dist/src/tui/term.js +309 -0
  72. package/dist/src/tui/text.js +104 -0
  73. package/dist/src/tui/themes/index.js +15 -0
  74. package/dist/src/tui/themes/palettes.js +137 -0
  75. package/dist/src/tui/themes/types.js +1 -0
  76. package/dist/src/utils/diff.js +161 -0
  77. package/dist/src/utils/platform.js +71 -0
  78. package/dist/src/utils/signals.js +26 -0
  79. package/dist/src/version.js +4 -0
  80. package/package.json +71 -0
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Minimal line-based unified diff. Pure, dependency-free: a classic LCS-based
3
+ * Myers-ish diff over lines with hunks, used for the diff review surface.
4
+ */
5
+ export function unifiedDiff(before, after, label = 'file', context = 3) {
6
+ const a = before.split('\n');
7
+ const b = after.split('\n');
8
+ const ops = diffOp(a, b);
9
+ const hunks = buildHunks(a, b, ops, context);
10
+ if (hunks.length === 0)
11
+ return '';
12
+ const out = [`--- ${label}a`, `+++ ${label}b`];
13
+ for (const h of hunks) {
14
+ out.push(h.header);
15
+ for (const l of h.lines)
16
+ out.push(l);
17
+ }
18
+ return out.join('\n');
19
+ }
20
+ export function countChanges(diff) {
21
+ let added = 0;
22
+ let removed = 0;
23
+ for (const line of diff.split('\n')) {
24
+ if (line.startsWith('+') && !line.startsWith('+++'))
25
+ added++;
26
+ else if (line.startsWith('-') && !line.startsWith('---'))
27
+ removed++;
28
+ }
29
+ return { added, removed };
30
+ }
31
+ function diffOp(a, b) {
32
+ const n = a.length;
33
+ const m = b.length;
34
+ // LCS table — O(n*m), fine for typical source files (never past pairwise
35
+ // content, capped to avoid pathological memory use on gigantic dumps).
36
+ if (n * m > 4_000_000)
37
+ return a.map(() => -1);
38
+ const dp = new Uint16Array((n + 1) * (m + 1));
39
+ const W = m + 1;
40
+ for (let i = n - 1; i >= 0; i--) {
41
+ for (let j = m - 1; j >= 0; j--) {
42
+ dp[i * W + j] =
43
+ a[i] === b[j]
44
+ ? dp[(i + 1) * W + j + 1] + 1
45
+ : Math.max(dp[(i + 1) * W + j], dp[i * W + j + 1]);
46
+ }
47
+ }
48
+ const ops = new Array(n).fill(-1);
49
+ let i = 0;
50
+ let j = 0;
51
+ const trace = [];
52
+ while (i < n && j < m) {
53
+ if (a[i] === b[j]) {
54
+ trace.push(0);
55
+ i++;
56
+ j++;
57
+ }
58
+ else if (dp[(i + 1) * W + j] >= dp[i * W + j + 1]) {
59
+ trace.push(-1);
60
+ i++;
61
+ }
62
+ else {
63
+ trace.push(1);
64
+ j++;
65
+ }
66
+ }
67
+ while (i < n) {
68
+ trace.push(-1);
69
+ i++;
70
+ }
71
+ while (j < m) {
72
+ trace.push(1);
73
+ j++;
74
+ }
75
+ return trace;
76
+ }
77
+ function buildHunks(a, b, ops, context) {
78
+ const hunks = [];
79
+ let hunk = null;
80
+ let beforeStart = 0;
81
+ let afterStart = 0;
82
+ let beforeCount = 0;
83
+ let afterCount = 0;
84
+ let gap = 0;
85
+ const flush = () => {
86
+ if (hunk) {
87
+ hunk.header = `@@ -${beforeStart},${beforeCount} +${afterStart},${afterCount} @@`;
88
+ hunks.push(hunk);
89
+ }
90
+ hunk = null;
91
+ gap = 0;
92
+ };
93
+ // Two-pass: mark which lines belong to a hunk (with context padding),
94
+ // then build the hunks from the marks so deleted/inserted context appears
95
+ // only once.
96
+ const marked = ops.map((op) => op !== 0);
97
+ for (let i = 0; i < ops.length; i++) {
98
+ if (ops[i] !== 0) {
99
+ for (let k = Math.max(0, i - context); k <= Math.min(ops.length - 1, i + context); k++) {
100
+ marked[k] = true;
101
+ }
102
+ }
103
+ }
104
+ let ai = 0;
105
+ let bi = 0;
106
+ for (let i = 0; i < ops.length; i++) {
107
+ const op = ops[i];
108
+ if (marked[i]) {
109
+ if (op === 0) {
110
+ if (!hunk) {
111
+ hunk = { header: '', lines: [] };
112
+ beforeStart = ai + 1;
113
+ afterStart = bi + 1;
114
+ }
115
+ beforeCount++;
116
+ afterCount++;
117
+ hunk.lines.push(` ${a[ai]}`);
118
+ ai++;
119
+ bi++;
120
+ }
121
+ else if (op === -1) {
122
+ if (!hunk) {
123
+ hunk = { header: '', lines: [] };
124
+ beforeStart = ai + 1;
125
+ afterStart = bi + 1;
126
+ }
127
+ beforeCount++;
128
+ hunk.lines.push(`-${a[ai]}`);
129
+ ai++;
130
+ }
131
+ else {
132
+ if (!hunk) {
133
+ hunk = { header: '', lines: [] };
134
+ beforeStart = ai + 1;
135
+ afterStart = bi + 1;
136
+ }
137
+ afterCount++;
138
+ hunk.lines.push(`+${b[bi]}`);
139
+ bi++;
140
+ }
141
+ gap = 0;
142
+ }
143
+ else {
144
+ if (op === 0) {
145
+ ai++;
146
+ bi++;
147
+ }
148
+ else if (op === -1) {
149
+ ai++;
150
+ }
151
+ else {
152
+ bi++;
153
+ }
154
+ gap++;
155
+ if (hunk && gap > context * 2)
156
+ flush();
157
+ }
158
+ }
159
+ flush();
160
+ return hunks;
161
+ }
@@ -0,0 +1,71 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ /**
5
+ * Platform detection and path helpers.
6
+ * Termux (Android aarch64) is detected by its environment signature.
7
+ */
8
+ export function isTermux() {
9
+ return (process.env.PREFIX === '/data/data/com.termux/files/usr' ||
10
+ (process.env.ANDROID_ROOT != null &&
11
+ existsSync('/data/data/com.termux/files/usr/bin')));
12
+ }
13
+ export function isAndroid() {
14
+ return process.env.ANDROID_ROOT != null || process.platform === 'android';
15
+ }
16
+ export function isWindows() {
17
+ return process.platform === 'win32';
18
+ }
19
+ export function platformLabel() {
20
+ if (isTermux())
21
+ return 'termux';
22
+ return process.platform;
23
+ }
24
+ function xdgConfigHome() {
25
+ return process.env.XDG_CONFIG_HOME || join(homedir(), '.config');
26
+ }
27
+ function xdgDataHome() {
28
+ return process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');
29
+ }
30
+ export function configDir() {
31
+ return join(xdgConfigHome(), 'orbit-agent');
32
+ }
33
+ export function dataDir() {
34
+ return isTermux() ? join(homedir(), '.orbit-agent') : join(xdgDataHome(), 'orbit-agent');
35
+ }
36
+ export function sessionsDir() {
37
+ return join(dataDir(), 'sessions');
38
+ }
39
+ export function configPath() {
40
+ return join(configDir(), 'config.json');
41
+ }
42
+ export function keysPath() {
43
+ return join(configDir(), 'keys.json');
44
+ }
45
+ export function historyPath() {
46
+ return join(dataDir(), 'history.json');
47
+ }
48
+ export function logPath() {
49
+ return join(dataDir(), 'orbit-agent.log');
50
+ }
51
+ export function defaultShell() {
52
+ if (isWindows())
53
+ return process.env.COMSPEC || 'cmd.exe';
54
+ return process.env.SHELL || '/bin/sh';
55
+ }
56
+ export function supportsTrueColor() {
57
+ const ct = process.env.COLORTERM;
58
+ if (ct === 'truecolor' || ct === '24bit')
59
+ return true;
60
+ const term = process.env.TERM;
61
+ return term?.includes('truecolor') ?? false;
62
+ }
63
+ export function supportsUnicode() {
64
+ const env = process.env.LC_ALL || process.env.LC_CTYPE || process.env.LANG || '';
65
+ if (env.toUpperCase().includes('UTF'))
66
+ return true;
67
+ if (process.env.TERM_PROGRAM === 'vscode')
68
+ return true;
69
+ // Termux terminals are UTF-8 by default.
70
+ return isTermux();
71
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * AbortSignal composition without relying on AbortSignal.any (portable across
3
+ * Node versions). Returns a signal that aborts when ANY input aborts, relaying
4
+ * the first non-generic reason.
5
+ */
6
+ export function combineSignals(signals) {
7
+ const valid = signals.filter((s) => s !== undefined);
8
+ if (valid.length === 0) {
9
+ return new AbortController().signal;
10
+ }
11
+ if (valid.length === 1)
12
+ return valid[0];
13
+ const controller = new AbortController();
14
+ const propagate = () => {
15
+ const first = valid.find((s) => s.aborted);
16
+ controller.abort(first?.reason ?? new Error('aborted'));
17
+ };
18
+ for (const s of valid) {
19
+ if (s.aborted) {
20
+ propagate();
21
+ break;
22
+ }
23
+ s.addEventListener('abort', propagate, { once: true });
24
+ }
25
+ return controller.signal;
26
+ }
@@ -0,0 +1,4 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const pkg = require('../../package.json');
4
+ export const VERSION = pkg.version;
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@orbit-intelligence/orbit-agent",
3
+ "version": "0.3.12",
4
+ "description": "orbit — a premium pure-TypeScript coding agent for Termux and desktop terminals, powered by Orbit X.",
5
+ "type": "module",
6
+ "license": "UNLICENSED",
7
+ "private": false,
8
+ "author": {
9
+ "name": "orbit-intelligence",
10
+ "url": "https://www.npmjs.com/~orbit-intelligence"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/dexter-butcher/orbit-agent.git"
15
+ },
16
+ "homepage": "https://github.com/dexter-butcher/orbit-agent",
17
+ "bugs": {
18
+ "url": "https://github.com/dexter-butcher/orbit-agent/issues"
19
+ },
20
+ "bin": {
21
+ "orbit": "bin/orbit"
22
+ },
23
+ "main": "dist/src/index.js",
24
+ "files": [
25
+ "bin",
26
+ "dist/src",
27
+ "dist/prompts",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "engines": {
32
+ "node": ">=20"
33
+ },
34
+ "scripts": {
35
+ "build": "node node_modules/typescript/bin/tsc -p tsconfig.json",
36
+ "typecheck": "node node_modules/typescript/bin/tsc -p tsconfig.json --noEmit",
37
+ "dev": "node --watch src/index.ts",
38
+ "start": "node dist/index.js",
39
+ "test": "node --test \"dist/tests/*.test.js\"",
40
+ "prepublishOnly": "npm run build && npm test"
41
+ },
42
+ "dependencies": {
43
+ "chalk": "^6.0.0",
44
+ "highlight.js": "^11.12.0",
45
+ "ink": "^7.1.1",
46
+ "marked": "^18.0.13",
47
+ "react": "^19.3.0",
48
+ "string-width": "^8.2.2",
49
+ "strip-ansi": "^7.2.0",
50
+ "zod": "^4.6.5"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^24.0.0",
54
+ "@types/react": "^19.3.0",
55
+ "typescript": "~5.9.0"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "keywords": [
61
+ "tui",
62
+ "agent",
63
+ "llm",
64
+ "cli",
65
+ "termux",
66
+ "orbit",
67
+ "coding-agent",
68
+ "openai-compatible"
69
+ ],
70
+ "start": "node dist/src/index.js"
71
+ }