@orion-agents/orion-code 0.3.4 → 0.3.9
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/CHANGELOG.md +157 -0
- package/README.md +59 -5
- package/README.zh-CN.md +6 -3
- package/dist/cli.js +58 -32
- package/dist/commands/context-tool-command-handlers.js +1 -5
- package/dist/commands/registry.js +1 -4
- package/dist/harness/intent.js +69 -16
- package/dist/harness/turn-summary.js +3 -1
- package/dist/memory/embeddings.js +2 -3
- package/dist/memory/prompts.js +1 -1
- package/dist/memory/relevant-finder.js +125 -15
- package/dist/memory/vector-store.js +13 -8
- package/dist/migration/migrate.js +8 -12
- package/dist/runtime/composer/history.js +1 -3
- package/dist/runtime/composer/layout.js +7 -4
- package/dist/runtime/legacy-thread-materializer.d.ts +3 -1
- package/dist/runtime/legacy-thread-materializer.js +15 -3
- package/dist/runtime/product-bootstrap.d.ts +12 -0
- package/dist/runtime/product-bootstrap.js +37 -22
- package/dist/runtime/rich-text/ansi-parser.js +12 -2
- package/dist/runtime/rich-text/layout.js +15 -19
- package/dist/runtime/subagents/budget.js +4 -1
- package/dist/runtime/subagents/policy.js +11 -4
- package/dist/runtime/subagents/provider-gate.js +6 -4
- package/dist/runtime/subagents/research-quality.js +3 -1
- package/dist/runtime/subagents/research-renderer.js +9 -2
- package/dist/runtime/subagents/result-parser.js +18 -7
- package/dist/runtime/thread-event-store.d.ts +5 -3
- package/dist/runtime/thread-event-store.js +29 -8
- package/dist/runtime/thread-projection.d.ts +17 -0
- package/dist/runtime/thread-projection.js +42 -1
- package/dist/runtime/tool-output-presentation.js +7 -7
- package/dist/runtime/turn-controller.js +1 -2
- package/dist/services/auth/auth.js +1 -4
- package/dist/services/auth/aws.js +24 -14
- package/dist/services/auto-fix/autoFixRunner.js +1 -1
- package/dist/services/auto-fix/index.d.ts +1 -1
- package/dist/services/diagnostic-tracking/diagnosticTracking.js +4 -2
- package/dist/services/diagnostic-tracking/index.d.ts +1 -1
- package/dist/services/effort.js +1 -9
- package/dist/services/file-glob.js +3 -4
- package/dist/services/mcp/transports.js +4 -4
- package/dist/services/model-catalog.js +179 -30
- package/dist/services/model-context.js +1 -1
- package/dist/services/provider-resilience/stream-recovery.js +1 -3
- package/dist/services/redaction.js +8 -0
- package/dist/services/session-storage.d.ts +28 -3
- package/dist/services/session-storage.js +70 -6
- package/dist/services/smart-routing.js +19 -11
- package/dist/services/verification-profile.js +17 -22
- package/dist/services/web-search-provider.js +21 -9
- package/dist/services/workspace-diff.js +10 -4
- package/dist/skills/builtin/code-review/SKILL.md +1 -1
- package/dist/skills/builtin/security-check/SKILL.md +1 -1
- package/dist/skills/builtin/test-gen/SKILL.md +1 -1
- package/dist/terminal-ui/editor.js +6 -2
- package/dist/terminal-ui/output-queue.js +9 -3
- package/dist/tools/lsp.js +12 -6
- package/dist/tui-core/frame.js +9 -7
- package/dist/tui-ui/transcript-cache.js +6 -6
- package/dist/tui-ui/transcript-inspector-surface.js +4 -1
- package/dist/tui-ui/transcript-inspector.js +3 -8
- package/dist/ui/box.js +14 -7
- package/dist/ui/markdown.js +4 -2
- package/dist/ui/shared/input-frame.js +12 -8
- package/dist/ui/stream-markdown.js +1 -1
- package/dist/ui/tool-preview.js +11 -3
- package/dist/ui/user-input.js +16 -10
- package/dist/web/cli-options.d.ts +13 -0
- package/dist/web/cli-options.js +47 -0
- package/dist/web/host-daemon.d.ts +61 -0
- package/dist/web/host-daemon.js +193 -0
- package/dist/web/launch.d.ts +3 -0
- package/dist/web/launch.js +24 -0
- package/dist/web/protocol.d.ts +2 -0
- package/dist/web/protocol.js +1 -0
- package/dist/web/review-service.js +41 -13
- package/dist/web/server.js +69 -0
- package/dist/web/session-runtime-registry.d.ts +14 -0
- package/dist/web/session-runtime-registry.js +23 -0
- package/dist/web/workbench-controller.d.ts +55 -0
- package/dist/web/workbench-controller.js +224 -14
- package/dist/web-client/assets/{DiffViewer-D6mG729y.js → DiffViewer-MMhvMif-.js} +1 -1
- package/dist/web-client/assets/{FilesPanel-CCDoAZ1J.js → FilesPanel-4litEN1k.js} +1 -1
- package/dist/web-client/assets/{GitPanel-DtNgiH7A.js → GitPanel-BVwlDRVo.js} +1 -1
- package/dist/web-client/assets/ReviewPanel-ChA0Zd2g.js +1 -0
- package/dist/web-client/assets/{TerminalPanel-CNxMaBLp.js → TerminalPanel-D8C1uybv.js} +1 -1
- package/dist/web-client/assets/index-DQfpqPTD.css +1 -0
- package/dist/web-client/assets/index-Dv_uE9dk.js +17 -0
- package/dist/web-client/index.html +2 -2
- package/npm-shrinkwrap.json +356 -120
- package/package.json +3 -1
- package/dist/web-client/assets/ReviewPanel-CKEBSt6P.js +0 -1
- package/dist/web-client/assets/index-BBvNg3By.css +0 -1
- package/dist/web-client/assets/index-C6TDJwMC.js +0 -17
|
@@ -97,12 +97,15 @@ function unquoteGitPath(path) {
|
|
|
97
97
|
function parseNameStatus(output) {
|
|
98
98
|
if (!output.trim())
|
|
99
99
|
return [];
|
|
100
|
-
return output
|
|
100
|
+
return output
|
|
101
|
+
.split('\n')
|
|
101
102
|
.filter(Boolean)
|
|
102
103
|
.map(line => {
|
|
103
104
|
const parts = line.split('\t');
|
|
104
105
|
const status = parts[0] || '?';
|
|
105
|
-
const rawPath = parts.length > 2
|
|
106
|
+
const rawPath = parts.length > 2
|
|
107
|
+
? `${parts[1]} -> ${parts[2]}`
|
|
108
|
+
: parts[1] || line.slice(status.length).trim();
|
|
106
109
|
const path = parts.length > 2
|
|
107
110
|
? `${unquoteGitPath(parts[1])} -> ${unquoteGitPath(parts[2])}`
|
|
108
111
|
: unquoteGitPath(rawPath);
|
|
@@ -112,7 +115,8 @@ function parseNameStatus(output) {
|
|
|
112
115
|
function parseUntracked(output) {
|
|
113
116
|
if (!output.trim())
|
|
114
117
|
return [];
|
|
115
|
-
return output
|
|
118
|
+
return output
|
|
119
|
+
.split('\n')
|
|
116
120
|
.filter(Boolean)
|
|
117
121
|
.map(path => ({ status: '??', path: unquoteGitPath(path) }));
|
|
118
122
|
}
|
|
@@ -178,7 +182,9 @@ function formatWorkspaceDiff(report, options = {}) {
|
|
|
178
182
|
`CWD ${report.cwd}`,
|
|
179
183
|
'Status not a git repository',
|
|
180
184
|
report.error ? `Error ${report.error}` : '',
|
|
181
|
-
]
|
|
185
|
+
]
|
|
186
|
+
.filter(Boolean)
|
|
187
|
+
.join('\n');
|
|
182
188
|
}
|
|
183
189
|
const lines = [
|
|
184
190
|
'Workspace Diff',
|
|
@@ -22,7 +22,9 @@ function openExternalEditor(options = {}) {
|
|
|
22
22
|
try {
|
|
23
23
|
(0, fs_1.chmodSync)(file, 0o600);
|
|
24
24
|
}
|
|
25
|
-
catch {
|
|
25
|
+
catch {
|
|
26
|
+
/* best effort */
|
|
27
|
+
}
|
|
26
28
|
const result = spawn(editor, [file], {
|
|
27
29
|
stdio: 'inherit',
|
|
28
30
|
shell: true,
|
|
@@ -47,7 +49,9 @@ function openExternalEditor(options = {}) {
|
|
|
47
49
|
try {
|
|
48
50
|
(0, fs_1.rmSync)(dir, { recursive: true, force: true });
|
|
49
51
|
}
|
|
50
|
-
catch {
|
|
52
|
+
catch {
|
|
53
|
+
/* best effort */
|
|
54
|
+
}
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
//# sourceMappingURL=editor.js.map
|
|
@@ -86,13 +86,17 @@ class TerminalOutputQueue {
|
|
|
86
86
|
try {
|
|
87
87
|
this.writer.off('drain', drainListener);
|
|
88
88
|
}
|
|
89
|
-
catch {
|
|
89
|
+
catch {
|
|
90
|
+
/* ok */
|
|
91
|
+
}
|
|
90
92
|
drainListener = null;
|
|
91
93
|
}
|
|
92
94
|
try {
|
|
93
95
|
this.writer.off('error', onError);
|
|
94
96
|
}
|
|
95
|
-
catch {
|
|
97
|
+
catch {
|
|
98
|
+
/* ok */
|
|
99
|
+
}
|
|
96
100
|
};
|
|
97
101
|
const onError = (error) => {
|
|
98
102
|
cleanup();
|
|
@@ -114,7 +118,9 @@ class TerminalOutputQueue {
|
|
|
114
118
|
try {
|
|
115
119
|
this.writer.off('drain', listener);
|
|
116
120
|
}
|
|
117
|
-
catch {
|
|
121
|
+
catch {
|
|
122
|
+
/* ok */
|
|
123
|
+
}
|
|
118
124
|
writeNext();
|
|
119
125
|
};
|
|
120
126
|
this.writer.on('drain', drainListener);
|
package/dist/tools/lsp.js
CHANGED
|
@@ -32,7 +32,9 @@ class LspClient extends events_1.EventEmitter {
|
|
|
32
32
|
* Uses spawnSync with `which`/`where` to avoid async ENOENT race.
|
|
33
33
|
*/
|
|
34
34
|
static probeBinary(cmd) {
|
|
35
|
-
const res = (0, child_process_1.spawnSync)(process.platform === 'win32' ? 'where' : 'which', [cmd], {
|
|
35
|
+
const res = (0, child_process_1.spawnSync)(process.platform === 'win32' ? 'where' : 'which', [cmd], {
|
|
36
|
+
stdio: 'ignore',
|
|
37
|
+
});
|
|
36
38
|
return res.status === 0;
|
|
37
39
|
}
|
|
38
40
|
async start() {
|
|
@@ -267,7 +269,7 @@ class LspManager {
|
|
|
267
269
|
const client = new LspClient(language, projectRoot);
|
|
268
270
|
// Fallback error listener — ensures the client NEVER crashes the process
|
|
269
271
|
// due to an unhandled 'error' event emission.
|
|
270
|
-
client.on('error',
|
|
272
|
+
client.on('error', msg => {
|
|
271
273
|
console.warn(`[LSP:${language}] ${msg}`);
|
|
272
274
|
});
|
|
273
275
|
try {
|
|
@@ -326,12 +328,14 @@ function formatLocationResult(location) {
|
|
|
326
328
|
const locations = Array.isArray(location) ? location : [location];
|
|
327
329
|
if (locations.length === 0)
|
|
328
330
|
return 'No definition found';
|
|
329
|
-
return locations
|
|
331
|
+
return locations
|
|
332
|
+
.map(loc => {
|
|
330
333
|
const path = loc.uri.replace('file://', '');
|
|
331
334
|
const line = loc.range.start.line + 1;
|
|
332
335
|
const char = loc.range.start.character + 1;
|
|
333
336
|
return `${path}:${line}:${char}`;
|
|
334
|
-
})
|
|
337
|
+
})
|
|
338
|
+
.join('\n');
|
|
335
339
|
}
|
|
336
340
|
/**
|
|
337
341
|
* 解析 Hover 结果
|
|
@@ -543,12 +547,14 @@ exports.lspGetDiagnosticsTool = (0, tool_1.buildTool)({
|
|
|
543
547
|
3: 'Information',
|
|
544
548
|
4: 'Hint',
|
|
545
549
|
};
|
|
546
|
-
const output = diagnostics
|
|
550
|
+
const output = diagnostics
|
|
551
|
+
.map(d => {
|
|
547
552
|
const sev = severityMap[d.severity] || 'Unknown';
|
|
548
553
|
const line = d.range.start.line + 1;
|
|
549
554
|
const char = d.range.start.character + 1;
|
|
550
555
|
return `[${sev}] ${file_path}:${line}:${char}: ${d.message}`;
|
|
551
|
-
})
|
|
556
|
+
})
|
|
557
|
+
.join('\n');
|
|
552
558
|
return { success: true, output };
|
|
553
559
|
}
|
|
554
560
|
catch (err) {
|
package/dist/tui-core/frame.js
CHANGED
|
@@ -58,9 +58,7 @@ function setFrameCursor(frame, row, column, visible = true) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
function renderFrameRows(frame) {
|
|
61
|
-
return frame.rows.map(row => row
|
|
62
|
-
.map(cell => cell.width === 0 ? '' : cell.char)
|
|
63
|
-
.join(''));
|
|
61
|
+
return frame.rows.map(row => row.map(cell => (cell.width === 0 ? '' : cell.char)).join(''));
|
|
64
62
|
}
|
|
65
63
|
function diffTuiFrames(previous, next) {
|
|
66
64
|
if (!previous || previous.width !== next.width || previous.height !== next.height) {
|
|
@@ -78,9 +76,9 @@ function diffTuiFrames(previous, next) {
|
|
|
78
76
|
}
|
|
79
77
|
return {
|
|
80
78
|
changedRows,
|
|
81
|
-
cursorChanged: previous.cursor.row !== next.cursor.row
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
cursorChanged: previous.cursor.row !== next.cursor.row ||
|
|
80
|
+
previous.cursor.column !== next.cursor.column ||
|
|
81
|
+
previous.cursor.visible !== next.cursor.visible,
|
|
84
82
|
};
|
|
85
83
|
}
|
|
86
84
|
function rowsDifferent(prev, next) {
|
|
@@ -97,7 +95,11 @@ function rowsDifferent(prev, next) {
|
|
|
97
95
|
return false;
|
|
98
96
|
}
|
|
99
97
|
function createEmptyRow(width) {
|
|
100
|
-
return Array.from({ length: width }, () => ({
|
|
98
|
+
return Array.from({ length: width }, () => ({
|
|
99
|
+
char: ' ',
|
|
100
|
+
width: 1,
|
|
101
|
+
style: style_1.DEFAULT_STYLE,
|
|
102
|
+
}));
|
|
101
103
|
}
|
|
102
104
|
function charWidth(char) {
|
|
103
105
|
const width = (0, string_width_1.default)(char);
|
|
@@ -22,9 +22,9 @@ class TranscriptLayoutCache {
|
|
|
22
22
|
}
|
|
23
23
|
/** Get cached rows for an entry, or null if not cached / stale. */
|
|
24
24
|
get(id, revision, generation, width, themeId = 'default') {
|
|
25
|
-
if (generation !== this.lastGeneration
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (generation !== this.lastGeneration ||
|
|
26
|
+
width !== this.lastWidth ||
|
|
27
|
+
themeId !== this.lastThemeId) {
|
|
28
28
|
this.invalidate(generation, width, themeId);
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
@@ -38,9 +38,9 @@ class TranscriptLayoutCache {
|
|
|
38
38
|
}
|
|
39
39
|
/** Store layout result for an entry. */
|
|
40
40
|
set(id, revision, rows, generation, width, themeId = 'default') {
|
|
41
|
-
if (generation !== this.lastGeneration
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
if (generation !== this.lastGeneration ||
|
|
42
|
+
width !== this.lastWidth ||
|
|
43
|
+
themeId !== this.lastThemeId) {
|
|
44
44
|
this.invalidate(generation, width, themeId);
|
|
45
45
|
}
|
|
46
46
|
// Evict oldest if at capacity.
|
|
@@ -72,7 +72,10 @@ class TranscriptInspectorSurface {
|
|
|
72
72
|
this.output.off('error', onError);
|
|
73
73
|
this.output.off('close', onClose);
|
|
74
74
|
};
|
|
75
|
-
const onDrain = () => {
|
|
75
|
+
const onDrain = () => {
|
|
76
|
+
cleanup();
|
|
77
|
+
resolve();
|
|
78
|
+
};
|
|
76
79
|
const onError = (error) => {
|
|
77
80
|
cleanup();
|
|
78
81
|
reject(error instanceof Error ? error : new Error(String(error ?? 'terminal output error')));
|
|
@@ -14,12 +14,7 @@ class TranscriptInspectorController {
|
|
|
14
14
|
view(entries, inspector) {
|
|
15
15
|
const query = inspector.searchQuery.trim().toLowerCase();
|
|
16
16
|
const filtered = query
|
|
17
|
-
? entries.filter(entry => [
|
|
18
|
-
entry.toolName,
|
|
19
|
-
entry.callId,
|
|
20
|
-
entry.summary,
|
|
21
|
-
this.details.get(entry.callId)?.content,
|
|
22
|
-
]
|
|
17
|
+
? entries.filter(entry => [entry.toolName, entry.callId, entry.summary, this.details.get(entry.callId)?.content]
|
|
23
18
|
.filter(Boolean)
|
|
24
19
|
.some(value => String(value).toLowerCase().includes(query)))
|
|
25
20
|
: entries;
|
|
@@ -43,7 +38,7 @@ class TranscriptInspectorController {
|
|
|
43
38
|
return;
|
|
44
39
|
const generation = ++this.requestGeneration;
|
|
45
40
|
this.details.set(entry.callId, {
|
|
46
|
-
content: append ? current?.content ?? '' : '',
|
|
41
|
+
content: append ? (current?.content ?? '') : '',
|
|
47
42
|
totalBytes: current?.totalBytes ?? entry.outputBytes,
|
|
48
43
|
nextOffsetBytes: current?.nextOffsetBytes,
|
|
49
44
|
redacted: current?.redacted ?? false,
|
|
@@ -72,7 +67,7 @@ class TranscriptInspectorController {
|
|
|
72
67
|
if (generation !== this.requestGeneration)
|
|
73
68
|
return;
|
|
74
69
|
this.details.set(entry.callId, {
|
|
75
|
-
content: append ? current?.content ?? '' : '',
|
|
70
|
+
content: append ? (current?.content ?? '') : '',
|
|
76
71
|
totalBytes: current?.totalBytes ?? entry.outputBytes,
|
|
77
72
|
redacted: current?.redacted ?? false,
|
|
78
73
|
loading: false,
|
package/dist/ui/box.js
CHANGED
|
@@ -40,18 +40,25 @@ function renderHeaderBox(config) {
|
|
|
40
40
|
// Model name
|
|
41
41
|
parts.push(ACCENT(config.model));
|
|
42
42
|
// Provider (shortened)
|
|
43
|
-
const providerShort = config.provider === 'Alibaba Cloud'
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const providerShort = config.provider === 'Alibaba Cloud'
|
|
44
|
+
? 'Qwen'
|
|
45
|
+
: config.provider === 'Anthropic'
|
|
46
|
+
? 'Anthropic'
|
|
47
|
+
: config.provider === 'OpenAI'
|
|
48
|
+
? 'OpenAI'
|
|
46
49
|
: config.provider;
|
|
47
50
|
if (providerShort) {
|
|
48
51
|
parts.push(DIM(providerShort));
|
|
49
52
|
}
|
|
50
53
|
// Status
|
|
51
|
-
const statusIcon = config.status === 'ready'
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const statusIcon = config.status === 'ready'
|
|
55
|
+
? GREEN('●')
|
|
56
|
+
: config.status === 'loading'
|
|
57
|
+
? YELLOW('○')
|
|
58
|
+
: config.status === 'error'
|
|
59
|
+
? RED('●')
|
|
60
|
+
: config.status === 'processing'
|
|
61
|
+
? ACCENT('◌')
|
|
55
62
|
: DIM('○');
|
|
56
63
|
parts.push(statusIcon);
|
|
57
64
|
return ` ${BRAND('orion')} ${DIM('v' + config.version)} ${DIM('│')} ${parts.join(` ${DIM('│')} `)}`;
|
package/dist/ui/markdown.js
CHANGED
|
@@ -149,8 +149,10 @@ function renderMarkdownFallback(text, maxWidth = DEFAULT_MAX_WIDTH) {
|
|
|
149
149
|
const level = headingMatch[1].length;
|
|
150
150
|
const headingText = headingMatch[2].trim();
|
|
151
151
|
const prefix = ' '.repeat(level - 1);
|
|
152
|
-
const styled = level <= 2
|
|
153
|
-
|
|
152
|
+
const styled = level <= 2
|
|
153
|
+
? BOLD(CYAN(prefix + ' ' + headingText))
|
|
154
|
+
: level <= 4
|
|
155
|
+
? BOLD(CYAN(prefix + headingText))
|
|
154
156
|
: BOLD(DIM(headingText));
|
|
155
157
|
result.push(styled);
|
|
156
158
|
result.push(DIM('─'.repeat(Math.min(headingText.length + prefix.length + 2, maxWidth - 2))));
|
|
@@ -9,13 +9,15 @@ exports.renderFramedInputFrame = renderFramedInputFrame;
|
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const text_1 = require("./text");
|
|
11
11
|
const NO_COLOR = process.env.NO_COLOR !== undefined || process.env.TERM === 'dumb';
|
|
12
|
-
const colorize = NO_COLOR
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const colorize = NO_COLOR
|
|
13
|
+
? {
|
|
14
|
+
accent: (s) => s,
|
|
15
|
+
dim: (s) => s,
|
|
16
|
+
}
|
|
17
|
+
: {
|
|
18
|
+
accent: chalk_1.default.hex('#00D4AA'),
|
|
19
|
+
dim: chalk_1.default.dim,
|
|
20
|
+
};
|
|
19
21
|
const INPUT_BG = '\x1b[48;2;56;56;56m';
|
|
20
22
|
const INPUT_FG = '\x1b[38;2;226;232;240m';
|
|
21
23
|
const RESET_COLORS = '\x1b[39;49m';
|
|
@@ -34,7 +36,9 @@ function renderFramedInputFrame(options) {
|
|
|
34
36
|
const prefix = index === 0 ? firstPrompt : continuationPrompt;
|
|
35
37
|
return renderInputLine((0, text_1.truncateVisible)(prefix + line, inputWidth));
|
|
36
38
|
});
|
|
37
|
-
const statusLine = options.statusText
|
|
39
|
+
const statusLine = options.statusText
|
|
40
|
+
? renderInputStatusLine(inputWidth, options.statusText)
|
|
41
|
+
: undefined;
|
|
38
42
|
const rowSpans = logicalLines.map((line, index) => {
|
|
39
43
|
const prefix = index === 0 ? firstPrompt : continuationPrompt;
|
|
40
44
|
return terminalRowsFor((0, text_1.visualWidth)(prefix) + (0, text_1.visualWidth)(line), width);
|
|
@@ -157,7 +157,7 @@ class StreamMarkdownRenderer {
|
|
|
157
157
|
// Ordered list
|
|
158
158
|
const orderedMatch = line.match(/^(\s*)(\d+)\.\s+(.*)$/);
|
|
159
159
|
if (orderedMatch) {
|
|
160
|
-
return orderedMatch[1] + CYAN(orderedMatch[2] + '.') + ' ' + this.renderInline(orderedMatch[3]);
|
|
160
|
+
return (orderedMatch[1] + CYAN(orderedMatch[2] + '.') + ' ' + this.renderInline(orderedMatch[3]));
|
|
161
161
|
}
|
|
162
162
|
return this.renderInline(line);
|
|
163
163
|
}
|
package/dist/ui/tool-preview.js
CHANGED
|
@@ -46,7 +46,9 @@ function renderToolCard(tool) {
|
|
|
46
46
|
lines.push(DIM('│ ') + truncated.padEnd(maxWidth - 4) + DIM(' │'));
|
|
47
47
|
}
|
|
48
48
|
if (tool.result.split('\n').length > 6) {
|
|
49
|
-
lines.push(DIM('│ ') +
|
|
49
|
+
lines.push(DIM('│ ') +
|
|
50
|
+
DIM(`... ${tool.result.split('\n').length - 6} more lines`).padEnd(maxWidth - 4) +
|
|
51
|
+
DIM(' │'));
|
|
50
52
|
}
|
|
51
53
|
// 底部
|
|
52
54
|
lines.push(DIM('└') + '─'.repeat(maxWidth - 2) + DIM('┘'));
|
|
@@ -92,7 +94,11 @@ function renderReadPreview(path, content, success) {
|
|
|
92
94
|
const maxWidth = 60;
|
|
93
95
|
const icon = success ? SUCCESS('📖') : ERROR('📖');
|
|
94
96
|
const title = `${icon} Read: ${path}`;
|
|
95
|
-
lines.push(DIM('┌─ ') +
|
|
97
|
+
lines.push(DIM('┌─ ') +
|
|
98
|
+
title.slice(0, maxWidth - 5) +
|
|
99
|
+
DIM(' ') +
|
|
100
|
+
'─'.repeat(Math.max(0, maxWidth - title.length - 5)) +
|
|
101
|
+
DIM('┐'));
|
|
96
102
|
if (success && content) {
|
|
97
103
|
const contentLines = content.split('\n').slice(0, 8);
|
|
98
104
|
for (const line of contentLines) {
|
|
@@ -100,7 +106,9 @@ function renderReadPreview(path, content, success) {
|
|
|
100
106
|
lines.push(DIM('│ ') + truncated.padEnd(maxWidth - 4) + DIM(' │'));
|
|
101
107
|
}
|
|
102
108
|
if (content.split('\n').length > 8) {
|
|
103
|
-
lines.push(DIM('│ ') +
|
|
109
|
+
lines.push(DIM('│ ') +
|
|
110
|
+
DIM(`... ${content.split('\n').length - 8} more lines`).padEnd(maxWidth - 4) +
|
|
111
|
+
DIM(' │'));
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
lines.push(DIM('└') + '─'.repeat(maxWidth - 2) + DIM('┘'));
|
package/dist/ui/user-input.js
CHANGED
|
@@ -33,16 +33,22 @@ function visualWidth(text) {
|
|
|
33
33
|
let width = 0;
|
|
34
34
|
for (const ch of text) {
|
|
35
35
|
const cp = ch.codePointAt(0) || 0;
|
|
36
|
-
width +=
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
width +=
|
|
37
|
+
cp >= 0x1100 &&
|
|
38
|
+
(cp <= 0x115f ||
|
|
39
|
+
cp === 0x2329 ||
|
|
40
|
+
cp === 0x232a ||
|
|
41
|
+
(cp >= 0x2e80 && cp <= 0xa4cf && cp !== 0x303f) ||
|
|
42
|
+
(cp >= 0xac00 && cp <= 0xd7a3) ||
|
|
43
|
+
(cp >= 0xf900 && cp <= 0xfaff) ||
|
|
44
|
+
(cp >= 0xfe10 && cp <= 0xfe19) ||
|
|
45
|
+
(cp >= 0xfe30 && cp <= 0xfe6f) ||
|
|
46
|
+
(cp >= 0xff01 && cp <= 0xff60) ||
|
|
47
|
+
(cp >= 0xffe0 && cp <= 0xffe6) ||
|
|
48
|
+
(cp >= 0x20000 && cp <= 0x2fffd) ||
|
|
49
|
+
(cp >= 0x30000 && cp <= 0x3fffd))
|
|
50
|
+
? 2
|
|
51
|
+
: 1;
|
|
46
52
|
}
|
|
47
53
|
return width;
|
|
48
54
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI option parsing for `orion web` (extracted from the CLI entry so the
|
|
3
|
+
* grammar has a unit-testable surface — issue #218 regression coverage).
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_WEB_PORT = 3080;
|
|
6
|
+
export interface WebCliOptions {
|
|
7
|
+
readonly port: number;
|
|
8
|
+
readonly open: boolean;
|
|
9
|
+
readonly cwd: string;
|
|
10
|
+
readonly background: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function parseWebCliOptions(args: readonly string[]): WebCliOptions;
|
|
13
|
+
//# sourceMappingURL=cli-options.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI option parsing for `orion web` (extracted from the CLI entry so the
|
|
4
|
+
* grammar has a unit-testable surface — issue #218 regression coverage).
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DEFAULT_WEB_PORT = void 0;
|
|
8
|
+
exports.parseWebCliOptions = parseWebCliOptions;
|
|
9
|
+
exports.DEFAULT_WEB_PORT = 3080;
|
|
10
|
+
function parseWebCliOptions(args) {
|
|
11
|
+
let port = exports.DEFAULT_WEB_PORT;
|
|
12
|
+
let open = true;
|
|
13
|
+
let cwd = process.cwd();
|
|
14
|
+
let background = false;
|
|
15
|
+
for (let index = 0; index < args.length; index++) {
|
|
16
|
+
const argument = args[index];
|
|
17
|
+
if (argument === '--background' || argument === '--daemon') {
|
|
18
|
+
background = true;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (argument === '--no-open') {
|
|
22
|
+
open = false;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (argument === '--port' || argument.startsWith('--port=')) {
|
|
26
|
+
const portValue = argument === '--port' ? args[++index] : argument.slice('--port='.length);
|
|
27
|
+
if (!portValue || !/^\d+$/u.test(portValue)) {
|
|
28
|
+
throw new Error('--port must be an integer from 0 through 65535.');
|
|
29
|
+
}
|
|
30
|
+
port = Number(portValue);
|
|
31
|
+
if (!Number.isSafeInteger(port) || port < 0 || port > 65535) {
|
|
32
|
+
throw new Error('--port must be an integer from 0 through 65535.');
|
|
33
|
+
}
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (argument === '--cwd' || argument.startsWith('--cwd=')) {
|
|
37
|
+
const cwdValue = argument === '--cwd' ? args[++index] : argument.slice('--cwd='.length);
|
|
38
|
+
if (!cwdValue?.trim())
|
|
39
|
+
throw new Error('--cwd requires a directory path.');
|
|
40
|
+
cwd = cwdValue;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Unknown orion web option: ${argument}`);
|
|
44
|
+
}
|
|
45
|
+
return { port, open, cwd, background };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=cli-options.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native background/daemon lifecycle for `orion web` (issue #247, S1+S2).
|
|
3
|
+
*
|
|
4
|
+
* A foreground `orion web --background` parent spawns the real host detached,
|
|
5
|
+
* waits for it to publish a pidfile under the config home, then returns. The
|
|
6
|
+
* detached child redirects its stdio to per-host log files and keeps the
|
|
7
|
+
* fail-closed approval / context / sandbox semantics untouched — this is a
|
|
8
|
+
* process-lifecycle concern only, still bound to 127.0.0.1.
|
|
9
|
+
*
|
|
10
|
+
* The pidfile shape is intentionally tiny and human-readable:
|
|
11
|
+
*
|
|
12
|
+
* { "pid": 12345, "port": 3080, "url": "http://127.0.0.1:3080",
|
|
13
|
+
* "startedAt": 1725000000000, "workspace": "/abs/path" }
|
|
14
|
+
*/
|
|
15
|
+
import { type ChildProcess } from 'child_process';
|
|
16
|
+
export declare const HOST_PIDFILE_BASE = "web-host";
|
|
17
|
+
export declare const HOST_DAEMON_CHILD_ENV = "ORION_WEB_DAEMON_CHILD";
|
|
18
|
+
export declare const DAEMON_READY_TIMEOUT_MS = 8000;
|
|
19
|
+
export declare const DAEMON_POLL_MS = 120;
|
|
20
|
+
export interface HostPidfile {
|
|
21
|
+
readonly pid: number;
|
|
22
|
+
readonly port: number;
|
|
23
|
+
readonly url: string;
|
|
24
|
+
readonly workspace: string;
|
|
25
|
+
readonly startedAt: number;
|
|
26
|
+
}
|
|
27
|
+
export type HostDaemonStatus = {
|
|
28
|
+
readonly state: 'running';
|
|
29
|
+
readonly pidfile: HostPidfile;
|
|
30
|
+
} | {
|
|
31
|
+
readonly state: 'stopped';
|
|
32
|
+
} | {
|
|
33
|
+
readonly state: 'stale';
|
|
34
|
+
readonly pid: number;
|
|
35
|
+
readonly port: number;
|
|
36
|
+
};
|
|
37
|
+
export declare function hostLogsDirectory(): string;
|
|
38
|
+
export declare function hostPidfilePath(port: number): string;
|
|
39
|
+
export declare function parseHostPidfile(raw: string): HostPidfile | null;
|
|
40
|
+
export declare function readHostPidfile(port: number): HostPidfile | null;
|
|
41
|
+
export declare function writeHostPidfile(pidfile: HostPidfile): void;
|
|
42
|
+
export declare function clearHostPidfile(port: number): void;
|
|
43
|
+
/** Cross-platform process-liveness probe used by `status`. */
|
|
44
|
+
export declare function isProcessAlive(pid: number): boolean;
|
|
45
|
+
export declare function hostDaemonStatus(port: number): HostDaemonStatus;
|
|
46
|
+
/**
|
|
47
|
+
* Parent-side entry for `--background`: spawn the host detached, redirect its
|
|
48
|
+
* stdio to `~/.orion-code/logs/web-<port>.log`, and wait for the pidfile so the
|
|
49
|
+
* foreground command can print the URL and exit cleanly.
|
|
50
|
+
*/
|
|
51
|
+
export declare function spawnBackgroundHost(options: {
|
|
52
|
+
readonly cwd: string;
|
|
53
|
+
readonly port: number;
|
|
54
|
+
readonly webArgs: readonly string[];
|
|
55
|
+
}): Promise<{
|
|
56
|
+
readonly child: ChildProcess;
|
|
57
|
+
readonly pidfile: HostPidfile;
|
|
58
|
+
}>;
|
|
59
|
+
/** Terminate a background host by pidfile (SIGTERM, then escalate to SIGKILL). */
|
|
60
|
+
export declare function stopBackgroundHost(port: number): Promise<'stopped' | 'not_running'>;
|
|
61
|
+
//# sourceMappingURL=host-daemon.d.ts.map
|