@pikaa-ai/pikaa 0.3.25 → 0.3.26
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 +125 -29
- package/dist/cli.js +214 -203
- package/dist/index.js +120 -120
- package/package.json +12 -1
package/dist/cli.js
CHANGED
|
@@ -1636,13 +1636,13 @@ class Session {
|
|
|
1636
1636
|
type: "StatusChanged",
|
|
1637
1637
|
status: "waiting_approval"
|
|
1638
1638
|
});
|
|
1639
|
-
return new Promise((
|
|
1639
|
+
return new Promise((resolve) => {
|
|
1640
1640
|
this.pendingApprovals.set(params.approvalId, (approved) => {
|
|
1641
1641
|
this.emitEvent({
|
|
1642
1642
|
type: "StatusChanged",
|
|
1643
1643
|
status: "running"
|
|
1644
1644
|
});
|
|
1645
|
-
|
|
1645
|
+
resolve(approved);
|
|
1646
1646
|
});
|
|
1647
1647
|
});
|
|
1648
1648
|
}
|
|
@@ -1665,13 +1665,13 @@ class Session {
|
|
|
1665
1665
|
type: "StatusChanged",
|
|
1666
1666
|
status: "waiting_user_input"
|
|
1667
1667
|
});
|
|
1668
|
-
return new Promise((
|
|
1668
|
+
return new Promise((resolve) => {
|
|
1669
1669
|
this.pendingUserQuestions.set(params.questionId, (answer) => {
|
|
1670
1670
|
this.emitEvent({
|
|
1671
1671
|
type: "StatusChanged",
|
|
1672
1672
|
status: "running"
|
|
1673
1673
|
});
|
|
1674
|
-
|
|
1674
|
+
resolve(answer);
|
|
1675
1675
|
});
|
|
1676
1676
|
});
|
|
1677
1677
|
}
|
|
@@ -1701,7 +1701,7 @@ class Session {
|
|
|
1701
1701
|
return handleTurnInput(this, { text, images });
|
|
1702
1702
|
}
|
|
1703
1703
|
async promptAndWait(text, images, timeoutMs = 30000) {
|
|
1704
|
-
return new Promise((
|
|
1704
|
+
return new Promise((resolve, reject) => {
|
|
1705
1705
|
const timer = setTimeout(() => {
|
|
1706
1706
|
unsub();
|
|
1707
1707
|
reject(new Error(`Turn timed out after ${timeoutMs}ms`));
|
|
@@ -1710,7 +1710,7 @@ class Session {
|
|
|
1710
1710
|
if (event.msg.type === "TurnCompleted") {
|
|
1711
1711
|
clearTimeout(timer);
|
|
1712
1712
|
unsub();
|
|
1713
|
-
|
|
1713
|
+
resolve();
|
|
1714
1714
|
} else if (event.msg.type === "Error") {
|
|
1715
1715
|
clearTimeout(timer);
|
|
1716
1716
|
unsub();
|
|
@@ -1729,8 +1729,8 @@ class Session {
|
|
|
1729
1729
|
if (this.submissionQueue.length > 0) {
|
|
1730
1730
|
yield this.submissionQueue.shift();
|
|
1731
1731
|
} else {
|
|
1732
|
-
const nextSub = await new Promise((
|
|
1733
|
-
this.submissionResolvers.push(
|
|
1732
|
+
const nextSub = await new Promise((resolve) => {
|
|
1733
|
+
this.submissionResolvers.push(resolve);
|
|
1734
1734
|
});
|
|
1735
1735
|
yield nextSub;
|
|
1736
1736
|
}
|
|
@@ -2344,7 +2344,7 @@ function createShellTool(policy = new ExecPolicy) {
|
|
|
2344
2344
|
} catch {}
|
|
2345
2345
|
});
|
|
2346
2346
|
}
|
|
2347
|
-
const timeoutPromise = new Promise((
|
|
2347
|
+
const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve({ isTimeout: true }), timeoutMs));
|
|
2348
2348
|
const result = await Promise.race([
|
|
2349
2349
|
proc.exited.then(async (code) => {
|
|
2350
2350
|
const stdout = await new Response(proc.stdout).text();
|
|
@@ -3762,8 +3762,8 @@ Your nickname is ${nickname}. Your assigned task is: '${params.taskName}'. Focus
|
|
|
3762
3762
|
});
|
|
3763
3763
|
let resolvePromise;
|
|
3764
3764
|
let rejectPromise;
|
|
3765
|
-
const taskPromise = new Promise((
|
|
3766
|
-
resolvePromise =
|
|
3765
|
+
const taskPromise = new Promise((resolve, reject) => {
|
|
3766
|
+
resolvePromise = resolve;
|
|
3767
3767
|
rejectPromise = reject;
|
|
3768
3768
|
});
|
|
3769
3769
|
const handle = {
|
|
@@ -4056,9 +4056,9 @@ function createMultiAgentTools(spawner) {
|
|
|
4056
4056
|
};
|
|
4057
4057
|
return [spawnAgentTool, waitAgentTool, sendInputTool, closeAgentTool, listAgentsTool];
|
|
4058
4058
|
}
|
|
4059
|
-
function registerMultiAgentTools(
|
|
4059
|
+
function registerMultiAgentTools(router, spawner) {
|
|
4060
4060
|
for (const tool of createMultiAgentTools(spawner)) {
|
|
4061
|
-
|
|
4061
|
+
router.register(tool);
|
|
4062
4062
|
}
|
|
4063
4063
|
}
|
|
4064
4064
|
|
|
@@ -4458,13 +4458,13 @@ class StdioTransport {
|
|
|
4458
4458
|
if (this.isClosed || !this.proc || !this.proc.stdin) {
|
|
4459
4459
|
throw new GroupyError("MCP Stdio transport is closed");
|
|
4460
4460
|
}
|
|
4461
|
-
return new Promise((
|
|
4461
|
+
return new Promise((resolve, reject) => {
|
|
4462
4462
|
const timeoutMs = 30000;
|
|
4463
4463
|
const timer = setTimeout(() => {
|
|
4464
4464
|
this.pendingRequests.delete(request.id);
|
|
4465
4465
|
reject(new GroupyError(`MCP request timed out after ${timeoutMs}ms (method: ${request.method})`));
|
|
4466
4466
|
}, timeoutMs);
|
|
4467
|
-
this.pendingRequests.set(request.id, { resolve
|
|
4467
|
+
this.pendingRequests.set(request.id, { resolve, reject, timer });
|
|
4468
4468
|
try {
|
|
4469
4469
|
const payload = JSON.stringify(request) + `
|
|
4470
4470
|
`;
|
|
@@ -4597,12 +4597,12 @@ class SseTransport {
|
|
|
4597
4597
|
if (!this.messageUrl) {
|
|
4598
4598
|
this.messageUrl = this.endpointUrl;
|
|
4599
4599
|
}
|
|
4600
|
-
return new Promise((
|
|
4600
|
+
return new Promise((resolve, reject) => {
|
|
4601
4601
|
const timer = setTimeout(() => {
|
|
4602
4602
|
this.pendingRequests.delete(request.id);
|
|
4603
4603
|
reject(new GroupyError(`MCP SSE request timed out (method: ${request.method})`));
|
|
4604
4604
|
}, 30000);
|
|
4605
|
-
this.pendingRequests.set(request.id, { resolve
|
|
4605
|
+
this.pendingRequests.set(request.id, { resolve, reject, timer });
|
|
4606
4606
|
fetch(this.messageUrl, {
|
|
4607
4607
|
method: "POST",
|
|
4608
4608
|
headers: {
|
|
@@ -4731,7 +4731,7 @@ class McpManager {
|
|
|
4731
4731
|
}
|
|
4732
4732
|
return client.ping();
|
|
4733
4733
|
}
|
|
4734
|
-
async removeServer(name,
|
|
4734
|
+
async removeServer(name, router) {
|
|
4735
4735
|
const client = this.clients.get(name);
|
|
4736
4736
|
if (!client)
|
|
4737
4737
|
return false;
|
|
@@ -4740,12 +4740,12 @@ class McpManager {
|
|
|
4740
4740
|
} catch {}
|
|
4741
4741
|
this.clients.delete(name);
|
|
4742
4742
|
this.serverConfigs.delete(name);
|
|
4743
|
-
if (
|
|
4744
|
-
|
|
4743
|
+
if (router) {
|
|
4744
|
+
router.unregisterPrefix(`mcp__${name}__`);
|
|
4745
4745
|
}
|
|
4746
4746
|
return true;
|
|
4747
4747
|
}
|
|
4748
|
-
registerToolsIntoRouter(
|
|
4748
|
+
registerToolsIntoRouter(router) {
|
|
4749
4749
|
if (this.clients.size === 0)
|
|
4750
4750
|
return;
|
|
4751
4751
|
let hasAnyLazyServer = false;
|
|
@@ -4769,7 +4769,7 @@ class McpManager {
|
|
|
4769
4769
|
return client.callTool(mcpTool.name, args);
|
|
4770
4770
|
}
|
|
4771
4771
|
};
|
|
4772
|
-
|
|
4772
|
+
router.register(tool);
|
|
4773
4773
|
}
|
|
4774
4774
|
}
|
|
4775
4775
|
if (client.getResources().length > 0) {
|
|
@@ -4819,7 +4819,7 @@ class McpManager {
|
|
|
4819
4819
|
}
|
|
4820
4820
|
}
|
|
4821
4821
|
};
|
|
4822
|
-
|
|
4822
|
+
router.register(callMcpTool);
|
|
4823
4823
|
const getToolSchemaTool = {
|
|
4824
4824
|
name: "get_mcp_tool_schema",
|
|
4825
4825
|
description: "Retrieve parameter specification and JSONSchema for a lazy-loaded MCP tool.",
|
|
@@ -4848,7 +4848,7 @@ class McpManager {
|
|
|
4848
4848
|
return { output: JSON.stringify(tool, null, 2) };
|
|
4849
4849
|
}
|
|
4850
4850
|
};
|
|
4851
|
-
|
|
4851
|
+
router.register(getToolSchemaTool);
|
|
4852
4852
|
const listResourcesTool = {
|
|
4853
4853
|
name: "list_mcp_resources",
|
|
4854
4854
|
description: "List available data resources exposed by a connected MCP server.",
|
|
@@ -4868,7 +4868,7 @@ class McpManager {
|
|
|
4868
4868
|
return { output: JSON.stringify(client.getResources(), null, 2) };
|
|
4869
4869
|
}
|
|
4870
4870
|
};
|
|
4871
|
-
|
|
4871
|
+
router.register(listResourcesTool);
|
|
4872
4872
|
const readResourceTool = {
|
|
4873
4873
|
name: "read_mcp_resource",
|
|
4874
4874
|
description: "Read the contents of an MCP resource by URI across connected MCP servers.",
|
|
@@ -4898,7 +4898,7 @@ class McpManager {
|
|
|
4898
4898
|
}
|
|
4899
4899
|
}
|
|
4900
4900
|
};
|
|
4901
|
-
|
|
4901
|
+
router.register(readResourceTool);
|
|
4902
4902
|
}
|
|
4903
4903
|
formatMcpPrompt() {
|
|
4904
4904
|
if (this.clients.size === 0)
|
|
@@ -4967,20 +4967,20 @@ class McpManager {
|
|
|
4967
4967
|
} catch {}
|
|
4968
4968
|
return false;
|
|
4969
4969
|
}
|
|
4970
|
-
async reload(
|
|
4970
|
+
async reload(router) {
|
|
4971
4971
|
await this.closeAll();
|
|
4972
|
-
if (
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4972
|
+
if (router) {
|
|
4973
|
+
router.unregisterPrefix("mcp__");
|
|
4974
|
+
router.unregister("call_mcp_tool");
|
|
4975
|
+
router.unregister("get_mcp_tool_schema");
|
|
4976
|
+
router.unregister("list_mcp_resources");
|
|
4977
|
+
router.unregister("read_mcp_resource");
|
|
4978
4978
|
}
|
|
4979
4979
|
for (const filePath of this.loadedConfigFiles) {
|
|
4980
4980
|
await this.loadConfigFile(filePath);
|
|
4981
4981
|
}
|
|
4982
|
-
if (
|
|
4983
|
-
this.registerToolsIntoRouter(
|
|
4982
|
+
if (router) {
|
|
4983
|
+
this.registerToolsIntoRouter(router);
|
|
4984
4984
|
}
|
|
4985
4985
|
}
|
|
4986
4986
|
getDefaultConfigFile(cwd = process.cwd()) {
|
|
@@ -5397,9 +5397,9 @@ class SkillsLoader {
|
|
|
5397
5397
|
}
|
|
5398
5398
|
const all = this.listSkills(cwd, { includeDisabled: false });
|
|
5399
5399
|
const target = skillName.trim().toLowerCase();
|
|
5400
|
-
const
|
|
5401
|
-
const targetNorm =
|
|
5402
|
-
const meta = all.find((s) => s.name.toLowerCase() === target) || all.find((s) =>
|
|
5400
|
+
const normalize = (str) => str.toLowerCase().replace(/[-_\s]/g, "");
|
|
5401
|
+
const targetNorm = normalize(skillName);
|
|
5402
|
+
const meta = all.find((s) => s.name.toLowerCase() === target) || all.find((s) => normalize(s.name) === targetNorm);
|
|
5403
5403
|
if (!meta)
|
|
5404
5404
|
return null;
|
|
5405
5405
|
try {
|
|
@@ -5596,13 +5596,13 @@ class MemoryStore {
|
|
|
5596
5596
|
}
|
|
5597
5597
|
getProjectMemoryDir(cwd) {
|
|
5598
5598
|
if (this.customWorkspacePath) {
|
|
5599
|
-
const
|
|
5600
|
-
if (!existsSync18(
|
|
5599
|
+
const dir = resolve15(this.customWorkspacePath);
|
|
5600
|
+
if (!existsSync18(dir)) {
|
|
5601
5601
|
try {
|
|
5602
|
-
mkdirSync11(
|
|
5602
|
+
mkdirSync11(dir, { recursive: true });
|
|
5603
5603
|
} catch {}
|
|
5604
5604
|
}
|
|
5605
|
-
return
|
|
5605
|
+
return dir;
|
|
5606
5606
|
}
|
|
5607
5607
|
const slug = this.getProjectSlug(cwd);
|
|
5608
5608
|
const dir = join10(getProjectsDir(), slug, "memory");
|
|
@@ -6132,8 +6132,8 @@ class AuthClient {
|
|
|
6132
6132
|
if (!res.ok) {
|
|
6133
6133
|
let errDetail = `HTTP ${res.status}`;
|
|
6134
6134
|
try {
|
|
6135
|
-
const
|
|
6136
|
-
errDetail =
|
|
6135
|
+
const data = await res.json();
|
|
6136
|
+
errDetail = data.detail || JSON.stringify(data);
|
|
6137
6137
|
} catch {}
|
|
6138
6138
|
throw new Error(`Login failed: ${errDetail}`);
|
|
6139
6139
|
}
|
|
@@ -6159,8 +6159,8 @@ class AuthClient {
|
|
|
6159
6159
|
const authUrl = `${backendUrl}/api/auth/authorize?response_type=code&client_id=groupy-cli&redirect_uri=${encodeURIComponent(redirectUri)}&code_challenge=${encodeURIComponent(codeChallenge)}&code_challenge_method=S256&state=${state}&direct=1`;
|
|
6160
6160
|
let serverResolve;
|
|
6161
6161
|
let serverReject;
|
|
6162
|
-
const codePromise = new Promise((
|
|
6163
|
-
serverResolve =
|
|
6162
|
+
const codePromise = new Promise((resolve, reject) => {
|
|
6163
|
+
serverResolve = resolve;
|
|
6164
6164
|
serverReject = reject;
|
|
6165
6165
|
});
|
|
6166
6166
|
if (options.openBrowser !== false) {
|
|
@@ -6545,9 +6545,9 @@ function lcsTokenDiff(oldTokens, newTokens) {
|
|
|
6545
6545
|
const m = oldTokens.length;
|
|
6546
6546
|
const n = newTokens.length;
|
|
6547
6547
|
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
6548
|
-
for (let
|
|
6549
|
-
for (let
|
|
6550
|
-
dp[
|
|
6548
|
+
for (let i = 1;i <= m; i++) {
|
|
6549
|
+
for (let j = 1;j <= n; j++) {
|
|
6550
|
+
dp[i][j] = oldTokens[i - 1] === newTokens[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);
|
|
6551
6551
|
}
|
|
6552
6552
|
}
|
|
6553
6553
|
const ops = [];
|
|
@@ -6729,7 +6729,7 @@ function parsePatch(oldSrc, newSrc, contextLines = 3) {
|
|
|
6729
6729
|
// package.json
|
|
6730
6730
|
var package_default = {
|
|
6731
6731
|
name: "@pikaa-ai/pikaa",
|
|
6732
|
-
version: "0.3.
|
|
6732
|
+
version: "0.3.26",
|
|
6733
6733
|
description: "PIKAA CLI - AI coding agent that runs locally in your terminal.",
|
|
6734
6734
|
main: "./dist/index.js",
|
|
6735
6735
|
module: "./dist/index.js",
|
|
@@ -6755,10 +6755,21 @@ var package_default = {
|
|
|
6755
6755
|
"build:js": "bun build ./src/index.ts --outdir ./dist --target=bun && bun build ./src/cli/index.ts --outfile ./dist/cli.js --target=bun",
|
|
6756
6756
|
"build:exe": "bun build ./src/cli/index.ts --compile --outfile pikaa.exe",
|
|
6757
6757
|
"build:binaries": "bun run scripts/build-binaries.ts",
|
|
6758
|
+
"publish:packages": "bun run scripts/publish-packages.ts",
|
|
6758
6759
|
"release:prepare": "bun run scripts/prepare-release.ts",
|
|
6759
6760
|
build: "bun run build:js && bun run build:exe",
|
|
6760
6761
|
prepublishOnly: "bun run build:js"
|
|
6761
6762
|
},
|
|
6763
|
+
optionalDependencies: {
|
|
6764
|
+
"@pikaa-ai/pikaa-linux-x64": "0.3.26",
|
|
6765
|
+
"@pikaa-ai/pikaa-linux-x64-musl": "0.3.26",
|
|
6766
|
+
"@pikaa-ai/pikaa-linux-arm64": "0.3.26",
|
|
6767
|
+
"@pikaa-ai/pikaa-linux-arm64-musl": "0.3.26",
|
|
6768
|
+
"@pikaa-ai/pikaa-darwin-x64": "0.3.26",
|
|
6769
|
+
"@pikaa-ai/pikaa-darwin-arm64": "0.3.26",
|
|
6770
|
+
"@pikaa-ai/pikaa-windows-x64": "0.3.26",
|
|
6771
|
+
"@pikaa-ai/pikaa-windows-arm64": "0.3.26"
|
|
6772
|
+
},
|
|
6762
6773
|
keywords: [
|
|
6763
6774
|
"ai",
|
|
6764
6775
|
"coding-agent",
|
|
@@ -6953,8 +6964,8 @@ class BannerAnimator {
|
|
|
6953
6964
|
async function renderAnimatedGroupyBanner(info, options) {
|
|
6954
6965
|
await BannerAnimator.play(info, options);
|
|
6955
6966
|
}
|
|
6956
|
-
function formatTaskProgressPlan(
|
|
6957
|
-
CliFormatter.formatTaskProgressPlan(
|
|
6967
|
+
function formatTaskProgressPlan(plan, explanation) {
|
|
6968
|
+
CliFormatter.formatTaskProgressPlan(plan, explanation);
|
|
6958
6969
|
}
|
|
6959
6970
|
function formatTurnSummary(metrics) {
|
|
6960
6971
|
CliFormatter.formatTurnSummary(metrics);
|
|
@@ -7006,9 +7017,9 @@ class CliFormatter {
|
|
|
7006
7017
|
const lat = update.latestVersion.startsWith("v") ? update.latestVersion : `v${update.latestVersion}`;
|
|
7007
7018
|
const innerWidth = 54;
|
|
7008
7019
|
const padLine = (content) => {
|
|
7009
|
-
const
|
|
7010
|
-
const
|
|
7011
|
-
return ` ${style.yellow("\u2502")} ${content}${" ".repeat(
|
|
7020
|
+
const visibleLen = style.stripAnsi(content).length;
|
|
7021
|
+
const padRight = Math.max(0, innerWidth - visibleLen);
|
|
7022
|
+
return ` ${style.yellow("\u2502")} ${content}${" ".repeat(padRight)}${style.yellow("\u2502")}`;
|
|
7012
7023
|
};
|
|
7013
7024
|
const topBorder = ` ${style.yellow("\u256D")}${style.yellow("\u2500".repeat(innerWidth + 2))}${style.yellow("\u256E")}`;
|
|
7014
7025
|
const bottomBorder = ` ${style.yellow("\u2570")}${style.yellow("\u2500".repeat(innerWidth + 2))}${style.yellow("\u256F")}`;
|
|
@@ -7155,7 +7166,7 @@ ${preview}${more}`);
|
|
|
7155
7166
|
formatted = formatted.replace(/^(#{1,3})\s+(.*)$/gm, `${c.bold}${c.brand}$1 $2${c.reset}`);
|
|
7156
7167
|
return formatted;
|
|
7157
7168
|
}
|
|
7158
|
-
static formatTaskProgressPlan(
|
|
7169
|
+
static formatTaskProgressPlan(plan, explanation) {
|
|
7159
7170
|
console.log();
|
|
7160
7171
|
if (explanation) {
|
|
7161
7172
|
console.log(` ${style.bold(explanation)}`);
|
|
@@ -7164,18 +7175,18 @@ ${preview}${more}`);
|
|
|
7164
7175
|
const ACTIVE = "\x1B[38;5;174m\u25FC\x1B[0m";
|
|
7165
7176
|
const PENDING = "\x1B[38;5;246m\u25FB\x1B[0m";
|
|
7166
7177
|
const DIM = "\x1B[38;5;246m";
|
|
7167
|
-
const
|
|
7168
|
-
for (let i = 0;i <
|
|
7169
|
-
const item =
|
|
7178
|
+
const RESET = "\x1B[0m";
|
|
7179
|
+
for (let i = 0;i < plan.length; i++) {
|
|
7180
|
+
const item = plan[i];
|
|
7170
7181
|
if (!item)
|
|
7171
7182
|
continue;
|
|
7172
7183
|
const prefix = i === 0 ? " \u23BF " : " ";
|
|
7173
7184
|
if (item.status === "completed") {
|
|
7174
|
-
console.log(` ${DIM}${prefix}${
|
|
7185
|
+
console.log(` ${DIM}${prefix}${RESET}${DONE} \x1B[9m\x1B[38;5;246m${item.step}\x1B[0m`);
|
|
7175
7186
|
} else if (item.status === "in_progress") {
|
|
7176
|
-
console.log(` ${DIM}${prefix}${
|
|
7187
|
+
console.log(` ${DIM}${prefix}${RESET}${ACTIVE} \x1B[1m\x1B[38;5;174m${item.step}\x1B[0m`);
|
|
7177
7188
|
} else {
|
|
7178
|
-
console.log(` ${DIM}${prefix}${
|
|
7189
|
+
console.log(` ${DIM}${prefix}${RESET}${PENDING} \x1B[38;5;246m${item.step}\x1B[0m`);
|
|
7179
7190
|
}
|
|
7180
7191
|
}
|
|
7181
7192
|
console.log();
|
|
@@ -7248,7 +7259,7 @@ ${preview}${more}`);
|
|
|
7248
7259
|
const BG = "\x1B[48;2;43;43;45m";
|
|
7249
7260
|
const CHEVRON = "\x1B[38;2;128;128;133m";
|
|
7250
7261
|
const TEXT = "\x1B[38;2;240;240;242m";
|
|
7251
|
-
const
|
|
7262
|
+
const RESET = "\x1B[0m";
|
|
7252
7263
|
const rawLines = text.split(`
|
|
7253
7264
|
`);
|
|
7254
7265
|
const wrappedLines = [];
|
|
@@ -7273,7 +7284,7 @@ ${preview}${more}`);
|
|
|
7273
7284
|
const formatted = wrappedLines.map((line, idx) => {
|
|
7274
7285
|
const prefix = idx === 0 ? `${CHEVRON} \u276F ` : `${CHEVRON} `;
|
|
7275
7286
|
const padLen = Math.max(0, contentWidth - line.length);
|
|
7276
|
-
return ` ${BG}${prefix}${TEXT}${line}${" ".repeat(padLen)}${
|
|
7287
|
+
return ` ${BG}${prefix}${TEXT}${line}${" ".repeat(padLen)}${RESET}`;
|
|
7277
7288
|
});
|
|
7278
7289
|
return formatted.join(`
|
|
7279
7290
|
`);
|
|
@@ -7391,15 +7402,15 @@ class InteractiveLineEditor {
|
|
|
7391
7402
|
}
|
|
7392
7403
|
async readLine() {
|
|
7393
7404
|
if (!process.stdin.isTTY) {
|
|
7394
|
-
return new Promise((
|
|
7405
|
+
return new Promise((resolve) => {
|
|
7395
7406
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
7396
7407
|
rl.question(this.promptSymbol, (answer) => {
|
|
7397
7408
|
rl.close();
|
|
7398
|
-
|
|
7409
|
+
resolve(answer);
|
|
7399
7410
|
});
|
|
7400
7411
|
});
|
|
7401
7412
|
}
|
|
7402
|
-
return new Promise((
|
|
7413
|
+
return new Promise((resolve) => {
|
|
7403
7414
|
let buffer = "";
|
|
7404
7415
|
let cursor = 0;
|
|
7405
7416
|
let selectedIndex = 0;
|
|
@@ -7486,26 +7497,26 @@ class InteractiveLineEditor {
|
|
|
7486
7497
|
const visibleMatches = slashMatches.slice(scrollTop, scrollTop + maxVisible);
|
|
7487
7498
|
const menuLines = [];
|
|
7488
7499
|
const rule = "\u2500".repeat(BOX_WIDTH);
|
|
7489
|
-
const
|
|
7500
|
+
const RULE_COLOR = "\x1B[38;2;80;80;88m";
|
|
7490
7501
|
const ACTIVE_COLOR = "\x1B[38;2;225;225;225m";
|
|
7491
7502
|
const INACTIVE_COLOR = "\x1B[38;2;139;139;144m";
|
|
7492
|
-
const
|
|
7493
|
-
menuLines.push(` ${
|
|
7503
|
+
const RESET = "\x1B[0m";
|
|
7504
|
+
menuLines.push(` ${RULE_COLOR}${rule}${RESET}`);
|
|
7494
7505
|
const maxDescLen = Math.max(10, BOX_WIDTH - 22);
|
|
7495
7506
|
for (let i = 0;i < visibleMatches.length; i++) {
|
|
7496
7507
|
const cmd = visibleMatches[i];
|
|
7497
7508
|
const actualIdx = scrollTop + i;
|
|
7498
7509
|
const isSelected = actualIdx === selectedIndex;
|
|
7499
|
-
const marker = isSelected ? `${ACTIVE_COLOR}\u276F${
|
|
7510
|
+
const marker = isSelected ? `${ACTIVE_COLOR}\u276F${RESET}` : " ";
|
|
7500
7511
|
const rawName = cmd.name.padEnd(16).slice(0, 16);
|
|
7501
7512
|
const rawDesc = cmd.description.length > maxDescLen ? cmd.description.slice(0, maxDescLen - 3) + "..." : cmd.description;
|
|
7502
7513
|
if (isSelected) {
|
|
7503
|
-
menuLines.push(` ${marker} \x1B[1m${ACTIVE_COLOR}${rawName}${
|
|
7514
|
+
menuLines.push(` ${marker} \x1B[1m${ACTIVE_COLOR}${rawName}${RESET} \x1B[1m${ACTIVE_COLOR}${rawDesc}${RESET}`);
|
|
7504
7515
|
} else {
|
|
7505
|
-
menuLines.push(` ${marker} ${INACTIVE_COLOR}${rawName}${
|
|
7516
|
+
menuLines.push(` ${marker} ${INACTIVE_COLOR}${rawName}${RESET} ${INACTIVE_COLOR}${rawDesc}${RESET}`);
|
|
7506
7517
|
}
|
|
7507
7518
|
}
|
|
7508
|
-
menuLines.push(` ${
|
|
7519
|
+
menuLines.push(` ${RULE_COLOR}${rule}${RESET}`);
|
|
7509
7520
|
for (const line of menuLines) {
|
|
7510
7521
|
frame += `
|
|
7511
7522
|
\x1B[2K${line}`;
|
|
@@ -7549,8 +7560,8 @@ class InteractiveLineEditor {
|
|
|
7549
7560
|
}
|
|
7550
7561
|
menuRows = menuLines.length;
|
|
7551
7562
|
} else {
|
|
7552
|
-
const
|
|
7553
|
-
const bottomRule = ` ${
|
|
7563
|
+
const RULE_COLOR = "\x1B[38;2;60;60;68m";
|
|
7564
|
+
const bottomRule = ` ${RULE_COLOR}${getRule()}\x1B[0m`;
|
|
7554
7565
|
const modeLine = this.getModeLine();
|
|
7555
7566
|
frame += `
|
|
7556
7567
|
\x1B[2K${bottomRule}
|
|
@@ -7604,7 +7615,7 @@ class InteractiveLineEditor {
|
|
|
7604
7615
|
try {
|
|
7605
7616
|
process.stdout.write(cleanupFrame);
|
|
7606
7617
|
} catch {}
|
|
7607
|
-
|
|
7618
|
+
resolve(result);
|
|
7608
7619
|
};
|
|
7609
7620
|
const onKeypress = (_str, key) => {
|
|
7610
7621
|
if (!key)
|
|
@@ -7792,23 +7803,23 @@ async function promptChoice(config) {
|
|
|
7792
7803
|
const def = choices[defaultIndex] || choices[0];
|
|
7793
7804
|
return def ? def.value : "";
|
|
7794
7805
|
}
|
|
7795
|
-
return new Promise((
|
|
7806
|
+
return new Promise((resolve) => {
|
|
7796
7807
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
7797
|
-
const promptText = ` ${message} (${choices.map((
|
|
7808
|
+
const promptText = ` ${message} (${choices.map((c2) => `[${c2.key}] ${c2.label}`).join(", ")}): `;
|
|
7798
7809
|
rl.question(promptText, (answer) => {
|
|
7799
7810
|
rl.close();
|
|
7800
7811
|
const trimmed = answer.trim().toLowerCase();
|
|
7801
|
-
const match = choices.find((
|
|
7812
|
+
const match = choices.find((c2) => c2.key.toLowerCase() === trimmed);
|
|
7802
7813
|
if (match) {
|
|
7803
|
-
|
|
7814
|
+
resolve(match.value);
|
|
7804
7815
|
} else {
|
|
7805
7816
|
const def = choices[defaultIndex] || choices[0];
|
|
7806
|
-
|
|
7817
|
+
resolve(def ? def.value : "");
|
|
7807
7818
|
}
|
|
7808
7819
|
});
|
|
7809
7820
|
});
|
|
7810
7821
|
}
|
|
7811
|
-
return new Promise((
|
|
7822
|
+
return new Promise((resolve) => {
|
|
7812
7823
|
let selectedIndex = defaultIndex;
|
|
7813
7824
|
if (selectedIndex < 0 || selectedIndex >= choices.length)
|
|
7814
7825
|
selectedIndex = 0;
|
|
@@ -7835,7 +7846,7 @@ async function promptChoice(config) {
|
|
|
7835
7846
|
ensureRawMode(wasRaw);
|
|
7836
7847
|
process.stdout.write(`\r\x1B[1A\r\x1B[2K ${style.bold(message)} ${style.cyan(`[${confirmedChoice.key}] ${confirmedChoice.label}`)}
|
|
7837
7848
|
\r\x1B[2K`);
|
|
7838
|
-
|
|
7849
|
+
resolve(confirmedChoice.value);
|
|
7839
7850
|
};
|
|
7840
7851
|
const onKeypress = (_str, key) => {
|
|
7841
7852
|
if (!key)
|
|
@@ -7857,7 +7868,7 @@ async function promptChoice(config) {
|
|
|
7857
7868
|
}
|
|
7858
7869
|
const char = _str ? _str.toLowerCase() : key.name ? key.name.toLowerCase() : "";
|
|
7859
7870
|
if (char) {
|
|
7860
|
-
const directMatch = choices.find((
|
|
7871
|
+
const directMatch = choices.find((c2) => c2.key.toLowerCase() === char);
|
|
7861
7872
|
if (directMatch) {
|
|
7862
7873
|
cleanup(directMatch);
|
|
7863
7874
|
return;
|
|
@@ -7880,28 +7891,28 @@ async function promptToolApproval(params) {
|
|
|
7880
7891
|
const FG = "\x1B[38;2;225;225;225m";
|
|
7881
7892
|
const MUTED = "\x1B[38;2;139;139;144m";
|
|
7882
7893
|
const DIM = "\x1B[38;2;108;108;108m";
|
|
7883
|
-
const
|
|
7894
|
+
const RESET = "\x1B[0m";
|
|
7884
7895
|
console.log();
|
|
7885
|
-
console.log(` ${BORDER} ${FG}${title}${
|
|
7886
|
-
console.log(` ${BORDER} ${MUTED}${command}${
|
|
7896
|
+
console.log(` ${BORDER} ${FG}${title}${RESET}`);
|
|
7897
|
+
console.log(` ${BORDER} ${MUTED}${command}${RESET}`);
|
|
7887
7898
|
console.log(` ${BORDER}`);
|
|
7888
7899
|
const renderCard = (selected) => {
|
|
7889
7900
|
for (let i = 0;i < options.length; i++) {
|
|
7890
7901
|
const opt = options[i];
|
|
7891
7902
|
const active = i === selected;
|
|
7892
|
-
const radio = active ? `${FG}(\u25CF)${
|
|
7893
|
-
const num = `${FG}${i + 1}${
|
|
7894
|
-
const label = active ? `\x1B[1m${FG}${opt.label}${
|
|
7903
|
+
const radio = active ? `${FG}(\u25CF)${RESET}` : `${DIM}(\u25CB)${RESET}`;
|
|
7904
|
+
const num = `${FG}${i + 1}${RESET}`;
|
|
7905
|
+
const label = active ? `\x1B[1m${FG}${opt.label}${RESET}` : `${MUTED}${opt.label}${RESET}`;
|
|
7895
7906
|
console.log(` ${BORDER} ${num} ${radio} ${label}`);
|
|
7896
7907
|
}
|
|
7897
7908
|
console.log(` ${BORDER}`);
|
|
7898
|
-
console.log(` ${FG}${selected + 1}/${options.length}${
|
|
7909
|
+
console.log(` ${FG}${selected + 1}/${options.length}${RESET}${DIM}:select \u2502 ${FG}Ctrl+o${RESET}${DIM}:yolo \u2502 ${FG}Ctrl+c${RESET}${DIM}:cancel${RESET}`);
|
|
7899
7910
|
};
|
|
7900
7911
|
if (!process.stdin.isTTY || false || !process.stdin.readable) {
|
|
7901
7912
|
renderCard(1);
|
|
7902
7913
|
return "yes";
|
|
7903
7914
|
}
|
|
7904
|
-
return new Promise((
|
|
7915
|
+
return new Promise((resolve) => {
|
|
7905
7916
|
let selectedIndex = 1;
|
|
7906
7917
|
const wasRaw = process.stdin.isRaw ?? false;
|
|
7907
7918
|
ensureRawMode(true);
|
|
@@ -7916,7 +7927,7 @@ async function promptToolApproval(params) {
|
|
|
7916
7927
|
}
|
|
7917
7928
|
ensureRawMode(wasRaw);
|
|
7918
7929
|
console.log();
|
|
7919
|
-
|
|
7930
|
+
resolve(val);
|
|
7920
7931
|
};
|
|
7921
7932
|
const onKeypress = (_str, key) => {
|
|
7922
7933
|
if (!key)
|
|
@@ -7999,7 +8010,7 @@ async function promptUserQuestion(params) {
|
|
|
7999
8010
|
if (!process.stdin.isTTY || false || !process.stdin.readable) {
|
|
8000
8011
|
return options[0] || "yes";
|
|
8001
8012
|
}
|
|
8002
|
-
return new Promise((
|
|
8013
|
+
return new Promise((resolve) => {
|
|
8003
8014
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
8004
8015
|
const promptLabel = options.length > 0 ? `Select [1-${options.length}] or type custom response: ` : `Your response: `;
|
|
8005
8016
|
rl.question(` ${style.bold(promptLabel)}`, (answer) => {
|
|
@@ -8009,7 +8020,7 @@ async function promptUserQuestion(params) {
|
|
|
8009
8020
|
const fallback = options[0] || "";
|
|
8010
8021
|
console.log(style.dim(` \u21B3 Default: ${fallback || "(empty)"}
|
|
8011
8022
|
`));
|
|
8012
|
-
|
|
8023
|
+
resolve(fallback);
|
|
8013
8024
|
return;
|
|
8014
8025
|
}
|
|
8015
8026
|
const num = parseInt(trimmed, 10);
|
|
@@ -8017,26 +8028,26 @@ async function promptUserQuestion(params) {
|
|
|
8017
8028
|
const picked = options[num - 1];
|
|
8018
8029
|
console.log(style.green(` \u2714 Selected: ${picked}
|
|
8019
8030
|
`));
|
|
8020
|
-
|
|
8031
|
+
resolve(picked);
|
|
8021
8032
|
return;
|
|
8022
8033
|
}
|
|
8023
8034
|
if (options.length === 2) {
|
|
8024
8035
|
if (/^(y|yes)$/i.test(trimmed)) {
|
|
8025
8036
|
console.log(style.green(` \u2714 Selected: ${options[0]}
|
|
8026
8037
|
`));
|
|
8027
|
-
|
|
8038
|
+
resolve(options[0]);
|
|
8028
8039
|
return;
|
|
8029
8040
|
}
|
|
8030
8041
|
if (/^(n|no)$/i.test(trimmed)) {
|
|
8031
8042
|
console.log(style.green(` \u2714 Selected: ${options[1]}
|
|
8032
8043
|
`));
|
|
8033
|
-
|
|
8044
|
+
resolve(options[1]);
|
|
8034
8045
|
return;
|
|
8035
8046
|
}
|
|
8036
8047
|
}
|
|
8037
8048
|
console.log(style.green(` \u2714 Answer: ${trimmed}
|
|
8038
8049
|
`));
|
|
8039
|
-
|
|
8050
|
+
resolve(trimmed);
|
|
8040
8051
|
});
|
|
8041
8052
|
});
|
|
8042
8053
|
}
|
|
@@ -8065,7 +8076,7 @@ async function promptInteractiveList(config) {
|
|
|
8065
8076
|
`);
|
|
8066
8077
|
return { selectedIndex: -1, action: "close" };
|
|
8067
8078
|
}
|
|
8068
|
-
return new Promise((
|
|
8079
|
+
return new Promise((resolve) => {
|
|
8069
8080
|
let selectedIndex = Math.max(0, Math.min(defaultIndex, items.length - 1));
|
|
8070
8081
|
let scrollTop = 0;
|
|
8071
8082
|
let renderedLines = 0;
|
|
@@ -8155,7 +8166,7 @@ async function promptInteractiveList(config) {
|
|
|
8155
8166
|
unsubscribe = null;
|
|
8156
8167
|
}
|
|
8157
8168
|
ensureRawMode(wasRaw);
|
|
8158
|
-
|
|
8169
|
+
resolve(res);
|
|
8159
8170
|
};
|
|
8160
8171
|
const onKeypress = async (_str, key) => {
|
|
8161
8172
|
if (!key)
|
|
@@ -8866,52 +8877,52 @@ function runProjectInit(options = {}) {
|
|
|
8866
8877
|
};
|
|
8867
8878
|
}
|
|
8868
8879
|
function printInitSummary(result) {
|
|
8869
|
-
const
|
|
8880
|
+
const BOLD = "\x1B[1m";
|
|
8870
8881
|
const GREEN = "\x1B[38;2;120;220;140m";
|
|
8871
8882
|
const BRAND = "\x1B[38;2;217;119;87m";
|
|
8872
8883
|
const CYAN = "\x1B[38;2;125;207;255m";
|
|
8873
|
-
const
|
|
8874
|
-
const
|
|
8875
|
-
const
|
|
8884
|
+
const GRAY = "\x1B[38;2;148;148;148m";
|
|
8885
|
+
const WHITE = "\x1B[38;2;240;240;245m";
|
|
8886
|
+
const RESET = "\x1B[0m";
|
|
8876
8887
|
const { analysis, filePath, overwritten } = result;
|
|
8877
8888
|
console.log("");
|
|
8878
|
-
console.log(` ${GREEN}\u2713${
|
|
8879
|
-
console.log(` ${
|
|
8889
|
+
console.log(` ${GREEN}\u2713${RESET} ${BOLD}${WHITE}${overwritten ? "Updated" : "Created"} Project Instructions Document${RESET}`);
|
|
8890
|
+
console.log(` ${GRAY}Path: ${CYAN}${filePath}${RESET}`);
|
|
8880
8891
|
console.log("");
|
|
8881
|
-
console.log(` ${BRAND}\u250C\u2500 ${
|
|
8882
|
-
console.log(` ${BRAND}\u2502${
|
|
8892
|
+
console.log(` ${BRAND}\u250C\u2500 ${BOLD}Project Overview${RESET} ${BRAND}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${RESET}`);
|
|
8893
|
+
console.log(` ${BRAND}\u2502${RESET} ${BOLD}Project:${RESET} ${WHITE}${analysis.projectName}${RESET}`);
|
|
8883
8894
|
if (analysis.languages.length > 0) {
|
|
8884
|
-
console.log(` ${BRAND}\u2502${
|
|
8895
|
+
console.log(` ${BRAND}\u2502${RESET} ${BOLD}Languages:${RESET} ${analysis.languages.join(", ")}`);
|
|
8885
8896
|
}
|
|
8886
8897
|
if (analysis.packageManager) {
|
|
8887
|
-
console.log(` ${BRAND}\u2502${
|
|
8898
|
+
console.log(` ${BRAND}\u2502${RESET} ${BOLD}Package Manager:${RESET} ${analysis.packageManager}`);
|
|
8888
8899
|
}
|
|
8889
8900
|
if (analysis.frameworks.length > 0) {
|
|
8890
|
-
console.log(` ${BRAND}\u2502${
|
|
8901
|
+
console.log(` ${BRAND}\u2502${RESET} ${BOLD}Frameworks:${RESET} ${analysis.frameworks.join(", ")}`);
|
|
8891
8902
|
}
|
|
8892
|
-
console.log(` ${BRAND}\u2502${
|
|
8893
|
-
console.log(` ${BRAND}\u2502${
|
|
8903
|
+
console.log(` ${BRAND}\u2502${RESET}`);
|
|
8904
|
+
console.log(` ${BRAND}\u2502${RESET} ${BOLD}Detected Commands:${RESET}`);
|
|
8894
8905
|
if (analysis.commands.build) {
|
|
8895
|
-
console.log(` ${BRAND}\u2502${
|
|
8906
|
+
console.log(` ${BRAND}\u2502${RESET} \u2022 Build: ${CYAN}${analysis.commands.build}${RESET}`);
|
|
8896
8907
|
}
|
|
8897
8908
|
if (analysis.commands.test) {
|
|
8898
|
-
console.log(` ${BRAND}\u2502${
|
|
8909
|
+
console.log(` ${BRAND}\u2502${RESET} \u2022 Test: ${GREEN}${analysis.commands.test}${RESET}`);
|
|
8899
8910
|
}
|
|
8900
8911
|
if (analysis.commands.typecheck) {
|
|
8901
|
-
console.log(` ${BRAND}\u2502${
|
|
8912
|
+
console.log(` ${BRAND}\u2502${RESET} \u2022 Typecheck: ${CYAN}${analysis.commands.typecheck}${RESET}`);
|
|
8902
8913
|
}
|
|
8903
8914
|
if (analysis.commands.lint) {
|
|
8904
|
-
console.log(` ${BRAND}\u2502${
|
|
8915
|
+
console.log(` ${BRAND}\u2502${RESET} \u2022 Lint: ${CYAN}${analysis.commands.lint}${RESET}`);
|
|
8905
8916
|
}
|
|
8906
8917
|
if (analysis.commands.dev) {
|
|
8907
|
-
console.log(` ${BRAND}\u2502${
|
|
8918
|
+
console.log(` ${BRAND}\u2502${RESET} \u2022 Dev: ${CYAN}${analysis.commands.dev}${RESET}`);
|
|
8908
8919
|
}
|
|
8909
8920
|
if (Object.keys(analysis.commands).length === 0) {
|
|
8910
|
-
console.log(` ${BRAND}\u2502${
|
|
8921
|
+
console.log(` ${BRAND}\u2502${RESET} \u2022 ${GRAY}(No standard commands detected)${RESET}`);
|
|
8911
8922
|
}
|
|
8912
|
-
console.log(` ${BRAND}\u2502${
|
|
8913
|
-
console.log(` ${BRAND}\u2502${
|
|
8914
|
-
console.log(` ${BRAND}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${
|
|
8923
|
+
console.log(` ${BRAND}\u2502${RESET}`);
|
|
8924
|
+
console.log(` ${BRAND}\u2502${RESET} ${GRAY}AI agents will now automatically load AGENTS.md on every session.${RESET}`);
|
|
8925
|
+
console.log(` ${BRAND}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${RESET}`);
|
|
8915
8926
|
console.log("");
|
|
8916
8927
|
}
|
|
8917
8928
|
// src/cli/commands.ts
|
|
@@ -9097,10 +9108,10 @@ async function printHelp(ctx) {
|
|
|
9097
9108
|
console.log();
|
|
9098
9109
|
return;
|
|
9099
9110
|
}
|
|
9100
|
-
const items = AVAILABLE_SLASH_COMMANDS.map((
|
|
9101
|
-
id:
|
|
9102
|
-
label:
|
|
9103
|
-
description:
|
|
9111
|
+
const items = AVAILABLE_SLASH_COMMANDS.map((c) => ({
|
|
9112
|
+
id: c.name,
|
|
9113
|
+
label: c.name,
|
|
9114
|
+
description: c.description
|
|
9104
9115
|
}));
|
|
9105
9116
|
const res = await promptInteractiveList({
|
|
9106
9117
|
title: "\u26A1 Slash Commands Palette",
|
|
@@ -9132,9 +9143,9 @@ async function handleReasoningCommand(ctx, arg) {
|
|
|
9132
9143
|
} else {
|
|
9133
9144
|
ctx.repl.showReasoning = !ctx.repl.showReasoning;
|
|
9134
9145
|
}
|
|
9135
|
-
const
|
|
9146
|
+
const stateStr = ctx.repl.showReasoning ? style.green("Visible") : style.yellow("Hidden (default)");
|
|
9136
9147
|
console.log(`
|
|
9137
|
-
Reasoning display: [${
|
|
9148
|
+
Reasoning display: [${stateStr}]
|
|
9138
9149
|
`);
|
|
9139
9150
|
return;
|
|
9140
9151
|
}
|
|
@@ -9173,14 +9184,14 @@ async function handleModelSelection(ctx, modelArg) {
|
|
|
9173
9184
|
const headers = {};
|
|
9174
9185
|
if (apiKey)
|
|
9175
9186
|
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
9176
|
-
const
|
|
9177
|
-
const timeout = setTimeout(() =>
|
|
9178
|
-
const
|
|
9187
|
+
const controller = new AbortController;
|
|
9188
|
+
const timeout = setTimeout(() => controller.abort(), 1500);
|
|
9189
|
+
const res = await fetch(`${baseUrl}/models`, {
|
|
9179
9190
|
headers,
|
|
9180
|
-
signal:
|
|
9191
|
+
signal: controller.signal
|
|
9181
9192
|
}).finally(() => clearTimeout(timeout));
|
|
9182
|
-
if (
|
|
9183
|
-
const data = await
|
|
9193
|
+
if (res.ok) {
|
|
9194
|
+
const data = await res.json();
|
|
9184
9195
|
if (Array.isArray(data.data) && data.data.length > 0) {
|
|
9185
9196
|
models = data.data;
|
|
9186
9197
|
}
|
|
@@ -9269,8 +9280,8 @@ Direct login failed: ${directErr instanceof Error ? directErr.message : String(d
|
|
|
9269
9280
|
}
|
|
9270
9281
|
}
|
|
9271
9282
|
function printWhoami() {
|
|
9272
|
-
const
|
|
9273
|
-
const creds =
|
|
9283
|
+
const store = new CredentialsStore;
|
|
9284
|
+
const creds = store.load();
|
|
9274
9285
|
console.log();
|
|
9275
9286
|
if (!creds || !creds.accessToken) {
|
|
9276
9287
|
console.log(style.yellow(" Not logged in."));
|
|
@@ -9343,11 +9354,11 @@ async function handleRolesCommand(ctx, roleArg) {
|
|
|
9343
9354
|
return;
|
|
9344
9355
|
}
|
|
9345
9356
|
const items = roles.map((r) => {
|
|
9346
|
-
const
|
|
9357
|
+
const tools = r.allowedToolNames ? r.allowedToolNames.join(", ") : "all tools";
|
|
9347
9358
|
return {
|
|
9348
9359
|
id: r.name,
|
|
9349
9360
|
label: r.name,
|
|
9350
|
-
description: `${r.description} \xB7 [${
|
|
9361
|
+
description: `${r.description} \xB7 [${tools}]`,
|
|
9351
9362
|
badge: r.name === "default" ? "primary" : undefined
|
|
9352
9363
|
};
|
|
9353
9364
|
});
|
|
@@ -9367,12 +9378,12 @@ async function handleRolesCommand(ctx, roleArg) {
|
|
|
9367
9378
|
function displayRoleDetails(role) {
|
|
9368
9379
|
const boxWidth = Math.min(process.stdout.columns ?? 80, 75);
|
|
9369
9380
|
const border = "\u2500".repeat(Math.max(10, boxWidth - role.name.length - 16));
|
|
9370
|
-
const
|
|
9381
|
+
const tools = role.allowedToolNames ? role.allowedToolNames.join(", ") : "all tools";
|
|
9371
9382
|
const nicks = role.nicknameCandidates ? role.nicknameCandidates.join(", ") : "none";
|
|
9372
9383
|
console.log();
|
|
9373
9384
|
console.log(` ${style.cyan("\u250C\u2500\u2500")} ${style.bold(`Role: ${role.name}`)} ${style.cyan(border)}`);
|
|
9374
9385
|
console.log(` ${style.cyan("\u2502")} ${style.bold("Description:")} ${role.description}`);
|
|
9375
|
-
console.log(` ${style.cyan("\u2502")} ${style.bold("Allowed Tools:")} ${style.dim(`[${
|
|
9386
|
+
console.log(` ${style.cyan("\u2502")} ${style.bold("Allowed Tools:")} ${style.dim(`[${tools}]`)}`);
|
|
9376
9387
|
console.log(` ${style.cyan("\u2502")} ${style.bold("Nicknames:")} ${style.dim(`[${nicks}]`)}`);
|
|
9377
9388
|
console.log(` ${style.cyan("\u2502")}`);
|
|
9378
9389
|
console.log(` ${style.cyan("\u2502")} ${style.bold("System Prompt:")}`);
|
|
@@ -9390,9 +9401,9 @@ function printRoles(ctx) {
|
|
|
9390
9401
|
console.log();
|
|
9391
9402
|
console.log(style.bold(" Configured Agent Roles:"));
|
|
9392
9403
|
for (const r of roles) {
|
|
9393
|
-
const
|
|
9404
|
+
const tools = r.allowedToolNames ? r.allowedToolNames.join(", ") : "all tools";
|
|
9394
9405
|
console.log(` \u2022 ${style.cyan(r.name)}: ${r.description}`);
|
|
9395
|
-
console.log(` ${style.dim(`Tools: [${
|
|
9406
|
+
console.log(` ${style.dim(`Tools: [${tools}]`)}`);
|
|
9396
9407
|
if (r.nicknameCandidates) {
|
|
9397
9408
|
console.log(` ${style.dim(`Nicknames: [${r.nicknameCandidates.join(", ")}]`)}`);
|
|
9398
9409
|
}
|
|
@@ -9567,19 +9578,19 @@ async function handleSkillsCommand(ctx, args) {
|
|
|
9567
9578
|
`);
|
|
9568
9579
|
}
|
|
9569
9580
|
function printMemories(ctx) {
|
|
9570
|
-
const
|
|
9571
|
-
if (!
|
|
9581
|
+
const store = ctx.memoryStore;
|
|
9582
|
+
if (!store) {
|
|
9572
9583
|
console.log(style.yellow(`
|
|
9573
9584
|
Memory store not active.
|
|
9574
9585
|
`));
|
|
9575
9586
|
return;
|
|
9576
9587
|
}
|
|
9577
9588
|
const cwd = ctx.session.cwd;
|
|
9578
|
-
const memoryDir =
|
|
9579
|
-
const topics =
|
|
9580
|
-
const indexContent =
|
|
9581
|
-
const
|
|
9582
|
-
const
|
|
9589
|
+
const memoryDir = store.getProjectMemoryDir(cwd);
|
|
9590
|
+
const topics = store.listProjectMemories(cwd);
|
|
9591
|
+
const indexContent = store.loadMemoryIndex(cwd);
|
|
9592
|
+
const BOLD = "\x1B[1m";
|
|
9593
|
+
const RESET = "\x1B[0m";
|
|
9583
9594
|
const DIM = "\x1B[2m";
|
|
9584
9595
|
const CYAN = "\x1B[38;2;120;190;255m";
|
|
9585
9596
|
const GREEN = "\x1B[38;2;140;220;140m";
|
|
@@ -9601,19 +9612,19 @@ function printMemories(ctx) {
|
|
|
9601
9612
|
}
|
|
9602
9613
|
};
|
|
9603
9614
|
console.log();
|
|
9604
|
-
console.log(` ${
|
|
9605
|
-
console.log(` ${DIM}Directory: ${memoryDir}${
|
|
9606
|
-
console.log(` ${DIM}Status: ${GREEN}Active (Loaded into turn context \u2264200 lines)${
|
|
9615
|
+
console.log(` ${BOLD}\uD83E\uDDE0 Project Auto-Memory Bank${RESET}`);
|
|
9616
|
+
console.log(` ${DIM}Directory: ${memoryDir}${RESET}`);
|
|
9617
|
+
console.log(` ${DIM}Status: ${GREEN}Active (Loaded into turn context \u2264200 lines)${RESET}`);
|
|
9607
9618
|
console.log();
|
|
9608
9619
|
if (topics.length === 0) {
|
|
9609
|
-
console.log(` ${DIM}No persistent topic memories saved for this project yet.${
|
|
9610
|
-
console.log(` ${DIM}As you work, Pikaa automatically records user preferences, feedback, and project context.${
|
|
9620
|
+
console.log(` ${DIM}No persistent topic memories saved for this project yet.${RESET}`);
|
|
9621
|
+
console.log(` ${DIM}As you work, Pikaa automatically records user preferences, feedback, and project context.${RESET}`);
|
|
9611
9622
|
} else {
|
|
9612
|
-
console.log(` ${
|
|
9623
|
+
console.log(` ${BOLD}Learned Memory Topics (${topics.length}):${RESET}`);
|
|
9613
9624
|
for (const t of topics) {
|
|
9614
9625
|
const color = getCategoryColor(t.type);
|
|
9615
|
-
console.log(` \u2022 ${color}[${t.type}]${
|
|
9616
|
-
`)[0]}${
|
|
9626
|
+
console.log(` \u2022 ${color}[${t.type}]${RESET} ${BOLD}${t.name}${RESET}: ${DIM}${t.description || t.content.split(`
|
|
9627
|
+
`)[0]}${RESET}`);
|
|
9617
9628
|
}
|
|
9618
9629
|
}
|
|
9619
9630
|
console.log();
|
|
@@ -10045,51 +10056,51 @@ async function handleMcpCommand(ctx, args) {
|
|
|
10045
10056
|
}
|
|
10046
10057
|
function printReleaseNotes() {
|
|
10047
10058
|
const version = getCliVersion({ prefix: true });
|
|
10048
|
-
const
|
|
10049
|
-
const
|
|
10050
|
-
const
|
|
10051
|
-
const
|
|
10052
|
-
const
|
|
10053
|
-
function
|
|
10059
|
+
const ROSE = "\x1B[38;2;205;105;74m";
|
|
10060
|
+
const WHITE = "\x1B[38;2;255;255;255m";
|
|
10061
|
+
const GRAY = "\x1B[38;2;148;148;148m";
|
|
10062
|
+
const BOLD = "\x1B[1m";
|
|
10063
|
+
const RESET = "\x1B[0m";
|
|
10064
|
+
function stripAnsi(str) {
|
|
10054
10065
|
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
10055
10066
|
}
|
|
10056
10067
|
function padLine(str, width) {
|
|
10057
|
-
const vis =
|
|
10068
|
+
const vis = stripAnsi(str);
|
|
10058
10069
|
return str + " ".repeat(Math.max(0, width - vis.length));
|
|
10059
10070
|
}
|
|
10060
10071
|
const totalInnerWidth = 74;
|
|
10061
10072
|
const contentLines = [
|
|
10062
10073
|
"",
|
|
10063
|
-
" " +
|
|
10064
|
-
" " +
|
|
10074
|
+
" " + BOLD + WHITE + "\uD83D\uDE80 What's New in " + version + " (Latest)" + RESET,
|
|
10075
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Persistent Default AI Model" + RESET + ": Switch via " + ROSE + "/model" + RESET + " and save",
|
|
10065
10076
|
" preference across sessions in ~/.pikaa/credentials.json.",
|
|
10066
|
-
" " +
|
|
10077
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Real-time Git Branch Detection" + RESET + ": Header displays active branch",
|
|
10067
10078
|
" (\uE0A0 main) alongside user subscription tier (Groupy Pro / Max).",
|
|
10068
|
-
" " +
|
|
10079
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Claude Code Terminal UI Parity" + RESET + ": Authentic pixel emblem, fieldset",
|
|
10069
10080
|
" header box, user prompt badge pills, and streaming responses.",
|
|
10070
|
-
" " +
|
|
10081
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Autonomous Sub-Agents & Roles" + RESET + ": Multi-agent spawner with roles",
|
|
10071
10082
|
" (Pikaa, Heca, Bankli, Moli) and cryptographic action provenance.",
|
|
10072
|
-
" " +
|
|
10083
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Model Context Protocol (MCP)" + RESET + ": Connect stdio & SSE servers with",
|
|
10073
10084
|
" multi-config auto-discovery, tool hot-reloads, and ping tests.",
|
|
10074
|
-
" " +
|
|
10085
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Isolated Git Worktrees" + RESET + ": Run risky tasks in isolated worktree",
|
|
10075
10086
|
" branches without dirtying your main workspace (/worktrees).",
|
|
10076
|
-
" " +
|
|
10087
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + BOLD + "Strix-Inspired Security Auditor" + RESET + ": Automated scanner for exposed",
|
|
10077
10088
|
" secrets, eval(), and SQL injection vulnerabilities (/security).",
|
|
10078
10089
|
"",
|
|
10079
|
-
" " +
|
|
10080
|
-
" " +
|
|
10081
|
-
" " +
|
|
10082
|
-
" " +
|
|
10090
|
+
" " + BOLD + WHITE + "\uD83D\uDCE6 Previous Highlights (v0.3.0 - v0.3.1)" + RESET,
|
|
10091
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + "Unified CI/CD Pipeline" + RESET + ": Single automated release packager on merge.",
|
|
10092
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + "Interactive Question Flow" + RESET + ": Selectable multiple-choice dialogs.",
|
|
10093
|
+
" " + ROSE + "\u2022" + RESET + " " + WHITE + "Persistent Memory Store" + RESET + ": Learned user preferences in markdown.",
|
|
10083
10094
|
"",
|
|
10084
|
-
" " +
|
|
10095
|
+
" " + GRAY + "Tip: Type " + ROSE + "/help" + GRAY + " to view all available commands." + RESET
|
|
10085
10096
|
];
|
|
10086
10097
|
const topDashes = Math.max(2, totalInnerWidth - (15 + version.length + 14));
|
|
10087
10098
|
console.log("");
|
|
10088
|
-
console.log(" " +
|
|
10099
|
+
console.log(" " + ROSE + "\u250C\u2500 " + ROSE + BOLD + "Groupy Code Release Notes" + RESET + " " + GRAY + version + RESET + " " + ROSE + "\u2500".repeat(topDashes) + "\u2510" + RESET);
|
|
10089
10100
|
for (const line of contentLines) {
|
|
10090
|
-
console.log(" " +
|
|
10101
|
+
console.log(" " + ROSE + "\u2502" + RESET + padLine(line, totalInnerWidth) + ROSE + "\u2502" + RESET);
|
|
10091
10102
|
}
|
|
10092
|
-
console.log(" " +
|
|
10103
|
+
console.log(" " + ROSE + "\u2514" + "\u2500".repeat(totalInnerWidth) + "\u2518" + RESET);
|
|
10093
10104
|
console.log("");
|
|
10094
10105
|
}
|
|
10095
10106
|
async function handleModeCommand(ctx, arg) {
|
|
@@ -10470,10 +10481,10 @@ function getUpdateCachePath() {
|
|
|
10470
10481
|
async function fetchLatestNpmVersion(packageName, timeoutMs = 1500) {
|
|
10471
10482
|
const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
|
|
10472
10483
|
try {
|
|
10473
|
-
const
|
|
10474
|
-
const timeout = setTimeout(() =>
|
|
10484
|
+
const controller = new AbortController;
|
|
10485
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
10475
10486
|
const response = await fetch(url, {
|
|
10476
|
-
signal:
|
|
10487
|
+
signal: controller.signal,
|
|
10477
10488
|
headers: {
|
|
10478
10489
|
Accept: "application/json",
|
|
10479
10490
|
"User-Agent": "pikaa-update-checker"
|
|
@@ -10703,9 +10714,9 @@ class CliRepl {
|
|
|
10703
10714
|
filesModified: Array.from(this.turnFilesModified)
|
|
10704
10715
|
});
|
|
10705
10716
|
if (this.turnDoneResolver) {
|
|
10706
|
-
const
|
|
10717
|
+
const resolve = this.turnDoneResolver;
|
|
10707
10718
|
this.turnDoneResolver = undefined;
|
|
10708
|
-
|
|
10719
|
+
resolve();
|
|
10709
10720
|
}
|
|
10710
10721
|
break;
|
|
10711
10722
|
case "Error":
|
|
@@ -10721,9 +10732,9 @@ class CliRepl {
|
|
|
10721
10732
|
console.error(style.red(`Error: ${msg.message}
|
|
10722
10733
|
`));
|
|
10723
10734
|
if (this.turnDoneResolver) {
|
|
10724
|
-
const
|
|
10735
|
+
const resolve = this.turnDoneResolver;
|
|
10725
10736
|
this.turnDoneResolver = undefined;
|
|
10726
|
-
|
|
10737
|
+
resolve();
|
|
10727
10738
|
}
|
|
10728
10739
|
break;
|
|
10729
10740
|
}
|
|
@@ -10793,16 +10804,16 @@ class CliRepl {
|
|
|
10793
10804
|
`));
|
|
10794
10805
|
this.isProcessing = false;
|
|
10795
10806
|
if (this.turnDoneResolver) {
|
|
10796
|
-
const
|
|
10807
|
+
const resolve = this.turnDoneResolver;
|
|
10797
10808
|
this.turnDoneResolver = undefined;
|
|
10798
|
-
|
|
10809
|
+
resolve();
|
|
10799
10810
|
}
|
|
10800
10811
|
}
|
|
10801
10812
|
}
|
|
10802
10813
|
}
|
|
10803
10814
|
});
|
|
10804
10815
|
while (!this.isClosed) {
|
|
10805
|
-
await new Promise((
|
|
10816
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
10806
10817
|
if (typeof Bun !== "undefined" && typeof Bun.gc === "function") {
|
|
10807
10818
|
try {
|
|
10808
10819
|
Bun.gc(false);
|
|
@@ -10838,8 +10849,8 @@ class CliRepl {
|
|
|
10838
10849
|
}
|
|
10839
10850
|
async submitTurn(text) {
|
|
10840
10851
|
try {
|
|
10841
|
-
const turnPromise = new Promise((
|
|
10842
|
-
this.turnDoneResolver =
|
|
10852
|
+
const turnPromise = new Promise((resolve) => {
|
|
10853
|
+
this.turnDoneResolver = resolve;
|
|
10843
10854
|
});
|
|
10844
10855
|
await this.session.submit({
|
|
10845
10856
|
type: "TurnInput",
|
|
@@ -10964,7 +10975,7 @@ async function main() {
|
|
|
10964
10975
|
apiKey: explicitApiKey,
|
|
10965
10976
|
defaultModel: model
|
|
10966
10977
|
});
|
|
10967
|
-
const
|
|
10978
|
+
const tools = createDefaultTools({ skillsLoader, memoryStore, worktreeManager });
|
|
10968
10979
|
const mcpManager = new McpManager;
|
|
10969
10980
|
const candidateConfigs = [
|
|
10970
10981
|
mcpConfigFile,
|
|
@@ -10975,7 +10986,7 @@ async function main() {
|
|
|
10975
10986
|
if (existsSync24(cfg)) {
|
|
10976
10987
|
try {
|
|
10977
10988
|
await mcpManager.loadConfigFile(cfg);
|
|
10978
|
-
mcpManager.registerToolsIntoRouter(
|
|
10989
|
+
mcpManager.registerToolsIntoRouter(tools);
|
|
10979
10990
|
break;
|
|
10980
10991
|
} catch {}
|
|
10981
10992
|
}
|
|
@@ -10986,7 +10997,7 @@ async function main() {
|
|
|
10986
10997
|
session = storageManager.resumeSession(resumeThreadId, {
|
|
10987
10998
|
model,
|
|
10988
10999
|
cwd,
|
|
10989
|
-
tools
|
|
11000
|
+
tools,
|
|
10990
11001
|
skillsLoader,
|
|
10991
11002
|
memoryStore,
|
|
10992
11003
|
mcpManager,
|
|
@@ -11001,7 +11012,7 @@ async function main() {
|
|
|
11001
11012
|
session = new Session({
|
|
11002
11013
|
model,
|
|
11003
11014
|
cwd,
|
|
11004
|
-
tools
|
|
11015
|
+
tools,
|
|
11005
11016
|
skillsLoader,
|
|
11006
11017
|
memoryStore,
|
|
11007
11018
|
mcpManager,
|
|
@@ -11010,7 +11021,7 @@ async function main() {
|
|
|
11010
11021
|
storageManager.bindSession(session, role);
|
|
11011
11022
|
}
|
|
11012
11023
|
const spawner = new AgentSpawner(session);
|
|
11013
|
-
registerMultiAgentTools(
|
|
11024
|
+
registerMultiAgentTools(tools, spawner);
|
|
11014
11025
|
if (singlePrompt) {
|
|
11015
11026
|
if (singlePrompt.startsWith("/") || singlePrompt.startsWith("security") || singlePrompt.startsWith("scan") || singlePrompt.startsWith("audit") || singlePrompt.startsWith("skills") || singlePrompt.startsWith("whoami") || singlePrompt.startsWith("roles") || singlePrompt.startsWith("mcp")) {
|
|
11016
11027
|
const slashInput = singlePrompt.startsWith("/") ? singlePrompt : `/${singlePrompt}`;
|
|
@@ -11115,8 +11126,8 @@ Direct login failed: ${directErr instanceof Error ? directErr.message : String(d
|
|
|
11115
11126
|
}
|
|
11116
11127
|
}
|
|
11117
11128
|
}
|
|
11118
|
-
function printWhoami2(
|
|
11119
|
-
const creds =
|
|
11129
|
+
function printWhoami2(store) {
|
|
11130
|
+
const creds = store.load();
|
|
11120
11131
|
console.log();
|
|
11121
11132
|
if (!creds || !creds.accessToken) {
|
|
11122
11133
|
console.log(style.yellow("Not logged in."));
|
|
@@ -11244,8 +11255,8 @@ function printSkillsList(loader, cwd) {
|
|
|
11244
11255
|
}
|
|
11245
11256
|
console.log();
|
|
11246
11257
|
}
|
|
11247
|
-
function printMemoriesList(
|
|
11248
|
-
const memories =
|
|
11258
|
+
function printMemoriesList(store, cwd) {
|
|
11259
|
+
const memories = store.getAllMemories(cwd);
|
|
11249
11260
|
console.log();
|
|
11250
11261
|
if (memories.length === 0) {
|
|
11251
11262
|
console.log(style.dim("No memories recorded yet."));
|