@hasna/assistants 0.6.19 → 0.6.21
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/index.js +1769 -600
- package/dist/index.js.map +19 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25630,7 +25630,7 @@ var __classPrivateFieldSet = function(receiver, state, value, kind2, f) {
|
|
|
25630
25630
|
}
|
|
25631
25631
|
}, startsWithSchemeRegexp, isAbsoluteURL = (url) => {
|
|
25632
25632
|
return startsWithSchemeRegexp.test(url);
|
|
25633
|
-
}, sleep2 = (ms) => new Promise((
|
|
25633
|
+
}, sleep2 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms)), validatePositiveInteger = (name, n) => {
|
|
25634
25634
|
if (typeof n !== "number" || !Number.isInteger(n)) {
|
|
25635
25635
|
throw new AnthropicError(`${name} must be an integer`);
|
|
25636
25636
|
}
|
|
@@ -25696,8 +25696,8 @@ var init_core = __esm(() => {
|
|
|
25696
25696
|
init_uploads();
|
|
25697
25697
|
APIPromise = class APIPromise extends Promise {
|
|
25698
25698
|
constructor(responsePromise, parseResponse = defaultParseResponse) {
|
|
25699
|
-
super((
|
|
25700
|
-
|
|
25699
|
+
super((resolve5) => {
|
|
25700
|
+
resolve5(null);
|
|
25701
25701
|
});
|
|
25702
25702
|
this.responsePromise = responsePromise;
|
|
25703
25703
|
this.parseResponse = parseResponse;
|
|
@@ -26295,12 +26295,12 @@ var init_PromptCachingBetaMessageStream = __esm(() => {
|
|
|
26295
26295
|
}
|
|
26296
26296
|
return this._emit("error", new AnthropicError(String(error)));
|
|
26297
26297
|
});
|
|
26298
|
-
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((
|
|
26299
|
-
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveConnectedPromise,
|
|
26298
|
+
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve5, reject) => {
|
|
26299
|
+
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve5, "f");
|
|
26300
26300
|
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
|
|
26301
26301
|
}), "f");
|
|
26302
|
-
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_endPromise, new Promise((
|
|
26303
|
-
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveEndPromise,
|
|
26302
|
+
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve5, reject) => {
|
|
26303
|
+
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve5, "f");
|
|
26304
26304
|
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
|
|
26305
26305
|
}), "f");
|
|
26306
26306
|
__classPrivateFieldGet2(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {});
|
|
@@ -26390,11 +26390,11 @@ var init_PromptCachingBetaMessageStream = __esm(() => {
|
|
|
26390
26390
|
return this;
|
|
26391
26391
|
}
|
|
26392
26392
|
emitted(event) {
|
|
26393
|
-
return new Promise((
|
|
26393
|
+
return new Promise((resolve5, reject) => {
|
|
26394
26394
|
__classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
|
|
26395
26395
|
if (event !== "error")
|
|
26396
26396
|
this.once("error", reject);
|
|
26397
|
-
this.once(event,
|
|
26397
|
+
this.once(event, resolve5);
|
|
26398
26398
|
});
|
|
26399
26399
|
}
|
|
26400
26400
|
async done() {
|
|
@@ -26612,7 +26612,7 @@ var init_PromptCachingBetaMessageStream = __esm(() => {
|
|
|
26612
26612
|
if (done) {
|
|
26613
26613
|
return { value: undefined, done: true };
|
|
26614
26614
|
}
|
|
26615
|
-
return new Promise((
|
|
26615
|
+
return new Promise((resolve5, reject) => readQueue.push({ resolve: resolve5, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: undefined, done: true });
|
|
26616
26616
|
}
|
|
26617
26617
|
const chunk = pushQueue.shift();
|
|
26618
26618
|
return { value: chunk, done: false };
|
|
@@ -26758,12 +26758,12 @@ var init_MessageStream = __esm(() => {
|
|
|
26758
26758
|
}
|
|
26759
26759
|
return this._emit("error", new AnthropicError(String(error)));
|
|
26760
26760
|
});
|
|
26761
|
-
__classPrivateFieldSet3(this, _MessageStream_connectedPromise, new Promise((
|
|
26762
|
-
__classPrivateFieldSet3(this, _MessageStream_resolveConnectedPromise,
|
|
26761
|
+
__classPrivateFieldSet3(this, _MessageStream_connectedPromise, new Promise((resolve5, reject) => {
|
|
26762
|
+
__classPrivateFieldSet3(this, _MessageStream_resolveConnectedPromise, resolve5, "f");
|
|
26763
26763
|
__classPrivateFieldSet3(this, _MessageStream_rejectConnectedPromise, reject, "f");
|
|
26764
26764
|
}), "f");
|
|
26765
|
-
__classPrivateFieldSet3(this, _MessageStream_endPromise, new Promise((
|
|
26766
|
-
__classPrivateFieldSet3(this, _MessageStream_resolveEndPromise,
|
|
26765
|
+
__classPrivateFieldSet3(this, _MessageStream_endPromise, new Promise((resolve5, reject) => {
|
|
26766
|
+
__classPrivateFieldSet3(this, _MessageStream_resolveEndPromise, resolve5, "f");
|
|
26767
26767
|
__classPrivateFieldSet3(this, _MessageStream_rejectEndPromise, reject, "f");
|
|
26768
26768
|
}), "f");
|
|
26769
26769
|
__classPrivateFieldGet3(this, _MessageStream_connectedPromise, "f").catch(() => {});
|
|
@@ -26853,11 +26853,11 @@ var init_MessageStream = __esm(() => {
|
|
|
26853
26853
|
return this;
|
|
26854
26854
|
}
|
|
26855
26855
|
emitted(event) {
|
|
26856
|
-
return new Promise((
|
|
26856
|
+
return new Promise((resolve5, reject) => {
|
|
26857
26857
|
__classPrivateFieldSet3(this, _MessageStream_catchingPromiseCreated, true, "f");
|
|
26858
26858
|
if (event !== "error")
|
|
26859
26859
|
this.once("error", reject);
|
|
26860
|
-
this.once(event,
|
|
26860
|
+
this.once(event, resolve5);
|
|
26861
26861
|
});
|
|
26862
26862
|
}
|
|
26863
26863
|
async done() {
|
|
@@ -27075,7 +27075,7 @@ var init_MessageStream = __esm(() => {
|
|
|
27075
27075
|
if (done) {
|
|
27076
27076
|
return { value: undefined, done: true };
|
|
27077
27077
|
}
|
|
27078
|
-
return new Promise((
|
|
27078
|
+
return new Promise((resolve5, reject) => readQueue.push({ resolve: resolve5, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: undefined, done: true });
|
|
27079
27079
|
}
|
|
27080
27080
|
const chunk = pushQueue.shift();
|
|
27081
27081
|
return { value: chunk, done: false };
|
|
@@ -27290,16 +27290,16 @@ var exports_anthropic = {};
|
|
|
27290
27290
|
__export(exports_anthropic, {
|
|
27291
27291
|
AnthropicClient: () => AnthropicClient
|
|
27292
27292
|
});
|
|
27293
|
-
import { readFileSync as
|
|
27293
|
+
import { readFileSync as readFileSync3, existsSync as existsSync8 } from "fs";
|
|
27294
27294
|
import { homedir as homedir8 } from "os";
|
|
27295
|
-
import { join as
|
|
27295
|
+
import { join as join12 } from "path";
|
|
27296
27296
|
function loadApiKeyFromSecrets() {
|
|
27297
27297
|
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
27298
27298
|
const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir8();
|
|
27299
|
-
const secretsPath =
|
|
27300
|
-
if (
|
|
27299
|
+
const secretsPath = join12(homeDir, ".secrets");
|
|
27300
|
+
if (existsSync8(secretsPath)) {
|
|
27301
27301
|
try {
|
|
27302
|
-
const content =
|
|
27302
|
+
const content = readFileSync3(secretsPath, "utf-8");
|
|
27303
27303
|
const match = content.match(/export\s+ANTHROPIC_API_KEY\s*=\s*["']?([^"'\n]+)["']?/);
|
|
27304
27304
|
if (match) {
|
|
27305
27305
|
return match[1];
|
|
@@ -35507,7 +35507,7 @@ var import_react20 = __toESM(require_react(), 1);
|
|
|
35507
35507
|
var import_react21 = __toESM(require_react(), 1);
|
|
35508
35508
|
// packages/core/src/agent/loop.ts
|
|
35509
35509
|
init_src();
|
|
35510
|
-
import { join as
|
|
35510
|
+
import { join as join19 } from "path";
|
|
35511
35511
|
|
|
35512
35512
|
// packages/core/src/agent/context.ts
|
|
35513
35513
|
init_src();
|
|
@@ -35567,6 +35567,13 @@ class AgentContext {
|
|
|
35567
35567
|
this.messages.push(message);
|
|
35568
35568
|
return message;
|
|
35569
35569
|
}
|
|
35570
|
+
removeSystemMessages(predicate) {
|
|
35571
|
+
this.messages = this.messages.filter((msg) => {
|
|
35572
|
+
if (msg.role !== "system")
|
|
35573
|
+
return true;
|
|
35574
|
+
return !predicate(msg.content);
|
|
35575
|
+
});
|
|
35576
|
+
}
|
|
35570
35577
|
getMessages() {
|
|
35571
35578
|
return [...this.messages];
|
|
35572
35579
|
}
|
|
@@ -36629,23 +36636,71 @@ function isErrorResult(result) {
|
|
|
36629
36636
|
init_errors();
|
|
36630
36637
|
import { homedir as homedir2 } from "os";
|
|
36631
36638
|
import { join as join3, delimiter } from "path";
|
|
36632
|
-
import { readdirSync, statSync } from "fs";
|
|
36639
|
+
import { readdirSync, statSync, existsSync as existsSync2, mkdirSync, writeFileSync, readFileSync as readFileSync2 } from "fs";
|
|
36633
36640
|
function resolveTimeout(resolve) {
|
|
36634
36641
|
resolve({ exitCode: 1 });
|
|
36635
36642
|
}
|
|
36643
|
+
var CACHE_VERSION = 1;
|
|
36644
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
36636
36645
|
|
|
36637
36646
|
class ConnectorBridge {
|
|
36638
36647
|
connectors = new Map;
|
|
36639
36648
|
static cache = new Map;
|
|
36649
|
+
static diskCacheLoaded = false;
|
|
36650
|
+
cwd;
|
|
36651
|
+
constructor(cwd2) {
|
|
36652
|
+
this.cwd = cwd2;
|
|
36653
|
+
if (!ConnectorBridge.diskCacheLoaded) {
|
|
36654
|
+
ConnectorBridge.loadDiskCache();
|
|
36655
|
+
}
|
|
36656
|
+
}
|
|
36640
36657
|
getHomeDir() {
|
|
36641
36658
|
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
36642
36659
|
return envHome && envHome.trim().length > 0 ? envHome : homedir2();
|
|
36643
36660
|
}
|
|
36661
|
+
static getCachePath() {
|
|
36662
|
+
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
36663
|
+
const home = envHome && envHome.trim().length > 0 ? envHome : homedir2();
|
|
36664
|
+
return join3(home, ".assistants", "cache", "connectors.json");
|
|
36665
|
+
}
|
|
36666
|
+
static loadDiskCache() {
|
|
36667
|
+
ConnectorBridge.diskCacheLoaded = true;
|
|
36668
|
+
try {
|
|
36669
|
+
const cachePath = ConnectorBridge.getCachePath();
|
|
36670
|
+
if (!existsSync2(cachePath))
|
|
36671
|
+
return;
|
|
36672
|
+
const data = JSON.parse(readFileSync2(cachePath, "utf-8"));
|
|
36673
|
+
if (data.version !== CACHE_VERSION)
|
|
36674
|
+
return;
|
|
36675
|
+
if (Date.now() - data.timestamp > CACHE_TTL_MS)
|
|
36676
|
+
return;
|
|
36677
|
+
for (const [name, connector] of Object.entries(data.connectors)) {
|
|
36678
|
+
ConnectorBridge.cache.set(name, connector);
|
|
36679
|
+
}
|
|
36680
|
+
} catch {}
|
|
36681
|
+
}
|
|
36682
|
+
static saveDiskCache() {
|
|
36683
|
+
try {
|
|
36684
|
+
const cachePath = ConnectorBridge.getCachePath();
|
|
36685
|
+
const cacheDir = join3(cachePath, "..");
|
|
36686
|
+
if (!existsSync2(cacheDir)) {
|
|
36687
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
36688
|
+
}
|
|
36689
|
+
const data = {
|
|
36690
|
+
version: CACHE_VERSION,
|
|
36691
|
+
timestamp: Date.now(),
|
|
36692
|
+
connectors: Object.fromEntries(ConnectorBridge.cache)
|
|
36693
|
+
};
|
|
36694
|
+
writeFileSync(cachePath, JSON.stringify(data));
|
|
36695
|
+
} catch {}
|
|
36696
|
+
}
|
|
36644
36697
|
autoDiscoverConnectorNames() {
|
|
36645
36698
|
const connectorNames = new Set;
|
|
36646
36699
|
const pathDirs = (process.env.PATH || "").split(delimiter);
|
|
36700
|
+
const baseCwd = this.cwd || process.cwd();
|
|
36647
36701
|
const homeDir = this.getHomeDir();
|
|
36648
36702
|
const extraDirs = [
|
|
36703
|
+
join3(baseCwd, "node_modules", ".bin"),
|
|
36649
36704
|
join3(homeDir, ".bun", "bin"),
|
|
36650
36705
|
join3(homeDir, ".npm-global", "bin"),
|
|
36651
36706
|
"/usr/local/bin"
|
|
@@ -36678,6 +36733,19 @@ class ConnectorBridge {
|
|
|
36678
36733
|
return Array.from(connectorNames);
|
|
36679
36734
|
}
|
|
36680
36735
|
fastDiscover(connectorNames) {
|
|
36736
|
+
if (ConnectorBridge.cache.size > 0) {
|
|
36737
|
+
const connectors2 = [];
|
|
36738
|
+
const allowList2 = connectorNames && connectorNames.length > 0 ? new Set(connectorNames) : null;
|
|
36739
|
+
for (const [name, connector] of ConnectorBridge.cache) {
|
|
36740
|
+
if (connector && (!allowList2 || allowList2.has(name))) {
|
|
36741
|
+
this.connectors.set(connector.name, connector);
|
|
36742
|
+
connectors2.push(connector);
|
|
36743
|
+
}
|
|
36744
|
+
}
|
|
36745
|
+
if (connectors2.length > 0) {
|
|
36746
|
+
return connectors2;
|
|
36747
|
+
}
|
|
36748
|
+
}
|
|
36681
36749
|
const discoveredNames = this.autoDiscoverConnectorNames();
|
|
36682
36750
|
const allowList = connectorNames && connectorNames.length > 0 ? new Set(connectorNames) : null;
|
|
36683
36751
|
const names = allowList ? discoveredNames.filter((name) => allowList.has(name)) : discoveredNames;
|
|
@@ -36700,6 +36768,9 @@ class ConnectorBridge {
|
|
|
36700
36768
|
this.connectors.set(connector.name, connector);
|
|
36701
36769
|
connectors.push(connector);
|
|
36702
36770
|
}
|
|
36771
|
+
if (connectors.length > 0) {
|
|
36772
|
+
ConnectorBridge.saveDiskCache();
|
|
36773
|
+
}
|
|
36703
36774
|
return connectors;
|
|
36704
36775
|
}
|
|
36705
36776
|
async discover(connectorNames) {
|
|
@@ -36719,6 +36790,7 @@ class ConnectorBridge {
|
|
|
36719
36790
|
tasks.push(this.populateCache(name));
|
|
36720
36791
|
}
|
|
36721
36792
|
await Promise.all(tasks);
|
|
36793
|
+
ConnectorBridge.saveDiskCache();
|
|
36722
36794
|
}
|
|
36723
36795
|
const discovered = [];
|
|
36724
36796
|
for (const name of names) {
|
|
@@ -36888,17 +36960,20 @@ class ConnectorBridge {
|
|
|
36888
36960
|
}
|
|
36889
36961
|
const lowerCommand = command.toLowerCase();
|
|
36890
36962
|
const lowerArgs = args.map((arg) => arg.toLowerCase());
|
|
36891
|
-
const
|
|
36892
|
-
|
|
36963
|
+
const combined = [lowerCommand, ...lowerArgs].join(" ");
|
|
36964
|
+
const isAuthLogin = /\bauth\b/.test(combined) && /(login|authorize|authorization|oauth|signin|sign-in|connect)/.test(combined);
|
|
36965
|
+
const runInBackground = options.background === true;
|
|
36966
|
+
if (isAuthLogin || runInBackground) {
|
|
36893
36967
|
try {
|
|
36894
|
-
Bun.spawn(cmdParts, {
|
|
36968
|
+
const proc = Bun.spawn(cmdParts, {
|
|
36895
36969
|
cwd: cwd2,
|
|
36896
36970
|
stdin: "ignore",
|
|
36897
36971
|
stdout: "ignore",
|
|
36898
|
-
stderr: "
|
|
36972
|
+
stderr: "ignore"
|
|
36899
36973
|
});
|
|
36974
|
+
proc.unref?.();
|
|
36900
36975
|
} catch {}
|
|
36901
|
-
return "Auth login started in the background. Complete it in your browser, then run auth status to confirm.";
|
|
36976
|
+
return isAuthLogin ? "Auth login started in the background. Complete it in your browser, then run auth status to confirm." : "Command started in the background.";
|
|
36902
36977
|
}
|
|
36903
36978
|
try {
|
|
36904
36979
|
const proc = Bun.spawn(cmdParts, {
|
|
@@ -37036,6 +37111,38 @@ function stripQuotedSegments(input) {
|
|
|
37036
37111
|
}
|
|
37037
37112
|
return result;
|
|
37038
37113
|
}
|
|
37114
|
+
function normalizeNewlinesOutsideQuotes(input) {
|
|
37115
|
+
let result = "";
|
|
37116
|
+
let quote = null;
|
|
37117
|
+
let escaped = false;
|
|
37118
|
+
for (let i = 0;i < input.length; i += 1) {
|
|
37119
|
+
const char = input[i];
|
|
37120
|
+
if (quote) {
|
|
37121
|
+
result += char;
|
|
37122
|
+
if (quote === '"' && !escaped && char === "\\") {
|
|
37123
|
+
escaped = true;
|
|
37124
|
+
continue;
|
|
37125
|
+
}
|
|
37126
|
+
if (!escaped && char === quote) {
|
|
37127
|
+
quote = null;
|
|
37128
|
+
}
|
|
37129
|
+
escaped = false;
|
|
37130
|
+
continue;
|
|
37131
|
+
}
|
|
37132
|
+
if (char === '"' || char === "'") {
|
|
37133
|
+
quote = char;
|
|
37134
|
+
result += char;
|
|
37135
|
+
continue;
|
|
37136
|
+
}
|
|
37137
|
+
if (char === "\r" || char === `
|
|
37138
|
+
`) {
|
|
37139
|
+
result += " ";
|
|
37140
|
+
continue;
|
|
37141
|
+
}
|
|
37142
|
+
result += char;
|
|
37143
|
+
}
|
|
37144
|
+
return result;
|
|
37145
|
+
}
|
|
37039
37146
|
|
|
37040
37147
|
class BashTool {
|
|
37041
37148
|
static tool = {
|
|
@@ -37155,7 +37262,11 @@ class BashTool {
|
|
|
37155
37262
|
const command = input.command;
|
|
37156
37263
|
const cwd2 = input.cwd || process.cwd();
|
|
37157
37264
|
const timeout = input.timeout || 30000;
|
|
37158
|
-
const
|
|
37265
|
+
const baseCommand = command.replace(/\s*2>&1\s*/g, " ").trim();
|
|
37266
|
+
const baseTrimmed = baseCommand.toLowerCase();
|
|
37267
|
+
const allowConnectorNewlines = baseTrimmed.startsWith("connect-");
|
|
37268
|
+
const commandForExec = allowConnectorNewlines ? normalizeNewlinesOutsideQuotes(baseCommand).trim() : baseCommand;
|
|
37269
|
+
const commandForChecks = commandForExec;
|
|
37159
37270
|
const commandSansQuotes = stripQuotedSegments(commandForChecks);
|
|
37160
37271
|
const securityCheck = validateBashCommand(commandForChecks);
|
|
37161
37272
|
if (!securityCheck.valid) {
|
|
@@ -37229,7 +37340,7 @@ class BashTool {
|
|
|
37229
37340
|
});
|
|
37230
37341
|
}
|
|
37231
37342
|
try {
|
|
37232
|
-
const proc = Bun.spawn(["bash", "-c",
|
|
37343
|
+
const proc = Bun.spawn(["bash", "-c", commandForExec], {
|
|
37233
37344
|
cwd: cwd2,
|
|
37234
37345
|
stdout: "pipe",
|
|
37235
37346
|
stderr: "pipe"
|
|
@@ -37268,7 +37379,7 @@ ${stderr || stdout}`.trim(), {
|
|
|
37268
37379
|
|
|
37269
37380
|
// packages/core/src/tools/filesystem.ts
|
|
37270
37381
|
import { join as join4, resolve as resolve3, dirname as dirname2, sep } from "path";
|
|
37271
|
-
import { existsSync as
|
|
37382
|
+
import { existsSync as existsSync3 } from "fs";
|
|
37272
37383
|
init_errors();
|
|
37273
37384
|
var {Glob } = globalThis.Bun;
|
|
37274
37385
|
|
|
@@ -37356,15 +37467,16 @@ async function isPathSafe(targetPath, operation, options = {}) {
|
|
|
37356
37467
|
|
|
37357
37468
|
// packages/core/src/tools/filesystem.ts
|
|
37358
37469
|
var currentSessionId = "default";
|
|
37359
|
-
function getScriptsFolder(cwd2) {
|
|
37470
|
+
function getScriptsFolder(cwd2, sessionId) {
|
|
37471
|
+
const resolvedSessionId = sessionId || currentSessionId;
|
|
37360
37472
|
const legacyDir = join4(cwd2, ".oldpal");
|
|
37361
|
-
if (
|
|
37362
|
-
return join4(legacyDir, "scripts",
|
|
37473
|
+
if (existsSync3(legacyDir)) {
|
|
37474
|
+
return join4(legacyDir, "scripts", resolvedSessionId);
|
|
37363
37475
|
}
|
|
37364
|
-
return join4(getProjectConfigDir(cwd2), "scripts",
|
|
37476
|
+
return join4(getProjectConfigDir(cwd2), "scripts", resolvedSessionId);
|
|
37365
37477
|
}
|
|
37366
|
-
function isInScriptsFolder(path2, cwd2) {
|
|
37367
|
-
const scriptsFolder = resolve3(getScriptsFolder(cwd2));
|
|
37478
|
+
function isInScriptsFolder(path2, cwd2, sessionId) {
|
|
37479
|
+
const scriptsFolder = resolve3(getScriptsFolder(cwd2, sessionId));
|
|
37368
37480
|
const resolved = resolve3(path2);
|
|
37369
37481
|
if (resolved === scriptsFolder)
|
|
37370
37482
|
return true;
|
|
@@ -37520,7 +37632,7 @@ class FilesystemTools {
|
|
|
37520
37632
|
const filename = input.filename || input.path;
|
|
37521
37633
|
const content = input.content;
|
|
37522
37634
|
const baseCwd = input.cwd || process.cwd();
|
|
37523
|
-
const scriptsFolder = getScriptsFolder(baseCwd);
|
|
37635
|
+
const scriptsFolder = getScriptsFolder(baseCwd, input.sessionId);
|
|
37524
37636
|
if (!filename || !filename.trim()) {
|
|
37525
37637
|
throw new ToolExecutionError("Filename is required", {
|
|
37526
37638
|
toolName: "write",
|
|
@@ -37533,7 +37645,7 @@ class FilesystemTools {
|
|
|
37533
37645
|
}
|
|
37534
37646
|
const sanitizedFilename = filename.replace(/\.\.[/\\]/g, "").replace(/\.\./g, "").replace(/^[/\\]+/, "");
|
|
37535
37647
|
const path2 = join4(scriptsFolder, sanitizedFilename);
|
|
37536
|
-
if (!isInScriptsFolder(path2, baseCwd)) {
|
|
37648
|
+
if (!isInScriptsFolder(path2, baseCwd, input.sessionId)) {
|
|
37537
37649
|
throw new ToolExecutionError(`Cannot write outside scripts folder. Files are saved to ${scriptsFolder}`, {
|
|
37538
37650
|
toolName: "write",
|
|
37539
37651
|
toolInput: input,
|
|
@@ -38283,7 +38395,7 @@ function isPrivateIPv4(octets) {
|
|
|
38283
38395
|
// packages/core/src/tools/feedback.ts
|
|
38284
38396
|
init_src();
|
|
38285
38397
|
import { join as join5 } from "path";
|
|
38286
|
-
import { existsSync as
|
|
38398
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
38287
38399
|
function normalizeTags(value) {
|
|
38288
38400
|
if (Array.isArray(value)) {
|
|
38289
38401
|
const tags = value.map((t) => String(t).trim()).filter(Boolean);
|
|
@@ -38298,16 +38410,16 @@ function normalizeTags(value) {
|
|
|
38298
38410
|
function resolveFeedbackDir(cwd2) {
|
|
38299
38411
|
const baseCwd = cwd2 && cwd2.trim().length > 0 ? cwd2 : process.cwd();
|
|
38300
38412
|
const legacyDir = join5(baseCwd, ".oldpal");
|
|
38301
|
-
if (
|
|
38413
|
+
if (existsSync4(legacyDir)) {
|
|
38302
38414
|
return join5(legacyDir, "feedback");
|
|
38303
38415
|
}
|
|
38304
38416
|
return join5(getConfigDir(), "feedback");
|
|
38305
38417
|
}
|
|
38306
38418
|
function saveFeedbackEntry(entry, cwd2) {
|
|
38307
38419
|
const feedbackDir = resolveFeedbackDir(cwd2);
|
|
38308
|
-
|
|
38420
|
+
mkdirSync2(feedbackDir, { recursive: true });
|
|
38309
38421
|
const path2 = join5(feedbackDir, `${entry.id}.json`);
|
|
38310
|
-
|
|
38422
|
+
writeFileSync2(path2, JSON.stringify(entry, null, 2));
|
|
38311
38423
|
return { path: path2 };
|
|
38312
38424
|
}
|
|
38313
38425
|
function buildEntry(input, overrides) {
|
|
@@ -38868,7 +38980,7 @@ class SchedulerTool {
|
|
|
38868
38980
|
|
|
38869
38981
|
// packages/core/src/tools/image.ts
|
|
38870
38982
|
init_src();
|
|
38871
|
-
import { existsSync as
|
|
38983
|
+
import { existsSync as existsSync5, writeFileSync as writeFileSync3, unlinkSync } from "fs";
|
|
38872
38984
|
import { tmpdir } from "os";
|
|
38873
38985
|
import { join as join7 } from "path";
|
|
38874
38986
|
import { homedir as homedir4 } from "os";
|
|
@@ -38949,13 +39061,13 @@ class ImageDisplayTool {
|
|
|
38949
39061
|
const buffer = await response.arrayBuffer();
|
|
38950
39062
|
const ext = contentType.split("/")[1]?.split(";")[0] || "png";
|
|
38951
39063
|
tempFile = join7(tmpdir(), `assistants-image-${generateId()}.${ext}`);
|
|
38952
|
-
|
|
39064
|
+
writeFileSync3(tempFile, Buffer.from(buffer));
|
|
38953
39065
|
localPath = tempFile;
|
|
38954
39066
|
} catch (error) {
|
|
38955
39067
|
return `Error: Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`;
|
|
38956
39068
|
}
|
|
38957
39069
|
}
|
|
38958
|
-
if (!
|
|
39070
|
+
if (!existsSync5(localPath)) {
|
|
38959
39071
|
return `Error: Image file not found: ${localPath}`;
|
|
38960
39072
|
}
|
|
38961
39073
|
try {
|
|
@@ -38980,7 +39092,7 @@ class ImageDisplayTool {
|
|
|
38980
39092
|
} catch (error) {
|
|
38981
39093
|
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
38982
39094
|
} finally {
|
|
38983
|
-
if (tempFile &&
|
|
39095
|
+
if (tempFile && existsSync5(tempFile)) {
|
|
38984
39096
|
try {
|
|
38985
39097
|
unlinkSync(tempFile);
|
|
38986
39098
|
} catch {}
|
|
@@ -39484,7 +39596,7 @@ Respond with JSON only: {"allow": boolean, "reason": string}`;
|
|
|
39484
39596
|
}
|
|
39485
39597
|
}
|
|
39486
39598
|
// packages/core/src/commands/loader.ts
|
|
39487
|
-
import { existsSync as
|
|
39599
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
39488
39600
|
import { join as join9, basename as basename2, extname } from "path";
|
|
39489
39601
|
import { homedir as homedir6 } from "os";
|
|
39490
39602
|
|
|
@@ -39508,7 +39620,7 @@ class CommandLoader {
|
|
|
39508
39620
|
await this.loadFromDirectory(legacyProjectDir, "project");
|
|
39509
39621
|
}
|
|
39510
39622
|
async loadFromDirectory(dir, source, prefix = "") {
|
|
39511
|
-
if (!
|
|
39623
|
+
if (!existsSync6(dir))
|
|
39512
39624
|
return;
|
|
39513
39625
|
const entries = readdirSync2(dir);
|
|
39514
39626
|
for (const entry of entries) {
|
|
@@ -39737,13 +39849,217 @@ ${stderr}`;
|
|
|
39737
39849
|
}
|
|
39738
39850
|
}
|
|
39739
39851
|
// packages/core/src/commands/builtin.ts
|
|
39740
|
-
import { join as
|
|
39852
|
+
import { join as join11 } from "path";
|
|
39741
39853
|
import { homedir as homedir7, platform as platform2, release, arch } from "os";
|
|
39742
|
-
import { existsSync as
|
|
39854
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
39743
39855
|
init_src();
|
|
39744
|
-
|
|
39745
|
-
|
|
39746
|
-
|
|
39856
|
+
|
|
39857
|
+
// packages/core/src/projects/store.ts
|
|
39858
|
+
init_src();
|
|
39859
|
+
import { join as join10 } from "path";
|
|
39860
|
+
import { mkdir as mkdir3, readdir as readdir2, readFile as readFile2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
|
|
39861
|
+
function projectsDir(cwd2) {
|
|
39862
|
+
return join10(cwd2, ".oldpal", "projects");
|
|
39863
|
+
}
|
|
39864
|
+
function projectPath(cwd2, id) {
|
|
39865
|
+
return join10(projectsDir(cwd2), `${id}.json`);
|
|
39866
|
+
}
|
|
39867
|
+
async function ensureProjectsDir(cwd2) {
|
|
39868
|
+
await mkdir3(projectsDir(cwd2), { recursive: true });
|
|
39869
|
+
}
|
|
39870
|
+
function normalizeName(name) {
|
|
39871
|
+
return name.trim().toLowerCase();
|
|
39872
|
+
}
|
|
39873
|
+
async function listProjects(cwd2) {
|
|
39874
|
+
try {
|
|
39875
|
+
const dir = projectsDir(cwd2);
|
|
39876
|
+
const files = await readdir2(dir);
|
|
39877
|
+
const projects = [];
|
|
39878
|
+
for (const file of files) {
|
|
39879
|
+
if (!file.endsWith(".json"))
|
|
39880
|
+
continue;
|
|
39881
|
+
try {
|
|
39882
|
+
const raw = await readFile2(join10(dir, file), "utf-8");
|
|
39883
|
+
const parsed = JSON.parse(raw);
|
|
39884
|
+
if (parsed?.id && parsed?.name) {
|
|
39885
|
+
projects.push(parsed);
|
|
39886
|
+
}
|
|
39887
|
+
} catch {}
|
|
39888
|
+
}
|
|
39889
|
+
return projects.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
39890
|
+
} catch {
|
|
39891
|
+
return [];
|
|
39892
|
+
}
|
|
39893
|
+
}
|
|
39894
|
+
async function readProject(cwd2, id) {
|
|
39895
|
+
try {
|
|
39896
|
+
const raw = await readFile2(projectPath(cwd2, id), "utf-8");
|
|
39897
|
+
const project = JSON.parse(raw);
|
|
39898
|
+
if (!project?.id || !project?.name)
|
|
39899
|
+
return null;
|
|
39900
|
+
return project;
|
|
39901
|
+
} catch {
|
|
39902
|
+
return null;
|
|
39903
|
+
}
|
|
39904
|
+
}
|
|
39905
|
+
async function findProjectByName(cwd2, name) {
|
|
39906
|
+
const normalized = normalizeName(name);
|
|
39907
|
+
const projects = await listProjects(cwd2);
|
|
39908
|
+
return projects.find((project) => normalizeName(project.name) === normalized) || null;
|
|
39909
|
+
}
|
|
39910
|
+
async function saveProject(cwd2, project) {
|
|
39911
|
+
await ensureProjectsDir(cwd2);
|
|
39912
|
+
await writeFile2(projectPath(cwd2, project.id), JSON.stringify(project, null, 2), "utf-8");
|
|
39913
|
+
}
|
|
39914
|
+
async function deleteProject(cwd2, id) {
|
|
39915
|
+
try {
|
|
39916
|
+
await unlink2(projectPath(cwd2, id));
|
|
39917
|
+
return true;
|
|
39918
|
+
} catch {
|
|
39919
|
+
return false;
|
|
39920
|
+
}
|
|
39921
|
+
}
|
|
39922
|
+
async function createProject(cwd2, name, description) {
|
|
39923
|
+
const now2 = Date.now();
|
|
39924
|
+
const project = {
|
|
39925
|
+
id: generateId(),
|
|
39926
|
+
name: name.trim(),
|
|
39927
|
+
description: description?.trim() || undefined,
|
|
39928
|
+
createdAt: now2,
|
|
39929
|
+
updatedAt: now2,
|
|
39930
|
+
context: [],
|
|
39931
|
+
plans: []
|
|
39932
|
+
};
|
|
39933
|
+
await saveProject(cwd2, project);
|
|
39934
|
+
return project;
|
|
39935
|
+
}
|
|
39936
|
+
async function updateProject(cwd2, id, updater) {
|
|
39937
|
+
const project = await readProject(cwd2, id);
|
|
39938
|
+
if (!project)
|
|
39939
|
+
return null;
|
|
39940
|
+
const updated = updater(project);
|
|
39941
|
+
await saveProject(cwd2, updated);
|
|
39942
|
+
return updated;
|
|
39943
|
+
}
|
|
39944
|
+
async function ensureDefaultProject(cwd2) {
|
|
39945
|
+
const projects = await listProjects(cwd2);
|
|
39946
|
+
if (projects.length > 0)
|
|
39947
|
+
return projects[0];
|
|
39948
|
+
return createProject(cwd2, "default", "Default project for this folder");
|
|
39949
|
+
}
|
|
39950
|
+
function hasProjectNameConflict(projects, name) {
|
|
39951
|
+
const normalized = normalizeName(name);
|
|
39952
|
+
return projects.some((project) => normalizeName(project.name) === normalized);
|
|
39953
|
+
}
|
|
39954
|
+
|
|
39955
|
+
// packages/core/src/projects/context.ts
|
|
39956
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
39957
|
+
import { resolve as resolve4 } from "path";
|
|
39958
|
+
var DEFAULT_MAX_FILE_BYTES = 12000;
|
|
39959
|
+
function formatPlan(plan) {
|
|
39960
|
+
const lines = [];
|
|
39961
|
+
lines.push(`- ${plan.title} (${plan.steps.length} steps)`);
|
|
39962
|
+
for (const step of plan.steps) {
|
|
39963
|
+
lines.push(` - [${step.status}] ${step.text}`);
|
|
39964
|
+
}
|
|
39965
|
+
return lines.join(`
|
|
39966
|
+
`);
|
|
39967
|
+
}
|
|
39968
|
+
function normalizeEntryLabel(entry) {
|
|
39969
|
+
return entry.label ? entry.label.trim() : entry.value.trim();
|
|
39970
|
+
}
|
|
39971
|
+
async function renderFileEntry(entry, options) {
|
|
39972
|
+
const rawPath = entry.value.trim();
|
|
39973
|
+
const resolved = resolve4(options.cwd, rawPath);
|
|
39974
|
+
const validation = await validatePath(resolved, { allowedPaths: [options.cwd] });
|
|
39975
|
+
if (!validation.valid) {
|
|
39976
|
+
return `- File: ${rawPath} (unavailable: ${validation.error || "invalid path"})`;
|
|
39977
|
+
}
|
|
39978
|
+
let content = "";
|
|
39979
|
+
try {
|
|
39980
|
+
const data = await readFile3(validation.resolved, "utf-8");
|
|
39981
|
+
const limit = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
39982
|
+
if (data.length > limit) {
|
|
39983
|
+
content = `${data.slice(0, limit)}
|
|
39984
|
+
|
|
39985
|
+
... [truncated ${data.length - limit} chars]`;
|
|
39986
|
+
} else {
|
|
39987
|
+
content = data;
|
|
39988
|
+
}
|
|
39989
|
+
} catch (error) {
|
|
39990
|
+
return `- File: ${rawPath} (unavailable: ${error instanceof Error ? error.message : String(error)})`;
|
|
39991
|
+
}
|
|
39992
|
+
return `- File: ${rawPath}
|
|
39993
|
+
\`\`\`
|
|
39994
|
+
${content}
|
|
39995
|
+
\`\`\``;
|
|
39996
|
+
}
|
|
39997
|
+
function renderConnectorEntry(entry, connectors) {
|
|
39998
|
+
const name = entry.value.trim();
|
|
39999
|
+
const connector = connectors?.find((c) => c.name === name);
|
|
40000
|
+
if (!connector) {
|
|
40001
|
+
return `- Connector: ${name}`;
|
|
40002
|
+
}
|
|
40003
|
+
const lines = [];
|
|
40004
|
+
lines.push(`- Connector: ${connector.name}`);
|
|
40005
|
+
if (connector.description) {
|
|
40006
|
+
lines.push(` - ${connector.description}`);
|
|
40007
|
+
}
|
|
40008
|
+
if (connector.cli) {
|
|
40009
|
+
lines.push(` - CLI: ${connector.cli}`);
|
|
40010
|
+
}
|
|
40011
|
+
if (connector.commands && connector.commands.length > 0) {
|
|
40012
|
+
const subset = connector.commands.slice(0, 5);
|
|
40013
|
+
for (const cmd of subset) {
|
|
40014
|
+
lines.push(` - ${cmd.name}: ${cmd.description}`);
|
|
40015
|
+
}
|
|
40016
|
+
if (connector.commands.length > subset.length) {
|
|
40017
|
+
lines.push(` - ... ${connector.commands.length - subset.length} more commands`);
|
|
40018
|
+
}
|
|
40019
|
+
}
|
|
40020
|
+
return lines.join(`
|
|
40021
|
+
`);
|
|
40022
|
+
}
|
|
40023
|
+
function renderGenericEntry(entry) {
|
|
40024
|
+
const label = normalizeEntryLabel(entry);
|
|
40025
|
+
return `- ${entry.type}: ${label}`;
|
|
40026
|
+
}
|
|
40027
|
+
async function buildProjectContext(project, options) {
|
|
40028
|
+
const lines = [];
|
|
40029
|
+
lines.push(`## Project: ${project.name}`);
|
|
40030
|
+
if (project.description) {
|
|
40031
|
+
lines.push(`Description: ${project.description}`);
|
|
40032
|
+
}
|
|
40033
|
+
if (project.context.length > 0) {
|
|
40034
|
+
lines.push("");
|
|
40035
|
+
lines.push("### Project Context");
|
|
40036
|
+
for (const entry of project.context) {
|
|
40037
|
+
if (entry.type === "file") {
|
|
40038
|
+
lines.push(await renderFileEntry(entry, options));
|
|
40039
|
+
continue;
|
|
40040
|
+
}
|
|
40041
|
+
if (entry.type === "connector") {
|
|
40042
|
+
lines.push(renderConnectorEntry(entry, options.connectors));
|
|
40043
|
+
continue;
|
|
40044
|
+
}
|
|
40045
|
+
lines.push(renderGenericEntry(entry));
|
|
40046
|
+
}
|
|
40047
|
+
}
|
|
40048
|
+
if (project.plans.length > 0) {
|
|
40049
|
+
lines.push("");
|
|
40050
|
+
lines.push("### Plans");
|
|
40051
|
+
for (const plan of project.plans) {
|
|
40052
|
+
lines.push(formatPlan(plan));
|
|
40053
|
+
}
|
|
40054
|
+
}
|
|
40055
|
+
return lines.join(`
|
|
40056
|
+
`);
|
|
40057
|
+
}
|
|
40058
|
+
|
|
40059
|
+
// packages/core/src/commands/builtin.ts
|
|
40060
|
+
var VERSION = process.env.ASSISTANTS_VERSION || process.env.npm_package_version || process.env.OLDPAL_VERSION || "unknown";
|
|
40061
|
+
function resolveAuthTimeout(resolve5) {
|
|
40062
|
+
resolve5({ exitCode: 1, stdout: { toString: () => "{}" } });
|
|
39747
40063
|
}
|
|
39748
40064
|
function splitArgs(input) {
|
|
39749
40065
|
const args = [];
|
|
@@ -39792,6 +40108,8 @@ class BuiltinCommands {
|
|
|
39792
40108
|
loader.register(this.statusCommand());
|
|
39793
40109
|
loader.register(this.tokensCommand());
|
|
39794
40110
|
loader.register(this.contextCommand());
|
|
40111
|
+
loader.register(this.projectsCommand());
|
|
40112
|
+
loader.register(this.plansCommand());
|
|
39795
40113
|
loader.register(this.summarizeCommand());
|
|
39796
40114
|
loader.register(this.restCommand());
|
|
39797
40115
|
loader.register(this.voiceCommand());
|
|
@@ -40397,130 +40715,722 @@ Identities:
|
|
|
40397
40715
|
contextCommand() {
|
|
40398
40716
|
return {
|
|
40399
40717
|
name: "context",
|
|
40400
|
-
description: "
|
|
40718
|
+
description: "Manage injected project context (files, connectors, notes) or show status",
|
|
40401
40719
|
builtin: true,
|
|
40402
40720
|
selfHandled: true,
|
|
40403
40721
|
content: "",
|
|
40404
40722
|
handler: async (args, context) => {
|
|
40405
|
-
const
|
|
40406
|
-
|
|
40723
|
+
const parts = splitArgs(args);
|
|
40724
|
+
const sub = parts[0] || "status";
|
|
40725
|
+
if (sub === "help") {
|
|
40726
|
+
const usage = [
|
|
40727
|
+
"Usage:",
|
|
40728
|
+
" /context status",
|
|
40729
|
+
" /context list",
|
|
40730
|
+
" /context add file <path>",
|
|
40731
|
+
" /context add connector <name>",
|
|
40732
|
+
" /context add database <name>",
|
|
40733
|
+
" /context add note <text>",
|
|
40734
|
+
" /context add entity <text>",
|
|
40735
|
+
" /context remove <id>",
|
|
40736
|
+
" /context clear"
|
|
40737
|
+
].join(`
|
|
40738
|
+
`);
|
|
40407
40739
|
context.emit("text", `
|
|
40408
|
-
|
|
40740
|
+
${usage}
|
|
40409
40741
|
`);
|
|
40410
40742
|
context.emit("done");
|
|
40411
40743
|
return { handled: true };
|
|
40412
40744
|
}
|
|
40413
|
-
|
|
40414
|
-
|
|
40415
|
-
|
|
40745
|
+
if (sub === "status") {
|
|
40746
|
+
const info = context.getContextInfo?.();
|
|
40747
|
+
if (!info) {
|
|
40748
|
+
context.emit("text", `
|
|
40749
|
+
Context summarization is not available.
|
|
40750
|
+
`);
|
|
40751
|
+
context.emit("done");
|
|
40752
|
+
return { handled: true };
|
|
40753
|
+
}
|
|
40754
|
+
const { config, state } = info;
|
|
40755
|
+
const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
|
|
40756
|
+
let message = `
|
|
40416
40757
|
**Context Status**
|
|
40417
40758
|
|
|
40418
40759
|
`;
|
|
40419
|
-
|
|
40760
|
+
message += `**Messages:** ${state.messageCount}
|
|
40420
40761
|
`;
|
|
40421
|
-
|
|
40762
|
+
message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
|
|
40422
40763
|
`;
|
|
40423
|
-
|
|
40764
|
+
message += `**Summary Count:** ${state.summaryCount}
|
|
40424
40765
|
`;
|
|
40425
|
-
|
|
40766
|
+
message += `**Strategy:** ${config.summaryStrategy}
|
|
40426
40767
|
`;
|
|
40427
|
-
|
|
40768
|
+
message += `**Keep Recent Messages:** ${config.keepRecentMessages}
|
|
40428
40769
|
`;
|
|
40429
|
-
|
|
40430
|
-
|
|
40770
|
+
if (state.lastSummaryAt) {
|
|
40771
|
+
message += `**Last Summary:** ${state.lastSummaryAt}
|
|
40431
40772
|
`;
|
|
40432
|
-
|
|
40433
|
-
|
|
40773
|
+
if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
|
|
40774
|
+
message += `**Last Summary Tokens:** ${state.lastSummaryTokensBefore.toLocaleString()} -> ${state.lastSummaryTokensAfter.toLocaleString()}
|
|
40434
40775
|
`;
|
|
40776
|
+
}
|
|
40435
40777
|
}
|
|
40436
|
-
|
|
40437
|
-
|
|
40438
|
-
|
|
40439
|
-
|
|
40440
|
-
message += `
|
|
40778
|
+
const barLength = 30;
|
|
40779
|
+
const filledLength = Math.round(usedPercent / 100 * barLength);
|
|
40780
|
+
const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
|
|
40781
|
+
message += `
|
|
40441
40782
|
[${bar}] ${usedPercent}%
|
|
40442
40783
|
`;
|
|
40443
|
-
|
|
40444
|
-
context.emit("done");
|
|
40445
|
-
return { handled: true };
|
|
40446
|
-
}
|
|
40447
|
-
};
|
|
40448
|
-
}
|
|
40449
|
-
summarizeCommand() {
|
|
40450
|
-
return {
|
|
40451
|
-
name: "summarize",
|
|
40452
|
-
description: "Summarize and compress the current conversation",
|
|
40453
|
-
builtin: true,
|
|
40454
|
-
selfHandled: true,
|
|
40455
|
-
content: "",
|
|
40456
|
-
handler: async (args, context) => {
|
|
40457
|
-
if (!context.summarizeContext) {
|
|
40458
|
-
context.emit("text", `
|
|
40459
|
-
Context summarization is not available.
|
|
40460
|
-
`);
|
|
40784
|
+
context.emit("text", message);
|
|
40461
40785
|
context.emit("done");
|
|
40462
40786
|
return { handled: true };
|
|
40463
40787
|
}
|
|
40464
|
-
const
|
|
40465
|
-
if (!
|
|
40466
|
-
context.emit("text", `
|
|
40467
|
-
Nothing to summarize right now.
|
|
40788
|
+
const project = await this.ensureActiveProject(context, true);
|
|
40789
|
+
if (!project) {
|
|
40790
|
+
context.emit("text", `No project found. Use /projects new <name> first.
|
|
40468
40791
|
`);
|
|
40469
40792
|
context.emit("done");
|
|
40470
40793
|
return { handled: true };
|
|
40471
40794
|
}
|
|
40472
|
-
|
|
40473
|
-
|
|
40474
|
-
|
|
40475
|
-
|
|
40476
|
-
|
|
40477
|
-
|
|
40478
|
-
|
|
40795
|
+
if (sub === "list") {
|
|
40796
|
+
if (project.context.length === 0) {
|
|
40797
|
+
context.emit("text", `
|
|
40798
|
+
No context entries for project "${project.name}".
|
|
40799
|
+
`);
|
|
40800
|
+
context.emit("done");
|
|
40801
|
+
return { handled: true };
|
|
40802
|
+
}
|
|
40803
|
+
let output = `
|
|
40804
|
+
**Context Entries (${project.name})**
|
|
40479
40805
|
|
|
40480
40806
|
`;
|
|
40481
|
-
|
|
40482
|
-
|
|
40807
|
+
for (const entry of project.context) {
|
|
40808
|
+
const label = entry.label ? ` (${entry.label})` : "";
|
|
40809
|
+
output += `- ${entry.id} [${entry.type}] ${entry.value}${label}
|
|
40483
40810
|
`;
|
|
40811
|
+
}
|
|
40812
|
+
context.emit("text", output);
|
|
40813
|
+
context.emit("done");
|
|
40814
|
+
return { handled: true };
|
|
40484
40815
|
}
|
|
40485
|
-
|
|
40816
|
+
if (sub === "clear") {
|
|
40817
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40818
|
+
...current,
|
|
40819
|
+
context: [],
|
|
40820
|
+
updatedAt: Date.now()
|
|
40821
|
+
}));
|
|
40822
|
+
if (updated) {
|
|
40823
|
+
await this.applyProjectContext(context, updated);
|
|
40824
|
+
context.emit("text", `Cleared context entries for "${updated.name}".
|
|
40825
|
+
`);
|
|
40826
|
+
context.emit("done");
|
|
40827
|
+
return { handled: true };
|
|
40828
|
+
}
|
|
40829
|
+
}
|
|
40830
|
+
if (sub === "remove") {
|
|
40831
|
+
const id = parts[1];
|
|
40832
|
+
if (!id) {
|
|
40833
|
+
context.emit("text", `Usage: /context remove <id>
|
|
40834
|
+
`);
|
|
40835
|
+
context.emit("done");
|
|
40836
|
+
return { handled: true };
|
|
40837
|
+
}
|
|
40838
|
+
if (!project.context.some((entry) => entry.id === id)) {
|
|
40839
|
+
context.emit("text", `Context entry not found: ${id}
|
|
40840
|
+
`);
|
|
40841
|
+
context.emit("done");
|
|
40842
|
+
return { handled: true };
|
|
40843
|
+
}
|
|
40844
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40845
|
+
...current,
|
|
40846
|
+
context: current.context.filter((entry) => entry.id !== id),
|
|
40847
|
+
updatedAt: Date.now()
|
|
40848
|
+
}));
|
|
40849
|
+
if (updated) {
|
|
40850
|
+
await this.applyProjectContext(context, updated);
|
|
40851
|
+
context.emit("text", `Removed context entry ${id} from "${updated.name}".
|
|
40852
|
+
`);
|
|
40853
|
+
context.emit("done");
|
|
40854
|
+
return { handled: true };
|
|
40855
|
+
}
|
|
40856
|
+
}
|
|
40857
|
+
if (sub === "add") {
|
|
40858
|
+
const type = parts[1];
|
|
40859
|
+
const value = parts.slice(2).join(" ").trim();
|
|
40860
|
+
if (!type) {
|
|
40861
|
+
context.emit("text", `Usage: /context add <type> <value>
|
|
40862
|
+
`);
|
|
40863
|
+
context.emit("done");
|
|
40864
|
+
return { handled: true };
|
|
40865
|
+
}
|
|
40866
|
+
const allowedTypes = ["file", "connector", "database", "note", "entity"];
|
|
40867
|
+
const entryType = allowedTypes.includes(type) ? type : "note";
|
|
40868
|
+
const entryValue = entryType === "note" && !value ? parts.slice(1).join(" ").trim() : value;
|
|
40869
|
+
if (!entryValue) {
|
|
40870
|
+
context.emit("text", `Error: context value is required.
|
|
40871
|
+
`);
|
|
40872
|
+
context.emit("done");
|
|
40873
|
+
return { handled: true };
|
|
40874
|
+
}
|
|
40875
|
+
const entry = {
|
|
40876
|
+
id: generateId(),
|
|
40877
|
+
type: entryType,
|
|
40878
|
+
value: entryValue,
|
|
40879
|
+
addedAt: Date.now()
|
|
40880
|
+
};
|
|
40881
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40882
|
+
...current,
|
|
40883
|
+
context: [...current.context, entry],
|
|
40884
|
+
updatedAt: Date.now()
|
|
40885
|
+
}));
|
|
40886
|
+
if (updated) {
|
|
40887
|
+
await this.applyProjectContext(context, updated);
|
|
40888
|
+
context.emit("text", `Added ${entry.type} context to "${updated.name}".
|
|
40889
|
+
`);
|
|
40890
|
+
context.emit("done");
|
|
40891
|
+
return { handled: true };
|
|
40892
|
+
}
|
|
40893
|
+
}
|
|
40894
|
+
context.emit("text", `Unknown /context command. Use /context help.
|
|
40895
|
+
`);
|
|
40486
40896
|
context.emit("done");
|
|
40487
40897
|
return { handled: true };
|
|
40488
40898
|
}
|
|
40489
40899
|
};
|
|
40490
40900
|
}
|
|
40491
|
-
|
|
40901
|
+
projectsCommand() {
|
|
40492
40902
|
return {
|
|
40493
|
-
name: "
|
|
40494
|
-
description: "
|
|
40903
|
+
name: "projects",
|
|
40904
|
+
description: "Manage projects inside this folder",
|
|
40495
40905
|
builtin: true,
|
|
40496
40906
|
selfHandled: true,
|
|
40497
40907
|
content: "",
|
|
40498
40908
|
handler: async (args, context) => {
|
|
40499
|
-
|
|
40909
|
+
const parts = splitArgs(args);
|
|
40910
|
+
const sub = parts[0] || "list";
|
|
40911
|
+
if (sub === "help") {
|
|
40912
|
+
const usage = [
|
|
40913
|
+
"Usage:",
|
|
40914
|
+
" /projects list",
|
|
40915
|
+
" /projects new <name>",
|
|
40916
|
+
" /projects use <id|name>",
|
|
40917
|
+
" /projects show [id|name]",
|
|
40918
|
+
" /projects delete <id|name>",
|
|
40919
|
+
" /projects describe <id|name> <description>"
|
|
40920
|
+
].join(`
|
|
40921
|
+
`);
|
|
40500
40922
|
context.emit("text", `
|
|
40501
|
-
|
|
40923
|
+
${usage}
|
|
40502
40924
|
`);
|
|
40503
40925
|
context.emit("done");
|
|
40504
40926
|
return { handled: true };
|
|
40505
40927
|
}
|
|
40506
|
-
|
|
40507
|
-
|
|
40508
|
-
|
|
40509
|
-
|
|
40510
|
-
|
|
40511
|
-
const percent = Math.round(state.current / Math.max(1, state.max) * 100);
|
|
40512
|
-
context.emit("text", `
|
|
40513
|
-
Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
|
|
40514
|
-
`);
|
|
40515
|
-
} else {
|
|
40516
|
-
context.emit("text", `
|
|
40517
|
-
Energy restored.
|
|
40928
|
+
if (sub === "list" || sub === "ls") {
|
|
40929
|
+
const projects = await listProjects(context.cwd);
|
|
40930
|
+
if (projects.length === 0) {
|
|
40931
|
+
context.emit("text", `
|
|
40932
|
+
No projects found. Use /projects new <name>.
|
|
40518
40933
|
`);
|
|
40519
|
-
|
|
40520
|
-
|
|
40521
|
-
|
|
40522
|
-
|
|
40523
|
-
|
|
40934
|
+
context.emit("done");
|
|
40935
|
+
return { handled: true };
|
|
40936
|
+
}
|
|
40937
|
+
const activeId = context.getActiveProjectId?.();
|
|
40938
|
+
let output = `
|
|
40939
|
+
**Projects**
|
|
40940
|
+
|
|
40941
|
+
`;
|
|
40942
|
+
for (const project of projects) {
|
|
40943
|
+
const marker = project.id === activeId ? "*" : " ";
|
|
40944
|
+
output += `${marker} ${project.name} (${project.id})
|
|
40945
|
+
`;
|
|
40946
|
+
}
|
|
40947
|
+
context.emit("text", output);
|
|
40948
|
+
context.emit("done");
|
|
40949
|
+
return { handled: true };
|
|
40950
|
+
}
|
|
40951
|
+
if (sub === "new" || sub === "create") {
|
|
40952
|
+
const name = parts.slice(1).join(" ").trim();
|
|
40953
|
+
if (!name) {
|
|
40954
|
+
context.emit("text", `Usage: /projects new <name>
|
|
40955
|
+
`);
|
|
40956
|
+
context.emit("done");
|
|
40957
|
+
return { handled: true };
|
|
40958
|
+
}
|
|
40959
|
+
const existing = await listProjects(context.cwd);
|
|
40960
|
+
if (hasProjectNameConflict(existing, name)) {
|
|
40961
|
+
context.emit("text", `Project "${name}" already exists.
|
|
40962
|
+
`);
|
|
40963
|
+
context.emit("done");
|
|
40964
|
+
return { handled: true };
|
|
40965
|
+
}
|
|
40966
|
+
const project = await createProject(context.cwd, name);
|
|
40967
|
+
context.setActiveProjectId?.(project.id);
|
|
40968
|
+
await this.applyProjectContext(context, project);
|
|
40969
|
+
context.emit("text", `Created project "${project.name}" (${project.id}).
|
|
40970
|
+
`);
|
|
40971
|
+
context.emit("done");
|
|
40972
|
+
return { handled: true };
|
|
40973
|
+
}
|
|
40974
|
+
if (sub === "use" || sub === "switch") {
|
|
40975
|
+
const target = parts.slice(1).join(" ").trim();
|
|
40976
|
+
if (!target) {
|
|
40977
|
+
context.emit("text", `Usage: /projects use <id|name>
|
|
40978
|
+
`);
|
|
40979
|
+
context.emit("done");
|
|
40980
|
+
return { handled: true };
|
|
40981
|
+
}
|
|
40982
|
+
const project = await this.resolveProject(context, target);
|
|
40983
|
+
if (!project) {
|
|
40984
|
+
context.emit("text", `Project not found: ${target}
|
|
40985
|
+
`);
|
|
40986
|
+
context.emit("done");
|
|
40987
|
+
return { handled: true };
|
|
40988
|
+
}
|
|
40989
|
+
context.setActiveProjectId?.(project.id);
|
|
40990
|
+
await this.applyProjectContext(context, project);
|
|
40991
|
+
context.emit("text", `Switched to project "${project.name}".
|
|
40992
|
+
`);
|
|
40993
|
+
context.emit("done");
|
|
40994
|
+
return { handled: true };
|
|
40995
|
+
}
|
|
40996
|
+
if (sub === "show" || sub === "info") {
|
|
40997
|
+
const target = parts.slice(1).join(" ").trim();
|
|
40998
|
+
const project = target ? await this.resolveProject(context, target) : await this.ensureActiveProject(context, false);
|
|
40999
|
+
if (!project) {
|
|
41000
|
+
context.emit("text", `No project selected. Use /projects use <id|name>.
|
|
41001
|
+
`);
|
|
41002
|
+
context.emit("done");
|
|
41003
|
+
return { handled: true };
|
|
41004
|
+
}
|
|
41005
|
+
let output = `
|
|
41006
|
+
**Project: ${project.name}**
|
|
41007
|
+
|
|
41008
|
+
`;
|
|
41009
|
+
output += `ID: ${project.id}
|
|
41010
|
+
`;
|
|
41011
|
+
if (project.description) {
|
|
41012
|
+
output += `Description: ${project.description}
|
|
41013
|
+
`;
|
|
41014
|
+
}
|
|
41015
|
+
output += `Context entries: ${project.context.length}
|
|
41016
|
+
`;
|
|
41017
|
+
output += `Plans: ${project.plans.length}
|
|
41018
|
+
`;
|
|
41019
|
+
context.emit("text", output);
|
|
41020
|
+
context.emit("done");
|
|
41021
|
+
return { handled: true };
|
|
41022
|
+
}
|
|
41023
|
+
if (sub === "describe" || sub === "desc") {
|
|
41024
|
+
const target = parts[1];
|
|
41025
|
+
const description = parts.slice(2).join(" ").trim();
|
|
41026
|
+
if (!target || !description) {
|
|
41027
|
+
context.emit("text", `Usage: /projects describe <id|name> <description>
|
|
41028
|
+
`);
|
|
41029
|
+
context.emit("done");
|
|
41030
|
+
return { handled: true };
|
|
41031
|
+
}
|
|
41032
|
+
const project = await this.resolveProject(context, target);
|
|
41033
|
+
if (!project) {
|
|
41034
|
+
context.emit("text", `Project not found: ${target}
|
|
41035
|
+
`);
|
|
41036
|
+
context.emit("done");
|
|
41037
|
+
return { handled: true };
|
|
41038
|
+
}
|
|
41039
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41040
|
+
...current,
|
|
41041
|
+
description,
|
|
41042
|
+
updatedAt: Date.now()
|
|
41043
|
+
}));
|
|
41044
|
+
if (updated) {
|
|
41045
|
+
await this.applyProjectContext(context, updated);
|
|
41046
|
+
context.emit("text", `Updated project "${updated.name}".
|
|
41047
|
+
`);
|
|
41048
|
+
context.emit("done");
|
|
41049
|
+
return { handled: true };
|
|
41050
|
+
}
|
|
41051
|
+
}
|
|
41052
|
+
if (sub === "delete" || sub === "rm") {
|
|
41053
|
+
const target = parts.slice(1).join(" ").trim();
|
|
41054
|
+
if (!target) {
|
|
41055
|
+
context.emit("text", `Usage: /projects delete <id|name>
|
|
41056
|
+
`);
|
|
41057
|
+
context.emit("done");
|
|
41058
|
+
return { handled: true };
|
|
41059
|
+
}
|
|
41060
|
+
const project = await this.resolveProject(context, target);
|
|
41061
|
+
if (!project) {
|
|
41062
|
+
context.emit("text", `Project not found: ${target}
|
|
41063
|
+
`);
|
|
41064
|
+
context.emit("done");
|
|
41065
|
+
return { handled: true };
|
|
41066
|
+
}
|
|
41067
|
+
const ok = await deleteProject(context.cwd, project.id);
|
|
41068
|
+
if (ok) {
|
|
41069
|
+
if (context.getActiveProjectId?.() === project.id) {
|
|
41070
|
+
context.setActiveProjectId?.(null);
|
|
41071
|
+
context.setProjectContext?.(null);
|
|
41072
|
+
}
|
|
41073
|
+
context.emit("text", `Deleted project "${project.name}".
|
|
41074
|
+
`);
|
|
41075
|
+
context.emit("done");
|
|
41076
|
+
return { handled: true };
|
|
41077
|
+
}
|
|
41078
|
+
}
|
|
41079
|
+
context.emit("text", `Unknown /projects command. Use /projects help.
|
|
41080
|
+
`);
|
|
41081
|
+
context.emit("done");
|
|
41082
|
+
return { handled: true };
|
|
41083
|
+
}
|
|
41084
|
+
};
|
|
41085
|
+
}
|
|
41086
|
+
plansCommand() {
|
|
41087
|
+
return {
|
|
41088
|
+
name: "plans",
|
|
41089
|
+
description: "Manage plans linked to the active project",
|
|
41090
|
+
builtin: true,
|
|
41091
|
+
selfHandled: true,
|
|
41092
|
+
content: "",
|
|
41093
|
+
handler: async (args, context) => {
|
|
41094
|
+
const parts = splitArgs(args);
|
|
41095
|
+
const sub = parts[0] || "list";
|
|
41096
|
+
if (sub === "help") {
|
|
41097
|
+
const usage = [
|
|
41098
|
+
"Usage:",
|
|
41099
|
+
" /plans list",
|
|
41100
|
+
" /plans new <title>",
|
|
41101
|
+
" /plans show <planId>",
|
|
41102
|
+
" /plans add <planId> <step>",
|
|
41103
|
+
" /plans set <planId> <stepId> <todo|doing|done|blocked>",
|
|
41104
|
+
" /plans remove <planId> <stepId>",
|
|
41105
|
+
" /plans delete <planId>"
|
|
41106
|
+
].join(`
|
|
41107
|
+
`);
|
|
41108
|
+
context.emit("text", `
|
|
41109
|
+
${usage}
|
|
41110
|
+
`);
|
|
41111
|
+
context.emit("done");
|
|
41112
|
+
return { handled: true };
|
|
41113
|
+
}
|
|
41114
|
+
const project = await this.ensureActiveProject(context, true);
|
|
41115
|
+
if (!project) {
|
|
41116
|
+
context.emit("text", `No project found. Use /projects new <name> first.
|
|
41117
|
+
`);
|
|
41118
|
+
context.emit("done");
|
|
41119
|
+
return { handled: true };
|
|
41120
|
+
}
|
|
41121
|
+
if (sub === "list" || sub === "ls") {
|
|
41122
|
+
if (project.plans.length === 0) {
|
|
41123
|
+
context.emit("text", `
|
|
41124
|
+
No plans for project "${project.name}".
|
|
41125
|
+
`);
|
|
41126
|
+
context.emit("done");
|
|
41127
|
+
return { handled: true };
|
|
41128
|
+
}
|
|
41129
|
+
let output = `
|
|
41130
|
+
**Plans (${project.name})**
|
|
41131
|
+
|
|
41132
|
+
`;
|
|
41133
|
+
for (const plan of project.plans) {
|
|
41134
|
+
output += `- ${plan.id} ${plan.title} (${plan.steps.length} steps)
|
|
41135
|
+
`;
|
|
41136
|
+
}
|
|
41137
|
+
context.emit("text", output);
|
|
41138
|
+
context.emit("done");
|
|
41139
|
+
return { handled: true };
|
|
41140
|
+
}
|
|
41141
|
+
if (sub === "new" || sub === "create") {
|
|
41142
|
+
const title = parts.slice(1).join(" ").trim();
|
|
41143
|
+
if (!title) {
|
|
41144
|
+
context.emit("text", `Usage: /plans new <title>
|
|
41145
|
+
`);
|
|
41146
|
+
context.emit("done");
|
|
41147
|
+
return { handled: true };
|
|
41148
|
+
}
|
|
41149
|
+
const now2 = Date.now();
|
|
41150
|
+
const plan = {
|
|
41151
|
+
id: generateId(),
|
|
41152
|
+
title,
|
|
41153
|
+
createdAt: now2,
|
|
41154
|
+
updatedAt: now2,
|
|
41155
|
+
steps: []
|
|
41156
|
+
};
|
|
41157
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41158
|
+
...current,
|
|
41159
|
+
plans: [...current.plans, plan],
|
|
41160
|
+
updatedAt: now2
|
|
41161
|
+
}));
|
|
41162
|
+
if (updated) {
|
|
41163
|
+
await this.applyProjectContext(context, updated);
|
|
41164
|
+
context.emit("text", `Created plan "${plan.title}" (${plan.id}).
|
|
41165
|
+
`);
|
|
41166
|
+
context.emit("done");
|
|
41167
|
+
return { handled: true };
|
|
41168
|
+
}
|
|
41169
|
+
}
|
|
41170
|
+
if (sub === "show") {
|
|
41171
|
+
const id = parts[1];
|
|
41172
|
+
if (!id) {
|
|
41173
|
+
context.emit("text", `Usage: /plans show <planId>
|
|
41174
|
+
`);
|
|
41175
|
+
context.emit("done");
|
|
41176
|
+
return { handled: true };
|
|
41177
|
+
}
|
|
41178
|
+
const plan = project.plans.find((p) => p.id === id);
|
|
41179
|
+
if (!plan) {
|
|
41180
|
+
context.emit("text", `Plan not found: ${id}
|
|
41181
|
+
`);
|
|
41182
|
+
context.emit("done");
|
|
41183
|
+
return { handled: true };
|
|
41184
|
+
}
|
|
41185
|
+
let output = `
|
|
41186
|
+
**Plan: ${plan.title}**
|
|
41187
|
+
|
|
41188
|
+
`;
|
|
41189
|
+
output += `ID: ${plan.id}
|
|
41190
|
+
`;
|
|
41191
|
+
if (plan.steps.length === 0) {
|
|
41192
|
+
output += `No steps yet.
|
|
41193
|
+
`;
|
|
41194
|
+
} else {
|
|
41195
|
+
for (const step of plan.steps) {
|
|
41196
|
+
output += `- ${step.id} [${step.status}] ${step.text}
|
|
41197
|
+
`;
|
|
41198
|
+
}
|
|
41199
|
+
}
|
|
41200
|
+
context.emit("text", output);
|
|
41201
|
+
context.emit("done");
|
|
41202
|
+
return { handled: true };
|
|
41203
|
+
}
|
|
41204
|
+
if (sub === "add") {
|
|
41205
|
+
const planId = parts[1];
|
|
41206
|
+
const text = parts.slice(2).join(" ").trim();
|
|
41207
|
+
if (!planId || !text) {
|
|
41208
|
+
context.emit("text", `Usage: /plans add <planId> <step>
|
|
41209
|
+
`);
|
|
41210
|
+
context.emit("done");
|
|
41211
|
+
return { handled: true };
|
|
41212
|
+
}
|
|
41213
|
+
if (!project.plans.some((plan) => plan.id === planId)) {
|
|
41214
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41215
|
+
`);
|
|
41216
|
+
context.emit("done");
|
|
41217
|
+
return { handled: true };
|
|
41218
|
+
}
|
|
41219
|
+
const now2 = Date.now();
|
|
41220
|
+
const step = {
|
|
41221
|
+
id: generateId(),
|
|
41222
|
+
text,
|
|
41223
|
+
status: "todo",
|
|
41224
|
+
createdAt: now2,
|
|
41225
|
+
updatedAt: now2
|
|
41226
|
+
};
|
|
41227
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41228
|
+
...current,
|
|
41229
|
+
plans: current.plans.map((plan) => plan.id === planId ? { ...plan, steps: [...plan.steps, step], updatedAt: now2 } : plan),
|
|
41230
|
+
updatedAt: now2
|
|
41231
|
+
}));
|
|
41232
|
+
if (updated) {
|
|
41233
|
+
await this.applyProjectContext(context, updated);
|
|
41234
|
+
context.emit("text", `Added step to plan ${planId}.
|
|
41235
|
+
`);
|
|
41236
|
+
context.emit("done");
|
|
41237
|
+
return { handled: true };
|
|
41238
|
+
}
|
|
41239
|
+
}
|
|
41240
|
+
if (sub === "set") {
|
|
41241
|
+
const planId = parts[1];
|
|
41242
|
+
const stepId = parts[2];
|
|
41243
|
+
const status = parts[3];
|
|
41244
|
+
if (!planId || !stepId || !status) {
|
|
41245
|
+
context.emit("text", `Usage: /plans set <planId> <stepId> <todo|doing|done|blocked>
|
|
41246
|
+
`);
|
|
41247
|
+
context.emit("done");
|
|
41248
|
+
return { handled: true };
|
|
41249
|
+
}
|
|
41250
|
+
const plan = project.plans.find((item) => item.id === planId);
|
|
41251
|
+
if (!plan) {
|
|
41252
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41253
|
+
`);
|
|
41254
|
+
context.emit("done");
|
|
41255
|
+
return { handled: true };
|
|
41256
|
+
}
|
|
41257
|
+
if (!plan.steps.some((step) => step.id === stepId)) {
|
|
41258
|
+
context.emit("text", `Step not found: ${stepId}
|
|
41259
|
+
`);
|
|
41260
|
+
context.emit("done");
|
|
41261
|
+
return { handled: true };
|
|
41262
|
+
}
|
|
41263
|
+
const allowed = ["todo", "doing", "done", "blocked"];
|
|
41264
|
+
if (!allowed.includes(status)) {
|
|
41265
|
+
context.emit("text", `Invalid status. Use todo, doing, done, or blocked.
|
|
41266
|
+
`);
|
|
41267
|
+
context.emit("done");
|
|
41268
|
+
return { handled: true };
|
|
41269
|
+
}
|
|
41270
|
+
const now2 = Date.now();
|
|
41271
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41272
|
+
...current,
|
|
41273
|
+
plans: current.plans.map((plan2) => plan2.id === planId ? {
|
|
41274
|
+
...plan2,
|
|
41275
|
+
steps: plan2.steps.map((step) => step.id === stepId ? { ...step, status, updatedAt: now2 } : step),
|
|
41276
|
+
updatedAt: now2
|
|
41277
|
+
} : plan2),
|
|
41278
|
+
updatedAt: now2
|
|
41279
|
+
}));
|
|
41280
|
+
if (updated) {
|
|
41281
|
+
await this.applyProjectContext(context, updated);
|
|
41282
|
+
context.emit("text", `Updated step ${stepId} to ${status}.
|
|
41283
|
+
`);
|
|
41284
|
+
context.emit("done");
|
|
41285
|
+
return { handled: true };
|
|
41286
|
+
}
|
|
41287
|
+
}
|
|
41288
|
+
if (sub === "remove") {
|
|
41289
|
+
const planId = parts[1];
|
|
41290
|
+
const stepId = parts[2];
|
|
41291
|
+
if (!planId || !stepId) {
|
|
41292
|
+
context.emit("text", `Usage: /plans remove <planId> <stepId>
|
|
41293
|
+
`);
|
|
41294
|
+
context.emit("done");
|
|
41295
|
+
return { handled: true };
|
|
41296
|
+
}
|
|
41297
|
+
const plan = project.plans.find((item) => item.id === planId);
|
|
41298
|
+
if (!plan) {
|
|
41299
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41300
|
+
`);
|
|
41301
|
+
context.emit("done");
|
|
41302
|
+
return { handled: true };
|
|
41303
|
+
}
|
|
41304
|
+
if (!plan.steps.some((step) => step.id === stepId)) {
|
|
41305
|
+
context.emit("text", `Step not found: ${stepId}
|
|
41306
|
+
`);
|
|
41307
|
+
context.emit("done");
|
|
41308
|
+
return { handled: true };
|
|
41309
|
+
}
|
|
41310
|
+
const now2 = Date.now();
|
|
41311
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41312
|
+
...current,
|
|
41313
|
+
plans: current.plans.map((plan2) => plan2.id === planId ? { ...plan2, steps: plan2.steps.filter((step) => step.id !== stepId), updatedAt: now2 } : plan2),
|
|
41314
|
+
updatedAt: now2
|
|
41315
|
+
}));
|
|
41316
|
+
if (updated) {
|
|
41317
|
+
await this.applyProjectContext(context, updated);
|
|
41318
|
+
context.emit("text", `Removed step ${stepId} from plan ${planId}.
|
|
41319
|
+
`);
|
|
41320
|
+
context.emit("done");
|
|
41321
|
+
return { handled: true };
|
|
41322
|
+
}
|
|
41323
|
+
}
|
|
41324
|
+
if (sub === "delete" || sub === "rm") {
|
|
41325
|
+
const planId = parts[1];
|
|
41326
|
+
if (!planId) {
|
|
41327
|
+
context.emit("text", `Usage: /plans delete <planId>
|
|
41328
|
+
`);
|
|
41329
|
+
context.emit("done");
|
|
41330
|
+
return { handled: true };
|
|
41331
|
+
}
|
|
41332
|
+
if (!project.plans.some((plan) => plan.id === planId)) {
|
|
41333
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41334
|
+
`);
|
|
41335
|
+
context.emit("done");
|
|
41336
|
+
return { handled: true };
|
|
41337
|
+
}
|
|
41338
|
+
const now2 = Date.now();
|
|
41339
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41340
|
+
...current,
|
|
41341
|
+
plans: current.plans.filter((plan) => plan.id !== planId),
|
|
41342
|
+
updatedAt: now2
|
|
41343
|
+
}));
|
|
41344
|
+
if (updated) {
|
|
41345
|
+
await this.applyProjectContext(context, updated);
|
|
41346
|
+
context.emit("text", `Deleted plan ${planId}.
|
|
41347
|
+
`);
|
|
41348
|
+
context.emit("done");
|
|
41349
|
+
return { handled: true };
|
|
41350
|
+
}
|
|
41351
|
+
}
|
|
41352
|
+
context.emit("text", `Unknown /plans command. Use /plans help.
|
|
41353
|
+
`);
|
|
41354
|
+
context.emit("done");
|
|
41355
|
+
return { handled: true };
|
|
41356
|
+
}
|
|
41357
|
+
};
|
|
41358
|
+
}
|
|
41359
|
+
summarizeCommand() {
|
|
41360
|
+
return {
|
|
41361
|
+
name: "summarize",
|
|
41362
|
+
description: "Summarize and compress the current conversation",
|
|
41363
|
+
builtin: true,
|
|
41364
|
+
selfHandled: true,
|
|
41365
|
+
content: "",
|
|
41366
|
+
handler: async (args, context) => {
|
|
41367
|
+
if (!context.summarizeContext) {
|
|
41368
|
+
context.emit("text", `
|
|
41369
|
+
Context summarization is not available.
|
|
41370
|
+
`);
|
|
41371
|
+
context.emit("done");
|
|
41372
|
+
return { handled: true };
|
|
41373
|
+
}
|
|
41374
|
+
const result = await context.summarizeContext();
|
|
41375
|
+
if (!result.summarized) {
|
|
41376
|
+
context.emit("text", `
|
|
41377
|
+
Nothing to summarize right now.
|
|
41378
|
+
`);
|
|
41379
|
+
context.emit("done");
|
|
41380
|
+
return { handled: true };
|
|
41381
|
+
}
|
|
41382
|
+
let message = `
|
|
41383
|
+
**Context Summary Generated**
|
|
41384
|
+
|
|
41385
|
+
`;
|
|
41386
|
+
message += `Summarized ${result.summarizedCount} message(s).
|
|
41387
|
+
`;
|
|
41388
|
+
message += `Tokens: ${result.tokensBefore.toLocaleString()} -> ${result.tokensAfter.toLocaleString()}
|
|
41389
|
+
|
|
41390
|
+
`;
|
|
41391
|
+
if (result.summary) {
|
|
41392
|
+
message += `${result.summary}
|
|
41393
|
+
`;
|
|
41394
|
+
}
|
|
41395
|
+
context.emit("text", message);
|
|
41396
|
+
context.emit("done");
|
|
41397
|
+
return { handled: true };
|
|
41398
|
+
}
|
|
41399
|
+
};
|
|
41400
|
+
}
|
|
41401
|
+
restCommand() {
|
|
41402
|
+
return {
|
|
41403
|
+
name: "rest",
|
|
41404
|
+
description: "Recharge assistant energy",
|
|
41405
|
+
builtin: true,
|
|
41406
|
+
selfHandled: true,
|
|
41407
|
+
content: "",
|
|
41408
|
+
handler: async (args, context) => {
|
|
41409
|
+
if (!context.restEnergy) {
|
|
41410
|
+
context.emit("text", `
|
|
41411
|
+
Energy system is not available.
|
|
41412
|
+
`);
|
|
41413
|
+
context.emit("done");
|
|
41414
|
+
return { handled: true };
|
|
41415
|
+
}
|
|
41416
|
+
const parsed = parseInt(args.trim(), 10);
|
|
41417
|
+
const amount = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
41418
|
+
context.restEnergy(amount);
|
|
41419
|
+
const state = context.getEnergyState?.();
|
|
41420
|
+
if (state) {
|
|
41421
|
+
const percent = Math.round(state.current / Math.max(1, state.max) * 100);
|
|
41422
|
+
context.emit("text", `
|
|
41423
|
+
Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
|
|
41424
|
+
`);
|
|
41425
|
+
} else {
|
|
41426
|
+
context.emit("text", `
|
|
41427
|
+
Energy restored.
|
|
41428
|
+
`);
|
|
41429
|
+
}
|
|
41430
|
+
context.emit("done");
|
|
41431
|
+
return { handled: true };
|
|
41432
|
+
}
|
|
41433
|
+
};
|
|
40524
41434
|
}
|
|
40525
41435
|
skillsCommand(loader) {
|
|
40526
41436
|
return {
|
|
@@ -40562,7 +41472,7 @@ ${context.skills.length} skill(s) available.
|
|
|
40562
41472
|
statusCommand() {
|
|
40563
41473
|
return {
|
|
40564
41474
|
name: "status",
|
|
40565
|
-
description: "Show current session status and token usage",
|
|
41475
|
+
description: "Show current session status, energy, identity, and token usage",
|
|
40566
41476
|
builtin: true,
|
|
40567
41477
|
selfHandled: true,
|
|
40568
41478
|
content: "",
|
|
@@ -40572,11 +41482,46 @@ ${context.skills.length} skill(s) available.
|
|
|
40572
41482
|
let message = `
|
|
40573
41483
|
**Session Status**
|
|
40574
41484
|
|
|
41485
|
+
`;
|
|
41486
|
+
message += `**Session ID:** ${context.sessionId}
|
|
40575
41487
|
`;
|
|
40576
41488
|
message += `**Working Directory:** ${context.cwd}
|
|
40577
41489
|
`;
|
|
40578
|
-
|
|
41490
|
+
const assistant = context.getAssistantManager?.()?.getActive();
|
|
41491
|
+
const identity = context.getIdentityManager?.()?.getActive();
|
|
41492
|
+
if (assistant) {
|
|
41493
|
+
message += `**Assistant:** ${assistant.name}`;
|
|
41494
|
+
if (identity) {
|
|
41495
|
+
message += ` \xB7 ${identity.name}`;
|
|
41496
|
+
}
|
|
41497
|
+
message += `
|
|
40579
41498
|
`;
|
|
41499
|
+
}
|
|
41500
|
+
const energyState = context.getEnergyState?.();
|
|
41501
|
+
if (energyState) {
|
|
41502
|
+
const energyPercent = Math.round(energyState.current / Math.max(1, energyState.max) * 100);
|
|
41503
|
+
const energyBar = "\u2588".repeat(Math.round(energyPercent / 10)) + "\u2591".repeat(10 - Math.round(energyPercent / 10));
|
|
41504
|
+
const energyEmoji = energyPercent > 70 ? "\u26A1" : energyPercent > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
|
|
41505
|
+
message += `**Energy:** ${energyEmoji} [${energyBar}] ${energyPercent}% (${energyState.current}/${energyState.max})
|
|
41506
|
+
`;
|
|
41507
|
+
}
|
|
41508
|
+
const voiceState = context.getVoiceState?.();
|
|
41509
|
+
if (voiceState?.enabled) {
|
|
41510
|
+
const voiceActivity = voiceState.isSpeaking ? "speaking" : voiceState.isListening ? "listening" : "idle";
|
|
41511
|
+
message += `**Voice:** ${voiceActivity}`;
|
|
41512
|
+
if (voiceState.sttProvider || voiceState.ttsProvider) {
|
|
41513
|
+
message += ` (STT: ${voiceState.sttProvider || "n/a"}, TTS: ${voiceState.ttsProvider || "n/a"})`;
|
|
41514
|
+
}
|
|
41515
|
+
message += `
|
|
41516
|
+
`;
|
|
41517
|
+
}
|
|
41518
|
+
if (context.getActiveProjectId) {
|
|
41519
|
+
const projectId = context.getActiveProjectId();
|
|
41520
|
+
if (projectId) {
|
|
41521
|
+
message += `**Active Project:** ${projectId}
|
|
41522
|
+
`;
|
|
41523
|
+
}
|
|
41524
|
+
}
|
|
40580
41525
|
message += `**Messages:** ${context.messages.length}
|
|
40581
41526
|
`;
|
|
40582
41527
|
message += `**Available Tools:** ${context.tools.length}
|
|
@@ -40663,9 +41608,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40663
41608
|
content: "",
|
|
40664
41609
|
handler: async (args, context) => {
|
|
40665
41610
|
const configPaths = [
|
|
40666
|
-
|
|
40667
|
-
|
|
40668
|
-
|
|
41611
|
+
join11(context.cwd, ".assistants", "config.json"),
|
|
41612
|
+
join11(context.cwd, ".assistants", "config.local.json"),
|
|
41613
|
+
join11(getConfigDir(), "config.json")
|
|
40669
41614
|
];
|
|
40670
41615
|
let message = `
|
|
40671
41616
|
**Configuration**
|
|
@@ -40674,7 +41619,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40674
41619
|
message += `**Config File Locations:**
|
|
40675
41620
|
`;
|
|
40676
41621
|
for (const path2 of configPaths) {
|
|
40677
|
-
const exists =
|
|
41622
|
+
const exists = existsSync7(path2);
|
|
40678
41623
|
message += ` ${exists ? "\u2713" : "\u25CB"} ${path2}
|
|
40679
41624
|
`;
|
|
40680
41625
|
}
|
|
@@ -40683,9 +41628,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40683
41628
|
message += `
|
|
40684
41629
|
**Commands Directories:**
|
|
40685
41630
|
`;
|
|
40686
|
-
message += ` - Project: ${
|
|
41631
|
+
message += ` - Project: ${join11(context.cwd, ".assistants", "commands")}
|
|
40687
41632
|
`;
|
|
40688
|
-
message += ` - Global: ${
|
|
41633
|
+
message += ` - Global: ${join11(homeDir, ".assistants", "commands")}
|
|
40689
41634
|
`;
|
|
40690
41635
|
context.emit("text", message);
|
|
40691
41636
|
context.emit("done");
|
|
@@ -40701,8 +41646,8 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40701
41646
|
selfHandled: true,
|
|
40702
41647
|
content: "",
|
|
40703
41648
|
handler: async (args, context) => {
|
|
40704
|
-
const commandsDir =
|
|
40705
|
-
|
|
41649
|
+
const commandsDir = join11(context.cwd, ".assistants", "commands");
|
|
41650
|
+
mkdirSync3(commandsDir, { recursive: true });
|
|
40706
41651
|
const exampleCommand = `---
|
|
40707
41652
|
name: reflect
|
|
40708
41653
|
description: Reflect on the conversation and suggest next steps
|
|
@@ -40717,9 +41662,9 @@ Please summarize the last interaction and suggest 2-3 next steps.
|
|
|
40717
41662
|
- Focus on clarity
|
|
40718
41663
|
- Ask a follow-up question if needed
|
|
40719
41664
|
`;
|
|
40720
|
-
const examplePath =
|
|
40721
|
-
if (!
|
|
40722
|
-
|
|
41665
|
+
const examplePath = join11(commandsDir, "reflect.md");
|
|
41666
|
+
if (!existsSync7(examplePath)) {
|
|
41667
|
+
writeFileSync4(examplePath, exampleCommand);
|
|
40723
41668
|
}
|
|
40724
41669
|
let message = `
|
|
40725
41670
|
**Initialized assistants**
|
|
@@ -41038,8 +41983,8 @@ Connector "${connectorName}" not found.
|
|
|
41038
41983
|
`;
|
|
41039
41984
|
try {
|
|
41040
41985
|
let timeoutId = null;
|
|
41041
|
-
const timeoutPromise = new Promise((
|
|
41042
|
-
timeoutId = setTimeout(resolveAuthTimeout, 1000,
|
|
41986
|
+
const timeoutPromise = new Promise((resolve5) => {
|
|
41987
|
+
timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
|
|
41043
41988
|
});
|
|
41044
41989
|
const result = await Promise.race([
|
|
41045
41990
|
Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
|
|
@@ -41101,8 +42046,8 @@ Connector "${connectorName}" not found.
|
|
|
41101
42046
|
let status = "\u25CB";
|
|
41102
42047
|
let timeoutId = null;
|
|
41103
42048
|
try {
|
|
41104
|
-
const timeoutPromise = new Promise((
|
|
41105
|
-
timeoutId = setTimeout(resolveAuthTimeout, 1000,
|
|
42049
|
+
const timeoutPromise = new Promise((resolve5) => {
|
|
42050
|
+
timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
|
|
41106
42051
|
});
|
|
41107
42052
|
const result = await Promise.race([
|
|
41108
42053
|
Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
|
|
@@ -41377,6 +42322,35 @@ ${repoUrl}/issues/new
|
|
|
41377
42322
|
}
|
|
41378
42323
|
};
|
|
41379
42324
|
}
|
|
42325
|
+
async resolveProject(context, target) {
|
|
42326
|
+
const byId = await readProject(context.cwd, target);
|
|
42327
|
+
if (byId)
|
|
42328
|
+
return byId;
|
|
42329
|
+
return findProjectByName(context.cwd, target);
|
|
42330
|
+
}
|
|
42331
|
+
async ensureActiveProject(context, createIfMissing) {
|
|
42332
|
+
const activeId = context.getActiveProjectId?.();
|
|
42333
|
+
if (activeId) {
|
|
42334
|
+
const project2 = await readProject(context.cwd, activeId);
|
|
42335
|
+
if (project2)
|
|
42336
|
+
return project2;
|
|
42337
|
+
}
|
|
42338
|
+
if (!createIfMissing)
|
|
42339
|
+
return null;
|
|
42340
|
+
const project = await ensureDefaultProject(context.cwd);
|
|
42341
|
+
context.setActiveProjectId?.(project.id);
|
|
42342
|
+
await this.applyProjectContext(context, project);
|
|
42343
|
+
return project;
|
|
42344
|
+
}
|
|
42345
|
+
async applyProjectContext(context, project) {
|
|
42346
|
+
if (!context.setProjectContext)
|
|
42347
|
+
return;
|
|
42348
|
+
const projectContext = await buildProjectContext(project, {
|
|
42349
|
+
cwd: context.cwd,
|
|
42350
|
+
connectors: context.connectors
|
|
42351
|
+
});
|
|
42352
|
+
context.setProjectContext(projectContext);
|
|
42353
|
+
}
|
|
41380
42354
|
}
|
|
41381
42355
|
// packages/core/src/llm/client.ts
|
|
41382
42356
|
async function createLLMClient(config) {
|
|
@@ -41389,8 +42363,8 @@ async function createLLMClient(config) {
|
|
|
41389
42363
|
|
|
41390
42364
|
// packages/core/src/heartbeat/manager.ts
|
|
41391
42365
|
import { dirname as dirname5 } from "path";
|
|
41392
|
-
import { mkdirSync as
|
|
41393
|
-
import { readFile as
|
|
42366
|
+
import { mkdirSync as mkdirSync4 } from "fs";
|
|
42367
|
+
import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
41394
42368
|
|
|
41395
42369
|
class HeartbeatManager {
|
|
41396
42370
|
config;
|
|
@@ -41411,7 +42385,7 @@ class HeartbeatManager {
|
|
|
41411
42385
|
uptimeSeconds: 0
|
|
41412
42386
|
};
|
|
41413
42387
|
const dir = dirname5(config.persistPath);
|
|
41414
|
-
|
|
42388
|
+
mkdirSync4(dir, { recursive: true });
|
|
41415
42389
|
}
|
|
41416
42390
|
start(sessionId) {
|
|
41417
42391
|
if (this.intervalId)
|
|
@@ -41469,12 +42443,12 @@ class HeartbeatManager {
|
|
|
41469
42443
|
}
|
|
41470
42444
|
async persist(heartbeat) {
|
|
41471
42445
|
try {
|
|
41472
|
-
await
|
|
42446
|
+
await writeFile3(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
|
|
41473
42447
|
} catch {}
|
|
41474
42448
|
}
|
|
41475
42449
|
static async checkStale(path2, thresholdMs) {
|
|
41476
42450
|
try {
|
|
41477
|
-
const content = await
|
|
42451
|
+
const content = await readFile4(path2, "utf-8");
|
|
41478
42452
|
const heartbeat = JSON.parse(content);
|
|
41479
42453
|
const age = Date.now() - new Date(heartbeat.timestamp).getTime();
|
|
41480
42454
|
return { isStale: age > thresholdMs, lastHeartbeat: heartbeat };
|
|
@@ -41485,23 +42459,23 @@ class HeartbeatManager {
|
|
|
41485
42459
|
}
|
|
41486
42460
|
// packages/core/src/heartbeat/persistence.ts
|
|
41487
42461
|
import { dirname as dirname6 } from "path";
|
|
41488
|
-
import { mkdirSync as
|
|
41489
|
-
import { readFile as
|
|
42462
|
+
import { mkdirSync as mkdirSync5 } from "fs";
|
|
42463
|
+
import { readFile as readFile5, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
41490
42464
|
|
|
41491
42465
|
class StatePersistence {
|
|
41492
42466
|
path;
|
|
41493
42467
|
constructor(path2) {
|
|
41494
42468
|
this.path = path2;
|
|
41495
|
-
|
|
42469
|
+
mkdirSync5(dirname6(path2), { recursive: true });
|
|
41496
42470
|
}
|
|
41497
42471
|
async save(state) {
|
|
41498
42472
|
try {
|
|
41499
|
-
await
|
|
42473
|
+
await writeFile4(this.path, JSON.stringify(state, null, 2));
|
|
41500
42474
|
} catch {}
|
|
41501
42475
|
}
|
|
41502
42476
|
async load() {
|
|
41503
42477
|
try {
|
|
41504
|
-
const content = await
|
|
42478
|
+
const content = await readFile5(this.path, "utf-8");
|
|
41505
42479
|
return JSON.parse(content);
|
|
41506
42480
|
} catch {
|
|
41507
42481
|
return null;
|
|
@@ -41509,7 +42483,7 @@ class StatePersistence {
|
|
|
41509
42483
|
}
|
|
41510
42484
|
async clear() {
|
|
41511
42485
|
try {
|
|
41512
|
-
await
|
|
42486
|
+
await unlink3(this.path);
|
|
41513
42487
|
} catch {}
|
|
41514
42488
|
}
|
|
41515
42489
|
}
|
|
@@ -41712,23 +42686,23 @@ class EnergyManager {
|
|
|
41712
42686
|
}
|
|
41713
42687
|
// packages/core/src/energy/storage.ts
|
|
41714
42688
|
import { dirname as dirname7 } from "path";
|
|
41715
|
-
import { mkdirSync as
|
|
41716
|
-
import { readFile as
|
|
42689
|
+
import { mkdirSync as mkdirSync6 } from "fs";
|
|
42690
|
+
import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
41717
42691
|
|
|
41718
42692
|
class EnergyStorage {
|
|
41719
42693
|
path;
|
|
41720
42694
|
constructor(path2) {
|
|
41721
42695
|
this.path = path2;
|
|
41722
|
-
|
|
42696
|
+
mkdirSync6(dirname7(path2), { recursive: true });
|
|
41723
42697
|
}
|
|
41724
42698
|
async save(state) {
|
|
41725
42699
|
try {
|
|
41726
|
-
await
|
|
42700
|
+
await writeFile5(this.path, JSON.stringify(state, null, 2));
|
|
41727
42701
|
} catch {}
|
|
41728
42702
|
}
|
|
41729
42703
|
async load() {
|
|
41730
42704
|
try {
|
|
41731
|
-
const content = await
|
|
42705
|
+
const content = await readFile6(this.path, "utf-8");
|
|
41732
42706
|
return JSON.parse(content);
|
|
41733
42707
|
} catch {
|
|
41734
42708
|
return null;
|
|
@@ -41786,18 +42760,18 @@ function validateToolCalls(toolCalls, tools) {
|
|
|
41786
42760
|
}
|
|
41787
42761
|
|
|
41788
42762
|
// packages/core/src/voice/utils.ts
|
|
41789
|
-
import { existsSync as
|
|
42763
|
+
import { existsSync as existsSync9, readFileSync as readFileSync4 } from "fs";
|
|
41790
42764
|
import { homedir as homedir9 } from "os";
|
|
41791
|
-
import { join as
|
|
42765
|
+
import { join as join13 } from "path";
|
|
41792
42766
|
import { spawnSync } from "child_process";
|
|
41793
42767
|
function loadApiKeyFromSecrets2(key) {
|
|
41794
42768
|
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
41795
42769
|
const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
|
|
41796
|
-
const secretsPath =
|
|
41797
|
-
if (!
|
|
42770
|
+
const secretsPath = join13(homeDir, ".secrets");
|
|
42771
|
+
if (!existsSync9(secretsPath))
|
|
41798
42772
|
return;
|
|
41799
42773
|
try {
|
|
41800
|
-
const content =
|
|
42774
|
+
const content = readFileSync4(secretsPath, "utf-8");
|
|
41801
42775
|
const match = content.match(new RegExp(`export\\s+${key}\\s*=\\s*['"]?([^'"\\n]+)['"]?`));
|
|
41802
42776
|
return match?.[1];
|
|
41803
42777
|
} catch {
|
|
@@ -41867,8 +42841,8 @@ class SystemSTT {
|
|
|
41867
42841
|
// packages/core/src/voice/tts.ts
|
|
41868
42842
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
41869
42843
|
import { tmpdir as tmpdir2 } from "os";
|
|
41870
|
-
import { join as
|
|
41871
|
-
import { readFileSync as
|
|
42844
|
+
import { join as join14 } from "path";
|
|
42845
|
+
import { readFileSync as readFileSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
41872
42846
|
class ElevenLabsTTS {
|
|
41873
42847
|
apiKey;
|
|
41874
42848
|
voiceId;
|
|
@@ -41971,7 +42945,7 @@ class SystemTTS {
|
|
|
41971
42945
|
if (!say) {
|
|
41972
42946
|
throw new Error('System TTS not available: missing "say" command.');
|
|
41973
42947
|
}
|
|
41974
|
-
const output =
|
|
42948
|
+
const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
|
|
41975
42949
|
const args = [];
|
|
41976
42950
|
if (this.voiceId) {
|
|
41977
42951
|
args.push("-v", this.voiceId);
|
|
@@ -41984,7 +42958,7 @@ class SystemTTS {
|
|
|
41984
42958
|
if (result.status !== 0) {
|
|
41985
42959
|
throw new Error(`System TTS failed: ${result.stderr || "unknown error"}`);
|
|
41986
42960
|
}
|
|
41987
|
-
const audio =
|
|
42961
|
+
const audio = readFileSync5(output);
|
|
41988
42962
|
unlinkSync2(output);
|
|
41989
42963
|
return {
|
|
41990
42964
|
audio: audio.buffer.slice(audio.byteOffset, audio.byteOffset + audio.byteLength),
|
|
@@ -41993,7 +42967,7 @@ class SystemTTS {
|
|
|
41993
42967
|
}
|
|
41994
42968
|
const espeak = findExecutable("espeak") || findExecutable("espeak-ng");
|
|
41995
42969
|
if (espeak) {
|
|
41996
|
-
const output =
|
|
42970
|
+
const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
|
|
41997
42971
|
const args = ["-w", output];
|
|
41998
42972
|
if (this.voiceId) {
|
|
41999
42973
|
args.push("-v", this.voiceId);
|
|
@@ -42006,7 +42980,7 @@ class SystemTTS {
|
|
|
42006
42980
|
if (result.status !== 0) {
|
|
42007
42981
|
throw new Error(`System TTS failed: ${result.stderr || "unknown error"}`);
|
|
42008
42982
|
}
|
|
42009
|
-
const audio =
|
|
42983
|
+
const audio = readFileSync5(output);
|
|
42010
42984
|
unlinkSync2(output);
|
|
42011
42985
|
return {
|
|
42012
42986
|
audio: audio.buffer.slice(audio.byteOffset, audio.byteOffset + audio.byteLength),
|
|
@@ -42020,32 +42994,32 @@ class SystemTTS {
|
|
|
42020
42994
|
// packages/core/src/voice/player.ts
|
|
42021
42995
|
import { spawn } from "child_process";
|
|
42022
42996
|
import { tmpdir as tmpdir3 } from "os";
|
|
42023
|
-
import { join as
|
|
42024
|
-
import { unlink as
|
|
42997
|
+
import { join as join15 } from "path";
|
|
42998
|
+
import { unlink as unlink4, writeFileSync as writeFileSync5 } from "fs";
|
|
42025
42999
|
class AudioPlayer {
|
|
42026
43000
|
currentProcess = null;
|
|
42027
43001
|
playing = false;
|
|
42028
43002
|
async play(audio, options = {}) {
|
|
42029
43003
|
const format = options.format ?? "mp3";
|
|
42030
|
-
const tempFile =
|
|
42031
|
-
|
|
43004
|
+
const tempFile = join15(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
|
|
43005
|
+
writeFileSync5(tempFile, Buffer.from(audio));
|
|
42032
43006
|
const player = this.resolvePlayer(format);
|
|
42033
43007
|
if (!player) {
|
|
42034
43008
|
throw new Error("No supported audio player found. Install afplay, ffplay, mpg123, or aplay.");
|
|
42035
43009
|
}
|
|
42036
|
-
await new Promise((
|
|
43010
|
+
await new Promise((resolve5, reject) => {
|
|
42037
43011
|
this.playing = true;
|
|
42038
43012
|
this.currentProcess = spawn(player.command, [...player.args, tempFile], { stdio: "ignore" });
|
|
42039
43013
|
this.currentProcess.on("close", () => {
|
|
42040
43014
|
this.playing = false;
|
|
42041
43015
|
this.currentProcess = null;
|
|
42042
|
-
|
|
42043
|
-
|
|
43016
|
+
unlink4(tempFile, () => {});
|
|
43017
|
+
resolve5();
|
|
42044
43018
|
});
|
|
42045
43019
|
this.currentProcess.on("error", (error) => {
|
|
42046
43020
|
this.playing = false;
|
|
42047
43021
|
this.currentProcess = null;
|
|
42048
|
-
|
|
43022
|
+
unlink4(tempFile, () => {});
|
|
42049
43023
|
reject(error);
|
|
42050
43024
|
});
|
|
42051
43025
|
});
|
|
@@ -42095,8 +43069,8 @@ class AudioPlayer {
|
|
|
42095
43069
|
// packages/core/src/voice/recorder.ts
|
|
42096
43070
|
import { spawn as spawn2 } from "child_process";
|
|
42097
43071
|
import { tmpdir as tmpdir4 } from "os";
|
|
42098
|
-
import { join as
|
|
42099
|
-
import { readFileSync as
|
|
43072
|
+
import { join as join16 } from "path";
|
|
43073
|
+
import { readFileSync as readFileSync6, unlink as unlink5 } from "fs";
|
|
42100
43074
|
class AudioRecorder {
|
|
42101
43075
|
currentProcess = null;
|
|
42102
43076
|
async record(options = {}) {
|
|
@@ -42106,17 +43080,17 @@ class AudioRecorder {
|
|
|
42106
43080
|
const duration = options.durationSeconds ?? 5;
|
|
42107
43081
|
const sampleRate = options.sampleRate ?? 16000;
|
|
42108
43082
|
const channels = options.channels ?? 1;
|
|
42109
|
-
const output =
|
|
43083
|
+
const output = join16(tmpdir4(), `assistants-record-${Date.now()}.wav`);
|
|
42110
43084
|
const recorder = this.resolveRecorder(sampleRate, channels, duration, output);
|
|
42111
43085
|
if (!recorder) {
|
|
42112
43086
|
throw new Error("No supported audio recorder found. Install sox or ffmpeg.");
|
|
42113
43087
|
}
|
|
42114
|
-
await new Promise((
|
|
43088
|
+
await new Promise((resolve5, reject) => {
|
|
42115
43089
|
this.currentProcess = spawn2(recorder.command, recorder.args, { stdio: "ignore" });
|
|
42116
43090
|
this.currentProcess.on("close", (code) => {
|
|
42117
43091
|
this.currentProcess = null;
|
|
42118
43092
|
if (code === 0) {
|
|
42119
|
-
|
|
43093
|
+
resolve5();
|
|
42120
43094
|
} else {
|
|
42121
43095
|
reject(new Error("Audio recording failed."));
|
|
42122
43096
|
}
|
|
@@ -42126,8 +43100,8 @@ class AudioRecorder {
|
|
|
42126
43100
|
reject(error);
|
|
42127
43101
|
});
|
|
42128
43102
|
});
|
|
42129
|
-
const data =
|
|
42130
|
-
|
|
43103
|
+
const data = readFileSync6(output);
|
|
43104
|
+
unlink5(output, () => {});
|
|
42131
43105
|
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
42132
43106
|
}
|
|
42133
43107
|
stop() {
|
|
@@ -42298,15 +43272,15 @@ class VoiceManager {
|
|
|
42298
43272
|
}
|
|
42299
43273
|
// packages/core/src/identity/assistant-manager.ts
|
|
42300
43274
|
init_src();
|
|
42301
|
-
import { existsSync as
|
|
42302
|
-
import { mkdir as
|
|
42303
|
-
import { join as
|
|
43275
|
+
import { existsSync as existsSync11 } from "fs";
|
|
43276
|
+
import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile7, rm as rm2 } from "fs/promises";
|
|
43277
|
+
import { join as join18 } from "path";
|
|
42304
43278
|
|
|
42305
43279
|
// packages/core/src/identity/identity-manager.ts
|
|
42306
43280
|
init_src();
|
|
42307
|
-
import { existsSync as
|
|
42308
|
-
import { mkdir as
|
|
42309
|
-
import { join as
|
|
43281
|
+
import { existsSync as existsSync10 } from "fs";
|
|
43282
|
+
import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile6, rm } from "fs/promises";
|
|
43283
|
+
import { join as join17 } from "path";
|
|
42310
43284
|
var DEFAULT_PROFILE = {
|
|
42311
43285
|
displayName: "Assistant",
|
|
42312
43286
|
timezone: "UTC",
|
|
@@ -42336,22 +43310,22 @@ class IdentityManager {
|
|
|
42336
43310
|
this.basePath = basePath;
|
|
42337
43311
|
}
|
|
42338
43312
|
get identitiesRoot() {
|
|
42339
|
-
return
|
|
43313
|
+
return join17(this.basePath, "assistants", this.assistantId, "identities");
|
|
42340
43314
|
}
|
|
42341
43315
|
get indexPath() {
|
|
42342
|
-
return
|
|
43316
|
+
return join17(this.identitiesRoot, "index.json");
|
|
42343
43317
|
}
|
|
42344
43318
|
get activePath() {
|
|
42345
|
-
return
|
|
43319
|
+
return join17(this.identitiesRoot, "active.json");
|
|
42346
43320
|
}
|
|
42347
43321
|
identityPath(id) {
|
|
42348
|
-
return
|
|
43322
|
+
return join17(this.identitiesRoot, `${id}.json`);
|
|
42349
43323
|
}
|
|
42350
43324
|
assistantConfigPath() {
|
|
42351
|
-
return
|
|
43325
|
+
return join17(this.basePath, "assistants", this.assistantId, "config.json");
|
|
42352
43326
|
}
|
|
42353
43327
|
async initialize() {
|
|
42354
|
-
await
|
|
43328
|
+
await mkdir4(this.identitiesRoot, { recursive: true });
|
|
42355
43329
|
const index = await this.readIndex();
|
|
42356
43330
|
for (const id of index.identities) {
|
|
42357
43331
|
const identity = await this.readIdentity(id);
|
|
@@ -42454,11 +43428,11 @@ class IdentityManager {
|
|
|
42454
43428
|
`);
|
|
42455
43429
|
}
|
|
42456
43430
|
async readIndex() {
|
|
42457
|
-
if (!
|
|
43431
|
+
if (!existsSync10(this.indexPath)) {
|
|
42458
43432
|
return { identities: [] };
|
|
42459
43433
|
}
|
|
42460
43434
|
try {
|
|
42461
|
-
const raw = await
|
|
43435
|
+
const raw = await readFile7(this.indexPath, "utf-8");
|
|
42462
43436
|
const data = JSON.parse(raw);
|
|
42463
43437
|
return { identities: Array.isArray(data.identities) ? data.identities : [] };
|
|
42464
43438
|
} catch {
|
|
@@ -42470,33 +43444,33 @@ class IdentityManager {
|
|
|
42470
43444
|
if (!index.identities.includes(id)) {
|
|
42471
43445
|
index.identities.push(id);
|
|
42472
43446
|
}
|
|
42473
|
-
await
|
|
43447
|
+
await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
|
|
42474
43448
|
}
|
|
42475
43449
|
async removeFromIndex(id) {
|
|
42476
43450
|
const index = await this.readIndex();
|
|
42477
43451
|
index.identities = index.identities.filter((identityId) => identityId !== id);
|
|
42478
|
-
await
|
|
43452
|
+
await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
|
|
42479
43453
|
}
|
|
42480
43454
|
async readIdentity(id) {
|
|
42481
43455
|
const path2 = this.identityPath(id);
|
|
42482
|
-
if (!
|
|
43456
|
+
if (!existsSync10(path2))
|
|
42483
43457
|
return null;
|
|
42484
43458
|
try {
|
|
42485
|
-
const raw = await
|
|
43459
|
+
const raw = await readFile7(path2, "utf-8");
|
|
42486
43460
|
return JSON.parse(raw);
|
|
42487
43461
|
} catch {
|
|
42488
43462
|
return null;
|
|
42489
43463
|
}
|
|
42490
43464
|
}
|
|
42491
43465
|
async persistIdentity(identity) {
|
|
42492
|
-
await
|
|
42493
|
-
await
|
|
43466
|
+
await mkdir4(this.identitiesRoot, { recursive: true });
|
|
43467
|
+
await writeFile6(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
|
|
42494
43468
|
}
|
|
42495
43469
|
async readActive() {
|
|
42496
|
-
if (!
|
|
43470
|
+
if (!existsSync10(this.activePath))
|
|
42497
43471
|
return null;
|
|
42498
43472
|
try {
|
|
42499
|
-
const raw = await
|
|
43473
|
+
const raw = await readFile7(this.activePath, "utf-8");
|
|
42500
43474
|
const data = JSON.parse(raw);
|
|
42501
43475
|
return data.id || null;
|
|
42502
43476
|
} catch {
|
|
@@ -42505,13 +43479,13 @@ class IdentityManager {
|
|
|
42505
43479
|
}
|
|
42506
43480
|
async setActive(id) {
|
|
42507
43481
|
this.activeId = id;
|
|
42508
|
-
await
|
|
43482
|
+
await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
|
|
42509
43483
|
}
|
|
42510
43484
|
async loadAssistant() {
|
|
42511
|
-
if (!
|
|
43485
|
+
if (!existsSync10(this.assistantConfigPath()))
|
|
42512
43486
|
return null;
|
|
42513
43487
|
try {
|
|
42514
|
-
const raw = await
|
|
43488
|
+
const raw = await readFile7(this.assistantConfigPath(), "utf-8");
|
|
42515
43489
|
return JSON.parse(raw);
|
|
42516
43490
|
} catch {
|
|
42517
43491
|
return null;
|
|
@@ -42532,19 +43506,19 @@ class AssistantManager {
|
|
|
42532
43506
|
this.basePath = basePath;
|
|
42533
43507
|
}
|
|
42534
43508
|
get assistantsRoot() {
|
|
42535
|
-
return
|
|
43509
|
+
return join18(this.basePath, "assistants");
|
|
42536
43510
|
}
|
|
42537
43511
|
get indexPath() {
|
|
42538
|
-
return
|
|
43512
|
+
return join18(this.assistantsRoot, "index.json");
|
|
42539
43513
|
}
|
|
42540
43514
|
get activePath() {
|
|
42541
|
-
return
|
|
43515
|
+
return join18(this.basePath, "active.json");
|
|
42542
43516
|
}
|
|
42543
43517
|
assistantConfigPath(id) {
|
|
42544
|
-
return
|
|
43518
|
+
return join18(this.assistantsRoot, id, "config.json");
|
|
42545
43519
|
}
|
|
42546
43520
|
async initialize() {
|
|
42547
|
-
await
|
|
43521
|
+
await mkdir5(this.assistantsRoot, { recursive: true });
|
|
42548
43522
|
const index = await this.readIndex();
|
|
42549
43523
|
for (const id of index.assistants) {
|
|
42550
43524
|
const assistant = await this.readAssistant(id);
|
|
@@ -42595,7 +43569,7 @@ class AssistantManager {
|
|
|
42595
43569
|
if (!this.assistants.has(id)) {
|
|
42596
43570
|
throw new Error(`Assistant ${id} not found`);
|
|
42597
43571
|
}
|
|
42598
|
-
await rm2(
|
|
43572
|
+
await rm2(join18(this.assistantsRoot, id), { recursive: true, force: true });
|
|
42599
43573
|
this.assistants.delete(id);
|
|
42600
43574
|
await this.removeFromIndex(id);
|
|
42601
43575
|
if (this.activeId === id) {
|
|
@@ -42626,11 +43600,11 @@ class AssistantManager {
|
|
|
42626
43600
|
return new IdentityManager(assistantId, this.basePath);
|
|
42627
43601
|
}
|
|
42628
43602
|
async readIndex() {
|
|
42629
|
-
if (!
|
|
43603
|
+
if (!existsSync11(this.indexPath)) {
|
|
42630
43604
|
return { assistants: [] };
|
|
42631
43605
|
}
|
|
42632
43606
|
try {
|
|
42633
|
-
const raw = await
|
|
43607
|
+
const raw = await readFile8(this.indexPath, "utf-8");
|
|
42634
43608
|
const data = JSON.parse(raw);
|
|
42635
43609
|
return { assistants: Array.isArray(data.assistants) ? data.assistants : [] };
|
|
42636
43610
|
} catch {
|
|
@@ -42642,34 +43616,34 @@ class AssistantManager {
|
|
|
42642
43616
|
if (!index.assistants.includes(id)) {
|
|
42643
43617
|
index.assistants.push(id);
|
|
42644
43618
|
}
|
|
42645
|
-
await
|
|
43619
|
+
await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
|
|
42646
43620
|
}
|
|
42647
43621
|
async removeFromIndex(id) {
|
|
42648
43622
|
const index = await this.readIndex();
|
|
42649
43623
|
index.assistants = index.assistants.filter((assistantId) => assistantId !== id);
|
|
42650
|
-
await
|
|
43624
|
+
await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
|
|
42651
43625
|
}
|
|
42652
43626
|
async readAssistant(id) {
|
|
42653
43627
|
const configPath = this.assistantConfigPath(id);
|
|
42654
|
-
if (!
|
|
43628
|
+
if (!existsSync11(configPath))
|
|
42655
43629
|
return null;
|
|
42656
43630
|
try {
|
|
42657
|
-
const raw = await
|
|
43631
|
+
const raw = await readFile8(configPath, "utf-8");
|
|
42658
43632
|
return JSON.parse(raw);
|
|
42659
43633
|
} catch {
|
|
42660
43634
|
return null;
|
|
42661
43635
|
}
|
|
42662
43636
|
}
|
|
42663
43637
|
async persistAssistant(assistant) {
|
|
42664
|
-
const dir =
|
|
42665
|
-
await
|
|
42666
|
-
await
|
|
43638
|
+
const dir = join18(this.assistantsRoot, assistant.id);
|
|
43639
|
+
await mkdir5(dir, { recursive: true });
|
|
43640
|
+
await writeFile7(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
|
|
42667
43641
|
}
|
|
42668
43642
|
async readActive() {
|
|
42669
|
-
if (!
|
|
43643
|
+
if (!existsSync11(this.activePath))
|
|
42670
43644
|
return null;
|
|
42671
43645
|
try {
|
|
42672
|
-
const raw = await
|
|
43646
|
+
const raw = await readFile8(this.activePath, "utf-8");
|
|
42673
43647
|
const data = JSON.parse(raw);
|
|
42674
43648
|
return data.id || null;
|
|
42675
43649
|
} catch {
|
|
@@ -42678,7 +43652,7 @@ class AssistantManager {
|
|
|
42678
43652
|
}
|
|
42679
43653
|
async setActive(id) {
|
|
42680
43654
|
this.activeId = id;
|
|
42681
|
-
await
|
|
43655
|
+
await writeFile7(this.activePath, JSON.stringify({ id }, null, 2));
|
|
42682
43656
|
}
|
|
42683
43657
|
}
|
|
42684
43658
|
// packages/core/src/agent/loop.ts
|
|
@@ -42723,6 +43697,8 @@ class AgentLoop {
|
|
|
42723
43697
|
assistantManager = null;
|
|
42724
43698
|
identityManager = null;
|
|
42725
43699
|
identityContext = null;
|
|
43700
|
+
projectContext = null;
|
|
43701
|
+
activeProjectId = null;
|
|
42726
43702
|
assistantId = null;
|
|
42727
43703
|
onChunk;
|
|
42728
43704
|
onToolStart;
|
|
@@ -42735,7 +43711,7 @@ class AgentLoop {
|
|
|
42735
43711
|
this.context = new AgentContext;
|
|
42736
43712
|
this.toolRegistry = new ToolRegistry;
|
|
42737
43713
|
this.toolRegistry.setErrorAggregator(this.errorAggregator);
|
|
42738
|
-
this.connectorBridge = new ConnectorBridge;
|
|
43714
|
+
this.connectorBridge = new ConnectorBridge(this.cwd);
|
|
42739
43715
|
this.skillLoader = new SkillLoader;
|
|
42740
43716
|
this.skillExecutor = new SkillExecutor;
|
|
42741
43717
|
this.hookLoader = new HookLoader;
|
|
@@ -43038,15 +44014,13 @@ class AgentLoop {
|
|
|
43038
44014
|
});
|
|
43039
44015
|
if (preHookResult?.updatedInput) {
|
|
43040
44016
|
toolCall.input = { ...preHookResult.updatedInput };
|
|
43041
|
-
if (toolCall.input.cwd === undefined) {
|
|
43042
|
-
toolCall.input.cwd = this.cwd;
|
|
43043
|
-
}
|
|
43044
44017
|
}
|
|
43045
|
-
|
|
43046
|
-
|
|
43047
|
-
|
|
43048
|
-
|
|
43049
|
-
|
|
44018
|
+
const input = toolCall.input;
|
|
44019
|
+
if (input.cwd === undefined) {
|
|
44020
|
+
input.cwd = this.cwd;
|
|
44021
|
+
}
|
|
44022
|
+
if (input.sessionId === undefined) {
|
|
44023
|
+
input.sessionId = this.sessionId;
|
|
43050
44024
|
}
|
|
43051
44025
|
if (preHookResult?.continue === false || preHookResult?.permissionDecision === "deny") {
|
|
43052
44026
|
const blockedResult = {
|
|
@@ -43170,6 +44144,13 @@ class AgentLoop {
|
|
|
43170
44144
|
switchIdentity: async (identityId) => {
|
|
43171
44145
|
await this.switchIdentity(identityId);
|
|
43172
44146
|
},
|
|
44147
|
+
getActiveProjectId: () => this.activeProjectId,
|
|
44148
|
+
setActiveProjectId: (projectId) => {
|
|
44149
|
+
this.activeProjectId = projectId;
|
|
44150
|
+
},
|
|
44151
|
+
setProjectContext: (content) => {
|
|
44152
|
+
this.setProjectContext(content);
|
|
44153
|
+
},
|
|
43173
44154
|
getVoiceState: () => this.getVoiceState(),
|
|
43174
44155
|
enableVoice: () => {
|
|
43175
44156
|
if (!this.voiceManager) {
|
|
@@ -43357,6 +44338,22 @@ class AgentLoop {
|
|
|
43357
44338
|
getSessionId() {
|
|
43358
44339
|
return this.sessionId;
|
|
43359
44340
|
}
|
|
44341
|
+
getActiveProjectId() {
|
|
44342
|
+
return this.activeProjectId;
|
|
44343
|
+
}
|
|
44344
|
+
setActiveProjectId(projectId) {
|
|
44345
|
+
this.activeProjectId = projectId;
|
|
44346
|
+
}
|
|
44347
|
+
setProjectContext(content) {
|
|
44348
|
+
const tag = "[Project Context]";
|
|
44349
|
+
this.projectContext = content;
|
|
44350
|
+
this.context.removeSystemMessages((message) => message.startsWith(tag));
|
|
44351
|
+
if (content && content.trim()) {
|
|
44352
|
+
this.context.addSystemMessage(`${tag}
|
|
44353
|
+
${content.trim()}`);
|
|
44354
|
+
}
|
|
44355
|
+
this.contextManager?.refreshState(this.context.getMessages());
|
|
44356
|
+
}
|
|
43360
44357
|
clearConversation() {
|
|
43361
44358
|
this.resetContext();
|
|
43362
44359
|
}
|
|
@@ -43368,7 +44365,7 @@ class AgentLoop {
|
|
|
43368
44365
|
const heartbeatConfig = this.buildHeartbeatConfig(this.config);
|
|
43369
44366
|
if (!heartbeatConfig)
|
|
43370
44367
|
return;
|
|
43371
|
-
const statePath =
|
|
44368
|
+
const statePath = join19(getConfigDir(), "state", `${this.sessionId}.json`);
|
|
43372
44369
|
this.heartbeatManager = new HeartbeatManager(heartbeatConfig);
|
|
43373
44370
|
this.heartbeatPersistence = new StatePersistence(statePath);
|
|
43374
44371
|
this.heartbeatRecovery = new RecoveryManager(this.heartbeatPersistence, heartbeatConfig.persistPath, heartbeatConfig.staleThresholdMs, {
|
|
@@ -43417,7 +44414,7 @@ class AgentLoop {
|
|
|
43417
44414
|
async startEnergySystem() {
|
|
43418
44415
|
if (!this.config || this.config.energy?.enabled === false)
|
|
43419
44416
|
return;
|
|
43420
|
-
const statePath =
|
|
44417
|
+
const statePath = join19(getConfigDir(), "energy", "state.json");
|
|
43421
44418
|
this.energyManager = new EnergyManager(this.config.energy, new EnergyStorage(statePath));
|
|
43422
44419
|
await this.energyManager.initialize();
|
|
43423
44420
|
this.refreshEnergyEffects();
|
|
@@ -43446,7 +44443,7 @@ ${effects.message}
|
|
|
43446
44443
|
const delay = this.energyEffects?.processingDelayMs ?? 0;
|
|
43447
44444
|
if (delay <= 0)
|
|
43448
44445
|
return;
|
|
43449
|
-
await new Promise((
|
|
44446
|
+
await new Promise((resolve5) => setTimeout(resolve5, delay));
|
|
43450
44447
|
}
|
|
43451
44448
|
applyEnergyPersonality(systemPrompt) {
|
|
43452
44449
|
if (!systemPrompt)
|
|
@@ -43557,6 +44554,9 @@ ${effects.message}
|
|
|
43557
44554
|
if (this.extraSystemPrompt) {
|
|
43558
44555
|
this.context.addSystemMessage(this.extraSystemPrompt);
|
|
43559
44556
|
}
|
|
44557
|
+
if (this.projectContext) {
|
|
44558
|
+
this.setProjectContext(this.projectContext);
|
|
44559
|
+
}
|
|
43560
44560
|
this.contextManager?.refreshState(this.context.getMessages());
|
|
43561
44561
|
}
|
|
43562
44562
|
buildSystemPrompt(messages) {
|
|
@@ -43643,7 +44643,7 @@ ${this.identityContext}`);
|
|
|
43643
44643
|
return null;
|
|
43644
44644
|
const intervalMs = Math.max(1000, config.heartbeat?.intervalMs ?? 15000);
|
|
43645
44645
|
const staleThresholdMs = Math.max(intervalMs * 2, config.heartbeat?.staleThresholdMs ?? 120000);
|
|
43646
|
-
const persistPath = config.heartbeat?.persistPath ??
|
|
44646
|
+
const persistPath = config.heartbeat?.persistPath ?? join19(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
|
|
43647
44647
|
return {
|
|
43648
44648
|
intervalMs,
|
|
43649
44649
|
staleThresholdMs,
|
|
@@ -43734,26 +44734,26 @@ function parseErrorCode(message) {
|
|
|
43734
44734
|
// packages/core/src/memory/sessions.ts
|
|
43735
44735
|
init_src();
|
|
43736
44736
|
// packages/core/src/migration/migrate-to-assistants.ts
|
|
43737
|
-
import { existsSync as
|
|
43738
|
-
import { mkdir as
|
|
43739
|
-
import { join as
|
|
44737
|
+
import { existsSync as existsSync12 } from "fs";
|
|
44738
|
+
import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile8, rename, cp } from "fs/promises";
|
|
44739
|
+
import { join as join20 } from "path";
|
|
43740
44740
|
import { homedir as homedir10 } from "os";
|
|
43741
44741
|
var MIGRATION_MARKER = ".migrated-from-oldpal";
|
|
43742
44742
|
async function ensureDir(path2) {
|
|
43743
|
-
await
|
|
44743
|
+
await mkdir6(path2, { recursive: true });
|
|
43744
44744
|
}
|
|
43745
44745
|
async function copyIfExists(source, destination) {
|
|
43746
|
-
if (!
|
|
44746
|
+
if (!existsSync12(source))
|
|
43747
44747
|
return false;
|
|
43748
|
-
await ensureDir(
|
|
44748
|
+
await ensureDir(join20(destination, ".."));
|
|
43749
44749
|
await cp(source, destination, { recursive: true });
|
|
43750
44750
|
return true;
|
|
43751
44751
|
}
|
|
43752
44752
|
async function readJson(path2) {
|
|
43753
|
-
if (!
|
|
44753
|
+
if (!existsSync12(path2))
|
|
43754
44754
|
return null;
|
|
43755
44755
|
try {
|
|
43756
|
-
const raw = await
|
|
44756
|
+
const raw = await readFile9(path2, "utf-8");
|
|
43757
44757
|
return JSON.parse(raw);
|
|
43758
44758
|
} catch {
|
|
43759
44759
|
return null;
|
|
@@ -43766,15 +44766,15 @@ async function migrateFromOldpal() {
|
|
|
43766
44766
|
errors: []
|
|
43767
44767
|
};
|
|
43768
44768
|
const home = homedir10();
|
|
43769
|
-
const oldPath =
|
|
43770
|
-
const newPath =
|
|
43771
|
-
if (!
|
|
44769
|
+
const oldPath = join20(home, ".oldpal");
|
|
44770
|
+
const newPath = join20(home, ".assistants");
|
|
44771
|
+
if (!existsSync12(oldPath)) {
|
|
43772
44772
|
result.success = true;
|
|
43773
44773
|
return result;
|
|
43774
44774
|
}
|
|
43775
|
-
if (
|
|
43776
|
-
const marker =
|
|
43777
|
-
if (
|
|
44775
|
+
if (existsSync12(newPath)) {
|
|
44776
|
+
const marker = join20(newPath, "migration", MIGRATION_MARKER);
|
|
44777
|
+
if (existsSync12(marker)) {
|
|
43778
44778
|
result.success = true;
|
|
43779
44779
|
return result;
|
|
43780
44780
|
}
|
|
@@ -43783,31 +44783,31 @@ async function migrateFromOldpal() {
|
|
|
43783
44783
|
}
|
|
43784
44784
|
try {
|
|
43785
44785
|
await ensureDir(newPath);
|
|
43786
|
-
await ensureDir(
|
|
43787
|
-
await ensureDir(
|
|
43788
|
-
await ensureDir(
|
|
43789
|
-
await ensureDir(
|
|
43790
|
-
const config = await readJson(
|
|
44786
|
+
await ensureDir(join20(newPath, "assistants"));
|
|
44787
|
+
await ensureDir(join20(newPath, "shared", "skills"));
|
|
44788
|
+
await ensureDir(join20(newPath, "logs"));
|
|
44789
|
+
await ensureDir(join20(newPath, "migration"));
|
|
44790
|
+
const config = await readJson(join20(oldPath, "settings.json"));
|
|
43791
44791
|
if (config) {
|
|
43792
|
-
await
|
|
44792
|
+
await writeFile8(join20(newPath, "config.json"), JSON.stringify(config, null, 2));
|
|
43793
44793
|
result.migrated.push("config.json");
|
|
43794
44794
|
}
|
|
43795
|
-
if (await copyIfExists(
|
|
44795
|
+
if (await copyIfExists(join20(oldPath, "settings.local.json"), join20(newPath, "config.local.json"))) {
|
|
43796
44796
|
result.migrated.push("config.local.json");
|
|
43797
44797
|
}
|
|
43798
|
-
if (await copyIfExists(
|
|
44798
|
+
if (await copyIfExists(join20(oldPath, "hooks.json"), join20(newPath, "hooks.json"))) {
|
|
43799
44799
|
result.migrated.push("hooks.json");
|
|
43800
44800
|
}
|
|
43801
|
-
if (await copyIfExists(
|
|
44801
|
+
if (await copyIfExists(join20(oldPath, "commands"), join20(newPath, "commands"))) {
|
|
43802
44802
|
result.migrated.push("commands");
|
|
43803
44803
|
}
|
|
43804
|
-
if (await copyIfExists(
|
|
44804
|
+
if (await copyIfExists(join20(oldPath, "OLDPAL.md"), join20(newPath, "ASSISTANTS.md"))) {
|
|
43805
44805
|
result.migrated.push("ASSISTANTS.md");
|
|
43806
44806
|
}
|
|
43807
|
-
if (await copyIfExists(
|
|
44807
|
+
if (await copyIfExists(join20(oldPath, "skills"), join20(newPath, "shared", "skills"))) {
|
|
43808
44808
|
result.migrated.push("skills");
|
|
43809
44809
|
}
|
|
43810
|
-
if (await copyIfExists(
|
|
44810
|
+
if (await copyIfExists(join20(oldPath, "logs"), join20(newPath, "logs"))) {
|
|
43811
44811
|
result.migrated.push("logs");
|
|
43812
44812
|
}
|
|
43813
44813
|
const manager = new AssistantManager(newPath);
|
|
@@ -43822,10 +44822,10 @@ async function migrateFromOldpal() {
|
|
|
43822
44822
|
const identityManager = manager.getIdentityManager(assistant.id);
|
|
43823
44823
|
await identityManager.initialize();
|
|
43824
44824
|
await identityManager.createIdentity({ name: "Default" });
|
|
43825
|
-
if (await copyIfExists(
|
|
44825
|
+
if (await copyIfExists(join20(oldPath, "sessions"), join20(newPath, "assistants", assistant.id, "sessions"))) {
|
|
43826
44826
|
result.migrated.push("sessions");
|
|
43827
44827
|
}
|
|
43828
|
-
await
|
|
44828
|
+
await writeFile8(join20(newPath, "migration", MIGRATION_MARKER), JSON.stringify({ migratedAt: new Date().toISOString() }, null, 2));
|
|
43829
44829
|
const backupPath = `${oldPath}.backup`;
|
|
43830
44830
|
await rename(oldPath, backupPath);
|
|
43831
44831
|
result.backupPath = backupPath;
|
|
@@ -43842,22 +44842,22 @@ init_anthropic();
|
|
|
43842
44842
|
init_src();
|
|
43843
44843
|
|
|
43844
44844
|
// packages/core/src/logger.ts
|
|
43845
|
-
import { existsSync as
|
|
43846
|
-
import { join as
|
|
44845
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync7, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
44846
|
+
import { join as join21 } from "path";
|
|
43847
44847
|
class Logger {
|
|
43848
44848
|
logDir;
|
|
43849
44849
|
logFile;
|
|
43850
44850
|
sessionId;
|
|
43851
44851
|
constructor(sessionId, basePath) {
|
|
43852
44852
|
this.sessionId = sessionId;
|
|
43853
|
-
this.logDir =
|
|
44853
|
+
this.logDir = join21(basePath || getConfigDir(), "logs");
|
|
43854
44854
|
this.ensureDir(this.logDir);
|
|
43855
44855
|
const date = new Date().toISOString().split("T")[0];
|
|
43856
|
-
this.logFile =
|
|
44856
|
+
this.logFile = join21(this.logDir, `${date}.log`);
|
|
43857
44857
|
}
|
|
43858
44858
|
ensureDir(dir) {
|
|
43859
|
-
if (!
|
|
43860
|
-
|
|
44859
|
+
if (!existsSync13(dir)) {
|
|
44860
|
+
mkdirSync7(dir, { recursive: true });
|
|
43861
44861
|
}
|
|
43862
44862
|
}
|
|
43863
44863
|
write(level, message, data) {
|
|
@@ -43897,18 +44897,18 @@ class SessionStorage {
|
|
|
43897
44897
|
constructor(sessionId, basePath, assistantId) {
|
|
43898
44898
|
this.sessionId = sessionId;
|
|
43899
44899
|
const root = basePath || getConfigDir();
|
|
43900
|
-
this.sessionsDir = assistantId ?
|
|
44900
|
+
this.sessionsDir = assistantId ? join21(root, "assistants", assistantId, "sessions") : join21(root, "sessions");
|
|
43901
44901
|
this.ensureDir(this.sessionsDir);
|
|
43902
|
-
this.sessionFile =
|
|
44902
|
+
this.sessionFile = join21(this.sessionsDir, `${sessionId}.json`);
|
|
43903
44903
|
}
|
|
43904
44904
|
ensureDir(dir) {
|
|
43905
|
-
if (!
|
|
43906
|
-
|
|
44905
|
+
if (!existsSync13(dir)) {
|
|
44906
|
+
mkdirSync7(dir, { recursive: true });
|
|
43907
44907
|
}
|
|
43908
44908
|
}
|
|
43909
44909
|
save(data) {
|
|
43910
44910
|
try {
|
|
43911
|
-
|
|
44911
|
+
writeFileSync6(this.sessionFile, JSON.stringify(data, null, 2));
|
|
43912
44912
|
} catch {}
|
|
43913
44913
|
}
|
|
43914
44914
|
getSessionId() {
|
|
@@ -43916,19 +44916,19 @@ class SessionStorage {
|
|
|
43916
44916
|
}
|
|
43917
44917
|
load() {
|
|
43918
44918
|
try {
|
|
43919
|
-
if (!
|
|
44919
|
+
if (!existsSync13(this.sessionFile))
|
|
43920
44920
|
return null;
|
|
43921
|
-
return JSON.parse(
|
|
44921
|
+
return JSON.parse(readFileSync7(this.sessionFile, "utf-8"));
|
|
43922
44922
|
} catch {
|
|
43923
44923
|
return null;
|
|
43924
44924
|
}
|
|
43925
44925
|
}
|
|
43926
44926
|
static getActiveAssistantId() {
|
|
43927
44927
|
try {
|
|
43928
|
-
const activePath =
|
|
43929
|
-
if (!
|
|
44928
|
+
const activePath = join21(getConfigDir(), "active.json");
|
|
44929
|
+
if (!existsSync13(activePath))
|
|
43930
44930
|
return null;
|
|
43931
|
-
const raw =
|
|
44931
|
+
const raw = readFileSync7(activePath, "utf-8");
|
|
43932
44932
|
const data = JSON.parse(raw);
|
|
43933
44933
|
return data.id || null;
|
|
43934
44934
|
} catch {
|
|
@@ -43939,16 +44939,16 @@ class SessionStorage {
|
|
|
43939
44939
|
const root = getConfigDir();
|
|
43940
44940
|
const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
|
|
43941
44941
|
if (resolvedId) {
|
|
43942
|
-
const assistantDir =
|
|
43943
|
-
if (
|
|
44942
|
+
const assistantDir = join21(root, "assistants", resolvedId, "sessions");
|
|
44943
|
+
if (existsSync13(assistantDir)) {
|
|
43944
44944
|
return assistantDir;
|
|
43945
44945
|
}
|
|
43946
44946
|
}
|
|
43947
|
-
return
|
|
44947
|
+
return join21(root, "sessions");
|
|
43948
44948
|
}
|
|
43949
44949
|
static listSessions(assistantId) {
|
|
43950
44950
|
const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
|
|
43951
|
-
if (!
|
|
44951
|
+
if (!existsSync13(sessionsDir))
|
|
43952
44952
|
return [];
|
|
43953
44953
|
const sessions = [];
|
|
43954
44954
|
const files = readdirSync3(sessionsDir);
|
|
@@ -43956,9 +44956,9 @@ class SessionStorage {
|
|
|
43956
44956
|
if (!file.endsWith(".json"))
|
|
43957
44957
|
continue;
|
|
43958
44958
|
try {
|
|
43959
|
-
const filePath =
|
|
44959
|
+
const filePath = join21(sessionsDir, file);
|
|
43960
44960
|
const stat = Bun.file(filePath);
|
|
43961
|
-
const content = JSON.parse(
|
|
44961
|
+
const content = JSON.parse(readFileSync7(filePath, "utf-8"));
|
|
43962
44962
|
sessions.push({
|
|
43963
44963
|
id: file.replace(".json", ""),
|
|
43964
44964
|
cwd: content.cwd,
|
|
@@ -43976,11 +44976,11 @@ class SessionStorage {
|
|
|
43976
44976
|
}
|
|
43977
44977
|
static loadSession(sessionId, assistantId) {
|
|
43978
44978
|
const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
|
|
43979
|
-
const sessionFile =
|
|
44979
|
+
const sessionFile = join21(sessionsDir, `${sessionId}.json`);
|
|
43980
44980
|
try {
|
|
43981
|
-
if (!
|
|
44981
|
+
if (!existsSync13(sessionFile))
|
|
43982
44982
|
return null;
|
|
43983
|
-
return JSON.parse(
|
|
44983
|
+
return JSON.parse(readFileSync7(sessionFile, "utf-8"));
|
|
43984
44984
|
} catch {
|
|
43985
44985
|
return null;
|
|
43986
44986
|
}
|
|
@@ -43990,19 +44990,19 @@ function initAssistantsDir() {
|
|
|
43990
44990
|
const baseDir = getConfigDir();
|
|
43991
44991
|
const dirs = [
|
|
43992
44992
|
baseDir,
|
|
43993
|
-
|
|
43994
|
-
|
|
43995
|
-
|
|
43996
|
-
|
|
43997
|
-
|
|
43998
|
-
|
|
43999
|
-
|
|
44000
|
-
|
|
44001
|
-
|
|
44993
|
+
join21(baseDir, "logs"),
|
|
44994
|
+
join21(baseDir, "assistants"),
|
|
44995
|
+
join21(baseDir, "shared", "skills"),
|
|
44996
|
+
join21(baseDir, "commands"),
|
|
44997
|
+
join21(baseDir, "temp"),
|
|
44998
|
+
join21(baseDir, "heartbeats"),
|
|
44999
|
+
join21(baseDir, "state"),
|
|
45000
|
+
join21(baseDir, "energy"),
|
|
45001
|
+
join21(baseDir, "migration")
|
|
44002
45002
|
];
|
|
44003
45003
|
for (const dir of dirs) {
|
|
44004
|
-
if (!
|
|
44005
|
-
|
|
45004
|
+
if (!existsSync13(dir)) {
|
|
45005
|
+
mkdirSync7(dir, { recursive: true });
|
|
44006
45006
|
}
|
|
44007
45007
|
}
|
|
44008
45008
|
}
|
|
@@ -44041,6 +45041,11 @@ class EmbeddedClient {
|
|
|
44041
45041
|
for (const callback of this.chunkCallbacks) {
|
|
44042
45042
|
callback(chunk);
|
|
44043
45043
|
}
|
|
45044
|
+
if (chunk.type === "done" || chunk.type === "error") {
|
|
45045
|
+
queueMicrotask(() => {
|
|
45046
|
+
this.drainQueue();
|
|
45047
|
+
});
|
|
45048
|
+
}
|
|
44044
45049
|
},
|
|
44045
45050
|
onToolStart: (toolCall) => {
|
|
44046
45051
|
this.logger.info("Tool started", { tool: toolCall.name, input: toolCall.input });
|
|
@@ -44083,12 +45088,11 @@ class EmbeddedClient {
|
|
|
44083
45088
|
if (!this.initialized) {
|
|
44084
45089
|
await this.initialize();
|
|
44085
45090
|
}
|
|
44086
|
-
|
|
44087
|
-
|
|
44088
|
-
this.
|
|
45091
|
+
this.messageQueue.push(message);
|
|
45092
|
+
if (this.agent.isProcessing() || this.processingQueue) {
|
|
45093
|
+
this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length });
|
|
44089
45094
|
return;
|
|
44090
45095
|
}
|
|
44091
|
-
await this.processMessage(message);
|
|
44092
45096
|
await this.drainQueue();
|
|
44093
45097
|
}
|
|
44094
45098
|
async processMessage(message) {
|
|
@@ -44479,10 +45483,13 @@ var COMMANDS = [
|
|
|
44479
45483
|
{ name: "/model", description: "show model information" },
|
|
44480
45484
|
{ name: "/skills", description: "list available skills" },
|
|
44481
45485
|
{ name: "/config", description: "show configuration" },
|
|
45486
|
+
{ name: "/projects", description: "manage projects in this folder" },
|
|
45487
|
+
{ name: "/plans", description: "manage project plans" },
|
|
44482
45488
|
{ name: "/connectors", description: "list available connectors" },
|
|
44483
45489
|
{ name: "/init", description: "initialize assistants in project" },
|
|
44484
45490
|
{ name: "/compact", description: "summarize to save context" },
|
|
44485
45491
|
{ name: "/memory", description: "show what AI remembers" },
|
|
45492
|
+
{ name: "/context", description: "manage injected project context" },
|
|
44486
45493
|
{ name: "/feedback", description: "submit feedback on GitHub" },
|
|
44487
45494
|
{ name: "/schedule", description: "schedule a command" },
|
|
44488
45495
|
{ name: "/schedules", description: "list scheduled commands" },
|
|
@@ -44578,14 +45585,14 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
|
|
|
44578
45585
|
if (autocompleteMode === "command" && filteredCommands.length > 0 && !submittedValue.includes(" ")) {
|
|
44579
45586
|
const selected = filteredCommands[selectedIndex] || filteredCommands[0];
|
|
44580
45587
|
if (selected) {
|
|
44581
|
-
onSubmit(selected.name, isProcessing ? "
|
|
45588
|
+
onSubmit(selected.name, isProcessing ? "inline" : "normal");
|
|
44582
45589
|
setValue("");
|
|
44583
45590
|
setSelectedIndex(0);
|
|
44584
45591
|
return;
|
|
44585
45592
|
}
|
|
44586
45593
|
}
|
|
44587
45594
|
if (isProcessing) {
|
|
44588
|
-
onSubmit(submittedValue, "
|
|
45595
|
+
onSubmit(submittedValue, "inline");
|
|
44589
45596
|
} else {
|
|
44590
45597
|
onSubmit(submittedValue, "normal");
|
|
44591
45598
|
}
|
|
@@ -44596,7 +45603,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
|
|
|
44596
45603
|
let placeholder = "Type a message...";
|
|
44597
45604
|
if (isProcessing) {
|
|
44598
45605
|
prompt = "\u22EF";
|
|
44599
|
-
placeholder = queueLength > 0 ? "Type to
|
|
45606
|
+
placeholder = queueLength > 0 ? "Type to send (Enter) or queue (Tab) \xB7 Shift+Enter to interrupt..." : "Type to send (Enter) or queue (Tab) \xB7 Shift+Enter to interrupt...";
|
|
44600
45607
|
}
|
|
44601
45608
|
const truncateDescription = (desc, maxLen = 60) => {
|
|
44602
45609
|
if (desc.length <= maxLen)
|
|
@@ -44737,7 +45744,12 @@ var import_react24 = __toESM(require_react(), 1);
|
|
|
44737
45744
|
|
|
44738
45745
|
// packages/terminal/src/components/Markdown.tsx
|
|
44739
45746
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
44740
|
-
function Markdown({ content }) {
|
|
45747
|
+
function Markdown({ content, preRendered = false }) {
|
|
45748
|
+
if (preRendered) {
|
|
45749
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
45750
|
+
children: content
|
|
45751
|
+
}, undefined, false, undefined, this);
|
|
45752
|
+
}
|
|
44741
45753
|
const { columns } = use_stdout_default();
|
|
44742
45754
|
const maxWidth = columns ? Math.max(20, columns - 2) : undefined;
|
|
44743
45755
|
const rendered = parseMarkdown(content, { maxWidth });
|
|
@@ -44745,6 +45757,9 @@ function Markdown({ content }) {
|
|
|
44745
45757
|
children: rendered
|
|
44746
45758
|
}, undefined, false, undefined, this);
|
|
44747
45759
|
}
|
|
45760
|
+
function renderMarkdown(text, options) {
|
|
45761
|
+
return parseMarkdown(text, { maxWidth: options?.maxWidth });
|
|
45762
|
+
}
|
|
44748
45763
|
function parseMarkdown(text, options) {
|
|
44749
45764
|
let result = text;
|
|
44750
45765
|
const codeBlocks = [];
|
|
@@ -44770,7 +45785,7 @@ function parseMarkdown(text, options) {
|
|
|
44770
45785
|
result = result.replace(/\b(Building|Running|Working|Queued|Pending|Connecting)\b/gi, (match) => source_default.yellow(match));
|
|
44771
45786
|
result = result.replace(/\b(Success|Succeeded|Done|Complete|Completed|Connected|Authenticated)\b/gi, (match) => source_default.green(match));
|
|
44772
45787
|
result = result.replace(/\b(Error|Failed|Failure|Denied|Blocked)\b/gi, (match) => source_default.red(match));
|
|
44773
|
-
result = formatMarkdownTables(result);
|
|
45788
|
+
result = formatMarkdownTables(result, options?.maxWidth);
|
|
44774
45789
|
result = result.replace(/@@BLOCKSECTION(\d+)@@/g, (_, index) => {
|
|
44775
45790
|
const section = blockSections[parseInt(index, 10)];
|
|
44776
45791
|
if (!section)
|
|
@@ -44784,6 +45799,7 @@ function parseMarkdown(text, options) {
|
|
|
44784
45799
|
});
|
|
44785
45800
|
return result.trimEnd();
|
|
44786
45801
|
}
|
|
45802
|
+
var ALLOWED_BLOCK_TYPES = new Set(["info", "success", "warning", "error", "note", "command"]);
|
|
44787
45803
|
function extractBlockSections(text, blocks) {
|
|
44788
45804
|
const lines = text.split(`
|
|
44789
45805
|
`);
|
|
@@ -44812,6 +45828,9 @@ function extractBlockSections(text, blocks) {
|
|
|
44812
45828
|
i += 1;
|
|
44813
45829
|
continue;
|
|
44814
45830
|
}
|
|
45831
|
+
if (parsed.warning) {
|
|
45832
|
+
output.push(createMalformedBlock(blocks, indent, "grid", parsed.warning));
|
|
45833
|
+
}
|
|
44815
45834
|
const bodyLines = stripIndent(parsed.bodyLines, indent);
|
|
44816
45835
|
const body = bodyLines.join(`
|
|
44817
45836
|
`);
|
|
@@ -44825,7 +45844,7 @@ function extractBlockSections(text, blocks) {
|
|
|
44825
45844
|
const indent = blockMatch[1] ?? "";
|
|
44826
45845
|
const header = blockMatch[2] ?? "";
|
|
44827
45846
|
const attrs = parseAttributes(header);
|
|
44828
|
-
|
|
45847
|
+
let type = String(attrs.type || "info");
|
|
44829
45848
|
const title = attrs.title ? String(attrs.title) : undefined;
|
|
44830
45849
|
const parsed = parseDelimitedBlock(lines, i, indent);
|
|
44831
45850
|
if (!parsed) {
|
|
@@ -44834,6 +45853,14 @@ function extractBlockSections(text, blocks) {
|
|
|
44834
45853
|
i += 1;
|
|
44835
45854
|
continue;
|
|
44836
45855
|
}
|
|
45856
|
+
const normalizedType = type.toLowerCase();
|
|
45857
|
+
if (!ALLOWED_BLOCK_TYPES.has(normalizedType)) {
|
|
45858
|
+
output.push(createMalformedBlock(blocks, indent, "block", `Unknown block type "${type}". Using info.`));
|
|
45859
|
+
type = "info";
|
|
45860
|
+
}
|
|
45861
|
+
if (parsed.warning) {
|
|
45862
|
+
output.push(createMalformedBlock(blocks, indent, "block", parsed.warning));
|
|
45863
|
+
}
|
|
44837
45864
|
const body = stripIndent(parsed.bodyLines, indent).join(`
|
|
44838
45865
|
`);
|
|
44839
45866
|
blocks.push({ kind: "block", type, title, body, indent });
|
|
@@ -44850,6 +45877,9 @@ function extractBlockSections(text, blocks) {
|
|
|
44850
45877
|
i += 1;
|
|
44851
45878
|
continue;
|
|
44852
45879
|
}
|
|
45880
|
+
if (parsed.warning) {
|
|
45881
|
+
output.push(createMalformedBlock(blocks, indent, "report", parsed.warning));
|
|
45882
|
+
}
|
|
44853
45883
|
const body = stripIndent(parsed.bodyLines, indent).join(`
|
|
44854
45884
|
`);
|
|
44855
45885
|
blocks.push({ kind: "report", body, indent });
|
|
@@ -44881,10 +45911,14 @@ function extractCards(body) {
|
|
|
44881
45911
|
const title = attrs.title ? String(attrs.title) : undefined;
|
|
44882
45912
|
const bodyLines = [];
|
|
44883
45913
|
let closed = false;
|
|
45914
|
+
let indentWarning;
|
|
44884
45915
|
i += 1;
|
|
44885
45916
|
while (i < lines.length) {
|
|
44886
45917
|
const current = lines[i];
|
|
44887
|
-
if (current.trim() === ":::"
|
|
45918
|
+
if (current.trim() === ":::") {
|
|
45919
|
+
if (indent.length > 0 && !current.startsWith(indent)) {
|
|
45920
|
+
indentWarning = "Card closing ::: indentation did not match opening.";
|
|
45921
|
+
}
|
|
44888
45922
|
closed = true;
|
|
44889
45923
|
i += 1;
|
|
44890
45924
|
break;
|
|
@@ -44901,6 +45935,13 @@ function extractCards(body) {
|
|
|
44901
45935
|
break;
|
|
44902
45936
|
}
|
|
44903
45937
|
const stripped = stripIndent(bodyLines, indent);
|
|
45938
|
+
if (indentWarning) {
|
|
45939
|
+
cards.push({
|
|
45940
|
+
type: "warning",
|
|
45941
|
+
title: "Malformed card",
|
|
45942
|
+
body: indentWarning
|
|
45943
|
+
});
|
|
45944
|
+
}
|
|
44904
45945
|
cards.push({ type, title, body: stripped.join(`
|
|
44905
45946
|
`) });
|
|
44906
45947
|
}
|
|
@@ -44909,6 +45950,7 @@ function extractCards(body) {
|
|
|
44909
45950
|
function parseDelimitedBlock(lines, startIndex, indent) {
|
|
44910
45951
|
const bodyLines = [];
|
|
44911
45952
|
let openCards = 0;
|
|
45953
|
+
let warning;
|
|
44912
45954
|
let i = startIndex + 1;
|
|
44913
45955
|
while (i < lines.length) {
|
|
44914
45956
|
const current = lines[i];
|
|
@@ -44919,14 +45961,18 @@ function parseDelimitedBlock(lines, startIndex, indent) {
|
|
|
44919
45961
|
i += 1;
|
|
44920
45962
|
continue;
|
|
44921
45963
|
}
|
|
44922
|
-
if (trimmed === ":::"
|
|
45964
|
+
if (trimmed === ":::") {
|
|
45965
|
+
const indentMismatch = indent.length > 0 && !current.startsWith(indent);
|
|
44923
45966
|
if (openCards > 0) {
|
|
44924
45967
|
openCards -= 1;
|
|
44925
45968
|
bodyLines.push(current);
|
|
44926
45969
|
i += 1;
|
|
44927
45970
|
continue;
|
|
44928
45971
|
}
|
|
44929
|
-
|
|
45972
|
+
if (indentMismatch) {
|
|
45973
|
+
warning = "Closing ::: indentation did not match opening. Adjust indentation for consistency.";
|
|
45974
|
+
}
|
|
45975
|
+
return { bodyLines, nextIndex: i + 1, warning };
|
|
44930
45976
|
}
|
|
44931
45977
|
bodyLines.push(current);
|
|
44932
45978
|
i += 1;
|
|
@@ -45093,7 +46139,7 @@ function formatBoxRow(line, width) {
|
|
|
45093
46139
|
const padded = len < width ? line + " ".repeat(width - len) : line;
|
|
45094
46140
|
return `\u2502 ${padded} \u2502`;
|
|
45095
46141
|
}
|
|
45096
|
-
function formatMarkdownTables(text) {
|
|
46142
|
+
function formatMarkdownTables(text, maxWidth) {
|
|
45097
46143
|
const lines = text.split(`
|
|
45098
46144
|
`);
|
|
45099
46145
|
const output = [];
|
|
@@ -45111,7 +46157,7 @@ function formatMarkdownTables(text) {
|
|
|
45111
46157
|
rows.push(parseTableRow(lines[i]));
|
|
45112
46158
|
i += 1;
|
|
45113
46159
|
}
|
|
45114
|
-
const table = renderTable(header, rows);
|
|
46160
|
+
const table = renderTable(header, rows, maxWidth);
|
|
45115
46161
|
output.push(...table);
|
|
45116
46162
|
continue;
|
|
45117
46163
|
}
|
|
@@ -45126,7 +46172,7 @@ function parseTableRow(line) {
|
|
|
45126
46172
|
const withoutEdges = trimmed.replace(/^\|/, "").replace(/\|$/, "");
|
|
45127
46173
|
return withoutEdges.split("|").map((cell) => cell.trim());
|
|
45128
46174
|
}
|
|
45129
|
-
function renderTable(header, rows) {
|
|
46175
|
+
function renderTable(header, rows, maxWidth) {
|
|
45130
46176
|
const colCount = Math.max(header.length, ...rows.map((r) => r.length));
|
|
45131
46177
|
const widths = new Array(colCount).fill(0);
|
|
45132
46178
|
const allRows = [header, ...rows];
|
|
@@ -45138,11 +46184,29 @@ function renderTable(header, rows) {
|
|
|
45138
46184
|
widths[i] = len;
|
|
45139
46185
|
}
|
|
45140
46186
|
}
|
|
46187
|
+
const minCellWidth = 4;
|
|
46188
|
+
const availableCellWidth = maxWidth ? Math.max(colCount * minCellWidth, maxWidth - (colCount - 1) * 3 - 4) : undefined;
|
|
46189
|
+
if (availableCellWidth) {
|
|
46190
|
+
const total = widths.reduce((sum, width) => sum + width, 0);
|
|
46191
|
+
if (total > availableCellWidth) {
|
|
46192
|
+
const minWidth = Math.max(1, Math.floor(availableCellWidth / colCount));
|
|
46193
|
+
while (widths.reduce((sum, width) => sum + width, 0) > availableCellWidth) {
|
|
46194
|
+
const maxWidthValue = Math.max(...widths);
|
|
46195
|
+
const idx = widths.findIndex((width) => width === maxWidthValue);
|
|
46196
|
+
if (idx === -1)
|
|
46197
|
+
break;
|
|
46198
|
+
if (widths[idx] <= minWidth)
|
|
46199
|
+
break;
|
|
46200
|
+
widths[idx] -= 1;
|
|
46201
|
+
}
|
|
46202
|
+
}
|
|
46203
|
+
}
|
|
45141
46204
|
const pad = (value, width) => {
|
|
45142
|
-
const
|
|
46205
|
+
const rendered = width > 0 ? truncateAnsi(value, width) : value;
|
|
46206
|
+
const len = stripAnsi2(rendered).length;
|
|
45143
46207
|
if (len >= width)
|
|
45144
|
-
return
|
|
45145
|
-
return
|
|
46208
|
+
return rendered;
|
|
46209
|
+
return rendered + " ".repeat(width - len);
|
|
45146
46210
|
};
|
|
45147
46211
|
const top = "\u250C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C") + "\u2510";
|
|
45148
46212
|
const mid = "\u251C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u253C") + "\u2524";
|
|
@@ -45220,7 +46284,8 @@ function renderReport(body, maxWidth, indent = "") {
|
|
|
45220
46284
|
}
|
|
45221
46285
|
if (tableLines.length > 0) {
|
|
45222
46286
|
output.push(indent + source_default.bold("Detailed Status Table"));
|
|
45223
|
-
const
|
|
46287
|
+
const adjustedWidth = maxWidth ? Math.max(20, maxWidth - indent.length) : undefined;
|
|
46288
|
+
const rendered = renderReportTable(tableLines, indent, adjustedWidth);
|
|
45224
46289
|
output.push(...rendered);
|
|
45225
46290
|
}
|
|
45226
46291
|
return output.join(`
|
|
@@ -45249,7 +46314,7 @@ function renderProgressLine(label, value, labelWidth, barWidth) {
|
|
|
45249
46314
|
const bar = source_default.gray("\u2591".repeat(empty));
|
|
45250
46315
|
return `${label.padEnd(labelWidth)} [${fill}${bar}] ${value}%`;
|
|
45251
46316
|
}
|
|
45252
|
-
function renderReportTable(lines, indent) {
|
|
46317
|
+
function renderReportTable(lines, indent, maxWidth) {
|
|
45253
46318
|
const tableLines = lines.map((line) => line.trim()).filter(Boolean);
|
|
45254
46319
|
if (tableLines.length < 2)
|
|
45255
46320
|
return [];
|
|
@@ -45273,7 +46338,7 @@ function renderReportTable(lines, indent) {
|
|
|
45273
46338
|
}
|
|
45274
46339
|
return next;
|
|
45275
46340
|
});
|
|
45276
|
-
return renderTable(header, styledRows).map((line) => indent + line);
|
|
46341
|
+
return renderTable(header, styledRows, maxWidth).map((line) => indent + line);
|
|
45277
46342
|
}
|
|
45278
46343
|
function decoratePriority(value) {
|
|
45279
46344
|
const normalized = value.toLowerCase();
|
|
@@ -45343,6 +46408,23 @@ function wrapAnsiLine(line, width) {
|
|
|
45343
46408
|
function truncateAnsi(line, width) {
|
|
45344
46409
|
if (stripAnsi2(line).length <= width)
|
|
45345
46410
|
return line;
|
|
46411
|
+
if (width <= 3) {
|
|
46412
|
+
let result = "";
|
|
46413
|
+
let visible2 = 0;
|
|
46414
|
+
let i2 = 0;
|
|
46415
|
+
while (i2 < line.length && visible2 < width) {
|
|
46416
|
+
const match = line.slice(i2).match(/^\x1b\[[0-9;]*m/);
|
|
46417
|
+
if (match) {
|
|
46418
|
+
result += match[0];
|
|
46419
|
+
i2 += match[0].length;
|
|
46420
|
+
continue;
|
|
46421
|
+
}
|
|
46422
|
+
result += line[i2];
|
|
46423
|
+
visible2 += 1;
|
|
46424
|
+
i2 += 1;
|
|
46425
|
+
}
|
|
46426
|
+
return result;
|
|
46427
|
+
}
|
|
45346
46428
|
const suffix = "...";
|
|
45347
46429
|
const target = Math.max(0, width - suffix.length);
|
|
45348
46430
|
let current = "";
|
|
@@ -45362,6 +46444,42 @@ function truncateAnsi(line, width) {
|
|
|
45362
46444
|
return current + suffix;
|
|
45363
46445
|
}
|
|
45364
46446
|
|
|
46447
|
+
// packages/terminal/src/components/messageLines.ts
|
|
46448
|
+
function estimateToolPanelLines(toolCalls, toolResults, hasContent) {
|
|
46449
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
46450
|
+
return 0;
|
|
46451
|
+
}
|
|
46452
|
+
const resultMap = new Set;
|
|
46453
|
+
for (const result of toolResults || []) {
|
|
46454
|
+
resultMap.add(result.toolCallId);
|
|
46455
|
+
}
|
|
46456
|
+
let lines = 3;
|
|
46457
|
+
if (hasContent) {
|
|
46458
|
+
lines += 1;
|
|
46459
|
+
}
|
|
46460
|
+
for (const call of toolCalls) {
|
|
46461
|
+
lines += 3;
|
|
46462
|
+
if (resultMap.has(call.id)) {
|
|
46463
|
+
lines += 1;
|
|
46464
|
+
}
|
|
46465
|
+
}
|
|
46466
|
+
return lines;
|
|
46467
|
+
}
|
|
46468
|
+
function estimateMessageLines(message) {
|
|
46469
|
+
if (message.role === "system") {
|
|
46470
|
+
return 0;
|
|
46471
|
+
}
|
|
46472
|
+
const content = message.content ?? "";
|
|
46473
|
+
const contentLines = content.length > 0 ? content.split(`
|
|
46474
|
+
`).length : 0;
|
|
46475
|
+
const hasContent = contentLines > 0;
|
|
46476
|
+
let lines = Math.max(1, contentLines);
|
|
46477
|
+
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
46478
|
+
lines += estimateToolPanelLines(message.toolCalls, message.toolResults, hasContent);
|
|
46479
|
+
}
|
|
46480
|
+
return lines;
|
|
46481
|
+
}
|
|
46482
|
+
|
|
45365
46483
|
// packages/terminal/src/components/Messages.tsx
|
|
45366
46484
|
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
45367
46485
|
function Messages4({
|
|
@@ -45371,19 +46489,28 @@ function Messages4({
|
|
|
45371
46489
|
currentToolCall,
|
|
45372
46490
|
lastToolResult,
|
|
45373
46491
|
activityLog = [],
|
|
45374
|
-
|
|
45375
|
-
|
|
46492
|
+
scrollOffsetLines = 0,
|
|
46493
|
+
maxVisibleLines = 10,
|
|
45376
46494
|
queuedMessageIds
|
|
45377
46495
|
}) {
|
|
45378
46496
|
const [now2, setNow] = import_react24.useState(Date.now());
|
|
45379
46497
|
const combinedMessages = import_react24.useMemo(() => [...messages, ...streamingMessages], [messages, streamingMessages]);
|
|
45380
|
-
const
|
|
45381
|
-
|
|
45382
|
-
|
|
46498
|
+
const lineSpans = import_react24.useMemo(() => {
|
|
46499
|
+
let cursor = 0;
|
|
46500
|
+
return combinedMessages.map((message, index) => {
|
|
46501
|
+
const lines = estimateMessageLines(message);
|
|
46502
|
+
const start = cursor;
|
|
46503
|
+
cursor += lines;
|
|
46504
|
+
return { message, index, start, end: cursor, lines };
|
|
46505
|
+
});
|
|
46506
|
+
}, [combinedMessages]);
|
|
46507
|
+
const totalLines = lineSpans.length > 0 ? lineSpans[lineSpans.length - 1].end : 0;
|
|
46508
|
+
const endLine = Math.max(0, totalLines - scrollOffsetLines);
|
|
46509
|
+
const startLine = Math.max(0, endLine - maxVisibleLines);
|
|
46510
|
+
const visibleSpans = lineSpans.filter((span) => span.end > startLine && span.start < endLine);
|
|
45383
46511
|
const historicalCount = messages.length;
|
|
45384
|
-
const
|
|
45385
|
-
const
|
|
45386
|
-
const visibleStreaming = visibleCombined.slice(splitIndex);
|
|
46512
|
+
const visibleMessages = visibleSpans.filter((span) => span.index < historicalCount).map((span) => span.message);
|
|
46513
|
+
const visibleStreaming = visibleSpans.filter((span) => span.index >= historicalCount).map((span) => span.message);
|
|
45387
46514
|
const groupedMessages = groupConsecutiveToolMessages(visibleMessages);
|
|
45388
46515
|
const historicalItems = groupedMessages.map((group) => {
|
|
45389
46516
|
if (group.type === "single") {
|
|
@@ -45586,6 +46713,8 @@ function MessageBubble({ message, queuedMessageIds }) {
|
|
|
45586
46713
|
const chunkMatch = message.id.match(/::chunk-(\d+)$/);
|
|
45587
46714
|
const chunkIndex = chunkMatch ? Number(chunkMatch[1]) : -1;
|
|
45588
46715
|
const isContinuation = chunkIndex > 0;
|
|
46716
|
+
const content = message.content ?? "";
|
|
46717
|
+
const leadingBullet = !isContinuation && !startsWithListOrTable(content);
|
|
45589
46718
|
if (isSystem) {
|
|
45590
46719
|
return null;
|
|
45591
46720
|
}
|
|
@@ -45614,7 +46743,7 @@ function MessageBubble({ message, queuedMessageIds }) {
|
|
|
45614
46743
|
}
|
|
45615
46744
|
const toolCalls = message.toolCalls || [];
|
|
45616
46745
|
const toolResults = message.toolResults || [];
|
|
45617
|
-
const hasContent =
|
|
46746
|
+
const hasContent = content && content.trim();
|
|
45618
46747
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45619
46748
|
marginY: isContinuation ? 0 : 1,
|
|
45620
46749
|
flexDirection: "column",
|
|
@@ -45624,14 +46753,15 @@ function MessageBubble({ message, queuedMessageIds }) {
|
|
|
45624
46753
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
45625
46754
|
dimColor: true,
|
|
45626
46755
|
children: [
|
|
45627
|
-
isContinuation ? " " : "\u25CF ",
|
|
46756
|
+
isContinuation || !leadingBullet ? " " : "\u25CF ",
|
|
45628
46757
|
" "
|
|
45629
46758
|
]
|
|
45630
46759
|
}, undefined, true, undefined, this),
|
|
45631
46760
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45632
46761
|
flexGrow: 1,
|
|
45633
46762
|
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Markdown, {
|
|
45634
|
-
content: message.content
|
|
46763
|
+
content: message.content,
|
|
46764
|
+
preRendered: Boolean(message.__rendered)
|
|
45635
46765
|
}, undefined, false, undefined, this)
|
|
45636
46766
|
}, undefined, false, undefined, this)
|
|
45637
46767
|
]
|
|
@@ -45646,12 +46776,31 @@ function MessageBubble({ message, queuedMessageIds }) {
|
|
|
45646
46776
|
]
|
|
45647
46777
|
}, undefined, true, undefined, this);
|
|
45648
46778
|
}
|
|
46779
|
+
function startsWithListOrTable(content) {
|
|
46780
|
+
const lines = content.split(`
|
|
46781
|
+
`);
|
|
46782
|
+
for (const line of lines) {
|
|
46783
|
+
const trimmed = line.trimStart();
|
|
46784
|
+
if (!trimmed)
|
|
46785
|
+
continue;
|
|
46786
|
+
if (/^[-*\u2022]\s+/.test(trimmed))
|
|
46787
|
+
return true;
|
|
46788
|
+
if (/^\d+\.\s+/.test(trimmed))
|
|
46789
|
+
return true;
|
|
46790
|
+
if (trimmed.startsWith("|"))
|
|
46791
|
+
return true;
|
|
46792
|
+
return false;
|
|
46793
|
+
}
|
|
46794
|
+
return false;
|
|
46795
|
+
}
|
|
45649
46796
|
function ToolCallPanel({
|
|
45650
46797
|
toolCalls,
|
|
45651
46798
|
toolResults
|
|
45652
46799
|
}) {
|
|
45653
46800
|
if (toolCalls.length === 0)
|
|
45654
46801
|
return null;
|
|
46802
|
+
const { columns } = use_stdout_default();
|
|
46803
|
+
const panelWidth = columns ? Math.max(24, columns - 4) : undefined;
|
|
45655
46804
|
const resultMap = new Map;
|
|
45656
46805
|
for (const result of toolResults || []) {
|
|
45657
46806
|
resultMap.set(result.toolCallId, result);
|
|
@@ -45690,6 +46839,8 @@ function ToolCallPanel({
|
|
|
45690
46839
|
const statusColor = result ? result.isError ? "red" : "green" : "yellow";
|
|
45691
46840
|
const displayName = getToolDisplayName(toolCall);
|
|
45692
46841
|
const context2 = getToolContext(toolCall);
|
|
46842
|
+
const maxLine = panelWidth ? Math.max(20, panelWidth - 8) : 80;
|
|
46843
|
+
const summaryLine = truncate(formatToolCall(toolCall), maxLine);
|
|
45693
46844
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45694
46845
|
flexDirection: "column",
|
|
45695
46846
|
marginTop: 1,
|
|
@@ -45719,7 +46870,7 @@ function ToolCallPanel({
|
|
|
45719
46870
|
}, undefined, true, undefined, this),
|
|
45720
46871
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
45721
46872
|
dimColor: true,
|
|
45722
|
-
children:
|
|
46873
|
+
children: summaryLine
|
|
45723
46874
|
}, undefined, false, undefined, this),
|
|
45724
46875
|
result && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45725
46876
|
marginLeft: 2,
|
|
@@ -45754,7 +46905,7 @@ function getToolContext(toolCall) {
|
|
|
45754
46905
|
return truncate(String(input.pattern || ""), 20);
|
|
45755
46906
|
case "schedule":
|
|
45756
46907
|
return String(input.action || "");
|
|
45757
|
-
case "
|
|
46908
|
+
case "submit_feedback":
|
|
45758
46909
|
return String(input.type || "feedback");
|
|
45759
46910
|
case "web_search":
|
|
45760
46911
|
return truncate(String(input.query || ""), 20);
|
|
@@ -45795,7 +46946,7 @@ function getToolDisplayName(toolCall) {
|
|
|
45795
46946
|
return "image";
|
|
45796
46947
|
case "schedule":
|
|
45797
46948
|
return "schedule";
|
|
45798
|
-
case "
|
|
46949
|
+
case "submit_feedback":
|
|
45799
46950
|
return "feedback";
|
|
45800
46951
|
case "notion":
|
|
45801
46952
|
case "gmail":
|
|
@@ -45829,7 +46980,7 @@ function formatToolCall(toolCall) {
|
|
|
45829
46980
|
return `Searching: ${truncate(String(input.pattern || ""), 60)}`;
|
|
45830
46981
|
case "schedule":
|
|
45831
46982
|
return formatScheduleCall(input);
|
|
45832
|
-
case "
|
|
46983
|
+
case "submit_feedback":
|
|
45833
46984
|
return formatFeedbackCall(input);
|
|
45834
46985
|
case "notion":
|
|
45835
46986
|
return `Notion: ${truncate(String(input.command || input.action || ""), 60)}`;
|
|
@@ -45925,7 +47076,7 @@ function formatToolResultNicely(toolName, content, isError) {
|
|
|
45925
47076
|
switch (toolName) {
|
|
45926
47077
|
case "schedule":
|
|
45927
47078
|
return formatScheduleResult(content);
|
|
45928
|
-
case "
|
|
47079
|
+
case "submit_feedback":
|
|
45929
47080
|
return formatFeedbackResult(content);
|
|
45930
47081
|
case "read":
|
|
45931
47082
|
return formatReadResult(content);
|
|
@@ -46035,46 +47186,7 @@ function formatSearchResult(content) {
|
|
|
46035
47186
|
|
|
46036
47187
|
// packages/terminal/src/components/Status.tsx
|
|
46037
47188
|
var import_react25 = __toESM(require_react(), 1);
|
|
46038
|
-
|
|
46039
|
-
// packages/terminal/src/components/EnergyBar.tsx
|
|
46040
47189
|
var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46041
|
-
function EnergyBar({ current, max }) {
|
|
46042
|
-
const safeMax = Math.max(1, max);
|
|
46043
|
-
const percentage = Math.round(current / safeMax * 100);
|
|
46044
|
-
const barWidth = 16;
|
|
46045
|
-
const filled = Math.round(current / safeMax * barWidth);
|
|
46046
|
-
const empty = Math.max(0, barWidth - filled);
|
|
46047
|
-
const color = percentage > 50 ? "green" : percentage > 20 ? "yellow" : "red";
|
|
46048
|
-
const emoji = percentage > 70 ? "\u26A1" : percentage > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
|
|
46049
|
-
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
46050
|
-
children: [
|
|
46051
|
-
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46052
|
-
children: [
|
|
46053
|
-
emoji,
|
|
46054
|
-
" "
|
|
46055
|
-
]
|
|
46056
|
-
}, undefined, true, undefined, this),
|
|
46057
|
-
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46058
|
-
color,
|
|
46059
|
-
children: "\u2588".repeat(filled)
|
|
46060
|
-
}, undefined, false, undefined, this),
|
|
46061
|
-
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46062
|
-
color: "gray",
|
|
46063
|
-
children: "\u2591".repeat(empty)
|
|
46064
|
-
}, undefined, false, undefined, this),
|
|
46065
|
-
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46066
|
-
children: [
|
|
46067
|
-
" ",
|
|
46068
|
-
percentage,
|
|
46069
|
-
"%"
|
|
46070
|
-
]
|
|
46071
|
-
}, undefined, true, undefined, this)
|
|
46072
|
-
]
|
|
46073
|
-
}, undefined, true, undefined, this);
|
|
46074
|
-
}
|
|
46075
|
-
|
|
46076
|
-
// packages/terminal/src/components/Status.tsx
|
|
46077
|
-
var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46078
47190
|
function Status({
|
|
46079
47191
|
isProcessing,
|
|
46080
47192
|
cwd: cwd2,
|
|
@@ -46112,75 +47224,60 @@ function Status({
|
|
|
46112
47224
|
let contextInfo = "";
|
|
46113
47225
|
if (tokenUsage && tokenUsage.maxContextTokens > 0) {
|
|
46114
47226
|
const percent = Math.round(tokenUsage.totalTokens / tokenUsage.maxContextTokens * 100);
|
|
46115
|
-
contextInfo = `${percent}
|
|
47227
|
+
contextInfo = `${percent}%`;
|
|
46116
47228
|
}
|
|
46117
|
-
const sessionInfo = sessionIndex && sessionCount ?
|
|
46118
|
-
const bgIndicator = backgroundProcessingCount > 0 ? `
|
|
46119
|
-
const
|
|
46120
|
-
const
|
|
46121
|
-
return /* @__PURE__ */
|
|
47229
|
+
const sessionInfo = sessionIndex && sessionCount && sessionCount > 1 ? `${sessionIndex}/${sessionCount}` : "";
|
|
47230
|
+
const bgIndicator = backgroundProcessingCount > 0 ? ` +${backgroundProcessingCount}` : "";
|
|
47231
|
+
const voiceIcon = voiceState?.enabled ? voiceState.isListening ? "\uD83C\uDFA4" : voiceState.isSpeaking ? "\uD83D\uDD0A" : "\uD83C\uDF99" : "";
|
|
47232
|
+
const sessionLabel = sessionId ? `id ${sessionId}` : "";
|
|
47233
|
+
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
46122
47234
|
marginTop: 1,
|
|
46123
47235
|
justifyContent: "space-between",
|
|
46124
47236
|
children: [
|
|
46125
|
-
/* @__PURE__ */
|
|
47237
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46126
47238
|
dimColor: true,
|
|
46127
47239
|
children: [
|
|
46128
|
-
"/help
|
|
46129
|
-
sessionCount && sessionCount > 1 ? "
|
|
47240
|
+
"/help",
|
|
47241
|
+
sessionCount && sessionCount > 1 ? " \xB7 Ctrl+S" : ""
|
|
46130
47242
|
]
|
|
46131
47243
|
}, undefined, true, undefined, this),
|
|
46132
|
-
/* @__PURE__ */
|
|
47244
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
46133
47245
|
children: [
|
|
46134
|
-
|
|
46135
|
-
marginRight: 2,
|
|
46136
|
-
children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(EnergyBar, {
|
|
46137
|
-
current: energyState.current,
|
|
46138
|
-
max: energyState.max
|
|
46139
|
-
}, undefined, false, undefined, this)
|
|
46140
|
-
}, undefined, false, undefined, this),
|
|
46141
|
-
identityLabel && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
46142
|
-
dimColor: true,
|
|
46143
|
-
children: [
|
|
46144
|
-
identityLabel,
|
|
46145
|
-
" \xB7 "
|
|
46146
|
-
]
|
|
46147
|
-
}, undefined, true, undefined, this),
|
|
46148
|
-
voiceInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
47246
|
+
voiceIcon && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46149
47247
|
dimColor: true,
|
|
46150
47248
|
children: [
|
|
46151
|
-
|
|
46152
|
-
"
|
|
47249
|
+
voiceIcon,
|
|
47250
|
+
" "
|
|
46153
47251
|
]
|
|
46154
47252
|
}, undefined, true, undefined, this),
|
|
46155
|
-
isProcessing && /* @__PURE__ */
|
|
47253
|
+
isProcessing && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46156
47254
|
dimColor: true,
|
|
46157
|
-
children: "esc
|
|
47255
|
+
children: "esc \xB7 "
|
|
46158
47256
|
}, undefined, false, undefined, this),
|
|
46159
|
-
sessionInfo && /* @__PURE__ */
|
|
47257
|
+
sessionInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46160
47258
|
dimColor: true,
|
|
46161
47259
|
children: [
|
|
46162
47260
|
sessionInfo,
|
|
46163
47261
|
bgIndicator,
|
|
46164
|
-
|
|
47262
|
+
" \xB7 "
|
|
46165
47263
|
]
|
|
46166
47264
|
}, undefined, true, undefined, this),
|
|
46167
|
-
contextInfo && /* @__PURE__ */
|
|
47265
|
+
contextInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46168
47266
|
dimColor: true,
|
|
46169
47267
|
children: contextInfo
|
|
46170
47268
|
}, undefined, false, undefined, this),
|
|
46171
|
-
|
|
47269
|
+
isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46172
47270
|
dimColor: true,
|
|
46173
47271
|
children: [
|
|
46174
|
-
|
|
46175
|
-
|
|
46176
|
-
sessionId
|
|
47272
|
+
" \xB7 ",
|
|
47273
|
+
formatDuration2(elapsed)
|
|
46177
47274
|
]
|
|
46178
47275
|
}, undefined, true, undefined, this),
|
|
46179
|
-
|
|
47276
|
+
sessionLabel && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46180
47277
|
dimColor: true,
|
|
46181
47278
|
children: [
|
|
46182
|
-
" \xB7
|
|
46183
|
-
|
|
47279
|
+
contextInfo || isProcessing && processingStartTime || sessionInfo ? " \xB7 " : "",
|
|
47280
|
+
sessionLabel
|
|
46184
47281
|
]
|
|
46185
47282
|
}, undefined, true, undefined, this)
|
|
46186
47283
|
]
|
|
@@ -46211,17 +47308,17 @@ function Spinner({ type = "dots" }) {
|
|
|
46211
47308
|
var build_default2 = Spinner;
|
|
46212
47309
|
|
|
46213
47310
|
// packages/terminal/src/components/Spinner.tsx
|
|
46214
|
-
var
|
|
47311
|
+
var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46215
47312
|
function Spinner2({ label }) {
|
|
46216
|
-
return /* @__PURE__ */
|
|
47313
|
+
return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
46217
47314
|
children: [
|
|
46218
|
-
/* @__PURE__ */
|
|
47315
|
+
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
46219
47316
|
dimColor: true,
|
|
46220
|
-
children: /* @__PURE__ */
|
|
47317
|
+
children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(build_default2, {
|
|
46221
47318
|
type: "dots"
|
|
46222
47319
|
}, undefined, false, undefined, this)
|
|
46223
47320
|
}, undefined, false, undefined, this),
|
|
46224
|
-
label && /* @__PURE__ */
|
|
47321
|
+
label && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
46225
47322
|
dimColor: true,
|
|
46226
47323
|
children: [
|
|
46227
47324
|
" ",
|
|
@@ -46234,7 +47331,7 @@ function Spinner2({ label }) {
|
|
|
46234
47331
|
|
|
46235
47332
|
// packages/terminal/src/components/ProcessingIndicator.tsx
|
|
46236
47333
|
var import_react27 = __toESM(require_react(), 1);
|
|
46237
|
-
var
|
|
47334
|
+
var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46238
47335
|
function ProcessingIndicator({
|
|
46239
47336
|
isProcessing,
|
|
46240
47337
|
startTime,
|
|
@@ -46278,14 +47375,14 @@ function ProcessingIndicator({
|
|
|
46278
47375
|
parts.push("thinking");
|
|
46279
47376
|
}
|
|
46280
47377
|
const label = isThinking ? "Metamorphosing" : "Working";
|
|
46281
|
-
return /* @__PURE__ */
|
|
47378
|
+
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
46282
47379
|
marginY: 1,
|
|
46283
47380
|
children: [
|
|
46284
|
-
/* @__PURE__ */
|
|
47381
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
46285
47382
|
dimColor: true,
|
|
46286
47383
|
children: "\u2736 "
|
|
46287
47384
|
}, undefined, false, undefined, this),
|
|
46288
|
-
/* @__PURE__ */
|
|
47385
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
46289
47386
|
dimColor: true,
|
|
46290
47387
|
children: [
|
|
46291
47388
|
" ",
|
|
@@ -46293,7 +47390,7 @@ function ProcessingIndicator({
|
|
|
46293
47390
|
"... "
|
|
46294
47391
|
]
|
|
46295
47392
|
}, undefined, true, undefined, this),
|
|
46296
|
-
/* @__PURE__ */
|
|
47393
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
46297
47394
|
dimColor: true,
|
|
46298
47395
|
children: [
|
|
46299
47396
|
"(",
|
|
@@ -46306,31 +47403,31 @@ function ProcessingIndicator({
|
|
|
46306
47403
|
}
|
|
46307
47404
|
|
|
46308
47405
|
// packages/terminal/src/components/WelcomeBanner.tsx
|
|
46309
|
-
var
|
|
47406
|
+
var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46310
47407
|
function WelcomeBanner({ version, model, directory }) {
|
|
46311
47408
|
const homeDir = process.env.HOME || "";
|
|
46312
47409
|
const displayDir = directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
|
|
46313
|
-
return /* @__PURE__ */
|
|
47410
|
+
return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46314
47411
|
flexDirection: "column",
|
|
46315
47412
|
marginBottom: 1,
|
|
46316
47413
|
children: [
|
|
46317
|
-
/* @__PURE__ */
|
|
47414
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46318
47415
|
children: [
|
|
46319
|
-
/* @__PURE__ */
|
|
47416
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46320
47417
|
color: "cyan",
|
|
46321
47418
|
bold: true,
|
|
46322
47419
|
children: ">"
|
|
46323
47420
|
}, undefined, false, undefined, this),
|
|
46324
|
-
/* @__PURE__ */
|
|
47421
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46325
47422
|
color: "cyan",
|
|
46326
47423
|
bold: true,
|
|
46327
47424
|
children: "_ "
|
|
46328
47425
|
}, undefined, false, undefined, this),
|
|
46329
|
-
/* @__PURE__ */
|
|
47426
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46330
47427
|
bold: true,
|
|
46331
47428
|
children: "assistants"
|
|
46332
47429
|
}, undefined, false, undefined, this),
|
|
46333
|
-
/* @__PURE__ */
|
|
47430
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46334
47431
|
dimColor: true,
|
|
46335
47432
|
children: [
|
|
46336
47433
|
" (v",
|
|
@@ -46340,29 +47437,29 @@ function WelcomeBanner({ version, model, directory }) {
|
|
|
46340
47437
|
}, undefined, true, undefined, this)
|
|
46341
47438
|
]
|
|
46342
47439
|
}, undefined, true, undefined, this),
|
|
46343
|
-
/* @__PURE__ */
|
|
47440
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46344
47441
|
marginTop: 1,
|
|
46345
47442
|
children: [
|
|
46346
|
-
/* @__PURE__ */
|
|
47443
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46347
47444
|
dimColor: true,
|
|
46348
47445
|
children: "model: "
|
|
46349
47446
|
}, undefined, false, undefined, this),
|
|
46350
|
-
/* @__PURE__ */
|
|
47447
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46351
47448
|
children: model
|
|
46352
47449
|
}, undefined, false, undefined, this),
|
|
46353
|
-
/* @__PURE__ */
|
|
47450
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46354
47451
|
dimColor: true,
|
|
46355
47452
|
children: " /model to change"
|
|
46356
47453
|
}, undefined, false, undefined, this)
|
|
46357
47454
|
]
|
|
46358
47455
|
}, undefined, true, undefined, this),
|
|
46359
|
-
/* @__PURE__ */
|
|
47456
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46360
47457
|
children: [
|
|
46361
|
-
/* @__PURE__ */
|
|
47458
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46362
47459
|
dimColor: true,
|
|
46363
47460
|
children: "directory: "
|
|
46364
47461
|
}, undefined, false, undefined, this),
|
|
46365
|
-
/* @__PURE__ */
|
|
47462
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46366
47463
|
children: displayDir
|
|
46367
47464
|
}, undefined, false, undefined, this)
|
|
46368
47465
|
]
|
|
@@ -46373,7 +47470,7 @@ function WelcomeBanner({ version, model, directory }) {
|
|
|
46373
47470
|
|
|
46374
47471
|
// packages/terminal/src/components/SessionSelector.tsx
|
|
46375
47472
|
var import_react28 = __toESM(require_react(), 1);
|
|
46376
|
-
var
|
|
47473
|
+
var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46377
47474
|
function formatSessionTime(timestamp) {
|
|
46378
47475
|
const date = new Date(timestamp);
|
|
46379
47476
|
const now2 = new Date;
|
|
@@ -46439,13 +47536,13 @@ function SessionSelector({
|
|
|
46439
47536
|
return;
|
|
46440
47537
|
}
|
|
46441
47538
|
});
|
|
46442
|
-
return /* @__PURE__ */
|
|
47539
|
+
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46443
47540
|
flexDirection: "column",
|
|
46444
47541
|
paddingY: 1,
|
|
46445
47542
|
children: [
|
|
46446
|
-
/* @__PURE__ */
|
|
47543
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46447
47544
|
marginBottom: 1,
|
|
46448
|
-
children: /* @__PURE__ */
|
|
47545
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46449
47546
|
bold: true,
|
|
46450
47547
|
children: "Sessions"
|
|
46451
47548
|
}, undefined, false, undefined, this)
|
|
@@ -46457,8 +47554,8 @@ function SessionSelector({
|
|
|
46457
47554
|
const time = formatSessionTime(session.updatedAt);
|
|
46458
47555
|
const path2 = formatPath(session.cwd);
|
|
46459
47556
|
const processing = session.isProcessing ? " (processing)" : "";
|
|
46460
|
-
return /* @__PURE__ */
|
|
46461
|
-
children: /* @__PURE__ */
|
|
47557
|
+
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
47558
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46462
47559
|
inverse: isSelected,
|
|
46463
47560
|
color: isActive ? "green" : undefined,
|
|
46464
47561
|
dimColor: !isSelected && !isActive,
|
|
@@ -46475,17 +47572,17 @@ function SessionSelector({
|
|
|
46475
47572
|
}, undefined, true, undefined, this)
|
|
46476
47573
|
}, session.id, false, undefined, this);
|
|
46477
47574
|
}),
|
|
46478
|
-
/* @__PURE__ */
|
|
47575
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46479
47576
|
marginTop: 1,
|
|
46480
|
-
children: /* @__PURE__ */
|
|
47577
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46481
47578
|
inverse: selectedIndex === sessions.length,
|
|
46482
47579
|
dimColor: selectedIndex !== sessions.length,
|
|
46483
47580
|
children: "+ New session (n)"
|
|
46484
47581
|
}, undefined, false, undefined, this)
|
|
46485
47582
|
}, undefined, false, undefined, this),
|
|
46486
|
-
/* @__PURE__ */
|
|
47583
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46487
47584
|
marginTop: 1,
|
|
46488
|
-
children: /* @__PURE__ */
|
|
47585
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46489
47586
|
dimColor: true,
|
|
46490
47587
|
children: [
|
|
46491
47588
|
"Enter to select | Esc to cancel | 1-",
|
|
@@ -46499,32 +47596,8 @@ function SessionSelector({
|
|
|
46499
47596
|
}
|
|
46500
47597
|
|
|
46501
47598
|
// packages/terminal/src/components/App.tsx
|
|
46502
|
-
var
|
|
47599
|
+
var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46503
47600
|
var SHOW_ERROR_CODES = process.env.ASSISTANTS_DEBUG === "1" || process.env.OLDPAL_DEBUG === "1";
|
|
46504
|
-
function formatToolName(toolCall) {
|
|
46505
|
-
const { name, input } = toolCall;
|
|
46506
|
-
switch (name) {
|
|
46507
|
-
case "bash":
|
|
46508
|
-
return `bash`;
|
|
46509
|
-
case "read":
|
|
46510
|
-
const path2 = String(input.path || input.file_path || "");
|
|
46511
|
-
return `read ${path2.split("/").pop() || ""}`;
|
|
46512
|
-
case "write":
|
|
46513
|
-
const writePath = String(input.filename || input.path || input.file_path || "");
|
|
46514
|
-
return `write ${writePath.split("/").pop() || ""}`;
|
|
46515
|
-
case "glob":
|
|
46516
|
-
return `glob`;
|
|
46517
|
-
case "grep":
|
|
46518
|
-
return `grep`;
|
|
46519
|
-
case "web_search":
|
|
46520
|
-
return `search`;
|
|
46521
|
-
case "web_fetch":
|
|
46522
|
-
case "curl":
|
|
46523
|
-
return `fetch`;
|
|
46524
|
-
default:
|
|
46525
|
-
return name;
|
|
46526
|
-
}
|
|
46527
|
-
}
|
|
46528
47601
|
function parseErrorMessage(error) {
|
|
46529
47602
|
const lines = error.split(`
|
|
46530
47603
|
`);
|
|
@@ -46544,9 +47617,75 @@ function parseErrorMessage(error) {
|
|
|
46544
47617
|
}
|
|
46545
47618
|
return { code, message, suggestion };
|
|
46546
47619
|
}
|
|
47620
|
+
function formatElapsedDuration(ms) {
|
|
47621
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
|
|
47622
|
+
if (totalSeconds < 60)
|
|
47623
|
+
return `${totalSeconds}s`;
|
|
47624
|
+
const mins = Math.floor(totalSeconds / 60);
|
|
47625
|
+
const secs = totalSeconds % 60;
|
|
47626
|
+
return `${mins}m ${secs}s`;
|
|
47627
|
+
}
|
|
46547
47628
|
var MESSAGE_CHUNK_LINES = 12;
|
|
46548
47629
|
var MESSAGE_WRAP_CHARS = 120;
|
|
46549
|
-
function
|
|
47630
|
+
function wrapTextLines(text, wrapChars) {
|
|
47631
|
+
const rawLines = text.split(`
|
|
47632
|
+
`);
|
|
47633
|
+
const lines = [];
|
|
47634
|
+
for (const line of rawLines) {
|
|
47635
|
+
if (line.length <= wrapChars) {
|
|
47636
|
+
lines.push(line);
|
|
47637
|
+
continue;
|
|
47638
|
+
}
|
|
47639
|
+
for (let i = 0;i < line.length; i += wrapChars) {
|
|
47640
|
+
lines.push(line.slice(i, i + wrapChars));
|
|
47641
|
+
}
|
|
47642
|
+
}
|
|
47643
|
+
return lines;
|
|
47644
|
+
}
|
|
47645
|
+
function stripAnsi3(text) {
|
|
47646
|
+
return text.replace(/\x1B\[[0-9;]*m/g, "");
|
|
47647
|
+
}
|
|
47648
|
+
function chunkRenderedLines(lines, chunkLines) {
|
|
47649
|
+
const chunks = [];
|
|
47650
|
+
let current = [];
|
|
47651
|
+
let i = 0;
|
|
47652
|
+
const isBoxStart = (line) => stripAnsi3(line).trimStart().startsWith("\u250C");
|
|
47653
|
+
const isBoxEnd = (line) => stripAnsi3(line).trimStart().startsWith("\u2514");
|
|
47654
|
+
while (i < lines.length) {
|
|
47655
|
+
const line = lines[i];
|
|
47656
|
+
if (isBoxStart(line)) {
|
|
47657
|
+
let end = i + 1;
|
|
47658
|
+
while (end < lines.length && !isBoxEnd(lines[end])) {
|
|
47659
|
+
end += 1;
|
|
47660
|
+
}
|
|
47661
|
+
if (end < lines.length)
|
|
47662
|
+
end += 1;
|
|
47663
|
+
const boxLines = lines.slice(i, end);
|
|
47664
|
+
if (current.length > 0 && current.length + boxLines.length > chunkLines) {
|
|
47665
|
+
chunks.push(current);
|
|
47666
|
+
current = [];
|
|
47667
|
+
}
|
|
47668
|
+
if (boxLines.length >= chunkLines) {
|
|
47669
|
+
chunks.push(boxLines);
|
|
47670
|
+
} else {
|
|
47671
|
+
current.push(...boxLines);
|
|
47672
|
+
}
|
|
47673
|
+
i = end;
|
|
47674
|
+
continue;
|
|
47675
|
+
}
|
|
47676
|
+
if (current.length >= chunkLines) {
|
|
47677
|
+
chunks.push(current);
|
|
47678
|
+
current = [];
|
|
47679
|
+
}
|
|
47680
|
+
current.push(line);
|
|
47681
|
+
i += 1;
|
|
47682
|
+
}
|
|
47683
|
+
if (current.length > 0) {
|
|
47684
|
+
chunks.push(current);
|
|
47685
|
+
}
|
|
47686
|
+
return chunks;
|
|
47687
|
+
}
|
|
47688
|
+
function buildDisplayMessages(messages, chunkLines, wrapChars, options) {
|
|
46550
47689
|
const display = [];
|
|
46551
47690
|
for (const msg of messages) {
|
|
46552
47691
|
const content = msg.content ?? "";
|
|
@@ -46555,32 +47694,34 @@ function buildDisplayMessages(messages, chunkLines, wrapChars) {
|
|
|
46555
47694
|
display.push(msg);
|
|
46556
47695
|
continue;
|
|
46557
47696
|
}
|
|
46558
|
-
const
|
|
46559
|
-
`);
|
|
46560
|
-
const lines = [];
|
|
46561
|
-
for (const line of rawLines) {
|
|
46562
|
-
if (line.length <= wrapChars) {
|
|
46563
|
-
lines.push(line);
|
|
46564
|
-
continue;
|
|
46565
|
-
}
|
|
46566
|
-
for (let i = 0;i < line.length; i += wrapChars) {
|
|
46567
|
-
lines.push(line.slice(i, i + wrapChars));
|
|
46568
|
-
}
|
|
46569
|
-
}
|
|
47697
|
+
const lines = wrapTextLines(content, wrapChars);
|
|
46570
47698
|
if (lines.length <= chunkLines) {
|
|
46571
|
-
|
|
47699
|
+
if (msg.role === "assistant") {
|
|
47700
|
+
const rendered2 = renderMarkdown(lines.join(`
|
|
47701
|
+
`), { maxWidth: options?.maxWidth });
|
|
47702
|
+
display.push({ ...msg, content: rendered2, __rendered: true });
|
|
47703
|
+
} else {
|
|
47704
|
+
display.push(msg);
|
|
47705
|
+
}
|
|
46572
47706
|
continue;
|
|
46573
47707
|
}
|
|
46574
|
-
const
|
|
46575
|
-
|
|
46576
|
-
|
|
47708
|
+
const baseContent = lines.join(`
|
|
47709
|
+
`);
|
|
47710
|
+
const renderAssistant = msg.role === "assistant";
|
|
47711
|
+
const rendered = renderAssistant ? renderMarkdown(baseContent, { maxWidth: options?.maxWidth }) : baseContent;
|
|
47712
|
+
const renderedLines = rendered.split(`
|
|
47713
|
+
`);
|
|
47714
|
+
const chunks = chunkRenderedLines(renderedLines, chunkLines);
|
|
47715
|
+
for (let i = 0;i < chunks.length; i++) {
|
|
47716
|
+
const chunkContent = chunks[i].join(`
|
|
46577
47717
|
`);
|
|
46578
47718
|
display.push({
|
|
46579
47719
|
...msg,
|
|
46580
47720
|
id: `${msg.id}::chunk-${i}`,
|
|
46581
47721
|
content: chunkContent,
|
|
46582
|
-
|
|
46583
|
-
|
|
47722
|
+
__rendered: renderAssistant,
|
|
47723
|
+
toolCalls: i === chunks.length - 1 ? msg.toolCalls : undefined,
|
|
47724
|
+
toolResults: i === chunks.length - 1 ? msg.toolResults : undefined
|
|
46584
47725
|
});
|
|
46585
47726
|
}
|
|
46586
47727
|
}
|
|
@@ -46601,6 +47742,7 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46601
47742
|
const [isProcessing, setIsProcessing] = import_react29.useState(false);
|
|
46602
47743
|
const [error, setError] = import_react29.useState(null);
|
|
46603
47744
|
const [messageQueue, setMessageQueue] = import_react29.useState([]);
|
|
47745
|
+
const [inlinePending, setInlinePending] = import_react29.useState([]);
|
|
46604
47746
|
const [activityLog, setActivityLog] = import_react29.useState([]);
|
|
46605
47747
|
const [tokenUsage, setTokenUsage] = import_react29.useState();
|
|
46606
47748
|
const [energyState, setEnergyState] = import_react29.useState();
|
|
@@ -46615,7 +47757,7 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46615
47757
|
const toolCallsRef = import_react29.useRef([]);
|
|
46616
47758
|
const toolResultsRef = import_react29.useRef([]);
|
|
46617
47759
|
const activityLogRef = import_react29.useRef([]);
|
|
46618
|
-
const
|
|
47760
|
+
const prevDisplayLineCountRef = import_react29.useRef(0);
|
|
46619
47761
|
const skipNextDoneRef = import_react29.useRef(false);
|
|
46620
47762
|
const isProcessingRef = import_react29.useRef(isProcessing);
|
|
46621
47763
|
import_react29.useEffect(() => {
|
|
@@ -46672,6 +47814,12 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46672
47814
|
content = content ? `${content}
|
|
46673
47815
|
|
|
46674
47816
|
[error]` : "[error]";
|
|
47817
|
+
}
|
|
47818
|
+
if (processingStartTime) {
|
|
47819
|
+
const workedFor = formatElapsedDuration(Date.now() - processingStartTime);
|
|
47820
|
+
content = content ? `${content}
|
|
47821
|
+
|
|
47822
|
+
\u273B Worked for ${workedFor}` : `\u273B Worked for ${workedFor}`;
|
|
46675
47823
|
}
|
|
46676
47824
|
setMessages((prev) => [
|
|
46677
47825
|
...prev,
|
|
@@ -46685,7 +47833,7 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46685
47833
|
}
|
|
46686
47834
|
]);
|
|
46687
47835
|
return true;
|
|
46688
|
-
}, [buildFullResponse]);
|
|
47836
|
+
}, [buildFullResponse, processingStartTime]);
|
|
46689
47837
|
const resetTurnState = import_react29.useCallback(() => {
|
|
46690
47838
|
setCurrentResponse("");
|
|
46691
47839
|
responseRef.current = "";
|
|
@@ -46754,6 +47902,21 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46754
47902
|
setAutoScroll(true);
|
|
46755
47903
|
}, []);
|
|
46756
47904
|
const handleChunk = import_react29.useCallback((chunk) => {
|
|
47905
|
+
if (!isProcessingRef.current && (chunk.type === "text" || chunk.type === "tool_use" || chunk.type === "tool_result")) {
|
|
47906
|
+
const active = registryRef.current.getActiveSession();
|
|
47907
|
+
if (active) {
|
|
47908
|
+
registryRef.current.setProcessing(active.id, true);
|
|
47909
|
+
setIsProcessing(true);
|
|
47910
|
+
isProcessingRef.current = true;
|
|
47911
|
+
setProcessingStartTime(Date.now());
|
|
47912
|
+
setInlinePending((prev) => {
|
|
47913
|
+
const idx = prev.findIndex((msg) => msg.sessionId === active.id);
|
|
47914
|
+
if (idx === -1)
|
|
47915
|
+
return prev;
|
|
47916
|
+
return [...prev.slice(0, idx), ...prev.slice(idx + 1)];
|
|
47917
|
+
});
|
|
47918
|
+
}
|
|
47919
|
+
}
|
|
46757
47920
|
if (chunk.type === "text" && chunk.content) {
|
|
46758
47921
|
responseRef.current += chunk.content;
|
|
46759
47922
|
setCurrentResponse(responseRef.current);
|
|
@@ -46937,9 +48100,11 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46937
48100
|
await activeSession2.client.send(nextMessage.content);
|
|
46938
48101
|
}, [activeSessionId]);
|
|
46939
48102
|
const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
|
|
46940
|
-
const
|
|
48103
|
+
const activeInline = activeSessionId ? inlinePending.filter((msg) => msg.sessionId === activeSessionId) : [];
|
|
48104
|
+
const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.filter((msg) => msg.mode === "queued").map((msg) => msg.id)), [activeQueue]);
|
|
46941
48105
|
const wrapChars = columns ? Math.max(40, columns - 4) : MESSAGE_WRAP_CHARS;
|
|
46942
|
-
const
|
|
48106
|
+
const renderWidth = columns ? Math.max(20, columns - 2) : undefined;
|
|
48107
|
+
const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth }), [messages, wrapChars, renderWidth]);
|
|
46943
48108
|
const streamingMessages = import_react29.useMemo(() => {
|
|
46944
48109
|
if (!isProcessing || !currentResponse.trim())
|
|
46945
48110
|
return [];
|
|
@@ -46949,9 +48114,12 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46949
48114
|
content: currentResponse,
|
|
46950
48115
|
timestamp: now()
|
|
46951
48116
|
};
|
|
46952
|
-
return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars);
|
|
46953
|
-
}, [currentResponse, isProcessing, wrapChars]);
|
|
46954
|
-
const
|
|
48117
|
+
return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth });
|
|
48118
|
+
}, [currentResponse, isProcessing, wrapChars, renderWidth]);
|
|
48119
|
+
const displayLineCount = import_react29.useMemo(() => {
|
|
48120
|
+
const combined = [...displayMessages, ...streamingMessages];
|
|
48121
|
+
return combined.reduce((sum, msg) => sum + estimateMessageLines(msg), 0);
|
|
48122
|
+
}, [displayMessages, streamingMessages]);
|
|
46955
48123
|
import_react29.useEffect(() => {
|
|
46956
48124
|
if (!isProcessing && activeQueue.length > 0) {
|
|
46957
48125
|
processQueue();
|
|
@@ -46961,23 +48129,21 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46961
48129
|
if (autoScroll) {
|
|
46962
48130
|
setScrollOffset(0);
|
|
46963
48131
|
}
|
|
46964
|
-
}, [
|
|
48132
|
+
}, [displayLineCount, autoScroll]);
|
|
46965
48133
|
import_react29.useEffect(() => {
|
|
46966
|
-
const prevCount =
|
|
46967
|
-
if (!autoScroll &&
|
|
46968
|
-
const delta =
|
|
48134
|
+
const prevCount = prevDisplayLineCountRef.current;
|
|
48135
|
+
if (!autoScroll && displayLineCount > prevCount) {
|
|
48136
|
+
const delta = displayLineCount - prevCount;
|
|
46969
48137
|
setScrollOffset((prev) => prev + delta);
|
|
46970
48138
|
}
|
|
46971
|
-
|
|
46972
|
-
}, [
|
|
48139
|
+
prevDisplayLineCountRef.current = displayLineCount;
|
|
48140
|
+
}, [displayLineCount, autoScroll]);
|
|
46973
48141
|
const reservedLines = 8;
|
|
46974
|
-
const
|
|
46975
|
-
const toolCallsHeight = isProcessing ? Math.min(toolCallsRef.current.length, 5) : 0;
|
|
46976
|
-
const maxVisibleMessages = Math.max(3, baseMaxVisible - toolCallsHeight);
|
|
48142
|
+
const maxVisibleLines = rows ? Math.max(6, rows - reservedLines) : 20;
|
|
46977
48143
|
import_react29.useEffect(() => {
|
|
46978
|
-
const maxOffset = Math.max(0,
|
|
48144
|
+
const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
|
|
46979
48145
|
setScrollOffset((prev) => Math.min(prev, maxOffset));
|
|
46980
|
-
}, [
|
|
48146
|
+
}, [displayLineCount, maxVisibleLines]);
|
|
46981
48147
|
const sessions = registry2.listSessions();
|
|
46982
48148
|
const activeSession = registry2.getActiveSession();
|
|
46983
48149
|
const sessionIndex = activeSessionId ? registry2.getSessionIndex(activeSessionId) : 0;
|
|
@@ -47056,8 +48222,9 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47056
48222
|
}
|
|
47057
48223
|
if (key.pageUp || key.shift && key.upArrow) {
|
|
47058
48224
|
setScrollOffset((prev) => {
|
|
47059
|
-
const maxOffset = Math.max(0,
|
|
47060
|
-
const
|
|
48225
|
+
const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
|
|
48226
|
+
const step = Math.max(3, Math.floor(maxVisibleLines / 2));
|
|
48227
|
+
const newOffset = Math.min(prev + step, maxOffset);
|
|
47061
48228
|
if (newOffset > 0)
|
|
47062
48229
|
setAutoScroll(false);
|
|
47063
48230
|
return newOffset;
|
|
@@ -47065,14 +48232,15 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47065
48232
|
}
|
|
47066
48233
|
if (key.pageDown || key.shift && key.downArrow) {
|
|
47067
48234
|
setScrollOffset((prev) => {
|
|
47068
|
-
const
|
|
48235
|
+
const step = Math.max(3, Math.floor(maxVisibleLines / 2));
|
|
48236
|
+
const newOffset = Math.max(0, prev - step);
|
|
47069
48237
|
if (newOffset === 0)
|
|
47070
48238
|
setAutoScroll(true);
|
|
47071
48239
|
return newOffset;
|
|
47072
48240
|
});
|
|
47073
48241
|
}
|
|
47074
48242
|
if (key.ctrl && input === "u") {
|
|
47075
|
-
const maxOffset = Math.max(0,
|
|
48243
|
+
const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
|
|
47076
48244
|
setScrollOffset(maxOffset);
|
|
47077
48245
|
setAutoScroll(false);
|
|
47078
48246
|
}
|
|
@@ -47109,7 +48277,13 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47109
48277
|
const queuedId = generateId();
|
|
47110
48278
|
setMessageQueue((prev) => [
|
|
47111
48279
|
...prev,
|
|
47112
|
-
{
|
|
48280
|
+
{
|
|
48281
|
+
id: queuedId,
|
|
48282
|
+
sessionId: activeSessionId,
|
|
48283
|
+
content: trimmedInput,
|
|
48284
|
+
queuedAt: now(),
|
|
48285
|
+
mode: "queued"
|
|
48286
|
+
}
|
|
47113
48287
|
]);
|
|
47114
48288
|
setMessages((prev) => [
|
|
47115
48289
|
...prev,
|
|
@@ -47122,6 +48296,32 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47122
48296
|
]);
|
|
47123
48297
|
return;
|
|
47124
48298
|
}
|
|
48299
|
+
if (mode === "inline") {
|
|
48300
|
+
if (!activeSessionId)
|
|
48301
|
+
return;
|
|
48302
|
+
const inlineId = generateId();
|
|
48303
|
+
setInlinePending((prev) => [
|
|
48304
|
+
...prev,
|
|
48305
|
+
{
|
|
48306
|
+
id: inlineId,
|
|
48307
|
+
sessionId: activeSessionId,
|
|
48308
|
+
content: trimmedInput,
|
|
48309
|
+
queuedAt: now(),
|
|
48310
|
+
mode: "inline"
|
|
48311
|
+
}
|
|
48312
|
+
]);
|
|
48313
|
+
setMessages((prev) => [
|
|
48314
|
+
...prev,
|
|
48315
|
+
{
|
|
48316
|
+
id: inlineId,
|
|
48317
|
+
role: "user",
|
|
48318
|
+
content: trimmedInput,
|
|
48319
|
+
timestamp: now()
|
|
48320
|
+
}
|
|
48321
|
+
]);
|
|
48322
|
+
await activeSession.client.send(trimmedInput);
|
|
48323
|
+
return;
|
|
48324
|
+
}
|
|
47125
48325
|
if (mode === "interrupt" && isProcessing) {
|
|
47126
48326
|
activeSession.client.stop();
|
|
47127
48327
|
const finalized = finalizeResponse("interrupted");
|
|
@@ -47173,19 +48373,19 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47173
48373
|
activeSessionId
|
|
47174
48374
|
]);
|
|
47175
48375
|
if (isInitializing) {
|
|
47176
|
-
return /* @__PURE__ */
|
|
48376
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47177
48377
|
flexDirection: "column",
|
|
47178
48378
|
padding: 1,
|
|
47179
|
-
children: /* @__PURE__ */
|
|
48379
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Spinner2, {
|
|
47180
48380
|
label: "Initializing..."
|
|
47181
48381
|
}, undefined, false, undefined, this)
|
|
47182
48382
|
}, undefined, false, undefined, this);
|
|
47183
48383
|
}
|
|
47184
48384
|
if (showSessionSelector) {
|
|
47185
|
-
return /* @__PURE__ */
|
|
48385
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47186
48386
|
flexDirection: "column",
|
|
47187
48387
|
padding: 1,
|
|
47188
|
-
children: /* @__PURE__ */
|
|
48388
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SessionSelector, {
|
|
47189
48389
|
sessions,
|
|
47190
48390
|
activeSessionId,
|
|
47191
48391
|
onSelect: handleSessionSwitch,
|
|
@@ -47205,19 +48405,21 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47205
48405
|
return text;
|
|
47206
48406
|
return text.slice(0, maxLen - 3) + "...";
|
|
47207
48407
|
};
|
|
48408
|
+
const queuedCount = activeQueue.filter((msg) => msg.mode === "queued").length;
|
|
48409
|
+
const inlineCount = activeInline.length;
|
|
47208
48410
|
const showWelcome = messages.length === 0 && !isProcessing;
|
|
47209
|
-
return /* @__PURE__ */
|
|
48411
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47210
48412
|
flexDirection: "column",
|
|
47211
48413
|
padding: 1,
|
|
47212
48414
|
children: [
|
|
47213
|
-
showWelcome && /* @__PURE__ */
|
|
47214
|
-
version: version ?? "
|
|
48415
|
+
showWelcome && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(WelcomeBanner, {
|
|
48416
|
+
version: version ?? "unknown",
|
|
47215
48417
|
model: "claude-sonnet-4",
|
|
47216
48418
|
directory: activeSession?.cwd || cwd2
|
|
47217
48419
|
}, undefined, false, undefined, this),
|
|
47218
|
-
backgroundProcessingCount > 0 && /* @__PURE__ */
|
|
48420
|
+
backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47219
48421
|
marginBottom: 1,
|
|
47220
|
-
children: /* @__PURE__ */
|
|
48422
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47221
48423
|
color: "yellow",
|
|
47222
48424
|
children: [
|
|
47223
48425
|
backgroundProcessingCount,
|
|
@@ -47227,17 +48429,17 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47227
48429
|
]
|
|
47228
48430
|
}, undefined, true, undefined, this)
|
|
47229
48431
|
}, undefined, false, undefined, this),
|
|
47230
|
-
scrollOffset > 0 && /* @__PURE__ */
|
|
47231
|
-
children: /* @__PURE__ */
|
|
48432
|
+
scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
48433
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47232
48434
|
dimColor: true,
|
|
47233
48435
|
children: [
|
|
47234
48436
|
"\u2191 ",
|
|
47235
48437
|
scrollOffset,
|
|
47236
|
-
" more
|
|
48438
|
+
" more lines above (Shift+\u2193 or Page Down to scroll down)"
|
|
47237
48439
|
]
|
|
47238
48440
|
}, undefined, true, undefined, this)
|
|
47239
48441
|
}, undefined, false, undefined, this),
|
|
47240
|
-
/* @__PURE__ */
|
|
48442
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Messages4, {
|
|
47241
48443
|
messages: displayMessages,
|
|
47242
48444
|
currentResponse: undefined,
|
|
47243
48445
|
streamingMessages,
|
|
@@ -47245,65 +48447,38 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47245
48447
|
lastToolResult: undefined,
|
|
47246
48448
|
activityLog: isProcessing ? activityLog : [],
|
|
47247
48449
|
queuedMessageIds,
|
|
47248
|
-
scrollOffset,
|
|
47249
|
-
|
|
48450
|
+
scrollOffsetLines: scrollOffset,
|
|
48451
|
+
maxVisibleLines
|
|
47250
48452
|
}, activeSessionId || "default", false, undefined, this),
|
|
47251
|
-
|
|
47252
|
-
marginY: 1,
|
|
47253
|
-
flexDirection: "column",
|
|
47254
|
-
children: [
|
|
47255
|
-
toolCallEntries.slice(-3).map(({ toolCall, result }) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
47256
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
47257
|
-
dimColor: true,
|
|
47258
|
-
children: [
|
|
47259
|
-
result ? "\u2713" : "\u2699",
|
|
47260
|
-
" ",
|
|
47261
|
-
formatToolName(toolCall),
|
|
47262
|
-
result?.isError && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
47263
|
-
color: "red",
|
|
47264
|
-
children: " (error)"
|
|
47265
|
-
}, undefined, false, undefined, this)
|
|
47266
|
-
]
|
|
47267
|
-
}, undefined, true, undefined, this)
|
|
47268
|
-
}, toolCall.id, false, undefined, this)),
|
|
47269
|
-
toolCallEntries.length > 3 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
47270
|
-
dimColor: true,
|
|
47271
|
-
children: [
|
|
47272
|
-
" ... and ",
|
|
47273
|
-
toolCallEntries.length - 3,
|
|
47274
|
-
" more tools"
|
|
47275
|
-
]
|
|
47276
|
-
}, undefined, true, undefined, this)
|
|
47277
|
-
]
|
|
47278
|
-
}, undefined, true, undefined, this),
|
|
47279
|
-
activeQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
48453
|
+
(activeQueue.length > 0 || inlineCount > 0) && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47280
48454
|
marginY: 1,
|
|
47281
48455
|
flexDirection: "column",
|
|
47282
48456
|
children: [
|
|
47283
|
-
/* @__PURE__ */
|
|
48457
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47284
48458
|
dimColor: true,
|
|
47285
48459
|
children: [
|
|
47286
|
-
activeQueue.length,
|
|
47287
|
-
" message",
|
|
47288
|
-
activeQueue.length > 1 ? "s" : "",
|
|
47289
|
-
|
|
48460
|
+
activeQueue.length + inlineCount,
|
|
48461
|
+
" pending message",
|
|
48462
|
+
activeQueue.length + inlineCount > 1 ? "s" : "",
|
|
48463
|
+
inlineCount > 0 || queuedCount > 0 ? ` \xB7 ${inlineCount} in-stream \xB7 ${queuedCount} queued` : ""
|
|
47290
48464
|
]
|
|
47291
48465
|
}, undefined, true, undefined, this),
|
|
47292
|
-
activeQueue.slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */
|
|
48466
|
+
[...activeInline, ...activeQueue].slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47293
48467
|
marginLeft: 2,
|
|
47294
|
-
children: /* @__PURE__ */
|
|
48468
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47295
48469
|
dimColor: true,
|
|
47296
48470
|
children: [
|
|
47297
|
-
"\
|
|
48471
|
+
queued.mode === "inline" ? "\u21B3" : "\u23F3",
|
|
48472
|
+
" ",
|
|
47298
48473
|
truncateQueued(queued.content)
|
|
47299
48474
|
]
|
|
47300
48475
|
}, undefined, true, undefined, this)
|
|
47301
48476
|
}, queued.id, false, undefined, this)),
|
|
47302
|
-
activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */
|
|
48477
|
+
activeQueue.length + inlineCount > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47303
48478
|
dimColor: true,
|
|
47304
48479
|
children: [
|
|
47305
48480
|
" ... and ",
|
|
47306
|
-
activeQueue.length - MAX_QUEUED_PREVIEW,
|
|
48481
|
+
activeQueue.length + inlineCount - MAX_QUEUED_PREVIEW,
|
|
47307
48482
|
" more"
|
|
47308
48483
|
]
|
|
47309
48484
|
}, undefined, true, undefined, this)
|
|
@@ -47313,18 +48488,18 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47313
48488
|
const parsed = parseErrorMessage(error);
|
|
47314
48489
|
const severity = parsed.code && /TIMEOUT|RATE_LIMITED/.test(parsed.code) ? "yellow" : "red";
|
|
47315
48490
|
const prefix = SHOW_ERROR_CODES && parsed.code ? `${parsed.code}: ` : "";
|
|
47316
|
-
return /* @__PURE__ */
|
|
48491
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47317
48492
|
marginY: 1,
|
|
47318
48493
|
flexDirection: "column",
|
|
47319
48494
|
children: [
|
|
47320
|
-
/* @__PURE__ */
|
|
48495
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47321
48496
|
color: severity,
|
|
47322
48497
|
children: [
|
|
47323
48498
|
prefix,
|
|
47324
48499
|
parsed.message
|
|
47325
48500
|
]
|
|
47326
48501
|
}, undefined, true, undefined, this),
|
|
47327
|
-
parsed.suggestion && /* @__PURE__ */
|
|
48502
|
+
parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47328
48503
|
color: severity,
|
|
47329
48504
|
children: [
|
|
47330
48505
|
"Suggestion: ",
|
|
@@ -47334,22 +48509,22 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47334
48509
|
]
|
|
47335
48510
|
}, undefined, true, undefined, this);
|
|
47336
48511
|
})(),
|
|
47337
|
-
/* @__PURE__ */
|
|
48512
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ProcessingIndicator, {
|
|
47338
48513
|
isProcessing,
|
|
47339
48514
|
startTime: processingStartTime,
|
|
47340
48515
|
tokenCount: currentTurnTokens,
|
|
47341
48516
|
isThinking
|
|
47342
48517
|
}, undefined, false, undefined, this),
|
|
47343
|
-
/* @__PURE__ */
|
|
48518
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Input, {
|
|
47344
48519
|
onSubmit: handleSubmit,
|
|
47345
48520
|
isProcessing,
|
|
47346
|
-
queueLength: activeQueue.length,
|
|
48521
|
+
queueLength: activeQueue.length + inlineCount,
|
|
47347
48522
|
skills
|
|
47348
48523
|
}, undefined, false, undefined, this),
|
|
47349
|
-
/* @__PURE__ */
|
|
48524
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Status, {
|
|
47350
48525
|
isProcessing,
|
|
47351
48526
|
cwd: activeSession?.cwd || cwd2,
|
|
47352
|
-
queueLength: activeQueue.length,
|
|
48527
|
+
queueLength: activeQueue.length + inlineCount,
|
|
47353
48528
|
tokenUsage,
|
|
47354
48529
|
energyState,
|
|
47355
48530
|
voiceState,
|
|
@@ -47538,8 +48713,9 @@ function formatStreamEvent(chunk) {
|
|
|
47538
48713
|
}
|
|
47539
48714
|
|
|
47540
48715
|
// packages/terminal/src/index.tsx
|
|
47541
|
-
var
|
|
47542
|
-
var VERSION3 = "0.6.
|
|
48716
|
+
var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
|
|
48717
|
+
var VERSION3 = "0.6.21";
|
|
48718
|
+
process.env.ASSISTANTS_VERSION ??= VERSION3;
|
|
47543
48719
|
function parseArgs(argv) {
|
|
47544
48720
|
const args = argv.slice(2);
|
|
47545
48721
|
const options = {
|
|
@@ -47665,14 +48841,7 @@ Interactive Mode:
|
|
|
47665
48841
|
`);
|
|
47666
48842
|
process.exit(0);
|
|
47667
48843
|
}
|
|
47668
|
-
|
|
47669
|
-
const result = await migrateFromOldpal();
|
|
47670
|
-
if (!result.success && result.errors.length > 0) {
|
|
47671
|
-
console.error(`Migration warning: ${result.errors.join("; ")}`);
|
|
47672
|
-
}
|
|
47673
|
-
} catch (error) {
|
|
47674
|
-
console.error(`Migration warning: ${error instanceof Error ? error.message : String(error)}`);
|
|
47675
|
-
}
|
|
48844
|
+
migrateFromOldpal().catch(() => {});
|
|
47676
48845
|
if (options.print !== null) {
|
|
47677
48846
|
if (!options.print.trim()) {
|
|
47678
48847
|
console.error("Error: Prompt is required with -p/--print flag");
|
|
@@ -47693,7 +48862,7 @@ if (options.print !== null) {
|
|
|
47693
48862
|
process.exit(1);
|
|
47694
48863
|
});
|
|
47695
48864
|
} else {
|
|
47696
|
-
const { waitUntilExit } = render_default(/* @__PURE__ */
|
|
48865
|
+
const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(App2, {
|
|
47697
48866
|
cwd: options.cwd,
|
|
47698
48867
|
version: VERSION3
|
|
47699
48868
|
}, undefined, false, undefined, this));
|
|
@@ -47702,4 +48871,4 @@ if (options.print !== null) {
|
|
|
47702
48871
|
});
|
|
47703
48872
|
}
|
|
47704
48873
|
|
|
47705
|
-
//# debugId=
|
|
48874
|
+
//# debugId=9F87F41E551C4D1964756E2164756E21
|