@pikaa-ai/pikaa 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/pikaa.js +1 -1
- package/dist/cli.js +85 -27
- package/dist/index.js +76 -18
- package/package.json +9 -9
package/bin/pikaa.js
CHANGED
|
@@ -31,7 +31,7 @@ const arch = process.arch;
|
|
|
31
31
|
let version = "";
|
|
32
32
|
let scope = "@pikaa-ai";
|
|
33
33
|
try {
|
|
34
|
-
const pkg = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8"));
|
|
34
|
+
const pkg = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8").replace(/^\uFEFF/, ""));
|
|
35
35
|
version = pkg.version || "";
|
|
36
36
|
if (pkg.name && pkg.name.startsWith("@")) {
|
|
37
37
|
scope = pkg.name.split("/")[0];
|
package/dist/cli.js
CHANGED
|
@@ -1171,7 +1171,7 @@ class ProjectAnalyzer {
|
|
|
1171
1171
|
const pkgPath = join5(this.cwd, "package.json");
|
|
1172
1172
|
if (existsSync6(pkgPath)) {
|
|
1173
1173
|
try {
|
|
1174
|
-
const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
|
|
1174
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
1175
1175
|
if (!description && pkg.description)
|
|
1176
1176
|
description = pkg.description;
|
|
1177
1177
|
const pm = packageManager || "npm";
|
|
@@ -1245,7 +1245,7 @@ class ProjectAnalyzer {
|
|
|
1245
1245
|
const tsconfigPath = join5(this.cwd, "tsconfig.json");
|
|
1246
1246
|
if (existsSync6(tsconfigPath)) {
|
|
1247
1247
|
try {
|
|
1248
|
-
const tsconfig = JSON.parse(readFileSync4(tsconfigPath, "utf8"));
|
|
1248
|
+
const tsconfig = JSON.parse(readFileSync4(tsconfigPath, "utf8").replace(/^\uFEFF/, ""));
|
|
1249
1249
|
if (tsconfig.compilerOptions?.strict) {
|
|
1250
1250
|
codeConventions.push("TypeScript strict mode enabled.");
|
|
1251
1251
|
}
|
|
@@ -1431,7 +1431,7 @@ class ProjectAnalyzer {
|
|
|
1431
1431
|
const pkgPath = join5(this.cwd, "package.json");
|
|
1432
1432
|
if (existsSync6(pkgPath)) {
|
|
1433
1433
|
try {
|
|
1434
|
-
const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
|
|
1434
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
1435
1435
|
if (pkg.name && pkg.name !== "frontend" && pkg.name !== "backend" && pkg.name !== "app") {
|
|
1436
1436
|
return pkg.name.startsWith("@") ? pkg.name.split("/")[1] || pkg.name : pkg.name;
|
|
1437
1437
|
}
|
|
@@ -1577,7 +1577,7 @@ class AutoVerifier {
|
|
|
1577
1577
|
const pkgPath = join6(this.cwd, "package.json");
|
|
1578
1578
|
if (existsSync7(pkgPath)) {
|
|
1579
1579
|
try {
|
|
1580
|
-
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
1580
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
1581
1581
|
const allDeps = { ...pkg.dependencies || {}, ...pkg.devDependencies || {} };
|
|
1582
1582
|
if (allDeps.vitest) {
|
|
1583
1583
|
return `npx vitest run ${quotedFiles}`;
|
|
@@ -1623,7 +1623,7 @@ class AutoVerifier {
|
|
|
1623
1623
|
const pkgPath = join6(this.cwd, "package.json");
|
|
1624
1624
|
if (existsSync7(pkgPath)) {
|
|
1625
1625
|
try {
|
|
1626
|
-
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
1626
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
1627
1627
|
if (pkg.scripts) {
|
|
1628
1628
|
const pm = existsSync7(join6(this.cwd, "bun.lockb")) || existsSync7(join6(this.cwd, "bun.lock")) ? "bun" : existsSync7(join6(this.cwd, "pnpm-lock.yaml")) ? "pnpm" : existsSync7(join6(this.cwd, "yarn.lock")) ? "yarn" : "npm";
|
|
1629
1629
|
const runCmd = pm === "bun" || pm === "pnpm" || pm === "yarn" ? `${pm} run` : "npm run";
|
|
@@ -1677,7 +1677,7 @@ class AutoVerifier {
|
|
|
1677
1677
|
const pkgPath = join6(this.cwd, "package.json");
|
|
1678
1678
|
if (existsSync7(pkgPath)) {
|
|
1679
1679
|
try {
|
|
1680
|
-
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
1680
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
1681
1681
|
if (pkg.scripts?.test) {
|
|
1682
1682
|
const pm = existsSync7(join6(this.cwd, "bun.lockb")) || existsSync7(join6(this.cwd, "bun.lock")) ? "bun" : "npm";
|
|
1683
1683
|
return pm === "bun" ? "bun test" : "npm test";
|
|
@@ -2343,14 +2343,33 @@ function parseShellCommand(commandLine) {
|
|
|
2343
2343
|
if (char === "$" && i + 1 < len && commandLine[i + 1] === "(") {
|
|
2344
2344
|
let depth = 1;
|
|
2345
2345
|
let endIdx = -1;
|
|
2346
|
+
let subInSingleQuote = false;
|
|
2347
|
+
let subInDoubleQuote = false;
|
|
2348
|
+
let subIsEscaped = false;
|
|
2346
2349
|
for (let j = i + 2;j < len; j++) {
|
|
2347
|
-
|
|
2348
|
-
|
|
2350
|
+
const subChar = commandLine[j];
|
|
2351
|
+
if (subIsEscaped) {
|
|
2352
|
+
subIsEscaped = false;
|
|
2349
2353
|
continue;
|
|
2350
2354
|
}
|
|
2351
|
-
if (
|
|
2355
|
+
if (subChar === "\\") {
|
|
2356
|
+
subIsEscaped = true;
|
|
2357
|
+
continue;
|
|
2358
|
+
}
|
|
2359
|
+
if (subChar === "'" && !subInDoubleQuote) {
|
|
2360
|
+
subInSingleQuote = !subInSingleQuote;
|
|
2361
|
+
continue;
|
|
2362
|
+
}
|
|
2363
|
+
if (subChar === '"' && !subInSingleQuote) {
|
|
2364
|
+
subInDoubleQuote = !subInDoubleQuote;
|
|
2365
|
+
continue;
|
|
2366
|
+
}
|
|
2367
|
+
if (subInSingleQuote || subInDoubleQuote) {
|
|
2368
|
+
continue;
|
|
2369
|
+
}
|
|
2370
|
+
if (subChar === "(")
|
|
2352
2371
|
depth++;
|
|
2353
|
-
else if (
|
|
2372
|
+
else if (subChar === ")") {
|
|
2354
2373
|
depth--;
|
|
2355
2374
|
if (depth === 0) {
|
|
2356
2375
|
endIdx = j;
|
|
@@ -3335,7 +3354,7 @@ class PrefixRulesStore {
|
|
|
3335
3354
|
return false;
|
|
3336
3355
|
const SHELL_OPERATORS = new Set([";", "&&", "||", "|", "&", ";;", "&|"]);
|
|
3337
3356
|
for (const token of cmdTokens) {
|
|
3338
|
-
if (SHELL_OPERATORS.has(token) || token.includes(";") || token.includes("&&") || token.includes("||")) {
|
|
3357
|
+
if (SHELL_OPERATORS.has(token) || token.includes(";") || token.includes("&&") || token.includes("||") || token.includes("|") || token.includes("&")) {
|
|
3339
3358
|
return false;
|
|
3340
3359
|
}
|
|
3341
3360
|
}
|
|
@@ -4784,7 +4803,30 @@ class AgentRoleRegistry {
|
|
|
4784
4803
|
name: "default",
|
|
4785
4804
|
description: "Generalist autonomous developer agent capable of coding, testing, and debugging.",
|
|
4786
4805
|
systemPrompt: "You are Groupy, an expert autonomous software engineer. Think carefully, use tools surgically, and verify every step.",
|
|
4787
|
-
nicknameCandidates: ["Pikaa", "Heca", "Bankli", "Moli"]
|
|
4806
|
+
nicknameCandidates: ["Pikaa", "Heca", "Bankli", "Moli"],
|
|
4807
|
+
allowedToolNames: [
|
|
4808
|
+
"read_file",
|
|
4809
|
+
"view_file",
|
|
4810
|
+
"write_file",
|
|
4811
|
+
"apply_patch",
|
|
4812
|
+
"list_dir",
|
|
4813
|
+
"shell",
|
|
4814
|
+
"update_plan",
|
|
4815
|
+
"ask_question",
|
|
4816
|
+
"request_user_input",
|
|
4817
|
+
"remember",
|
|
4818
|
+
"list_memories",
|
|
4819
|
+
"read_memory",
|
|
4820
|
+
"save_memory",
|
|
4821
|
+
"spawn_agent",
|
|
4822
|
+
"wait_agent",
|
|
4823
|
+
"send_input",
|
|
4824
|
+
"close_agent",
|
|
4825
|
+
"list_agents",
|
|
4826
|
+
"create_worktree",
|
|
4827
|
+
"list_worktrees",
|
|
4828
|
+
"merge_worktree"
|
|
4829
|
+
]
|
|
4788
4830
|
});
|
|
4789
4831
|
this.registerRole({
|
|
4790
4832
|
name: "reviewer",
|
|
@@ -4863,7 +4905,7 @@ class AgentRoleRegistry {
|
|
|
4863
4905
|
for (const entry of entries) {
|
|
4864
4906
|
if (entry.endsWith(".json")) {
|
|
4865
4907
|
try {
|
|
4866
|
-
const content = readFileSync9(join8(fullPath, entry), "utf8");
|
|
4908
|
+
const content = readFileSync9(join8(fullPath, entry), "utf8").replace(/^\uFEFF/, "");
|
|
4867
4909
|
const parsed = JSON.parse(content);
|
|
4868
4910
|
if (parsed.name && parsed.systemPrompt) {
|
|
4869
4911
|
this.registerRole(parsed);
|
|
@@ -4881,7 +4923,13 @@ class AgentRoleRegistry {
|
|
|
4881
4923
|
if (!role || !role.allowedToolNames)
|
|
4882
4924
|
return sourceRouter;
|
|
4883
4925
|
const filtered = sourceRouter.list().filter((t) => {
|
|
4884
|
-
return role.allowedToolNames.some((allowed) =>
|
|
4926
|
+
return role.allowedToolNames.some((allowed) => {
|
|
4927
|
+
if (t.name === allowed)
|
|
4928
|
+
return true;
|
|
4929
|
+
if (allowed.endsWith("*") && t.name.startsWith(allowed.slice(0, -1)))
|
|
4930
|
+
return true;
|
|
4931
|
+
return false;
|
|
4932
|
+
});
|
|
4885
4933
|
});
|
|
4886
4934
|
const newRouter = new sourceRouter.constructor;
|
|
4887
4935
|
for (const tool of filtered) {
|
|
@@ -5101,7 +5149,9 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
5101
5149
|
promise: taskPromise,
|
|
5102
5150
|
depth: this.depth + 1,
|
|
5103
5151
|
tokenBudget,
|
|
5104
|
-
totalTokens: 0
|
|
5152
|
+
totalTokens: 0,
|
|
5153
|
+
resolvePromise: (output) => resolvePromise(output),
|
|
5154
|
+
rejectPromise: (err) => rejectPromise(err)
|
|
5105
5155
|
};
|
|
5106
5156
|
try {
|
|
5107
5157
|
this.graphStore.upsertEdge(this.parentSession.threadId, agentId, "open");
|
|
@@ -5155,13 +5205,14 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
5155
5205
|
if (handle.status === "running") {
|
|
5156
5206
|
handle.status = "interrupted";
|
|
5157
5207
|
handle.totalTokens = accumulatedTokens;
|
|
5208
|
+
handle.lastOutput = collectedAgentText.trim() || "[Task was interrupted]";
|
|
5158
5209
|
try {
|
|
5159
5210
|
this.graphStore.setEdgeStatus(agentId, "closed");
|
|
5160
5211
|
} catch (err) {
|
|
5161
5212
|
console.warn(`[AgentSpawner] Failed to update edge status for agent '${agentId}':`, err);
|
|
5162
5213
|
}
|
|
5163
5214
|
this.pruneCompletedAgents();
|
|
5164
|
-
resolvePromise(
|
|
5215
|
+
resolvePromise(handle.lastOutput);
|
|
5165
5216
|
}
|
|
5166
5217
|
}
|
|
5167
5218
|
});
|
|
@@ -5220,7 +5271,7 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
5220
5271
|
return this.waitSingleAgent(handle, timeoutMs);
|
|
5221
5272
|
}
|
|
5222
5273
|
async waitSingleAgent(handle, timeoutMs) {
|
|
5223
|
-
if (handle.status === "completed" && handle.lastOutput !== undefined) {
|
|
5274
|
+
if ((handle.status === "completed" || handle.status === "interrupted") && handle.lastOutput !== undefined) {
|
|
5224
5275
|
return handle.lastOutput;
|
|
5225
5276
|
}
|
|
5226
5277
|
if (handle.status === "error") {
|
|
@@ -5253,7 +5304,11 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
5253
5304
|
throw new GroupyError(`Sub-agent with ID '${agentId}' not found.`);
|
|
5254
5305
|
}
|
|
5255
5306
|
handle.session.interrupt();
|
|
5256
|
-
handle.status
|
|
5307
|
+
if (handle.status === "running") {
|
|
5308
|
+
handle.status = "interrupted";
|
|
5309
|
+
handle.lastOutput = handle.lastOutput || "[Task was interrupted]";
|
|
5310
|
+
handle.resolvePromise?.(handle.lastOutput);
|
|
5311
|
+
}
|
|
5257
5312
|
try {
|
|
5258
5313
|
this.graphStore.setEdgeStatus(agentId, "closed");
|
|
5259
5314
|
} catch (err) {
|
|
@@ -5268,6 +5323,9 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
5268
5323
|
return false;
|
|
5269
5324
|
if (handle.status === "running") {
|
|
5270
5325
|
handle.session.interrupt();
|
|
5326
|
+
handle.status = "interrupted";
|
|
5327
|
+
handle.lastOutput = handle.lastOutput || "[Task was interrupted]";
|
|
5328
|
+
handle.resolvePromise?.(handle.lastOutput);
|
|
5271
5329
|
}
|
|
5272
5330
|
try {
|
|
5273
5331
|
this.graphStore.setEdgeStatus(agentId, "closed");
|
|
@@ -8155,7 +8213,7 @@ function parsePatch(oldSrc, newSrc, contextLines = 3) {
|
|
|
8155
8213
|
// package.json
|
|
8156
8214
|
var package_default = {
|
|
8157
8215
|
name: "@pikaa-ai/pikaa",
|
|
8158
|
-
version: "0.4.
|
|
8216
|
+
version: "0.4.2",
|
|
8159
8217
|
description: "PIKAA CLI - AI coding agent that runs locally in your terminal.",
|
|
8160
8218
|
main: "./dist/index.js",
|
|
8161
8219
|
module: "./dist/index.js",
|
|
@@ -8187,14 +8245,14 @@ var package_default = {
|
|
|
8187
8245
|
prepublishOnly: "bun run build:js"
|
|
8188
8246
|
},
|
|
8189
8247
|
optionalDependencies: {
|
|
8190
|
-
"@pikaa-ai/pikaa-linux-x64": "0.4.
|
|
8191
|
-
"@pikaa-ai/pikaa-linux-x64-musl": "0.4.
|
|
8192
|
-
"@pikaa-ai/pikaa-linux-arm64": "0.4.
|
|
8193
|
-
"@pikaa-ai/pikaa-linux-arm64-musl": "0.4.
|
|
8194
|
-
"@pikaa-ai/pikaa-darwin-x64": "0.4.
|
|
8195
|
-
"@pikaa-ai/pikaa-darwin-arm64": "0.4.
|
|
8196
|
-
"@pikaa-ai/pikaa-windows-x64": "0.4.
|
|
8197
|
-
"@pikaa-ai/pikaa-windows-arm64": "0.4.
|
|
8248
|
+
"@pikaa-ai/pikaa-linux-x64": "0.4.2",
|
|
8249
|
+
"@pikaa-ai/pikaa-linux-x64-musl": "0.4.2",
|
|
8250
|
+
"@pikaa-ai/pikaa-linux-arm64": "0.4.2",
|
|
8251
|
+
"@pikaa-ai/pikaa-linux-arm64-musl": "0.4.2",
|
|
8252
|
+
"@pikaa-ai/pikaa-darwin-x64": "0.4.2",
|
|
8253
|
+
"@pikaa-ai/pikaa-darwin-arm64": "0.4.2",
|
|
8254
|
+
"@pikaa-ai/pikaa-windows-x64": "0.4.2",
|
|
8255
|
+
"@pikaa-ai/pikaa-windows-arm64": "0.4.2"
|
|
8198
8256
|
},
|
|
8199
8257
|
keywords: [
|
|
8200
8258
|
"ai",
|
package/dist/index.js
CHANGED
|
@@ -1972,14 +1972,33 @@ function parseShellCommand(commandLine) {
|
|
|
1972
1972
|
if (char === "$" && i + 1 < len && commandLine[i + 1] === "(") {
|
|
1973
1973
|
let depth = 1;
|
|
1974
1974
|
let endIdx = -1;
|
|
1975
|
+
let subInSingleQuote = false;
|
|
1976
|
+
let subInDoubleQuote = false;
|
|
1977
|
+
let subIsEscaped = false;
|
|
1975
1978
|
for (let j = i + 2;j < len; j++) {
|
|
1976
|
-
|
|
1977
|
-
|
|
1979
|
+
const subChar = commandLine[j];
|
|
1980
|
+
if (subIsEscaped) {
|
|
1981
|
+
subIsEscaped = false;
|
|
1982
|
+
continue;
|
|
1983
|
+
}
|
|
1984
|
+
if (subChar === "\\") {
|
|
1985
|
+
subIsEscaped = true;
|
|
1986
|
+
continue;
|
|
1987
|
+
}
|
|
1988
|
+
if (subChar === "'" && !subInDoubleQuote) {
|
|
1989
|
+
subInSingleQuote = !subInSingleQuote;
|
|
1990
|
+
continue;
|
|
1991
|
+
}
|
|
1992
|
+
if (subChar === '"' && !subInSingleQuote) {
|
|
1993
|
+
subInDoubleQuote = !subInDoubleQuote;
|
|
1994
|
+
continue;
|
|
1995
|
+
}
|
|
1996
|
+
if (subInSingleQuote || subInDoubleQuote) {
|
|
1978
1997
|
continue;
|
|
1979
1998
|
}
|
|
1980
|
-
if (
|
|
1999
|
+
if (subChar === "(")
|
|
1981
2000
|
depth++;
|
|
1982
|
-
else if (
|
|
2001
|
+
else if (subChar === ")") {
|
|
1983
2002
|
depth--;
|
|
1984
2003
|
if (depth === 0) {
|
|
1985
2004
|
endIdx = j;
|
|
@@ -2574,7 +2593,7 @@ class PrefixRulesStore {
|
|
|
2574
2593
|
return false;
|
|
2575
2594
|
const SHELL_OPERATORS = new Set([";", "&&", "||", "|", "&", ";;", "&|"]);
|
|
2576
2595
|
for (const token of cmdTokens) {
|
|
2577
|
-
if (SHELL_OPERATORS.has(token) || token.includes(";") || token.includes("&&") || token.includes("||")) {
|
|
2596
|
+
if (SHELL_OPERATORS.has(token) || token.includes(";") || token.includes("&&") || token.includes("||") || token.includes("|") || token.includes("&")) {
|
|
2578
2597
|
return false;
|
|
2579
2598
|
}
|
|
2580
2599
|
}
|
|
@@ -4751,7 +4770,7 @@ class ProjectAnalyzer {
|
|
|
4751
4770
|
const pkgPath = join7(this.cwd, "package.json");
|
|
4752
4771
|
if (existsSync13(pkgPath)) {
|
|
4753
4772
|
try {
|
|
4754
|
-
const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
|
|
4773
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
4755
4774
|
if (!description && pkg.description)
|
|
4756
4775
|
description = pkg.description;
|
|
4757
4776
|
const pm = packageManager || "npm";
|
|
@@ -4825,7 +4844,7 @@ class ProjectAnalyzer {
|
|
|
4825
4844
|
const tsconfigPath = join7(this.cwd, "tsconfig.json");
|
|
4826
4845
|
if (existsSync13(tsconfigPath)) {
|
|
4827
4846
|
try {
|
|
4828
|
-
const tsconfig = JSON.parse(readFileSync8(tsconfigPath, "utf8"));
|
|
4847
|
+
const tsconfig = JSON.parse(readFileSync8(tsconfigPath, "utf8").replace(/^\uFEFF/, ""));
|
|
4829
4848
|
if (tsconfig.compilerOptions?.strict) {
|
|
4830
4849
|
codeConventions.push("TypeScript strict mode enabled.");
|
|
4831
4850
|
}
|
|
@@ -5011,7 +5030,7 @@ class ProjectAnalyzer {
|
|
|
5011
5030
|
const pkgPath = join7(this.cwd, "package.json");
|
|
5012
5031
|
if (existsSync13(pkgPath)) {
|
|
5013
5032
|
try {
|
|
5014
|
-
const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
|
|
5033
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
5015
5034
|
if (pkg.name && pkg.name !== "frontend" && pkg.name !== "backend" && pkg.name !== "app") {
|
|
5016
5035
|
return pkg.name.startsWith("@") ? pkg.name.split("/")[1] || pkg.name : pkg.name;
|
|
5017
5036
|
}
|
|
@@ -5157,7 +5176,7 @@ class AutoVerifier {
|
|
|
5157
5176
|
const pkgPath = join8(this.cwd, "package.json");
|
|
5158
5177
|
if (existsSync14(pkgPath)) {
|
|
5159
5178
|
try {
|
|
5160
|
-
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
|
|
5179
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
5161
5180
|
const allDeps = { ...pkg.dependencies || {}, ...pkg.devDependencies || {} };
|
|
5162
5181
|
if (allDeps.vitest) {
|
|
5163
5182
|
return `npx vitest run ${quotedFiles}`;
|
|
@@ -5203,7 +5222,7 @@ class AutoVerifier {
|
|
|
5203
5222
|
const pkgPath = join8(this.cwd, "package.json");
|
|
5204
5223
|
if (existsSync14(pkgPath)) {
|
|
5205
5224
|
try {
|
|
5206
|
-
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
|
|
5225
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
5207
5226
|
if (pkg.scripts) {
|
|
5208
5227
|
const pm = existsSync14(join8(this.cwd, "bun.lockb")) || existsSync14(join8(this.cwd, "bun.lock")) ? "bun" : existsSync14(join8(this.cwd, "pnpm-lock.yaml")) ? "pnpm" : existsSync14(join8(this.cwd, "yarn.lock")) ? "yarn" : "npm";
|
|
5209
5228
|
const runCmd = pm === "bun" || pm === "pnpm" || pm === "yarn" ? `${pm} run` : "npm run";
|
|
@@ -5257,7 +5276,7 @@ class AutoVerifier {
|
|
|
5257
5276
|
const pkgPath = join8(this.cwd, "package.json");
|
|
5258
5277
|
if (existsSync14(pkgPath)) {
|
|
5259
5278
|
try {
|
|
5260
|
-
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
|
|
5279
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8").replace(/^\uFEFF/, ""));
|
|
5261
5280
|
if (pkg.scripts?.test) {
|
|
5262
5281
|
const pm = existsSync14(join8(this.cwd, "bun.lockb")) || existsSync14(join8(this.cwd, "bun.lock")) ? "bun" : "npm";
|
|
5263
5282
|
return pm === "bun" ? "bun test" : "npm test";
|
|
@@ -9628,7 +9647,30 @@ class AgentRoleRegistry {
|
|
|
9628
9647
|
name: "default",
|
|
9629
9648
|
description: "Generalist autonomous developer agent capable of coding, testing, and debugging.",
|
|
9630
9649
|
systemPrompt: "You are Groupy, an expert autonomous software engineer. Think carefully, use tools surgically, and verify every step.",
|
|
9631
|
-
nicknameCandidates: ["Pikaa", "Heca", "Bankli", "Moli"]
|
|
9650
|
+
nicknameCandidates: ["Pikaa", "Heca", "Bankli", "Moli"],
|
|
9651
|
+
allowedToolNames: [
|
|
9652
|
+
"read_file",
|
|
9653
|
+
"view_file",
|
|
9654
|
+
"write_file",
|
|
9655
|
+
"apply_patch",
|
|
9656
|
+
"list_dir",
|
|
9657
|
+
"shell",
|
|
9658
|
+
"update_plan",
|
|
9659
|
+
"ask_question",
|
|
9660
|
+
"request_user_input",
|
|
9661
|
+
"remember",
|
|
9662
|
+
"list_memories",
|
|
9663
|
+
"read_memory",
|
|
9664
|
+
"save_memory",
|
|
9665
|
+
"spawn_agent",
|
|
9666
|
+
"wait_agent",
|
|
9667
|
+
"send_input",
|
|
9668
|
+
"close_agent",
|
|
9669
|
+
"list_agents",
|
|
9670
|
+
"create_worktree",
|
|
9671
|
+
"list_worktrees",
|
|
9672
|
+
"merge_worktree"
|
|
9673
|
+
]
|
|
9632
9674
|
});
|
|
9633
9675
|
this.registerRole({
|
|
9634
9676
|
name: "reviewer",
|
|
@@ -9707,7 +9749,7 @@ class AgentRoleRegistry {
|
|
|
9707
9749
|
for (const entry of entries) {
|
|
9708
9750
|
if (entry.endsWith(".json")) {
|
|
9709
9751
|
try {
|
|
9710
|
-
const content = readFileSync11(join11(fullPath, entry), "utf8");
|
|
9752
|
+
const content = readFileSync11(join11(fullPath, entry), "utf8").replace(/^\uFEFF/, "");
|
|
9711
9753
|
const parsed = JSON.parse(content);
|
|
9712
9754
|
if (parsed.name && parsed.systemPrompt) {
|
|
9713
9755
|
this.registerRole(parsed);
|
|
@@ -9725,7 +9767,13 @@ class AgentRoleRegistry {
|
|
|
9725
9767
|
if (!role || !role.allowedToolNames)
|
|
9726
9768
|
return sourceRouter;
|
|
9727
9769
|
const filtered = sourceRouter.list().filter((t) => {
|
|
9728
|
-
return role.allowedToolNames.some((allowed) =>
|
|
9770
|
+
return role.allowedToolNames.some((allowed) => {
|
|
9771
|
+
if (t.name === allowed)
|
|
9772
|
+
return true;
|
|
9773
|
+
if (allowed.endsWith("*") && t.name.startsWith(allowed.slice(0, -1)))
|
|
9774
|
+
return true;
|
|
9775
|
+
return false;
|
|
9776
|
+
});
|
|
9729
9777
|
});
|
|
9730
9778
|
const newRouter = new sourceRouter.constructor;
|
|
9731
9779
|
for (const tool of filtered) {
|
|
@@ -9921,7 +9969,9 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
9921
9969
|
promise: taskPromise,
|
|
9922
9970
|
depth: this.depth + 1,
|
|
9923
9971
|
tokenBudget,
|
|
9924
|
-
totalTokens: 0
|
|
9972
|
+
totalTokens: 0,
|
|
9973
|
+
resolvePromise: (output) => resolvePromise(output),
|
|
9974
|
+
rejectPromise: (err) => rejectPromise(err)
|
|
9925
9975
|
};
|
|
9926
9976
|
try {
|
|
9927
9977
|
this.graphStore.upsertEdge(this.parentSession.threadId, agentId, "open");
|
|
@@ -9975,13 +10025,14 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
9975
10025
|
if (handle.status === "running") {
|
|
9976
10026
|
handle.status = "interrupted";
|
|
9977
10027
|
handle.totalTokens = accumulatedTokens;
|
|
10028
|
+
handle.lastOutput = collectedAgentText.trim() || "[Task was interrupted]";
|
|
9978
10029
|
try {
|
|
9979
10030
|
this.graphStore.setEdgeStatus(agentId, "closed");
|
|
9980
10031
|
} catch (err) {
|
|
9981
10032
|
console.warn(`[AgentSpawner] Failed to update edge status for agent '${agentId}':`, err);
|
|
9982
10033
|
}
|
|
9983
10034
|
this.pruneCompletedAgents();
|
|
9984
|
-
resolvePromise(
|
|
10035
|
+
resolvePromise(handle.lastOutput);
|
|
9985
10036
|
}
|
|
9986
10037
|
}
|
|
9987
10038
|
});
|
|
@@ -10040,7 +10091,7 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
10040
10091
|
return this.waitSingleAgent(handle, timeoutMs);
|
|
10041
10092
|
}
|
|
10042
10093
|
async waitSingleAgent(handle, timeoutMs) {
|
|
10043
|
-
if (handle.status === "completed" && handle.lastOutput !== undefined) {
|
|
10094
|
+
if ((handle.status === "completed" || handle.status === "interrupted") && handle.lastOutput !== undefined) {
|
|
10044
10095
|
return handle.lastOutput;
|
|
10045
10096
|
}
|
|
10046
10097
|
if (handle.status === "error") {
|
|
@@ -10073,7 +10124,11 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
10073
10124
|
throw new GroupyError(`Sub-agent with ID '${agentId}' not found.`);
|
|
10074
10125
|
}
|
|
10075
10126
|
handle.session.interrupt();
|
|
10076
|
-
handle.status
|
|
10127
|
+
if (handle.status === "running") {
|
|
10128
|
+
handle.status = "interrupted";
|
|
10129
|
+
handle.lastOutput = handle.lastOutput || "[Task was interrupted]";
|
|
10130
|
+
handle.resolvePromise?.(handle.lastOutput);
|
|
10131
|
+
}
|
|
10077
10132
|
try {
|
|
10078
10133
|
this.graphStore.setEdgeStatus(agentId, "closed");
|
|
10079
10134
|
} catch (err) {
|
|
@@ -10088,6 +10143,9 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
10088
10143
|
return false;
|
|
10089
10144
|
if (handle.status === "running") {
|
|
10090
10145
|
handle.session.interrupt();
|
|
10146
|
+
handle.status = "interrupted";
|
|
10147
|
+
handle.lastOutput = handle.lastOutput || "[Task was interrupted]";
|
|
10148
|
+
handle.resolvePromise?.(handle.lastOutput);
|
|
10091
10149
|
}
|
|
10092
10150
|
try {
|
|
10093
10151
|
this.graphStore.setEdgeStatus(agentId, "closed");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikaa-ai/pikaa",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "PIKAA CLI - AI coding agent that runs locally in your terminal.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"prepublishOnly": "bun run build:js"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@pikaa-ai/pikaa-linux-x64": "0.4.
|
|
36
|
-
"@pikaa-ai/pikaa-linux-x64-musl": "0.4.
|
|
37
|
-
"@pikaa-ai/pikaa-linux-arm64": "0.4.
|
|
38
|
-
"@pikaa-ai/pikaa-linux-arm64-musl": "0.4.
|
|
39
|
-
"@pikaa-ai/pikaa-darwin-x64": "0.4.
|
|
40
|
-
"@pikaa-ai/pikaa-darwin-arm64": "0.4.
|
|
41
|
-
"@pikaa-ai/pikaa-windows-x64": "0.4.
|
|
42
|
-
"@pikaa-ai/pikaa-windows-arm64": "0.4.
|
|
35
|
+
"@pikaa-ai/pikaa-linux-x64": "0.4.2",
|
|
36
|
+
"@pikaa-ai/pikaa-linux-x64-musl": "0.4.2",
|
|
37
|
+
"@pikaa-ai/pikaa-linux-arm64": "0.4.2",
|
|
38
|
+
"@pikaa-ai/pikaa-linux-arm64-musl": "0.4.2",
|
|
39
|
+
"@pikaa-ai/pikaa-darwin-x64": "0.4.2",
|
|
40
|
+
"@pikaa-ai/pikaa-darwin-arm64": "0.4.2",
|
|
41
|
+
"@pikaa-ai/pikaa-windows-x64": "0.4.2",
|
|
42
|
+
"@pikaa-ai/pikaa-windows-arm64": "0.4.2"
|
|
43
43
|
},
|
|
44
44
|
"keywords": [
|
|
45
45
|
"ai",
|