@hasna/oldpal 0.1.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.oldpal/OLDPAL.md +89 -0
- package/dist/.oldpal/skills/skill-brainstorm/SKILL.md +30 -0
- package/dist/.oldpal/skills/skill-draft/SKILL.md +30 -0
- package/dist/.oldpal/skills/skill-research/SKILL.md +27 -0
- package/dist/.oldpal/skills/skill-summarize/SKILL.md +25 -0
- package/dist/index.js +769 -218
- package/dist/index.js.map +17 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20450,12 +20450,12 @@ var exports_anthropic = {};
|
|
|
20450
20450
|
__export(exports_anthropic, {
|
|
20451
20451
|
AnthropicClient: () => AnthropicClient
|
|
20452
20452
|
});
|
|
20453
|
-
import { readFileSync as readFileSync2, existsSync as
|
|
20454
|
-
import { homedir as
|
|
20455
|
-
import { join as
|
|
20453
|
+
import { readFileSync as readFileSync2, existsSync as existsSync5 } from "fs";
|
|
20454
|
+
import { homedir as homedir6 } from "os";
|
|
20455
|
+
import { join as join7 } from "path";
|
|
20456
20456
|
function loadApiKeyFromSecrets() {
|
|
20457
|
-
const secretsPath =
|
|
20458
|
-
if (
|
|
20457
|
+
const secretsPath = join7(homedir6(), ".secrets");
|
|
20458
|
+
if (existsSync5(secretsPath)) {
|
|
20459
20459
|
try {
|
|
20460
20460
|
const content = readFileSync2(secretsPath, "utf-8");
|
|
20461
20461
|
const match = content.match(/export\s+ANTHROPIC_API_KEY\s*=\s*["']?([^"'\n]+)["']?/);
|
|
@@ -20543,6 +20543,7 @@ class AnthropicClient {
|
|
|
20543
20543
|
}
|
|
20544
20544
|
convertMessages(messages) {
|
|
20545
20545
|
const result = [];
|
|
20546
|
+
const pendingToolUseIds = new Set;
|
|
20546
20547
|
for (const msg of messages) {
|
|
20547
20548
|
if (msg.role === "system")
|
|
20548
20549
|
continue;
|
|
@@ -20558,16 +20559,20 @@ class AnthropicClient {
|
|
|
20558
20559
|
name: toolCall.name,
|
|
20559
20560
|
input: toolCall.input
|
|
20560
20561
|
});
|
|
20562
|
+
pendingToolUseIds.add(toolCall.id);
|
|
20561
20563
|
}
|
|
20562
20564
|
}
|
|
20563
20565
|
if (msg.toolResults) {
|
|
20564
20566
|
for (const toolResult of msg.toolResults) {
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
|
|
20567
|
+
if (pendingToolUseIds.has(toolResult.toolCallId)) {
|
|
20568
|
+
content.push({
|
|
20569
|
+
type: "tool_result",
|
|
20570
|
+
tool_use_id: toolResult.toolCallId,
|
|
20571
|
+
content: toolResult.content,
|
|
20572
|
+
is_error: toolResult.isError
|
|
20573
|
+
});
|
|
20574
|
+
pendingToolUseIds.delete(toolResult.toolCallId);
|
|
20575
|
+
}
|
|
20571
20576
|
}
|
|
20572
20577
|
}
|
|
20573
20578
|
if (content.length > 0) {
|
|
@@ -28589,7 +28594,7 @@ var import_react20 = __toESM(require_react(), 1);
|
|
|
28589
28594
|
// node_modules/.pnpm/ink@5.2.1_@types+react@18.3.27_react-devtools-core@4.28.5_react@18.3.1/node_modules/ink/build/hooks/use-focus-manager.js
|
|
28590
28595
|
var import_react21 = __toESM(require_react(), 1);
|
|
28591
28596
|
// packages/terminal/src/components/App.tsx
|
|
28592
|
-
var
|
|
28597
|
+
var import_react27 = __toESM(require_react(), 1);
|
|
28593
28598
|
// packages/shared/src/utils.ts
|
|
28594
28599
|
import { randomUUID } from "crypto";
|
|
28595
28600
|
function generateId() {
|
|
@@ -28702,11 +28707,25 @@ class AgentContext {
|
|
|
28702
28707
|
this.messages = [];
|
|
28703
28708
|
}
|
|
28704
28709
|
prune() {
|
|
28705
|
-
if (this.messages.length
|
|
28706
|
-
|
|
28707
|
-
const recentMessages = this.messages.filter((m) => m.role !== "system").slice(-(this.maxMessages - systemMessages.length));
|
|
28708
|
-
this.messages = [...systemMessages, ...recentMessages];
|
|
28710
|
+
if (this.messages.length <= this.maxMessages) {
|
|
28711
|
+
return;
|
|
28709
28712
|
}
|
|
28713
|
+
const systemMessages = this.messages.filter((m) => m.role === "system");
|
|
28714
|
+
const nonSystemMessages = this.messages.filter((m) => m.role !== "system");
|
|
28715
|
+
const targetCount = this.maxMessages - systemMessages.length;
|
|
28716
|
+
let recentMessages = nonSystemMessages.slice(-targetCount);
|
|
28717
|
+
while (recentMessages.length > 0 && recentMessages[0].toolResults) {
|
|
28718
|
+
const firstIndex = nonSystemMessages.indexOf(recentMessages[0]);
|
|
28719
|
+
if (firstIndex > 0) {
|
|
28720
|
+
recentMessages = nonSystemMessages.slice(firstIndex - 1);
|
|
28721
|
+
if (recentMessages.length > targetCount + 1) {
|
|
28722
|
+
recentMessages = recentMessages.slice(-(targetCount + 1));
|
|
28723
|
+
}
|
|
28724
|
+
} else {
|
|
28725
|
+
recentMessages = recentMessages.slice(1);
|
|
28726
|
+
}
|
|
28727
|
+
}
|
|
28728
|
+
this.messages = [...systemMessages, ...recentMessages];
|
|
28710
28729
|
}
|
|
28711
28730
|
export() {
|
|
28712
28731
|
return this.messages;
|
|
@@ -28770,7 +28789,6 @@ import { join } from "path";
|
|
|
28770
28789
|
class ConnectorBridge {
|
|
28771
28790
|
connectors = new Map;
|
|
28772
28791
|
async discover(connectorNames) {
|
|
28773
|
-
const discovered = [];
|
|
28774
28792
|
const names = connectorNames || [
|
|
28775
28793
|
"notion",
|
|
28776
28794
|
"googledrive",
|
|
@@ -28787,19 +28805,22 @@ class ConnectorBridge {
|
|
|
28787
28805
|
"openai",
|
|
28788
28806
|
"elevenlabs"
|
|
28789
28807
|
];
|
|
28790
|
-
|
|
28808
|
+
const results = await Promise.all(names.map(async (name) => {
|
|
28791
28809
|
const cli = `connect-${name}`;
|
|
28792
28810
|
try {
|
|
28793
|
-
const result = await Bun.$`which ${cli}`.quiet();
|
|
28811
|
+
const result = await Bun.$`which ${cli}`.quiet().nothrow();
|
|
28794
28812
|
if (result.exitCode !== 0)
|
|
28795
|
-
|
|
28813
|
+
return null;
|
|
28796
28814
|
} catch {
|
|
28797
|
-
|
|
28815
|
+
return null;
|
|
28798
28816
|
}
|
|
28799
|
-
|
|
28817
|
+
return this.discoverConnector(name, cli);
|
|
28818
|
+
}));
|
|
28819
|
+
const discovered = [];
|
|
28820
|
+
for (const connector of results) {
|
|
28800
28821
|
if (connector) {
|
|
28801
28822
|
discovered.push(connector);
|
|
28802
|
-
this.connectors.set(name, connector);
|
|
28823
|
+
this.connectors.set(connector.name, connector);
|
|
28803
28824
|
}
|
|
28804
28825
|
}
|
|
28805
28826
|
return discovered;
|
|
@@ -29368,35 +29389,260 @@ function parseDuckDuckGoResults(html, maxResults) {
|
|
|
29368
29389
|
return results;
|
|
29369
29390
|
}
|
|
29370
29391
|
|
|
29392
|
+
class CurlTool {
|
|
29393
|
+
static tool = {
|
|
29394
|
+
name: "curl",
|
|
29395
|
+
description: "Fetch content from a URL (like curl). Returns text content from web pages, JSON from APIs, etc.",
|
|
29396
|
+
parameters: {
|
|
29397
|
+
type: "object",
|
|
29398
|
+
properties: {
|
|
29399
|
+
url: {
|
|
29400
|
+
type: "string",
|
|
29401
|
+
description: "The URL to fetch"
|
|
29402
|
+
},
|
|
29403
|
+
method: {
|
|
29404
|
+
type: "string",
|
|
29405
|
+
description: "HTTP method (GET, POST, PUT, DELETE). Defaults to GET.",
|
|
29406
|
+
enum: ["GET", "POST", "PUT", "DELETE"],
|
|
29407
|
+
default: "GET"
|
|
29408
|
+
},
|
|
29409
|
+
headers: {
|
|
29410
|
+
type: "object",
|
|
29411
|
+
description: "Optional headers to send with the request"
|
|
29412
|
+
},
|
|
29413
|
+
body: {
|
|
29414
|
+
type: "string",
|
|
29415
|
+
description: "Request body for POST/PUT requests"
|
|
29416
|
+
}
|
|
29417
|
+
},
|
|
29418
|
+
required: ["url"]
|
|
29419
|
+
}
|
|
29420
|
+
};
|
|
29421
|
+
static executor = async (input) => {
|
|
29422
|
+
const url = input.url;
|
|
29423
|
+
const method = input.method || "GET";
|
|
29424
|
+
const headers = input.headers || {};
|
|
29425
|
+
const body = input.body;
|
|
29426
|
+
const timeout = 30000;
|
|
29427
|
+
try {
|
|
29428
|
+
const parsedUrl = new URL(url);
|
|
29429
|
+
const hostname = parsedUrl.hostname;
|
|
29430
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname.startsWith("192.168.") || hostname.startsWith("10.") || hostname.startsWith("172.")) {
|
|
29431
|
+
return "Error: Cannot fetch from local/private network addresses for security reasons";
|
|
29432
|
+
}
|
|
29433
|
+
const controller = new AbortController;
|
|
29434
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
29435
|
+
const response = await fetch(url, {
|
|
29436
|
+
method,
|
|
29437
|
+
signal: controller.signal,
|
|
29438
|
+
headers: {
|
|
29439
|
+
"User-Agent": "oldpal/1.0 (AI Assistant)",
|
|
29440
|
+
...headers
|
|
29441
|
+
},
|
|
29442
|
+
body: body && ["POST", "PUT"].includes(method) ? body : undefined
|
|
29443
|
+
});
|
|
29444
|
+
clearTimeout(timeoutId);
|
|
29445
|
+
const contentType = response.headers.get("content-type") || "";
|
|
29446
|
+
let responseBody;
|
|
29447
|
+
if (contentType.includes("application/json")) {
|
|
29448
|
+
try {
|
|
29449
|
+
const json = await response.json();
|
|
29450
|
+
responseBody = JSON.stringify(json, null, 2);
|
|
29451
|
+
} catch {
|
|
29452
|
+
responseBody = await response.text();
|
|
29453
|
+
}
|
|
29454
|
+
} else {
|
|
29455
|
+
responseBody = await response.text();
|
|
29456
|
+
if (contentType.includes("text/html")) {
|
|
29457
|
+
responseBody = extractReadableText(responseBody);
|
|
29458
|
+
}
|
|
29459
|
+
}
|
|
29460
|
+
const maxLength = 30000;
|
|
29461
|
+
if (responseBody.length > maxLength) {
|
|
29462
|
+
responseBody = responseBody.slice(0, maxLength) + `
|
|
29463
|
+
|
|
29464
|
+
[Content truncated...]`;
|
|
29465
|
+
}
|
|
29466
|
+
const statusLine = `HTTP ${response.status} ${response.statusText}`;
|
|
29467
|
+
return `${statusLine}
|
|
29468
|
+
|
|
29469
|
+
${responseBody || "(empty response)"}`;
|
|
29470
|
+
} catch (error) {
|
|
29471
|
+
if (error instanceof Error) {
|
|
29472
|
+
if (error.name === "AbortError") {
|
|
29473
|
+
return `Error: Request timed out after ${timeout}ms`;
|
|
29474
|
+
}
|
|
29475
|
+
return `Error: ${error.message}`;
|
|
29476
|
+
}
|
|
29477
|
+
return `Error: ${String(error)}`;
|
|
29478
|
+
}
|
|
29479
|
+
};
|
|
29480
|
+
}
|
|
29481
|
+
|
|
29371
29482
|
class WebTools {
|
|
29372
29483
|
static registerAll(registry) {
|
|
29373
29484
|
registry.register(WebFetchTool.tool, WebFetchTool.executor);
|
|
29374
29485
|
registry.register(WebSearchTool.tool, WebSearchTool.executor);
|
|
29486
|
+
registry.register(CurlTool.tool, CurlTool.executor);
|
|
29375
29487
|
}
|
|
29376
29488
|
}
|
|
29377
29489
|
|
|
29378
|
-
// packages/core/src/
|
|
29490
|
+
// packages/core/src/tools/image.ts
|
|
29491
|
+
import { existsSync as existsSync2, writeFileSync, unlinkSync } from "fs";
|
|
29492
|
+
import { tmpdir } from "os";
|
|
29379
29493
|
import { join as join3 } from "path";
|
|
29380
29494
|
import { homedir as homedir2 } from "os";
|
|
29495
|
+
async function getViuPath() {
|
|
29496
|
+
const locations = [
|
|
29497
|
+
"viu",
|
|
29498
|
+
join3(homedir2(), ".cargo", "bin", "viu"),
|
|
29499
|
+
"/usr/local/bin/viu",
|
|
29500
|
+
"/opt/homebrew/bin/viu"
|
|
29501
|
+
];
|
|
29502
|
+
for (const path of locations) {
|
|
29503
|
+
try {
|
|
29504
|
+
const result = await Bun.$`${path} --version`.quiet().nothrow();
|
|
29505
|
+
if (result.exitCode === 0) {
|
|
29506
|
+
return path;
|
|
29507
|
+
}
|
|
29508
|
+
} catch {
|
|
29509
|
+
continue;
|
|
29510
|
+
}
|
|
29511
|
+
}
|
|
29512
|
+
return null;
|
|
29513
|
+
}
|
|
29514
|
+
|
|
29515
|
+
class ImageDisplayTool {
|
|
29516
|
+
static tool = {
|
|
29517
|
+
name: "display_image",
|
|
29518
|
+
description: "Display an image in the terminal. Works with local files and URLs. Supports PNG, JPG, GIF, BMP, and other common formats.",
|
|
29519
|
+
parameters: {
|
|
29520
|
+
type: "object",
|
|
29521
|
+
properties: {
|
|
29522
|
+
path: {
|
|
29523
|
+
type: "string",
|
|
29524
|
+
description: "Path to the image file or URL to fetch"
|
|
29525
|
+
},
|
|
29526
|
+
width: {
|
|
29527
|
+
type: "number",
|
|
29528
|
+
description: "Width in characters (optional, defaults to terminal width)"
|
|
29529
|
+
},
|
|
29530
|
+
height: {
|
|
29531
|
+
type: "number",
|
|
29532
|
+
description: "Height in characters (optional)"
|
|
29533
|
+
}
|
|
29534
|
+
},
|
|
29535
|
+
required: ["path"]
|
|
29536
|
+
}
|
|
29537
|
+
};
|
|
29538
|
+
static executor = async (input) => {
|
|
29539
|
+
const imagePath = input.path;
|
|
29540
|
+
const width = input.width;
|
|
29541
|
+
const height = input.height;
|
|
29542
|
+
const viuPath = await getViuPath();
|
|
29543
|
+
if (!viuPath) {
|
|
29544
|
+
return "Error: viu is not installed. Install with: cargo install viu";
|
|
29545
|
+
}
|
|
29546
|
+
let localPath = imagePath;
|
|
29547
|
+
let tempFile = null;
|
|
29548
|
+
if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
|
|
29549
|
+
try {
|
|
29550
|
+
const response = await fetch(imagePath);
|
|
29551
|
+
if (!response.ok) {
|
|
29552
|
+
return `Error: Failed to fetch image: HTTP ${response.status}`;
|
|
29553
|
+
}
|
|
29554
|
+
const contentType = response.headers.get("content-type") || "";
|
|
29555
|
+
if (!contentType.startsWith("image/")) {
|
|
29556
|
+
return `Error: URL does not point to an image (content-type: ${contentType})`;
|
|
29557
|
+
}
|
|
29558
|
+
const buffer = await response.arrayBuffer();
|
|
29559
|
+
const ext = contentType.split("/")[1]?.split(";")[0] || "png";
|
|
29560
|
+
tempFile = join3(tmpdir(), `oldpal-image-${generateId()}.${ext}`);
|
|
29561
|
+
writeFileSync(tempFile, Buffer.from(buffer));
|
|
29562
|
+
localPath = tempFile;
|
|
29563
|
+
} catch (error) {
|
|
29564
|
+
return `Error: Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`;
|
|
29565
|
+
}
|
|
29566
|
+
}
|
|
29567
|
+
if (!existsSync2(localPath)) {
|
|
29568
|
+
return `Error: Image file not found: ${localPath}`;
|
|
29569
|
+
}
|
|
29570
|
+
try {
|
|
29571
|
+
const args = [];
|
|
29572
|
+
if (width) {
|
|
29573
|
+
args.push("-w", String(width));
|
|
29574
|
+
}
|
|
29575
|
+
if (height) {
|
|
29576
|
+
args.push("-h", String(height));
|
|
29577
|
+
}
|
|
29578
|
+
args.push(localPath);
|
|
29579
|
+
const result = await Bun.$`${viuPath} ${args}`.quiet().nothrow();
|
|
29580
|
+
if (result.exitCode !== 0) {
|
|
29581
|
+
const stderr = result.stderr.toString().trim();
|
|
29582
|
+
return `Error displaying image: ${stderr || "Unknown error"}`;
|
|
29583
|
+
}
|
|
29584
|
+
const output = result.stdout.toString();
|
|
29585
|
+
if (output) {
|
|
29586
|
+
process.stdout.write(output);
|
|
29587
|
+
}
|
|
29588
|
+
return `Image displayed: ${imagePath}${width ? ` (width: ${width})` : ""}${height ? ` (height: ${height})` : ""}`;
|
|
29589
|
+
} catch (error) {
|
|
29590
|
+
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
29591
|
+
} finally {
|
|
29592
|
+
if (tempFile && existsSync2(tempFile)) {
|
|
29593
|
+
try {
|
|
29594
|
+
unlinkSync(tempFile);
|
|
29595
|
+
} catch {}
|
|
29596
|
+
}
|
|
29597
|
+
}
|
|
29598
|
+
};
|
|
29599
|
+
}
|
|
29600
|
+
|
|
29601
|
+
class ImageTools {
|
|
29602
|
+
static registerAll(registry) {
|
|
29603
|
+
registry.register(ImageDisplayTool.tool, ImageDisplayTool.executor);
|
|
29604
|
+
}
|
|
29605
|
+
}
|
|
29606
|
+
|
|
29607
|
+
// packages/core/src/skills/loader.ts
|
|
29608
|
+
import { join as join4 } from "path";
|
|
29609
|
+
import { homedir as homedir3 } from "os";
|
|
29381
29610
|
var {Glob: Glob2 } = globalThis.Bun;
|
|
29382
29611
|
class SkillLoader {
|
|
29383
29612
|
skills = new Map;
|
|
29384
29613
|
async loadAll(projectDir = process.cwd()) {
|
|
29385
|
-
const userSkillsDir =
|
|
29614
|
+
const userSkillsDir = join4(homedir3(), ".oldpal", "skills");
|
|
29386
29615
|
await this.loadFromDirectory(userSkillsDir);
|
|
29387
|
-
const projectSkillsDir =
|
|
29616
|
+
const projectSkillsDir = join4(projectDir, ".oldpal", "skills");
|
|
29388
29617
|
await this.loadFromDirectory(projectSkillsDir);
|
|
29389
29618
|
const nestedGlob = new Glob2("**/.oldpal/skills/*/SKILL.md");
|
|
29390
29619
|
for await (const file of nestedGlob.scan({ cwd: projectDir })) {
|
|
29391
|
-
await this.loadSkillFile(
|
|
29620
|
+
await this.loadSkillFile(join4(projectDir, file));
|
|
29392
29621
|
}
|
|
29393
29622
|
}
|
|
29394
29623
|
async loadFromDirectory(dir) {
|
|
29395
29624
|
try {
|
|
29396
|
-
const
|
|
29397
|
-
|
|
29398
|
-
await
|
|
29625
|
+
const { stat } = await import("fs/promises");
|
|
29626
|
+
try {
|
|
29627
|
+
const stats = await stat(dir);
|
|
29628
|
+
if (!stats.isDirectory())
|
|
29629
|
+
return;
|
|
29630
|
+
} catch {
|
|
29631
|
+
return;
|
|
29632
|
+
}
|
|
29633
|
+
const filesToLoad = [];
|
|
29634
|
+
const skillPrefixGlob = new Glob2("skill-*/SKILL.md");
|
|
29635
|
+
for await (const file of skillPrefixGlob.scan({ cwd: dir })) {
|
|
29636
|
+
filesToLoad.push(join4(dir, file));
|
|
29637
|
+
}
|
|
29638
|
+
const regularGlob = new Glob2("*/SKILL.md");
|
|
29639
|
+
for await (const file of regularGlob.scan({ cwd: dir })) {
|
|
29640
|
+
const dirName = file.split("/")[0];
|
|
29641
|
+
if (!dirName.startsWith("skill-")) {
|
|
29642
|
+
filesToLoad.push(join4(dir, file));
|
|
29643
|
+
}
|
|
29399
29644
|
}
|
|
29645
|
+
await Promise.all(filesToLoad.map((file) => this.loadSkillFile(file)));
|
|
29400
29646
|
} catch {}
|
|
29401
29647
|
}
|
|
29402
29648
|
async loadSkillFile(filePath) {
|
|
@@ -29457,8 +29703,9 @@ class SkillLoader {
|
|
|
29457
29703
|
}
|
|
29458
29704
|
|
|
29459
29705
|
// packages/core/src/skills/executor.ts
|
|
29706
|
+
import { dirname as dirname2 } from "path";
|
|
29460
29707
|
class SkillExecutor {
|
|
29461
|
-
prepare(skill, args) {
|
|
29708
|
+
async prepare(skill, args) {
|
|
29462
29709
|
let content = skill.content;
|
|
29463
29710
|
content = substituteVariables(content, args);
|
|
29464
29711
|
if (!skill.content.includes("$ARGUMENTS") && args.length > 0) {
|
|
@@ -29466,15 +29713,28 @@ class SkillExecutor {
|
|
|
29466
29713
|
|
|
29467
29714
|
ARGUMENTS: ${args.join(" ")}`;
|
|
29468
29715
|
}
|
|
29469
|
-
content = this.executeDynamicContext(content);
|
|
29716
|
+
content = await this.executeDynamicContext(content, skill.filePath);
|
|
29470
29717
|
return content;
|
|
29471
29718
|
}
|
|
29472
|
-
executeDynamicContext(content) {
|
|
29473
|
-
const backtickPattern =
|
|
29719
|
+
async executeDynamicContext(content, skillFilePath) {
|
|
29720
|
+
const backtickPattern = /!\`([^`]+)\`/g;
|
|
29721
|
+
const matches = [...content.matchAll(backtickPattern)];
|
|
29722
|
+
if (matches.length === 0) {
|
|
29723
|
+
return content;
|
|
29724
|
+
}
|
|
29725
|
+
const skillDir = dirname2(skillFilePath);
|
|
29474
29726
|
let result = content;
|
|
29475
|
-
|
|
29476
|
-
|
|
29477
|
-
|
|
29727
|
+
for (const match of matches) {
|
|
29728
|
+
const fullMatch = match[0];
|
|
29729
|
+
const command = match[1];
|
|
29730
|
+
try {
|
|
29731
|
+
const output = await Bun.$`cd ${skillDir} && ${command}`.quiet().text();
|
|
29732
|
+
result = result.replace(fullMatch, output.trim());
|
|
29733
|
+
} catch (error) {
|
|
29734
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
29735
|
+
result = result.replace(fullMatch, `[Command failed: ${errorMsg}]`);
|
|
29736
|
+
}
|
|
29737
|
+
}
|
|
29478
29738
|
return result;
|
|
29479
29739
|
}
|
|
29480
29740
|
shouldAutoInvoke(skill, userMessage) {
|
|
@@ -29644,9 +29904,9 @@ class HookExecutor {
|
|
|
29644
29904
|
}
|
|
29645
29905
|
}
|
|
29646
29906
|
// packages/core/src/commands/loader.ts
|
|
29647
|
-
import { existsSync as
|
|
29648
|
-
import { join as
|
|
29649
|
-
import { homedir as
|
|
29907
|
+
import { existsSync as existsSync3, readdirSync, statSync } from "fs";
|
|
29908
|
+
import { join as join5, basename, extname } from "path";
|
|
29909
|
+
import { homedir as homedir4 } from "os";
|
|
29650
29910
|
|
|
29651
29911
|
class CommandLoader {
|
|
29652
29912
|
commands = new Map;
|
|
@@ -29656,17 +29916,17 @@ class CommandLoader {
|
|
|
29656
29916
|
}
|
|
29657
29917
|
async loadAll() {
|
|
29658
29918
|
this.commands.clear();
|
|
29659
|
-
const globalDir =
|
|
29919
|
+
const globalDir = join5(homedir4(), ".oldpal", "commands");
|
|
29660
29920
|
await this.loadFromDirectory(globalDir, "global");
|
|
29661
|
-
const projectDir =
|
|
29921
|
+
const projectDir = join5(this.cwd, ".oldpal", "commands");
|
|
29662
29922
|
await this.loadFromDirectory(projectDir, "project");
|
|
29663
29923
|
}
|
|
29664
29924
|
async loadFromDirectory(dir, source, prefix = "") {
|
|
29665
|
-
if (!
|
|
29925
|
+
if (!existsSync3(dir))
|
|
29666
29926
|
return;
|
|
29667
29927
|
const entries = readdirSync(dir);
|
|
29668
29928
|
for (const entry of entries) {
|
|
29669
|
-
const fullPath =
|
|
29929
|
+
const fullPath = join5(dir, entry);
|
|
29670
29930
|
const stat = statSync(fullPath);
|
|
29671
29931
|
if (stat.isDirectory()) {
|
|
29672
29932
|
const newPrefix = prefix ? `${prefix}:${entry}` : entry;
|
|
@@ -29844,9 +30104,9 @@ ${stderr}`;
|
|
|
29844
30104
|
}
|
|
29845
30105
|
}
|
|
29846
30106
|
// packages/core/src/commands/builtin.ts
|
|
29847
|
-
import { join as
|
|
29848
|
-
import { homedir as
|
|
29849
|
-
import { existsSync as
|
|
30107
|
+
import { join as join6 } from "path";
|
|
30108
|
+
import { homedir as homedir5 } from "os";
|
|
30109
|
+
import { existsSync as existsSync4, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
29850
30110
|
|
|
29851
30111
|
class BuiltinCommands {
|
|
29852
30112
|
tokenUsage = {
|
|
@@ -30016,8 +30276,8 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
30016
30276
|
content: "",
|
|
30017
30277
|
handler: async (args, context) => {
|
|
30018
30278
|
const configPaths = [
|
|
30019
|
-
|
|
30020
|
-
|
|
30279
|
+
join6(context.cwd, ".oldpal", "config.json"),
|
|
30280
|
+
join6(homedir5(), ".oldpal", "config.json")
|
|
30021
30281
|
];
|
|
30022
30282
|
let message = `
|
|
30023
30283
|
**Configuration**
|
|
@@ -30026,16 +30286,16 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
30026
30286
|
message += `**Config File Locations:**
|
|
30027
30287
|
`;
|
|
30028
30288
|
for (const path of configPaths) {
|
|
30029
|
-
const exists =
|
|
30289
|
+
const exists = existsSync4(path);
|
|
30030
30290
|
message += ` ${exists ? "\u2713" : "\u25CB"} ${path}
|
|
30031
30291
|
`;
|
|
30032
30292
|
}
|
|
30033
30293
|
message += `
|
|
30034
30294
|
**Commands Directories:**
|
|
30035
30295
|
`;
|
|
30036
|
-
message += ` - Project: ${
|
|
30296
|
+
message += ` - Project: ${join6(context.cwd, ".oldpal", "commands")}
|
|
30037
30297
|
`;
|
|
30038
|
-
message += ` - Global: ${
|
|
30298
|
+
message += ` - Global: ${join6(homedir5(), ".oldpal", "commands")}
|
|
30039
30299
|
`;
|
|
30040
30300
|
context.emit("text", message);
|
|
30041
30301
|
context.emit("done");
|
|
@@ -30051,7 +30311,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
30051
30311
|
selfHandled: true,
|
|
30052
30312
|
content: "",
|
|
30053
30313
|
handler: async (args, context) => {
|
|
30054
|
-
const commandsDir =
|
|
30314
|
+
const commandsDir = join6(context.cwd, ".oldpal", "commands");
|
|
30055
30315
|
mkdirSync(commandsDir, { recursive: true });
|
|
30056
30316
|
const exampleCommand = `---
|
|
30057
30317
|
name: review
|
|
@@ -30080,9 +30340,9 @@ Please review the current code changes and provide feedback on:
|
|
|
30080
30340
|
|
|
30081
30341
|
If there are staged git changes, focus on those. Otherwise, ask what code to review.
|
|
30082
30342
|
`;
|
|
30083
|
-
const examplePath =
|
|
30084
|
-
if (!
|
|
30085
|
-
|
|
30343
|
+
const examplePath = join6(commandsDir, "review.md");
|
|
30344
|
+
if (!existsSync4(examplePath)) {
|
|
30345
|
+
writeFileSync2(examplePath, exampleCommand);
|
|
30086
30346
|
}
|
|
30087
30347
|
let message = `
|
|
30088
30348
|
**Initialized oldpal**
|
|
@@ -30256,8 +30516,8 @@ async function createLLMClient(config) {
|
|
|
30256
30516
|
}
|
|
30257
30517
|
|
|
30258
30518
|
// packages/core/src/config.ts
|
|
30259
|
-
import { join as
|
|
30260
|
-
import { homedir as
|
|
30519
|
+
import { join as join8 } from "path";
|
|
30520
|
+
import { homedir as homedir7 } from "os";
|
|
30261
30521
|
var DEFAULT_CONFIG = {
|
|
30262
30522
|
llm: {
|
|
30263
30523
|
provider: "anthropic",
|
|
@@ -30287,13 +30547,13 @@ var DEFAULT_CONFIG = {
|
|
|
30287
30547
|
]
|
|
30288
30548
|
};
|
|
30289
30549
|
function getConfigDir() {
|
|
30290
|
-
return
|
|
30550
|
+
return join8(homedir7(), ".oldpal");
|
|
30291
30551
|
}
|
|
30292
30552
|
function getConfigPath(filename) {
|
|
30293
|
-
return
|
|
30553
|
+
return join8(getConfigDir(), filename);
|
|
30294
30554
|
}
|
|
30295
30555
|
function getProjectConfigDir(cwd2 = process.cwd()) {
|
|
30296
|
-
return
|
|
30556
|
+
return join8(cwd2, ".oldpal");
|
|
30297
30557
|
}
|
|
30298
30558
|
async function loadConfig(cwd2 = process.cwd()) {
|
|
30299
30559
|
const config = { ...DEFAULT_CONFIG };
|
|
@@ -30306,7 +30566,7 @@ async function loadConfig(cwd2 = process.cwd()) {
|
|
|
30306
30566
|
if (userConfig.voice)
|
|
30307
30567
|
config.voice = { ...config.voice, ...userConfig.voice };
|
|
30308
30568
|
}
|
|
30309
|
-
const projectConfigPath =
|
|
30569
|
+
const projectConfigPath = join8(getProjectConfigDir(cwd2), "settings.json");
|
|
30310
30570
|
const projectConfig = await loadJsonFile(projectConfigPath);
|
|
30311
30571
|
if (projectConfig) {
|
|
30312
30572
|
Object.assign(config, projectConfig);
|
|
@@ -30315,7 +30575,7 @@ async function loadConfig(cwd2 = process.cwd()) {
|
|
|
30315
30575
|
if (projectConfig.voice)
|
|
30316
30576
|
config.voice = { ...config.voice, ...projectConfig.voice };
|
|
30317
30577
|
}
|
|
30318
|
-
const localConfigPath =
|
|
30578
|
+
const localConfigPath = join8(getProjectConfigDir(cwd2), "settings.local.json");
|
|
30319
30579
|
const localConfig = await loadJsonFile(localConfigPath);
|
|
30320
30580
|
if (localConfig) {
|
|
30321
30581
|
Object.assign(config, localConfig);
|
|
@@ -30333,7 +30593,7 @@ async function loadHooksConfig(cwd2 = process.cwd()) {
|
|
|
30333
30593
|
if (userHooks?.hooks) {
|
|
30334
30594
|
mergeHooks(hooks, userHooks.hooks);
|
|
30335
30595
|
}
|
|
30336
|
-
const projectHooksPath =
|
|
30596
|
+
const projectHooksPath = join8(getProjectConfigDir(cwd2), "hooks.json");
|
|
30337
30597
|
const projectHooks = await loadJsonFile(projectHooksPath);
|
|
30338
30598
|
if (projectHooks?.hooks) {
|
|
30339
30599
|
mergeHooks(hooks, projectHooks.hooks);
|
|
@@ -30359,6 +30619,47 @@ async function loadJsonFile(path) {
|
|
|
30359
30619
|
return null;
|
|
30360
30620
|
}
|
|
30361
30621
|
}
|
|
30622
|
+
async function ensureConfigDir() {
|
|
30623
|
+
const { mkdir } = await import("fs/promises");
|
|
30624
|
+
const configDir = getConfigDir();
|
|
30625
|
+
await Promise.all([
|
|
30626
|
+
mkdir(configDir, { recursive: true }),
|
|
30627
|
+
mkdir(join8(configDir, "sessions"), { recursive: true }),
|
|
30628
|
+
mkdir(join8(configDir, "skills"), { recursive: true })
|
|
30629
|
+
]);
|
|
30630
|
+
}
|
|
30631
|
+
async function loadSystemPrompt(cwd2 = process.cwd()) {
|
|
30632
|
+
const prompts = [];
|
|
30633
|
+
const globalPromptPath = getConfigPath("OLDPAL.md");
|
|
30634
|
+
const globalPrompt = await loadTextFile(globalPromptPath);
|
|
30635
|
+
if (globalPrompt) {
|
|
30636
|
+
prompts.push(globalPrompt);
|
|
30637
|
+
}
|
|
30638
|
+
const projectPromptPath = join8(getProjectConfigDir(cwd2), "OLDPAL.md");
|
|
30639
|
+
const projectPrompt = await loadTextFile(projectPromptPath);
|
|
30640
|
+
if (projectPrompt) {
|
|
30641
|
+
prompts.push(projectPrompt);
|
|
30642
|
+
}
|
|
30643
|
+
if (prompts.length === 0) {
|
|
30644
|
+
return null;
|
|
30645
|
+
}
|
|
30646
|
+
return prompts.join(`
|
|
30647
|
+
|
|
30648
|
+
---
|
|
30649
|
+
|
|
30650
|
+
`);
|
|
30651
|
+
}
|
|
30652
|
+
async function loadTextFile(path) {
|
|
30653
|
+
try {
|
|
30654
|
+
const file = Bun.file(path);
|
|
30655
|
+
if (!await file.exists()) {
|
|
30656
|
+
return null;
|
|
30657
|
+
}
|
|
30658
|
+
return await file.text();
|
|
30659
|
+
} catch {
|
|
30660
|
+
return null;
|
|
30661
|
+
}
|
|
30662
|
+
}
|
|
30362
30663
|
|
|
30363
30664
|
// packages/core/src/agent/loop.ts
|
|
30364
30665
|
class AgentLoop {
|
|
@@ -30401,18 +30702,31 @@ class AgentLoop {
|
|
|
30401
30702
|
this.onTokenUsage = options.onTokenUsage;
|
|
30402
30703
|
}
|
|
30403
30704
|
async initialize() {
|
|
30404
|
-
|
|
30405
|
-
|
|
30705
|
+
const [config] = await Promise.all([
|
|
30706
|
+
loadConfig(this.cwd),
|
|
30707
|
+
ensureConfigDir()
|
|
30708
|
+
]);
|
|
30709
|
+
this.config = config;
|
|
30710
|
+
const [, , , hooksConfig, systemPrompt] = await Promise.all([
|
|
30711
|
+
createLLMClient(this.config.llm).then((client) => {
|
|
30712
|
+
this.llmClient = client;
|
|
30713
|
+
}),
|
|
30714
|
+
this.connectorBridge.discover(this.config.connectors),
|
|
30715
|
+
this.skillLoader.loadAll(this.cwd),
|
|
30716
|
+
loadHooksConfig(this.cwd),
|
|
30717
|
+
loadSystemPrompt(this.cwd),
|
|
30718
|
+
this.commandLoader.loadAll()
|
|
30719
|
+
]);
|
|
30406
30720
|
this.toolRegistry.register(BashTool.tool, BashTool.executor);
|
|
30407
30721
|
FilesystemTools.registerAll(this.toolRegistry);
|
|
30408
30722
|
WebTools.registerAll(this.toolRegistry);
|
|
30409
|
-
|
|
30723
|
+
ImageTools.registerAll(this.toolRegistry);
|
|
30410
30724
|
this.connectorBridge.registerAll(this.toolRegistry);
|
|
30411
|
-
await this.skillLoader.loadAll(this.cwd);
|
|
30412
|
-
await this.commandLoader.loadAll();
|
|
30413
30725
|
this.builtinCommands.registerAll(this.commandLoader);
|
|
30414
|
-
const hooksConfig = await loadHooksConfig(this.cwd);
|
|
30415
30726
|
this.hookLoader.load(hooksConfig);
|
|
30727
|
+
if (systemPrompt) {
|
|
30728
|
+
this.context.addSystemMessage(systemPrompt);
|
|
30729
|
+
}
|
|
30416
30730
|
await this.hookExecutor.execute(this.hookLoader.getHooks("SessionStart"), {
|
|
30417
30731
|
session_id: this.sessionId,
|
|
30418
30732
|
hook_event_name: "SessionStart",
|
|
@@ -30565,7 +30879,7 @@ class AgentLoop {
|
|
|
30565
30879
|
return false;
|
|
30566
30880
|
}
|
|
30567
30881
|
const argsList = args ? args.split(/\s+/) : [];
|
|
30568
|
-
const content = this.skillExecutor.prepare(skill, argsList);
|
|
30882
|
+
const content = await this.skillExecutor.prepare(skill, argsList);
|
|
30569
30883
|
this.context.addSystemMessage(content);
|
|
30570
30884
|
this.context.addUserMessage(`Execute the "${skillName}" skill with arguments: ${args || "(none)"}`);
|
|
30571
30885
|
await this.runLoop();
|
|
@@ -30611,9 +30925,9 @@ class AgentLoop {
|
|
|
30611
30925
|
init_anthropic();
|
|
30612
30926
|
|
|
30613
30927
|
// packages/core/src/logger.ts
|
|
30614
|
-
import { existsSync as
|
|
30615
|
-
import { join as
|
|
30616
|
-
import { homedir as
|
|
30928
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, appendFileSync } from "fs";
|
|
30929
|
+
import { join as join9 } from "path";
|
|
30930
|
+
import { homedir as homedir8 } from "os";
|
|
30617
30931
|
|
|
30618
30932
|
class Logger {
|
|
30619
30933
|
logDir;
|
|
@@ -30621,13 +30935,13 @@ class Logger {
|
|
|
30621
30935
|
sessionId;
|
|
30622
30936
|
constructor(sessionId) {
|
|
30623
30937
|
this.sessionId = sessionId;
|
|
30624
|
-
this.logDir =
|
|
30938
|
+
this.logDir = join9(homedir8(), ".oldpal", "logs");
|
|
30625
30939
|
this.ensureDir(this.logDir);
|
|
30626
30940
|
const date = new Date().toISOString().split("T")[0];
|
|
30627
|
-
this.logFile =
|
|
30941
|
+
this.logFile = join9(this.logDir, `${date}.log`);
|
|
30628
30942
|
}
|
|
30629
30943
|
ensureDir(dir) {
|
|
30630
|
-
if (!
|
|
30944
|
+
if (!existsSync6(dir)) {
|
|
30631
30945
|
mkdirSync2(dir, { recursive: true });
|
|
30632
30946
|
}
|
|
30633
30947
|
}
|
|
@@ -30667,12 +30981,12 @@ class SessionStorage {
|
|
|
30667
30981
|
sessionId;
|
|
30668
30982
|
constructor(sessionId) {
|
|
30669
30983
|
this.sessionId = sessionId;
|
|
30670
|
-
this.sessionsDir =
|
|
30984
|
+
this.sessionsDir = join9(homedir8(), ".oldpal", "sessions");
|
|
30671
30985
|
this.ensureDir(this.sessionsDir);
|
|
30672
|
-
this.sessionFile =
|
|
30986
|
+
this.sessionFile = join9(this.sessionsDir, `${sessionId}.json`);
|
|
30673
30987
|
}
|
|
30674
30988
|
ensureDir(dir) {
|
|
30675
|
-
if (!
|
|
30989
|
+
if (!existsSync6(dir)) {
|
|
30676
30990
|
mkdirSync2(dir, { recursive: true });
|
|
30677
30991
|
}
|
|
30678
30992
|
}
|
|
@@ -30686,15 +31000,15 @@ class SessionStorage {
|
|
|
30686
31000
|
}
|
|
30687
31001
|
}
|
|
30688
31002
|
function initOldpalDir() {
|
|
30689
|
-
const baseDir =
|
|
31003
|
+
const baseDir = join9(homedir8(), ".oldpal");
|
|
30690
31004
|
const dirs = [
|
|
30691
31005
|
baseDir,
|
|
30692
|
-
|
|
30693
|
-
|
|
30694
|
-
|
|
31006
|
+
join9(baseDir, "sessions"),
|
|
31007
|
+
join9(baseDir, "logs"),
|
|
31008
|
+
join9(baseDir, "skills")
|
|
30695
31009
|
];
|
|
30696
31010
|
for (const dir of dirs) {
|
|
30697
|
-
if (!
|
|
31011
|
+
if (!existsSync6(dir)) {
|
|
30698
31012
|
mkdirSync2(dir, { recursive: true });
|
|
30699
31013
|
}
|
|
30700
31014
|
}
|
|
@@ -31027,8 +31341,18 @@ function parseMarkdown(text) {
|
|
|
31027
31341
|
|
|
31028
31342
|
// packages/terminal/src/components/Messages.tsx
|
|
31029
31343
|
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
31030
|
-
function Messages4({
|
|
31031
|
-
|
|
31344
|
+
function Messages4({
|
|
31345
|
+
messages,
|
|
31346
|
+
currentResponse,
|
|
31347
|
+
currentToolCall,
|
|
31348
|
+
lastToolResult,
|
|
31349
|
+
activityLog = [],
|
|
31350
|
+
scrollOffset = 0,
|
|
31351
|
+
maxVisible = 10
|
|
31352
|
+
}) {
|
|
31353
|
+
const endIndex = messages.length - scrollOffset;
|
|
31354
|
+
const startIndex = Math.max(0, endIndex - maxVisible);
|
|
31355
|
+
const visibleMessages = messages.slice(startIndex, endIndex);
|
|
31032
31356
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31033
31357
|
flexDirection: "column",
|
|
31034
31358
|
children: [
|
|
@@ -31036,59 +31360,25 @@ function Messages4({ messages, currentResponse, currentToolCall, lastToolResult,
|
|
|
31036
31360
|
message
|
|
31037
31361
|
}, message.id, false, undefined, this)),
|
|
31038
31362
|
activityLog.map((entry) => {
|
|
31039
|
-
if (entry.type === "
|
|
31363
|
+
if (entry.type === "text" && entry.content) {
|
|
31040
31364
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31041
31365
|
marginY: 1,
|
|
31042
31366
|
children: [
|
|
31043
31367
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
31044
31368
|
dimColor: true,
|
|
31045
|
-
children: "\
|
|
31369
|
+
children: "\u25CF "
|
|
31046
31370
|
}, undefined, false, undefined, this),
|
|
31047
|
-
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(
|
|
31048
|
-
|
|
31049
|
-
children:
|
|
31371
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31372
|
+
flexGrow: 1,
|
|
31373
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Markdown, {
|
|
31374
|
+
content: entry.content
|
|
31375
|
+
}, undefined, false, undefined, this)
|
|
31050
31376
|
}, undefined, false, undefined, this)
|
|
31051
31377
|
]
|
|
31052
31378
|
}, entry.id, true, undefined, this);
|
|
31053
31379
|
}
|
|
31054
|
-
if (entry.type === "tool_result" && entry.toolResult) {
|
|
31055
|
-
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31056
|
-
marginLeft: 2,
|
|
31057
|
-
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
31058
|
-
dimColor: true,
|
|
31059
|
-
children: [
|
|
31060
|
-
"\u2192 ",
|
|
31061
|
-
truncate(entry.toolResult.content, 100)
|
|
31062
|
-
]
|
|
31063
|
-
}, undefined, true, undefined, this)
|
|
31064
|
-
}, entry.id, false, undefined, this);
|
|
31065
|
-
}
|
|
31066
31380
|
return null;
|
|
31067
31381
|
}),
|
|
31068
|
-
currentToolCall && !activityLog.some((e) => e.toolCall?.id === currentToolCall.id) && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31069
|
-
marginY: 1,
|
|
31070
|
-
children: [
|
|
31071
|
-
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
31072
|
-
dimColor: true,
|
|
31073
|
-
children: "\u25D0 "
|
|
31074
|
-
}, undefined, false, undefined, this),
|
|
31075
|
-
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
31076
|
-
dimColor: true,
|
|
31077
|
-
children: formatToolCall(currentToolCall)
|
|
31078
|
-
}, undefined, false, undefined, this)
|
|
31079
|
-
]
|
|
31080
|
-
}, undefined, true, undefined, this),
|
|
31081
|
-
lastToolResult && !activityLog.some((e) => e.toolResult?.toolCallId === lastToolResult.toolCallId) && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31082
|
-
marginY: 1,
|
|
31083
|
-
marginLeft: 2,
|
|
31084
|
-
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
31085
|
-
dimColor: true,
|
|
31086
|
-
children: [
|
|
31087
|
-
"\u2192 ",
|
|
31088
|
-
truncate(lastToolResult.content, 100)
|
|
31089
|
-
]
|
|
31090
|
-
}, undefined, true, undefined, this)
|
|
31091
|
-
}, undefined, false, undefined, this),
|
|
31092
31382
|
currentResponse && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31093
31383
|
marginY: 1,
|
|
31094
31384
|
children: [
|
|
@@ -31127,6 +31417,7 @@ function MessageBubble({ message }) {
|
|
|
31127
31417
|
]
|
|
31128
31418
|
}, undefined, true, undefined, this);
|
|
31129
31419
|
}
|
|
31420
|
+
const toolCount = message.toolCalls?.length || 0;
|
|
31130
31421
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31131
31422
|
marginY: 1,
|
|
31132
31423
|
flexDirection: "column",
|
|
@@ -31145,54 +31436,22 @@ function MessageBubble({ message }) {
|
|
|
31145
31436
|
}, undefined, false, undefined, this)
|
|
31146
31437
|
]
|
|
31147
31438
|
}, undefined, true, undefined, this),
|
|
31148
|
-
|
|
31439
|
+
toolCount > 0 && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
31149
31440
|
marginLeft: 2,
|
|
31150
|
-
marginTop: 1,
|
|
31151
31441
|
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
31152
31442
|
dimColor: true,
|
|
31153
31443
|
children: [
|
|
31154
|
-
"
|
|
31155
|
-
|
|
31444
|
+
"[",
|
|
31445
|
+
toolCount,
|
|
31446
|
+
" tool",
|
|
31447
|
+
toolCount > 1 ? "s" : "",
|
|
31448
|
+
" used]"
|
|
31156
31449
|
]
|
|
31157
31450
|
}, undefined, true, undefined, this)
|
|
31158
|
-
},
|
|
31451
|
+
}, undefined, false, undefined, this)
|
|
31159
31452
|
]
|
|
31160
31453
|
}, undefined, true, undefined, this);
|
|
31161
31454
|
}
|
|
31162
|
-
function formatToolCall(toolCall) {
|
|
31163
|
-
const { name, input } = toolCall;
|
|
31164
|
-
switch (name) {
|
|
31165
|
-
case "bash":
|
|
31166
|
-
return `Running: ${truncate(String(input.command || ""), 60)}`;
|
|
31167
|
-
case "read":
|
|
31168
|
-
return `Reading: ${truncate(String(input.path || input.file_path || ""), 60)}`;
|
|
31169
|
-
case "write":
|
|
31170
|
-
return `Writing: ${truncate(String(input.path || input.file_path || ""), 60)}`;
|
|
31171
|
-
case "glob":
|
|
31172
|
-
return `Finding: ${truncate(String(input.pattern || ""), 60)}`;
|
|
31173
|
-
case "grep":
|
|
31174
|
-
return `Searching: ${truncate(String(input.pattern || ""), 60)}`;
|
|
31175
|
-
case "notion":
|
|
31176
|
-
return `Notion: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
31177
|
-
case "gmail":
|
|
31178
|
-
return `Gmail: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
31179
|
-
case "googledrive":
|
|
31180
|
-
return `Drive: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
31181
|
-
case "googlecalendar":
|
|
31182
|
-
return `Calendar: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
31183
|
-
case "linear":
|
|
31184
|
-
return `Linear: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
31185
|
-
case "slack":
|
|
31186
|
-
return `Slack: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
31187
|
-
default:
|
|
31188
|
-
return `${name}: ${truncate(JSON.stringify(input), 50)}`;
|
|
31189
|
-
}
|
|
31190
|
-
}
|
|
31191
|
-
function truncate(text, maxLength) {
|
|
31192
|
-
if (text.length <= maxLength)
|
|
31193
|
-
return text;
|
|
31194
|
-
return text.slice(0, maxLength - 3) + "...";
|
|
31195
|
-
}
|
|
31196
31455
|
|
|
31197
31456
|
// packages/terminal/src/components/Status.tsx
|
|
31198
31457
|
var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -31289,26 +31548,232 @@ function Spinner2({ label }) {
|
|
|
31289
31548
|
}, undefined, true, undefined, this);
|
|
31290
31549
|
}
|
|
31291
31550
|
|
|
31292
|
-
// packages/terminal/src/components/
|
|
31551
|
+
// packages/terminal/src/components/ProcessingIndicator.tsx
|
|
31552
|
+
var import_react25 = __toESM(require_react(), 1);
|
|
31293
31553
|
var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
|
|
31554
|
+
function ProcessingIndicator({
|
|
31555
|
+
isProcessing,
|
|
31556
|
+
startTime,
|
|
31557
|
+
tokenCount = 0,
|
|
31558
|
+
isThinking = false
|
|
31559
|
+
}) {
|
|
31560
|
+
const [elapsed, setElapsed] = import_react25.useState(0);
|
|
31561
|
+
import_react25.useEffect(() => {
|
|
31562
|
+
if (!isProcessing || !startTime) {
|
|
31563
|
+
setElapsed(0);
|
|
31564
|
+
return;
|
|
31565
|
+
}
|
|
31566
|
+
const interval = setInterval(() => {
|
|
31567
|
+
setElapsed(Math.floor((Date.now() - startTime) / 1000));
|
|
31568
|
+
}, 1000);
|
|
31569
|
+
setElapsed(Math.floor((Date.now() - startTime) / 1000));
|
|
31570
|
+
return () => clearInterval(interval);
|
|
31571
|
+
}, [isProcessing, startTime]);
|
|
31572
|
+
if (!isProcessing) {
|
|
31573
|
+
return null;
|
|
31574
|
+
}
|
|
31575
|
+
const formatTime = (seconds) => {
|
|
31576
|
+
if (seconds < 60) {
|
|
31577
|
+
return `${seconds}s`;
|
|
31578
|
+
}
|
|
31579
|
+
const mins = Math.floor(seconds / 60);
|
|
31580
|
+
const secs = seconds % 60;
|
|
31581
|
+
return `${mins}m ${secs}s`;
|
|
31582
|
+
};
|
|
31583
|
+
const formatTokens = (tokens) => {
|
|
31584
|
+
if (tokens >= 1000) {
|
|
31585
|
+
return `${(tokens / 1000).toFixed(1)}k`;
|
|
31586
|
+
}
|
|
31587
|
+
return String(tokens);
|
|
31588
|
+
};
|
|
31589
|
+
const parts = [];
|
|
31590
|
+
parts.push("esc to interrupt");
|
|
31591
|
+
if (elapsed > 0) {
|
|
31592
|
+
parts.push(formatTime(elapsed));
|
|
31593
|
+
}
|
|
31594
|
+
if (tokenCount > 0) {
|
|
31595
|
+
parts.push(`\u2193 ${formatTokens(tokenCount)} tokens`);
|
|
31596
|
+
}
|
|
31597
|
+
if (isThinking) {
|
|
31598
|
+
parts.push("thinking");
|
|
31599
|
+
}
|
|
31600
|
+
const label = isThinking ? "Thinking" : "Working";
|
|
31601
|
+
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
31602
|
+
marginY: 1,
|
|
31603
|
+
children: [
|
|
31604
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
31605
|
+
dimColor: true,
|
|
31606
|
+
children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(build_default2, {
|
|
31607
|
+
type: "dots"
|
|
31608
|
+
}, undefined, false, undefined, this)
|
|
31609
|
+
}, undefined, false, undefined, this),
|
|
31610
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
31611
|
+
dimColor: true,
|
|
31612
|
+
children: [
|
|
31613
|
+
" ",
|
|
31614
|
+
label,
|
|
31615
|
+
"... "
|
|
31616
|
+
]
|
|
31617
|
+
}, undefined, true, undefined, this),
|
|
31618
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
31619
|
+
dimColor: true,
|
|
31620
|
+
children: [
|
|
31621
|
+
"(",
|
|
31622
|
+
parts.join(" \xB7 "),
|
|
31623
|
+
")"
|
|
31624
|
+
]
|
|
31625
|
+
}, undefined, true, undefined, this)
|
|
31626
|
+
]
|
|
31627
|
+
}, undefined, true, undefined, this);
|
|
31628
|
+
}
|
|
31629
|
+
|
|
31630
|
+
// packages/terminal/src/components/ToolCallBox.tsx
|
|
31631
|
+
var import_react26 = __toESM(require_react(), 1);
|
|
31632
|
+
var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
|
|
31633
|
+
function ToolCallBox({
|
|
31634
|
+
entries,
|
|
31635
|
+
maxVisible = 3,
|
|
31636
|
+
isExpanded = false,
|
|
31637
|
+
onToggleExpand
|
|
31638
|
+
}) {
|
|
31639
|
+
if (entries.length === 0) {
|
|
31640
|
+
return null;
|
|
31641
|
+
}
|
|
31642
|
+
const visibleEntries = isExpanded ? entries : entries.slice(-maxVisible);
|
|
31643
|
+
const hiddenCount = entries.length - visibleEntries.length;
|
|
31644
|
+
return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
31645
|
+
flexDirection: "column",
|
|
31646
|
+
borderStyle: "round",
|
|
31647
|
+
borderColor: "gray",
|
|
31648
|
+
paddingX: 1,
|
|
31649
|
+
marginY: 1,
|
|
31650
|
+
children: [
|
|
31651
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
31652
|
+
justifyContent: "space-between",
|
|
31653
|
+
children: [
|
|
31654
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
31655
|
+
dimColor: true,
|
|
31656
|
+
bold: true,
|
|
31657
|
+
children: [
|
|
31658
|
+
"Tools (",
|
|
31659
|
+
entries.length,
|
|
31660
|
+
")"
|
|
31661
|
+
]
|
|
31662
|
+
}, undefined, true, undefined, this),
|
|
31663
|
+
entries.length > maxVisible && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
31664
|
+
dimColor: true,
|
|
31665
|
+
children: isExpanded ? "Ctrl+O to collapse" : "Ctrl+O to expand"
|
|
31666
|
+
}, undefined, false, undefined, this)
|
|
31667
|
+
]
|
|
31668
|
+
}, undefined, true, undefined, this),
|
|
31669
|
+
hiddenCount > 0 && !isExpanded && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
31670
|
+
dimColor: true,
|
|
31671
|
+
children: [
|
|
31672
|
+
" +",
|
|
31673
|
+
hiddenCount,
|
|
31674
|
+
" more above..."
|
|
31675
|
+
]
|
|
31676
|
+
}, undefined, true, undefined, this),
|
|
31677
|
+
visibleEntries.map((entry, index) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(ToolCallRow, {
|
|
31678
|
+
entry
|
|
31679
|
+
}, entry.toolCall.id, false, undefined, this))
|
|
31680
|
+
]
|
|
31681
|
+
}, undefined, true, undefined, this);
|
|
31682
|
+
}
|
|
31683
|
+
function ToolCallRow({ entry }) {
|
|
31684
|
+
const { toolCall, result } = entry;
|
|
31685
|
+
const statusIcon = result ? result.isError ? "\u2717" : "\u2713" : "\u25D0";
|
|
31686
|
+
const statusColor = result ? result.isError ? "red" : "green" : "yellow";
|
|
31687
|
+
return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
31688
|
+
children: [
|
|
31689
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
31690
|
+
color: statusColor,
|
|
31691
|
+
children: [
|
|
31692
|
+
statusIcon,
|
|
31693
|
+
" "
|
|
31694
|
+
]
|
|
31695
|
+
}, undefined, true, undefined, this),
|
|
31696
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
31697
|
+
dimColor: true,
|
|
31698
|
+
children: formatToolCall(toolCall)
|
|
31699
|
+
}, undefined, false, undefined, this)
|
|
31700
|
+
]
|
|
31701
|
+
}, undefined, true, undefined, this);
|
|
31702
|
+
}
|
|
31703
|
+
function formatToolCall(toolCall) {
|
|
31704
|
+
const { name, input } = toolCall;
|
|
31705
|
+
switch (name) {
|
|
31706
|
+
case "bash":
|
|
31707
|
+
return `bash: ${truncate(String(input.command || ""), 50)}`;
|
|
31708
|
+
case "curl":
|
|
31709
|
+
case "web_fetch":
|
|
31710
|
+
return `fetch: ${truncate(String(input.url || ""), 50)}`;
|
|
31711
|
+
case "web_search":
|
|
31712
|
+
return `search: ${truncate(String(input.query || ""), 50)}`;
|
|
31713
|
+
case "read":
|
|
31714
|
+
return `read: ${truncate(String(input.path || input.file_path || ""), 50)}`;
|
|
31715
|
+
case "write":
|
|
31716
|
+
return `write: ${truncate(String(input.path || input.file_path || ""), 50)}`;
|
|
31717
|
+
case "glob":
|
|
31718
|
+
return `glob: ${truncate(String(input.pattern || ""), 50)}`;
|
|
31719
|
+
case "grep":
|
|
31720
|
+
return `grep: ${truncate(String(input.pattern || ""), 50)}`;
|
|
31721
|
+
case "notion":
|
|
31722
|
+
return `notion: ${truncate(String(input.command || input.action || ""), 50)}`;
|
|
31723
|
+
case "gmail":
|
|
31724
|
+
return `gmail: ${truncate(String(input.command || input.action || ""), 50)}`;
|
|
31725
|
+
case "googledrive":
|
|
31726
|
+
return `drive: ${truncate(String(input.command || input.action || ""), 50)}`;
|
|
31727
|
+
case "googlecalendar":
|
|
31728
|
+
return `calendar: ${truncate(String(input.command || input.action || ""), 50)}`;
|
|
31729
|
+
case "linear":
|
|
31730
|
+
return `linear: ${truncate(String(input.command || input.action || ""), 50)}`;
|
|
31731
|
+
case "slack":
|
|
31732
|
+
return `slack: ${truncate(String(input.command || input.action || ""), 50)}`;
|
|
31733
|
+
default:
|
|
31734
|
+
return `${name}: ${truncate(JSON.stringify(input), 40)}`;
|
|
31735
|
+
}
|
|
31736
|
+
}
|
|
31737
|
+
function truncate(text, maxLength) {
|
|
31738
|
+
if (text.length <= maxLength)
|
|
31739
|
+
return text;
|
|
31740
|
+
return text.slice(0, maxLength - 3) + "...";
|
|
31741
|
+
}
|
|
31742
|
+
function useToolCallExpansion() {
|
|
31743
|
+
const [isExpanded, setIsExpanded] = import_react26.useState(false);
|
|
31744
|
+
use_input_default((input, key) => {
|
|
31745
|
+
if (key.ctrl && input === "o") {
|
|
31746
|
+
setIsExpanded((prev) => !prev);
|
|
31747
|
+
}
|
|
31748
|
+
});
|
|
31749
|
+
return { isExpanded, setIsExpanded };
|
|
31750
|
+
}
|
|
31751
|
+
|
|
31752
|
+
// packages/terminal/src/components/App.tsx
|
|
31753
|
+
var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
31294
31754
|
function App2({ cwd: cwd2 }) {
|
|
31295
31755
|
const { exit } = use_app_default();
|
|
31296
|
-
const [client, setClient] =
|
|
31297
|
-
const [messages, setMessages] =
|
|
31298
|
-
const [currentResponse, setCurrentResponse] =
|
|
31299
|
-
const [currentToolCall, setCurrentToolCall] =
|
|
31300
|
-
const [lastToolResult, setLastToolResult] =
|
|
31301
|
-
const [isProcessing, setIsProcessing] =
|
|
31302
|
-
const [isInitializing, setIsInitializing] =
|
|
31303
|
-
const [error, setError] =
|
|
31304
|
-
const [messageQueue, setMessageQueue] =
|
|
31305
|
-
const [activityLog, setActivityLog] =
|
|
31306
|
-
const [tokenUsage, setTokenUsage] =
|
|
31307
|
-
const
|
|
31308
|
-
const
|
|
31309
|
-
const
|
|
31310
|
-
const
|
|
31311
|
-
const
|
|
31756
|
+
const [client, setClient] = import_react27.useState(null);
|
|
31757
|
+
const [messages, setMessages] = import_react27.useState([]);
|
|
31758
|
+
const [currentResponse, setCurrentResponse] = import_react27.useState("");
|
|
31759
|
+
const [currentToolCall, setCurrentToolCall] = import_react27.useState();
|
|
31760
|
+
const [lastToolResult, setLastToolResult] = import_react27.useState();
|
|
31761
|
+
const [isProcessing, setIsProcessing] = import_react27.useState(false);
|
|
31762
|
+
const [isInitializing, setIsInitializing] = import_react27.useState(true);
|
|
31763
|
+
const [error, setError] = import_react27.useState(null);
|
|
31764
|
+
const [messageQueue, setMessageQueue] = import_react27.useState([]);
|
|
31765
|
+
const [activityLog, setActivityLog] = import_react27.useState([]);
|
|
31766
|
+
const [tokenUsage, setTokenUsage] = import_react27.useState();
|
|
31767
|
+
const [processingStartTime, setProcessingStartTime] = import_react27.useState();
|
|
31768
|
+
const [currentTurnTokens, setCurrentTurnTokens] = import_react27.useState(0);
|
|
31769
|
+
const [scrollOffset, setScrollOffset] = import_react27.useState(0);
|
|
31770
|
+
const [autoScroll, setAutoScroll] = import_react27.useState(true);
|
|
31771
|
+
const { isExpanded: toolsExpanded } = useToolCallExpansion();
|
|
31772
|
+
const responseRef = import_react27.useRef("");
|
|
31773
|
+
const clientRef = import_react27.useRef(null);
|
|
31774
|
+
const toolCallsRef = import_react27.useRef([]);
|
|
31775
|
+
const toolResultsRef = import_react27.useRef([]);
|
|
31776
|
+
const processQueue = import_react27.useCallback(async () => {
|
|
31312
31777
|
if (!clientRef.current || messageQueue.length === 0)
|
|
31313
31778
|
return;
|
|
31314
31779
|
const nextMessage = messageQueue[0];
|
|
@@ -31328,10 +31793,12 @@ function App2({ cwd: cwd2 }) {
|
|
|
31328
31793
|
setCurrentToolCall(undefined);
|
|
31329
31794
|
setLastToolResult(undefined);
|
|
31330
31795
|
setActivityLog([]);
|
|
31796
|
+
setProcessingStartTime(Date.now());
|
|
31797
|
+
setCurrentTurnTokens(0);
|
|
31331
31798
|
setIsProcessing(true);
|
|
31332
31799
|
await clientRef.current.send(nextMessage);
|
|
31333
31800
|
}, [messageQueue]);
|
|
31334
|
-
|
|
31801
|
+
import_react27.useEffect(() => {
|
|
31335
31802
|
const initClient = async () => {
|
|
31336
31803
|
try {
|
|
31337
31804
|
const newClient = new EmbeddedClient(cwd2);
|
|
@@ -31341,6 +31808,19 @@ function App2({ cwd: cwd2 }) {
|
|
|
31341
31808
|
responseRef.current += chunk.content;
|
|
31342
31809
|
setCurrentResponse(responseRef.current);
|
|
31343
31810
|
} else if (chunk.type === "tool_use" && chunk.toolCall) {
|
|
31811
|
+
if (responseRef.current.trim()) {
|
|
31812
|
+
setActivityLog((prev) => [
|
|
31813
|
+
...prev,
|
|
31814
|
+
{
|
|
31815
|
+
id: generateId(),
|
|
31816
|
+
type: "text",
|
|
31817
|
+
content: responseRef.current,
|
|
31818
|
+
timestamp: now()
|
|
31819
|
+
}
|
|
31820
|
+
]);
|
|
31821
|
+
setCurrentResponse("");
|
|
31822
|
+
responseRef.current = "";
|
|
31823
|
+
}
|
|
31344
31824
|
toolCallsRef.current.push(chunk.toolCall);
|
|
31345
31825
|
setActivityLog((prev) => [
|
|
31346
31826
|
...prev,
|
|
@@ -31352,7 +31832,6 @@ function App2({ cwd: cwd2 }) {
|
|
|
31352
31832
|
}
|
|
31353
31833
|
]);
|
|
31354
31834
|
setCurrentToolCall(chunk.toolCall);
|
|
31355
|
-
setLastToolResult(undefined);
|
|
31356
31835
|
} else if (chunk.type === "tool_result" && chunk.toolResult) {
|
|
31357
31836
|
toolResultsRef.current.push(chunk.toolResult);
|
|
31358
31837
|
setActivityLog((prev) => [
|
|
@@ -31364,33 +31843,49 @@ function App2({ cwd: cwd2 }) {
|
|
|
31364
31843
|
timestamp: now()
|
|
31365
31844
|
}
|
|
31366
31845
|
]);
|
|
31367
|
-
setLastToolResult(chunk.toolResult);
|
|
31368
31846
|
setCurrentToolCall(undefined);
|
|
31369
31847
|
} else if (chunk.type === "error" && chunk.error) {
|
|
31370
31848
|
setError(chunk.error);
|
|
31371
31849
|
setIsProcessing(false);
|
|
31372
31850
|
} else if (chunk.type === "usage" && chunk.usage) {
|
|
31373
31851
|
setTokenUsage(chunk.usage);
|
|
31852
|
+
setCurrentTurnTokens((prev) => prev + (chunk.usage?.outputTokens || 0));
|
|
31374
31853
|
} else if (chunk.type === "done") {
|
|
31375
|
-
if (responseRef.current
|
|
31854
|
+
if (responseRef.current.trim()) {
|
|
31855
|
+
setActivityLog((prev) => [
|
|
31856
|
+
...prev,
|
|
31857
|
+
{
|
|
31858
|
+
id: generateId(),
|
|
31859
|
+
type: "text",
|
|
31860
|
+
content: responseRef.current,
|
|
31861
|
+
timestamp: now()
|
|
31862
|
+
}
|
|
31863
|
+
]);
|
|
31864
|
+
}
|
|
31865
|
+
const fullContent = activityLog.filter((e) => e.type === "text").map((e) => e.content).join(`
|
|
31866
|
+
`) + (responseRef.current ? `
|
|
31867
|
+
` + responseRef.current : "");
|
|
31868
|
+
if (fullContent.trim() || toolCallsRef.current.length > 0) {
|
|
31376
31869
|
setMessages((prev) => [
|
|
31377
31870
|
...prev,
|
|
31378
31871
|
{
|
|
31379
31872
|
id: generateId(),
|
|
31380
31873
|
role: "assistant",
|
|
31381
|
-
content:
|
|
31874
|
+
content: fullContent.trim(),
|
|
31382
31875
|
timestamp: now(),
|
|
31383
31876
|
toolCalls: toolCallsRef.current.length > 0 ? [...toolCallsRef.current] : undefined,
|
|
31384
31877
|
toolResults: toolResultsRef.current.length > 0 ? [...toolResultsRef.current] : undefined
|
|
31385
31878
|
}
|
|
31386
31879
|
]);
|
|
31387
|
-
setCurrentResponse("");
|
|
31388
|
-
responseRef.current = "";
|
|
31389
|
-
toolCallsRef.current = [];
|
|
31390
|
-
toolResultsRef.current = [];
|
|
31391
31880
|
}
|
|
31881
|
+
setCurrentResponse("");
|
|
31882
|
+
responseRef.current = "";
|
|
31883
|
+
toolCallsRef.current = [];
|
|
31884
|
+
toolResultsRef.current = [];
|
|
31392
31885
|
setCurrentToolCall(undefined);
|
|
31393
|
-
|
|
31886
|
+
setActivityLog([]);
|
|
31887
|
+
setProcessingStartTime(undefined);
|
|
31888
|
+
setCurrentTurnTokens(0);
|
|
31394
31889
|
setIsProcessing(false);
|
|
31395
31890
|
if (newClient) {
|
|
31396
31891
|
setTokenUsage(newClient.getTokenUsage());
|
|
@@ -31411,11 +31906,17 @@ function App2({ cwd: cwd2 }) {
|
|
|
31411
31906
|
};
|
|
31412
31907
|
initClient();
|
|
31413
31908
|
}, [cwd2]);
|
|
31414
|
-
|
|
31909
|
+
import_react27.useEffect(() => {
|
|
31415
31910
|
if (!isProcessing && messageQueue.length > 0) {
|
|
31416
31911
|
processQueue();
|
|
31417
31912
|
}
|
|
31418
31913
|
}, [isProcessing, messageQueue.length, processQueue]);
|
|
31914
|
+
import_react27.useEffect(() => {
|
|
31915
|
+
if (autoScroll) {
|
|
31916
|
+
setScrollOffset(0);
|
|
31917
|
+
}
|
|
31918
|
+
}, [messages.length, autoScroll]);
|
|
31919
|
+
const maxVisibleMessages = 10;
|
|
31419
31920
|
use_input_default((input, key) => {
|
|
31420
31921
|
if (key.ctrl && input === "c") {
|
|
31421
31922
|
if (isProcessing && client) {
|
|
@@ -31459,8 +31960,34 @@ function App2({ cwd: cwd2 }) {
|
|
|
31459
31960
|
}
|
|
31460
31961
|
setIsProcessing(false);
|
|
31461
31962
|
}
|
|
31963
|
+
if (key.pageUp || key.shift && key.upArrow) {
|
|
31964
|
+
setScrollOffset((prev) => {
|
|
31965
|
+
const maxOffset = Math.max(0, messages.length - maxVisibleMessages);
|
|
31966
|
+
const newOffset = Math.min(prev + 3, maxOffset);
|
|
31967
|
+
if (newOffset > 0)
|
|
31968
|
+
setAutoScroll(false);
|
|
31969
|
+
return newOffset;
|
|
31970
|
+
});
|
|
31971
|
+
}
|
|
31972
|
+
if (key.pageDown || key.shift && key.downArrow) {
|
|
31973
|
+
setScrollOffset((prev) => {
|
|
31974
|
+
const newOffset = Math.max(0, prev - 3);
|
|
31975
|
+
if (newOffset === 0)
|
|
31976
|
+
setAutoScroll(true);
|
|
31977
|
+
return newOffset;
|
|
31978
|
+
});
|
|
31979
|
+
}
|
|
31980
|
+
if (key.ctrl && input === "u") {
|
|
31981
|
+
const maxOffset = Math.max(0, messages.length - maxVisibleMessages);
|
|
31982
|
+
setScrollOffset(maxOffset);
|
|
31983
|
+
setAutoScroll(false);
|
|
31984
|
+
}
|
|
31985
|
+
if (key.ctrl && input === "d") {
|
|
31986
|
+
setScrollOffset(0);
|
|
31987
|
+
setAutoScroll(true);
|
|
31988
|
+
}
|
|
31462
31989
|
});
|
|
31463
|
-
const handleSubmit =
|
|
31990
|
+
const handleSubmit = import_react27.useCallback(async (input, mode = "normal") => {
|
|
31464
31991
|
if (!client || !input.trim())
|
|
31465
31992
|
return;
|
|
31466
31993
|
const trimmedInput = input.trim();
|
|
@@ -31503,32 +32030,56 @@ function App2({ cwd: cwd2 }) {
|
|
|
31503
32030
|
setCurrentToolCall(undefined);
|
|
31504
32031
|
setLastToolResult(undefined);
|
|
31505
32032
|
setActivityLog([]);
|
|
32033
|
+
setProcessingStartTime(Date.now());
|
|
32034
|
+
setCurrentTurnTokens(0);
|
|
31506
32035
|
setIsProcessing(true);
|
|
31507
32036
|
await client.send(trimmedInput);
|
|
31508
32037
|
}, [client, isProcessing]);
|
|
31509
32038
|
if (isInitializing) {
|
|
31510
|
-
return /* @__PURE__ */
|
|
32039
|
+
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
31511
32040
|
flexDirection: "column",
|
|
31512
32041
|
padding: 1,
|
|
31513
|
-
children: /* @__PURE__ */
|
|
32042
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Spinner2, {
|
|
31514
32043
|
label: "Initializing..."
|
|
31515
32044
|
}, undefined, false, undefined, this)
|
|
31516
32045
|
}, undefined, false, undefined, this);
|
|
31517
32046
|
}
|
|
31518
|
-
|
|
32047
|
+
const toolCallEntries = activityLog.filter((e) => e.type === "tool_call" && e.toolCall).map((e) => {
|
|
32048
|
+
const result = activityLog.find((r) => r.type === "tool_result" && r.toolResult?.toolCallId === e.toolCall?.id)?.toolResult;
|
|
32049
|
+
return { toolCall: e.toolCall, result };
|
|
32050
|
+
});
|
|
32051
|
+
const isThinking = isProcessing && !currentResponse && !currentToolCall && toolCallEntries.length === 0;
|
|
32052
|
+
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
31519
32053
|
flexDirection: "column",
|
|
31520
32054
|
padding: 1,
|
|
31521
32055
|
children: [
|
|
31522
|
-
/* @__PURE__ */
|
|
32056
|
+
scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
32057
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
32058
|
+
dimColor: true,
|
|
32059
|
+
children: [
|
|
32060
|
+
"\u2191 ",
|
|
32061
|
+
scrollOffset,
|
|
32062
|
+
" more messages above (Shift+\u2193 or Ctrl+D to scroll down)"
|
|
32063
|
+
]
|
|
32064
|
+
}, undefined, true, undefined, this)
|
|
32065
|
+
}, undefined, false, undefined, this),
|
|
32066
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Messages4, {
|
|
31523
32067
|
messages,
|
|
31524
32068
|
currentResponse: isProcessing ? currentResponse : undefined,
|
|
31525
|
-
currentToolCall,
|
|
31526
|
-
lastToolResult,
|
|
31527
|
-
activityLog: isProcessing ? activityLog : []
|
|
32069
|
+
currentToolCall: undefined,
|
|
32070
|
+
lastToolResult: undefined,
|
|
32071
|
+
activityLog: isProcessing ? activityLog.filter((e) => e.type === "text") : [],
|
|
32072
|
+
scrollOffset,
|
|
32073
|
+
maxVisible: maxVisibleMessages
|
|
31528
32074
|
}, undefined, false, undefined, this),
|
|
31529
|
-
|
|
32075
|
+
isProcessing && toolCallEntries.length > 0 && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(ToolCallBox, {
|
|
32076
|
+
entries: toolCallEntries,
|
|
32077
|
+
maxVisible: 3,
|
|
32078
|
+
isExpanded: toolsExpanded
|
|
32079
|
+
}, undefined, false, undefined, this),
|
|
32080
|
+
messageQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
31530
32081
|
marginY: 1,
|
|
31531
|
-
children: /* @__PURE__ */
|
|
32082
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
31532
32083
|
dimColor: true,
|
|
31533
32084
|
children: [
|
|
31534
32085
|
messageQueue.length,
|
|
@@ -31538,9 +32089,9 @@ function App2({ cwd: cwd2 }) {
|
|
|
31538
32089
|
]
|
|
31539
32090
|
}, undefined, true, undefined, this)
|
|
31540
32091
|
}, undefined, false, undefined, this),
|
|
31541
|
-
error && /* @__PURE__ */
|
|
32092
|
+
error && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
31542
32093
|
marginY: 1,
|
|
31543
|
-
children: /* @__PURE__ */
|
|
32094
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
31544
32095
|
color: "red",
|
|
31545
32096
|
children: [
|
|
31546
32097
|
"Error: ",
|
|
@@ -31548,18 +32099,18 @@ function App2({ cwd: cwd2 }) {
|
|
|
31548
32099
|
]
|
|
31549
32100
|
}, undefined, true, undefined, this)
|
|
31550
32101
|
}, undefined, false, undefined, this),
|
|
31551
|
-
|
|
31552
|
-
|
|
31553
|
-
|
|
31554
|
-
|
|
31555
|
-
|
|
32102
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(ProcessingIndicator, {
|
|
32103
|
+
isProcessing,
|
|
32104
|
+
startTime: processingStartTime,
|
|
32105
|
+
tokenCount: currentTurnTokens,
|
|
32106
|
+
isThinking
|
|
31556
32107
|
}, undefined, false, undefined, this),
|
|
31557
|
-
/* @__PURE__ */
|
|
32108
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Input, {
|
|
31558
32109
|
onSubmit: handleSubmit,
|
|
31559
32110
|
isProcessing,
|
|
31560
32111
|
queueLength: messageQueue.length
|
|
31561
32112
|
}, undefined, false, undefined, this),
|
|
31562
|
-
/* @__PURE__ */
|
|
32113
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Status, {
|
|
31563
32114
|
isProcessing,
|
|
31564
32115
|
cwd: cwd2,
|
|
31565
32116
|
queueLength: messageQueue.length,
|
|
@@ -31570,7 +32121,7 @@ function App2({ cwd: cwd2 }) {
|
|
|
31570
32121
|
}
|
|
31571
32122
|
|
|
31572
32123
|
// packages/terminal/src/index.tsx
|
|
31573
|
-
var
|
|
32124
|
+
var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
31574
32125
|
var args = process.argv.slice(2);
|
|
31575
32126
|
var options = {
|
|
31576
32127
|
cwd: process.cwd(),
|
|
@@ -31578,7 +32129,7 @@ var options = {
|
|
|
31578
32129
|
help: args.includes("--help") || args.includes("-h")
|
|
31579
32130
|
};
|
|
31580
32131
|
if (options.version) {
|
|
31581
|
-
console.log("oldpal v0.
|
|
32132
|
+
console.log("oldpal v0.2.0");
|
|
31582
32133
|
process.exit(0);
|
|
31583
32134
|
}
|
|
31584
32135
|
if (options.help) {
|
|
@@ -31602,11 +32153,11 @@ In interactive mode:
|
|
|
31602
32153
|
`);
|
|
31603
32154
|
process.exit(0);
|
|
31604
32155
|
}
|
|
31605
|
-
var { waitUntilExit } = render_default(/* @__PURE__ */
|
|
32156
|
+
var { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(App2, {
|
|
31606
32157
|
cwd: options.cwd
|
|
31607
32158
|
}, undefined, false, undefined, this));
|
|
31608
32159
|
waitUntilExit().then(() => {
|
|
31609
32160
|
process.exit(0);
|
|
31610
32161
|
});
|
|
31611
32162
|
|
|
31612
|
-
//# debugId=
|
|
32163
|
+
//# debugId=B53720C03AFA977C64756E2164756E21
|