@aria_asi/cli 0.2.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/bin/aria.js +168 -0
- package/dist/aria-connector/src/auth-commands.d.ts +28 -0
- package/dist/aria-connector/src/auth-commands.d.ts.map +1 -0
- package/dist/aria-connector/src/auth-commands.js +129 -0
- package/dist/aria-connector/src/auth-commands.js.map +1 -0
- package/dist/aria-connector/src/auth.d.ts +12 -0
- package/dist/aria-connector/src/auth.d.ts.map +1 -0
- package/dist/aria-connector/src/auth.js +31 -0
- package/dist/aria-connector/src/auth.js.map +1 -0
- package/dist/aria-connector/src/auto-mcp.d.ts +23 -0
- package/dist/aria-connector/src/auto-mcp.d.ts.map +1 -0
- package/dist/aria-connector/src/auto-mcp.js +994 -0
- package/dist/aria-connector/src/auto-mcp.js.map +1 -0
- package/dist/aria-connector/src/chat.d.ts +21 -0
- package/dist/aria-connector/src/chat.d.ts.map +1 -0
- package/dist/aria-connector/src/chat.js +332 -0
- package/dist/aria-connector/src/chat.js.map +1 -0
- package/dist/aria-connector/src/codebase-scanner.d.ts +7 -0
- package/dist/aria-connector/src/codebase-scanner.d.ts.map +1 -0
- package/dist/aria-connector/src/codebase-scanner.js +6 -0
- package/dist/aria-connector/src/codebase-scanner.js.map +1 -0
- package/dist/aria-connector/src/cognition-log.d.ts +17 -0
- package/dist/aria-connector/src/cognition-log.d.ts.map +1 -0
- package/dist/aria-connector/src/cognition-log.js +19 -0
- package/dist/aria-connector/src/cognition-log.js.map +1 -0
- package/dist/aria-connector/src/config.d.ts +41 -0
- package/dist/aria-connector/src/config.d.ts.map +1 -0
- package/dist/aria-connector/src/config.js +50 -0
- package/dist/aria-connector/src/config.js.map +1 -0
- package/dist/aria-connector/src/connectors/claude-code.d.ts +4 -0
- package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/claude-code.js +204 -0
- package/dist/aria-connector/src/connectors/claude-code.js.map +1 -0
- package/dist/aria-connector/src/connectors/cursor.d.ts +4 -0
- package/dist/aria-connector/src/connectors/cursor.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/cursor.js +63 -0
- package/dist/aria-connector/src/connectors/cursor.js.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts +4 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.js +102 -0
- package/dist/aria-connector/src/connectors/opencode.js.map +1 -0
- package/dist/aria-connector/src/connectors/shell.d.ts +4 -0
- package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/shell.js +58 -0
- package/dist/aria-connector/src/connectors/shell.js.map +1 -0
- package/dist/aria-connector/src/garden-client.d.ts +19 -0
- package/dist/aria-connector/src/garden-client.d.ts.map +1 -0
- package/dist/aria-connector/src/garden-client.js +85 -0
- package/dist/aria-connector/src/garden-client.js.map +1 -0
- package/dist/aria-connector/src/garden-control-plane.d.ts +22 -0
- package/dist/aria-connector/src/garden-control-plane.d.ts.map +1 -0
- package/dist/aria-connector/src/garden-control-plane.js +43 -0
- package/dist/aria-connector/src/garden-control-plane.js.map +1 -0
- package/dist/aria-connector/src/harness-client.d.ts +166 -0
- package/dist/aria-connector/src/harness-client.d.ts.map +1 -0
- package/dist/aria-connector/src/harness-client.js +344 -0
- package/dist/aria-connector/src/harness-client.js.map +1 -0
- package/dist/aria-connector/src/hive-client.d.ts +32 -0
- package/dist/aria-connector/src/hive-client.d.ts.map +1 -0
- package/dist/aria-connector/src/hive-client.js +69 -0
- package/dist/aria-connector/src/hive-client.js.map +1 -0
- package/dist/aria-connector/src/index.d.ts +19 -0
- package/dist/aria-connector/src/index.d.ts.map +1 -0
- package/dist/aria-connector/src/index.js +13 -0
- package/dist/aria-connector/src/index.js.map +1 -0
- package/dist/aria-connector/src/install-hooks.d.ts +18 -0
- package/dist/aria-connector/src/install-hooks.d.ts.map +1 -0
- package/dist/aria-connector/src/install-hooks.js +224 -0
- package/dist/aria-connector/src/install-hooks.js.map +1 -0
- package/dist/aria-connector/src/model-context.d.ts +8 -0
- package/dist/aria-connector/src/model-context.d.ts.map +1 -0
- package/dist/aria-connector/src/model-context.js +83 -0
- package/dist/aria-connector/src/model-context.js.map +1 -0
- package/dist/aria-connector/src/persona.d.ts +27 -0
- package/dist/aria-connector/src/persona.d.ts.map +1 -0
- package/dist/aria-connector/src/persona.js +86 -0
- package/dist/aria-connector/src/persona.js.map +1 -0
- package/dist/aria-connector/src/providers/anthropic.d.ts +4 -0
- package/dist/aria-connector/src/providers/anthropic.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/anthropic.js +92 -0
- package/dist/aria-connector/src/providers/anthropic.js.map +1 -0
- package/dist/aria-connector/src/providers/deepseek.d.ts +3 -0
- package/dist/aria-connector/src/providers/deepseek.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/deepseek.js +28 -0
- package/dist/aria-connector/src/providers/deepseek.js.map +1 -0
- package/dist/aria-connector/src/providers/google.d.ts +3 -0
- package/dist/aria-connector/src/providers/google.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/google.js +38 -0
- package/dist/aria-connector/src/providers/google.js.map +1 -0
- package/dist/aria-connector/src/providers/ollama.d.ts +3 -0
- package/dist/aria-connector/src/providers/ollama.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/ollama.js +28 -0
- package/dist/aria-connector/src/providers/ollama.js.map +1 -0
- package/dist/aria-connector/src/providers/openai.d.ts +4 -0
- package/dist/aria-connector/src/providers/openai.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/openai.js +84 -0
- package/dist/aria-connector/src/providers/openai.js.map +1 -0
- package/dist/aria-connector/src/providers/openrouter.d.ts +3 -0
- package/dist/aria-connector/src/providers/openrouter.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/openrouter.js +30 -0
- package/dist/aria-connector/src/providers/openrouter.js.map +1 -0
- package/dist/aria-connector/src/providers/types.d.ts +20 -0
- package/dist/aria-connector/src/providers/types.d.ts.map +1 -0
- package/dist/aria-connector/src/providers/types.js +2 -0
- package/dist/aria-connector/src/providers/types.js.map +1 -0
- package/dist/aria-connector/src/setup-wizard.d.ts +2 -0
- package/dist/aria-connector/src/setup-wizard.d.ts.map +1 -0
- package/dist/aria-connector/src/setup-wizard.js +140 -0
- package/dist/aria-connector/src/setup-wizard.js.map +1 -0
- package/dist/aria-connector/src/types.d.ts +30 -0
- package/dist/aria-connector/src/types.d.ts.map +1 -0
- package/dist/aria-connector/src/types.js +5 -0
- package/dist/aria-connector/src/types.js.map +1 -0
- package/dist/aria-web/src/lib/codebase-scanner.d.ts +127 -0
- package/dist/aria-web/src/lib/codebase-scanner.d.ts.map +1 -0
- package/dist/aria-web/src/lib/codebase-scanner.js +1730 -0
- package/dist/aria-web/src/lib/codebase-scanner.js.map +1 -0
- package/dist/cli-0.2.0.tgz +0 -0
- package/dist/install.sh +13 -0
- package/hooks/aria-harness-via-sdk.mjs +317 -0
- package/hooks/aria-pre-tool-gate.mjs +596 -0
- package/hooks/aria-preprompt-consult.mjs +175 -0
- package/hooks/aria-stop-gate.mjs +222 -0
- package/package.json +47 -0
- package/src/__tests__/auth-commands.test.ts +132 -0
- package/src/auth-commands.ts +175 -0
- package/src/auth.ts +33 -0
- package/src/auto-mcp.ts +1172 -0
- package/src/chat.ts +387 -0
- package/src/codebase-scanner.ts +18 -0
- package/src/cognition-log.ts +30 -0
- package/src/config.ts +94 -0
- package/src/connectors/claude-code.ts +213 -0
- package/src/connectors/cursor.ts +75 -0
- package/src/connectors/opencode.ts +115 -0
- package/src/connectors/shell.ts +72 -0
- package/src/garden-client.ts +98 -0
- package/src/garden-control-plane.ts +108 -0
- package/src/harness-client.ts +454 -0
- package/src/hive-client.ts +104 -0
- package/src/index.ts +26 -0
- package/src/install-hooks.ts +259 -0
- package/src/model-context.ts +88 -0
- package/src/persona.ts +113 -0
- package/src/providers/anthropic.ts +120 -0
- package/src/providers/deepseek.ts +40 -0
- package/src/providers/google.ts +57 -0
- package/src/providers/ollama.ts +43 -0
- package/src/providers/openai.ts +108 -0
- package/src/providers/openrouter.ts +42 -0
- package/src/providers/types.ts +35 -0
- package/src/setup-wizard.ts +177 -0
- package/src/types.ts +32 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Message, ChatOptions, ChatResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
export async function chat(
|
|
4
|
+
messages: Message[],
|
|
5
|
+
_apiKey: string,
|
|
6
|
+
model: string,
|
|
7
|
+
opts?: ChatOptions,
|
|
8
|
+
): Promise<ChatResult> {
|
|
9
|
+
const baseUrl = process.env.OLLAMA_HOST || 'http://localhost:11434';
|
|
10
|
+
|
|
11
|
+
const resp = await fetch(`${baseUrl}/api/chat`, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14
|
+
body: JSON.stringify({
|
|
15
|
+
model: model || 'llama3',
|
|
16
|
+
messages,
|
|
17
|
+
stream: false,
|
|
18
|
+
options: {
|
|
19
|
+
num_predict: opts?.maxTokens ?? 4096,
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
signal: opts?.signal,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (!resp.ok) {
|
|
26
|
+
const err = await resp.text().catch(() => resp.statusText);
|
|
27
|
+
throw new Error(`Ollama error ${resp.status}: ${err}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const data = (await resp.json()) as {
|
|
31
|
+
message?: { content: string };
|
|
32
|
+
eval_count?: number;
|
|
33
|
+
prompt_eval_count?: number;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
text: data.message?.content ?? '',
|
|
38
|
+
usage:
|
|
39
|
+
data.prompt_eval_count !== undefined
|
|
40
|
+
? { promptTokens: data.prompt_eval_count, completionTokens: data.eval_count ?? 0 }
|
|
41
|
+
: undefined,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Message, ChatOptions, ChatResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
export async function chat(
|
|
4
|
+
messages: Message[],
|
|
5
|
+
apiKey: string,
|
|
6
|
+
model: string,
|
|
7
|
+
opts?: ChatOptions,
|
|
8
|
+
): Promise<ChatResult> {
|
|
9
|
+
if (opts?.stream) {
|
|
10
|
+
return streamChat(messages, apiKey, model);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const resp = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
headers: {
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
Authorization: `Bearer ${apiKey}`,
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify({
|
|
20
|
+
model: model || 'gpt-4o',
|
|
21
|
+
messages,
|
|
22
|
+
max_tokens: opts?.maxTokens ?? 4096,
|
|
23
|
+
stream: false,
|
|
24
|
+
}),
|
|
25
|
+
signal: opts?.signal,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (!resp.ok) {
|
|
29
|
+
const err = await resp.text().catch(() => resp.statusText);
|
|
30
|
+
throw new Error(`OpenAI error ${resp.status}: ${err}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const data = (await resp.json()) as {
|
|
34
|
+
choices: { message: { content: string } }[];
|
|
35
|
+
usage?: { prompt_tokens: number; completion_tokens: number };
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
text: data.choices[0]?.message?.content ?? '',
|
|
40
|
+
usage: data.usage
|
|
41
|
+
? { promptTokens: data.usage.prompt_tokens, completionTokens: data.usage.completion_tokens }
|
|
42
|
+
: undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function streamChat(
|
|
47
|
+
messages: Message[],
|
|
48
|
+
apiKey: string,
|
|
49
|
+
model: string,
|
|
50
|
+
onToken?: (token: string) => void,
|
|
51
|
+
): Promise<ChatResult> {
|
|
52
|
+
const resp = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
Authorization: `Bearer ${apiKey}`,
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({
|
|
59
|
+
model: model || 'gpt-4o',
|
|
60
|
+
messages,
|
|
61
|
+
max_tokens: 4096,
|
|
62
|
+
stream: true,
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (!resp.ok) {
|
|
67
|
+
const err = await resp.text().catch(() => resp.statusText);
|
|
68
|
+
throw new Error(`OpenAI error ${resp.status}: ${err}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const reader = resp.body?.getReader();
|
|
72
|
+
if (!reader) throw new Error('No response body');
|
|
73
|
+
|
|
74
|
+
let fullText = '';
|
|
75
|
+
const decoder = new TextDecoder();
|
|
76
|
+
let buffer = '';
|
|
77
|
+
|
|
78
|
+
while (true) {
|
|
79
|
+
const { done, value } = await reader.read();
|
|
80
|
+
if (done) break;
|
|
81
|
+
|
|
82
|
+
buffer += decoder.decode(value, { stream: true });
|
|
83
|
+
const lines = buffer.split('\n');
|
|
84
|
+
buffer = lines.pop() ?? '';
|
|
85
|
+
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
const trimmed = line.trim();
|
|
88
|
+
if (!trimmed.startsWith('data: ')) continue;
|
|
89
|
+
const json = trimmed.slice(6);
|
|
90
|
+
if (json === '[DONE]') continue;
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(json) as {
|
|
94
|
+
choices?: { delta?: { content?: string } }[];
|
|
95
|
+
};
|
|
96
|
+
const token = parsed.choices?.[0]?.delta?.content;
|
|
97
|
+
if (token) {
|
|
98
|
+
fullText += token;
|
|
99
|
+
onToken?.(token);
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
// skip malformed chunks
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { text: fullText };
|
|
108
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Message, ChatOptions, ChatResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
export async function chat(
|
|
4
|
+
messages: Message[],
|
|
5
|
+
apiKey: string,
|
|
6
|
+
model: string,
|
|
7
|
+
opts?: ChatOptions,
|
|
8
|
+
): Promise<ChatResult> {
|
|
9
|
+
const resp = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
|
10
|
+
method: 'POST',
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
Authorization: `Bearer ${apiKey}`,
|
|
14
|
+
'HTTP-Referer': 'http://localhost',
|
|
15
|
+
'X-Title': 'Aria Smart CLI',
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
model: model || 'openai/gpt-4o',
|
|
19
|
+
messages,
|
|
20
|
+
max_tokens: opts?.maxTokens ?? 4096,
|
|
21
|
+
stream: false,
|
|
22
|
+
}),
|
|
23
|
+
signal: opts?.signal,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!resp.ok) {
|
|
27
|
+
const err = await resp.text().catch(() => resp.statusText);
|
|
28
|
+
throw new Error(`OpenRouter error ${resp.status}: ${err}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const data = (await resp.json()) as {
|
|
32
|
+
choices: { message: { content: string } }[];
|
|
33
|
+
usage?: { prompt_tokens: number; completion_tokens: number };
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
text: data.choices[0]?.message?.content ?? '',
|
|
38
|
+
usage: data.usage
|
|
39
|
+
? { promptTokens: data.usage.prompt_tokens, completionTokens: data.usage.completion_tokens }
|
|
40
|
+
: undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface Message {
|
|
2
|
+
role: 'system' | 'user' | 'assistant';
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface ChatOptions {
|
|
7
|
+
stream?: boolean;
|
|
8
|
+
maxTokens?: number;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ChatResult {
|
|
13
|
+
text: string;
|
|
14
|
+
usage?: {
|
|
15
|
+
promptTokens: number;
|
|
16
|
+
completionTokens: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ProviderName = 'openai' | 'anthropic' | 'google' | 'deepseek' | 'openrouter' | 'ollama';
|
|
21
|
+
|
|
22
|
+
export type ChatFn = (
|
|
23
|
+
messages: Message[],
|
|
24
|
+
apiKey: string,
|
|
25
|
+
model: string,
|
|
26
|
+
opts?: ChatOptions,
|
|
27
|
+
) => Promise<ChatResult>;
|
|
28
|
+
|
|
29
|
+
export type StreamChatFn = (
|
|
30
|
+
messages: Message[],
|
|
31
|
+
apiKey: string,
|
|
32
|
+
model: string,
|
|
33
|
+
onToken: (token: string) => void,
|
|
34
|
+
opts?: ChatOptions,
|
|
35
|
+
) => Promise<ChatResult>;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Thin-loop onboarding — server-driven deep conversation.
|
|
2
|
+
//
|
|
3
|
+
// Replaces the prior 200-line hardcoded Q&A wizard. The CLI is now a
|
|
4
|
+
// pure render loop calling /api/onboarding/converse on aria-soul; the
|
|
5
|
+
// server holds the topic state machine, depth tracking, and templated
|
|
6
|
+
// (eventually Aria-voiced) prompts. Every configWrite the server emits
|
|
7
|
+
// is applied locally here — that keeps integration provisioning
|
|
8
|
+
// (codebase scan, persona update, config set) on the client where it
|
|
9
|
+
// belongs without baking the conversation flow into the CLI.
|
|
10
|
+
//
|
|
11
|
+
// Direction set 2026-04-26 (Hamza): "onboarding is not a Q&A wizard.
|
|
12
|
+
// It's a deep conversation with Aria directly, where Aria and the user
|
|
13
|
+
// co-direct depth." See HARNESS_RELEASE_PLAN.md §"Onboarding refactor"
|
|
14
|
+
// and apps/arias-soul/api/onboarding/converse.ts for the server side.
|
|
15
|
+
|
|
16
|
+
import { createInterface } from 'readline';
|
|
17
|
+
import { randomBytes } from 'crypto';
|
|
18
|
+
import { loadConfig, updateConfig, type AriaConfig, type LinkedRepo } from './config.js';
|
|
19
|
+
import { scanCodebase, schemaImageToText } from './codebase-scanner.js';
|
|
20
|
+
import { updatePersona } from './persona.js';
|
|
21
|
+
|
|
22
|
+
const HARNESS_URL = process.env.ARIA_HARNESS_URL || 'http://192.168.4.25:30080';
|
|
23
|
+
const HARNESS_TOKEN = process.env.ARIA_HARNESS_TOKEN || '';
|
|
24
|
+
|
|
25
|
+
type ConfigWrite =
|
|
26
|
+
| { kind: 'persona_update'; updates: Record<string, unknown> }
|
|
27
|
+
| { kind: 'config_set'; path: string[]; value: unknown }
|
|
28
|
+
| { kind: 'codebase_scan'; cwd: string }
|
|
29
|
+
| { kind: 'note'; text: string };
|
|
30
|
+
|
|
31
|
+
interface DepthOption {
|
|
32
|
+
label: string;
|
|
33
|
+
signal: string;
|
|
34
|
+
hint?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface ConverseResponse {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
sessionId: string;
|
|
40
|
+
topic: 'identity' | 'codebase' | 'persona' | 'done';
|
|
41
|
+
ariaPrompt: string;
|
|
42
|
+
depthOptions: DepthOption[];
|
|
43
|
+
freeTextAllowed: boolean;
|
|
44
|
+
configWrites?: ConfigWrite[];
|
|
45
|
+
isComplete: boolean;
|
|
46
|
+
progressPct: number;
|
|
47
|
+
error?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function runSetupWizard(): Promise<void> {
|
|
51
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
52
|
+
const ask = (q: string): Promise<string> =>
|
|
53
|
+
new Promise((resolve) => rl.question(q, (a) => resolve(a)));
|
|
54
|
+
|
|
55
|
+
const sessionId = `onboard_${Date.now()}_${randomBytes(4).toString('hex')}`;
|
|
56
|
+
let userMessage: string | undefined;
|
|
57
|
+
let action: 'start' | 'answer' = 'start';
|
|
58
|
+
|
|
59
|
+
console.log('\n💬 Aria: starting onboarding…\n');
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
while (true) {
|
|
63
|
+
const resp = await callConverse({ sessionId, action, userMessage });
|
|
64
|
+
if (!resp.ok) {
|
|
65
|
+
console.error(`\n❌ Onboarding error: ${resp.error || 'unknown'}`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(`\nđź’¬ Aria: ${resp.ariaPrompt}`);
|
|
70
|
+
|
|
71
|
+
if (resp.configWrites?.length) {
|
|
72
|
+
await applyConfigWrites(resp.configWrites);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (resp.isComplete) break;
|
|
76
|
+
|
|
77
|
+
if (resp.depthOptions.length) {
|
|
78
|
+
const chips = resp.depthOptions.map((o) => `[${o.label}]`).join(' ');
|
|
79
|
+
console.log(` options: ${chips}${resp.freeTextAllowed ? ' (or type your own)' : ''}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
userMessage = (await ask('> ')).trim();
|
|
83
|
+
action = 'answer';
|
|
84
|
+
if (!userMessage) userMessage = resp.depthOptions[0]?.signal ?? 'next';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('\nâś… Setup complete. Run `aria status` anytime.\n');
|
|
88
|
+
} finally {
|
|
89
|
+
rl.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function callConverse(body: {
|
|
94
|
+
sessionId: string;
|
|
95
|
+
action: 'start' | 'answer';
|
|
96
|
+
userMessage?: string;
|
|
97
|
+
}): Promise<ConverseResponse> {
|
|
98
|
+
try {
|
|
99
|
+
const res = await fetch(`${HARNESS_URL}/api/onboarding/converse`, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: {
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
...(HARNESS_TOKEN ? { Authorization: `Bearer ${HARNESS_TOKEN}` } : {}),
|
|
104
|
+
},
|
|
105
|
+
body: JSON.stringify(body),
|
|
106
|
+
});
|
|
107
|
+
return (await res.json()) as ConverseResponse;
|
|
108
|
+
} catch (err) {
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
sessionId: body.sessionId,
|
|
112
|
+
topic: 'identity',
|
|
113
|
+
ariaPrompt: '',
|
|
114
|
+
depthOptions: [],
|
|
115
|
+
freeTextAllowed: false,
|
|
116
|
+
isComplete: false,
|
|
117
|
+
progressPct: 0,
|
|
118
|
+
error: err instanceof Error ? err.message : String(err),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function applyConfigWrites(writes: ConfigWrite[]): Promise<void> {
|
|
124
|
+
for (const w of writes) {
|
|
125
|
+
try {
|
|
126
|
+
if (w.kind === 'persona_update') {
|
|
127
|
+
updatePersona(w.updates as Parameters<typeof updatePersona>[0]);
|
|
128
|
+
} else if (w.kind === 'config_set') {
|
|
129
|
+
const patch = pathToPatch(w.path, w.value);
|
|
130
|
+
updateConfig(patch);
|
|
131
|
+
} else if (w.kind === 'codebase_scan') {
|
|
132
|
+
const cwd = w.cwd === '__CLI_CWD__' ? process.cwd() : w.cwd;
|
|
133
|
+
const image = await scanCodebase(cwd);
|
|
134
|
+
const text = schemaImageToText(image);
|
|
135
|
+
const config = loadConfig();
|
|
136
|
+
updateConfig({
|
|
137
|
+
schemaImages: { ...config.schemaImages, [image.projectName]: text },
|
|
138
|
+
repositories: [
|
|
139
|
+
...config.repositories.filter((r) => r.path !== cwd),
|
|
140
|
+
{
|
|
141
|
+
path: cwd,
|
|
142
|
+
name: image.projectName,
|
|
143
|
+
scanHash: '',
|
|
144
|
+
lastScan: new Date().toISOString(),
|
|
145
|
+
} as LinkedRepo,
|
|
146
|
+
],
|
|
147
|
+
});
|
|
148
|
+
console.log(
|
|
149
|
+
` scanned: ${image.language}${image.framework && image.framework !== image.language ? `, ${image.framework}` : ''}` +
|
|
150
|
+
`${image.orm ? `, ${image.orm}` : ''}${image.database ? ` with ${image.database}` : ''}` +
|
|
151
|
+
` — ${image.fileCount} files`,
|
|
152
|
+
);
|
|
153
|
+
} else if (w.kind === 'note') {
|
|
154
|
+
console.log(` 📝 ${w.text}`);
|
|
155
|
+
}
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.warn(` âš configWrite '${w.kind}' failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function pathToPatch(path: string[], value: unknown): Partial<AriaConfig> {
|
|
163
|
+
if (path.length === 1) return { [path[0]]: value } as Partial<AriaConfig>;
|
|
164
|
+
// Nested path → shallow merge under top-level key.
|
|
165
|
+
const top = path[0] as keyof AriaConfig;
|
|
166
|
+
const rest = path.slice(1);
|
|
167
|
+
const config = loadConfig();
|
|
168
|
+
const current = (config[top] ?? {}) as Record<string, unknown>;
|
|
169
|
+
const cursor: Record<string, unknown> = { ...current };
|
|
170
|
+
let pointer: Record<string, unknown> = cursor;
|
|
171
|
+
for (let i = 0; i < rest.length - 1; i++) {
|
|
172
|
+
pointer[rest[i]] = { ...((pointer[rest[i]] as Record<string, unknown>) ?? {}) };
|
|
173
|
+
pointer = pointer[rest[i]] as Record<string, unknown>;
|
|
174
|
+
}
|
|
175
|
+
pointer[rest[rest.length - 1]] = value;
|
|
176
|
+
return { [top]: cursor } as Partial<AriaConfig>;
|
|
177
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for harness-client and cognition log.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface AuthConfig {
|
|
6
|
+
/** Token from license file or env var */
|
|
7
|
+
harnessToken?: string;
|
|
8
|
+
/** License JWT identifier */
|
|
9
|
+
jti?: string;
|
|
10
|
+
/** License tier (e.g. 'standard', 'pro') */
|
|
11
|
+
tier?: string;
|
|
12
|
+
/** License expiry unix timestamp */
|
|
13
|
+
exp?: number;
|
|
14
|
+
/** License issued-at unix timestamp */
|
|
15
|
+
iat?: number;
|
|
16
|
+
/** License subject (userId) */
|
|
17
|
+
sub?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface HarnessResponse<T = unknown> {
|
|
21
|
+
success: boolean;
|
|
22
|
+
data?: T;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface HarnessGateDecision {
|
|
27
|
+
gate: string;
|
|
28
|
+
passed: boolean;
|
|
29
|
+
reason?: string;
|
|
30
|
+
score?: number;
|
|
31
|
+
metadata?: Record<string, unknown>;
|
|
32
|
+
}
|