arki 0.0.4 → 0.0.5
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/dist/index.d.ts +45 -8
- package/dist/index.js +177 -114
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -113,6 +113,28 @@ declare class Tool {
|
|
|
113
113
|
run(args: Record<string, unknown>): Promise<ToolResult>;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Procedure class - step-by-step guide for specific workflows
|
|
118
|
+
*/
|
|
119
|
+
declare class Procedure {
|
|
120
|
+
readonly name: string;
|
|
121
|
+
readonly description: string;
|
|
122
|
+
readonly manual: string;
|
|
123
|
+
constructor(config: {
|
|
124
|
+
name: string;
|
|
125
|
+
procedureContent: string;
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* Parse procedure.md content
|
|
129
|
+
* First line format: "procedure_name: description", extract description
|
|
130
|
+
* Remaining content is the procedure steps
|
|
131
|
+
*/
|
|
132
|
+
static parseManual(content: string): {
|
|
133
|
+
description: string;
|
|
134
|
+
manual: string;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
116
138
|
/**
|
|
117
139
|
* Fixed parameters
|
|
118
140
|
*/
|
|
@@ -221,6 +243,8 @@ declare let workingDir: string;
|
|
|
221
243
|
declare function setWorkingDir(dir: string): void;
|
|
222
244
|
/** Global tool registry */
|
|
223
245
|
declare const TOOLS: Record<string, Tool>;
|
|
246
|
+
/** Global procedure registry */
|
|
247
|
+
declare const PROCEDURES: Record<string, Procedure>;
|
|
224
248
|
/** Global Adapter instance */
|
|
225
249
|
declare let adapter: Adapter | null;
|
|
226
250
|
/** Initialize global state */
|
|
@@ -228,29 +252,31 @@ declare function init(cwd?: string): Promise<void>;
|
|
|
228
252
|
|
|
229
253
|
/**
|
|
230
254
|
* Debug logging module
|
|
255
|
+
* All debug output is single-line for log-friendly format
|
|
231
256
|
*/
|
|
232
257
|
/** Get debug mode status */
|
|
233
258
|
declare function isDebugMode(): boolean;
|
|
234
259
|
/** Set debug mode */
|
|
235
260
|
declare function setDebugMode(enabled: boolean): void;
|
|
236
261
|
/**
|
|
237
|
-
* Debug log function
|
|
262
|
+
* Debug log function - single line output with timestamp
|
|
238
263
|
* @param category Log category (e.g., 'API', 'Agent', 'Tool')
|
|
239
264
|
* @param message Log message
|
|
240
|
-
* @param data Optional additional data
|
|
265
|
+
* @param data Optional additional data (will be formatted to single line)
|
|
241
266
|
*/
|
|
242
267
|
declare function debug(category: string, message: string, data?: unknown): void;
|
|
243
268
|
|
|
244
269
|
/**
|
|
245
270
|
* General logging module
|
|
271
|
+
* All log output is single-line with timestamp prefix
|
|
272
|
+
* Supports XML-style color tags: <red>text</red>, <bold>text</bold>, etc.
|
|
246
273
|
*/
|
|
247
|
-
|
|
248
274
|
/**
|
|
249
|
-
*
|
|
250
|
-
* @param color
|
|
251
|
-
* @
|
|
275
|
+
* Log output with timestamp and XML color tag support
|
|
276
|
+
* @param message Message string with optional XML color tags
|
|
277
|
+
* @example log('<yellow>[TOOL]</yellow> read_file <dim>{"path":"test.txt"}</dim>')
|
|
252
278
|
*/
|
|
253
|
-
declare function log(
|
|
279
|
+
declare function log(message: string): void;
|
|
254
280
|
/**
|
|
255
281
|
* Info log
|
|
256
282
|
*/
|
|
@@ -271,6 +297,7 @@ declare function error(message: string): void;
|
|
|
271
297
|
/**
|
|
272
298
|
* Logging module
|
|
273
299
|
* Provides debug mode and logging functionality
|
|
300
|
+
* Supports XML-style color tags: <red>text</red>, <bold>text</bold>, etc.
|
|
274
301
|
*/
|
|
275
302
|
/**
|
|
276
303
|
* Terminal colors and style definitions
|
|
@@ -293,6 +320,16 @@ declare const colors: {
|
|
|
293
320
|
};
|
|
294
321
|
/** Color name type */
|
|
295
322
|
type ColorName = keyof typeof colors;
|
|
323
|
+
/**
|
|
324
|
+
* Convert XML-style color tags to ANSI escape sequences
|
|
325
|
+
* Example: "<red>error</red>" -> "\x1b[31merror\x1b[0m"
|
|
326
|
+
*/
|
|
327
|
+
declare function convertColorTags(str: string): string;
|
|
328
|
+
/**
|
|
329
|
+
* Create a buffered streaming color converter
|
|
330
|
+
* Used for streaming output where tags may span multiple chunks
|
|
331
|
+
*/
|
|
332
|
+
declare function createColorConverter(): (chunk: string) => string;
|
|
296
333
|
|
|
297
334
|
declare class OpenAIAdapter extends Adapter {
|
|
298
335
|
private client;
|
|
@@ -367,4 +404,4 @@ interface Model {
|
|
|
367
404
|
readonly capabilities: ModelCapabilities;
|
|
368
405
|
}
|
|
369
406
|
|
|
370
|
-
export { AIMsg, Adapter, type AdapterResponse, Agent, type AgentResponse, type ColorName, HAS_MANUAL, MAX_COMPLETION_TOKENS, MODELS, type Model, type ModelCapabilities, type ModelProvider, Msg, MsgType, OpenAIAdapter, type ReasoningEffort$1 as ReasoningEffort, SystemMsg, TEMPERATURE, TOOLS, Tool, type ToolCall, ToolCallMsg, type ToolResult, ToolResultMsg, UserMsg, adapter, colors, config, debug, error, info, init, isDebugMode, log, setDebugMode, setWorkingDir, success, warn, workingDir };
|
|
407
|
+
export { AIMsg, Adapter, type AdapterResponse, Agent, type AgentResponse, type ColorName, HAS_MANUAL, MAX_COMPLETION_TOKENS, MODELS, type Model, type ModelCapabilities, type ModelProvider, Msg, MsgType, OpenAIAdapter, PROCEDURES, type ReasoningEffort$1 as ReasoningEffort, SystemMsg, TEMPERATURE, TOOLS, Tool, type ToolCall, ToolCallMsg, type ToolResult, ToolResultMsg, UserMsg, adapter, colors, config, convertColorTags, createColorConverter, debug, error, info, init, isDebugMode, log, setDebugMode, setWorkingDir, success, warn, workingDir };
|
package/dist/index.js
CHANGED
|
@@ -179,6 +179,27 @@ var ToolResultMsg = class _ToolResultMsg extends Msg {
|
|
|
179
179
|
}
|
|
180
180
|
};
|
|
181
181
|
|
|
182
|
+
// src/log/log.ts
|
|
183
|
+
function getTimestamp() {
|
|
184
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
185
|
+
}
|
|
186
|
+
function log(message) {
|
|
187
|
+
const ts = `<gray>[${getTimestamp()}]</gray>`;
|
|
188
|
+
console.log(convertColorTags(`${ts} ${message}`));
|
|
189
|
+
}
|
|
190
|
+
function info(message) {
|
|
191
|
+
log(`<blue>[INFO]</blue> ${message}`);
|
|
192
|
+
}
|
|
193
|
+
function success(message) {
|
|
194
|
+
log(`<green>[OK]</green> ${message}`);
|
|
195
|
+
}
|
|
196
|
+
function warn(message) {
|
|
197
|
+
log(`<yellow>[WARN]</yellow> ${message}`);
|
|
198
|
+
}
|
|
199
|
+
function error(message) {
|
|
200
|
+
log(`<red>[ERROR]</red> ${message}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
182
203
|
// src/log/debug.ts
|
|
183
204
|
var _debugMode = false;
|
|
184
205
|
function isDebugMode() {
|
|
@@ -187,43 +208,20 @@ function isDebugMode() {
|
|
|
187
208
|
function setDebugMode(enabled) {
|
|
188
209
|
_debugMode = enabled;
|
|
189
210
|
}
|
|
211
|
+
function formatData(data, maxLen = 100) {
|
|
212
|
+
if (data === void 0) return "";
|
|
213
|
+
const str = typeof data === "string" ? data : JSON.stringify(data);
|
|
214
|
+
const singleLine = str.replace(/\s+/g, " ").trim();
|
|
215
|
+
return singleLine.length > maxLen ? singleLine.slice(0, maxLen) + "..." : singleLine;
|
|
216
|
+
}
|
|
190
217
|
function debug(category, message, data) {
|
|
191
218
|
if (!_debugMode) return;
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
console.log(`${prefix} ${colors.cyan}${message}${colors.reset}`);
|
|
195
|
-
if (data !== void 0) {
|
|
196
|
-
const dataStr = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
197
|
-
const lines = dataStr.split("\n");
|
|
198
|
-
const maxLines = 20;
|
|
199
|
-
const truncated = lines.length > maxLines;
|
|
200
|
-
const displayLines = truncated ? lines.slice(-maxLines) : lines;
|
|
201
|
-
if (truncated) {
|
|
202
|
-
console.log(colors.dim + ` ... (${lines.length - maxLines} earlier lines)` + colors.reset);
|
|
203
|
-
}
|
|
204
|
-
console.log(colors.dim + displayLines.map((l) => ` ${l}`).join("\n") + colors.reset);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// src/log/log.ts
|
|
209
|
-
function log(color, ...args) {
|
|
210
|
-
console.log(colors[color], ...args, colors.reset);
|
|
211
|
-
}
|
|
212
|
-
function info(message) {
|
|
213
|
-
console.log(`${colors.blue}\u2139${colors.reset} ${message}`);
|
|
214
|
-
}
|
|
215
|
-
function success(message) {
|
|
216
|
-
console.log(`${colors.green}\u2714${colors.reset} ${message}`);
|
|
217
|
-
}
|
|
218
|
-
function warn(message) {
|
|
219
|
-
console.log(`${colors.yellow}\u26A0${colors.reset} ${message}`);
|
|
220
|
-
}
|
|
221
|
-
function error(message) {
|
|
222
|
-
console.log(`${colors.red}\u2716${colors.reset} ${message}`);
|
|
219
|
+
const dataStr = data !== void 0 ? ` <dim>${formatData(data)}</dim>` : "";
|
|
220
|
+
log(`<magenta>[${category}]</magenta> <cyan>${message}</cyan>${dataStr}`);
|
|
223
221
|
}
|
|
224
222
|
|
|
225
223
|
// src/log/index.ts
|
|
226
|
-
var
|
|
224
|
+
var colors2 = {
|
|
227
225
|
reset: "\x1B[0m",
|
|
228
226
|
bold: "\x1B[1m",
|
|
229
227
|
dim: "\x1B[2m",
|
|
@@ -239,6 +237,33 @@ var colors = {
|
|
|
239
237
|
cyan: "\x1B[36m",
|
|
240
238
|
gray: "\x1B[90m"
|
|
241
239
|
};
|
|
240
|
+
var tagNames = Object.keys(colors2).filter((k) => k !== "reset").join("|");
|
|
241
|
+
var tagRegex = new RegExp(`<(\\/?)(${tagNames})>`, "gi");
|
|
242
|
+
function convertColorTags(str) {
|
|
243
|
+
return str.replace(tagRegex, (_, closing, tag) => {
|
|
244
|
+
return closing ? colors2.reset : colors2[tag.toLowerCase()] || "";
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function createColorConverter() {
|
|
248
|
+
let buffer = "";
|
|
249
|
+
return (chunk) => {
|
|
250
|
+
buffer += chunk;
|
|
251
|
+
const lastOpen = buffer.lastIndexOf("<");
|
|
252
|
+
if (lastOpen === -1) {
|
|
253
|
+
const out2 = convertColorTags(buffer);
|
|
254
|
+
buffer = "";
|
|
255
|
+
return out2;
|
|
256
|
+
}
|
|
257
|
+
if (buffer.indexOf(">", lastOpen) !== -1) {
|
|
258
|
+
const out2 = convertColorTags(buffer);
|
|
259
|
+
buffer = "";
|
|
260
|
+
return out2;
|
|
261
|
+
}
|
|
262
|
+
const out = convertColorTags(buffer.slice(0, lastOpen));
|
|
263
|
+
buffer = buffer.slice(lastOpen);
|
|
264
|
+
return out;
|
|
265
|
+
};
|
|
266
|
+
}
|
|
242
267
|
|
|
243
268
|
// src/adapter/openai.ts
|
|
244
269
|
var OpenAIAdapter = class extends Adapter {
|
|
@@ -300,7 +325,6 @@ var OpenAIAdapter = class extends Adapter {
|
|
|
300
325
|
async chat(messages, onChunk) {
|
|
301
326
|
debug("API", `Requesting OpenAI (model: ${this.model}, messages: ${messages.length})`);
|
|
302
327
|
const openaiMessages = this.toOpenAIMessages(messages);
|
|
303
|
-
debug("API", "Sent prompt:", openaiMessages);
|
|
304
328
|
const startTime = Date.now();
|
|
305
329
|
const requestParams = {
|
|
306
330
|
model: this.model,
|
|
@@ -360,6 +384,7 @@ function setWorkingDir(dir) {
|
|
|
360
384
|
workingDir = dir;
|
|
361
385
|
}
|
|
362
386
|
var TOOLS = {};
|
|
387
|
+
var PROCEDURES = {};
|
|
363
388
|
var adapter = null;
|
|
364
389
|
function initAdapter() {
|
|
365
390
|
if (adapter) {
|
|
@@ -421,21 +446,15 @@ var Tool = class _Tool {
|
|
|
421
446
|
* Execute tool (with error handling and logging)
|
|
422
447
|
*/
|
|
423
448
|
async run(args) {
|
|
424
|
-
debug("Tool", `Starting tool execution: ${this.name}`, args);
|
|
425
|
-
const startTime = Date.now();
|
|
426
449
|
try {
|
|
427
450
|
const result = await this._execute(args);
|
|
428
|
-
const elapsed = Date.now() - startTime;
|
|
429
451
|
if (typeof result === "string") {
|
|
430
|
-
debug("Tool", `Tool execution successful: ${this.name} (elapsed: ${elapsed}ms, result length: ${result.length})`);
|
|
431
452
|
return { toolName: this.name, result };
|
|
432
453
|
}
|
|
433
|
-
debug("Tool", `Tool execution completed: ${this.name} (elapsed: ${elapsed}ms, isError: ${result.isError || false})`);
|
|
434
454
|
return { toolName: this.name, result: result.content, isError: result.isError };
|
|
435
455
|
} catch (error2) {
|
|
436
|
-
const elapsed = Date.now() - startTime;
|
|
437
456
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
438
|
-
debug("Tool",
|
|
457
|
+
debug("Tool", `${this.name} error`, errorMsg);
|
|
439
458
|
return { toolName: this.name, result: `Error: ${errorMsg}`, isError: true };
|
|
440
459
|
}
|
|
441
460
|
}
|
|
@@ -603,6 +622,76 @@ ${foundTool.manual}`;
|
|
|
603
622
|
}
|
|
604
623
|
});
|
|
605
624
|
|
|
625
|
+
// src/tool/read_procedure/manual.md
|
|
626
|
+
var manual_default6 = "read_procedure: View detailed steps for a specified procedure\n";
|
|
627
|
+
|
|
628
|
+
// src/tool/read_procedure/index.ts
|
|
629
|
+
TOOLS["read_procedure"] = new Tool({
|
|
630
|
+
name: "read_procedure",
|
|
631
|
+
parameters: {
|
|
632
|
+
procedure_name: { type: "string", description: "Procedure name to view" }
|
|
633
|
+
},
|
|
634
|
+
required: ["procedure_name"],
|
|
635
|
+
manualContent: manual_default6,
|
|
636
|
+
execute: async (args) => {
|
|
637
|
+
const procedureName = args.procedure_name;
|
|
638
|
+
const procedure = PROCEDURES[procedureName];
|
|
639
|
+
if (!procedure) {
|
|
640
|
+
const available = Object.keys(PROCEDURES).join(", ");
|
|
641
|
+
return {
|
|
642
|
+
content: `Procedure not found: ${procedureName}
|
|
643
|
+
Available: ${available}`,
|
|
644
|
+
isError: true
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
return `# ${procedure.name}
|
|
648
|
+
|
|
649
|
+
${procedure.description}
|
|
650
|
+
|
|
651
|
+
## Steps
|
|
652
|
+
|
|
653
|
+
${procedure.manual}`;
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// src/procedure/Procedure.ts
|
|
658
|
+
var Procedure = class _Procedure {
|
|
659
|
+
name;
|
|
660
|
+
description;
|
|
661
|
+
manual;
|
|
662
|
+
constructor(config2) {
|
|
663
|
+
this.name = config2.name;
|
|
664
|
+
const { description, manual } = _Procedure.parseManual(config2.procedureContent);
|
|
665
|
+
this.description = description;
|
|
666
|
+
this.manual = manual;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Parse procedure.md content
|
|
670
|
+
* First line format: "procedure_name: description", extract description
|
|
671
|
+
* Remaining content is the procedure steps
|
|
672
|
+
*/
|
|
673
|
+
static parseManual(content) {
|
|
674
|
+
const lines = content.split("\n");
|
|
675
|
+
const firstLine = lines[0] || "";
|
|
676
|
+
let description = "";
|
|
677
|
+
const colonIndex = firstLine.indexOf(":");
|
|
678
|
+
if (colonIndex > 0) {
|
|
679
|
+
description = firstLine.slice(colonIndex + 1).trim();
|
|
680
|
+
}
|
|
681
|
+
const manual = lines.slice(1).join("\n").trim();
|
|
682
|
+
return { description, manual };
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
// src/procedure/understand_project/procedure.md
|
|
687
|
+
var procedure_default = "understand_project: Systematically explore and understand the current project structure\n\n1. Use `list_directory` on the root directory to get an overview\n - Identify key directories (src, lib, tests, docs, etc.)\n - Note configuration files (package.json, tsconfig.json, Cargo.toml, etc.)\n\n2. Use `read_file` on the main configuration file (package.json, Cargo.toml, pyproject.toml, etc.)\n - Project name and description\n - Dependencies and their purposes\n - Scripts/commands available\n - Entry points\n\n3. Use `read_file` on README.md if it exists\n - Project purpose and goals\n - Setup instructions\n - Usage examples\n\n4. Use `list_directory` on the main source directory (src/, lib/, app/, etc.)\n - Identify the entry point file (index.ts, main.ts, app.ts, etc.)\n - List subdirectories to understand module organization\n - Note any patterns (MVC, feature-based, etc.)\n\n5. Use `read_file` on 2-3 key source files to understand\n - Coding style and conventions\n - Main abstractions and patterns used\n - How modules interact with each other\n\n6. Output the final report in this format **in user's language**:\n\n---\n<bold><cyan>Project Overview</cyan></bold>\n\nName: [project name]\nType: [CLI tool / Web app / Library / API server / etc.]\nLanguage: [TypeScript / JavaScript / Python / etc.]\nPackage Manager: [npm / pnpm / yarn / pip / cargo / etc.]\n\n<bold><cyan>Project Structure</cyan></bold>\n\n[Brief description of directory structure and organization pattern]\n\n<bold><cyan>Key Components</cyan></bold>\n\n\u2022 [Component 1]: [brief description]\n\u2022 [Component 2]: [brief description]\n\u2022 [Component 3]: [brief description]\n...\n\n<bold><cyan>Entry Points</cyan></bold>\n\n\u2022 Main: [path to main entry]\n\u2022 CLI: [path to CLI entry if applicable]\n\u2022 Tests: [path to test entry if applicable]\n\n<bold><cyan>Dependencies</cyan></bold>\n\nCore:\n\u2022 [dep1]: [purpose]\n\u2022 [dep2]: [purpose]\n\nDev:\n\u2022 [dev-dep1]: [purpose]\n\u2022 [dev-dep2]: [purpose]\n\n<bold><cyan>Available Commands</cyan></bold>\n\n\u2022 [command1]: [description]\n\u2022 [command2]: [description]\n...\n\n<bold><cyan>Code Patterns</cyan></bold>\n\n\u2022 [Pattern 1 observed in the codebase]\n\u2022 [Pattern 2 observed in the codebase]\n...\n---\n";
|
|
688
|
+
|
|
689
|
+
// src/procedure/understand_project/index.ts
|
|
690
|
+
PROCEDURES["understand_project"] = new Procedure({
|
|
691
|
+
name: "understand_project",
|
|
692
|
+
procedureContent: procedure_default
|
|
693
|
+
});
|
|
694
|
+
|
|
606
695
|
// src/model/models.ts
|
|
607
696
|
var MODELS = {
|
|
608
697
|
"gpt-5.2": {
|
|
@@ -696,13 +785,8 @@ var Agent = class {
|
|
|
696
785
|
const toolResults = [];
|
|
697
786
|
for (const tc of toolCalls) {
|
|
698
787
|
this.config.onBeforeToolRun?.(tc.name, tc.arguments);
|
|
699
|
-
debug("Agent", `Executing tool: ${tc.name}`, tc.arguments);
|
|
700
788
|
const tool = TOOLS[tc.name];
|
|
701
789
|
const result = tool ? await tool.run(tc.arguments) : { toolName: tc.name, result: `Unknown tool: ${tc.name}`, isError: true };
|
|
702
|
-
debug("Agent", `Tool execution completed: ${tc.name}`, {
|
|
703
|
-
isError: result.isError,
|
|
704
|
-
contentLength: result.result.length
|
|
705
|
-
});
|
|
706
790
|
toolCallHistory.push({
|
|
707
791
|
name: tc.name,
|
|
708
792
|
arguments: tc.arguments,
|
|
@@ -720,46 +804,20 @@ var Agent = class {
|
|
|
720
804
|
}
|
|
721
805
|
};
|
|
722
806
|
|
|
723
|
-
// src/agent/Arki/colors.ts
|
|
724
|
-
var tagNames = Object.keys(colors).filter((k) => k !== "reset").join("|");
|
|
725
|
-
var tagRegex = new RegExp(`<(\\/?)(${tagNames})>`, "gi");
|
|
726
|
-
function convertColorTags(str) {
|
|
727
|
-
return str.replace(tagRegex, (_, closing, tag) => {
|
|
728
|
-
return closing ? colors.reset : colors[tag.toLowerCase()] || "";
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
function createColorConverter() {
|
|
732
|
-
let buffer = "";
|
|
733
|
-
return (chunk) => {
|
|
734
|
-
buffer += chunk;
|
|
735
|
-
const lastOpen = buffer.lastIndexOf("<");
|
|
736
|
-
if (lastOpen === -1) {
|
|
737
|
-
const out2 = convertColorTags(buffer);
|
|
738
|
-
buffer = "";
|
|
739
|
-
return out2;
|
|
740
|
-
}
|
|
741
|
-
if (buffer.indexOf(">", lastOpen) !== -1) {
|
|
742
|
-
const out2 = convertColorTags(buffer);
|
|
743
|
-
buffer = "";
|
|
744
|
-
return out2;
|
|
745
|
-
}
|
|
746
|
-
const out = convertColorTags(buffer.slice(0, lastOpen));
|
|
747
|
-
buffer = buffer.slice(lastOpen);
|
|
748
|
-
return out;
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
|
|
752
807
|
// src/agent/Arki/system.md
|
|
753
|
-
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## 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";
|
|
808
|
+
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";
|
|
754
809
|
|
|
755
810
|
// src/agent/Arki/Arki.ts
|
|
811
|
+
var toolStartTimes = /* @__PURE__ */ new Map();
|
|
756
812
|
function createMainAgent() {
|
|
757
813
|
if (!adapter) {
|
|
758
814
|
throw new Error("Adapter not initialized, please call init() first");
|
|
759
815
|
}
|
|
816
|
+
const proceduresList = Object.values(PROCEDURES).map((p) => `- ${p.name}: ${p.description}`).join("\n");
|
|
760
817
|
const systemInstruction = Agent.renderTemplate(system_default, {
|
|
761
818
|
working_dir: workingDir,
|
|
762
|
-
has_manual: HAS_MANUAL
|
|
819
|
+
has_manual: HAS_MANUAL,
|
|
820
|
+
procedures: proceduresList || "(none)"
|
|
763
821
|
});
|
|
764
822
|
const convertColor = createColorConverter();
|
|
765
823
|
const agent = new Agent({
|
|
@@ -768,27 +826,31 @@ function createMainAgent() {
|
|
|
768
826
|
onStream: (chunk) => {
|
|
769
827
|
process.stdout.write(convertColor(chunk));
|
|
770
828
|
},
|
|
771
|
-
onBeforeToolRun: (name
|
|
772
|
-
|
|
773
|
-
const argsPreview = argsStr.length > 60 ? argsStr.substring(0, 60) + "..." : argsStr;
|
|
774
|
-
if (isDebugMode()) {
|
|
775
|
-
console.log(`\x1B[33m\u{1F527} ${name}\x1B[0m \x1B[2m${argsPreview}\x1B[0m`);
|
|
776
|
-
} else {
|
|
777
|
-
process.stdout.write(`\x1B[33m\u{1F527} ${name}\x1B[0m \x1B[2m${argsPreview}\x1B[0m`);
|
|
778
|
-
}
|
|
829
|
+
onBeforeToolRun: (name) => {
|
|
830
|
+
toolStartTimes.set(name, Date.now());
|
|
779
831
|
},
|
|
780
832
|
onToolResult: (name, args, result) => {
|
|
833
|
+
const startTime = toolStartTimes.get(name) || Date.now();
|
|
834
|
+
const elapsed = Date.now() - startTime;
|
|
835
|
+
toolStartTimes.delete(name);
|
|
781
836
|
const argsStr = JSON.stringify(args);
|
|
782
837
|
const argsPreview = argsStr.length > 60 ? argsStr.substring(0, 60) + "..." : argsStr;
|
|
783
|
-
|
|
784
|
-
const firstLine = resultPreview.split("\n")[0];
|
|
838
|
+
let output = `<green>[TOOL]</green> ${name} <dim>${argsPreview} (${elapsed}ms)`;
|
|
785
839
|
if (isDebugMode()) {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
840
|
+
const lines = result.split("\n").filter((l) => l.trim());
|
|
841
|
+
let summary;
|
|
842
|
+
if (lines.length <= 3) {
|
|
843
|
+
summary = lines.join(", ");
|
|
844
|
+
if (summary.length > 60) summary = summary.substring(0, 60) + "...";
|
|
845
|
+
} else {
|
|
846
|
+
const preview = lines.slice(0, 3).join(", ");
|
|
847
|
+
summary = preview.length > 50 ? preview.substring(0, 50) + "..." : preview;
|
|
848
|
+
summary += ` (+${lines.length - 3} more)`;
|
|
849
|
+
}
|
|
850
|
+
output += ` -> ${summary}`;
|
|
790
851
|
}
|
|
791
|
-
|
|
852
|
+
output += "</dim>";
|
|
853
|
+
log(output);
|
|
792
854
|
}
|
|
793
855
|
});
|
|
794
856
|
return agent;
|
|
@@ -797,7 +859,7 @@ function createMainAgent() {
|
|
|
797
859
|
// package.json
|
|
798
860
|
var package_default = {
|
|
799
861
|
name: "arki",
|
|
800
|
-
version: "0.0.
|
|
862
|
+
version: "0.0.5",
|
|
801
863
|
description: "AI Agent Programming Assistant",
|
|
802
864
|
type: "module",
|
|
803
865
|
main: "dist/index.js",
|
|
@@ -905,15 +967,15 @@ async function main() {
|
|
|
905
967
|
const mainAgentConfig = config.getAgentConfig("main");
|
|
906
968
|
const model = MODELS[mainAgentConfig.model];
|
|
907
969
|
console.log();
|
|
908
|
-
log(
|
|
970
|
+
log(`<cyan>Arki AI Agent v${package_default.version}</cyan>`);
|
|
909
971
|
console.log();
|
|
910
|
-
log(
|
|
911
|
-
log(
|
|
972
|
+
log(`<dim>Model: ${mainAgentConfig.model}${model ? ` (${model.name})` : ""}</dim>`);
|
|
973
|
+
log(`<dim>Working directory: ${workingDir}</dim>`);
|
|
912
974
|
if (isDebugMode()) {
|
|
913
|
-
log(
|
|
975
|
+
log(`<yellow>Debug mode enabled</yellow>`);
|
|
914
976
|
}
|
|
915
977
|
console.log();
|
|
916
|
-
log(
|
|
978
|
+
log(`<dim>Loaded ${Object.keys(TOOLS).length} tools</dim>`);
|
|
917
979
|
if (isDebugMode()) {
|
|
918
980
|
debug("Init", "Loaded tools", Object.keys(TOOLS));
|
|
919
981
|
debug("Init", "Agent config", mainAgentConfig);
|
|
@@ -924,38 +986,39 @@ async function main() {
|
|
|
924
986
|
input: process.stdin,
|
|
925
987
|
output: process.stdout
|
|
926
988
|
});
|
|
927
|
-
log(
|
|
928
|
-
log(
|
|
989
|
+
log(`<blue>Enter your question and press Enter to send. Type /exit or /quit to exit.</blue>`);
|
|
990
|
+
log(`<blue>Type /clear to clear conversation history.</blue>`);
|
|
929
991
|
console.log();
|
|
992
|
+
const promptStr = convertColorTags("<green>> </green>");
|
|
930
993
|
const prompt = () => {
|
|
931
|
-
rl.question(
|
|
994
|
+
rl.question(promptStr, async (input) => {
|
|
932
995
|
const trimmed = input.trim();
|
|
933
996
|
if (trimmed === "/exit" || trimmed === "/quit") {
|
|
934
|
-
log(
|
|
997
|
+
log(`<cyan>Goodbye!</cyan>`);
|
|
935
998
|
rl.close();
|
|
936
999
|
process.exit(0);
|
|
937
1000
|
}
|
|
938
1001
|
if (trimmed === "/clear") {
|
|
939
1002
|
agent.reset();
|
|
940
|
-
log(
|
|
1003
|
+
log(`<yellow>Conversation history cleared</yellow>`);
|
|
941
1004
|
console.log();
|
|
942
1005
|
prompt();
|
|
943
1006
|
return;
|
|
944
1007
|
}
|
|
945
1008
|
if (trimmed === "/help") {
|
|
946
1009
|
console.log();
|
|
947
|
-
log(
|
|
948
|
-
log(
|
|
949
|
-
log(
|
|
950
|
-
log(
|
|
951
|
-
log(
|
|
1010
|
+
log(`<cyan>Available commands:</cyan>`);
|
|
1011
|
+
log(`<dim> /exit, /quit - Exit program</dim>`);
|
|
1012
|
+
log(`<dim> /clear - Clear conversation history</dim>`);
|
|
1013
|
+
log(`<dim> /debug - Toggle debug mode</dim>`);
|
|
1014
|
+
log(`<dim> /help - Show help</dim>`);
|
|
952
1015
|
console.log();
|
|
953
1016
|
prompt();
|
|
954
1017
|
return;
|
|
955
1018
|
}
|
|
956
1019
|
if (trimmed === "/debug") {
|
|
957
1020
|
setDebugMode(!isDebugMode());
|
|
958
|
-
log(
|
|
1021
|
+
log(`<yellow>Debug mode ${isDebugMode() ? "enabled" : "disabled"}</yellow>`);
|
|
959
1022
|
console.log();
|
|
960
1023
|
prompt();
|
|
961
1024
|
return;
|
|
@@ -970,14 +1033,11 @@ async function main() {
|
|
|
970
1033
|
console.log();
|
|
971
1034
|
if (result.usage) {
|
|
972
1035
|
const contextLimit = model?.capabilities.contextWindow || "N/A";
|
|
973
|
-
log(
|
|
974
|
-
"dim",
|
|
975
|
-
`[Tokens: ${result.usage.totalTokens} (prompt: ${result.usage.promptTokens}, cached: ${result.usage.cachedTokens || 0}, limit: ${contextLimit})]`
|
|
976
|
-
);
|
|
1036
|
+
log(`<dim>[Tokens: ${result.usage.totalTokens} (prompt: ${result.usage.promptTokens}, cached: ${result.usage.cachedTokens || 0}, limit: ${contextLimit})]</dim>`);
|
|
977
1037
|
}
|
|
978
1038
|
console.log();
|
|
979
1039
|
} catch (error2) {
|
|
980
|
-
log(
|
|
1040
|
+
log(`<red>Error: ${error2 instanceof Error ? error2.message : String(error2)}</red>`);
|
|
981
1041
|
console.log();
|
|
982
1042
|
}
|
|
983
1043
|
prompt();
|
|
@@ -999,6 +1059,7 @@ export {
|
|
|
999
1059
|
Msg,
|
|
1000
1060
|
MsgType,
|
|
1001
1061
|
OpenAIAdapter,
|
|
1062
|
+
PROCEDURES,
|
|
1002
1063
|
SystemMsg,
|
|
1003
1064
|
TEMPERATURE,
|
|
1004
1065
|
TOOLS,
|
|
@@ -1007,8 +1068,10 @@ export {
|
|
|
1007
1068
|
ToolResultMsg,
|
|
1008
1069
|
UserMsg,
|
|
1009
1070
|
adapter,
|
|
1010
|
-
colors,
|
|
1071
|
+
colors2 as colors,
|
|
1011
1072
|
config,
|
|
1073
|
+
convertColorTags,
|
|
1074
|
+
createColorConverter,
|
|
1012
1075
|
debug,
|
|
1013
1076
|
error,
|
|
1014
1077
|
info,
|