@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 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
- if (commandLine[j] === "\\" && j + 1 < len) {
2348
- j++;
2350
+ const subChar = commandLine[j];
2351
+ if (subIsEscaped) {
2352
+ subIsEscaped = false;
2349
2353
  continue;
2350
2354
  }
2351
- if (commandLine[j] === "(")
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 (commandLine[j] === ")") {
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) => t.name === allowed || t.name.startsWith(`mcp__`));
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(collectedAgentText.trim() || "[Task was interrupted]");
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 = "interrupted";
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.0",
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.0",
8191
- "@pikaa-ai/pikaa-linux-x64-musl": "0.4.0",
8192
- "@pikaa-ai/pikaa-linux-arm64": "0.4.0",
8193
- "@pikaa-ai/pikaa-linux-arm64-musl": "0.4.0",
8194
- "@pikaa-ai/pikaa-darwin-x64": "0.4.0",
8195
- "@pikaa-ai/pikaa-darwin-arm64": "0.4.0",
8196
- "@pikaa-ai/pikaa-windows-x64": "0.4.0",
8197
- "@pikaa-ai/pikaa-windows-arm64": "0.4.0"
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
- if (commandLine[j] === "\\" && j + 1 < len) {
1977
- j++;
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 (commandLine[j] === "(")
1999
+ if (subChar === "(")
1981
2000
  depth++;
1982
- else if (commandLine[j] === ")") {
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) => t.name === allowed || t.name.startsWith(`mcp__`));
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(collectedAgentText.trim() || "[Task was interrupted]");
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 = "interrupted";
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.0",
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.0",
36
- "@pikaa-ai/pikaa-linux-x64-musl": "0.4.0",
37
- "@pikaa-ai/pikaa-linux-arm64": "0.4.0",
38
- "@pikaa-ai/pikaa-linux-arm64-musl": "0.4.0",
39
- "@pikaa-ai/pikaa-darwin-x64": "0.4.0",
40
- "@pikaa-ai/pikaa-darwin-arm64": "0.4.0",
41
- "@pikaa-ai/pikaa-windows-x64": "0.4.0",
42
- "@pikaa-ai/pikaa-windows-arm64": "0.4.0"
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",