codebase-onboarder 0.7.0 → 1.0.0
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 +115 -12
- package/bin/onboarder.js +0 -0
- package/cli/agent/command.d.ts +71 -0
- package/cli/agent/command.js +177 -0
- package/cli/agent/command.js.map +1 -0
- package/cli/agent/config.d.ts +31 -0
- package/cli/agent/config.js +98 -0
- package/cli/agent/config.js.map +1 -0
- package/cli/agent/contracts.d.ts +77 -0
- package/cli/agent/contracts.js +2 -0
- package/cli/agent/contracts.js.map +1 -0
- package/cli/agent/files.d.ts +19 -0
- package/cli/agent/files.js +109 -0
- package/cli/agent/files.js.map +1 -0
- package/cli/agent/gitSource.d.ts +18 -0
- package/cli/agent/gitSource.js +69 -0
- package/cli/agent/gitSource.js.map +1 -0
- package/cli/agent/github.d.ts +21 -0
- package/cli/agent/github.js +94 -0
- package/cli/agent/github.js.map +1 -0
- package/cli/agent/mcp.d.ts +15 -0
- package/cli/agent/mcp.js +78 -0
- package/cli/agent/mcp.js.map +1 -0
- package/cli/agent/process.d.ts +18 -0
- package/cli/agent/process.js +118 -0
- package/cli/agent/process.js.map +1 -0
- package/cli/agent/protocol.d.ts +3 -0
- package/cli/agent/protocol.js +26 -0
- package/cli/agent/protocol.js.map +1 -0
- package/cli/agent/runner.d.ts +34 -0
- package/cli/agent/runner.js +152 -0
- package/cli/agent/runner.js.map +1 -0
- package/cli/agent/stdio.d.ts +1 -0
- package/cli/agent/stdio.js +62 -0
- package/cli/agent/stdio.js.map +1 -0
- package/cli/agent/tools.d.ts +7 -0
- package/cli/agent/tools.js +201 -0
- package/cli/agent/tools.js.map +1 -0
- package/cli/chat/app.d.ts +16 -0
- package/cli/chat/app.js +345 -0
- package/cli/chat/app.js.map +1 -0
- package/cli/chat/commands.d.ts +11 -0
- package/cli/chat/commands.js +120 -0
- package/cli/chat/commands.js.map +1 -0
- package/cli/chat/composer.d.ts +75 -0
- package/cli/chat/composer.js +467 -0
- package/cli/chat/composer.js.map +1 -0
- package/cli/chat/controller.d.ts +60 -0
- package/cli/chat/controller.js +393 -0
- package/cli/chat/controller.js.map +1 -0
- package/cli/chat/logo.d.ts +3 -0
- package/cli/chat/logo.js +14 -0
- package/cli/chat/logo.js.map +1 -0
- package/cli/chat/models.d.ts +18 -0
- package/cli/chat/models.js +88 -0
- package/cli/chat/models.js.map +1 -0
- package/cli/chat/profile.d.ts +5 -0
- package/cli/chat/profile.js +98 -0
- package/cli/chat/profile.js.map +1 -0
- package/cli/chat/render.d.ts +40 -0
- package/cli/chat/render.js +259 -0
- package/cli/chat/render.js.map +1 -0
- package/cli/chat/screen.d.ts +26 -0
- package/cli/chat/screen.js +117 -0
- package/cli/chat/screen.js.map +1 -0
- package/cli/chat/source.d.ts +29 -0
- package/cli/chat/source.js +116 -0
- package/cli/chat/source.js.map +1 -0
- package/cli/chat/store.d.ts +43 -0
- package/cli/chat/store.js +94 -0
- package/cli/chat/store.js.map +1 -0
- package/cli/chat/text.d.ts +4 -0
- package/cli/chat/text.js +27 -0
- package/cli/chat/text.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +20 -1
- package/cli/explorer/app.js.map +1 -1
- package/cli/explorer/commands.js +5 -0
- package/cli/explorer/commands.js.map +1 -1
- package/cli/main.js +47 -13
- package/cli/main.js.map +1 -1
- package/docs/HERMES_RESEARCH.md +51 -0
- package/package.json +2 -1
- package/public/app.js +98 -24
- package/public/app.js.map +1 -1
- package/public/assets/onboarder-mark.svg +11 -0
- package/public/browser.d.ts +3 -0
- package/public/browser.js.map +1 -1
- package/public/index.html +24 -7
- package/public/js/about.js +2 -2
- package/public/js/about.js.map +1 -1
- package/public/js/aiDraft.d.ts +1 -0
- package/public/js/aiDraft.js +66 -17
- package/public/js/aiDraft.js.map +1 -1
- package/public/js/api.d.ts +8 -5
- package/public/js/api.js +45 -22
- package/public/js/api.js.map +1 -1
- package/public/js/deepAnalysisView.js +2 -2
- package/public/js/deepAnalysisView.js.map +1 -1
- package/public/js/diagramPane.d.ts +1 -0
- package/public/js/diagramPane.js +5 -0
- package/public/js/diagramPane.js.map +1 -1
- package/public/js/docsView.js +6 -6
- package/public/js/docsView.js.map +1 -1
- package/public/js/dom.d.ts +8 -0
- package/public/js/dom.js.map +1 -1
- package/public/js/llm.d.ts +3 -1
- package/public/js/llm.js +15 -8
- package/public/js/llm.js.map +1 -1
- package/public/js/repoFiles.js +1 -1
- package/public/js/repoFiles.js.map +1 -1
- package/public/js/reviewView.js +1 -1
- package/public/js/reviewView.js.map +1 -1
- package/public/styles.css +25 -0
- package/server/gitDiff.d.ts +1 -1
- package/server/hermesChat.d.ts +13 -0
- package/server/hermesChat.js +145 -0
- package/server/hermesChat.js.map +1 -0
- package/server/http.d.ts +5 -4
- package/server/http.js +0 -4
- package/server/http.js.map +1 -1
- package/server/mcp/server.d.ts +1 -1
- package/server/mcp/server.js +2 -2
- package/server/mcp/server.js.map +1 -1
- package/server/router.js +7 -3
- package/server/router.js.map +1 -1
- package/shared/diagram/aiMermaid.js +16 -13
- package/shared/diagram/aiMermaid.js.map +1 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type AgentMode, type AgentEvent, type AgentResult } from '../agent/contracts.js';
|
|
2
|
+
import { runAgent, type RunnerOptions } from '../agent/runner.js';
|
|
3
|
+
import { ChatStore, type ChatRecord, type ChatSettings } from './store.js';
|
|
4
|
+
import { ChatSources } from './source.js';
|
|
5
|
+
export type ChatOutput = {
|
|
6
|
+
type: 'message';
|
|
7
|
+
text: string;
|
|
8
|
+
} | {
|
|
9
|
+
type: 'start';
|
|
10
|
+
prompt: string;
|
|
11
|
+
mode: AgentMode;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'event';
|
|
14
|
+
event: AgentEvent;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'end';
|
|
17
|
+
result: AgentResult;
|
|
18
|
+
elapsed: number;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'clear' | 'exit';
|
|
21
|
+
};
|
|
22
|
+
export interface ChatPorts {
|
|
23
|
+
output: (event: ChatOutput) => void;
|
|
24
|
+
run?: typeof runAgent;
|
|
25
|
+
browse?: (name: string, args: string[], root: string, signal: AbortSignal) => Promise<string>;
|
|
26
|
+
utility?: (name: ChatUtility, signal: AbortSignal) => Promise<string>;
|
|
27
|
+
chooseModel?: (configure: boolean, signal: AbortSignal) => Promise<boolean>;
|
|
28
|
+
store?: ChatStore;
|
|
29
|
+
runner?: Omit<RunnerOptions, 'onEvent' | 'signal'>;
|
|
30
|
+
sources?: ChatSources;
|
|
31
|
+
}
|
|
32
|
+
export type ChatUtility = 'doctor' | 'setup' | 'model' | 'tools' | 'runs';
|
|
33
|
+
export declare class ChatController {
|
|
34
|
+
private ports;
|
|
35
|
+
record: ChatRecord;
|
|
36
|
+
lastResult: AgentResult | null;
|
|
37
|
+
busy: boolean;
|
|
38
|
+
closed: boolean;
|
|
39
|
+
private abort;
|
|
40
|
+
private paste;
|
|
41
|
+
private store;
|
|
42
|
+
private sources;
|
|
43
|
+
constructor(settings: ChatSettings, ports: ChatPorts);
|
|
44
|
+
get settings(): ChatSettings;
|
|
45
|
+
get pasting(): boolean;
|
|
46
|
+
get workspace(): string;
|
|
47
|
+
private say;
|
|
48
|
+
cancel(): void;
|
|
49
|
+
close(): void;
|
|
50
|
+
private persist;
|
|
51
|
+
save(): Promise<boolean>;
|
|
52
|
+
private resetContext;
|
|
53
|
+
status(): string;
|
|
54
|
+
accept(input: string): Promise<void>;
|
|
55
|
+
private submit;
|
|
56
|
+
private utility;
|
|
57
|
+
private openSource;
|
|
58
|
+
resume(id: string): Promise<void>;
|
|
59
|
+
private run;
|
|
60
|
+
}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { AGENT_MODES } from '../agent/contracts.js';
|
|
3
|
+
import { runAgent, savedRun } from '../agent/runner.js';
|
|
4
|
+
import { agentHome } from '../agent/config.js';
|
|
5
|
+
import { redact, terminalText } from '../agent/process.js';
|
|
6
|
+
import { ChatStore, newChat, historySummary } from './store.js';
|
|
7
|
+
import { slashInput, chatHelp, BROWSE_COMMANDS } from './commands.js';
|
|
8
|
+
import { ChatSources, isRemoteSource } from './source.js';
|
|
9
|
+
export class ChatController {
|
|
10
|
+
ports;
|
|
11
|
+
record;
|
|
12
|
+
lastResult = null;
|
|
13
|
+
busy = false;
|
|
14
|
+
closed = false;
|
|
15
|
+
abort = null;
|
|
16
|
+
paste = null;
|
|
17
|
+
store;
|
|
18
|
+
sources;
|
|
19
|
+
constructor(settings, ports) {
|
|
20
|
+
this.ports = ports;
|
|
21
|
+
this.record = newChat(settings);
|
|
22
|
+
this.store = ports.store || new ChatStore(ports.runner?.home || agentHome(ports.runner?.env), ports.runner?.env);
|
|
23
|
+
this.sources = ports.sources || new ChatSources(this.store.home, { env: ports.runner?.env });
|
|
24
|
+
}
|
|
25
|
+
get settings() { return this.record.settings; }
|
|
26
|
+
get pasting() { return this.paste !== null; }
|
|
27
|
+
get workspace() { return this.lastResult?.workspace || this.settings.root; }
|
|
28
|
+
say(text) { this.ports.output({ type: 'message', text: terminalText(redact(text, this.ports.runner?.env)) }); }
|
|
29
|
+
cancel() { this.abort?.abort(); }
|
|
30
|
+
close() { this.closed = true; this.cancel(); this.paste = null; this.ports.output({ type: 'exit' }); }
|
|
31
|
+
async persist() {
|
|
32
|
+
this.record.updatedAt = new Date().toISOString();
|
|
33
|
+
try {
|
|
34
|
+
await this.store.save(this.record);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
this.say(`Could not save this conversation: ${e instanceof Error ? e.message : e}. The agent run remains in agent runs.`);
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async save() { return this.persist(); }
|
|
43
|
+
resetContext() { this.record.lastRun = null; this.lastResult = null; }
|
|
44
|
+
status() {
|
|
45
|
+
const s = this.settings;
|
|
46
|
+
return [...(s.sourceUrl ? [`GitHub: ${s.sourceUrl}`] : []), `Repository: ${s.root}`, `Workflow: ${s.mode}${s.pr ? ' · PR #' + s.pr : ''}${s.issue ? ' · issue #' + s.issue : ''}`,
|
|
47
|
+
`Model: ${s.model || 'Hermes profile default'}${s.provider ? ' (' + s.provider + ')' : ''}`,
|
|
48
|
+
`Permissions: files ${['implement', 'pr'].includes(s.mode) ? 'isolated workspace' : 'read only'} · checks ${s.checks ? 'on' : 'off'} · GitHub writes ${s.github ? 'on' : 'off'}`,
|
|
49
|
+
`Limits: ${s.timeout}s · ${s.maxTurns} agent turns`, `Conversation: ${this.record.id}`, `Session run: ${this.record.lastRun || 'new'}`,
|
|
50
|
+
`Workspace: ${this.workspace}`, ...(this.lastResult?.branch ? [`Branch: ${this.lastResult.branch}`] : [])].join('\n');
|
|
51
|
+
}
|
|
52
|
+
async accept(input) {
|
|
53
|
+
if (this.closed)
|
|
54
|
+
return;
|
|
55
|
+
const trimmed = input.trim(), command = slashInput(trimmed);
|
|
56
|
+
if (command?.name === 'exit' || command?.name === 'quit') {
|
|
57
|
+
this.close();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (command?.name === 'cancel') {
|
|
61
|
+
if (this.busy) {
|
|
62
|
+
this.cancel();
|
|
63
|
+
this.say('Cancelling…');
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
this.say('No active task.');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (this.busy) {
|
|
70
|
+
this.say('A task is running. Use /cancel or Ctrl-C before starting another.');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (this.paste !== null) {
|
|
74
|
+
if (trimmed === '/discard') {
|
|
75
|
+
this.paste = null;
|
|
76
|
+
this.say('Multiline message discarded.');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (trimmed === '/send') {
|
|
80
|
+
const body = this.paste.join('\n');
|
|
81
|
+
this.paste = null;
|
|
82
|
+
if (body.trim())
|
|
83
|
+
await this.submit(body);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (this.paste.join('\n').length + input.length + 1 > 16000) {
|
|
87
|
+
this.say('Message limit is 16000 characters. /send or /discard this message.');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.paste.push(input);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!trimmed)
|
|
94
|
+
return;
|
|
95
|
+
this.busy = true;
|
|
96
|
+
this.abort = new AbortController();
|
|
97
|
+
try {
|
|
98
|
+
if (!command) {
|
|
99
|
+
if (trimmed.startsWith('/'))
|
|
100
|
+
throw new Error('Invalid slash command. Use /help.');
|
|
101
|
+
const first = trimmed.split(/\s+/)[0];
|
|
102
|
+
if (isRemoteSource(first)) {
|
|
103
|
+
await this.openSource(first);
|
|
104
|
+
const question = trimmed.slice(first.length).trim();
|
|
105
|
+
if (question)
|
|
106
|
+
await this.run(question);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
await this.run(trimmed);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const { name, args, body } = command;
|
|
113
|
+
if (!name || name === 'help') {
|
|
114
|
+
this.say(chatHelp(args[0]));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (name === 'status') {
|
|
118
|
+
this.say(this.status());
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (name === 'skills') {
|
|
122
|
+
this.say('Built-in workflow skills\n' + ['ask — repository Q&A', 'review — local and PR review', 'triage — investigate issues', 'implement — isolated code changes', 'pr — prepare or publish a draft PR', 'github — issues, discussions, labels, and CI'].map(s => ' /' + s).join('\n'));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (name === 'tools' || name === 'runs') {
|
|
126
|
+
this.say(await this.utility(name));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (name === 'run') {
|
|
130
|
+
const saved = await savedRun(args[0] || '', this.store.home);
|
|
131
|
+
if (saved.manifest.sourceRoot !== this.settings.root)
|
|
132
|
+
throw new Error('This run belongs to another repository. Switch with /repo first.');
|
|
133
|
+
this.say(`Run: ${saved.manifest.id} · ${saved.result?.status || 'unfinished'}\nWorkspace: ${saved.manifest.root}\n\n${saved.result?.answer || 'No saved final answer.'}`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (name === 'export') {
|
|
137
|
+
this.say('Conversation exported: ' + await this.store.export(this.record));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (name === 'send' || name === 'discard') {
|
|
141
|
+
this.say('Use /paste first to compose a multiline message.');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (name === 'clear') {
|
|
145
|
+
this.ports.output({ type: 'clear' });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (name === 'paste') {
|
|
149
|
+
this.paste = [];
|
|
150
|
+
this.say('Multiline input. /send submits; /discard cancels.');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (name === 'new') {
|
|
154
|
+
this.record = newChat({ ...this.settings, pr: undefined, issue: undefined });
|
|
155
|
+
this.lastResult = null;
|
|
156
|
+
this.say('New conversation. ' + this.record.id);
|
|
157
|
+
await this.persist();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (name === 'history') {
|
|
161
|
+
this.say(historySummary(await this.store.list(this.settings.root)));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (name === 'resume') {
|
|
165
|
+
await this.resume(args[0] || '');
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (name === 'repo' || name === 'clone') {
|
|
169
|
+
if (!body) {
|
|
170
|
+
this.say(name === 'clone' ? 'Usage: /clone <GitHub URL>' : (this.settings.sourceUrl || this.settings.root));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (name === 'clone' && (args.length !== 1 || !isRemoteSource(args[0])))
|
|
174
|
+
throw new Error('Usage: /clone <GitHub URL>');
|
|
175
|
+
await this.openSource(args.join(' '));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (name === 'pull') {
|
|
179
|
+
if (body)
|
|
180
|
+
throw new Error('Usage: /pull');
|
|
181
|
+
if (this.lastResult?.branch)
|
|
182
|
+
throw new Error('Use /new before pulling the source checkout. Your implementation workspace remains saved in agent runs.');
|
|
183
|
+
this.say(await this.sources.pull(this.settings.root, this.abort.signal, text => this.say(text)));
|
|
184
|
+
this.resetContext();
|
|
185
|
+
await this.persist();
|
|
186
|
+
this.say('Source refreshed. The next question starts a new agent session.');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (name === 'mode') {
|
|
190
|
+
if (!body) {
|
|
191
|
+
this.say(`Workflow: ${this.settings.mode}. Choose ${AGENT_MODES.join(', ')}.`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (!AGENT_MODES.includes(body))
|
|
195
|
+
throw new Error('Usage: /mode ' + AGENT_MODES.join('|'));
|
|
196
|
+
if (body !== this.settings.mode) {
|
|
197
|
+
this.settings.mode = body;
|
|
198
|
+
this.settings.pr = undefined;
|
|
199
|
+
this.settings.issue = undefined;
|
|
200
|
+
this.resetContext();
|
|
201
|
+
}
|
|
202
|
+
this.say('Workflow: ' + body + '. Following messages use this workflow.');
|
|
203
|
+
await this.persist();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (name === 'permissions') {
|
|
207
|
+
if (!body) {
|
|
208
|
+
this.say(`Checks: ${this.settings.checks ? 'on' : 'off'} · GitHub writes: ${this.settings.github ? 'on' : 'off'}\n/permissions checks on|off · /permissions github on|off`);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (args.length !== 2 || !['checks', 'github'].includes(args[0]) || !['on', 'off'].includes(args[1]))
|
|
212
|
+
throw new Error('Usage: /permissions checks|github on|off');
|
|
213
|
+
const key = args[0], value = args[1] === 'on';
|
|
214
|
+
if (this.settings[key] !== value) {
|
|
215
|
+
this.settings[key] = value;
|
|
216
|
+
this.resetContext();
|
|
217
|
+
}
|
|
218
|
+
this.say(`${key === 'checks' ? 'Repository test execution' : 'GitHub writes'} ${value ? 'enabled' : 'disabled'}.`);
|
|
219
|
+
await this.persist();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (name === 'model') {
|
|
223
|
+
if (args.length > 2 || args.some(arg => arg.length > 512))
|
|
224
|
+
throw new Error('Usage: /model <name> [provider] (maximum 512 characters each)');
|
|
225
|
+
if (!body || body === 'configure') {
|
|
226
|
+
const changed = this.ports.chooseModel ? await this.ports.chooseModel(body === 'configure', this.abort.signal) : (this.say(await this.utility('model')), true);
|
|
227
|
+
if (!changed) {
|
|
228
|
+
this.say('Model selection closed. Current settings kept.');
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.settings.model = undefined;
|
|
232
|
+
this.settings.provider = undefined;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
this.settings.model = args[0] === 'default' ? undefined : args[0];
|
|
236
|
+
this.settings.provider = args[0] === 'default' ? undefined : args[1];
|
|
237
|
+
}
|
|
238
|
+
this.resetContext();
|
|
239
|
+
this.say('Model: ' + (this.settings.model || 'Hermes profile default'));
|
|
240
|
+
await this.persist();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (name === 'limits') {
|
|
244
|
+
if (!body) {
|
|
245
|
+
this.say(`${this.settings.timeout}s · ${this.settings.maxTurns} agent turns`);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const seconds = Number(args[0]), turns = args[1] === undefined ? this.settings.maxTurns : Number(args[1]);
|
|
249
|
+
if (args.length > 2 || !Number.isInteger(seconds) || seconds < 15 || seconds > 3600 || !Number.isInteger(turns) || turns < 1 || turns > 100)
|
|
250
|
+
throw new Error('Usage: /limits <15–3600 seconds> [1–100 turns]');
|
|
251
|
+
this.settings.timeout = seconds;
|
|
252
|
+
this.settings.maxTurns = turns;
|
|
253
|
+
await this.persist();
|
|
254
|
+
this.say(`${seconds}s · ${turns} agent turns`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (name === 'setup' || name === 'doctor') {
|
|
258
|
+
this.say(await this.utility(name));
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (BROWSE_COMMANDS.includes(name)) {
|
|
262
|
+
if (name === 'deep' && !this.settings.checks)
|
|
263
|
+
throw new Error('Enable /permissions checks on before running an external analyzer.');
|
|
264
|
+
if (!this.ports.browse)
|
|
265
|
+
throw new Error('Repository browsing is unavailable.');
|
|
266
|
+
this.say(await this.ports.browse(name, args, this.workspace, this.abort.signal));
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (AGENT_MODES.includes(name)) {
|
|
270
|
+
const mode = name;
|
|
271
|
+
let task = body, pr, issue;
|
|
272
|
+
if (['review', 'triage'].includes(mode) && /^\d+(?:\s|$)/.test(body)) {
|
|
273
|
+
const match = /^(\d+)(?:\s+([\s\S]*))?$/.exec(body);
|
|
274
|
+
const id = Number(match[1]);
|
|
275
|
+
if (!Number.isSafeInteger(id) || id < 1)
|
|
276
|
+
throw new Error('Use a positive PR or issue number.');
|
|
277
|
+
if (mode === 'review')
|
|
278
|
+
pr = id;
|
|
279
|
+
else
|
|
280
|
+
issue = id;
|
|
281
|
+
task = match[2] || '';
|
|
282
|
+
}
|
|
283
|
+
task ||= mode === 'review' ? `Review ${pr ? 'PR #' + pr : 'local changes'} for actionable correctness and security issues.` : mode === 'triage' ? `Investigate ${issue ? 'issue #' + issue : 'open issues'} and propose a prioritized plan.` : '';
|
|
284
|
+
if (!task)
|
|
285
|
+
throw new Error(`Usage: /${mode} <task>`);
|
|
286
|
+
if (mode !== this.settings.mode || pr !== this.settings.pr || issue !== this.settings.issue)
|
|
287
|
+
this.resetContext();
|
|
288
|
+
Object.assign(this.settings, { mode, pr, issue });
|
|
289
|
+
await this.run(task);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
throw new Error(`Unknown command /${name}. Use /help; Tab completes commands.`);
|
|
293
|
+
}
|
|
294
|
+
catch (e) {
|
|
295
|
+
this.say(e instanceof Error ? e.message : String(e));
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
this.busy = false;
|
|
299
|
+
this.abort = null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
async submit(task) {
|
|
303
|
+
this.busy = true;
|
|
304
|
+
this.abort = new AbortController();
|
|
305
|
+
try {
|
|
306
|
+
await this.run(task);
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
this.say(e instanceof Error ? e.message : String(e));
|
|
310
|
+
}
|
|
311
|
+
finally {
|
|
312
|
+
this.busy = false;
|
|
313
|
+
this.abort = null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async utility(name) {
|
|
317
|
+
if (!this.ports.utility)
|
|
318
|
+
throw new Error(`Use onboarder agent ${name} in a terminal.`);
|
|
319
|
+
return this.ports.utility(name, this.abort.signal);
|
|
320
|
+
}
|
|
321
|
+
async openSource(target) {
|
|
322
|
+
const source = await this.sources.open(target, this.settings.root, this.abort.signal, text => this.say(text));
|
|
323
|
+
this.abort.signal.throwIfAborted();
|
|
324
|
+
await this.persist();
|
|
325
|
+
this.abort.signal.throwIfAborted();
|
|
326
|
+
this.record = newChat({ ...this.settings, root: source.root, sourceUrl: source.sourceUrl, pr: undefined, issue: undefined });
|
|
327
|
+
this.lastResult = null;
|
|
328
|
+
this.say(`Repository: ${source.sourceUrl || source.root}\nNew conversation. Type your question.`);
|
|
329
|
+
await this.persist();
|
|
330
|
+
}
|
|
331
|
+
async resume(id) {
|
|
332
|
+
const record = await this.store.load(id);
|
|
333
|
+
if (record.settings.root !== this.settings.root)
|
|
334
|
+
throw new Error('This conversation belongs to another repository. Switch with /repo first.');
|
|
335
|
+
let result = null;
|
|
336
|
+
if (record.lastRun) {
|
|
337
|
+
const saved = await savedRun(record.lastRun, this.store.home);
|
|
338
|
+
if (saved.manifest.sourceRoot !== this.settings.root || saved.manifest.mode !== record.settings.mode || !saved.result?.sessionId)
|
|
339
|
+
throw new Error('This conversation has no resumable Hermes session. Use /new.');
|
|
340
|
+
await fs.access(saved.manifest.root);
|
|
341
|
+
if (this.settings.checks && !saved.manifest.permissions.checks || this.settings.github && !saved.manifest.permissions.github)
|
|
342
|
+
throw new Error('Resume cannot expand permissions. Turn them off first or use /new.');
|
|
343
|
+
result = saved.result;
|
|
344
|
+
}
|
|
345
|
+
// Restore the model and task target, while retaining the permissions chosen in this application.
|
|
346
|
+
const changed = record.settings.checks !== this.settings.checks || record.settings.github !== this.settings.github;
|
|
347
|
+
record.settings.checks = this.settings.checks;
|
|
348
|
+
record.settings.github = this.settings.github;
|
|
349
|
+
if (changed)
|
|
350
|
+
record.lastRun = null;
|
|
351
|
+
this.record = record;
|
|
352
|
+
this.lastResult = changed ? null : result;
|
|
353
|
+
this.say(`Resumed conversation ${id}.\n${this.status()}${changed ? '\nPermissions changed; the next task starts a new Hermes session.' : ''}`);
|
|
354
|
+
const last = record.turns.at(-1);
|
|
355
|
+
if (last)
|
|
356
|
+
this.say('Last answer\n' + last.answer);
|
|
357
|
+
}
|
|
358
|
+
async run(task) {
|
|
359
|
+
if (!task.trim() || task.length > 16000)
|
|
360
|
+
throw new Error('Messages must contain 1–16000 characters.');
|
|
361
|
+
const s = this.settings, start = Date.now();
|
|
362
|
+
const request = { root: s.root, mode: s.mode, task, model: s.model, provider: s.provider, pr: s.pr, issue: s.issue,
|
|
363
|
+
base: s.base, allowChecks: s.checks, allowGithubWrites: s.github, timeoutSeconds: s.timeout, maxTurns: s.maxTurns,
|
|
364
|
+
...(this.record.lastRun ? { resume: this.record.lastRun } : {}) };
|
|
365
|
+
this.ports.output({ type: 'start', prompt: terminalText(redact(task, this.ports.runner?.env)), mode: s.mode });
|
|
366
|
+
let result, sessionStarted = false;
|
|
367
|
+
try {
|
|
368
|
+
result = await (this.ports.run || runAgent)(request, { ...this.ports.runner, signal: this.abort.signal,
|
|
369
|
+
onEvent: event => {
|
|
370
|
+
if (['text', 'tool_use', 'tool_result'].includes(event.type))
|
|
371
|
+
sessionStarted = true;
|
|
372
|
+
this.ports.output({ type: 'event', event });
|
|
373
|
+
} });
|
|
374
|
+
}
|
|
375
|
+
catch (e) {
|
|
376
|
+
// Validation can reject before a run exists. Finish the UI without inventing a saved run.
|
|
377
|
+
this.say('Task could not start: ' + (e instanceof Error ? e.message : String(e)));
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if ('dryRun' in result)
|
|
381
|
+
throw new Error('Chat requires a live agent result.');
|
|
382
|
+
this.lastResult = result;
|
|
383
|
+
// Failed startup can emit an ID without creating a usable Hermes session.
|
|
384
|
+
// Keep the previous working session on failure; new failures start fresh.
|
|
385
|
+
if (result.sessionId && (result.status === 'completed' || result.status === 'cancelled' && sessionStarted))
|
|
386
|
+
this.record.lastRun = result.id;
|
|
387
|
+
this.record.turns.push({ at: new Date().toISOString(), prompt: task, answer: result.answer, run: result.id, status: result.status });
|
|
388
|
+
this.record.turns = this.record.turns.slice(-100);
|
|
389
|
+
this.ports.output({ type: 'end', result, elapsed: Date.now() - start });
|
|
390
|
+
await this.persist();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/cli/chat/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport { AGENT_MODES, type AgentMode, type AgentRequest, type AgentEvent, type AgentResult } from '../agent/contracts.js';\nimport { runAgent, savedRun, type RunnerOptions } from '../agent/runner.js';\nimport { agentHome } from '../agent/config.js';\nimport { redact, terminalText } from '../agent/process.js';\nimport { ChatStore, newChat, historySummary, type ChatRecord, type ChatSettings } from './store.js';\nimport { slashInput, chatHelp, BROWSE_COMMANDS } from './commands.js';\nimport { ChatSources, isRemoteSource } from './source.js';\n\nexport type ChatOutput =\n | { type: 'message'; text: string }\n | { type: 'start'; prompt: string; mode: AgentMode }\n | { type: 'event'; event: AgentEvent }\n | { type: 'end'; result: AgentResult; elapsed: number }\n | { type: 'clear' | 'exit' };\nexport interface ChatPorts {\n output: (event: ChatOutput) => void;\n run?: typeof runAgent;\n browse?: (name: string, args: string[], root: string, signal: AbortSignal) => Promise<string>;\n utility?: (name: ChatUtility, signal: AbortSignal) => Promise<string>;\n chooseModel?: (configure: boolean, signal: AbortSignal) => Promise<boolean>;\n store?: ChatStore; runner?: Omit<RunnerOptions, 'onEvent' | 'signal'>;\n sources?: ChatSources;\n}\nexport type ChatUtility = 'doctor' | 'setup' | 'model' | 'tools' | 'runs';\nexport class ChatController {\n record: ChatRecord;\n lastResult: AgentResult | null = null;\n busy = false;\n closed = false;\n private abort: AbortController | null = null;\n private paste: string[] | null = null;\n private store: ChatStore;\n private sources: ChatSources;\n constructor(settings: ChatSettings, private ports: ChatPorts) {\n this.record = newChat(settings);\n this.store = ports.store || new ChatStore(ports.runner?.home || agentHome(ports.runner?.env), ports.runner?.env);\n this.sources = ports.sources || new ChatSources(this.store.home, { env: ports.runner?.env });\n }\n get settings() { return this.record.settings; }\n get pasting() { return this.paste !== null; }\n get workspace() { return this.lastResult?.workspace || this.settings.root; }\n private say(text: string) { this.ports.output({ type: 'message', text: terminalText(redact(text, this.ports.runner?.env)) }); }\n cancel() { this.abort?.abort(); }\n close() { this.closed = true; this.cancel(); this.paste = null; this.ports.output({ type: 'exit' }); }\n private async persist() {\n this.record.updatedAt = new Date().toISOString();\n try { await this.store.save(this.record); return true; }\n catch (e) { this.say(`Could not save this conversation: ${e instanceof Error ? e.message : e}. The agent run remains in agent runs.`); return false; }\n }\n async save() { return this.persist(); }\n private resetContext() { this.record.lastRun = null; this.lastResult = null; }\n status(): string {\n const s = this.settings;\n return [...(s.sourceUrl ? [`GitHub: ${s.sourceUrl}`] : []), `Repository: ${s.root}`, `Workflow: ${s.mode}${s.pr ? ' · PR #' + s.pr : ''}${s.issue ? ' · issue #' + s.issue : ''}`,\n `Model: ${s.model || 'Hermes profile default'}${s.provider ? ' (' + s.provider + ')' : ''}`,\n `Permissions: files ${['implement', 'pr'].includes(s.mode) ? 'isolated workspace' : 'read only'} · checks ${s.checks ? 'on' : 'off'} · GitHub writes ${s.github ? 'on' : 'off'}`,\n `Limits: ${s.timeout}s · ${s.maxTurns} agent turns`, `Conversation: ${this.record.id}`, `Session run: ${this.record.lastRun || 'new'}`,\n `Workspace: ${this.workspace}`, ...(this.lastResult?.branch ? [`Branch: ${this.lastResult.branch}`] : [])].join('\\n');\n }\n async accept(input: string): Promise<void> {\n if (this.closed) return;\n const trimmed = input.trim(), command = slashInput(trimmed);\n if (command?.name === 'exit' || command?.name === 'quit') { this.close(); return; }\n if (command?.name === 'cancel') { if (this.busy) { this.cancel(); this.say('Cancelling…'); } else this.say('No active task.'); return; }\n if (this.busy) { this.say('A task is running. Use /cancel or Ctrl-C before starting another.'); return; }\n if (this.paste !== null) {\n if (trimmed === '/discard') { this.paste = null; this.say('Multiline message discarded.'); return; }\n if (trimmed === '/send') { const body = this.paste.join('\\n'); this.paste = null; if (body.trim()) await this.submit(body); return; }\n if (this.paste.join('\\n').length + input.length + 1 > 16000) { this.say('Message limit is 16000 characters. /send or /discard this message.'); return; }\n this.paste.push(input); return;\n }\n if (!trimmed) return;\n this.busy = true; this.abort = new AbortController();\n try {\n if (!command) {\n if (trimmed.startsWith('/')) throw new Error('Invalid slash command. Use /help.');\n const first = trimmed.split(/\\s+/)[0]!;\n if (isRemoteSource(first)) {\n await this.openSource(first);\n const question = trimmed.slice(first.length).trim(); if (question) await this.run(question);\n return;\n }\n await this.run(trimmed); return;\n }\n const { name, args, body } = command;\n if (!name || name === 'help') { this.say(chatHelp(args[0])); return; }\n if (name === 'status') { this.say(this.status()); return; }\n if (name === 'skills') { this.say('Built-in workflow skills\\n' + ['ask — repository Q&A', 'review — local and PR review', 'triage — investigate issues', 'implement — isolated code changes', 'pr — prepare or publish a draft PR', 'github — issues, discussions, labels, and CI'].map(s => ' /' + s).join('\\n')); return; }\n if (name === 'tools' || name === 'runs') { this.say(await this.utility(name)); return; }\n if (name === 'run') {\n const saved = await savedRun(args[0] || '', this.store.home);\n if (saved.manifest.sourceRoot !== this.settings.root) throw new Error('This run belongs to another repository. Switch with /repo first.');\n this.say(`Run: ${saved.manifest.id} · ${saved.result?.status || 'unfinished'}\\nWorkspace: ${saved.manifest.root}\\n\\n${saved.result?.answer || 'No saved final answer.'}`); return;\n }\n if (name === 'export') { this.say('Conversation exported: ' + await this.store.export(this.record)); return; }\n if (name === 'send' || name === 'discard') { this.say('Use /paste first to compose a multiline message.'); return; }\n if (name === 'clear') { this.ports.output({ type: 'clear' }); return; }\n if (name === 'paste') { this.paste = []; this.say('Multiline input. /send submits; /discard cancels.'); return; }\n if (name === 'new') { this.record = newChat({ ...this.settings, pr: undefined, issue: undefined }); this.lastResult = null; this.say('New conversation. ' + this.record.id); await this.persist(); return; }\n if (name === 'history') { this.say(historySummary(await this.store.list(this.settings.root))); return; }\n if (name === 'resume') { await this.resume(args[0] || ''); return; }\n if (name === 'repo' || name === 'clone') {\n if (!body) { this.say(name === 'clone' ? 'Usage: /clone <GitHub URL>' : (this.settings.sourceUrl || this.settings.root)); return; }\n if (name === 'clone' && (args.length !== 1 || !isRemoteSource(args[0]!))) throw new Error('Usage: /clone <GitHub URL>');\n await this.openSource(args.join(' ')); return;\n }\n if (name === 'pull') {\n if (body) throw new Error('Usage: /pull');\n if (this.lastResult?.branch) throw new Error('Use /new before pulling the source checkout. Your implementation workspace remains saved in agent runs.');\n this.say(await this.sources.pull(this.settings.root, this.abort.signal, text => this.say(text)));\n this.resetContext(); await this.persist(); this.say('Source refreshed. The next question starts a new agent session.'); return;\n }\n if (name === 'mode') {\n if (!body) { this.say(`Workflow: ${this.settings.mode}. Choose ${AGENT_MODES.join(', ')}.`); return; }\n if (!AGENT_MODES.includes(body as AgentMode)) throw new Error('Usage: /mode ' + AGENT_MODES.join('|'));\n if (body !== this.settings.mode) { this.settings.mode = body as AgentMode; this.settings.pr = undefined; this.settings.issue = undefined; this.resetContext(); }\n this.say('Workflow: ' + body + '. Following messages use this workflow.'); await this.persist(); return;\n }\n if (name === 'permissions') {\n if (!body) { this.say(`Checks: ${this.settings.checks ? 'on' : 'off'} · GitHub writes: ${this.settings.github ? 'on' : 'off'}\\n/permissions checks on|off · /permissions github on|off`); return; }\n if (args.length !== 2 || !['checks', 'github'].includes(args[0]!) || !['on', 'off'].includes(args[1]!)) throw new Error('Usage: /permissions checks|github on|off');\n const key = args[0] as 'checks' | 'github', value = args[1] === 'on';\n if (this.settings[key] !== value) { this.settings[key] = value; this.resetContext(); }\n this.say(`${key === 'checks' ? 'Repository test execution' : 'GitHub writes'} ${value ? 'enabled' : 'disabled'}.`); await this.persist(); return;\n }\n if (name === 'model') {\n if (args.length > 2 || args.some(arg => arg.length > 512)) throw new Error('Usage: /model <name> [provider] (maximum 512 characters each)');\n if (!body || body === 'configure') {\n const changed = this.ports.chooseModel ? await this.ports.chooseModel(body === 'configure', this.abort.signal) : (this.say(await this.utility('model')), true);\n if (!changed) { this.say('Model selection closed. Current settings kept.'); return; }\n this.settings.model = undefined; this.settings.provider = undefined;\n }\n else { this.settings.model = args[0] === 'default' ? undefined : args[0]; this.settings.provider = args[0] === 'default' ? undefined : args[1]; }\n this.resetContext(); this.say('Model: ' + (this.settings.model || 'Hermes profile default')); await this.persist(); return;\n }\n if (name === 'limits') {\n if (!body) { this.say(`${this.settings.timeout}s · ${this.settings.maxTurns} agent turns`); return; }\n const seconds = Number(args[0]), turns = args[1] === undefined ? this.settings.maxTurns : Number(args[1]);\n if (args.length > 2 || !Number.isInteger(seconds) || seconds < 15 || seconds > 3600 || !Number.isInteger(turns) || turns < 1 || turns > 100) throw new Error('Usage: /limits <15–3600 seconds> [1–100 turns]');\n this.settings.timeout = seconds; this.settings.maxTurns = turns; await this.persist(); this.say(`${seconds}s · ${turns} agent turns`); return;\n }\n if (name === 'setup' || name === 'doctor') { this.say(await this.utility(name)); return; }\n if (BROWSE_COMMANDS.includes(name as typeof BROWSE_COMMANDS[number])) {\n if (name === 'deep' && !this.settings.checks) throw new Error('Enable /permissions checks on before running an external analyzer.');\n if (!this.ports.browse) throw new Error('Repository browsing is unavailable.');\n this.say(await this.ports.browse(name, args, this.workspace, this.abort.signal)); return;\n }\n if (AGENT_MODES.includes(name as AgentMode)) {\n const mode = name as AgentMode;\n let task = body, pr: number | undefined, issue: number | undefined;\n if (['review', 'triage'].includes(mode) && /^\\d+(?:\\s|$)/.test(body)) {\n const match = /^(\\d+)(?:\\s+([\\s\\S]*))?$/.exec(body)!;\n const id = Number(match[1]); if (!Number.isSafeInteger(id) || id < 1) throw new Error('Use a positive PR or issue number.');\n if (mode === 'review') pr = id; else issue = id;\n task = match[2] || '';\n }\n task ||= mode === 'review' ? `Review ${pr ? 'PR #' + pr : 'local changes'} for actionable correctness and security issues.` : mode === 'triage' ? `Investigate ${issue ? 'issue #' + issue : 'open issues'} and propose a prioritized plan.` : '';\n if (!task) throw new Error(`Usage: /${mode} <task>`);\n if (mode !== this.settings.mode || pr !== this.settings.pr || issue !== this.settings.issue) this.resetContext();\n Object.assign(this.settings, { mode, pr, issue }); await this.run(task); return;\n }\n throw new Error(`Unknown command /${name}. Use /help; Tab completes commands.`);\n } catch (e) { this.say(e instanceof Error ? e.message : String(e)); }\n finally { this.busy = false; this.abort = null; }\n }\n private async submit(task: string) {\n this.busy = true; this.abort = new AbortController();\n try { await this.run(task); } catch (e) { this.say(e instanceof Error ? e.message : String(e)); }\n finally { this.busy = false; this.abort = null; }\n }\n private async utility(name: ChatUtility) {\n if (!this.ports.utility) throw new Error(`Use onboarder agent ${name} in a terminal.`);\n return this.ports.utility(name, this.abort!.signal);\n }\n private async openSource(target: string) {\n const source = await this.sources.open(target, this.settings.root, this.abort!.signal, text => this.say(text));\n this.abort!.signal.throwIfAborted();\n await this.persist();\n this.abort!.signal.throwIfAborted();\n this.record = newChat({ ...this.settings, root: source.root, sourceUrl: source.sourceUrl, pr: undefined, issue: undefined });\n this.lastResult = null;\n this.say(`Repository: ${source.sourceUrl || source.root}\\nNew conversation. Type your question.`);\n await this.persist();\n }\n async resume(id: string) {\n const record = await this.store.load(id);\n if (record.settings.root !== this.settings.root) throw new Error('This conversation belongs to another repository. Switch with /repo first.');\n let result: AgentResult | null = null;\n if (record.lastRun) {\n const saved = await savedRun(record.lastRun, this.store.home);\n if (saved.manifest.sourceRoot !== this.settings.root || saved.manifest.mode !== record.settings.mode || !saved.result?.sessionId) throw new Error('This conversation has no resumable Hermes session. Use /new.');\n await fs.access(saved.manifest.root);\n if (this.settings.checks && !saved.manifest.permissions.checks || this.settings.github && !saved.manifest.permissions.github) throw new Error('Resume cannot expand permissions. Turn them off first or use /new.');\n result = saved.result;\n }\n // Restore the model and task target, while retaining the permissions chosen in this application.\n const changed = record.settings.checks !== this.settings.checks || record.settings.github !== this.settings.github;\n record.settings.checks = this.settings.checks; record.settings.github = this.settings.github;\n if (changed) record.lastRun = null;\n this.record = record; this.lastResult = changed ? null : result;\n this.say(`Resumed conversation ${id}.\\n${this.status()}${changed ? '\\nPermissions changed; the next task starts a new Hermes session.' : ''}`);\n const last = record.turns.at(-1); if (last) this.say('Last answer\\n' + last.answer);\n }\n private async run(task: string) {\n if (!task.trim() || task.length > 16000) throw new Error('Messages must contain 1–16000 characters.');\n const s = this.settings, start = Date.now();\n const request: AgentRequest = { root: s.root, mode: s.mode, task, model: s.model, provider: s.provider, pr: s.pr, issue: s.issue,\n base: s.base, allowChecks: s.checks, allowGithubWrites: s.github, timeoutSeconds: s.timeout, maxTurns: s.maxTurns,\n ...(this.record.lastRun ? { resume: this.record.lastRun } : {}) };\n this.ports.output({ type: 'start', prompt: terminalText(redact(task, this.ports.runner?.env)), mode: s.mode });\n let result: Awaited<ReturnType<typeof runAgent>>, sessionStarted = false;\n try {\n result = await (this.ports.run || runAgent)(request, { ...this.ports.runner, signal: this.abort!.signal,\n onEvent: event => {\n if (['text', 'tool_use', 'tool_result'].includes(event.type)) sessionStarted = true;\n this.ports.output({ type: 'event', event });\n } });\n } catch (e) {\n // Validation can reject before a run exists. Finish the UI without inventing a saved run.\n this.say('Task could not start: ' + (e instanceof Error ? e.message : String(e))); return;\n }\n if ('dryRun' in result) throw new Error('Chat requires a live agent result.');\n this.lastResult = result;\n // Failed startup can emit an ID without creating a usable Hermes session.\n // Keep the previous working session on failure; new failures start fresh.\n if (result.sessionId && (result.status === 'completed' || result.status === 'cancelled' && sessionStarted)) this.record.lastRun = result.id;\n this.record.turns.push({ at: new Date().toISOString(), prompt: task, answer: result.answer, run: result.id, status: result.status });\n this.record.turns = this.record.turns.slice(-100);\n this.ports.output({ type: 'end', result, elapsed: Date.now() - start });\n await this.persist();\n }\n}\n"]}
|
package/cli/chat/logo.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Original Onboarder mark: a compass inside an O, with a repository branch. */
|
|
2
|
+
export const ONBOARDER_MARK = [
|
|
3
|
+
' ▄██████▄',
|
|
4
|
+
' ▄██▀ ▀██▄',
|
|
5
|
+
' ▄██ ▲ ██▄',
|
|
6
|
+
' ██ │ ██',
|
|
7
|
+
' ██ ●───┼───● ██',
|
|
8
|
+
' ██ │ ██',
|
|
9
|
+
' ▀██ ● ██▀',
|
|
10
|
+
' ▀██▄ ▄██▀',
|
|
11
|
+
' ▀██████▀',
|
|
12
|
+
];
|
|
13
|
+
export const ONBOARDER_COMPACT_MARK = [' ╭─────╮', ' │ ▲ │', ' │ ●┼● │', ' │ ● │', ' ╰─────╯'];
|
|
14
|
+
//# sourceMappingURL=logo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logo.js","sourceRoot":"","sources":["../../src/cli/chat/logo.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,mBAAmB;IACnB,sBAAsB;IACtB,wBAAwB;IACxB,wBAAwB;IACxB,wBAAwB;IACxB,wBAAwB;IACxB,wBAAwB;IACxB,sBAAsB;IACtB,mBAAmB;CACpB,CAAC;AACF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC","sourcesContent":["/** Original Onboarder mark: a compass inside an O, with a repository branch. */\nexport const ONBOARDER_MARK = [\n ' ▄██████▄',\n ' ▄██▀ ▀██▄',\n ' ▄██ ▲ ██▄',\n ' ██ │ ██',\n ' ██ ●───┼───● ██',\n ' ██ │ ██',\n ' ▀██ ● ██▀',\n ' ▀██▄ ▄██▀',\n ' ▀██████▀',\n];\nexport const ONBOARDER_COMPACT_MARK = [' ╭─────╮', ' │ ▲ │', ' │ ●┼● │', ' │ ● │', ' ╰─────╯'];\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { runProcess } from '../agent/process.js';
|
|
2
|
+
export interface ModelProvider {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
models: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare class HermesModels {
|
|
8
|
+
private home;
|
|
9
|
+
private env;
|
|
10
|
+
private execute;
|
|
11
|
+
constructor(home?: string, env?: NodeJS.ProcessEnv, execute?: typeof runProcess);
|
|
12
|
+
private request;
|
|
13
|
+
catalog(signal: AbortSignal): Promise<ModelProvider[]>;
|
|
14
|
+
select(model: string, provider: string, signal: AbortSignal): Promise<{
|
|
15
|
+
model: string;
|
|
16
|
+
provider: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|