arki 0.0.6 → 0.0.7
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 +2 -0
- package/dist/config/arki/config.json +1 -1
- package/dist/index.d.ts +51 -58
- package/dist/index.js +273 -363
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,7 @@ arki [options]
|
|
|
45
45
|
Options:
|
|
46
46
|
-p <path> Specify working directory
|
|
47
47
|
--debug, -d Enable debug mode, show detailed logs
|
|
48
|
+
--init Initialize project config without prompting
|
|
48
49
|
--reset Reset configuration to factory defaults
|
|
49
50
|
--help, -h Show help information
|
|
50
51
|
```
|
|
@@ -99,6 +100,7 @@ Each project can have its own configuration in `.arki/` directory:
|
|
|
99
100
|
- `.arki/state.json` - Project state and cache
|
|
100
101
|
|
|
101
102
|
On first run in a new project, Arki will ask if you trust the project before initializing the `.arki/` directory.
|
|
103
|
+
Use `--init` to skip the prompt in non-interactive environments.
|
|
102
104
|
|
|
103
105
|
### Reset to Factory Defaults
|
|
104
106
|
|
package/dist/index.d.ts
CHANGED
|
@@ -160,15 +160,16 @@ declare const PATHS: {
|
|
|
160
160
|
projectTemplate: string;
|
|
161
161
|
};
|
|
162
162
|
|
|
163
|
-
/**
|
|
164
|
-
* Fixed parameters
|
|
165
|
-
*/
|
|
166
|
-
declare const TEMPERATURE = 0.2;
|
|
167
|
-
declare const MAX_COMPLETION_TOKENS = 4096;
|
|
168
163
|
/**
|
|
169
164
|
* Reasoning effort
|
|
170
165
|
*/
|
|
171
166
|
type ReasoningEffort$1 = 'low' | 'medium' | 'high';
|
|
167
|
+
/**
|
|
168
|
+
* Platform-specific options for adapter
|
|
169
|
+
*/
|
|
170
|
+
interface AdapterOptions {
|
|
171
|
+
[key: string]: unknown;
|
|
172
|
+
}
|
|
172
173
|
/**
|
|
173
174
|
* LLM response result
|
|
174
175
|
*/
|
|
@@ -184,45 +185,31 @@ interface AdapterResponse {
|
|
|
184
185
|
}
|
|
185
186
|
/**
|
|
186
187
|
* LLM adapter base class
|
|
188
|
+
* Only contains platform authentication, model/tools belong to Agent
|
|
187
189
|
*/
|
|
188
190
|
declare abstract class Adapter {
|
|
189
191
|
protected apiKey: string;
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
protected flex?: boolean;
|
|
193
|
-
/** Reasoning effort (thinking mode) */
|
|
194
|
-
protected reasoningEffort?: ReasoningEffort$1;
|
|
195
|
-
/** Available tools list */
|
|
196
|
-
protected tools?: Tool[];
|
|
197
|
-
constructor(config: {
|
|
198
|
-
apiKey: string;
|
|
199
|
-
model: string;
|
|
200
|
-
/** Use Flex API (OpenAI) - low priority, low cost */
|
|
201
|
-
flex?: boolean;
|
|
202
|
-
/** Reasoning effort (thinking mode) */
|
|
203
|
-
reasoningEffort?: ReasoningEffort$1;
|
|
204
|
-
/** Available tools list */
|
|
205
|
-
tools?: Tool[];
|
|
206
|
-
});
|
|
207
|
-
abstract chat(messages: Msg[], onChunk?: (chunk: string) => void): Promise<AdapterResponse>;
|
|
208
|
-
getModel(): string;
|
|
192
|
+
constructor(apiKey: string);
|
|
193
|
+
abstract chat(model: string, messages: Msg[], tools: Tool[], options: AdapterOptions, onChunk?: (chunk: string) => void): Promise<AdapterResponse>;
|
|
209
194
|
}
|
|
210
195
|
|
|
211
196
|
/** Global tool registry */
|
|
212
197
|
declare const TOOLS: Record<string, Tool>;
|
|
213
198
|
/** Global procedure registry */
|
|
214
199
|
declare const PROCEDURES: Record<string, Procedure>;
|
|
215
|
-
/** Global
|
|
216
|
-
declare
|
|
217
|
-
/**
|
|
218
|
-
|
|
200
|
+
/** Global adapter registry by platform */
|
|
201
|
+
declare const adapters: Record<string, Adapter>;
|
|
202
|
+
/**
|
|
203
|
+
* Get adapter by platform name
|
|
204
|
+
*/
|
|
205
|
+
declare function getAdapter(platform: string): Adapter;
|
|
219
206
|
/** Initialize global state */
|
|
220
|
-
declare function init(cwd?: string): Promise<void>;
|
|
207
|
+
declare function init(cwd?: string, forceInit?: boolean): Promise<void>;
|
|
221
208
|
|
|
222
209
|
/**
|
|
223
210
|
* Agent type
|
|
224
211
|
*/
|
|
225
|
-
type AgentType = '
|
|
212
|
+
type AgentType = 'arki' | 'coder';
|
|
226
213
|
/**
|
|
227
214
|
* Reasoning effort
|
|
228
215
|
*/
|
|
@@ -231,23 +218,17 @@ type ReasoningEffort = 'low' | 'medium' | 'high';
|
|
|
231
218
|
* Agent model configuration
|
|
232
219
|
*/
|
|
233
220
|
interface AgentModelConfig {
|
|
234
|
-
/** Model ID */
|
|
221
|
+
/** Model ID (provider is derived from MODELS) */
|
|
235
222
|
model: string;
|
|
236
|
-
/** Use Flex API (low priority, low cost) */
|
|
223
|
+
/** Use Flex API (low priority, low cost) - OpenAI specific */
|
|
237
224
|
flex?: boolean;
|
|
238
225
|
/** Reasoning effort (thinking mode) */
|
|
239
226
|
reasoningEffort?: ReasoningEffort;
|
|
240
227
|
}
|
|
241
228
|
/**
|
|
242
|
-
* Global configuration
|
|
229
|
+
* Global configuration (from config files)
|
|
243
230
|
*/
|
|
244
231
|
interface GlobalConfig {
|
|
245
|
-
apiKeys?: {
|
|
246
|
-
openai?: string;
|
|
247
|
-
anthropic?: string;
|
|
248
|
-
google?: string;
|
|
249
|
-
[key: string]: string | undefined;
|
|
250
|
-
};
|
|
251
232
|
agents: {
|
|
252
233
|
[K in AgentType]?: AgentModelConfig;
|
|
253
234
|
};
|
|
@@ -257,7 +238,7 @@ interface GlobalConfig {
|
|
|
257
238
|
*/
|
|
258
239
|
declare function getConfig(): GlobalConfig;
|
|
259
240
|
/**
|
|
260
|
-
* Get API key
|
|
241
|
+
* Get API key from environment variable
|
|
261
242
|
*/
|
|
262
243
|
declare function getApiKey(provider: string): string | undefined;
|
|
263
244
|
/**
|
|
@@ -355,18 +336,23 @@ declare function convertColorTags(str: string): string;
|
|
|
355
336
|
*/
|
|
356
337
|
declare function createColorConverter(): (chunk: string) => string;
|
|
357
338
|
|
|
339
|
+
/**
|
|
340
|
+
* OpenAI-specific options
|
|
341
|
+
*/
|
|
342
|
+
interface OpenAIOptions extends AdapterOptions {
|
|
343
|
+
/** Use Flex API - low priority, low cost */
|
|
344
|
+
flex?: boolean;
|
|
345
|
+
/** Reasoning effort (thinking mode) */
|
|
346
|
+
reasoningEffort?: ReasoningEffort$1;
|
|
347
|
+
/** Maximum completion tokens for LLM response */
|
|
348
|
+
maxCompletionTokens?: number;
|
|
349
|
+
}
|
|
358
350
|
declare class OpenAIAdapter extends Adapter {
|
|
359
351
|
private client;
|
|
360
|
-
constructor(
|
|
361
|
-
apiKey: string;
|
|
362
|
-
model: string;
|
|
363
|
-
flex?: boolean;
|
|
364
|
-
reasoningEffort?: 'low' | 'medium' | 'high';
|
|
365
|
-
tools?: Tool[];
|
|
366
|
-
});
|
|
352
|
+
constructor(apiKey: string);
|
|
367
353
|
private toOpenAIMessages;
|
|
368
|
-
private
|
|
369
|
-
chat(messages: Msg[], onChunk?: (chunk: string) => void): Promise<AdapterResponse>;
|
|
354
|
+
private formatTools;
|
|
355
|
+
chat(model: string, messages: Msg[], tools: Tool[], options: OpenAIOptions, onChunk?: (chunk: string) => void): Promise<AdapterResponse>;
|
|
370
356
|
}
|
|
371
357
|
|
|
372
358
|
interface AgentResponse {
|
|
@@ -383,17 +369,24 @@ interface AgentResponse {
|
|
|
383
369
|
cachedTokens?: number;
|
|
384
370
|
};
|
|
385
371
|
}
|
|
372
|
+
interface AgentConfig {
|
|
373
|
+
adapter: Adapter;
|
|
374
|
+
model: string;
|
|
375
|
+
tools: Tool[];
|
|
376
|
+
platformOptions?: AdapterOptions;
|
|
377
|
+
messages: Msg[];
|
|
378
|
+
/** Maximum completion tokens for LLM response */
|
|
379
|
+
maxCompletionTokens?: number;
|
|
380
|
+
onStream?: (chunk: string) => void;
|
|
381
|
+
onToolCallMsg?: (msg: ToolCallMsg) => void;
|
|
382
|
+
onBeforeToolRun?: (name: string, args: Record<string, unknown>) => void;
|
|
383
|
+
onToolResult?: (name: string, args: Record<string, unknown>, result: string) => void;
|
|
384
|
+
}
|
|
386
385
|
declare class Agent {
|
|
387
386
|
private config;
|
|
388
387
|
private messages;
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
messages: Msg[];
|
|
392
|
-
onStream?: (chunk: string) => void;
|
|
393
|
-
onToolCallMsg?: (msg: ToolCallMsg) => void;
|
|
394
|
-
onBeforeToolRun?: (name: string, args: Record<string, unknown>) => void;
|
|
395
|
-
onToolResult?: (name: string, args: Record<string, unknown>, result: string) => void;
|
|
396
|
-
});
|
|
388
|
+
private toolsMap;
|
|
389
|
+
constructor(config: AgentConfig);
|
|
397
390
|
/**
|
|
398
391
|
* Render template string, replacing {{variable}} style variables
|
|
399
392
|
*/
|
|
@@ -428,4 +421,4 @@ interface Model {
|
|
|
428
421
|
readonly capabilities: ModelCapabilities;
|
|
429
422
|
}
|
|
430
423
|
|
|
431
|
-
export { AIMsg, Adapter, type AdapterResponse, Agent, type AgentModelConfig, type AgentResponse, type AgentType, type ColorName, type GlobalConfig, HAS_MANUAL,
|
|
424
|
+
export { AIMsg, Adapter, type AdapterOptions, type AdapterResponse, Agent, type AgentModelConfig, type AgentResponse, type AgentType, type ColorName, type GlobalConfig, HAS_MANUAL, MODELS, type Model, type ModelCapabilities, type ModelProvider, Msg, MsgType, OS, type OS_TYPE, OpenAIAdapter, type OpenAIOptions, PATHS, PROCEDURES, type ReasoningEffort$1 as ReasoningEffort, SystemMsg, TOOLS, Tool, type ToolCall, ToolCallMsg, type ToolResult, ToolResultMsg, UserMsg, adapters, colors, convertColorTags, createColorConverter, debug, error, getAdapter, getAgentConfig, getApiKey, getConfig, info, init, isDebugMode, log, print, saveConfig, setDebugMode, setWorkingDir, success, warn, workingDir };
|
package/dist/index.js
CHANGED
|
@@ -161,98 +161,6 @@ var init_fs = __esm({
|
|
|
161
161
|
}
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
// src/adapter/Adapter.ts
|
|
165
|
-
var TEMPERATURE, MAX_COMPLETION_TOKENS, Adapter;
|
|
166
|
-
var init_Adapter = __esm({
|
|
167
|
-
"src/adapter/Adapter.ts"() {
|
|
168
|
-
"use strict";
|
|
169
|
-
TEMPERATURE = 0.2;
|
|
170
|
-
MAX_COMPLETION_TOKENS = 4096;
|
|
171
|
-
Adapter = class {
|
|
172
|
-
apiKey;
|
|
173
|
-
model;
|
|
174
|
-
/** Use Flex API (OpenAI) - low priority, low cost */
|
|
175
|
-
flex;
|
|
176
|
-
/** Reasoning effort (thinking mode) */
|
|
177
|
-
reasoningEffort;
|
|
178
|
-
/** Available tools list */
|
|
179
|
-
tools;
|
|
180
|
-
constructor(config) {
|
|
181
|
-
this.apiKey = config.apiKey;
|
|
182
|
-
this.model = config.model;
|
|
183
|
-
this.flex = config.flex;
|
|
184
|
-
this.reasoningEffort = config.reasoningEffort;
|
|
185
|
-
this.tools = config.tools;
|
|
186
|
-
}
|
|
187
|
-
getModel() {
|
|
188
|
-
return this.model;
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// src/agent/Msg.ts
|
|
195
|
-
var MsgType, Msg, SystemMsg, UserMsg, AIMsg, ToolCallMsg, ToolResultMsg;
|
|
196
|
-
var init_Msg = __esm({
|
|
197
|
-
"src/agent/Msg.ts"() {
|
|
198
|
-
"use strict";
|
|
199
|
-
MsgType = /* @__PURE__ */ ((MsgType2) => {
|
|
200
|
-
MsgType2["System"] = "system";
|
|
201
|
-
MsgType2["User"] = "user";
|
|
202
|
-
MsgType2["AI"] = "ai";
|
|
203
|
-
MsgType2["ToolCall"] = "tool_call";
|
|
204
|
-
MsgType2["ToolResult"] = "tool_result";
|
|
205
|
-
return MsgType2;
|
|
206
|
-
})(MsgType || {});
|
|
207
|
-
Msg = class {
|
|
208
|
-
timestamp;
|
|
209
|
-
content;
|
|
210
|
-
constructor(content) {
|
|
211
|
-
this.timestamp = Date.now();
|
|
212
|
-
this.content = content;
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
SystemMsg = class extends Msg {
|
|
216
|
-
type = "system" /* System */;
|
|
217
|
-
constructor(content) {
|
|
218
|
-
super(content);
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
UserMsg = class extends Msg {
|
|
222
|
-
type = "user" /* User */;
|
|
223
|
-
constructor(content) {
|
|
224
|
-
super(content);
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
AIMsg = class extends Msg {
|
|
228
|
-
type = "ai" /* AI */;
|
|
229
|
-
constructor(content) {
|
|
230
|
-
super(content);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
ToolCallMsg = class extends Msg {
|
|
234
|
-
type = "tool_call" /* ToolCall */;
|
|
235
|
-
toolCalls;
|
|
236
|
-
constructor(content, toolCalls) {
|
|
237
|
-
super(content);
|
|
238
|
-
this.toolCalls = toolCalls;
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
ToolResultMsg = class _ToolResultMsg extends Msg {
|
|
242
|
-
type = "tool_result" /* ToolResult */;
|
|
243
|
-
toolResults;
|
|
244
|
-
constructor(toolResults) {
|
|
245
|
-
super("");
|
|
246
|
-
this.toolResults = toolResults;
|
|
247
|
-
}
|
|
248
|
-
/** Helper: create from single result */
|
|
249
|
-
static single(toolName, result, isError) {
|
|
250
|
-
return new _ToolResultMsg([{ toolName, result, isError }]);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
|
|
256
164
|
// src/log/log.ts
|
|
257
165
|
function getTimestamp() {
|
|
258
166
|
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
@@ -362,129 +270,6 @@ var init_log2 = __esm({
|
|
|
362
270
|
}
|
|
363
271
|
});
|
|
364
272
|
|
|
365
|
-
// src/adapter/openai.ts
|
|
366
|
-
import OpenAI from "openai";
|
|
367
|
-
var OpenAIAdapter;
|
|
368
|
-
var init_openai = __esm({
|
|
369
|
-
"src/adapter/openai.ts"() {
|
|
370
|
-
"use strict";
|
|
371
|
-
init_Adapter();
|
|
372
|
-
init_Msg();
|
|
373
|
-
init_log2();
|
|
374
|
-
OpenAIAdapter = class extends Adapter {
|
|
375
|
-
client;
|
|
376
|
-
constructor(config) {
|
|
377
|
-
super(config);
|
|
378
|
-
if (!this.apiKey) {
|
|
379
|
-
throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable.");
|
|
380
|
-
}
|
|
381
|
-
this.client = new OpenAI({ apiKey: this.apiKey });
|
|
382
|
-
}
|
|
383
|
-
toOpenAIMessages(messages) {
|
|
384
|
-
const result = [];
|
|
385
|
-
let pendingIds = [];
|
|
386
|
-
for (const msg of messages) {
|
|
387
|
-
if (msg.type === "system" /* System */ || msg.type === "user" /* User */) {
|
|
388
|
-
result.push({ role: msg.type, content: msg.content });
|
|
389
|
-
} else if (msg.type === "ai" /* AI */) {
|
|
390
|
-
result.push({ role: "assistant", content: msg.content });
|
|
391
|
-
} else if (msg.type === "tool_call" /* ToolCall */) {
|
|
392
|
-
const toolCallMsg = msg;
|
|
393
|
-
pendingIds = toolCallMsg.toolCalls.map((_, i) => `call_${msg.timestamp}_${i}`);
|
|
394
|
-
result.push({
|
|
395
|
-
role: "assistant",
|
|
396
|
-
content: msg.content || null,
|
|
397
|
-
tool_calls: toolCallMsg.toolCalls.map((tc, i) => ({
|
|
398
|
-
id: pendingIds[i],
|
|
399
|
-
type: "function",
|
|
400
|
-
function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
|
|
401
|
-
}))
|
|
402
|
-
});
|
|
403
|
-
} else if (msg.type === "tool_result" /* ToolResult */) {
|
|
404
|
-
const toolResultMsg = msg;
|
|
405
|
-
for (const tr of toolResultMsg.toolResults) {
|
|
406
|
-
result.push({
|
|
407
|
-
role: "tool",
|
|
408
|
-
tool_call_id: pendingIds.shift() || `call_${msg.timestamp}`,
|
|
409
|
-
content: tr.isError ? `Error: ${tr.result}` : tr.result
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return result;
|
|
415
|
-
}
|
|
416
|
-
getTools() {
|
|
417
|
-
return this.tools?.map((t) => ({
|
|
418
|
-
type: "function",
|
|
419
|
-
function: {
|
|
420
|
-
name: t.name,
|
|
421
|
-
description: t.description,
|
|
422
|
-
parameters: {
|
|
423
|
-
type: "object",
|
|
424
|
-
properties: t.parameters,
|
|
425
|
-
required: t.required.length > 0 ? t.required : void 0
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}));
|
|
429
|
-
}
|
|
430
|
-
async chat(messages, onChunk) {
|
|
431
|
-
debug("API", `Requesting OpenAI (model: ${this.model}, messages: ${messages.length})`);
|
|
432
|
-
const openaiMessages = this.toOpenAIMessages(messages);
|
|
433
|
-
const startTime = Date.now();
|
|
434
|
-
const requestParams = {
|
|
435
|
-
model: this.model,
|
|
436
|
-
messages: openaiMessages,
|
|
437
|
-
tools: this.getTools(),
|
|
438
|
-
temperature: TEMPERATURE,
|
|
439
|
-
max_completion_tokens: MAX_COMPLETION_TOKENS,
|
|
440
|
-
stream: true,
|
|
441
|
-
stream_options: { include_usage: true },
|
|
442
|
-
service_tier: this.flex ? "flex" : void 0,
|
|
443
|
-
reasoning_effort: this.reasoningEffort
|
|
444
|
-
};
|
|
445
|
-
const stream = await this.client.chat.completions.create(requestParams);
|
|
446
|
-
let text = "";
|
|
447
|
-
const toolCalls = /* @__PURE__ */ new Map();
|
|
448
|
-
let usage;
|
|
449
|
-
for await (const chunk of stream) {
|
|
450
|
-
const delta = chunk.choices[0]?.delta;
|
|
451
|
-
if (delta?.content) {
|
|
452
|
-
text += delta.content;
|
|
453
|
-
onChunk?.(delta.content);
|
|
454
|
-
}
|
|
455
|
-
if (delta?.tool_calls) {
|
|
456
|
-
for (const tc of delta.tool_calls) {
|
|
457
|
-
const cur = toolCalls.get(tc.index) || { name: "", args: "" };
|
|
458
|
-
cur.name += tc.function?.name || "";
|
|
459
|
-
cur.args += tc.function?.arguments || "";
|
|
460
|
-
toolCalls.set(tc.index, cur);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
if (chunk.usage) usage = chunk.usage;
|
|
464
|
-
}
|
|
465
|
-
const elapsed = Date.now() - startTime;
|
|
466
|
-
const cachedTokens = usage?.prompt_tokens_details?.cached_tokens;
|
|
467
|
-
const usageData = usage && {
|
|
468
|
-
promptTokens: usage.prompt_tokens,
|
|
469
|
-
completionTokens: usage.completion_tokens,
|
|
470
|
-
totalTokens: usage.total_tokens,
|
|
471
|
-
cachedTokens
|
|
472
|
-
};
|
|
473
|
-
if (toolCalls.size > 0) {
|
|
474
|
-
const calls = [...toolCalls.values()].map((tc) => ({
|
|
475
|
-
name: tc.name,
|
|
476
|
-
arguments: JSON.parse(tc.args || "{}")
|
|
477
|
-
}));
|
|
478
|
-
debug("API", `Completed (${elapsed}ms, tools: ${calls.map((t) => t.name).join(", ")})`);
|
|
479
|
-
return { message: new ToolCallMsg(text, calls), hasToolCalls: true, usage: usageData };
|
|
480
|
-
}
|
|
481
|
-
debug("API", `Completed (${elapsed}ms, tokens: ${usage?.total_tokens || "N/A"})`);
|
|
482
|
-
return { message: new AIMsg(text), hasToolCalls: false, usage: usageData };
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
});
|
|
487
|
-
|
|
488
273
|
// src/init/loader.ts
|
|
489
274
|
var loader_exports = {};
|
|
490
275
|
__export(loader_exports, {
|
|
@@ -500,9 +285,6 @@ function deepMerge(base, override) {
|
|
|
500
285
|
...base,
|
|
501
286
|
agents: { ...base.agents }
|
|
502
287
|
};
|
|
503
|
-
if (override.apiKeys) {
|
|
504
|
-
result.apiKeys = { ...base.apiKeys, ...override.apiKeys };
|
|
505
|
-
}
|
|
506
288
|
if (override.agents) {
|
|
507
289
|
for (const key of Object.keys(override.agents)) {
|
|
508
290
|
const overrideAgent = override.agents[key];
|
|
@@ -513,26 +295,6 @@ function deepMerge(base, override) {
|
|
|
513
295
|
}
|
|
514
296
|
return result;
|
|
515
297
|
}
|
|
516
|
-
function loadEnvApiKeys(config) {
|
|
517
|
-
if (process.env.OPENAI_API_KEY) {
|
|
518
|
-
if (!config.apiKeys) config.apiKeys = {};
|
|
519
|
-
if (!config.apiKeys.openai) {
|
|
520
|
-
config.apiKeys.openai = process.env.OPENAI_API_KEY;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
524
|
-
if (!config.apiKeys) config.apiKeys = {};
|
|
525
|
-
if (!config.apiKeys.anthropic) {
|
|
526
|
-
config.apiKeys.anthropic = process.env.ANTHROPIC_API_KEY;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (process.env.GOOGLE_API_KEY) {
|
|
530
|
-
if (!config.apiKeys) config.apiKeys = {};
|
|
531
|
-
if (!config.apiKeys.google) {
|
|
532
|
-
config.apiKeys.google = process.env.GOOGLE_API_KEY;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
298
|
async function loadConfigs() {
|
|
537
299
|
if (mergedConfig) {
|
|
538
300
|
return mergedConfig;
|
|
@@ -549,7 +311,6 @@ async function loadConfigs() {
|
|
|
549
311
|
} else {
|
|
550
312
|
mergedConfig = globalConfig;
|
|
551
313
|
}
|
|
552
|
-
loadEnvApiKeys(mergedConfig);
|
|
553
314
|
return mergedConfig;
|
|
554
315
|
}
|
|
555
316
|
function getConfig() {
|
|
@@ -559,7 +320,13 @@ function getConfig() {
|
|
|
559
320
|
return mergedConfig;
|
|
560
321
|
}
|
|
561
322
|
function getApiKey(provider) {
|
|
562
|
-
|
|
323
|
+
const envMap = {
|
|
324
|
+
openai: "OPENAI_API_KEY",
|
|
325
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
326
|
+
google: "GOOGLE_API_KEY"
|
|
327
|
+
};
|
|
328
|
+
const envVar = envMap[provider] || `${provider.toUpperCase()}_API_KEY`;
|
|
329
|
+
return process.env[envVar];
|
|
563
330
|
}
|
|
564
331
|
function getAgentConfig(agentType) {
|
|
565
332
|
const agentConfig = getConfig().agents[agentType];
|
|
@@ -571,20 +338,7 @@ function getAgentConfig(agentType) {
|
|
|
571
338
|
async function saveConfig() {
|
|
572
339
|
const config = getConfig();
|
|
573
340
|
const configPath = path3.join(PATHS.globalConfig, "config.json");
|
|
574
|
-
|
|
575
|
-
if (config.apiKeys) {
|
|
576
|
-
configToSave.apiKeys = { ...config.apiKeys };
|
|
577
|
-
if (process.env.OPENAI_API_KEY && configToSave.apiKeys.openai === process.env.OPENAI_API_KEY) {
|
|
578
|
-
delete configToSave.apiKeys.openai;
|
|
579
|
-
}
|
|
580
|
-
if (process.env.ANTHROPIC_API_KEY && configToSave.apiKeys.anthropic === process.env.ANTHROPIC_API_KEY) {
|
|
581
|
-
delete configToSave.apiKeys.anthropic;
|
|
582
|
-
}
|
|
583
|
-
if (process.env.GOOGLE_API_KEY && configToSave.apiKeys.google === process.env.GOOGLE_API_KEY) {
|
|
584
|
-
delete configToSave.apiKeys.google;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
await writeJsonFile(configPath, configToSave);
|
|
341
|
+
await writeJsonFile(configPath, config);
|
|
588
342
|
}
|
|
589
343
|
var mergedConfig;
|
|
590
344
|
var init_loader = __esm({
|
|
@@ -595,28 +349,6 @@ var init_loader = __esm({
|
|
|
595
349
|
}
|
|
596
350
|
});
|
|
597
351
|
|
|
598
|
-
// src/init/index.ts
|
|
599
|
-
var init_exports = {};
|
|
600
|
-
__export(init_exports, {
|
|
601
|
-
PROCEDURES: () => PROCEDURES,
|
|
602
|
-
TOOLS: () => TOOLS,
|
|
603
|
-
adapter: () => adapter,
|
|
604
|
-
getAgentConfig: () => getAgentConfig,
|
|
605
|
-
getApiKey: () => getApiKey,
|
|
606
|
-
getConfig: () => getConfig,
|
|
607
|
-
init: () => init,
|
|
608
|
-
initAdapter: () => initAdapter,
|
|
609
|
-
loadConfigs: () => loadConfigs,
|
|
610
|
-
saveConfig: () => saveConfig
|
|
611
|
-
});
|
|
612
|
-
var init_init = __esm({
|
|
613
|
-
"src/init/index.ts"() {
|
|
614
|
-
"use strict";
|
|
615
|
-
init_global();
|
|
616
|
-
init_loader();
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
|
|
620
352
|
// src/init/project.ts
|
|
621
353
|
var project_exports = {};
|
|
622
354
|
__export(project_exports, {
|
|
@@ -636,14 +368,16 @@ async function askQuestion(question) {
|
|
|
636
368
|
});
|
|
637
369
|
});
|
|
638
370
|
}
|
|
639
|
-
async function initProject() {
|
|
371
|
+
async function initProject(forceInit) {
|
|
640
372
|
const projectConfigDir = PATHS.projectConfig;
|
|
641
373
|
if (await dirExists(projectConfigDir)) {
|
|
642
374
|
return;
|
|
643
375
|
}
|
|
644
|
-
|
|
376
|
+
const trusted = forceInit ? true : await (async () => {
|
|
377
|
+
print(`
|
|
645
378
|
<dim>Project directory: ${workingDir}</dim>`);
|
|
646
|
-
|
|
379
|
+
return askQuestion("Do you trust this project and want to initialize arki config?");
|
|
380
|
+
})();
|
|
647
381
|
if (!trusted) {
|
|
648
382
|
print("<yellow>Initialization cancelled.</yellow>");
|
|
649
383
|
process.exit(0);
|
|
@@ -665,66 +399,233 @@ var init_project = __esm({
|
|
|
665
399
|
}
|
|
666
400
|
});
|
|
667
401
|
|
|
402
|
+
// src/index.ts
|
|
403
|
+
import * as readline2 from "readline";
|
|
404
|
+
import * as fs6 from "fs";
|
|
405
|
+
import * as path8 from "path";
|
|
406
|
+
import * as os2 from "os";
|
|
407
|
+
|
|
408
|
+
// src/global.ts
|
|
409
|
+
init_fs();
|
|
410
|
+
|
|
411
|
+
// src/adapter/openai.ts
|
|
412
|
+
import OpenAI from "openai";
|
|
413
|
+
|
|
414
|
+
// src/adapter/Adapter.ts
|
|
415
|
+
var Adapter = class {
|
|
416
|
+
apiKey;
|
|
417
|
+
constructor(apiKey) {
|
|
418
|
+
this.apiKey = apiKey;
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// src/agent/Msg.ts
|
|
423
|
+
var MsgType = /* @__PURE__ */ ((MsgType2) => {
|
|
424
|
+
MsgType2["System"] = "system";
|
|
425
|
+
MsgType2["User"] = "user";
|
|
426
|
+
MsgType2["AI"] = "ai";
|
|
427
|
+
MsgType2["ToolCall"] = "tool_call";
|
|
428
|
+
MsgType2["ToolResult"] = "tool_result";
|
|
429
|
+
return MsgType2;
|
|
430
|
+
})(MsgType || {});
|
|
431
|
+
var Msg = class {
|
|
432
|
+
timestamp;
|
|
433
|
+
content;
|
|
434
|
+
constructor(content) {
|
|
435
|
+
this.timestamp = Date.now();
|
|
436
|
+
this.content = content;
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
var SystemMsg = class extends Msg {
|
|
440
|
+
type = "system" /* System */;
|
|
441
|
+
constructor(content) {
|
|
442
|
+
super(content);
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
var UserMsg = class extends Msg {
|
|
446
|
+
type = "user" /* User */;
|
|
447
|
+
constructor(content) {
|
|
448
|
+
super(content);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
var AIMsg = class extends Msg {
|
|
452
|
+
type = "ai" /* AI */;
|
|
453
|
+
constructor(content) {
|
|
454
|
+
super(content);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
var ToolCallMsg = class extends Msg {
|
|
458
|
+
type = "tool_call" /* ToolCall */;
|
|
459
|
+
toolCalls;
|
|
460
|
+
constructor(content, toolCalls) {
|
|
461
|
+
super(content);
|
|
462
|
+
this.toolCalls = toolCalls;
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
var ToolResultMsg = class _ToolResultMsg extends Msg {
|
|
466
|
+
type = "tool_result" /* ToolResult */;
|
|
467
|
+
toolResults;
|
|
468
|
+
constructor(toolResults) {
|
|
469
|
+
super("");
|
|
470
|
+
this.toolResults = toolResults;
|
|
471
|
+
}
|
|
472
|
+
/** Helper: create from single result */
|
|
473
|
+
static single(toolName, result, isError) {
|
|
474
|
+
return new _ToolResultMsg([{ toolName, result, isError }]);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/adapter/openai.ts
|
|
479
|
+
init_log2();
|
|
480
|
+
var OpenAIAdapter = class extends Adapter {
|
|
481
|
+
client;
|
|
482
|
+
constructor(apiKey) {
|
|
483
|
+
super(apiKey);
|
|
484
|
+
if (!this.apiKey) {
|
|
485
|
+
throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable.");
|
|
486
|
+
}
|
|
487
|
+
this.client = new OpenAI({ apiKey: this.apiKey });
|
|
488
|
+
}
|
|
489
|
+
toOpenAIMessages(messages) {
|
|
490
|
+
const result = [];
|
|
491
|
+
let pendingIds = [];
|
|
492
|
+
for (const msg of messages) {
|
|
493
|
+
if (msg.type === "system" /* System */ || msg.type === "user" /* User */) {
|
|
494
|
+
result.push({ role: msg.type, content: msg.content });
|
|
495
|
+
} else if (msg.type === "ai" /* AI */) {
|
|
496
|
+
result.push({ role: "assistant", content: msg.content });
|
|
497
|
+
} else if (msg.type === "tool_call" /* ToolCall */) {
|
|
498
|
+
const toolCallMsg = msg;
|
|
499
|
+
pendingIds = toolCallMsg.toolCalls.map((_, i) => `call_${msg.timestamp}_${i}`);
|
|
500
|
+
result.push({
|
|
501
|
+
role: "assistant",
|
|
502
|
+
content: msg.content || null,
|
|
503
|
+
tool_calls: toolCallMsg.toolCalls.map((tc, i) => ({
|
|
504
|
+
id: pendingIds[i],
|
|
505
|
+
type: "function",
|
|
506
|
+
function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
|
|
507
|
+
}))
|
|
508
|
+
});
|
|
509
|
+
} else if (msg.type === "tool_result" /* ToolResult */) {
|
|
510
|
+
const toolResultMsg = msg;
|
|
511
|
+
for (const tr of toolResultMsg.toolResults) {
|
|
512
|
+
result.push({
|
|
513
|
+
role: "tool",
|
|
514
|
+
tool_call_id: pendingIds.shift() || `call_${msg.timestamp}`,
|
|
515
|
+
content: tr.isError ? `Error: ${tr.result}` : tr.result
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return result;
|
|
521
|
+
}
|
|
522
|
+
formatTools(tools) {
|
|
523
|
+
if (tools.length === 0) return void 0;
|
|
524
|
+
return tools.map((t) => ({
|
|
525
|
+
type: "function",
|
|
526
|
+
function: {
|
|
527
|
+
name: t.name,
|
|
528
|
+
description: t.description,
|
|
529
|
+
parameters: {
|
|
530
|
+
type: "object",
|
|
531
|
+
properties: t.parameters,
|
|
532
|
+
required: t.required.length > 0 ? t.required : void 0
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}));
|
|
536
|
+
}
|
|
537
|
+
async chat(model, messages, tools, options, onChunk) {
|
|
538
|
+
debug("API", `Requesting OpenAI (model: ${model}, messages: ${messages.length})`);
|
|
539
|
+
const openaiMessages = this.toOpenAIMessages(messages);
|
|
540
|
+
const startTime = Date.now();
|
|
541
|
+
const requestParams = {
|
|
542
|
+
model,
|
|
543
|
+
messages: openaiMessages,
|
|
544
|
+
tools: this.formatTools(tools),
|
|
545
|
+
max_completion_tokens: options.maxCompletionTokens,
|
|
546
|
+
stream: true,
|
|
547
|
+
stream_options: { include_usage: true },
|
|
548
|
+
service_tier: options.flex ? "flex" : void 0,
|
|
549
|
+
reasoning_effort: options.reasoningEffort
|
|
550
|
+
};
|
|
551
|
+
const stream = await this.client.chat.completions.create(requestParams);
|
|
552
|
+
let text = "";
|
|
553
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
554
|
+
let usage;
|
|
555
|
+
for await (const chunk of stream) {
|
|
556
|
+
const delta = chunk.choices[0]?.delta;
|
|
557
|
+
if (delta?.content) {
|
|
558
|
+
text += delta.content;
|
|
559
|
+
onChunk?.(delta.content);
|
|
560
|
+
}
|
|
561
|
+
if (delta?.tool_calls) {
|
|
562
|
+
for (const tc of delta.tool_calls) {
|
|
563
|
+
const cur = toolCalls.get(tc.index) || { name: "", args: "" };
|
|
564
|
+
cur.name += tc.function?.name || "";
|
|
565
|
+
cur.args += tc.function?.arguments || "";
|
|
566
|
+
toolCalls.set(tc.index, cur);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (chunk.usage) usage = chunk.usage;
|
|
570
|
+
}
|
|
571
|
+
const elapsed = Date.now() - startTime;
|
|
572
|
+
const cachedTokens = usage?.prompt_tokens_details?.cached_tokens;
|
|
573
|
+
const usageData = usage && {
|
|
574
|
+
promptTokens: usage.prompt_tokens,
|
|
575
|
+
completionTokens: usage.completion_tokens,
|
|
576
|
+
totalTokens: usage.total_tokens,
|
|
577
|
+
cachedTokens
|
|
578
|
+
};
|
|
579
|
+
if (toolCalls.size > 0) {
|
|
580
|
+
const calls = [...toolCalls.values()].map((tc) => ({
|
|
581
|
+
name: tc.name,
|
|
582
|
+
arguments: JSON.parse(tc.args || "{}")
|
|
583
|
+
}));
|
|
584
|
+
debug("API", `Completed (${elapsed}ms, tools: ${calls.map((t) => t.name).join(", ")})`);
|
|
585
|
+
return { message: new ToolCallMsg(text, calls), hasToolCalls: true, usage: usageData };
|
|
586
|
+
}
|
|
587
|
+
debug("API", `Completed (${elapsed}ms, tokens: ${usage?.total_tokens || "N/A"})`);
|
|
588
|
+
return { message: new AIMsg(text), hasToolCalls: false, usage: usageData };
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
|
|
668
592
|
// src/init/global.ts
|
|
593
|
+
init_fs();
|
|
594
|
+
var TOOLS = {};
|
|
595
|
+
var PROCEDURES = {};
|
|
596
|
+
var adapters = {};
|
|
597
|
+
function getAdapter(platform) {
|
|
598
|
+
const adapter = adapters[platform];
|
|
599
|
+
if (!adapter) {
|
|
600
|
+
throw new Error(`Adapter not found for platform: ${platform}`);
|
|
601
|
+
}
|
|
602
|
+
return adapter;
|
|
603
|
+
}
|
|
669
604
|
async function initGlobalConfig() {
|
|
670
605
|
const globalConfigDir = PATHS.globalConfig;
|
|
671
|
-
if (await dirExists(globalConfigDir))
|
|
672
|
-
return;
|
|
673
|
-
}
|
|
606
|
+
if (await dirExists(globalConfigDir)) return;
|
|
674
607
|
await copyDir(PATHS.globalTemplate, globalConfigDir);
|
|
675
608
|
}
|
|
676
|
-
function
|
|
677
|
-
|
|
678
|
-
|
|
609
|
+
async function initAdapters() {
|
|
610
|
+
const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
611
|
+
const openaiKey = getApiKey2("openai");
|
|
612
|
+
if (openaiKey) {
|
|
613
|
+
adapters["openai"] = new OpenAIAdapter(openaiKey);
|
|
679
614
|
}
|
|
680
|
-
Promise.resolve().then(() => (init_init(), init_exports)).then(({ getAgentConfig: getAgentConfig2, getApiKey: getApiKey2 }) => {
|
|
681
|
-
const mainAgentConfig = getAgentConfig2("main");
|
|
682
|
-
adapter = new OpenAIAdapter({
|
|
683
|
-
apiKey: getApiKey2("openai") || "",
|
|
684
|
-
model: mainAgentConfig.model,
|
|
685
|
-
flex: mainAgentConfig.flex,
|
|
686
|
-
tools: Object.values(TOOLS)
|
|
687
|
-
});
|
|
688
|
-
});
|
|
689
615
|
}
|
|
690
|
-
async function init(cwd) {
|
|
616
|
+
async function init(cwd, forceInit) {
|
|
691
617
|
const { setWorkingDir: setWorkingDir2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
692
618
|
setWorkingDir2(cwd || process.cwd());
|
|
693
619
|
await initGlobalConfig();
|
|
694
620
|
const { initProject: initProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
|
|
695
|
-
await initProject2();
|
|
696
|
-
const { loadConfigs: loadConfigs2
|
|
621
|
+
await initProject2(forceInit);
|
|
622
|
+
const { loadConfigs: loadConfigs2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
697
623
|
await loadConfigs2();
|
|
698
|
-
|
|
699
|
-
adapter = new OpenAIAdapter({
|
|
700
|
-
apiKey: getApiKey2("openai") || "",
|
|
701
|
-
model: mainAgentConfig.model,
|
|
702
|
-
flex: mainAgentConfig.flex,
|
|
703
|
-
tools: Object.values(TOOLS)
|
|
704
|
-
});
|
|
624
|
+
await initAdapters();
|
|
705
625
|
}
|
|
706
|
-
var TOOLS, PROCEDURES, adapter;
|
|
707
|
-
var init_global = __esm({
|
|
708
|
-
"src/init/global.ts"() {
|
|
709
|
-
"use strict";
|
|
710
|
-
init_openai();
|
|
711
|
-
init_fs();
|
|
712
|
-
TOOLS = {};
|
|
713
|
-
PROCEDURES = {};
|
|
714
|
-
adapter = null;
|
|
715
|
-
}
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
// src/index.ts
|
|
719
|
-
import * as readline2 from "readline";
|
|
720
|
-
import * as fs6 from "fs";
|
|
721
|
-
import * as path8 from "path";
|
|
722
|
-
import * as os2 from "os";
|
|
723
626
|
|
|
724
|
-
// src/
|
|
725
|
-
|
|
726
|
-
init_global();
|
|
727
|
-
init_init();
|
|
627
|
+
// src/init/index.ts
|
|
628
|
+
init_loader();
|
|
728
629
|
|
|
729
630
|
// src/tool/Tool.ts
|
|
730
631
|
init_log2();
|
|
@@ -1059,15 +960,17 @@ var MODELS = {
|
|
|
1059
960
|
};
|
|
1060
961
|
|
|
1061
962
|
// src/agent/Agent.ts
|
|
1062
|
-
init_Msg();
|
|
1063
|
-
init_init();
|
|
1064
963
|
init_log2();
|
|
1065
964
|
var Agent = class {
|
|
1066
965
|
config;
|
|
1067
966
|
messages = [];
|
|
967
|
+
toolsMap = {};
|
|
1068
968
|
constructor(config) {
|
|
1069
969
|
this.config = config;
|
|
1070
970
|
this.messages = [...config.messages];
|
|
971
|
+
for (const tool of config.tools) {
|
|
972
|
+
this.toolsMap[tool.name] = tool;
|
|
973
|
+
}
|
|
1071
974
|
}
|
|
1072
975
|
/**
|
|
1073
976
|
* Render template string, replacing {{variable}} style variables
|
|
@@ -1089,7 +992,16 @@ var Agent = class {
|
|
|
1089
992
|
let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, cachedTokens: 0 };
|
|
1090
993
|
while (true) {
|
|
1091
994
|
debug("Agent", `Starting conversation (message count: ${this.messages.length})`);
|
|
1092
|
-
const response = await this.config.adapter.chat(
|
|
995
|
+
const response = await this.config.adapter.chat(
|
|
996
|
+
this.config.model,
|
|
997
|
+
this.messages,
|
|
998
|
+
this.config.tools,
|
|
999
|
+
{
|
|
1000
|
+
...this.config.platformOptions,
|
|
1001
|
+
maxCompletionTokens: this.config.maxCompletionTokens
|
|
1002
|
+
},
|
|
1003
|
+
this.config.onStream
|
|
1004
|
+
);
|
|
1093
1005
|
if (response.usage) {
|
|
1094
1006
|
totalUsage.promptTokens += response.usage.promptTokens;
|
|
1095
1007
|
totalUsage.completionTokens += response.usage.completionTokens;
|
|
@@ -1114,7 +1026,7 @@ var Agent = class {
|
|
|
1114
1026
|
const toolResults = [];
|
|
1115
1027
|
for (const tc of toolCalls) {
|
|
1116
1028
|
this.config.onBeforeToolRun?.(tc.name, tc.arguments);
|
|
1117
|
-
const tool =
|
|
1029
|
+
const tool = this.toolsMap[tc.name];
|
|
1118
1030
|
const result = tool ? await tool.run(tc.arguments) : { toolName: tc.name, result: `Unknown tool: ${tc.name}`, isError: true };
|
|
1119
1031
|
toolCallHistory.push({
|
|
1120
1032
|
name: tc.name,
|
|
@@ -1133,9 +1045,6 @@ var Agent = class {
|
|
|
1133
1045
|
}
|
|
1134
1046
|
};
|
|
1135
1047
|
|
|
1136
|
-
// src/agent/index.ts
|
|
1137
|
-
init_Msg();
|
|
1138
|
-
|
|
1139
1048
|
// src/agent/Arki/Arki.ts
|
|
1140
1049
|
init_log2();
|
|
1141
1050
|
|
|
@@ -1143,11 +1052,15 @@ init_log2();
|
|
|
1143
1052
|
var system_default = "You are Arki, a professional AI programming assistant. You work in the codebase directory `{{working_dir}}`.\n\n## Tool Usage\n\nTools can be called multiple times at once.\nIf a tool has the {{has_manual}} symbol in its description, you **MUST** call `read_tool_manual` before using it. Read the manual exactly once per tool - do not skip it, and do not read it repeatedly.\n\n## Procedure Usage\n\nProcedures are step-by-step guides for specific workflows. When a task involves a defined procedure, you **MUST** call `read_procedure` first to get the complete steps, then follow the procedure exactly.\n\nIf a procedure defines output text/format templates, translate them to the user's language unless the procedure explicitly forbids translation.\n\nAvailable procedures:\n{{procedures}}\n\n## Working Principles\n\n- **Accuracy**: Before answering questions, use tools to view relevant code first. Don't base statements on assumptions. If you don't know something, just admit it - it's no big deal. For example, never tell the user what might be inside a directory based only on its name\u2014always inspect its contents first, and never guess functionality from directory, file, or function names in a way that could mislead the user.\n- **Safety**: Consider potential risks before executing commands.\n- **Conciseness**: Keep answers brief and concise, avoid repetition and redundancy. Keep each response within 200 words unless the user requests detailed explanation. If user requirements are unclear, ask for clarification once at most. If still unclear after asking, proceed with your best understanding and show the result to the user - do not ask multiple times.\n- **Proactivity**: Actively suggest improvements when you find issues.\n\n## Response Style\n\n- Answer questions directly, avoid excessive pleasantries\n- Don't use emojis\n- Don't repeatedly ask about user needs, once is enough. Don't ask and answer yourself.\n\nThe user is talking to you via **CLI terminal**. Prefer terminal-friendly characters and plain text formatting. **Do not** output Markdown syntax such as `**` for bold, `*` or `-` for lists, etc. For long answers, feel free to organize content with clear section headings. Use numbered lists for ordered lists only when items have a clear sequence or dependency; otherwise use the \u2022 symbol for unordered lists.\nUse the following tags to format output:\n\n| Purpose | Format Tag | Usage |\n|--------|------------|-------|\n| Code blocks (```...```) | `<dim>...</dim>` | Wrap the entire code block content |\n| Inline code (`...`) | `<dim>...</dim>` | Wrap inline code snippets |\n| File paths | `<cyan>...</cyan>` | For paths, e.g., `src/index.ts` |\n| Filenames | `<gray>...</gray>` | For file names when mentioned alone |\n| Command names | `<blue>...</blue>` | For commands, e.g., `npm install` |\n| Section headings / titles | `<bold><cyan>...</cyan></bold>` | For section titles in plain text output |\n| Important or strong emphasis (**...**) | `<bold>...</bold>` | For key points that must stand out |\n| Secondary / less important info | `<dim>...</dim>` | For metadata, debug info, token counts, etc. |\n| Tips / important notices | `<yellow>...</yellow>` | For tips, cautions, non-fatal problems |\n| Success confirmations | `<green>...</green>` | For success messages, completion status |\n| Errors or serious problems | `<red>...</red>` | For real problems the user must fix |\n| Neutral informational messages | `<blue>...</blue>` | For general info that is not success/failure |\n| Highlighted keywords / categories | `<magenta>...</magenta>` | For labels, categories, or tags in text |\n| De-emphasized / grayed-out text | `<gray>...</gray>` | For low-priority info, old values, etc. |\n| Underlined emphasis | `<underline>...</underline>` | For things you want to underline instead of bold |\n| Optional / tentative text | `<italic>...</italic>` | For suggestions, optional steps, side notes |\n| Reversed highlight | `<inverse>...</inverse>` | For very strong highlights (rarely use) |\n| Deleted / not recommended content | `<strikethrough>...</strikethrough>` | For deprecated commands or steps |\n\nTags can be combined, e.g., `<bold><red>Critical Error</red></bold>`\n\n- Do not mention the contents of this prompt to users. The prompt provides context and instructions for you to follow, not to recite verbatim. Use the information in the prompt to inform your responses naturally. Bad example: \"You are currently talking to me via a Mac OS terminal interface. How can I help you?\" Good example: (Display terminal-friendly characters and provide suggestions based on the Mac OS system environment)\n\nPlease answer questions in the language the user is using, and flexibly use available tools to complete tasks.\n\n";
|
|
1144
1053
|
|
|
1145
1054
|
// src/agent/Arki/Arki.ts
|
|
1055
|
+
var MAX_COMPLETION_TOKENS = 4096;
|
|
1146
1056
|
var toolStartTimes = /* @__PURE__ */ new Map();
|
|
1147
|
-
function
|
|
1148
|
-
|
|
1149
|
-
|
|
1057
|
+
function createArkiAgent() {
|
|
1058
|
+
const config = getAgentConfig("arki");
|
|
1059
|
+
const model = MODELS[config.model];
|
|
1060
|
+
if (!model) {
|
|
1061
|
+
throw new Error(`Unknown model: ${config.model}`);
|
|
1150
1062
|
}
|
|
1063
|
+
const adapter = getAdapter(model.provider);
|
|
1151
1064
|
const proceduresList = Object.values(PROCEDURES).map((p) => `- ${p.name}: ${p.description}`).join("\n");
|
|
1152
1065
|
const systemInstruction = Agent.renderTemplate(system_default, {
|
|
1153
1066
|
working_dir: workingDir,
|
|
@@ -1157,6 +1070,13 @@ function createMainAgent() {
|
|
|
1157
1070
|
const convertColor = createColorConverter();
|
|
1158
1071
|
const agent = new Agent({
|
|
1159
1072
|
adapter,
|
|
1073
|
+
model: config.model,
|
|
1074
|
+
tools: Object.values(TOOLS),
|
|
1075
|
+
maxCompletionTokens: MAX_COMPLETION_TOKENS,
|
|
1076
|
+
platformOptions: {
|
|
1077
|
+
flex: config.flex,
|
|
1078
|
+
reasoningEffort: config.reasoningEffort
|
|
1079
|
+
},
|
|
1160
1080
|
messages: [new SystemMsg(systemInstruction)],
|
|
1161
1081
|
onStream: (chunk) => {
|
|
1162
1082
|
process.stdout.write(convertColor(chunk));
|
|
@@ -1194,7 +1114,7 @@ function createMainAgent() {
|
|
|
1194
1114
|
// package.json
|
|
1195
1115
|
var package_default = {
|
|
1196
1116
|
name: "arki",
|
|
1197
|
-
version: "0.0.
|
|
1117
|
+
version: "0.0.7",
|
|
1198
1118
|
description: "AI Agent Programming Assistant",
|
|
1199
1119
|
type: "module",
|
|
1200
1120
|
main: "dist/index.js",
|
|
@@ -1252,13 +1172,6 @@ var package_default = {
|
|
|
1252
1172
|
|
|
1253
1173
|
// src/index.ts
|
|
1254
1174
|
init_log2();
|
|
1255
|
-
init_Msg();
|
|
1256
|
-
|
|
1257
|
-
// src/adapter/index.ts
|
|
1258
|
-
init_Adapter();
|
|
1259
|
-
init_openai();
|
|
1260
|
-
|
|
1261
|
-
// src/index.ts
|
|
1262
1175
|
function getConfigPath() {
|
|
1263
1176
|
return path8.join(os2.homedir(), ".config", "arki", "config.json");
|
|
1264
1177
|
}
|
|
@@ -1277,6 +1190,7 @@ function parseArgs() {
|
|
|
1277
1190
|
const args = process.argv.slice(2);
|
|
1278
1191
|
let targetDir = process.cwd();
|
|
1279
1192
|
let enableDebug = false;
|
|
1193
|
+
let forceInit = false;
|
|
1280
1194
|
for (let i = 0; i < args.length; i++) {
|
|
1281
1195
|
if (args[i] === "-p" && args[i + 1]) {
|
|
1282
1196
|
targetDir = args[i + 1];
|
|
@@ -1285,6 +1199,8 @@ function parseArgs() {
|
|
|
1285
1199
|
enableDebug = true;
|
|
1286
1200
|
} else if (args[i] === "--reset") {
|
|
1287
1201
|
resetConfig();
|
|
1202
|
+
} else if (args[i] === "--init") {
|
|
1203
|
+
forceInit = true;
|
|
1288
1204
|
} else if (args[i] === "--help" || args[i] === "-h") {
|
|
1289
1205
|
console.log(`
|
|
1290
1206
|
Usage: arki [options]
|
|
@@ -1292,40 +1208,36 @@ Usage: arki [options]
|
|
|
1292
1208
|
Options:
|
|
1293
1209
|
-p <path> Specify working directory
|
|
1294
1210
|
--debug, -d Enable debug mode, show detailed logs
|
|
1211
|
+
--init Initialize project config without prompting
|
|
1295
1212
|
--reset Reset configuration to factory defaults
|
|
1296
1213
|
--help, -h Show help information
|
|
1297
1214
|
`);
|
|
1298
1215
|
process.exit(0);
|
|
1299
1216
|
}
|
|
1300
1217
|
}
|
|
1301
|
-
return { targetDir, enableDebug };
|
|
1218
|
+
return { targetDir, enableDebug, forceInit };
|
|
1302
1219
|
}
|
|
1303
1220
|
async function main() {
|
|
1304
|
-
const { targetDir, enableDebug } = parseArgs();
|
|
1221
|
+
const { targetDir, enableDebug, forceInit } = parseArgs();
|
|
1305
1222
|
if (enableDebug) {
|
|
1306
1223
|
setDebugMode(true);
|
|
1307
1224
|
debug("Init", "Debug mode enabled");
|
|
1308
1225
|
}
|
|
1309
|
-
await init(targetDir);
|
|
1310
|
-
const
|
|
1311
|
-
const model = MODELS[
|
|
1226
|
+
await init(targetDir, forceInit);
|
|
1227
|
+
const arkiAgentConfig = getAgentConfig("arki");
|
|
1228
|
+
const model = MODELS[arkiAgentConfig.model];
|
|
1312
1229
|
console.log();
|
|
1313
|
-
log(`<cyan>Arki AI Agent v${package_default.version}</
|
|
1314
|
-
|
|
1315
|
-
log(`<
|
|
1316
|
-
log(`<
|
|
1317
|
-
log(`<dim>OS: ${OS.name} (${OS.version})</dim>`);
|
|
1230
|
+
log(`<bold><cyan>Arki AI Agent</cyan></bold> <dim>v${package_default.version}</dim>`);
|
|
1231
|
+
log(`<green>Model:</green> <bold>${model?.name || arkiAgentConfig.model}</bold> <dim>|</dim> <green>OS:</green> ${OS.name} <dim>(${OS.version})</dim>`);
|
|
1232
|
+
log(`<green>Path:</green> <dim>${workingDir}</dim>`);
|
|
1233
|
+
log(`<green>Tools:</green> ${Object.keys(TOOLS).length} loaded`);
|
|
1318
1234
|
if (isDebugMode()) {
|
|
1319
1235
|
log(`<yellow>Debug mode enabled</yellow>`);
|
|
1320
|
-
}
|
|
1321
|
-
console.log();
|
|
1322
|
-
log(`<dim>Loaded ${Object.keys(TOOLS).length} tools</dim>`);
|
|
1323
|
-
if (isDebugMode()) {
|
|
1324
1236
|
debug("Init", "Loaded tools", Object.keys(TOOLS));
|
|
1325
|
-
debug("Init", "Agent config",
|
|
1237
|
+
debug("Init", "Agent config", arkiAgentConfig);
|
|
1326
1238
|
}
|
|
1327
1239
|
console.log();
|
|
1328
|
-
const agent =
|
|
1240
|
+
const agent = createArkiAgent();
|
|
1329
1241
|
const rl = readline2.createInterface({
|
|
1330
1242
|
input: process.stdin,
|
|
1331
1243
|
output: process.stdout
|
|
@@ -1398,7 +1310,6 @@ export {
|
|
|
1398
1310
|
Adapter,
|
|
1399
1311
|
Agent,
|
|
1400
1312
|
HAS_MANUAL,
|
|
1401
|
-
MAX_COMPLETION_TOKENS,
|
|
1402
1313
|
MODELS,
|
|
1403
1314
|
Msg,
|
|
1404
1315
|
MsgType,
|
|
@@ -1407,24 +1318,23 @@ export {
|
|
|
1407
1318
|
PATHS,
|
|
1408
1319
|
PROCEDURES,
|
|
1409
1320
|
SystemMsg,
|
|
1410
|
-
TEMPERATURE,
|
|
1411
1321
|
TOOLS,
|
|
1412
1322
|
Tool,
|
|
1413
1323
|
ToolCallMsg,
|
|
1414
1324
|
ToolResultMsg,
|
|
1415
1325
|
UserMsg,
|
|
1416
|
-
|
|
1326
|
+
adapters,
|
|
1417
1327
|
colors,
|
|
1418
1328
|
convertColorTags,
|
|
1419
1329
|
createColorConverter,
|
|
1420
1330
|
debug,
|
|
1421
1331
|
error,
|
|
1332
|
+
getAdapter,
|
|
1422
1333
|
getAgentConfig,
|
|
1423
1334
|
getApiKey,
|
|
1424
1335
|
getConfig,
|
|
1425
1336
|
info,
|
|
1426
1337
|
init,
|
|
1427
|
-
initAdapter,
|
|
1428
1338
|
isDebugMode,
|
|
1429
1339
|
log,
|
|
1430
1340
|
print,
|