arki 0.0.5 → 0.0.6
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 +19 -3
- package/dist/config/.arki/config.json +3 -0
- package/dist/config/.arki/state.json +4 -0
- package/dist/index.d.ts +56 -32
- package/dist/index.js +683 -332
- package/package.json +1 -1
- /package/dist/config/{config.json → arki/config.json} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,191 +1,267 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
2
11
|
|
|
3
|
-
// src/
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import * as path5 from "path";
|
|
7
|
-
import * as os2 from "os";
|
|
8
|
-
|
|
9
|
-
// src/config/config.ts
|
|
10
|
-
import * as fs from "fs/promises";
|
|
11
|
-
import * as path from "path";
|
|
12
|
-
import * as os from "os";
|
|
12
|
+
// src/fs/paths.ts
|
|
13
|
+
import os from "os";
|
|
14
|
+
import path from "path";
|
|
13
15
|
import { fileURLToPath } from "url";
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
+
function getOSName() {
|
|
17
|
+
const platform = os.platform();
|
|
18
|
+
switch (platform) {
|
|
19
|
+
case "win32":
|
|
20
|
+
return "windows";
|
|
21
|
+
case "darwin":
|
|
22
|
+
return "mac";
|
|
23
|
+
case "linux":
|
|
24
|
+
return "linux";
|
|
25
|
+
default:
|
|
26
|
+
return "other";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function setWorkingDir(dir) {
|
|
30
|
+
workingDir = dir;
|
|
16
31
|
}
|
|
17
|
-
function
|
|
32
|
+
function getGlobalConfigDir() {
|
|
33
|
+
if (OS.name === "windows") {
|
|
34
|
+
return path.join(
|
|
35
|
+
process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"),
|
|
36
|
+
"arki"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return path.join(os.homedir(), ".config", "arki");
|
|
40
|
+
}
|
|
41
|
+
function getPackageDir(relativePath) {
|
|
18
42
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
-
return path.join(__dirname, "
|
|
43
|
+
return path.join(__dirname, "..", relativePath);
|
|
20
44
|
}
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
this.loadEnvApiKeys();
|
|
43
|
-
this.loaded = true;
|
|
44
|
-
return this.config;
|
|
45
|
+
var OS, workingDir, PATHS;
|
|
46
|
+
var init_paths = __esm({
|
|
47
|
+
"src/fs/paths.ts"() {
|
|
48
|
+
"use strict";
|
|
49
|
+
OS = {
|
|
50
|
+
name: getOSName(),
|
|
51
|
+
version: os.release()
|
|
52
|
+
};
|
|
53
|
+
workingDir = process.cwd();
|
|
54
|
+
PATHS = {
|
|
55
|
+
/** Global config directory (~/.config/arki or %APPDATA%\arki) */
|
|
56
|
+
globalConfig: getGlobalConfigDir(),
|
|
57
|
+
/** Project config directory (.arki/) - returns path based on current workingDir */
|
|
58
|
+
get projectConfig() {
|
|
59
|
+
return path.join(workingDir, ".arki");
|
|
60
|
+
},
|
|
61
|
+
/** Package's global config template directory */
|
|
62
|
+
globalTemplate: getPackageDir("config/arki"),
|
|
63
|
+
/** Package's project config template directory */
|
|
64
|
+
projectTemplate: getPackageDir("config/.arki")
|
|
65
|
+
};
|
|
45
66
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
if (process.env.ANTHROPIC_API_KEY && configToSave.apiKeys.anthropic === process.env.ANTHROPIC_API_KEY) {
|
|
58
|
-
delete configToSave.apiKeys.anthropic;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
await fs.writeFile(configPath, JSON.stringify(configToSave, null, 2), "utf-8");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// src/fs/file.ts
|
|
70
|
+
import * as fs from "fs/promises";
|
|
71
|
+
async function fileExists(filePath) {
|
|
72
|
+
try {
|
|
73
|
+
const stat3 = await fs.stat(filePath);
|
|
74
|
+
return stat3.isFile();
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
62
77
|
}
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
}
|
|
79
|
+
async function readJsonFile(filePath) {
|
|
80
|
+
try {
|
|
81
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
82
|
+
return JSON.parse(content);
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
65
85
|
}
|
|
66
|
-
|
|
67
|
-
|
|
86
|
+
}
|
|
87
|
+
async function writeJsonFile(filePath, data) {
|
|
88
|
+
await fs.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
89
|
+
}
|
|
90
|
+
async function readFile2(filePath) {
|
|
91
|
+
try {
|
|
92
|
+
return await fs.readFile(filePath, "utf-8");
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
68
95
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
96
|
+
}
|
|
97
|
+
async function writeFile2(filePath, content) {
|
|
98
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
99
|
+
}
|
|
100
|
+
var init_file = __esm({
|
|
101
|
+
"src/fs/file.ts"() {
|
|
102
|
+
"use strict";
|
|
75
103
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (!this.config.apiKeys.google) {
|
|
92
|
-
this.config.apiKeys.google = process.env.GOOGLE_API_KEY;
|
|
93
|
-
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// src/fs/dir.ts
|
|
107
|
+
import * as fs2 from "fs/promises";
|
|
108
|
+
import * as path2 from "path";
|
|
109
|
+
async function copyDir(src, dest) {
|
|
110
|
+
await fs2.mkdir(dest, { recursive: true });
|
|
111
|
+
const entries = await fs2.readdir(src, { withFileTypes: true });
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
const srcPath = path2.join(src, entry.name);
|
|
114
|
+
const destPath = path2.join(dest, entry.name);
|
|
115
|
+
if (entry.isDirectory()) {
|
|
116
|
+
await copyDir(srcPath, destPath);
|
|
117
|
+
} else {
|
|
118
|
+
await fs2.copyFile(srcPath, destPath);
|
|
94
119
|
}
|
|
95
120
|
}
|
|
96
|
-
}
|
|
97
|
-
|
|
121
|
+
}
|
|
122
|
+
async function dirExists(dirPath) {
|
|
123
|
+
try {
|
|
124
|
+
const stat3 = await fs2.stat(dirPath);
|
|
125
|
+
return stat3.isDirectory();
|
|
126
|
+
} catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function mkdir2(dirPath) {
|
|
131
|
+
await fs2.mkdir(dirPath, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
var init_dir = __esm({
|
|
134
|
+
"src/fs/dir.ts"() {
|
|
135
|
+
"use strict";
|
|
136
|
+
}
|
|
137
|
+
});
|
|
98
138
|
|
|
99
|
-
// src/
|
|
100
|
-
|
|
139
|
+
// src/fs/index.ts
|
|
140
|
+
var fs_exports = {};
|
|
141
|
+
__export(fs_exports, {
|
|
142
|
+
OS: () => OS,
|
|
143
|
+
PATHS: () => PATHS,
|
|
144
|
+
copyDir: () => copyDir,
|
|
145
|
+
dirExists: () => dirExists,
|
|
146
|
+
fileExists: () => fileExists,
|
|
147
|
+
mkdir: () => mkdir2,
|
|
148
|
+
readFile: () => readFile2,
|
|
149
|
+
readJsonFile: () => readJsonFile,
|
|
150
|
+
setWorkingDir: () => setWorkingDir,
|
|
151
|
+
workingDir: () => workingDir,
|
|
152
|
+
writeFile: () => writeFile2,
|
|
153
|
+
writeJsonFile: () => writeJsonFile
|
|
154
|
+
});
|
|
155
|
+
var init_fs = __esm({
|
|
156
|
+
"src/fs/index.ts"() {
|
|
157
|
+
"use strict";
|
|
158
|
+
init_paths();
|
|
159
|
+
init_file();
|
|
160
|
+
init_dir();
|
|
161
|
+
}
|
|
162
|
+
});
|
|
101
163
|
|
|
102
164
|
// src/adapter/Adapter.ts
|
|
103
|
-
var TEMPERATURE
|
|
104
|
-
var
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
+
};
|
|
123
191
|
}
|
|
124
|
-
};
|
|
192
|
+
});
|
|
125
193
|
|
|
126
194
|
// src/agent/Msg.ts
|
|
127
|
-
var MsgType
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
+
};
|
|
179
253
|
}
|
|
180
|
-
};
|
|
254
|
+
});
|
|
181
255
|
|
|
182
256
|
// src/log/log.ts
|
|
183
257
|
function getTimestamp() {
|
|
184
258
|
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
185
259
|
}
|
|
260
|
+
function print(message) {
|
|
261
|
+
console.log(convertColorTags(message));
|
|
262
|
+
}
|
|
186
263
|
function log(message) {
|
|
187
|
-
|
|
188
|
-
console.log(convertColorTags(`${ts} ${message}`));
|
|
264
|
+
print(`<gray>[${getTimestamp()}]</gray> ${message}`);
|
|
189
265
|
}
|
|
190
266
|
function info(message) {
|
|
191
267
|
log(`<blue>[INFO]</blue> ${message}`);
|
|
@@ -199,9 +275,14 @@ function warn(message) {
|
|
|
199
275
|
function error(message) {
|
|
200
276
|
log(`<red>[ERROR]</red> ${message}`);
|
|
201
277
|
}
|
|
278
|
+
var init_log = __esm({
|
|
279
|
+
"src/log/log.ts"() {
|
|
280
|
+
"use strict";
|
|
281
|
+
init_log2();
|
|
282
|
+
}
|
|
283
|
+
});
|
|
202
284
|
|
|
203
285
|
// src/log/debug.ts
|
|
204
|
-
var _debugMode = false;
|
|
205
286
|
function isDebugMode() {
|
|
206
287
|
return _debugMode;
|
|
207
288
|
}
|
|
@@ -219,29 +300,19 @@ function debug(category, message, data) {
|
|
|
219
300
|
const dataStr = data !== void 0 ? ` <dim>${formatData(data)}</dim>` : "";
|
|
220
301
|
log(`<magenta>[${category}]</magenta> <cyan>${message}</cyan>${dataStr}`);
|
|
221
302
|
}
|
|
303
|
+
var _debugMode;
|
|
304
|
+
var init_debug = __esm({
|
|
305
|
+
"src/log/debug.ts"() {
|
|
306
|
+
"use strict";
|
|
307
|
+
init_log();
|
|
308
|
+
_debugMode = false;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
222
311
|
|
|
223
312
|
// src/log/index.ts
|
|
224
|
-
var colors2 = {
|
|
225
|
-
reset: "\x1B[0m",
|
|
226
|
-
bold: "\x1B[1m",
|
|
227
|
-
dim: "\x1B[2m",
|
|
228
|
-
italic: "\x1B[3m",
|
|
229
|
-
underline: "\x1B[4m",
|
|
230
|
-
inverse: "\x1B[7m",
|
|
231
|
-
strikethrough: "\x1B[9m",
|
|
232
|
-
red: "\x1B[31m",
|
|
233
|
-
green: "\x1B[32m",
|
|
234
|
-
yellow: "\x1B[33m",
|
|
235
|
-
blue: "\x1B[34m",
|
|
236
|
-
magenta: "\x1B[35m",
|
|
237
|
-
cyan: "\x1B[36m",
|
|
238
|
-
gray: "\x1B[90m"
|
|
239
|
-
};
|
|
240
|
-
var tagNames = Object.keys(colors2).filter((k) => k !== "reset").join("|");
|
|
241
|
-
var tagRegex = new RegExp(`<(\\/?)(${tagNames})>`, "gi");
|
|
242
313
|
function convertColorTags(str) {
|
|
243
314
|
return str.replace(tagRegex, (_, closing, tag) => {
|
|
244
|
-
return closing ?
|
|
315
|
+
return closing ? colors.reset : colors[tag.toLowerCase()] || "";
|
|
245
316
|
});
|
|
246
317
|
}
|
|
247
318
|
function createColorConverter() {
|
|
@@ -264,147 +335,399 @@ function createColorConverter() {
|
|
|
264
335
|
return out;
|
|
265
336
|
};
|
|
266
337
|
}
|
|
338
|
+
var colors, tagNames, tagRegex;
|
|
339
|
+
var init_log2 = __esm({
|
|
340
|
+
"src/log/index.ts"() {
|
|
341
|
+
"use strict";
|
|
342
|
+
init_debug();
|
|
343
|
+
init_log();
|
|
344
|
+
colors = {
|
|
345
|
+
reset: "\x1B[0m",
|
|
346
|
+
bold: "\x1B[1m",
|
|
347
|
+
dim: "\x1B[2m",
|
|
348
|
+
italic: "\x1B[3m",
|
|
349
|
+
underline: "\x1B[4m",
|
|
350
|
+
inverse: "\x1B[7m",
|
|
351
|
+
strikethrough: "\x1B[9m",
|
|
352
|
+
red: "\x1B[31m",
|
|
353
|
+
green: "\x1B[32m",
|
|
354
|
+
yellow: "\x1B[33m",
|
|
355
|
+
blue: "\x1B[34m",
|
|
356
|
+
magenta: "\x1B[35m",
|
|
357
|
+
cyan: "\x1B[36m",
|
|
358
|
+
gray: "\x1B[90m"
|
|
359
|
+
};
|
|
360
|
+
tagNames = Object.keys(colors).filter((k) => k !== "reset").join("|");
|
|
361
|
+
tagRegex = new RegExp(`<(\\/?)(${tagNames})>`, "gi");
|
|
362
|
+
}
|
|
363
|
+
});
|
|
267
364
|
|
|
268
365
|
// src/adapter/openai.ts
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
result.push({ role: msg.type, content: msg.content });
|
|
284
|
-
} else if (msg.type === "ai" /* AI */) {
|
|
285
|
-
result.push({ role: "assistant", content: msg.content });
|
|
286
|
-
} else if (msg.type === "tool_call" /* ToolCall */) {
|
|
287
|
-
const toolCallMsg = msg;
|
|
288
|
-
pendingIds = toolCallMsg.toolCalls.map((_, i) => `call_${msg.timestamp}_${i}`);
|
|
289
|
-
result.push({
|
|
290
|
-
role: "assistant",
|
|
291
|
-
content: msg.content || null,
|
|
292
|
-
tool_calls: toolCallMsg.toolCalls.map((tc, i) => ({
|
|
293
|
-
id: pendingIds[i],
|
|
294
|
-
type: "function",
|
|
295
|
-
function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
|
|
296
|
-
}))
|
|
297
|
-
});
|
|
298
|
-
} else if (msg.type === "tool_result" /* ToolResult */) {
|
|
299
|
-
const toolResultMsg = msg;
|
|
300
|
-
for (const tr of toolResultMsg.toolResults) {
|
|
301
|
-
result.push({
|
|
302
|
-
role: "tool",
|
|
303
|
-
tool_call_id: pendingIds.shift() || `call_${msg.timestamp}`,
|
|
304
|
-
content: tr.isError ? `Error: ${tr.result}` : tr.result
|
|
305
|
-
});
|
|
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.");
|
|
306
380
|
}
|
|
381
|
+
this.client = new OpenAI({ apiKey: this.apiKey });
|
|
307
382
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
+
}
|
|
321
413
|
}
|
|
414
|
+
return result;
|
|
322
415
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
stream_options: { include_usage: true },
|
|
337
|
-
service_tier: this.flex ? "flex" : void 0,
|
|
338
|
-
reasoning_effort: this.reasoningEffort
|
|
339
|
-
};
|
|
340
|
-
const stream = await this.client.chat.completions.create(requestParams);
|
|
341
|
-
let text = "";
|
|
342
|
-
const toolCalls = /* @__PURE__ */ new Map();
|
|
343
|
-
let usage;
|
|
344
|
-
for await (const chunk of stream) {
|
|
345
|
-
const delta = chunk.choices[0]?.delta;
|
|
346
|
-
if (delta?.content) {
|
|
347
|
-
text += delta.content;
|
|
348
|
-
onChunk?.(delta.content);
|
|
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
|
+
}));
|
|
349
429
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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;
|
|
356
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 };
|
|
357
483
|
}
|
|
358
|
-
if (chunk.usage) usage = chunk.usage;
|
|
359
|
-
}
|
|
360
|
-
const elapsed = Date.now() - startTime;
|
|
361
|
-
const cachedTokens = usage?.prompt_tokens_details?.cached_tokens;
|
|
362
|
-
const usageData = usage && {
|
|
363
|
-
promptTokens: usage.prompt_tokens,
|
|
364
|
-
completionTokens: usage.completion_tokens,
|
|
365
|
-
totalTokens: usage.total_tokens,
|
|
366
|
-
cachedTokens
|
|
367
484
|
};
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// src/init/loader.ts
|
|
489
|
+
var loader_exports = {};
|
|
490
|
+
__export(loader_exports, {
|
|
491
|
+
getAgentConfig: () => getAgentConfig,
|
|
492
|
+
getApiKey: () => getApiKey,
|
|
493
|
+
getConfig: () => getConfig,
|
|
494
|
+
loadConfigs: () => loadConfigs,
|
|
495
|
+
saveConfig: () => saveConfig
|
|
496
|
+
});
|
|
497
|
+
import * as path3 from "path";
|
|
498
|
+
function deepMerge(base, override) {
|
|
499
|
+
const result = {
|
|
500
|
+
...base,
|
|
501
|
+
agents: { ...base.agents }
|
|
502
|
+
};
|
|
503
|
+
if (override.apiKeys) {
|
|
504
|
+
result.apiKeys = { ...base.apiKeys, ...override.apiKeys };
|
|
505
|
+
}
|
|
506
|
+
if (override.agents) {
|
|
507
|
+
for (const key of Object.keys(override.agents)) {
|
|
508
|
+
const overrideAgent = override.agents[key];
|
|
509
|
+
if (overrideAgent) {
|
|
510
|
+
result.agents[key] = { ...result.agents[key], ...overrideAgent };
|
|
511
|
+
}
|
|
375
512
|
}
|
|
376
|
-
debug("API", `Completed (${elapsed}ms, tokens: ${usage?.total_tokens || "N/A"})`);
|
|
377
|
-
return { message: new AIMsg(text), hasToolCalls: false, usage: usageData };
|
|
378
513
|
}
|
|
379
|
-
|
|
514
|
+
return result;
|
|
515
|
+
}
|
|
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
|
+
async function loadConfigs() {
|
|
537
|
+
if (mergedConfig) {
|
|
538
|
+
return mergedConfig;
|
|
539
|
+
}
|
|
540
|
+
const globalConfigPath = path3.join(PATHS.globalConfig, "config.json");
|
|
541
|
+
const globalConfig = await readJsonFile(globalConfigPath);
|
|
542
|
+
if (!globalConfig) {
|
|
543
|
+
throw new Error(`Failed to load global config: ${globalConfigPath}`);
|
|
544
|
+
}
|
|
545
|
+
const projectConfigPath = path3.join(PATHS.projectConfig, "config.json");
|
|
546
|
+
const projectConfig = await readJsonFile(projectConfigPath);
|
|
547
|
+
if (projectConfig) {
|
|
548
|
+
mergedConfig = deepMerge(globalConfig, projectConfig);
|
|
549
|
+
} else {
|
|
550
|
+
mergedConfig = globalConfig;
|
|
551
|
+
}
|
|
552
|
+
loadEnvApiKeys(mergedConfig);
|
|
553
|
+
return mergedConfig;
|
|
554
|
+
}
|
|
555
|
+
function getConfig() {
|
|
556
|
+
if (!mergedConfig) {
|
|
557
|
+
throw new Error("Config not loaded yet. Please call loadConfigs() first.");
|
|
558
|
+
}
|
|
559
|
+
return mergedConfig;
|
|
560
|
+
}
|
|
561
|
+
function getApiKey(provider) {
|
|
562
|
+
return getConfig().apiKeys?.[provider];
|
|
563
|
+
}
|
|
564
|
+
function getAgentConfig(agentType) {
|
|
565
|
+
const agentConfig = getConfig().agents[agentType];
|
|
566
|
+
if (!agentConfig) {
|
|
567
|
+
throw new Error(`Agent config not found: ${agentType}`);
|
|
568
|
+
}
|
|
569
|
+
return agentConfig;
|
|
570
|
+
}
|
|
571
|
+
async function saveConfig() {
|
|
572
|
+
const config = getConfig();
|
|
573
|
+
const configPath = path3.join(PATHS.globalConfig, "config.json");
|
|
574
|
+
const configToSave = { ...config };
|
|
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);
|
|
588
|
+
}
|
|
589
|
+
var mergedConfig;
|
|
590
|
+
var init_loader = __esm({
|
|
591
|
+
"src/init/loader.ts"() {
|
|
592
|
+
"use strict";
|
|
593
|
+
init_fs();
|
|
594
|
+
mergedConfig = null;
|
|
595
|
+
}
|
|
596
|
+
});
|
|
380
597
|
|
|
381
|
-
// src/
|
|
382
|
-
var
|
|
383
|
-
|
|
384
|
-
|
|
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
|
+
// src/init/project.ts
|
|
621
|
+
var project_exports = {};
|
|
622
|
+
__export(project_exports, {
|
|
623
|
+
initProject: () => initProject
|
|
624
|
+
});
|
|
625
|
+
import * as path4 from "path";
|
|
626
|
+
import * as readline from "readline";
|
|
627
|
+
async function askQuestion(question) {
|
|
628
|
+
const rl = readline.createInterface({
|
|
629
|
+
input: process.stdin,
|
|
630
|
+
output: process.stdout
|
|
631
|
+
});
|
|
632
|
+
return new Promise((resolve4) => {
|
|
633
|
+
rl.question(`${question} (y/n): `, (answer) => {
|
|
634
|
+
rl.close();
|
|
635
|
+
resolve4(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
636
|
+
});
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
async function initProject() {
|
|
640
|
+
const projectConfigDir = PATHS.projectConfig;
|
|
641
|
+
if (await dirExists(projectConfigDir)) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
print(`
|
|
645
|
+
<dim>Project directory: ${workingDir}</dim>`);
|
|
646
|
+
const trusted = await askQuestion("Do you trust this project and want to initialize arki config?");
|
|
647
|
+
if (!trusted) {
|
|
648
|
+
print("<yellow>Initialization cancelled.</yellow>");
|
|
649
|
+
process.exit(0);
|
|
650
|
+
}
|
|
651
|
+
await copyDir(PATHS.projectTemplate, projectConfigDir);
|
|
652
|
+
const statePath = path4.join(projectConfigDir, "state.json");
|
|
653
|
+
const state = {
|
|
654
|
+
initialized: true,
|
|
655
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
656
|
+
};
|
|
657
|
+
await writeJsonFile(statePath, state);
|
|
658
|
+
print("<green>Project configuration initialized.</green>");
|
|
659
|
+
}
|
|
660
|
+
var init_project = __esm({
|
|
661
|
+
"src/init/project.ts"() {
|
|
662
|
+
"use strict";
|
|
663
|
+
init_fs();
|
|
664
|
+
init_log2();
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
// src/init/global.ts
|
|
669
|
+
async function initGlobalConfig() {
|
|
670
|
+
const globalConfigDir = PATHS.globalConfig;
|
|
671
|
+
if (await dirExists(globalConfigDir)) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
await copyDir(PATHS.globalTemplate, globalConfigDir);
|
|
385
675
|
}
|
|
386
|
-
var TOOLS = {};
|
|
387
|
-
var PROCEDURES = {};
|
|
388
|
-
var adapter = null;
|
|
389
676
|
function initAdapter() {
|
|
390
677
|
if (adapter) {
|
|
391
678
|
return;
|
|
392
679
|
}
|
|
393
|
-
|
|
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
|
+
}
|
|
690
|
+
async function init(cwd) {
|
|
691
|
+
const { setWorkingDir: setWorkingDir2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
692
|
+
setWorkingDir2(cwd || process.cwd());
|
|
693
|
+
await initGlobalConfig();
|
|
694
|
+
const { initProject: initProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
|
|
695
|
+
await initProject2();
|
|
696
|
+
const { loadConfigs: loadConfigs2, getAgentConfig: getAgentConfig2, getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
697
|
+
await loadConfigs2();
|
|
698
|
+
const mainAgentConfig = getAgentConfig2("main");
|
|
394
699
|
adapter = new OpenAIAdapter({
|
|
395
|
-
apiKey:
|
|
700
|
+
apiKey: getApiKey2("openai") || "",
|
|
396
701
|
model: mainAgentConfig.model,
|
|
397
702
|
flex: mainAgentConfig.flex,
|
|
398
703
|
tools: Object.values(TOOLS)
|
|
399
704
|
});
|
|
400
705
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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
|
+
|
|
724
|
+
// src/global.ts
|
|
725
|
+
init_fs();
|
|
726
|
+
init_global();
|
|
727
|
+
init_init();
|
|
406
728
|
|
|
407
729
|
// src/tool/Tool.ts
|
|
730
|
+
init_log2();
|
|
408
731
|
var HAS_MANUAL = "\u{1F4D8}";
|
|
409
732
|
var Tool = class _Tool {
|
|
410
733
|
name;
|
|
@@ -413,12 +736,12 @@ var Tool = class _Tool {
|
|
|
413
736
|
required;
|
|
414
737
|
manual;
|
|
415
738
|
_execute;
|
|
416
|
-
constructor(
|
|
417
|
-
this.name =
|
|
418
|
-
this.parameters =
|
|
419
|
-
this.required =
|
|
420
|
-
this._execute =
|
|
421
|
-
const { description, manual } = _Tool.parseManual(
|
|
739
|
+
constructor(config) {
|
|
740
|
+
this.name = config.name;
|
|
741
|
+
this.parameters = config.parameters;
|
|
742
|
+
this.required = config.required;
|
|
743
|
+
this._execute = config.execute;
|
|
744
|
+
const { description, manual } = _Tool.parseManual(config.manualContent);
|
|
422
745
|
this.description = description;
|
|
423
746
|
this.manual = manual;
|
|
424
747
|
}
|
|
@@ -461,8 +784,8 @@ var Tool = class _Tool {
|
|
|
461
784
|
};
|
|
462
785
|
|
|
463
786
|
// src/tool/read_file/index.ts
|
|
464
|
-
import * as
|
|
465
|
-
import * as
|
|
787
|
+
import * as fs3 from "fs/promises";
|
|
788
|
+
import * as path5 from "path";
|
|
466
789
|
|
|
467
790
|
// src/tool/read_file/manual.md
|
|
468
791
|
var manual_default = "read_file: Read the content of a specified file\n";
|
|
@@ -478,8 +801,8 @@ TOOLS["read_file"] = new Tool({
|
|
|
478
801
|
execute: async (args) => {
|
|
479
802
|
const filePath = args.path;
|
|
480
803
|
try {
|
|
481
|
-
const fullPath =
|
|
482
|
-
return await
|
|
804
|
+
const fullPath = path5.resolve(workingDir, filePath);
|
|
805
|
+
return await fs3.readFile(fullPath, "utf-8");
|
|
483
806
|
} catch (error2) {
|
|
484
807
|
return {
|
|
485
808
|
content: `Failed to read file: ${error2 instanceof Error ? error2.message : String(error2)}`,
|
|
@@ -490,8 +813,8 @@ TOOLS["read_file"] = new Tool({
|
|
|
490
813
|
});
|
|
491
814
|
|
|
492
815
|
// src/tool/write_file/index.ts
|
|
493
|
-
import * as
|
|
494
|
-
import * as
|
|
816
|
+
import * as fs4 from "fs/promises";
|
|
817
|
+
import * as path6 from "path";
|
|
495
818
|
|
|
496
819
|
// src/tool/write_file/manual.md
|
|
497
820
|
var manual_default2 = "write_file: Write content to a specified file, create the file if it doesn't exist\n";
|
|
@@ -509,9 +832,9 @@ TOOLS["write_file"] = new Tool({
|
|
|
509
832
|
const filePath = args.path;
|
|
510
833
|
const content = args.content;
|
|
511
834
|
try {
|
|
512
|
-
const fullPath =
|
|
513
|
-
await
|
|
514
|
-
await
|
|
835
|
+
const fullPath = path6.resolve(workingDir, filePath);
|
|
836
|
+
await fs4.mkdir(path6.dirname(fullPath), { recursive: true });
|
|
837
|
+
await fs4.writeFile(fullPath, content, "utf-8");
|
|
515
838
|
return `File written successfully: ${filePath}`;
|
|
516
839
|
} catch (error2) {
|
|
517
840
|
return {
|
|
@@ -523,8 +846,8 @@ TOOLS["write_file"] = new Tool({
|
|
|
523
846
|
});
|
|
524
847
|
|
|
525
848
|
// src/tool/list_directory/index.ts
|
|
526
|
-
import * as
|
|
527
|
-
import * as
|
|
849
|
+
import * as fs5 from "fs/promises";
|
|
850
|
+
import * as path7 from "path";
|
|
528
851
|
|
|
529
852
|
// src/tool/list_directory/manual.md
|
|
530
853
|
var manual_default3 = "list_directory: List files and subdirectories in a specified directory\n";
|
|
@@ -540,8 +863,8 @@ TOOLS["list_directory"] = new Tool({
|
|
|
540
863
|
execute: async (args) => {
|
|
541
864
|
const dirPath = args.path || ".";
|
|
542
865
|
try {
|
|
543
|
-
const fullPath =
|
|
544
|
-
const entries = await
|
|
866
|
+
const fullPath = path7.resolve(workingDir, dirPath);
|
|
867
|
+
const entries = await fs5.readdir(fullPath, { withFileTypes: true });
|
|
545
868
|
const result = entries.map((entry) => {
|
|
546
869
|
const type = entry.isDirectory() ? "[DIR]" : "[FILE]";
|
|
547
870
|
return `${type} ${entry.name}`;
|
|
@@ -659,9 +982,9 @@ var Procedure = class _Procedure {
|
|
|
659
982
|
name;
|
|
660
983
|
description;
|
|
661
984
|
manual;
|
|
662
|
-
constructor(
|
|
663
|
-
this.name =
|
|
664
|
-
const { description, manual } = _Procedure.parseManual(
|
|
985
|
+
constructor(config) {
|
|
986
|
+
this.name = config.name;
|
|
987
|
+
const { description, manual } = _Procedure.parseManual(config.procedureContent);
|
|
665
988
|
this.description = description;
|
|
666
989
|
this.manual = manual;
|
|
667
990
|
}
|
|
@@ -692,6 +1015,9 @@ PROCEDURES["understand_project"] = new Procedure({
|
|
|
692
1015
|
procedureContent: procedure_default
|
|
693
1016
|
});
|
|
694
1017
|
|
|
1018
|
+
// src/index.ts
|
|
1019
|
+
init_log2();
|
|
1020
|
+
|
|
695
1021
|
// src/model/models.ts
|
|
696
1022
|
var MODELS = {
|
|
697
1023
|
"gpt-5.2": {
|
|
@@ -733,12 +1059,15 @@ var MODELS = {
|
|
|
733
1059
|
};
|
|
734
1060
|
|
|
735
1061
|
// src/agent/Agent.ts
|
|
1062
|
+
init_Msg();
|
|
1063
|
+
init_init();
|
|
1064
|
+
init_log2();
|
|
736
1065
|
var Agent = class {
|
|
737
1066
|
config;
|
|
738
1067
|
messages = [];
|
|
739
|
-
constructor(
|
|
740
|
-
this.config =
|
|
741
|
-
this.messages = [...
|
|
1068
|
+
constructor(config) {
|
|
1069
|
+
this.config = config;
|
|
1070
|
+
this.messages = [...config.messages];
|
|
742
1071
|
}
|
|
743
1072
|
/**
|
|
744
1073
|
* Render template string, replacing {{variable}} style variables
|
|
@@ -804,6 +1133,12 @@ var Agent = class {
|
|
|
804
1133
|
}
|
|
805
1134
|
};
|
|
806
1135
|
|
|
1136
|
+
// src/agent/index.ts
|
|
1137
|
+
init_Msg();
|
|
1138
|
+
|
|
1139
|
+
// src/agent/Arki/Arki.ts
|
|
1140
|
+
init_log2();
|
|
1141
|
+
|
|
807
1142
|
// src/agent/Arki/system.md
|
|
808
1143
|
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";
|
|
809
1144
|
|
|
@@ -859,7 +1194,7 @@ function createMainAgent() {
|
|
|
859
1194
|
// package.json
|
|
860
1195
|
var package_default = {
|
|
861
1196
|
name: "arki",
|
|
862
|
-
version: "0.0.
|
|
1197
|
+
version: "0.0.6",
|
|
863
1198
|
description: "AI Agent Programming Assistant",
|
|
864
1199
|
type: "module",
|
|
865
1200
|
main: "dist/index.js",
|
|
@@ -916,13 +1251,21 @@ var package_default = {
|
|
|
916
1251
|
};
|
|
917
1252
|
|
|
918
1253
|
// src/index.ts
|
|
919
|
-
|
|
920
|
-
|
|
1254
|
+
init_log2();
|
|
1255
|
+
init_Msg();
|
|
1256
|
+
|
|
1257
|
+
// src/adapter/index.ts
|
|
1258
|
+
init_Adapter();
|
|
1259
|
+
init_openai();
|
|
1260
|
+
|
|
1261
|
+
// src/index.ts
|
|
1262
|
+
function getConfigPath() {
|
|
1263
|
+
return path8.join(os2.homedir(), ".config", "arki", "config.json");
|
|
921
1264
|
}
|
|
922
1265
|
function resetConfig() {
|
|
923
|
-
const configPath =
|
|
924
|
-
if (
|
|
925
|
-
|
|
1266
|
+
const configPath = getConfigPath();
|
|
1267
|
+
if (fs6.existsSync(configPath)) {
|
|
1268
|
+
fs6.unlinkSync(configPath);
|
|
926
1269
|
console.log(`Configuration file deleted: ${configPath}`);
|
|
927
1270
|
console.log("Default configuration will be used on next startup.");
|
|
928
1271
|
} else {
|
|
@@ -964,13 +1307,14 @@ async function main() {
|
|
|
964
1307
|
debug("Init", "Debug mode enabled");
|
|
965
1308
|
}
|
|
966
1309
|
await init(targetDir);
|
|
967
|
-
const mainAgentConfig =
|
|
1310
|
+
const mainAgentConfig = getAgentConfig("main");
|
|
968
1311
|
const model = MODELS[mainAgentConfig.model];
|
|
969
1312
|
console.log();
|
|
970
1313
|
log(`<cyan>Arki AI Agent v${package_default.version}</cyan>`);
|
|
971
1314
|
console.log();
|
|
972
1315
|
log(`<dim>Model: ${mainAgentConfig.model}${model ? ` (${model.name})` : ""}</dim>`);
|
|
973
1316
|
log(`<dim>Working directory: ${workingDir}</dim>`);
|
|
1317
|
+
log(`<dim>OS: ${OS.name} (${OS.version})</dim>`);
|
|
974
1318
|
if (isDebugMode()) {
|
|
975
1319
|
log(`<yellow>Debug mode enabled</yellow>`);
|
|
976
1320
|
}
|
|
@@ -982,7 +1326,7 @@ async function main() {
|
|
|
982
1326
|
}
|
|
983
1327
|
console.log();
|
|
984
1328
|
const agent = createMainAgent();
|
|
985
|
-
const rl =
|
|
1329
|
+
const rl = readline2.createInterface({
|
|
986
1330
|
input: process.stdin,
|
|
987
1331
|
output: process.stdout
|
|
988
1332
|
});
|
|
@@ -1058,7 +1402,9 @@ export {
|
|
|
1058
1402
|
MODELS,
|
|
1059
1403
|
Msg,
|
|
1060
1404
|
MsgType,
|
|
1405
|
+
OS,
|
|
1061
1406
|
OpenAIAdapter,
|
|
1407
|
+
PATHS,
|
|
1062
1408
|
PROCEDURES,
|
|
1063
1409
|
SystemMsg,
|
|
1064
1410
|
TEMPERATURE,
|
|
@@ -1068,16 +1414,21 @@ export {
|
|
|
1068
1414
|
ToolResultMsg,
|
|
1069
1415
|
UserMsg,
|
|
1070
1416
|
adapter,
|
|
1071
|
-
|
|
1072
|
-
config,
|
|
1417
|
+
colors,
|
|
1073
1418
|
convertColorTags,
|
|
1074
1419
|
createColorConverter,
|
|
1075
1420
|
debug,
|
|
1076
1421
|
error,
|
|
1422
|
+
getAgentConfig,
|
|
1423
|
+
getApiKey,
|
|
1424
|
+
getConfig,
|
|
1077
1425
|
info,
|
|
1078
1426
|
init,
|
|
1427
|
+
initAdapter,
|
|
1079
1428
|
isDebugMode,
|
|
1080
1429
|
log,
|
|
1430
|
+
print,
|
|
1431
|
+
saveConfig,
|
|
1081
1432
|
setDebugMode,
|
|
1082
1433
|
setWorkingDir,
|
|
1083
1434
|
success,
|