@hasna/assistants 0.6.19 → 0.6.20
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 +1569 -536
- 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 };
|
|
@@ -27292,11 +27292,11 @@ __export(exports_anthropic, {
|
|
|
27292
27292
|
});
|
|
27293
27293
|
import { readFileSync as readFileSync2, existsSync as existsSync7 } 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 =
|
|
27299
|
+
const secretsPath = join12(homeDir, ".secrets");
|
|
27300
27300
|
if (existsSync7(secretsPath)) {
|
|
27301
27301
|
try {
|
|
27302
27302
|
const content = readFileSync2(secretsPath, "utf-8");
|
|
@@ -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
|
}
|
|
@@ -36637,6 +36644,10 @@ function resolveTimeout(resolve) {
|
|
|
36637
36644
|
class ConnectorBridge {
|
|
36638
36645
|
connectors = new Map;
|
|
36639
36646
|
static cache = new Map;
|
|
36647
|
+
cwd;
|
|
36648
|
+
constructor(cwd2) {
|
|
36649
|
+
this.cwd = cwd2;
|
|
36650
|
+
}
|
|
36640
36651
|
getHomeDir() {
|
|
36641
36652
|
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
36642
36653
|
return envHome && envHome.trim().length > 0 ? envHome : homedir2();
|
|
@@ -36644,8 +36655,10 @@ class ConnectorBridge {
|
|
|
36644
36655
|
autoDiscoverConnectorNames() {
|
|
36645
36656
|
const connectorNames = new Set;
|
|
36646
36657
|
const pathDirs = (process.env.PATH || "").split(delimiter);
|
|
36658
|
+
const baseCwd = this.cwd || process.cwd();
|
|
36647
36659
|
const homeDir = this.getHomeDir();
|
|
36648
36660
|
const extraDirs = [
|
|
36661
|
+
join3(baseCwd, "node_modules", ".bin"),
|
|
36649
36662
|
join3(homeDir, ".bun", "bin"),
|
|
36650
36663
|
join3(homeDir, ".npm-global", "bin"),
|
|
36651
36664
|
"/usr/local/bin"
|
|
@@ -36888,17 +36901,20 @@ class ConnectorBridge {
|
|
|
36888
36901
|
}
|
|
36889
36902
|
const lowerCommand = command.toLowerCase();
|
|
36890
36903
|
const lowerArgs = args.map((arg) => arg.toLowerCase());
|
|
36891
|
-
const
|
|
36892
|
-
|
|
36904
|
+
const combined = [lowerCommand, ...lowerArgs].join(" ");
|
|
36905
|
+
const isAuthLogin = /\bauth\b/.test(combined) && /(login|authorize|authorization|oauth|signin|sign-in|connect)/.test(combined);
|
|
36906
|
+
const runInBackground = options.background === true;
|
|
36907
|
+
if (isAuthLogin || runInBackground) {
|
|
36893
36908
|
try {
|
|
36894
|
-
Bun.spawn(cmdParts, {
|
|
36909
|
+
const proc = Bun.spawn(cmdParts, {
|
|
36895
36910
|
cwd: cwd2,
|
|
36896
36911
|
stdin: "ignore",
|
|
36897
36912
|
stdout: "ignore",
|
|
36898
36913
|
stderr: "pipe"
|
|
36899
36914
|
});
|
|
36915
|
+
proc.unref?.();
|
|
36900
36916
|
} catch {}
|
|
36901
|
-
return "Auth login started in the background. Complete it in your browser, then run auth status to confirm.";
|
|
36917
|
+
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
36918
|
}
|
|
36903
36919
|
try {
|
|
36904
36920
|
const proc = Bun.spawn(cmdParts, {
|
|
@@ -37036,6 +37052,38 @@ function stripQuotedSegments(input) {
|
|
|
37036
37052
|
}
|
|
37037
37053
|
return result;
|
|
37038
37054
|
}
|
|
37055
|
+
function normalizeNewlinesOutsideQuotes(input) {
|
|
37056
|
+
let result = "";
|
|
37057
|
+
let quote = null;
|
|
37058
|
+
let escaped = false;
|
|
37059
|
+
for (let i = 0;i < input.length; i += 1) {
|
|
37060
|
+
const char = input[i];
|
|
37061
|
+
if (quote) {
|
|
37062
|
+
result += char;
|
|
37063
|
+
if (quote === '"' && !escaped && char === "\\") {
|
|
37064
|
+
escaped = true;
|
|
37065
|
+
continue;
|
|
37066
|
+
}
|
|
37067
|
+
if (!escaped && char === quote) {
|
|
37068
|
+
quote = null;
|
|
37069
|
+
}
|
|
37070
|
+
escaped = false;
|
|
37071
|
+
continue;
|
|
37072
|
+
}
|
|
37073
|
+
if (char === '"' || char === "'") {
|
|
37074
|
+
quote = char;
|
|
37075
|
+
result += char;
|
|
37076
|
+
continue;
|
|
37077
|
+
}
|
|
37078
|
+
if (char === "\r" || char === `
|
|
37079
|
+
`) {
|
|
37080
|
+
result += " ";
|
|
37081
|
+
continue;
|
|
37082
|
+
}
|
|
37083
|
+
result += char;
|
|
37084
|
+
}
|
|
37085
|
+
return result;
|
|
37086
|
+
}
|
|
37039
37087
|
|
|
37040
37088
|
class BashTool {
|
|
37041
37089
|
static tool = {
|
|
@@ -37155,7 +37203,11 @@ class BashTool {
|
|
|
37155
37203
|
const command = input.command;
|
|
37156
37204
|
const cwd2 = input.cwd || process.cwd();
|
|
37157
37205
|
const timeout = input.timeout || 30000;
|
|
37158
|
-
const
|
|
37206
|
+
const baseCommand = command.replace(/\s*2>&1\s*/g, " ").trim();
|
|
37207
|
+
const baseTrimmed = baseCommand.toLowerCase();
|
|
37208
|
+
const allowConnectorNewlines = baseTrimmed.startsWith("connect-");
|
|
37209
|
+
const commandForExec = allowConnectorNewlines ? normalizeNewlinesOutsideQuotes(baseCommand).trim() : baseCommand;
|
|
37210
|
+
const commandForChecks = commandForExec;
|
|
37159
37211
|
const commandSansQuotes = stripQuotedSegments(commandForChecks);
|
|
37160
37212
|
const securityCheck = validateBashCommand(commandForChecks);
|
|
37161
37213
|
if (!securityCheck.valid) {
|
|
@@ -37229,7 +37281,7 @@ class BashTool {
|
|
|
37229
37281
|
});
|
|
37230
37282
|
}
|
|
37231
37283
|
try {
|
|
37232
|
-
const proc = Bun.spawn(["bash", "-c",
|
|
37284
|
+
const proc = Bun.spawn(["bash", "-c", commandForExec], {
|
|
37233
37285
|
cwd: cwd2,
|
|
37234
37286
|
stdout: "pipe",
|
|
37235
37287
|
stderr: "pipe"
|
|
@@ -37356,15 +37408,16 @@ async function isPathSafe(targetPath, operation, options = {}) {
|
|
|
37356
37408
|
|
|
37357
37409
|
// packages/core/src/tools/filesystem.ts
|
|
37358
37410
|
var currentSessionId = "default";
|
|
37359
|
-
function getScriptsFolder(cwd2) {
|
|
37411
|
+
function getScriptsFolder(cwd2, sessionId) {
|
|
37412
|
+
const resolvedSessionId = sessionId || currentSessionId;
|
|
37360
37413
|
const legacyDir = join4(cwd2, ".oldpal");
|
|
37361
37414
|
if (existsSync2(legacyDir)) {
|
|
37362
|
-
return join4(legacyDir, "scripts",
|
|
37415
|
+
return join4(legacyDir, "scripts", resolvedSessionId);
|
|
37363
37416
|
}
|
|
37364
|
-
return join4(getProjectConfigDir(cwd2), "scripts",
|
|
37417
|
+
return join4(getProjectConfigDir(cwd2), "scripts", resolvedSessionId);
|
|
37365
37418
|
}
|
|
37366
|
-
function isInScriptsFolder(path2, cwd2) {
|
|
37367
|
-
const scriptsFolder = resolve3(getScriptsFolder(cwd2));
|
|
37419
|
+
function isInScriptsFolder(path2, cwd2, sessionId) {
|
|
37420
|
+
const scriptsFolder = resolve3(getScriptsFolder(cwd2, sessionId));
|
|
37368
37421
|
const resolved = resolve3(path2);
|
|
37369
37422
|
if (resolved === scriptsFolder)
|
|
37370
37423
|
return true;
|
|
@@ -37520,7 +37573,7 @@ class FilesystemTools {
|
|
|
37520
37573
|
const filename = input.filename || input.path;
|
|
37521
37574
|
const content = input.content;
|
|
37522
37575
|
const baseCwd = input.cwd || process.cwd();
|
|
37523
|
-
const scriptsFolder = getScriptsFolder(baseCwd);
|
|
37576
|
+
const scriptsFolder = getScriptsFolder(baseCwd, input.sessionId);
|
|
37524
37577
|
if (!filename || !filename.trim()) {
|
|
37525
37578
|
throw new ToolExecutionError("Filename is required", {
|
|
37526
37579
|
toolName: "write",
|
|
@@ -37533,7 +37586,7 @@ class FilesystemTools {
|
|
|
37533
37586
|
}
|
|
37534
37587
|
const sanitizedFilename = filename.replace(/\.\.[/\\]/g, "").replace(/\.\./g, "").replace(/^[/\\]+/, "");
|
|
37535
37588
|
const path2 = join4(scriptsFolder, sanitizedFilename);
|
|
37536
|
-
if (!isInScriptsFolder(path2, baseCwd)) {
|
|
37589
|
+
if (!isInScriptsFolder(path2, baseCwd, input.sessionId)) {
|
|
37537
37590
|
throw new ToolExecutionError(`Cannot write outside scripts folder. Files are saved to ${scriptsFolder}`, {
|
|
37538
37591
|
toolName: "write",
|
|
37539
37592
|
toolInput: input,
|
|
@@ -39737,13 +39790,217 @@ ${stderr}`;
|
|
|
39737
39790
|
}
|
|
39738
39791
|
}
|
|
39739
39792
|
// packages/core/src/commands/builtin.ts
|
|
39740
|
-
import { join as
|
|
39793
|
+
import { join as join11 } from "path";
|
|
39741
39794
|
import { homedir as homedir7, platform as platform2, release, arch } from "os";
|
|
39742
39795
|
import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
39743
39796
|
init_src();
|
|
39744
|
-
|
|
39745
|
-
|
|
39746
|
-
|
|
39797
|
+
|
|
39798
|
+
// packages/core/src/projects/store.ts
|
|
39799
|
+
init_src();
|
|
39800
|
+
import { join as join10 } from "path";
|
|
39801
|
+
import { mkdir as mkdir3, readdir as readdir2, readFile as readFile2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
|
|
39802
|
+
function projectsDir(cwd2) {
|
|
39803
|
+
return join10(cwd2, ".oldpal", "projects");
|
|
39804
|
+
}
|
|
39805
|
+
function projectPath(cwd2, id) {
|
|
39806
|
+
return join10(projectsDir(cwd2), `${id}.json`);
|
|
39807
|
+
}
|
|
39808
|
+
async function ensureProjectsDir(cwd2) {
|
|
39809
|
+
await mkdir3(projectsDir(cwd2), { recursive: true });
|
|
39810
|
+
}
|
|
39811
|
+
function normalizeName(name) {
|
|
39812
|
+
return name.trim().toLowerCase();
|
|
39813
|
+
}
|
|
39814
|
+
async function listProjects(cwd2) {
|
|
39815
|
+
try {
|
|
39816
|
+
const dir = projectsDir(cwd2);
|
|
39817
|
+
const files = await readdir2(dir);
|
|
39818
|
+
const projects = [];
|
|
39819
|
+
for (const file of files) {
|
|
39820
|
+
if (!file.endsWith(".json"))
|
|
39821
|
+
continue;
|
|
39822
|
+
try {
|
|
39823
|
+
const raw = await readFile2(join10(dir, file), "utf-8");
|
|
39824
|
+
const parsed = JSON.parse(raw);
|
|
39825
|
+
if (parsed?.id && parsed?.name) {
|
|
39826
|
+
projects.push(parsed);
|
|
39827
|
+
}
|
|
39828
|
+
} catch {}
|
|
39829
|
+
}
|
|
39830
|
+
return projects.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
39831
|
+
} catch {
|
|
39832
|
+
return [];
|
|
39833
|
+
}
|
|
39834
|
+
}
|
|
39835
|
+
async function readProject(cwd2, id) {
|
|
39836
|
+
try {
|
|
39837
|
+
const raw = await readFile2(projectPath(cwd2, id), "utf-8");
|
|
39838
|
+
const project = JSON.parse(raw);
|
|
39839
|
+
if (!project?.id || !project?.name)
|
|
39840
|
+
return null;
|
|
39841
|
+
return project;
|
|
39842
|
+
} catch {
|
|
39843
|
+
return null;
|
|
39844
|
+
}
|
|
39845
|
+
}
|
|
39846
|
+
async function findProjectByName(cwd2, name) {
|
|
39847
|
+
const normalized = normalizeName(name);
|
|
39848
|
+
const projects = await listProjects(cwd2);
|
|
39849
|
+
return projects.find((project) => normalizeName(project.name) === normalized) || null;
|
|
39850
|
+
}
|
|
39851
|
+
async function saveProject(cwd2, project) {
|
|
39852
|
+
await ensureProjectsDir(cwd2);
|
|
39853
|
+
await writeFile2(projectPath(cwd2, project.id), JSON.stringify(project, null, 2), "utf-8");
|
|
39854
|
+
}
|
|
39855
|
+
async function deleteProject(cwd2, id) {
|
|
39856
|
+
try {
|
|
39857
|
+
await unlink2(projectPath(cwd2, id));
|
|
39858
|
+
return true;
|
|
39859
|
+
} catch {
|
|
39860
|
+
return false;
|
|
39861
|
+
}
|
|
39862
|
+
}
|
|
39863
|
+
async function createProject(cwd2, name, description) {
|
|
39864
|
+
const now2 = Date.now();
|
|
39865
|
+
const project = {
|
|
39866
|
+
id: generateId(),
|
|
39867
|
+
name: name.trim(),
|
|
39868
|
+
description: description?.trim() || undefined,
|
|
39869
|
+
createdAt: now2,
|
|
39870
|
+
updatedAt: now2,
|
|
39871
|
+
context: [],
|
|
39872
|
+
plans: []
|
|
39873
|
+
};
|
|
39874
|
+
await saveProject(cwd2, project);
|
|
39875
|
+
return project;
|
|
39876
|
+
}
|
|
39877
|
+
async function updateProject(cwd2, id, updater) {
|
|
39878
|
+
const project = await readProject(cwd2, id);
|
|
39879
|
+
if (!project)
|
|
39880
|
+
return null;
|
|
39881
|
+
const updated = updater(project);
|
|
39882
|
+
await saveProject(cwd2, updated);
|
|
39883
|
+
return updated;
|
|
39884
|
+
}
|
|
39885
|
+
async function ensureDefaultProject(cwd2) {
|
|
39886
|
+
const projects = await listProjects(cwd2);
|
|
39887
|
+
if (projects.length > 0)
|
|
39888
|
+
return projects[0];
|
|
39889
|
+
return createProject(cwd2, "default", "Default project for this folder");
|
|
39890
|
+
}
|
|
39891
|
+
function hasProjectNameConflict(projects, name) {
|
|
39892
|
+
const normalized = normalizeName(name);
|
|
39893
|
+
return projects.some((project) => normalizeName(project.name) === normalized);
|
|
39894
|
+
}
|
|
39895
|
+
|
|
39896
|
+
// packages/core/src/projects/context.ts
|
|
39897
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
39898
|
+
import { resolve as resolve4 } from "path";
|
|
39899
|
+
var DEFAULT_MAX_FILE_BYTES = 12000;
|
|
39900
|
+
function formatPlan(plan) {
|
|
39901
|
+
const lines = [];
|
|
39902
|
+
lines.push(`- ${plan.title} (${plan.steps.length} steps)`);
|
|
39903
|
+
for (const step of plan.steps) {
|
|
39904
|
+
lines.push(` - [${step.status}] ${step.text}`);
|
|
39905
|
+
}
|
|
39906
|
+
return lines.join(`
|
|
39907
|
+
`);
|
|
39908
|
+
}
|
|
39909
|
+
function normalizeEntryLabel(entry) {
|
|
39910
|
+
return entry.label ? entry.label.trim() : entry.value.trim();
|
|
39911
|
+
}
|
|
39912
|
+
async function renderFileEntry(entry, options) {
|
|
39913
|
+
const rawPath = entry.value.trim();
|
|
39914
|
+
const resolved = resolve4(options.cwd, rawPath);
|
|
39915
|
+
const validation = await validatePath(resolved, { allowedPaths: [options.cwd] });
|
|
39916
|
+
if (!validation.valid) {
|
|
39917
|
+
return `- File: ${rawPath} (unavailable: ${validation.error || "invalid path"})`;
|
|
39918
|
+
}
|
|
39919
|
+
let content = "";
|
|
39920
|
+
try {
|
|
39921
|
+
const data = await readFile3(validation.resolved, "utf-8");
|
|
39922
|
+
const limit = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
39923
|
+
if (data.length > limit) {
|
|
39924
|
+
content = `${data.slice(0, limit)}
|
|
39925
|
+
|
|
39926
|
+
... [truncated ${data.length - limit} chars]`;
|
|
39927
|
+
} else {
|
|
39928
|
+
content = data;
|
|
39929
|
+
}
|
|
39930
|
+
} catch (error) {
|
|
39931
|
+
return `- File: ${rawPath} (unavailable: ${error instanceof Error ? error.message : String(error)})`;
|
|
39932
|
+
}
|
|
39933
|
+
return `- File: ${rawPath}
|
|
39934
|
+
\`\`\`
|
|
39935
|
+
${content}
|
|
39936
|
+
\`\`\``;
|
|
39937
|
+
}
|
|
39938
|
+
function renderConnectorEntry(entry, connectors) {
|
|
39939
|
+
const name = entry.value.trim();
|
|
39940
|
+
const connector = connectors?.find((c) => c.name === name);
|
|
39941
|
+
if (!connector) {
|
|
39942
|
+
return `- Connector: ${name}`;
|
|
39943
|
+
}
|
|
39944
|
+
const lines = [];
|
|
39945
|
+
lines.push(`- Connector: ${connector.name}`);
|
|
39946
|
+
if (connector.description) {
|
|
39947
|
+
lines.push(` - ${connector.description}`);
|
|
39948
|
+
}
|
|
39949
|
+
if (connector.cli) {
|
|
39950
|
+
lines.push(` - CLI: ${connector.cli}`);
|
|
39951
|
+
}
|
|
39952
|
+
if (connector.commands && connector.commands.length > 0) {
|
|
39953
|
+
const subset = connector.commands.slice(0, 5);
|
|
39954
|
+
for (const cmd of subset) {
|
|
39955
|
+
lines.push(` - ${cmd.name}: ${cmd.description}`);
|
|
39956
|
+
}
|
|
39957
|
+
if (connector.commands.length > subset.length) {
|
|
39958
|
+
lines.push(` - ... ${connector.commands.length - subset.length} more commands`);
|
|
39959
|
+
}
|
|
39960
|
+
}
|
|
39961
|
+
return lines.join(`
|
|
39962
|
+
`);
|
|
39963
|
+
}
|
|
39964
|
+
function renderGenericEntry(entry) {
|
|
39965
|
+
const label = normalizeEntryLabel(entry);
|
|
39966
|
+
return `- ${entry.type}: ${label}`;
|
|
39967
|
+
}
|
|
39968
|
+
async function buildProjectContext(project, options) {
|
|
39969
|
+
const lines = [];
|
|
39970
|
+
lines.push(`## Project: ${project.name}`);
|
|
39971
|
+
if (project.description) {
|
|
39972
|
+
lines.push(`Description: ${project.description}`);
|
|
39973
|
+
}
|
|
39974
|
+
if (project.context.length > 0) {
|
|
39975
|
+
lines.push("");
|
|
39976
|
+
lines.push("### Project Context");
|
|
39977
|
+
for (const entry of project.context) {
|
|
39978
|
+
if (entry.type === "file") {
|
|
39979
|
+
lines.push(await renderFileEntry(entry, options));
|
|
39980
|
+
continue;
|
|
39981
|
+
}
|
|
39982
|
+
if (entry.type === "connector") {
|
|
39983
|
+
lines.push(renderConnectorEntry(entry, options.connectors));
|
|
39984
|
+
continue;
|
|
39985
|
+
}
|
|
39986
|
+
lines.push(renderGenericEntry(entry));
|
|
39987
|
+
}
|
|
39988
|
+
}
|
|
39989
|
+
if (project.plans.length > 0) {
|
|
39990
|
+
lines.push("");
|
|
39991
|
+
lines.push("### Plans");
|
|
39992
|
+
for (const plan of project.plans) {
|
|
39993
|
+
lines.push(formatPlan(plan));
|
|
39994
|
+
}
|
|
39995
|
+
}
|
|
39996
|
+
return lines.join(`
|
|
39997
|
+
`);
|
|
39998
|
+
}
|
|
39999
|
+
|
|
40000
|
+
// packages/core/src/commands/builtin.ts
|
|
40001
|
+
var VERSION = process.env.ASSISTANTS_VERSION || process.env.npm_package_version || process.env.OLDPAL_VERSION || "unknown";
|
|
40002
|
+
function resolveAuthTimeout(resolve5) {
|
|
40003
|
+
resolve5({ exitCode: 1, stdout: { toString: () => "{}" } });
|
|
39747
40004
|
}
|
|
39748
40005
|
function splitArgs(input) {
|
|
39749
40006
|
const args = [];
|
|
@@ -39792,6 +40049,8 @@ class BuiltinCommands {
|
|
|
39792
40049
|
loader.register(this.statusCommand());
|
|
39793
40050
|
loader.register(this.tokensCommand());
|
|
39794
40051
|
loader.register(this.contextCommand());
|
|
40052
|
+
loader.register(this.projectsCommand());
|
|
40053
|
+
loader.register(this.plansCommand());
|
|
39795
40054
|
loader.register(this.summarizeCommand());
|
|
39796
40055
|
loader.register(this.restCommand());
|
|
39797
40056
|
loader.register(this.voiceCommand());
|
|
@@ -40397,151 +40656,743 @@ Identities:
|
|
|
40397
40656
|
contextCommand() {
|
|
40398
40657
|
return {
|
|
40399
40658
|
name: "context",
|
|
40400
|
-
description: "
|
|
40659
|
+
description: "Manage injected project context (files, connectors, notes) or show status",
|
|
40401
40660
|
builtin: true,
|
|
40402
40661
|
selfHandled: true,
|
|
40403
40662
|
content: "",
|
|
40404
40663
|
handler: async (args, context) => {
|
|
40405
|
-
const
|
|
40406
|
-
|
|
40664
|
+
const parts = splitArgs(args);
|
|
40665
|
+
const sub = parts[0] || "status";
|
|
40666
|
+
if (sub === "help") {
|
|
40667
|
+
const usage = [
|
|
40668
|
+
"Usage:",
|
|
40669
|
+
" /context status",
|
|
40670
|
+
" /context list",
|
|
40671
|
+
" /context add file <path>",
|
|
40672
|
+
" /context add connector <name>",
|
|
40673
|
+
" /context add database <name>",
|
|
40674
|
+
" /context add note <text>",
|
|
40675
|
+
" /context add entity <text>",
|
|
40676
|
+
" /context remove <id>",
|
|
40677
|
+
" /context clear"
|
|
40678
|
+
].join(`
|
|
40679
|
+
`);
|
|
40407
40680
|
context.emit("text", `
|
|
40408
|
-
|
|
40681
|
+
${usage}
|
|
40409
40682
|
`);
|
|
40410
40683
|
context.emit("done");
|
|
40411
40684
|
return { handled: true };
|
|
40412
40685
|
}
|
|
40413
|
-
|
|
40414
|
-
|
|
40415
|
-
|
|
40686
|
+
if (sub === "status") {
|
|
40687
|
+
const info = context.getContextInfo?.();
|
|
40688
|
+
if (!info) {
|
|
40689
|
+
context.emit("text", `
|
|
40690
|
+
Context summarization is not available.
|
|
40691
|
+
`);
|
|
40692
|
+
context.emit("done");
|
|
40693
|
+
return { handled: true };
|
|
40694
|
+
}
|
|
40695
|
+
const { config, state } = info;
|
|
40696
|
+
const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
|
|
40697
|
+
let message = `
|
|
40416
40698
|
**Context Status**
|
|
40417
40699
|
|
|
40418
40700
|
`;
|
|
40419
|
-
|
|
40701
|
+
message += `**Messages:** ${state.messageCount}
|
|
40420
40702
|
`;
|
|
40421
|
-
|
|
40703
|
+
message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
|
|
40422
40704
|
`;
|
|
40423
|
-
|
|
40705
|
+
message += `**Summary Count:** ${state.summaryCount}
|
|
40424
40706
|
`;
|
|
40425
|
-
|
|
40707
|
+
message += `**Strategy:** ${config.summaryStrategy}
|
|
40426
40708
|
`;
|
|
40427
|
-
|
|
40709
|
+
message += `**Keep Recent Messages:** ${config.keepRecentMessages}
|
|
40428
40710
|
`;
|
|
40429
|
-
|
|
40430
|
-
|
|
40711
|
+
if (state.lastSummaryAt) {
|
|
40712
|
+
message += `**Last Summary:** ${state.lastSummaryAt}
|
|
40431
40713
|
`;
|
|
40432
|
-
|
|
40433
|
-
|
|
40714
|
+
if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
|
|
40715
|
+
message += `**Last Summary Tokens:** ${state.lastSummaryTokensBefore.toLocaleString()} -> ${state.lastSummaryTokensAfter.toLocaleString()}
|
|
40434
40716
|
`;
|
|
40717
|
+
}
|
|
40435
40718
|
}
|
|
40436
|
-
|
|
40437
|
-
|
|
40438
|
-
|
|
40439
|
-
|
|
40440
|
-
message += `
|
|
40719
|
+
const barLength = 30;
|
|
40720
|
+
const filledLength = Math.round(usedPercent / 100 * barLength);
|
|
40721
|
+
const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
|
|
40722
|
+
message += `
|
|
40441
40723
|
[${bar}] ${usedPercent}%
|
|
40442
40724
|
`;
|
|
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
|
-
`);
|
|
40725
|
+
context.emit("text", message);
|
|
40461
40726
|
context.emit("done");
|
|
40462
40727
|
return { handled: true };
|
|
40463
40728
|
}
|
|
40464
|
-
const
|
|
40465
|
-
if (!
|
|
40466
|
-
context.emit("text", `
|
|
40467
|
-
Nothing to summarize right now.
|
|
40729
|
+
const project = await this.ensureActiveProject(context, true);
|
|
40730
|
+
if (!project) {
|
|
40731
|
+
context.emit("text", `No project found. Use /projects new <name> first.
|
|
40468
40732
|
`);
|
|
40469
40733
|
context.emit("done");
|
|
40470
40734
|
return { handled: true };
|
|
40471
40735
|
}
|
|
40472
|
-
|
|
40473
|
-
|
|
40474
|
-
|
|
40475
|
-
|
|
40476
|
-
|
|
40477
|
-
|
|
40478
|
-
|
|
40736
|
+
if (sub === "list") {
|
|
40737
|
+
if (project.context.length === 0) {
|
|
40738
|
+
context.emit("text", `
|
|
40739
|
+
No context entries for project "${project.name}".
|
|
40740
|
+
`);
|
|
40741
|
+
context.emit("done");
|
|
40742
|
+
return { handled: true };
|
|
40743
|
+
}
|
|
40744
|
+
let output = `
|
|
40745
|
+
**Context Entries (${project.name})**
|
|
40479
40746
|
|
|
40480
40747
|
`;
|
|
40481
|
-
|
|
40482
|
-
|
|
40748
|
+
for (const entry of project.context) {
|
|
40749
|
+
const label = entry.label ? ` (${entry.label})` : "";
|
|
40750
|
+
output += `- ${entry.id} [${entry.type}] ${entry.value}${label}
|
|
40483
40751
|
`;
|
|
40752
|
+
}
|
|
40753
|
+
context.emit("text", output);
|
|
40754
|
+
context.emit("done");
|
|
40755
|
+
return { handled: true };
|
|
40484
40756
|
}
|
|
40485
|
-
|
|
40757
|
+
if (sub === "clear") {
|
|
40758
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40759
|
+
...current,
|
|
40760
|
+
context: [],
|
|
40761
|
+
updatedAt: Date.now()
|
|
40762
|
+
}));
|
|
40763
|
+
if (updated) {
|
|
40764
|
+
await this.applyProjectContext(context, updated);
|
|
40765
|
+
context.emit("text", `Cleared context entries for "${updated.name}".
|
|
40766
|
+
`);
|
|
40767
|
+
context.emit("done");
|
|
40768
|
+
return { handled: true };
|
|
40769
|
+
}
|
|
40770
|
+
}
|
|
40771
|
+
if (sub === "remove") {
|
|
40772
|
+
const id = parts[1];
|
|
40773
|
+
if (!id) {
|
|
40774
|
+
context.emit("text", `Usage: /context remove <id>
|
|
40775
|
+
`);
|
|
40776
|
+
context.emit("done");
|
|
40777
|
+
return { handled: true };
|
|
40778
|
+
}
|
|
40779
|
+
if (!project.context.some((entry) => entry.id === id)) {
|
|
40780
|
+
context.emit("text", `Context entry not found: ${id}
|
|
40781
|
+
`);
|
|
40782
|
+
context.emit("done");
|
|
40783
|
+
return { handled: true };
|
|
40784
|
+
}
|
|
40785
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40786
|
+
...current,
|
|
40787
|
+
context: current.context.filter((entry) => entry.id !== id),
|
|
40788
|
+
updatedAt: Date.now()
|
|
40789
|
+
}));
|
|
40790
|
+
if (updated) {
|
|
40791
|
+
await this.applyProjectContext(context, updated);
|
|
40792
|
+
context.emit("text", `Removed context entry ${id} from "${updated.name}".
|
|
40793
|
+
`);
|
|
40794
|
+
context.emit("done");
|
|
40795
|
+
return { handled: true };
|
|
40796
|
+
}
|
|
40797
|
+
}
|
|
40798
|
+
if (sub === "add") {
|
|
40799
|
+
const type = parts[1];
|
|
40800
|
+
const value = parts.slice(2).join(" ").trim();
|
|
40801
|
+
if (!type) {
|
|
40802
|
+
context.emit("text", `Usage: /context add <type> <value>
|
|
40803
|
+
`);
|
|
40804
|
+
context.emit("done");
|
|
40805
|
+
return { handled: true };
|
|
40806
|
+
}
|
|
40807
|
+
const allowedTypes = ["file", "connector", "database", "note", "entity"];
|
|
40808
|
+
const entryType = allowedTypes.includes(type) ? type : "note";
|
|
40809
|
+
const entryValue = entryType === "note" && !value ? parts.slice(1).join(" ").trim() : value;
|
|
40810
|
+
if (!entryValue) {
|
|
40811
|
+
context.emit("text", `Error: context value is required.
|
|
40812
|
+
`);
|
|
40813
|
+
context.emit("done");
|
|
40814
|
+
return { handled: true };
|
|
40815
|
+
}
|
|
40816
|
+
const entry = {
|
|
40817
|
+
id: generateId(),
|
|
40818
|
+
type: entryType,
|
|
40819
|
+
value: entryValue,
|
|
40820
|
+
addedAt: Date.now()
|
|
40821
|
+
};
|
|
40822
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40823
|
+
...current,
|
|
40824
|
+
context: [...current.context, entry],
|
|
40825
|
+
updatedAt: Date.now()
|
|
40826
|
+
}));
|
|
40827
|
+
if (updated) {
|
|
40828
|
+
await this.applyProjectContext(context, updated);
|
|
40829
|
+
context.emit("text", `Added ${entry.type} context to "${updated.name}".
|
|
40830
|
+
`);
|
|
40831
|
+
context.emit("done");
|
|
40832
|
+
return { handled: true };
|
|
40833
|
+
}
|
|
40834
|
+
}
|
|
40835
|
+
context.emit("text", `Unknown /context command. Use /context help.
|
|
40836
|
+
`);
|
|
40486
40837
|
context.emit("done");
|
|
40487
40838
|
return { handled: true };
|
|
40488
40839
|
}
|
|
40489
40840
|
};
|
|
40490
40841
|
}
|
|
40491
|
-
|
|
40842
|
+
projectsCommand() {
|
|
40492
40843
|
return {
|
|
40493
|
-
name: "
|
|
40494
|
-
description: "
|
|
40844
|
+
name: "projects",
|
|
40845
|
+
description: "Manage projects inside this folder",
|
|
40495
40846
|
builtin: true,
|
|
40496
40847
|
selfHandled: true,
|
|
40497
40848
|
content: "",
|
|
40498
40849
|
handler: async (args, context) => {
|
|
40499
|
-
|
|
40850
|
+
const parts = splitArgs(args);
|
|
40851
|
+
const sub = parts[0] || "list";
|
|
40852
|
+
if (sub === "help") {
|
|
40853
|
+
const usage = [
|
|
40854
|
+
"Usage:",
|
|
40855
|
+
" /projects list",
|
|
40856
|
+
" /projects new <name>",
|
|
40857
|
+
" /projects use <id|name>",
|
|
40858
|
+
" /projects show [id|name]",
|
|
40859
|
+
" /projects delete <id|name>",
|
|
40860
|
+
" /projects describe <id|name> <description>"
|
|
40861
|
+
].join(`
|
|
40862
|
+
`);
|
|
40500
40863
|
context.emit("text", `
|
|
40501
|
-
|
|
40864
|
+
${usage}
|
|
40502
40865
|
`);
|
|
40503
40866
|
context.emit("done");
|
|
40504
40867
|
return { handled: true };
|
|
40505
40868
|
}
|
|
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.
|
|
40869
|
+
if (sub === "list" || sub === "ls") {
|
|
40870
|
+
const projects = await listProjects(context.cwd);
|
|
40871
|
+
if (projects.length === 0) {
|
|
40872
|
+
context.emit("text", `
|
|
40873
|
+
No projects found. Use /projects new <name>.
|
|
40518
40874
|
`);
|
|
40519
|
-
|
|
40520
|
-
|
|
40521
|
-
|
|
40522
|
-
|
|
40523
|
-
|
|
40524
|
-
|
|
40525
|
-
skillsCommand(loader) {
|
|
40526
|
-
return {
|
|
40527
|
-
name: "skills",
|
|
40528
|
-
description: "List available skills",
|
|
40529
|
-
builtin: true,
|
|
40530
|
-
selfHandled: true,
|
|
40531
|
-
content: "",
|
|
40532
|
-
handler: async (args, context) => {
|
|
40533
|
-
let message = `
|
|
40534
|
-
**Available Skills**
|
|
40535
|
-
|
|
40536
|
-
`;
|
|
40537
|
-
message += `Skills are invoked with $skill-name [arguments] or /skill-name [arguments]
|
|
40875
|
+
context.emit("done");
|
|
40876
|
+
return { handled: true };
|
|
40877
|
+
}
|
|
40878
|
+
const activeId = context.getActiveProjectId?.();
|
|
40879
|
+
let output = `
|
|
40880
|
+
**Projects**
|
|
40538
40881
|
|
|
40539
40882
|
`;
|
|
40540
|
-
|
|
40541
|
-
|
|
40883
|
+
for (const project of projects) {
|
|
40884
|
+
const marker = project.id === activeId ? "*" : " ";
|
|
40885
|
+
output += `${marker} ${project.name} (${project.id})
|
|
40542
40886
|
`;
|
|
40543
|
-
|
|
40544
|
-
|
|
40887
|
+
}
|
|
40888
|
+
context.emit("text", output);
|
|
40889
|
+
context.emit("done");
|
|
40890
|
+
return { handled: true };
|
|
40891
|
+
}
|
|
40892
|
+
if (sub === "new" || sub === "create") {
|
|
40893
|
+
const name = parts.slice(1).join(" ").trim();
|
|
40894
|
+
if (!name) {
|
|
40895
|
+
context.emit("text", `Usage: /projects new <name>
|
|
40896
|
+
`);
|
|
40897
|
+
context.emit("done");
|
|
40898
|
+
return { handled: true };
|
|
40899
|
+
}
|
|
40900
|
+
const existing = await listProjects(context.cwd);
|
|
40901
|
+
if (hasProjectNameConflict(existing, name)) {
|
|
40902
|
+
context.emit("text", `Project "${name}" already exists.
|
|
40903
|
+
`);
|
|
40904
|
+
context.emit("done");
|
|
40905
|
+
return { handled: true };
|
|
40906
|
+
}
|
|
40907
|
+
const project = await createProject(context.cwd, name);
|
|
40908
|
+
context.setActiveProjectId?.(project.id);
|
|
40909
|
+
await this.applyProjectContext(context, project);
|
|
40910
|
+
context.emit("text", `Created project "${project.name}" (${project.id}).
|
|
40911
|
+
`);
|
|
40912
|
+
context.emit("done");
|
|
40913
|
+
return { handled: true };
|
|
40914
|
+
}
|
|
40915
|
+
if (sub === "use" || sub === "switch") {
|
|
40916
|
+
const target = parts.slice(1).join(" ").trim();
|
|
40917
|
+
if (!target) {
|
|
40918
|
+
context.emit("text", `Usage: /projects use <id|name>
|
|
40919
|
+
`);
|
|
40920
|
+
context.emit("done");
|
|
40921
|
+
return { handled: true };
|
|
40922
|
+
}
|
|
40923
|
+
const project = await this.resolveProject(context, target);
|
|
40924
|
+
if (!project) {
|
|
40925
|
+
context.emit("text", `Project not found: ${target}
|
|
40926
|
+
`);
|
|
40927
|
+
context.emit("done");
|
|
40928
|
+
return { handled: true };
|
|
40929
|
+
}
|
|
40930
|
+
context.setActiveProjectId?.(project.id);
|
|
40931
|
+
await this.applyProjectContext(context, project);
|
|
40932
|
+
context.emit("text", `Switched to project "${project.name}".
|
|
40933
|
+
`);
|
|
40934
|
+
context.emit("done");
|
|
40935
|
+
return { handled: true };
|
|
40936
|
+
}
|
|
40937
|
+
if (sub === "show" || sub === "info") {
|
|
40938
|
+
const target = parts.slice(1).join(" ").trim();
|
|
40939
|
+
const project = target ? await this.resolveProject(context, target) : await this.ensureActiveProject(context, false);
|
|
40940
|
+
if (!project) {
|
|
40941
|
+
context.emit("text", `No project selected. Use /projects use <id|name>.
|
|
40942
|
+
`);
|
|
40943
|
+
context.emit("done");
|
|
40944
|
+
return { handled: true };
|
|
40945
|
+
}
|
|
40946
|
+
let output = `
|
|
40947
|
+
**Project: ${project.name}**
|
|
40948
|
+
|
|
40949
|
+
`;
|
|
40950
|
+
output += `ID: ${project.id}
|
|
40951
|
+
`;
|
|
40952
|
+
if (project.description) {
|
|
40953
|
+
output += `Description: ${project.description}
|
|
40954
|
+
`;
|
|
40955
|
+
}
|
|
40956
|
+
output += `Context entries: ${project.context.length}
|
|
40957
|
+
`;
|
|
40958
|
+
output += `Plans: ${project.plans.length}
|
|
40959
|
+
`;
|
|
40960
|
+
context.emit("text", output);
|
|
40961
|
+
context.emit("done");
|
|
40962
|
+
return { handled: true };
|
|
40963
|
+
}
|
|
40964
|
+
if (sub === "describe" || sub === "desc") {
|
|
40965
|
+
const target = parts[1];
|
|
40966
|
+
const description = parts.slice(2).join(" ").trim();
|
|
40967
|
+
if (!target || !description) {
|
|
40968
|
+
context.emit("text", `Usage: /projects describe <id|name> <description>
|
|
40969
|
+
`);
|
|
40970
|
+
context.emit("done");
|
|
40971
|
+
return { handled: true };
|
|
40972
|
+
}
|
|
40973
|
+
const project = await this.resolveProject(context, target);
|
|
40974
|
+
if (!project) {
|
|
40975
|
+
context.emit("text", `Project not found: ${target}
|
|
40976
|
+
`);
|
|
40977
|
+
context.emit("done");
|
|
40978
|
+
return { handled: true };
|
|
40979
|
+
}
|
|
40980
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
40981
|
+
...current,
|
|
40982
|
+
description,
|
|
40983
|
+
updatedAt: Date.now()
|
|
40984
|
+
}));
|
|
40985
|
+
if (updated) {
|
|
40986
|
+
await this.applyProjectContext(context, updated);
|
|
40987
|
+
context.emit("text", `Updated project "${updated.name}".
|
|
40988
|
+
`);
|
|
40989
|
+
context.emit("done");
|
|
40990
|
+
return { handled: true };
|
|
40991
|
+
}
|
|
40992
|
+
}
|
|
40993
|
+
if (sub === "delete" || sub === "rm") {
|
|
40994
|
+
const target = parts.slice(1).join(" ").trim();
|
|
40995
|
+
if (!target) {
|
|
40996
|
+
context.emit("text", `Usage: /projects delete <id|name>
|
|
40997
|
+
`);
|
|
40998
|
+
context.emit("done");
|
|
40999
|
+
return { handled: true };
|
|
41000
|
+
}
|
|
41001
|
+
const project = await this.resolveProject(context, target);
|
|
41002
|
+
if (!project) {
|
|
41003
|
+
context.emit("text", `Project not found: ${target}
|
|
41004
|
+
`);
|
|
41005
|
+
context.emit("done");
|
|
41006
|
+
return { handled: true };
|
|
41007
|
+
}
|
|
41008
|
+
const ok = await deleteProject(context.cwd, project.id);
|
|
41009
|
+
if (ok) {
|
|
41010
|
+
if (context.getActiveProjectId?.() === project.id) {
|
|
41011
|
+
context.setActiveProjectId?.(null);
|
|
41012
|
+
context.setProjectContext?.(null);
|
|
41013
|
+
}
|
|
41014
|
+
context.emit("text", `Deleted project "${project.name}".
|
|
41015
|
+
`);
|
|
41016
|
+
context.emit("done");
|
|
41017
|
+
return { handled: true };
|
|
41018
|
+
}
|
|
41019
|
+
}
|
|
41020
|
+
context.emit("text", `Unknown /projects command. Use /projects help.
|
|
41021
|
+
`);
|
|
41022
|
+
context.emit("done");
|
|
41023
|
+
return { handled: true };
|
|
41024
|
+
}
|
|
41025
|
+
};
|
|
41026
|
+
}
|
|
41027
|
+
plansCommand() {
|
|
41028
|
+
return {
|
|
41029
|
+
name: "plans",
|
|
41030
|
+
description: "Manage plans linked to the active project",
|
|
41031
|
+
builtin: true,
|
|
41032
|
+
selfHandled: true,
|
|
41033
|
+
content: "",
|
|
41034
|
+
handler: async (args, context) => {
|
|
41035
|
+
const parts = splitArgs(args);
|
|
41036
|
+
const sub = parts[0] || "list";
|
|
41037
|
+
if (sub === "help") {
|
|
41038
|
+
const usage = [
|
|
41039
|
+
"Usage:",
|
|
41040
|
+
" /plans list",
|
|
41041
|
+
" /plans new <title>",
|
|
41042
|
+
" /plans show <planId>",
|
|
41043
|
+
" /plans add <planId> <step>",
|
|
41044
|
+
" /plans set <planId> <stepId> <todo|doing|done|blocked>",
|
|
41045
|
+
" /plans remove <planId> <stepId>",
|
|
41046
|
+
" /plans delete <planId>"
|
|
41047
|
+
].join(`
|
|
41048
|
+
`);
|
|
41049
|
+
context.emit("text", `
|
|
41050
|
+
${usage}
|
|
41051
|
+
`);
|
|
41052
|
+
context.emit("done");
|
|
41053
|
+
return { handled: true };
|
|
41054
|
+
}
|
|
41055
|
+
const project = await this.ensureActiveProject(context, true);
|
|
41056
|
+
if (!project) {
|
|
41057
|
+
context.emit("text", `No project found. Use /projects new <name> first.
|
|
41058
|
+
`);
|
|
41059
|
+
context.emit("done");
|
|
41060
|
+
return { handled: true };
|
|
41061
|
+
}
|
|
41062
|
+
if (sub === "list" || sub === "ls") {
|
|
41063
|
+
if (project.plans.length === 0) {
|
|
41064
|
+
context.emit("text", `
|
|
41065
|
+
No plans for project "${project.name}".
|
|
41066
|
+
`);
|
|
41067
|
+
context.emit("done");
|
|
41068
|
+
return { handled: true };
|
|
41069
|
+
}
|
|
41070
|
+
let output = `
|
|
41071
|
+
**Plans (${project.name})**
|
|
41072
|
+
|
|
41073
|
+
`;
|
|
41074
|
+
for (const plan of project.plans) {
|
|
41075
|
+
output += `- ${plan.id} ${plan.title} (${plan.steps.length} steps)
|
|
41076
|
+
`;
|
|
41077
|
+
}
|
|
41078
|
+
context.emit("text", output);
|
|
41079
|
+
context.emit("done");
|
|
41080
|
+
return { handled: true };
|
|
41081
|
+
}
|
|
41082
|
+
if (sub === "new" || sub === "create") {
|
|
41083
|
+
const title = parts.slice(1).join(" ").trim();
|
|
41084
|
+
if (!title) {
|
|
41085
|
+
context.emit("text", `Usage: /plans new <title>
|
|
41086
|
+
`);
|
|
41087
|
+
context.emit("done");
|
|
41088
|
+
return { handled: true };
|
|
41089
|
+
}
|
|
41090
|
+
const now2 = Date.now();
|
|
41091
|
+
const plan = {
|
|
41092
|
+
id: generateId(),
|
|
41093
|
+
title,
|
|
41094
|
+
createdAt: now2,
|
|
41095
|
+
updatedAt: now2,
|
|
41096
|
+
steps: []
|
|
41097
|
+
};
|
|
41098
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41099
|
+
...current,
|
|
41100
|
+
plans: [...current.plans, plan],
|
|
41101
|
+
updatedAt: now2
|
|
41102
|
+
}));
|
|
41103
|
+
if (updated) {
|
|
41104
|
+
await this.applyProjectContext(context, updated);
|
|
41105
|
+
context.emit("text", `Created plan "${plan.title}" (${plan.id}).
|
|
41106
|
+
`);
|
|
41107
|
+
context.emit("done");
|
|
41108
|
+
return { handled: true };
|
|
41109
|
+
}
|
|
41110
|
+
}
|
|
41111
|
+
if (sub === "show") {
|
|
41112
|
+
const id = parts[1];
|
|
41113
|
+
if (!id) {
|
|
41114
|
+
context.emit("text", `Usage: /plans show <planId>
|
|
41115
|
+
`);
|
|
41116
|
+
context.emit("done");
|
|
41117
|
+
return { handled: true };
|
|
41118
|
+
}
|
|
41119
|
+
const plan = project.plans.find((p) => p.id === id);
|
|
41120
|
+
if (!plan) {
|
|
41121
|
+
context.emit("text", `Plan not found: ${id}
|
|
41122
|
+
`);
|
|
41123
|
+
context.emit("done");
|
|
41124
|
+
return { handled: true };
|
|
41125
|
+
}
|
|
41126
|
+
let output = `
|
|
41127
|
+
**Plan: ${plan.title}**
|
|
41128
|
+
|
|
41129
|
+
`;
|
|
41130
|
+
output += `ID: ${plan.id}
|
|
41131
|
+
`;
|
|
41132
|
+
if (plan.steps.length === 0) {
|
|
41133
|
+
output += `No steps yet.
|
|
41134
|
+
`;
|
|
41135
|
+
} else {
|
|
41136
|
+
for (const step of plan.steps) {
|
|
41137
|
+
output += `- ${step.id} [${step.status}] ${step.text}
|
|
41138
|
+
`;
|
|
41139
|
+
}
|
|
41140
|
+
}
|
|
41141
|
+
context.emit("text", output);
|
|
41142
|
+
context.emit("done");
|
|
41143
|
+
return { handled: true };
|
|
41144
|
+
}
|
|
41145
|
+
if (sub === "add") {
|
|
41146
|
+
const planId = parts[1];
|
|
41147
|
+
const text = parts.slice(2).join(" ").trim();
|
|
41148
|
+
if (!planId || !text) {
|
|
41149
|
+
context.emit("text", `Usage: /plans add <planId> <step>
|
|
41150
|
+
`);
|
|
41151
|
+
context.emit("done");
|
|
41152
|
+
return { handled: true };
|
|
41153
|
+
}
|
|
41154
|
+
if (!project.plans.some((plan) => plan.id === planId)) {
|
|
41155
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41156
|
+
`);
|
|
41157
|
+
context.emit("done");
|
|
41158
|
+
return { handled: true };
|
|
41159
|
+
}
|
|
41160
|
+
const now2 = Date.now();
|
|
41161
|
+
const step = {
|
|
41162
|
+
id: generateId(),
|
|
41163
|
+
text,
|
|
41164
|
+
status: "todo",
|
|
41165
|
+
createdAt: now2,
|
|
41166
|
+
updatedAt: now2
|
|
41167
|
+
};
|
|
41168
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41169
|
+
...current,
|
|
41170
|
+
plans: current.plans.map((plan) => plan.id === planId ? { ...plan, steps: [...plan.steps, step], updatedAt: now2 } : plan),
|
|
41171
|
+
updatedAt: now2
|
|
41172
|
+
}));
|
|
41173
|
+
if (updated) {
|
|
41174
|
+
await this.applyProjectContext(context, updated);
|
|
41175
|
+
context.emit("text", `Added step to plan ${planId}.
|
|
41176
|
+
`);
|
|
41177
|
+
context.emit("done");
|
|
41178
|
+
return { handled: true };
|
|
41179
|
+
}
|
|
41180
|
+
}
|
|
41181
|
+
if (sub === "set") {
|
|
41182
|
+
const planId = parts[1];
|
|
41183
|
+
const stepId = parts[2];
|
|
41184
|
+
const status = parts[3];
|
|
41185
|
+
if (!planId || !stepId || !status) {
|
|
41186
|
+
context.emit("text", `Usage: /plans set <planId> <stepId> <todo|doing|done|blocked>
|
|
41187
|
+
`);
|
|
41188
|
+
context.emit("done");
|
|
41189
|
+
return { handled: true };
|
|
41190
|
+
}
|
|
41191
|
+
const plan = project.plans.find((item) => item.id === planId);
|
|
41192
|
+
if (!plan) {
|
|
41193
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41194
|
+
`);
|
|
41195
|
+
context.emit("done");
|
|
41196
|
+
return { handled: true };
|
|
41197
|
+
}
|
|
41198
|
+
if (!plan.steps.some((step) => step.id === stepId)) {
|
|
41199
|
+
context.emit("text", `Step not found: ${stepId}
|
|
41200
|
+
`);
|
|
41201
|
+
context.emit("done");
|
|
41202
|
+
return { handled: true };
|
|
41203
|
+
}
|
|
41204
|
+
const allowed = ["todo", "doing", "done", "blocked"];
|
|
41205
|
+
if (!allowed.includes(status)) {
|
|
41206
|
+
context.emit("text", `Invalid status. Use todo, doing, done, or blocked.
|
|
41207
|
+
`);
|
|
41208
|
+
context.emit("done");
|
|
41209
|
+
return { handled: true };
|
|
41210
|
+
}
|
|
41211
|
+
const now2 = Date.now();
|
|
41212
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41213
|
+
...current,
|
|
41214
|
+
plans: current.plans.map((plan2) => plan2.id === planId ? {
|
|
41215
|
+
...plan2,
|
|
41216
|
+
steps: plan2.steps.map((step) => step.id === stepId ? { ...step, status, updatedAt: now2 } : step),
|
|
41217
|
+
updatedAt: now2
|
|
41218
|
+
} : plan2),
|
|
41219
|
+
updatedAt: now2
|
|
41220
|
+
}));
|
|
41221
|
+
if (updated) {
|
|
41222
|
+
await this.applyProjectContext(context, updated);
|
|
41223
|
+
context.emit("text", `Updated step ${stepId} to ${status}.
|
|
41224
|
+
`);
|
|
41225
|
+
context.emit("done");
|
|
41226
|
+
return { handled: true };
|
|
41227
|
+
}
|
|
41228
|
+
}
|
|
41229
|
+
if (sub === "remove") {
|
|
41230
|
+
const planId = parts[1];
|
|
41231
|
+
const stepId = parts[2];
|
|
41232
|
+
if (!planId || !stepId) {
|
|
41233
|
+
context.emit("text", `Usage: /plans remove <planId> <stepId>
|
|
41234
|
+
`);
|
|
41235
|
+
context.emit("done");
|
|
41236
|
+
return { handled: true };
|
|
41237
|
+
}
|
|
41238
|
+
const plan = project.plans.find((item) => item.id === planId);
|
|
41239
|
+
if (!plan) {
|
|
41240
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41241
|
+
`);
|
|
41242
|
+
context.emit("done");
|
|
41243
|
+
return { handled: true };
|
|
41244
|
+
}
|
|
41245
|
+
if (!plan.steps.some((step) => step.id === stepId)) {
|
|
41246
|
+
context.emit("text", `Step not found: ${stepId}
|
|
41247
|
+
`);
|
|
41248
|
+
context.emit("done");
|
|
41249
|
+
return { handled: true };
|
|
41250
|
+
}
|
|
41251
|
+
const now2 = Date.now();
|
|
41252
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41253
|
+
...current,
|
|
41254
|
+
plans: current.plans.map((plan2) => plan2.id === planId ? { ...plan2, steps: plan2.steps.filter((step) => step.id !== stepId), updatedAt: now2 } : plan2),
|
|
41255
|
+
updatedAt: now2
|
|
41256
|
+
}));
|
|
41257
|
+
if (updated) {
|
|
41258
|
+
await this.applyProjectContext(context, updated);
|
|
41259
|
+
context.emit("text", `Removed step ${stepId} from plan ${planId}.
|
|
41260
|
+
`);
|
|
41261
|
+
context.emit("done");
|
|
41262
|
+
return { handled: true };
|
|
41263
|
+
}
|
|
41264
|
+
}
|
|
41265
|
+
if (sub === "delete" || sub === "rm") {
|
|
41266
|
+
const planId = parts[1];
|
|
41267
|
+
if (!planId) {
|
|
41268
|
+
context.emit("text", `Usage: /plans delete <planId>
|
|
41269
|
+
`);
|
|
41270
|
+
context.emit("done");
|
|
41271
|
+
return { handled: true };
|
|
41272
|
+
}
|
|
41273
|
+
if (!project.plans.some((plan) => plan.id === planId)) {
|
|
41274
|
+
context.emit("text", `Plan not found: ${planId}
|
|
41275
|
+
`);
|
|
41276
|
+
context.emit("done");
|
|
41277
|
+
return { handled: true };
|
|
41278
|
+
}
|
|
41279
|
+
const now2 = Date.now();
|
|
41280
|
+
const updated = await updateProject(context.cwd, project.id, (current) => ({
|
|
41281
|
+
...current,
|
|
41282
|
+
plans: current.plans.filter((plan) => plan.id !== planId),
|
|
41283
|
+
updatedAt: now2
|
|
41284
|
+
}));
|
|
41285
|
+
if (updated) {
|
|
41286
|
+
await this.applyProjectContext(context, updated);
|
|
41287
|
+
context.emit("text", `Deleted plan ${planId}.
|
|
41288
|
+
`);
|
|
41289
|
+
context.emit("done");
|
|
41290
|
+
return { handled: true };
|
|
41291
|
+
}
|
|
41292
|
+
}
|
|
41293
|
+
context.emit("text", `Unknown /plans command. Use /plans help.
|
|
41294
|
+
`);
|
|
41295
|
+
context.emit("done");
|
|
41296
|
+
return { handled: true };
|
|
41297
|
+
}
|
|
41298
|
+
};
|
|
41299
|
+
}
|
|
41300
|
+
summarizeCommand() {
|
|
41301
|
+
return {
|
|
41302
|
+
name: "summarize",
|
|
41303
|
+
description: "Summarize and compress the current conversation",
|
|
41304
|
+
builtin: true,
|
|
41305
|
+
selfHandled: true,
|
|
41306
|
+
content: "",
|
|
41307
|
+
handler: async (args, context) => {
|
|
41308
|
+
if (!context.summarizeContext) {
|
|
41309
|
+
context.emit("text", `
|
|
41310
|
+
Context summarization is not available.
|
|
41311
|
+
`);
|
|
41312
|
+
context.emit("done");
|
|
41313
|
+
return { handled: true };
|
|
41314
|
+
}
|
|
41315
|
+
const result = await context.summarizeContext();
|
|
41316
|
+
if (!result.summarized) {
|
|
41317
|
+
context.emit("text", `
|
|
41318
|
+
Nothing to summarize right now.
|
|
41319
|
+
`);
|
|
41320
|
+
context.emit("done");
|
|
41321
|
+
return { handled: true };
|
|
41322
|
+
}
|
|
41323
|
+
let message = `
|
|
41324
|
+
**Context Summary Generated**
|
|
41325
|
+
|
|
41326
|
+
`;
|
|
41327
|
+
message += `Summarized ${result.summarizedCount} message(s).
|
|
41328
|
+
`;
|
|
41329
|
+
message += `Tokens: ${result.tokensBefore.toLocaleString()} -> ${result.tokensAfter.toLocaleString()}
|
|
41330
|
+
|
|
41331
|
+
`;
|
|
41332
|
+
if (result.summary) {
|
|
41333
|
+
message += `${result.summary}
|
|
41334
|
+
`;
|
|
41335
|
+
}
|
|
41336
|
+
context.emit("text", message);
|
|
41337
|
+
context.emit("done");
|
|
41338
|
+
return { handled: true };
|
|
41339
|
+
}
|
|
41340
|
+
};
|
|
41341
|
+
}
|
|
41342
|
+
restCommand() {
|
|
41343
|
+
return {
|
|
41344
|
+
name: "rest",
|
|
41345
|
+
description: "Recharge assistant energy",
|
|
41346
|
+
builtin: true,
|
|
41347
|
+
selfHandled: true,
|
|
41348
|
+
content: "",
|
|
41349
|
+
handler: async (args, context) => {
|
|
41350
|
+
if (!context.restEnergy) {
|
|
41351
|
+
context.emit("text", `
|
|
41352
|
+
Energy system is not available.
|
|
41353
|
+
`);
|
|
41354
|
+
context.emit("done");
|
|
41355
|
+
return { handled: true };
|
|
41356
|
+
}
|
|
41357
|
+
const parsed = parseInt(args.trim(), 10);
|
|
41358
|
+
const amount = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
41359
|
+
context.restEnergy(amount);
|
|
41360
|
+
const state = context.getEnergyState?.();
|
|
41361
|
+
if (state) {
|
|
41362
|
+
const percent = Math.round(state.current / Math.max(1, state.max) * 100);
|
|
41363
|
+
context.emit("text", `
|
|
41364
|
+
Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
|
|
41365
|
+
`);
|
|
41366
|
+
} else {
|
|
41367
|
+
context.emit("text", `
|
|
41368
|
+
Energy restored.
|
|
41369
|
+
`);
|
|
41370
|
+
}
|
|
41371
|
+
context.emit("done");
|
|
41372
|
+
return { handled: true };
|
|
41373
|
+
}
|
|
41374
|
+
};
|
|
41375
|
+
}
|
|
41376
|
+
skillsCommand(loader) {
|
|
41377
|
+
return {
|
|
41378
|
+
name: "skills",
|
|
41379
|
+
description: "List available skills",
|
|
41380
|
+
builtin: true,
|
|
41381
|
+
selfHandled: true,
|
|
41382
|
+
content: "",
|
|
41383
|
+
handler: async (args, context) => {
|
|
41384
|
+
let message = `
|
|
41385
|
+
**Available Skills**
|
|
41386
|
+
|
|
41387
|
+
`;
|
|
41388
|
+
message += `Skills are invoked with $skill-name [arguments] or /skill-name [arguments]
|
|
41389
|
+
|
|
41390
|
+
`;
|
|
41391
|
+
if (context.skills.length === 0) {
|
|
41392
|
+
message += `No skills loaded.
|
|
41393
|
+
`;
|
|
41394
|
+
message += `
|
|
41395
|
+
Add skills to ~/.assistants/assistants-shared/skills/ or .assistants/skills/
|
|
40545
41396
|
`;
|
|
40546
41397
|
} else {
|
|
40547
41398
|
for (const skill of context.skills) {
|
|
@@ -40562,7 +41413,7 @@ ${context.skills.length} skill(s) available.
|
|
|
40562
41413
|
statusCommand() {
|
|
40563
41414
|
return {
|
|
40564
41415
|
name: "status",
|
|
40565
|
-
description: "Show current session status and token usage",
|
|
41416
|
+
description: "Show current session status, energy, identity, and token usage",
|
|
40566
41417
|
builtin: true,
|
|
40567
41418
|
selfHandled: true,
|
|
40568
41419
|
content: "",
|
|
@@ -40572,11 +41423,46 @@ ${context.skills.length} skill(s) available.
|
|
|
40572
41423
|
let message = `
|
|
40573
41424
|
**Session Status**
|
|
40574
41425
|
|
|
41426
|
+
`;
|
|
41427
|
+
message += `**Session ID:** ${context.sessionId}
|
|
40575
41428
|
`;
|
|
40576
41429
|
message += `**Working Directory:** ${context.cwd}
|
|
40577
41430
|
`;
|
|
40578
|
-
|
|
41431
|
+
const assistant = context.getAssistantManager?.()?.getActive();
|
|
41432
|
+
const identity = context.getIdentityManager?.()?.getActive();
|
|
41433
|
+
if (assistant) {
|
|
41434
|
+
message += `**Assistant:** ${assistant.name}`;
|
|
41435
|
+
if (identity) {
|
|
41436
|
+
message += ` \xB7 ${identity.name}`;
|
|
41437
|
+
}
|
|
41438
|
+
message += `
|
|
41439
|
+
`;
|
|
41440
|
+
}
|
|
41441
|
+
const energyState = context.getEnergyState?.();
|
|
41442
|
+
if (energyState) {
|
|
41443
|
+
const energyPercent = Math.round(energyState.current / Math.max(1, energyState.max) * 100);
|
|
41444
|
+
const energyBar = "\u2588".repeat(Math.round(energyPercent / 10)) + "\u2591".repeat(10 - Math.round(energyPercent / 10));
|
|
41445
|
+
const energyEmoji = energyPercent > 70 ? "\u26A1" : energyPercent > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
|
|
41446
|
+
message += `**Energy:** ${energyEmoji} [${energyBar}] ${energyPercent}% (${energyState.current}/${energyState.max})
|
|
41447
|
+
`;
|
|
41448
|
+
}
|
|
41449
|
+
const voiceState = context.getVoiceState?.();
|
|
41450
|
+
if (voiceState?.enabled) {
|
|
41451
|
+
const voiceActivity = voiceState.isSpeaking ? "speaking" : voiceState.isListening ? "listening" : "idle";
|
|
41452
|
+
message += `**Voice:** ${voiceActivity}`;
|
|
41453
|
+
if (voiceState.sttProvider || voiceState.ttsProvider) {
|
|
41454
|
+
message += ` (STT: ${voiceState.sttProvider || "n/a"}, TTS: ${voiceState.ttsProvider || "n/a"})`;
|
|
41455
|
+
}
|
|
41456
|
+
message += `
|
|
41457
|
+
`;
|
|
41458
|
+
}
|
|
41459
|
+
if (context.getActiveProjectId) {
|
|
41460
|
+
const projectId = context.getActiveProjectId();
|
|
41461
|
+
if (projectId) {
|
|
41462
|
+
message += `**Active Project:** ${projectId}
|
|
40579
41463
|
`;
|
|
41464
|
+
}
|
|
41465
|
+
}
|
|
40580
41466
|
message += `**Messages:** ${context.messages.length}
|
|
40581
41467
|
`;
|
|
40582
41468
|
message += `**Available Tools:** ${context.tools.length}
|
|
@@ -40663,9 +41549,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40663
41549
|
content: "",
|
|
40664
41550
|
handler: async (args, context) => {
|
|
40665
41551
|
const configPaths = [
|
|
40666
|
-
|
|
40667
|
-
|
|
40668
|
-
|
|
41552
|
+
join11(context.cwd, ".assistants", "config.json"),
|
|
41553
|
+
join11(context.cwd, ".assistants", "config.local.json"),
|
|
41554
|
+
join11(getConfigDir(), "config.json")
|
|
40669
41555
|
];
|
|
40670
41556
|
let message = `
|
|
40671
41557
|
**Configuration**
|
|
@@ -40683,9 +41569,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40683
41569
|
message += `
|
|
40684
41570
|
**Commands Directories:**
|
|
40685
41571
|
`;
|
|
40686
|
-
message += ` - Project: ${
|
|
41572
|
+
message += ` - Project: ${join11(context.cwd, ".assistants", "commands")}
|
|
40687
41573
|
`;
|
|
40688
|
-
message += ` - Global: ${
|
|
41574
|
+
message += ` - Global: ${join11(homeDir, ".assistants", "commands")}
|
|
40689
41575
|
`;
|
|
40690
41576
|
context.emit("text", message);
|
|
40691
41577
|
context.emit("done");
|
|
@@ -40701,7 +41587,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
|
|
|
40701
41587
|
selfHandled: true,
|
|
40702
41588
|
content: "",
|
|
40703
41589
|
handler: async (args, context) => {
|
|
40704
|
-
const commandsDir =
|
|
41590
|
+
const commandsDir = join11(context.cwd, ".assistants", "commands");
|
|
40705
41591
|
mkdirSync2(commandsDir, { recursive: true });
|
|
40706
41592
|
const exampleCommand = `---
|
|
40707
41593
|
name: reflect
|
|
@@ -40717,7 +41603,7 @@ Please summarize the last interaction and suggest 2-3 next steps.
|
|
|
40717
41603
|
- Focus on clarity
|
|
40718
41604
|
- Ask a follow-up question if needed
|
|
40719
41605
|
`;
|
|
40720
|
-
const examplePath =
|
|
41606
|
+
const examplePath = join11(commandsDir, "reflect.md");
|
|
40721
41607
|
if (!existsSync6(examplePath)) {
|
|
40722
41608
|
writeFileSync3(examplePath, exampleCommand);
|
|
40723
41609
|
}
|
|
@@ -41038,8 +41924,8 @@ Connector "${connectorName}" not found.
|
|
|
41038
41924
|
`;
|
|
41039
41925
|
try {
|
|
41040
41926
|
let timeoutId = null;
|
|
41041
|
-
const timeoutPromise = new Promise((
|
|
41042
|
-
timeoutId = setTimeout(resolveAuthTimeout, 1000,
|
|
41927
|
+
const timeoutPromise = new Promise((resolve5) => {
|
|
41928
|
+
timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
|
|
41043
41929
|
});
|
|
41044
41930
|
const result = await Promise.race([
|
|
41045
41931
|
Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
|
|
@@ -41101,8 +41987,8 @@ Connector "${connectorName}" not found.
|
|
|
41101
41987
|
let status = "\u25CB";
|
|
41102
41988
|
let timeoutId = null;
|
|
41103
41989
|
try {
|
|
41104
|
-
const timeoutPromise = new Promise((
|
|
41105
|
-
timeoutId = setTimeout(resolveAuthTimeout, 1000,
|
|
41990
|
+
const timeoutPromise = new Promise((resolve5) => {
|
|
41991
|
+
timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
|
|
41106
41992
|
});
|
|
41107
41993
|
const result = await Promise.race([
|
|
41108
41994
|
Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
|
|
@@ -41377,6 +42263,35 @@ ${repoUrl}/issues/new
|
|
|
41377
42263
|
}
|
|
41378
42264
|
};
|
|
41379
42265
|
}
|
|
42266
|
+
async resolveProject(context, target) {
|
|
42267
|
+
const byId = await readProject(context.cwd, target);
|
|
42268
|
+
if (byId)
|
|
42269
|
+
return byId;
|
|
42270
|
+
return findProjectByName(context.cwd, target);
|
|
42271
|
+
}
|
|
42272
|
+
async ensureActiveProject(context, createIfMissing) {
|
|
42273
|
+
const activeId = context.getActiveProjectId?.();
|
|
42274
|
+
if (activeId) {
|
|
42275
|
+
const project2 = await readProject(context.cwd, activeId);
|
|
42276
|
+
if (project2)
|
|
42277
|
+
return project2;
|
|
42278
|
+
}
|
|
42279
|
+
if (!createIfMissing)
|
|
42280
|
+
return null;
|
|
42281
|
+
const project = await ensureDefaultProject(context.cwd);
|
|
42282
|
+
context.setActiveProjectId?.(project.id);
|
|
42283
|
+
await this.applyProjectContext(context, project);
|
|
42284
|
+
return project;
|
|
42285
|
+
}
|
|
42286
|
+
async applyProjectContext(context, project) {
|
|
42287
|
+
if (!context.setProjectContext)
|
|
42288
|
+
return;
|
|
42289
|
+
const projectContext = await buildProjectContext(project, {
|
|
42290
|
+
cwd: context.cwd,
|
|
42291
|
+
connectors: context.connectors
|
|
42292
|
+
});
|
|
42293
|
+
context.setProjectContext(projectContext);
|
|
42294
|
+
}
|
|
41380
42295
|
}
|
|
41381
42296
|
// packages/core/src/llm/client.ts
|
|
41382
42297
|
async function createLLMClient(config) {
|
|
@@ -41390,7 +42305,7 @@ async function createLLMClient(config) {
|
|
|
41390
42305
|
// packages/core/src/heartbeat/manager.ts
|
|
41391
42306
|
import { dirname as dirname5 } from "path";
|
|
41392
42307
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
41393
|
-
import { readFile as
|
|
42308
|
+
import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
41394
42309
|
|
|
41395
42310
|
class HeartbeatManager {
|
|
41396
42311
|
config;
|
|
@@ -41469,12 +42384,12 @@ class HeartbeatManager {
|
|
|
41469
42384
|
}
|
|
41470
42385
|
async persist(heartbeat) {
|
|
41471
42386
|
try {
|
|
41472
|
-
await
|
|
42387
|
+
await writeFile3(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
|
|
41473
42388
|
} catch {}
|
|
41474
42389
|
}
|
|
41475
42390
|
static async checkStale(path2, thresholdMs) {
|
|
41476
42391
|
try {
|
|
41477
|
-
const content = await
|
|
42392
|
+
const content = await readFile4(path2, "utf-8");
|
|
41478
42393
|
const heartbeat = JSON.parse(content);
|
|
41479
42394
|
const age = Date.now() - new Date(heartbeat.timestamp).getTime();
|
|
41480
42395
|
return { isStale: age > thresholdMs, lastHeartbeat: heartbeat };
|
|
@@ -41486,7 +42401,7 @@ class HeartbeatManager {
|
|
|
41486
42401
|
// packages/core/src/heartbeat/persistence.ts
|
|
41487
42402
|
import { dirname as dirname6 } from "path";
|
|
41488
42403
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
41489
|
-
import { readFile as
|
|
42404
|
+
import { readFile as readFile5, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
41490
42405
|
|
|
41491
42406
|
class StatePersistence {
|
|
41492
42407
|
path;
|
|
@@ -41496,12 +42411,12 @@ class StatePersistence {
|
|
|
41496
42411
|
}
|
|
41497
42412
|
async save(state) {
|
|
41498
42413
|
try {
|
|
41499
|
-
await
|
|
42414
|
+
await writeFile4(this.path, JSON.stringify(state, null, 2));
|
|
41500
42415
|
} catch {}
|
|
41501
42416
|
}
|
|
41502
42417
|
async load() {
|
|
41503
42418
|
try {
|
|
41504
|
-
const content = await
|
|
42419
|
+
const content = await readFile5(this.path, "utf-8");
|
|
41505
42420
|
return JSON.parse(content);
|
|
41506
42421
|
} catch {
|
|
41507
42422
|
return null;
|
|
@@ -41509,7 +42424,7 @@ class StatePersistence {
|
|
|
41509
42424
|
}
|
|
41510
42425
|
async clear() {
|
|
41511
42426
|
try {
|
|
41512
|
-
await
|
|
42427
|
+
await unlink3(this.path);
|
|
41513
42428
|
} catch {}
|
|
41514
42429
|
}
|
|
41515
42430
|
}
|
|
@@ -41713,7 +42628,7 @@ class EnergyManager {
|
|
|
41713
42628
|
// packages/core/src/energy/storage.ts
|
|
41714
42629
|
import { dirname as dirname7 } from "path";
|
|
41715
42630
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
41716
|
-
import { readFile as
|
|
42631
|
+
import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
41717
42632
|
|
|
41718
42633
|
class EnergyStorage {
|
|
41719
42634
|
path;
|
|
@@ -41723,12 +42638,12 @@ class EnergyStorage {
|
|
|
41723
42638
|
}
|
|
41724
42639
|
async save(state) {
|
|
41725
42640
|
try {
|
|
41726
|
-
await
|
|
42641
|
+
await writeFile5(this.path, JSON.stringify(state, null, 2));
|
|
41727
42642
|
} catch {}
|
|
41728
42643
|
}
|
|
41729
42644
|
async load() {
|
|
41730
42645
|
try {
|
|
41731
|
-
const content = await
|
|
42646
|
+
const content = await readFile6(this.path, "utf-8");
|
|
41732
42647
|
return JSON.parse(content);
|
|
41733
42648
|
} catch {
|
|
41734
42649
|
return null;
|
|
@@ -41788,12 +42703,12 @@ function validateToolCalls(toolCalls, tools) {
|
|
|
41788
42703
|
// packages/core/src/voice/utils.ts
|
|
41789
42704
|
import { existsSync as existsSync8, readFileSync as readFileSync3 } from "fs";
|
|
41790
42705
|
import { homedir as homedir9 } from "os";
|
|
41791
|
-
import { join as
|
|
42706
|
+
import { join as join13 } from "path";
|
|
41792
42707
|
import { spawnSync } from "child_process";
|
|
41793
42708
|
function loadApiKeyFromSecrets2(key) {
|
|
41794
42709
|
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
41795
42710
|
const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
|
|
41796
|
-
const secretsPath =
|
|
42711
|
+
const secretsPath = join13(homeDir, ".secrets");
|
|
41797
42712
|
if (!existsSync8(secretsPath))
|
|
41798
42713
|
return;
|
|
41799
42714
|
try {
|
|
@@ -41867,7 +42782,7 @@ class SystemSTT {
|
|
|
41867
42782
|
// packages/core/src/voice/tts.ts
|
|
41868
42783
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
41869
42784
|
import { tmpdir as tmpdir2 } from "os";
|
|
41870
|
-
import { join as
|
|
42785
|
+
import { join as join14 } from "path";
|
|
41871
42786
|
import { readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
|
|
41872
42787
|
class ElevenLabsTTS {
|
|
41873
42788
|
apiKey;
|
|
@@ -41971,7 +42886,7 @@ class SystemTTS {
|
|
|
41971
42886
|
if (!say) {
|
|
41972
42887
|
throw new Error('System TTS not available: missing "say" command.');
|
|
41973
42888
|
}
|
|
41974
|
-
const output =
|
|
42889
|
+
const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
|
|
41975
42890
|
const args = [];
|
|
41976
42891
|
if (this.voiceId) {
|
|
41977
42892
|
args.push("-v", this.voiceId);
|
|
@@ -41993,7 +42908,7 @@ class SystemTTS {
|
|
|
41993
42908
|
}
|
|
41994
42909
|
const espeak = findExecutable("espeak") || findExecutable("espeak-ng");
|
|
41995
42910
|
if (espeak) {
|
|
41996
|
-
const output =
|
|
42911
|
+
const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
|
|
41997
42912
|
const args = ["-w", output];
|
|
41998
42913
|
if (this.voiceId) {
|
|
41999
42914
|
args.push("-v", this.voiceId);
|
|
@@ -42020,32 +42935,32 @@ class SystemTTS {
|
|
|
42020
42935
|
// packages/core/src/voice/player.ts
|
|
42021
42936
|
import { spawn } from "child_process";
|
|
42022
42937
|
import { tmpdir as tmpdir3 } from "os";
|
|
42023
|
-
import { join as
|
|
42024
|
-
import { unlink as
|
|
42938
|
+
import { join as join15 } from "path";
|
|
42939
|
+
import { unlink as unlink4, writeFileSync as writeFileSync4 } from "fs";
|
|
42025
42940
|
class AudioPlayer {
|
|
42026
42941
|
currentProcess = null;
|
|
42027
42942
|
playing = false;
|
|
42028
42943
|
async play(audio, options = {}) {
|
|
42029
42944
|
const format = options.format ?? "mp3";
|
|
42030
|
-
const tempFile =
|
|
42945
|
+
const tempFile = join15(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
|
|
42031
42946
|
writeFileSync4(tempFile, Buffer.from(audio));
|
|
42032
42947
|
const player = this.resolvePlayer(format);
|
|
42033
42948
|
if (!player) {
|
|
42034
42949
|
throw new Error("No supported audio player found. Install afplay, ffplay, mpg123, or aplay.");
|
|
42035
42950
|
}
|
|
42036
|
-
await new Promise((
|
|
42951
|
+
await new Promise((resolve5, reject) => {
|
|
42037
42952
|
this.playing = true;
|
|
42038
42953
|
this.currentProcess = spawn(player.command, [...player.args, tempFile], { stdio: "ignore" });
|
|
42039
42954
|
this.currentProcess.on("close", () => {
|
|
42040
42955
|
this.playing = false;
|
|
42041
42956
|
this.currentProcess = null;
|
|
42042
|
-
|
|
42043
|
-
|
|
42957
|
+
unlink4(tempFile, () => {});
|
|
42958
|
+
resolve5();
|
|
42044
42959
|
});
|
|
42045
42960
|
this.currentProcess.on("error", (error) => {
|
|
42046
42961
|
this.playing = false;
|
|
42047
42962
|
this.currentProcess = null;
|
|
42048
|
-
|
|
42963
|
+
unlink4(tempFile, () => {});
|
|
42049
42964
|
reject(error);
|
|
42050
42965
|
});
|
|
42051
42966
|
});
|
|
@@ -42095,8 +43010,8 @@ class AudioPlayer {
|
|
|
42095
43010
|
// packages/core/src/voice/recorder.ts
|
|
42096
43011
|
import { spawn as spawn2 } from "child_process";
|
|
42097
43012
|
import { tmpdir as tmpdir4 } from "os";
|
|
42098
|
-
import { join as
|
|
42099
|
-
import { readFileSync as readFileSync5, unlink as
|
|
43013
|
+
import { join as join16 } from "path";
|
|
43014
|
+
import { readFileSync as readFileSync5, unlink as unlink5 } from "fs";
|
|
42100
43015
|
class AudioRecorder {
|
|
42101
43016
|
currentProcess = null;
|
|
42102
43017
|
async record(options = {}) {
|
|
@@ -42106,17 +43021,17 @@ class AudioRecorder {
|
|
|
42106
43021
|
const duration = options.durationSeconds ?? 5;
|
|
42107
43022
|
const sampleRate = options.sampleRate ?? 16000;
|
|
42108
43023
|
const channels = options.channels ?? 1;
|
|
42109
|
-
const output =
|
|
43024
|
+
const output = join16(tmpdir4(), `assistants-record-${Date.now()}.wav`);
|
|
42110
43025
|
const recorder = this.resolveRecorder(sampleRate, channels, duration, output);
|
|
42111
43026
|
if (!recorder) {
|
|
42112
43027
|
throw new Error("No supported audio recorder found. Install sox or ffmpeg.");
|
|
42113
43028
|
}
|
|
42114
|
-
await new Promise((
|
|
43029
|
+
await new Promise((resolve5, reject) => {
|
|
42115
43030
|
this.currentProcess = spawn2(recorder.command, recorder.args, { stdio: "ignore" });
|
|
42116
43031
|
this.currentProcess.on("close", (code) => {
|
|
42117
43032
|
this.currentProcess = null;
|
|
42118
43033
|
if (code === 0) {
|
|
42119
|
-
|
|
43034
|
+
resolve5();
|
|
42120
43035
|
} else {
|
|
42121
43036
|
reject(new Error("Audio recording failed."));
|
|
42122
43037
|
}
|
|
@@ -42127,7 +43042,7 @@ class AudioRecorder {
|
|
|
42127
43042
|
});
|
|
42128
43043
|
});
|
|
42129
43044
|
const data = readFileSync5(output);
|
|
42130
|
-
|
|
43045
|
+
unlink5(output, () => {});
|
|
42131
43046
|
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
42132
43047
|
}
|
|
42133
43048
|
stop() {
|
|
@@ -42299,14 +43214,14 @@ class VoiceManager {
|
|
|
42299
43214
|
// packages/core/src/identity/assistant-manager.ts
|
|
42300
43215
|
init_src();
|
|
42301
43216
|
import { existsSync as existsSync10 } from "fs";
|
|
42302
|
-
import { mkdir as
|
|
42303
|
-
import { join as
|
|
43217
|
+
import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile7, rm as rm2 } from "fs/promises";
|
|
43218
|
+
import { join as join18 } from "path";
|
|
42304
43219
|
|
|
42305
43220
|
// packages/core/src/identity/identity-manager.ts
|
|
42306
43221
|
init_src();
|
|
42307
43222
|
import { existsSync as existsSync9 } from "fs";
|
|
42308
|
-
import { mkdir as
|
|
42309
|
-
import { join as
|
|
43223
|
+
import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile6, rm } from "fs/promises";
|
|
43224
|
+
import { join as join17 } from "path";
|
|
42310
43225
|
var DEFAULT_PROFILE = {
|
|
42311
43226
|
displayName: "Assistant",
|
|
42312
43227
|
timezone: "UTC",
|
|
@@ -42336,22 +43251,22 @@ class IdentityManager {
|
|
|
42336
43251
|
this.basePath = basePath;
|
|
42337
43252
|
}
|
|
42338
43253
|
get identitiesRoot() {
|
|
42339
|
-
return
|
|
43254
|
+
return join17(this.basePath, "assistants", this.assistantId, "identities");
|
|
42340
43255
|
}
|
|
42341
43256
|
get indexPath() {
|
|
42342
|
-
return
|
|
43257
|
+
return join17(this.identitiesRoot, "index.json");
|
|
42343
43258
|
}
|
|
42344
43259
|
get activePath() {
|
|
42345
|
-
return
|
|
43260
|
+
return join17(this.identitiesRoot, "active.json");
|
|
42346
43261
|
}
|
|
42347
43262
|
identityPath(id) {
|
|
42348
|
-
return
|
|
43263
|
+
return join17(this.identitiesRoot, `${id}.json`);
|
|
42349
43264
|
}
|
|
42350
43265
|
assistantConfigPath() {
|
|
42351
|
-
return
|
|
43266
|
+
return join17(this.basePath, "assistants", this.assistantId, "config.json");
|
|
42352
43267
|
}
|
|
42353
43268
|
async initialize() {
|
|
42354
|
-
await
|
|
43269
|
+
await mkdir4(this.identitiesRoot, { recursive: true });
|
|
42355
43270
|
const index = await this.readIndex();
|
|
42356
43271
|
for (const id of index.identities) {
|
|
42357
43272
|
const identity = await this.readIdentity(id);
|
|
@@ -42458,7 +43373,7 @@ class IdentityManager {
|
|
|
42458
43373
|
return { identities: [] };
|
|
42459
43374
|
}
|
|
42460
43375
|
try {
|
|
42461
|
-
const raw = await
|
|
43376
|
+
const raw = await readFile7(this.indexPath, "utf-8");
|
|
42462
43377
|
const data = JSON.parse(raw);
|
|
42463
43378
|
return { identities: Array.isArray(data.identities) ? data.identities : [] };
|
|
42464
43379
|
} catch {
|
|
@@ -42470,33 +43385,33 @@ class IdentityManager {
|
|
|
42470
43385
|
if (!index.identities.includes(id)) {
|
|
42471
43386
|
index.identities.push(id);
|
|
42472
43387
|
}
|
|
42473
|
-
await
|
|
43388
|
+
await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
|
|
42474
43389
|
}
|
|
42475
43390
|
async removeFromIndex(id) {
|
|
42476
43391
|
const index = await this.readIndex();
|
|
42477
43392
|
index.identities = index.identities.filter((identityId) => identityId !== id);
|
|
42478
|
-
await
|
|
43393
|
+
await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
|
|
42479
43394
|
}
|
|
42480
43395
|
async readIdentity(id) {
|
|
42481
43396
|
const path2 = this.identityPath(id);
|
|
42482
43397
|
if (!existsSync9(path2))
|
|
42483
43398
|
return null;
|
|
42484
43399
|
try {
|
|
42485
|
-
const raw = await
|
|
43400
|
+
const raw = await readFile7(path2, "utf-8");
|
|
42486
43401
|
return JSON.parse(raw);
|
|
42487
43402
|
} catch {
|
|
42488
43403
|
return null;
|
|
42489
43404
|
}
|
|
42490
43405
|
}
|
|
42491
43406
|
async persistIdentity(identity) {
|
|
42492
|
-
await
|
|
42493
|
-
await
|
|
43407
|
+
await mkdir4(this.identitiesRoot, { recursive: true });
|
|
43408
|
+
await writeFile6(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
|
|
42494
43409
|
}
|
|
42495
43410
|
async readActive() {
|
|
42496
43411
|
if (!existsSync9(this.activePath))
|
|
42497
43412
|
return null;
|
|
42498
43413
|
try {
|
|
42499
|
-
const raw = await
|
|
43414
|
+
const raw = await readFile7(this.activePath, "utf-8");
|
|
42500
43415
|
const data = JSON.parse(raw);
|
|
42501
43416
|
return data.id || null;
|
|
42502
43417
|
} catch {
|
|
@@ -42505,13 +43420,13 @@ class IdentityManager {
|
|
|
42505
43420
|
}
|
|
42506
43421
|
async setActive(id) {
|
|
42507
43422
|
this.activeId = id;
|
|
42508
|
-
await
|
|
43423
|
+
await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
|
|
42509
43424
|
}
|
|
42510
43425
|
async loadAssistant() {
|
|
42511
43426
|
if (!existsSync9(this.assistantConfigPath()))
|
|
42512
43427
|
return null;
|
|
42513
43428
|
try {
|
|
42514
|
-
const raw = await
|
|
43429
|
+
const raw = await readFile7(this.assistantConfigPath(), "utf-8");
|
|
42515
43430
|
return JSON.parse(raw);
|
|
42516
43431
|
} catch {
|
|
42517
43432
|
return null;
|
|
@@ -42532,19 +43447,19 @@ class AssistantManager {
|
|
|
42532
43447
|
this.basePath = basePath;
|
|
42533
43448
|
}
|
|
42534
43449
|
get assistantsRoot() {
|
|
42535
|
-
return
|
|
43450
|
+
return join18(this.basePath, "assistants");
|
|
42536
43451
|
}
|
|
42537
43452
|
get indexPath() {
|
|
42538
|
-
return
|
|
43453
|
+
return join18(this.assistantsRoot, "index.json");
|
|
42539
43454
|
}
|
|
42540
43455
|
get activePath() {
|
|
42541
|
-
return
|
|
43456
|
+
return join18(this.basePath, "active.json");
|
|
42542
43457
|
}
|
|
42543
43458
|
assistantConfigPath(id) {
|
|
42544
|
-
return
|
|
43459
|
+
return join18(this.assistantsRoot, id, "config.json");
|
|
42545
43460
|
}
|
|
42546
43461
|
async initialize() {
|
|
42547
|
-
await
|
|
43462
|
+
await mkdir5(this.assistantsRoot, { recursive: true });
|
|
42548
43463
|
const index = await this.readIndex();
|
|
42549
43464
|
for (const id of index.assistants) {
|
|
42550
43465
|
const assistant = await this.readAssistant(id);
|
|
@@ -42595,7 +43510,7 @@ class AssistantManager {
|
|
|
42595
43510
|
if (!this.assistants.has(id)) {
|
|
42596
43511
|
throw new Error(`Assistant ${id} not found`);
|
|
42597
43512
|
}
|
|
42598
|
-
await rm2(
|
|
43513
|
+
await rm2(join18(this.assistantsRoot, id), { recursive: true, force: true });
|
|
42599
43514
|
this.assistants.delete(id);
|
|
42600
43515
|
await this.removeFromIndex(id);
|
|
42601
43516
|
if (this.activeId === id) {
|
|
@@ -42630,7 +43545,7 @@ class AssistantManager {
|
|
|
42630
43545
|
return { assistants: [] };
|
|
42631
43546
|
}
|
|
42632
43547
|
try {
|
|
42633
|
-
const raw = await
|
|
43548
|
+
const raw = await readFile8(this.indexPath, "utf-8");
|
|
42634
43549
|
const data = JSON.parse(raw);
|
|
42635
43550
|
return { assistants: Array.isArray(data.assistants) ? data.assistants : [] };
|
|
42636
43551
|
} catch {
|
|
@@ -42642,34 +43557,34 @@ class AssistantManager {
|
|
|
42642
43557
|
if (!index.assistants.includes(id)) {
|
|
42643
43558
|
index.assistants.push(id);
|
|
42644
43559
|
}
|
|
42645
|
-
await
|
|
43560
|
+
await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
|
|
42646
43561
|
}
|
|
42647
43562
|
async removeFromIndex(id) {
|
|
42648
43563
|
const index = await this.readIndex();
|
|
42649
43564
|
index.assistants = index.assistants.filter((assistantId) => assistantId !== id);
|
|
42650
|
-
await
|
|
43565
|
+
await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
|
|
42651
43566
|
}
|
|
42652
43567
|
async readAssistant(id) {
|
|
42653
43568
|
const configPath = this.assistantConfigPath(id);
|
|
42654
43569
|
if (!existsSync10(configPath))
|
|
42655
43570
|
return null;
|
|
42656
43571
|
try {
|
|
42657
|
-
const raw = await
|
|
43572
|
+
const raw = await readFile8(configPath, "utf-8");
|
|
42658
43573
|
return JSON.parse(raw);
|
|
42659
43574
|
} catch {
|
|
42660
43575
|
return null;
|
|
42661
43576
|
}
|
|
42662
43577
|
}
|
|
42663
43578
|
async persistAssistant(assistant) {
|
|
42664
|
-
const dir =
|
|
42665
|
-
await
|
|
42666
|
-
await
|
|
43579
|
+
const dir = join18(this.assistantsRoot, assistant.id);
|
|
43580
|
+
await mkdir5(dir, { recursive: true });
|
|
43581
|
+
await writeFile7(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
|
|
42667
43582
|
}
|
|
42668
43583
|
async readActive() {
|
|
42669
43584
|
if (!existsSync10(this.activePath))
|
|
42670
43585
|
return null;
|
|
42671
43586
|
try {
|
|
42672
|
-
const raw = await
|
|
43587
|
+
const raw = await readFile8(this.activePath, "utf-8");
|
|
42673
43588
|
const data = JSON.parse(raw);
|
|
42674
43589
|
return data.id || null;
|
|
42675
43590
|
} catch {
|
|
@@ -42678,7 +43593,7 @@ class AssistantManager {
|
|
|
42678
43593
|
}
|
|
42679
43594
|
async setActive(id) {
|
|
42680
43595
|
this.activeId = id;
|
|
42681
|
-
await
|
|
43596
|
+
await writeFile7(this.activePath, JSON.stringify({ id }, null, 2));
|
|
42682
43597
|
}
|
|
42683
43598
|
}
|
|
42684
43599
|
// packages/core/src/agent/loop.ts
|
|
@@ -42723,6 +43638,8 @@ class AgentLoop {
|
|
|
42723
43638
|
assistantManager = null;
|
|
42724
43639
|
identityManager = null;
|
|
42725
43640
|
identityContext = null;
|
|
43641
|
+
projectContext = null;
|
|
43642
|
+
activeProjectId = null;
|
|
42726
43643
|
assistantId = null;
|
|
42727
43644
|
onChunk;
|
|
42728
43645
|
onToolStart;
|
|
@@ -42735,7 +43652,7 @@ class AgentLoop {
|
|
|
42735
43652
|
this.context = new AgentContext;
|
|
42736
43653
|
this.toolRegistry = new ToolRegistry;
|
|
42737
43654
|
this.toolRegistry.setErrorAggregator(this.errorAggregator);
|
|
42738
|
-
this.connectorBridge = new ConnectorBridge;
|
|
43655
|
+
this.connectorBridge = new ConnectorBridge(this.cwd);
|
|
42739
43656
|
this.skillLoader = new SkillLoader;
|
|
42740
43657
|
this.skillExecutor = new SkillExecutor;
|
|
42741
43658
|
this.hookLoader = new HookLoader;
|
|
@@ -43038,15 +43955,13 @@ class AgentLoop {
|
|
|
43038
43955
|
});
|
|
43039
43956
|
if (preHookResult?.updatedInput) {
|
|
43040
43957
|
toolCall.input = { ...preHookResult.updatedInput };
|
|
43041
|
-
if (toolCall.input.cwd === undefined) {
|
|
43042
|
-
toolCall.input.cwd = this.cwd;
|
|
43043
|
-
}
|
|
43044
43958
|
}
|
|
43045
|
-
|
|
43046
|
-
|
|
43047
|
-
|
|
43048
|
-
|
|
43049
|
-
|
|
43959
|
+
const input = toolCall.input;
|
|
43960
|
+
if (input.cwd === undefined) {
|
|
43961
|
+
input.cwd = this.cwd;
|
|
43962
|
+
}
|
|
43963
|
+
if (input.sessionId === undefined) {
|
|
43964
|
+
input.sessionId = this.sessionId;
|
|
43050
43965
|
}
|
|
43051
43966
|
if (preHookResult?.continue === false || preHookResult?.permissionDecision === "deny") {
|
|
43052
43967
|
const blockedResult = {
|
|
@@ -43170,6 +44085,13 @@ class AgentLoop {
|
|
|
43170
44085
|
switchIdentity: async (identityId) => {
|
|
43171
44086
|
await this.switchIdentity(identityId);
|
|
43172
44087
|
},
|
|
44088
|
+
getActiveProjectId: () => this.activeProjectId,
|
|
44089
|
+
setActiveProjectId: (projectId) => {
|
|
44090
|
+
this.activeProjectId = projectId;
|
|
44091
|
+
},
|
|
44092
|
+
setProjectContext: (content) => {
|
|
44093
|
+
this.setProjectContext(content);
|
|
44094
|
+
},
|
|
43173
44095
|
getVoiceState: () => this.getVoiceState(),
|
|
43174
44096
|
enableVoice: () => {
|
|
43175
44097
|
if (!this.voiceManager) {
|
|
@@ -43357,6 +44279,22 @@ class AgentLoop {
|
|
|
43357
44279
|
getSessionId() {
|
|
43358
44280
|
return this.sessionId;
|
|
43359
44281
|
}
|
|
44282
|
+
getActiveProjectId() {
|
|
44283
|
+
return this.activeProjectId;
|
|
44284
|
+
}
|
|
44285
|
+
setActiveProjectId(projectId) {
|
|
44286
|
+
this.activeProjectId = projectId;
|
|
44287
|
+
}
|
|
44288
|
+
setProjectContext(content) {
|
|
44289
|
+
const tag = "[Project Context]";
|
|
44290
|
+
this.projectContext = content;
|
|
44291
|
+
this.context.removeSystemMessages((message) => message.startsWith(tag));
|
|
44292
|
+
if (content && content.trim()) {
|
|
44293
|
+
this.context.addSystemMessage(`${tag}
|
|
44294
|
+
${content.trim()}`);
|
|
44295
|
+
}
|
|
44296
|
+
this.contextManager?.refreshState(this.context.getMessages());
|
|
44297
|
+
}
|
|
43360
44298
|
clearConversation() {
|
|
43361
44299
|
this.resetContext();
|
|
43362
44300
|
}
|
|
@@ -43368,7 +44306,7 @@ class AgentLoop {
|
|
|
43368
44306
|
const heartbeatConfig = this.buildHeartbeatConfig(this.config);
|
|
43369
44307
|
if (!heartbeatConfig)
|
|
43370
44308
|
return;
|
|
43371
|
-
const statePath =
|
|
44309
|
+
const statePath = join19(getConfigDir(), "state", `${this.sessionId}.json`);
|
|
43372
44310
|
this.heartbeatManager = new HeartbeatManager(heartbeatConfig);
|
|
43373
44311
|
this.heartbeatPersistence = new StatePersistence(statePath);
|
|
43374
44312
|
this.heartbeatRecovery = new RecoveryManager(this.heartbeatPersistence, heartbeatConfig.persistPath, heartbeatConfig.staleThresholdMs, {
|
|
@@ -43417,7 +44355,7 @@ class AgentLoop {
|
|
|
43417
44355
|
async startEnergySystem() {
|
|
43418
44356
|
if (!this.config || this.config.energy?.enabled === false)
|
|
43419
44357
|
return;
|
|
43420
|
-
const statePath =
|
|
44358
|
+
const statePath = join19(getConfigDir(), "energy", "state.json");
|
|
43421
44359
|
this.energyManager = new EnergyManager(this.config.energy, new EnergyStorage(statePath));
|
|
43422
44360
|
await this.energyManager.initialize();
|
|
43423
44361
|
this.refreshEnergyEffects();
|
|
@@ -43446,7 +44384,7 @@ ${effects.message}
|
|
|
43446
44384
|
const delay = this.energyEffects?.processingDelayMs ?? 0;
|
|
43447
44385
|
if (delay <= 0)
|
|
43448
44386
|
return;
|
|
43449
|
-
await new Promise((
|
|
44387
|
+
await new Promise((resolve5) => setTimeout(resolve5, delay));
|
|
43450
44388
|
}
|
|
43451
44389
|
applyEnergyPersonality(systemPrompt) {
|
|
43452
44390
|
if (!systemPrompt)
|
|
@@ -43557,6 +44495,9 @@ ${effects.message}
|
|
|
43557
44495
|
if (this.extraSystemPrompt) {
|
|
43558
44496
|
this.context.addSystemMessage(this.extraSystemPrompt);
|
|
43559
44497
|
}
|
|
44498
|
+
if (this.projectContext) {
|
|
44499
|
+
this.setProjectContext(this.projectContext);
|
|
44500
|
+
}
|
|
43560
44501
|
this.contextManager?.refreshState(this.context.getMessages());
|
|
43561
44502
|
}
|
|
43562
44503
|
buildSystemPrompt(messages) {
|
|
@@ -43643,7 +44584,7 @@ ${this.identityContext}`);
|
|
|
43643
44584
|
return null;
|
|
43644
44585
|
const intervalMs = Math.max(1000, config.heartbeat?.intervalMs ?? 15000);
|
|
43645
44586
|
const staleThresholdMs = Math.max(intervalMs * 2, config.heartbeat?.staleThresholdMs ?? 120000);
|
|
43646
|
-
const persistPath = config.heartbeat?.persistPath ??
|
|
44587
|
+
const persistPath = config.heartbeat?.persistPath ?? join19(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
|
|
43647
44588
|
return {
|
|
43648
44589
|
intervalMs,
|
|
43649
44590
|
staleThresholdMs,
|
|
@@ -43735,17 +44676,17 @@ function parseErrorCode(message) {
|
|
|
43735
44676
|
init_src();
|
|
43736
44677
|
// packages/core/src/migration/migrate-to-assistants.ts
|
|
43737
44678
|
import { existsSync as existsSync11 } from "fs";
|
|
43738
|
-
import { mkdir as
|
|
43739
|
-
import { join as
|
|
44679
|
+
import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile8, rename, cp } from "fs/promises";
|
|
44680
|
+
import { join as join20 } from "path";
|
|
43740
44681
|
import { homedir as homedir10 } from "os";
|
|
43741
44682
|
var MIGRATION_MARKER = ".migrated-from-oldpal";
|
|
43742
44683
|
async function ensureDir(path2) {
|
|
43743
|
-
await
|
|
44684
|
+
await mkdir6(path2, { recursive: true });
|
|
43744
44685
|
}
|
|
43745
44686
|
async function copyIfExists(source, destination) {
|
|
43746
44687
|
if (!existsSync11(source))
|
|
43747
44688
|
return false;
|
|
43748
|
-
await ensureDir(
|
|
44689
|
+
await ensureDir(join20(destination, ".."));
|
|
43749
44690
|
await cp(source, destination, { recursive: true });
|
|
43750
44691
|
return true;
|
|
43751
44692
|
}
|
|
@@ -43753,7 +44694,7 @@ async function readJson(path2) {
|
|
|
43753
44694
|
if (!existsSync11(path2))
|
|
43754
44695
|
return null;
|
|
43755
44696
|
try {
|
|
43756
|
-
const raw = await
|
|
44697
|
+
const raw = await readFile9(path2, "utf-8");
|
|
43757
44698
|
return JSON.parse(raw);
|
|
43758
44699
|
} catch {
|
|
43759
44700
|
return null;
|
|
@@ -43766,14 +44707,14 @@ async function migrateFromOldpal() {
|
|
|
43766
44707
|
errors: []
|
|
43767
44708
|
};
|
|
43768
44709
|
const home = homedir10();
|
|
43769
|
-
const oldPath =
|
|
43770
|
-
const newPath =
|
|
44710
|
+
const oldPath = join20(home, ".oldpal");
|
|
44711
|
+
const newPath = join20(home, ".assistants");
|
|
43771
44712
|
if (!existsSync11(oldPath)) {
|
|
43772
44713
|
result.success = true;
|
|
43773
44714
|
return result;
|
|
43774
44715
|
}
|
|
43775
44716
|
if (existsSync11(newPath)) {
|
|
43776
|
-
const marker =
|
|
44717
|
+
const marker = join20(newPath, "migration", MIGRATION_MARKER);
|
|
43777
44718
|
if (existsSync11(marker)) {
|
|
43778
44719
|
result.success = true;
|
|
43779
44720
|
return result;
|
|
@@ -43783,31 +44724,31 @@ async function migrateFromOldpal() {
|
|
|
43783
44724
|
}
|
|
43784
44725
|
try {
|
|
43785
44726
|
await ensureDir(newPath);
|
|
43786
|
-
await ensureDir(
|
|
43787
|
-
await ensureDir(
|
|
43788
|
-
await ensureDir(
|
|
43789
|
-
await ensureDir(
|
|
43790
|
-
const config = await readJson(
|
|
44727
|
+
await ensureDir(join20(newPath, "assistants"));
|
|
44728
|
+
await ensureDir(join20(newPath, "shared", "skills"));
|
|
44729
|
+
await ensureDir(join20(newPath, "logs"));
|
|
44730
|
+
await ensureDir(join20(newPath, "migration"));
|
|
44731
|
+
const config = await readJson(join20(oldPath, "settings.json"));
|
|
43791
44732
|
if (config) {
|
|
43792
|
-
await
|
|
44733
|
+
await writeFile8(join20(newPath, "config.json"), JSON.stringify(config, null, 2));
|
|
43793
44734
|
result.migrated.push("config.json");
|
|
43794
44735
|
}
|
|
43795
|
-
if (await copyIfExists(
|
|
44736
|
+
if (await copyIfExists(join20(oldPath, "settings.local.json"), join20(newPath, "config.local.json"))) {
|
|
43796
44737
|
result.migrated.push("config.local.json");
|
|
43797
44738
|
}
|
|
43798
|
-
if (await copyIfExists(
|
|
44739
|
+
if (await copyIfExists(join20(oldPath, "hooks.json"), join20(newPath, "hooks.json"))) {
|
|
43799
44740
|
result.migrated.push("hooks.json");
|
|
43800
44741
|
}
|
|
43801
|
-
if (await copyIfExists(
|
|
44742
|
+
if (await copyIfExists(join20(oldPath, "commands"), join20(newPath, "commands"))) {
|
|
43802
44743
|
result.migrated.push("commands");
|
|
43803
44744
|
}
|
|
43804
|
-
if (await copyIfExists(
|
|
44745
|
+
if (await copyIfExists(join20(oldPath, "OLDPAL.md"), join20(newPath, "ASSISTANTS.md"))) {
|
|
43805
44746
|
result.migrated.push("ASSISTANTS.md");
|
|
43806
44747
|
}
|
|
43807
|
-
if (await copyIfExists(
|
|
44748
|
+
if (await copyIfExists(join20(oldPath, "skills"), join20(newPath, "shared", "skills"))) {
|
|
43808
44749
|
result.migrated.push("skills");
|
|
43809
44750
|
}
|
|
43810
|
-
if (await copyIfExists(
|
|
44751
|
+
if (await copyIfExists(join20(oldPath, "logs"), join20(newPath, "logs"))) {
|
|
43811
44752
|
result.migrated.push("logs");
|
|
43812
44753
|
}
|
|
43813
44754
|
const manager = new AssistantManager(newPath);
|
|
@@ -43822,10 +44763,10 @@ async function migrateFromOldpal() {
|
|
|
43822
44763
|
const identityManager = manager.getIdentityManager(assistant.id);
|
|
43823
44764
|
await identityManager.initialize();
|
|
43824
44765
|
await identityManager.createIdentity({ name: "Default" });
|
|
43825
|
-
if (await copyIfExists(
|
|
44766
|
+
if (await copyIfExists(join20(oldPath, "sessions"), join20(newPath, "assistants", assistant.id, "sessions"))) {
|
|
43826
44767
|
result.migrated.push("sessions");
|
|
43827
44768
|
}
|
|
43828
|
-
await
|
|
44769
|
+
await writeFile8(join20(newPath, "migration", MIGRATION_MARKER), JSON.stringify({ migratedAt: new Date().toISOString() }, null, 2));
|
|
43829
44770
|
const backupPath = `${oldPath}.backup`;
|
|
43830
44771
|
await rename(oldPath, backupPath);
|
|
43831
44772
|
result.backupPath = backupPath;
|
|
@@ -43843,17 +44784,17 @@ init_src();
|
|
|
43843
44784
|
|
|
43844
44785
|
// packages/core/src/logger.ts
|
|
43845
44786
|
import { existsSync as existsSync12, mkdirSync as mkdirSync6, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
43846
|
-
import { join as
|
|
44787
|
+
import { join as join21 } from "path";
|
|
43847
44788
|
class Logger {
|
|
43848
44789
|
logDir;
|
|
43849
44790
|
logFile;
|
|
43850
44791
|
sessionId;
|
|
43851
44792
|
constructor(sessionId, basePath) {
|
|
43852
44793
|
this.sessionId = sessionId;
|
|
43853
|
-
this.logDir =
|
|
44794
|
+
this.logDir = join21(basePath || getConfigDir(), "logs");
|
|
43854
44795
|
this.ensureDir(this.logDir);
|
|
43855
44796
|
const date = new Date().toISOString().split("T")[0];
|
|
43856
|
-
this.logFile =
|
|
44797
|
+
this.logFile = join21(this.logDir, `${date}.log`);
|
|
43857
44798
|
}
|
|
43858
44799
|
ensureDir(dir) {
|
|
43859
44800
|
if (!existsSync12(dir)) {
|
|
@@ -43897,9 +44838,9 @@ class SessionStorage {
|
|
|
43897
44838
|
constructor(sessionId, basePath, assistantId) {
|
|
43898
44839
|
this.sessionId = sessionId;
|
|
43899
44840
|
const root = basePath || getConfigDir();
|
|
43900
|
-
this.sessionsDir = assistantId ?
|
|
44841
|
+
this.sessionsDir = assistantId ? join21(root, "assistants", assistantId, "sessions") : join21(root, "sessions");
|
|
43901
44842
|
this.ensureDir(this.sessionsDir);
|
|
43902
|
-
this.sessionFile =
|
|
44843
|
+
this.sessionFile = join21(this.sessionsDir, `${sessionId}.json`);
|
|
43903
44844
|
}
|
|
43904
44845
|
ensureDir(dir) {
|
|
43905
44846
|
if (!existsSync12(dir)) {
|
|
@@ -43925,7 +44866,7 @@ class SessionStorage {
|
|
|
43925
44866
|
}
|
|
43926
44867
|
static getActiveAssistantId() {
|
|
43927
44868
|
try {
|
|
43928
|
-
const activePath =
|
|
44869
|
+
const activePath = join21(getConfigDir(), "active.json");
|
|
43929
44870
|
if (!existsSync12(activePath))
|
|
43930
44871
|
return null;
|
|
43931
44872
|
const raw = readFileSync6(activePath, "utf-8");
|
|
@@ -43939,12 +44880,12 @@ class SessionStorage {
|
|
|
43939
44880
|
const root = getConfigDir();
|
|
43940
44881
|
const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
|
|
43941
44882
|
if (resolvedId) {
|
|
43942
|
-
const assistantDir =
|
|
44883
|
+
const assistantDir = join21(root, "assistants", resolvedId, "sessions");
|
|
43943
44884
|
if (existsSync12(assistantDir)) {
|
|
43944
44885
|
return assistantDir;
|
|
43945
44886
|
}
|
|
43946
44887
|
}
|
|
43947
|
-
return
|
|
44888
|
+
return join21(root, "sessions");
|
|
43948
44889
|
}
|
|
43949
44890
|
static listSessions(assistantId) {
|
|
43950
44891
|
const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
|
|
@@ -43956,7 +44897,7 @@ class SessionStorage {
|
|
|
43956
44897
|
if (!file.endsWith(".json"))
|
|
43957
44898
|
continue;
|
|
43958
44899
|
try {
|
|
43959
|
-
const filePath =
|
|
44900
|
+
const filePath = join21(sessionsDir, file);
|
|
43960
44901
|
const stat = Bun.file(filePath);
|
|
43961
44902
|
const content = JSON.parse(readFileSync6(filePath, "utf-8"));
|
|
43962
44903
|
sessions.push({
|
|
@@ -43976,7 +44917,7 @@ class SessionStorage {
|
|
|
43976
44917
|
}
|
|
43977
44918
|
static loadSession(sessionId, assistantId) {
|
|
43978
44919
|
const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
|
|
43979
|
-
const sessionFile =
|
|
44920
|
+
const sessionFile = join21(sessionsDir, `${sessionId}.json`);
|
|
43980
44921
|
try {
|
|
43981
44922
|
if (!existsSync12(sessionFile))
|
|
43982
44923
|
return null;
|
|
@@ -43990,15 +44931,15 @@ function initAssistantsDir() {
|
|
|
43990
44931
|
const baseDir = getConfigDir();
|
|
43991
44932
|
const dirs = [
|
|
43992
44933
|
baseDir,
|
|
43993
|
-
|
|
43994
|
-
|
|
43995
|
-
|
|
43996
|
-
|
|
43997
|
-
|
|
43998
|
-
|
|
43999
|
-
|
|
44000
|
-
|
|
44001
|
-
|
|
44934
|
+
join21(baseDir, "logs"),
|
|
44935
|
+
join21(baseDir, "assistants"),
|
|
44936
|
+
join21(baseDir, "shared", "skills"),
|
|
44937
|
+
join21(baseDir, "commands"),
|
|
44938
|
+
join21(baseDir, "temp"),
|
|
44939
|
+
join21(baseDir, "heartbeats"),
|
|
44940
|
+
join21(baseDir, "state"),
|
|
44941
|
+
join21(baseDir, "energy"),
|
|
44942
|
+
join21(baseDir, "migration")
|
|
44002
44943
|
];
|
|
44003
44944
|
for (const dir of dirs) {
|
|
44004
44945
|
if (!existsSync12(dir)) {
|
|
@@ -44041,6 +44982,11 @@ class EmbeddedClient {
|
|
|
44041
44982
|
for (const callback of this.chunkCallbacks) {
|
|
44042
44983
|
callback(chunk);
|
|
44043
44984
|
}
|
|
44985
|
+
if (chunk.type === "done" || chunk.type === "error") {
|
|
44986
|
+
queueMicrotask(() => {
|
|
44987
|
+
this.drainQueue();
|
|
44988
|
+
});
|
|
44989
|
+
}
|
|
44044
44990
|
},
|
|
44045
44991
|
onToolStart: (toolCall) => {
|
|
44046
44992
|
this.logger.info("Tool started", { tool: toolCall.name, input: toolCall.input });
|
|
@@ -44083,12 +45029,11 @@ class EmbeddedClient {
|
|
|
44083
45029
|
if (!this.initialized) {
|
|
44084
45030
|
await this.initialize();
|
|
44085
45031
|
}
|
|
44086
|
-
|
|
44087
|
-
|
|
44088
|
-
this.
|
|
45032
|
+
this.messageQueue.push(message);
|
|
45033
|
+
if (this.agent.isProcessing() || this.processingQueue) {
|
|
45034
|
+
this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length });
|
|
44089
45035
|
return;
|
|
44090
45036
|
}
|
|
44091
|
-
await this.processMessage(message);
|
|
44092
45037
|
await this.drainQueue();
|
|
44093
45038
|
}
|
|
44094
45039
|
async processMessage(message) {
|
|
@@ -44479,10 +45424,13 @@ var COMMANDS = [
|
|
|
44479
45424
|
{ name: "/model", description: "show model information" },
|
|
44480
45425
|
{ name: "/skills", description: "list available skills" },
|
|
44481
45426
|
{ name: "/config", description: "show configuration" },
|
|
45427
|
+
{ name: "/projects", description: "manage projects in this folder" },
|
|
45428
|
+
{ name: "/plans", description: "manage project plans" },
|
|
44482
45429
|
{ name: "/connectors", description: "list available connectors" },
|
|
44483
45430
|
{ name: "/init", description: "initialize assistants in project" },
|
|
44484
45431
|
{ name: "/compact", description: "summarize to save context" },
|
|
44485
45432
|
{ name: "/memory", description: "show what AI remembers" },
|
|
45433
|
+
{ name: "/context", description: "manage injected project context" },
|
|
44486
45434
|
{ name: "/feedback", description: "submit feedback on GitHub" },
|
|
44487
45435
|
{ name: "/schedule", description: "schedule a command" },
|
|
44488
45436
|
{ name: "/schedules", description: "list scheduled commands" },
|
|
@@ -44578,14 +45526,14 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
|
|
|
44578
45526
|
if (autocompleteMode === "command" && filteredCommands.length > 0 && !submittedValue.includes(" ")) {
|
|
44579
45527
|
const selected = filteredCommands[selectedIndex] || filteredCommands[0];
|
|
44580
45528
|
if (selected) {
|
|
44581
|
-
onSubmit(selected.name, isProcessing ? "
|
|
45529
|
+
onSubmit(selected.name, isProcessing ? "inline" : "normal");
|
|
44582
45530
|
setValue("");
|
|
44583
45531
|
setSelectedIndex(0);
|
|
44584
45532
|
return;
|
|
44585
45533
|
}
|
|
44586
45534
|
}
|
|
44587
45535
|
if (isProcessing) {
|
|
44588
|
-
onSubmit(submittedValue, "
|
|
45536
|
+
onSubmit(submittedValue, "inline");
|
|
44589
45537
|
} else {
|
|
44590
45538
|
onSubmit(submittedValue, "normal");
|
|
44591
45539
|
}
|
|
@@ -44596,7 +45544,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
|
|
|
44596
45544
|
let placeholder = "Type a message...";
|
|
44597
45545
|
if (isProcessing) {
|
|
44598
45546
|
prompt = "\u22EF";
|
|
44599
|
-
placeholder = queueLength > 0 ? "Type to
|
|
45547
|
+
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
45548
|
}
|
|
44601
45549
|
const truncateDescription = (desc, maxLen = 60) => {
|
|
44602
45550
|
if (desc.length <= maxLen)
|
|
@@ -44737,7 +45685,12 @@ var import_react24 = __toESM(require_react(), 1);
|
|
|
44737
45685
|
|
|
44738
45686
|
// packages/terminal/src/components/Markdown.tsx
|
|
44739
45687
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
44740
|
-
function Markdown({ content }) {
|
|
45688
|
+
function Markdown({ content, preRendered = false }) {
|
|
45689
|
+
if (preRendered) {
|
|
45690
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
45691
|
+
children: content
|
|
45692
|
+
}, undefined, false, undefined, this);
|
|
45693
|
+
}
|
|
44741
45694
|
const { columns } = use_stdout_default();
|
|
44742
45695
|
const maxWidth = columns ? Math.max(20, columns - 2) : undefined;
|
|
44743
45696
|
const rendered = parseMarkdown(content, { maxWidth });
|
|
@@ -44745,6 +45698,9 @@ function Markdown({ content }) {
|
|
|
44745
45698
|
children: rendered
|
|
44746
45699
|
}, undefined, false, undefined, this);
|
|
44747
45700
|
}
|
|
45701
|
+
function renderMarkdown(text, options) {
|
|
45702
|
+
return parseMarkdown(text, { maxWidth: options?.maxWidth });
|
|
45703
|
+
}
|
|
44748
45704
|
function parseMarkdown(text, options) {
|
|
44749
45705
|
let result = text;
|
|
44750
45706
|
const codeBlocks = [];
|
|
@@ -44770,7 +45726,7 @@ function parseMarkdown(text, options) {
|
|
|
44770
45726
|
result = result.replace(/\b(Building|Running|Working|Queued|Pending|Connecting)\b/gi, (match) => source_default.yellow(match));
|
|
44771
45727
|
result = result.replace(/\b(Success|Succeeded|Done|Complete|Completed|Connected|Authenticated)\b/gi, (match) => source_default.green(match));
|
|
44772
45728
|
result = result.replace(/\b(Error|Failed|Failure|Denied|Blocked)\b/gi, (match) => source_default.red(match));
|
|
44773
|
-
result = formatMarkdownTables(result);
|
|
45729
|
+
result = formatMarkdownTables(result, options?.maxWidth);
|
|
44774
45730
|
result = result.replace(/@@BLOCKSECTION(\d+)@@/g, (_, index) => {
|
|
44775
45731
|
const section = blockSections[parseInt(index, 10)];
|
|
44776
45732
|
if (!section)
|
|
@@ -44784,6 +45740,7 @@ function parseMarkdown(text, options) {
|
|
|
44784
45740
|
});
|
|
44785
45741
|
return result.trimEnd();
|
|
44786
45742
|
}
|
|
45743
|
+
var ALLOWED_BLOCK_TYPES = new Set(["info", "success", "warning", "error", "note", "command"]);
|
|
44787
45744
|
function extractBlockSections(text, blocks) {
|
|
44788
45745
|
const lines = text.split(`
|
|
44789
45746
|
`);
|
|
@@ -44812,6 +45769,9 @@ function extractBlockSections(text, blocks) {
|
|
|
44812
45769
|
i += 1;
|
|
44813
45770
|
continue;
|
|
44814
45771
|
}
|
|
45772
|
+
if (parsed.warning) {
|
|
45773
|
+
output.push(createMalformedBlock(blocks, indent, "grid", parsed.warning));
|
|
45774
|
+
}
|
|
44815
45775
|
const bodyLines = stripIndent(parsed.bodyLines, indent);
|
|
44816
45776
|
const body = bodyLines.join(`
|
|
44817
45777
|
`);
|
|
@@ -44825,7 +45785,7 @@ function extractBlockSections(text, blocks) {
|
|
|
44825
45785
|
const indent = blockMatch[1] ?? "";
|
|
44826
45786
|
const header = blockMatch[2] ?? "";
|
|
44827
45787
|
const attrs = parseAttributes(header);
|
|
44828
|
-
|
|
45788
|
+
let type = String(attrs.type || "info");
|
|
44829
45789
|
const title = attrs.title ? String(attrs.title) : undefined;
|
|
44830
45790
|
const parsed = parseDelimitedBlock(lines, i, indent);
|
|
44831
45791
|
if (!parsed) {
|
|
@@ -44834,6 +45794,14 @@ function extractBlockSections(text, blocks) {
|
|
|
44834
45794
|
i += 1;
|
|
44835
45795
|
continue;
|
|
44836
45796
|
}
|
|
45797
|
+
const normalizedType = type.toLowerCase();
|
|
45798
|
+
if (!ALLOWED_BLOCK_TYPES.has(normalizedType)) {
|
|
45799
|
+
output.push(createMalformedBlock(blocks, indent, "block", `Unknown block type "${type}". Using info.`));
|
|
45800
|
+
type = "info";
|
|
45801
|
+
}
|
|
45802
|
+
if (parsed.warning) {
|
|
45803
|
+
output.push(createMalformedBlock(blocks, indent, "block", parsed.warning));
|
|
45804
|
+
}
|
|
44837
45805
|
const body = stripIndent(parsed.bodyLines, indent).join(`
|
|
44838
45806
|
`);
|
|
44839
45807
|
blocks.push({ kind: "block", type, title, body, indent });
|
|
@@ -44850,6 +45818,9 @@ function extractBlockSections(text, blocks) {
|
|
|
44850
45818
|
i += 1;
|
|
44851
45819
|
continue;
|
|
44852
45820
|
}
|
|
45821
|
+
if (parsed.warning) {
|
|
45822
|
+
output.push(createMalformedBlock(blocks, indent, "report", parsed.warning));
|
|
45823
|
+
}
|
|
44853
45824
|
const body = stripIndent(parsed.bodyLines, indent).join(`
|
|
44854
45825
|
`);
|
|
44855
45826
|
blocks.push({ kind: "report", body, indent });
|
|
@@ -44881,10 +45852,14 @@ function extractCards(body) {
|
|
|
44881
45852
|
const title = attrs.title ? String(attrs.title) : undefined;
|
|
44882
45853
|
const bodyLines = [];
|
|
44883
45854
|
let closed = false;
|
|
45855
|
+
let indentWarning;
|
|
44884
45856
|
i += 1;
|
|
44885
45857
|
while (i < lines.length) {
|
|
44886
45858
|
const current = lines[i];
|
|
44887
|
-
if (current.trim() === ":::"
|
|
45859
|
+
if (current.trim() === ":::") {
|
|
45860
|
+
if (indent.length > 0 && !current.startsWith(indent)) {
|
|
45861
|
+
indentWarning = "Card closing ::: indentation did not match opening.";
|
|
45862
|
+
}
|
|
44888
45863
|
closed = true;
|
|
44889
45864
|
i += 1;
|
|
44890
45865
|
break;
|
|
@@ -44901,6 +45876,13 @@ function extractCards(body) {
|
|
|
44901
45876
|
break;
|
|
44902
45877
|
}
|
|
44903
45878
|
const stripped = stripIndent(bodyLines, indent);
|
|
45879
|
+
if (indentWarning) {
|
|
45880
|
+
cards.push({
|
|
45881
|
+
type: "warning",
|
|
45882
|
+
title: "Malformed card",
|
|
45883
|
+
body: indentWarning
|
|
45884
|
+
});
|
|
45885
|
+
}
|
|
44904
45886
|
cards.push({ type, title, body: stripped.join(`
|
|
44905
45887
|
`) });
|
|
44906
45888
|
}
|
|
@@ -44909,6 +45891,7 @@ function extractCards(body) {
|
|
|
44909
45891
|
function parseDelimitedBlock(lines, startIndex, indent) {
|
|
44910
45892
|
const bodyLines = [];
|
|
44911
45893
|
let openCards = 0;
|
|
45894
|
+
let warning;
|
|
44912
45895
|
let i = startIndex + 1;
|
|
44913
45896
|
while (i < lines.length) {
|
|
44914
45897
|
const current = lines[i];
|
|
@@ -44919,14 +45902,18 @@ function parseDelimitedBlock(lines, startIndex, indent) {
|
|
|
44919
45902
|
i += 1;
|
|
44920
45903
|
continue;
|
|
44921
45904
|
}
|
|
44922
|
-
if (trimmed === ":::"
|
|
45905
|
+
if (trimmed === ":::") {
|
|
45906
|
+
const indentMismatch = indent.length > 0 && !current.startsWith(indent);
|
|
44923
45907
|
if (openCards > 0) {
|
|
44924
45908
|
openCards -= 1;
|
|
44925
45909
|
bodyLines.push(current);
|
|
44926
45910
|
i += 1;
|
|
44927
45911
|
continue;
|
|
44928
45912
|
}
|
|
44929
|
-
|
|
45913
|
+
if (indentMismatch) {
|
|
45914
|
+
warning = "Closing ::: indentation did not match opening. Adjust indentation for consistency.";
|
|
45915
|
+
}
|
|
45916
|
+
return { bodyLines, nextIndex: i + 1, warning };
|
|
44930
45917
|
}
|
|
44931
45918
|
bodyLines.push(current);
|
|
44932
45919
|
i += 1;
|
|
@@ -45093,7 +46080,7 @@ function formatBoxRow(line, width) {
|
|
|
45093
46080
|
const padded = len < width ? line + " ".repeat(width - len) : line;
|
|
45094
46081
|
return `\u2502 ${padded} \u2502`;
|
|
45095
46082
|
}
|
|
45096
|
-
function formatMarkdownTables(text) {
|
|
46083
|
+
function formatMarkdownTables(text, maxWidth) {
|
|
45097
46084
|
const lines = text.split(`
|
|
45098
46085
|
`);
|
|
45099
46086
|
const output = [];
|
|
@@ -45111,7 +46098,7 @@ function formatMarkdownTables(text) {
|
|
|
45111
46098
|
rows.push(parseTableRow(lines[i]));
|
|
45112
46099
|
i += 1;
|
|
45113
46100
|
}
|
|
45114
|
-
const table = renderTable(header, rows);
|
|
46101
|
+
const table = renderTable(header, rows, maxWidth);
|
|
45115
46102
|
output.push(...table);
|
|
45116
46103
|
continue;
|
|
45117
46104
|
}
|
|
@@ -45126,7 +46113,7 @@ function parseTableRow(line) {
|
|
|
45126
46113
|
const withoutEdges = trimmed.replace(/^\|/, "").replace(/\|$/, "");
|
|
45127
46114
|
return withoutEdges.split("|").map((cell) => cell.trim());
|
|
45128
46115
|
}
|
|
45129
|
-
function renderTable(header, rows) {
|
|
46116
|
+
function renderTable(header, rows, maxWidth) {
|
|
45130
46117
|
const colCount = Math.max(header.length, ...rows.map((r) => r.length));
|
|
45131
46118
|
const widths = new Array(colCount).fill(0);
|
|
45132
46119
|
const allRows = [header, ...rows];
|
|
@@ -45138,11 +46125,29 @@ function renderTable(header, rows) {
|
|
|
45138
46125
|
widths[i] = len;
|
|
45139
46126
|
}
|
|
45140
46127
|
}
|
|
46128
|
+
const minCellWidth = 4;
|
|
46129
|
+
const availableCellWidth = maxWidth ? Math.max(colCount * minCellWidth, maxWidth - (colCount - 1) * 3 - 4) : undefined;
|
|
46130
|
+
if (availableCellWidth) {
|
|
46131
|
+
const total = widths.reduce((sum, width) => sum + width, 0);
|
|
46132
|
+
if (total > availableCellWidth) {
|
|
46133
|
+
const minWidth = Math.max(1, Math.floor(availableCellWidth / colCount));
|
|
46134
|
+
while (widths.reduce((sum, width) => sum + width, 0) > availableCellWidth) {
|
|
46135
|
+
const maxWidthValue = Math.max(...widths);
|
|
46136
|
+
const idx = widths.findIndex((width) => width === maxWidthValue);
|
|
46137
|
+
if (idx === -1)
|
|
46138
|
+
break;
|
|
46139
|
+
if (widths[idx] <= minWidth)
|
|
46140
|
+
break;
|
|
46141
|
+
widths[idx] -= 1;
|
|
46142
|
+
}
|
|
46143
|
+
}
|
|
46144
|
+
}
|
|
45141
46145
|
const pad = (value, width) => {
|
|
45142
|
-
const
|
|
46146
|
+
const rendered = width > 0 ? truncateAnsi(value, width) : value;
|
|
46147
|
+
const len = stripAnsi2(rendered).length;
|
|
45143
46148
|
if (len >= width)
|
|
45144
|
-
return
|
|
45145
|
-
return
|
|
46149
|
+
return rendered;
|
|
46150
|
+
return rendered + " ".repeat(width - len);
|
|
45146
46151
|
};
|
|
45147
46152
|
const top = "\u250C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C") + "\u2510";
|
|
45148
46153
|
const mid = "\u251C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u253C") + "\u2524";
|
|
@@ -45220,7 +46225,8 @@ function renderReport(body, maxWidth, indent = "") {
|
|
|
45220
46225
|
}
|
|
45221
46226
|
if (tableLines.length > 0) {
|
|
45222
46227
|
output.push(indent + source_default.bold("Detailed Status Table"));
|
|
45223
|
-
const
|
|
46228
|
+
const adjustedWidth = maxWidth ? Math.max(20, maxWidth - indent.length) : undefined;
|
|
46229
|
+
const rendered = renderReportTable(tableLines, indent, adjustedWidth);
|
|
45224
46230
|
output.push(...rendered);
|
|
45225
46231
|
}
|
|
45226
46232
|
return output.join(`
|
|
@@ -45249,7 +46255,7 @@ function renderProgressLine(label, value, labelWidth, barWidth) {
|
|
|
45249
46255
|
const bar = source_default.gray("\u2591".repeat(empty));
|
|
45250
46256
|
return `${label.padEnd(labelWidth)} [${fill}${bar}] ${value}%`;
|
|
45251
46257
|
}
|
|
45252
|
-
function renderReportTable(lines, indent) {
|
|
46258
|
+
function renderReportTable(lines, indent, maxWidth) {
|
|
45253
46259
|
const tableLines = lines.map((line) => line.trim()).filter(Boolean);
|
|
45254
46260
|
if (tableLines.length < 2)
|
|
45255
46261
|
return [];
|
|
@@ -45273,7 +46279,7 @@ function renderReportTable(lines, indent) {
|
|
|
45273
46279
|
}
|
|
45274
46280
|
return next;
|
|
45275
46281
|
});
|
|
45276
|
-
return renderTable(header, styledRows).map((line) => indent + line);
|
|
46282
|
+
return renderTable(header, styledRows, maxWidth).map((line) => indent + line);
|
|
45277
46283
|
}
|
|
45278
46284
|
function decoratePriority(value) {
|
|
45279
46285
|
const normalized = value.toLowerCase();
|
|
@@ -45343,6 +46349,23 @@ function wrapAnsiLine(line, width) {
|
|
|
45343
46349
|
function truncateAnsi(line, width) {
|
|
45344
46350
|
if (stripAnsi2(line).length <= width)
|
|
45345
46351
|
return line;
|
|
46352
|
+
if (width <= 3) {
|
|
46353
|
+
let result = "";
|
|
46354
|
+
let visible2 = 0;
|
|
46355
|
+
let i2 = 0;
|
|
46356
|
+
while (i2 < line.length && visible2 < width) {
|
|
46357
|
+
const match = line.slice(i2).match(/^\x1b\[[0-9;]*m/);
|
|
46358
|
+
if (match) {
|
|
46359
|
+
result += match[0];
|
|
46360
|
+
i2 += match[0].length;
|
|
46361
|
+
continue;
|
|
46362
|
+
}
|
|
46363
|
+
result += line[i2];
|
|
46364
|
+
visible2 += 1;
|
|
46365
|
+
i2 += 1;
|
|
46366
|
+
}
|
|
46367
|
+
return result;
|
|
46368
|
+
}
|
|
45346
46369
|
const suffix = "...";
|
|
45347
46370
|
const target = Math.max(0, width - suffix.length);
|
|
45348
46371
|
let current = "";
|
|
@@ -45362,6 +46385,42 @@ function truncateAnsi(line, width) {
|
|
|
45362
46385
|
return current + suffix;
|
|
45363
46386
|
}
|
|
45364
46387
|
|
|
46388
|
+
// packages/terminal/src/components/messageLines.ts
|
|
46389
|
+
function estimateToolPanelLines(toolCalls, toolResults, hasContent) {
|
|
46390
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
46391
|
+
return 0;
|
|
46392
|
+
}
|
|
46393
|
+
const resultMap = new Set;
|
|
46394
|
+
for (const result of toolResults || []) {
|
|
46395
|
+
resultMap.add(result.toolCallId);
|
|
46396
|
+
}
|
|
46397
|
+
let lines = 3;
|
|
46398
|
+
if (hasContent) {
|
|
46399
|
+
lines += 1;
|
|
46400
|
+
}
|
|
46401
|
+
for (const call of toolCalls) {
|
|
46402
|
+
lines += 3;
|
|
46403
|
+
if (resultMap.has(call.id)) {
|
|
46404
|
+
lines += 1;
|
|
46405
|
+
}
|
|
46406
|
+
}
|
|
46407
|
+
return lines;
|
|
46408
|
+
}
|
|
46409
|
+
function estimateMessageLines(message) {
|
|
46410
|
+
if (message.role === "system") {
|
|
46411
|
+
return 0;
|
|
46412
|
+
}
|
|
46413
|
+
const content = message.content ?? "";
|
|
46414
|
+
const contentLines = content.length > 0 ? content.split(`
|
|
46415
|
+
`).length : 0;
|
|
46416
|
+
const hasContent = contentLines > 0;
|
|
46417
|
+
let lines = Math.max(1, contentLines);
|
|
46418
|
+
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
46419
|
+
lines += estimateToolPanelLines(message.toolCalls, message.toolResults, hasContent);
|
|
46420
|
+
}
|
|
46421
|
+
return lines;
|
|
46422
|
+
}
|
|
46423
|
+
|
|
45365
46424
|
// packages/terminal/src/components/Messages.tsx
|
|
45366
46425
|
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
45367
46426
|
function Messages4({
|
|
@@ -45371,19 +46430,28 @@ function Messages4({
|
|
|
45371
46430
|
currentToolCall,
|
|
45372
46431
|
lastToolResult,
|
|
45373
46432
|
activityLog = [],
|
|
45374
|
-
|
|
45375
|
-
|
|
46433
|
+
scrollOffsetLines = 0,
|
|
46434
|
+
maxVisibleLines = 10,
|
|
45376
46435
|
queuedMessageIds
|
|
45377
46436
|
}) {
|
|
45378
46437
|
const [now2, setNow] = import_react24.useState(Date.now());
|
|
45379
46438
|
const combinedMessages = import_react24.useMemo(() => [...messages, ...streamingMessages], [messages, streamingMessages]);
|
|
45380
|
-
const
|
|
45381
|
-
|
|
45382
|
-
|
|
46439
|
+
const lineSpans = import_react24.useMemo(() => {
|
|
46440
|
+
let cursor = 0;
|
|
46441
|
+
return combinedMessages.map((message, index) => {
|
|
46442
|
+
const lines = estimateMessageLines(message);
|
|
46443
|
+
const start = cursor;
|
|
46444
|
+
cursor += lines;
|
|
46445
|
+
return { message, index, start, end: cursor, lines };
|
|
46446
|
+
});
|
|
46447
|
+
}, [combinedMessages]);
|
|
46448
|
+
const totalLines = lineSpans.length > 0 ? lineSpans[lineSpans.length - 1].end : 0;
|
|
46449
|
+
const endLine = Math.max(0, totalLines - scrollOffsetLines);
|
|
46450
|
+
const startLine = Math.max(0, endLine - maxVisibleLines);
|
|
46451
|
+
const visibleSpans = lineSpans.filter((span) => span.end > startLine && span.start < endLine);
|
|
45383
46452
|
const historicalCount = messages.length;
|
|
45384
|
-
const
|
|
45385
|
-
const
|
|
45386
|
-
const visibleStreaming = visibleCombined.slice(splitIndex);
|
|
46453
|
+
const visibleMessages = visibleSpans.filter((span) => span.index < historicalCount).map((span) => span.message);
|
|
46454
|
+
const visibleStreaming = visibleSpans.filter((span) => span.index >= historicalCount).map((span) => span.message);
|
|
45387
46455
|
const groupedMessages = groupConsecutiveToolMessages(visibleMessages);
|
|
45388
46456
|
const historicalItems = groupedMessages.map((group) => {
|
|
45389
46457
|
if (group.type === "single") {
|
|
@@ -45631,7 +46699,8 @@ function MessageBubble({ message, queuedMessageIds }) {
|
|
|
45631
46699
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45632
46700
|
flexGrow: 1,
|
|
45633
46701
|
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Markdown, {
|
|
45634
|
-
content: message.content
|
|
46702
|
+
content: message.content,
|
|
46703
|
+
preRendered: Boolean(message.__rendered)
|
|
45635
46704
|
}, undefined, false, undefined, this)
|
|
45636
46705
|
}, undefined, false, undefined, this)
|
|
45637
46706
|
]
|
|
@@ -45652,6 +46721,8 @@ function ToolCallPanel({
|
|
|
45652
46721
|
}) {
|
|
45653
46722
|
if (toolCalls.length === 0)
|
|
45654
46723
|
return null;
|
|
46724
|
+
const { columns } = use_stdout_default();
|
|
46725
|
+
const panelWidth = columns ? Math.max(24, columns - 4) : undefined;
|
|
45655
46726
|
const resultMap = new Map;
|
|
45656
46727
|
for (const result of toolResults || []) {
|
|
45657
46728
|
resultMap.set(result.toolCallId, result);
|
|
@@ -45664,7 +46735,7 @@ function ToolCallPanel({
|
|
|
45664
46735
|
borderStyle: "round",
|
|
45665
46736
|
borderColor,
|
|
45666
46737
|
paddingX: 1,
|
|
45667
|
-
width: "100%",
|
|
46738
|
+
width: panelWidth ?? "100%",
|
|
45668
46739
|
children: [
|
|
45669
46740
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45670
46741
|
justifyContent: "space-between",
|
|
@@ -45690,6 +46761,8 @@ function ToolCallPanel({
|
|
|
45690
46761
|
const statusColor = result ? result.isError ? "red" : "green" : "yellow";
|
|
45691
46762
|
const displayName = getToolDisplayName(toolCall);
|
|
45692
46763
|
const context2 = getToolContext(toolCall);
|
|
46764
|
+
const maxLine = panelWidth ? Math.max(20, panelWidth - 8) : 80;
|
|
46765
|
+
const summaryLine = truncate(formatToolCall(toolCall), maxLine);
|
|
45693
46766
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45694
46767
|
flexDirection: "column",
|
|
45695
46768
|
marginTop: 1,
|
|
@@ -45719,7 +46792,7 @@ function ToolCallPanel({
|
|
|
45719
46792
|
}, undefined, true, undefined, this),
|
|
45720
46793
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
45721
46794
|
dimColor: true,
|
|
45722
|
-
children:
|
|
46795
|
+
children: summaryLine
|
|
45723
46796
|
}, undefined, false, undefined, this),
|
|
45724
46797
|
result && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
45725
46798
|
marginLeft: 2,
|
|
@@ -45754,7 +46827,7 @@ function getToolContext(toolCall) {
|
|
|
45754
46827
|
return truncate(String(input.pattern || ""), 20);
|
|
45755
46828
|
case "schedule":
|
|
45756
46829
|
return String(input.action || "");
|
|
45757
|
-
case "
|
|
46830
|
+
case "submit_feedback":
|
|
45758
46831
|
return String(input.type || "feedback");
|
|
45759
46832
|
case "web_search":
|
|
45760
46833
|
return truncate(String(input.query || ""), 20);
|
|
@@ -46035,46 +47108,7 @@ function formatSearchResult(content) {
|
|
|
46035
47108
|
|
|
46036
47109
|
// packages/terminal/src/components/Status.tsx
|
|
46037
47110
|
var import_react25 = __toESM(require_react(), 1);
|
|
46038
|
-
|
|
46039
|
-
// packages/terminal/src/components/EnergyBar.tsx
|
|
46040
47111
|
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
47112
|
function Status({
|
|
46079
47113
|
isProcessing,
|
|
46080
47114
|
cwd: cwd2,
|
|
@@ -46112,74 +47146,51 @@ function Status({
|
|
|
46112
47146
|
let contextInfo = "";
|
|
46113
47147
|
if (tokenUsage && tokenUsage.maxContextTokens > 0) {
|
|
46114
47148
|
const percent = Math.round(tokenUsage.totalTokens / tokenUsage.maxContextTokens * 100);
|
|
46115
|
-
contextInfo = `${percent}
|
|
47149
|
+
contextInfo = `${percent}%`;
|
|
46116
47150
|
}
|
|
46117
|
-
const sessionInfo = sessionIndex && sessionCount ?
|
|
46118
|
-
const bgIndicator = backgroundProcessingCount > 0 ? `
|
|
46119
|
-
const
|
|
46120
|
-
|
|
46121
|
-
return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
47151
|
+
const sessionInfo = sessionIndex && sessionCount && sessionCount > 1 ? `${sessionIndex}/${sessionCount}` : "";
|
|
47152
|
+
const bgIndicator = backgroundProcessingCount > 0 ? ` +${backgroundProcessingCount}` : "";
|
|
47153
|
+
const voiceIcon = voiceState?.enabled ? voiceState.isListening ? "\uD83C\uDFA4" : voiceState.isSpeaking ? "\uD83D\uDD0A" : "\uD83C\uDF99" : "";
|
|
47154
|
+
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
46122
47155
|
marginTop: 1,
|
|
46123
47156
|
justifyContent: "space-between",
|
|
46124
47157
|
children: [
|
|
46125
|
-
/* @__PURE__ */
|
|
47158
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46126
47159
|
dimColor: true,
|
|
46127
47160
|
children: [
|
|
46128
|
-
"/help
|
|
46129
|
-
sessionCount && sessionCount > 1 ? "
|
|
47161
|
+
"/help",
|
|
47162
|
+
sessionCount && sessionCount > 1 ? " \xB7 Ctrl+S" : ""
|
|
46130
47163
|
]
|
|
46131
47164
|
}, undefined, true, undefined, this),
|
|
46132
|
-
/* @__PURE__ */
|
|
47165
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
46133
47166
|
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, {
|
|
47167
|
+
voiceIcon && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46149
47168
|
dimColor: true,
|
|
46150
47169
|
children: [
|
|
46151
|
-
|
|
46152
|
-
"
|
|
47170
|
+
voiceIcon,
|
|
47171
|
+
" "
|
|
46153
47172
|
]
|
|
46154
47173
|
}, undefined, true, undefined, this),
|
|
46155
|
-
isProcessing && /* @__PURE__ */
|
|
47174
|
+
isProcessing && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46156
47175
|
dimColor: true,
|
|
46157
|
-
children: "esc
|
|
47176
|
+
children: "esc \xB7 "
|
|
46158
47177
|
}, undefined, false, undefined, this),
|
|
46159
|
-
sessionInfo && /* @__PURE__ */
|
|
47178
|
+
sessionInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46160
47179
|
dimColor: true,
|
|
46161
47180
|
children: [
|
|
46162
47181
|
sessionInfo,
|
|
46163
47182
|
bgIndicator,
|
|
46164
|
-
|
|
47183
|
+
" \xB7 "
|
|
46165
47184
|
]
|
|
46166
47185
|
}, undefined, true, undefined, this),
|
|
46167
|
-
contextInfo && /* @__PURE__ */
|
|
47186
|
+
contextInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46168
47187
|
dimColor: true,
|
|
46169
47188
|
children: contextInfo
|
|
46170
47189
|
}, undefined, false, undefined, this),
|
|
46171
|
-
|
|
46172
|
-
dimColor: true,
|
|
46173
|
-
children: [
|
|
46174
|
-
sessionInfo || contextInfo ? " \xB7 " : "",
|
|
46175
|
-
"id ",
|
|
46176
|
-
sessionId
|
|
46177
|
-
]
|
|
46178
|
-
}, undefined, true, undefined, this),
|
|
46179
|
-
isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
47190
|
+
isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
46180
47191
|
dimColor: true,
|
|
46181
47192
|
children: [
|
|
46182
|
-
" \xB7
|
|
47193
|
+
" \xB7 ",
|
|
46183
47194
|
formatDuration2(elapsed)
|
|
46184
47195
|
]
|
|
46185
47196
|
}, undefined, true, undefined, this)
|
|
@@ -46211,17 +47222,17 @@ function Spinner({ type = "dots" }) {
|
|
|
46211
47222
|
var build_default2 = Spinner;
|
|
46212
47223
|
|
|
46213
47224
|
// packages/terminal/src/components/Spinner.tsx
|
|
46214
|
-
var
|
|
47225
|
+
var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46215
47226
|
function Spinner2({ label }) {
|
|
46216
|
-
return /* @__PURE__ */
|
|
47227
|
+
return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
46217
47228
|
children: [
|
|
46218
|
-
/* @__PURE__ */
|
|
47229
|
+
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
46219
47230
|
dimColor: true,
|
|
46220
|
-
children: /* @__PURE__ */
|
|
47231
|
+
children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(build_default2, {
|
|
46221
47232
|
type: "dots"
|
|
46222
47233
|
}, undefined, false, undefined, this)
|
|
46223
47234
|
}, undefined, false, undefined, this),
|
|
46224
|
-
label && /* @__PURE__ */
|
|
47235
|
+
label && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
46225
47236
|
dimColor: true,
|
|
46226
47237
|
children: [
|
|
46227
47238
|
" ",
|
|
@@ -46234,7 +47245,7 @@ function Spinner2({ label }) {
|
|
|
46234
47245
|
|
|
46235
47246
|
// packages/terminal/src/components/ProcessingIndicator.tsx
|
|
46236
47247
|
var import_react27 = __toESM(require_react(), 1);
|
|
46237
|
-
var
|
|
47248
|
+
var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46238
47249
|
function ProcessingIndicator({
|
|
46239
47250
|
isProcessing,
|
|
46240
47251
|
startTime,
|
|
@@ -46278,14 +47289,14 @@ function ProcessingIndicator({
|
|
|
46278
47289
|
parts.push("thinking");
|
|
46279
47290
|
}
|
|
46280
47291
|
const label = isThinking ? "Metamorphosing" : "Working";
|
|
46281
|
-
return /* @__PURE__ */
|
|
47292
|
+
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
46282
47293
|
marginY: 1,
|
|
46283
47294
|
children: [
|
|
46284
|
-
/* @__PURE__ */
|
|
47295
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
46285
47296
|
dimColor: true,
|
|
46286
47297
|
children: "\u2736 "
|
|
46287
47298
|
}, undefined, false, undefined, this),
|
|
46288
|
-
/* @__PURE__ */
|
|
47299
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
46289
47300
|
dimColor: true,
|
|
46290
47301
|
children: [
|
|
46291
47302
|
" ",
|
|
@@ -46293,7 +47304,7 @@ function ProcessingIndicator({
|
|
|
46293
47304
|
"... "
|
|
46294
47305
|
]
|
|
46295
47306
|
}, undefined, true, undefined, this),
|
|
46296
|
-
/* @__PURE__ */
|
|
47307
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
46297
47308
|
dimColor: true,
|
|
46298
47309
|
children: [
|
|
46299
47310
|
"(",
|
|
@@ -46306,31 +47317,31 @@ function ProcessingIndicator({
|
|
|
46306
47317
|
}
|
|
46307
47318
|
|
|
46308
47319
|
// packages/terminal/src/components/WelcomeBanner.tsx
|
|
46309
|
-
var
|
|
47320
|
+
var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46310
47321
|
function WelcomeBanner({ version, model, directory }) {
|
|
46311
47322
|
const homeDir = process.env.HOME || "";
|
|
46312
47323
|
const displayDir = directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
|
|
46313
|
-
return /* @__PURE__ */
|
|
47324
|
+
return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46314
47325
|
flexDirection: "column",
|
|
46315
47326
|
marginBottom: 1,
|
|
46316
47327
|
children: [
|
|
46317
|
-
/* @__PURE__ */
|
|
47328
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46318
47329
|
children: [
|
|
46319
|
-
/* @__PURE__ */
|
|
47330
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46320
47331
|
color: "cyan",
|
|
46321
47332
|
bold: true,
|
|
46322
47333
|
children: ">"
|
|
46323
47334
|
}, undefined, false, undefined, this),
|
|
46324
|
-
/* @__PURE__ */
|
|
47335
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46325
47336
|
color: "cyan",
|
|
46326
47337
|
bold: true,
|
|
46327
47338
|
children: "_ "
|
|
46328
47339
|
}, undefined, false, undefined, this),
|
|
46329
|
-
/* @__PURE__ */
|
|
47340
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46330
47341
|
bold: true,
|
|
46331
47342
|
children: "assistants"
|
|
46332
47343
|
}, undefined, false, undefined, this),
|
|
46333
|
-
/* @__PURE__ */
|
|
47344
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46334
47345
|
dimColor: true,
|
|
46335
47346
|
children: [
|
|
46336
47347
|
" (v",
|
|
@@ -46340,29 +47351,29 @@ function WelcomeBanner({ version, model, directory }) {
|
|
|
46340
47351
|
}, undefined, true, undefined, this)
|
|
46341
47352
|
]
|
|
46342
47353
|
}, undefined, true, undefined, this),
|
|
46343
|
-
/* @__PURE__ */
|
|
47354
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46344
47355
|
marginTop: 1,
|
|
46345
47356
|
children: [
|
|
46346
|
-
/* @__PURE__ */
|
|
47357
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46347
47358
|
dimColor: true,
|
|
46348
47359
|
children: "model: "
|
|
46349
47360
|
}, undefined, false, undefined, this),
|
|
46350
|
-
/* @__PURE__ */
|
|
47361
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46351
47362
|
children: model
|
|
46352
47363
|
}, undefined, false, undefined, this),
|
|
46353
|
-
/* @__PURE__ */
|
|
47364
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46354
47365
|
dimColor: true,
|
|
46355
47366
|
children: " /model to change"
|
|
46356
47367
|
}, undefined, false, undefined, this)
|
|
46357
47368
|
]
|
|
46358
47369
|
}, undefined, true, undefined, this),
|
|
46359
|
-
/* @__PURE__ */
|
|
47370
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
46360
47371
|
children: [
|
|
46361
|
-
/* @__PURE__ */
|
|
47372
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46362
47373
|
dimColor: true,
|
|
46363
47374
|
children: "directory: "
|
|
46364
47375
|
}, undefined, false, undefined, this),
|
|
46365
|
-
/* @__PURE__ */
|
|
47376
|
+
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
46366
47377
|
children: displayDir
|
|
46367
47378
|
}, undefined, false, undefined, this)
|
|
46368
47379
|
]
|
|
@@ -46373,7 +47384,7 @@ function WelcomeBanner({ version, model, directory }) {
|
|
|
46373
47384
|
|
|
46374
47385
|
// packages/terminal/src/components/SessionSelector.tsx
|
|
46375
47386
|
var import_react28 = __toESM(require_react(), 1);
|
|
46376
|
-
var
|
|
47387
|
+
var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46377
47388
|
function formatSessionTime(timestamp) {
|
|
46378
47389
|
const date = new Date(timestamp);
|
|
46379
47390
|
const now2 = new Date;
|
|
@@ -46439,13 +47450,13 @@ function SessionSelector({
|
|
|
46439
47450
|
return;
|
|
46440
47451
|
}
|
|
46441
47452
|
});
|
|
46442
|
-
return /* @__PURE__ */
|
|
47453
|
+
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46443
47454
|
flexDirection: "column",
|
|
46444
47455
|
paddingY: 1,
|
|
46445
47456
|
children: [
|
|
46446
|
-
/* @__PURE__ */
|
|
47457
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46447
47458
|
marginBottom: 1,
|
|
46448
|
-
children: /* @__PURE__ */
|
|
47459
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46449
47460
|
bold: true,
|
|
46450
47461
|
children: "Sessions"
|
|
46451
47462
|
}, undefined, false, undefined, this)
|
|
@@ -46457,8 +47468,8 @@ function SessionSelector({
|
|
|
46457
47468
|
const time = formatSessionTime(session.updatedAt);
|
|
46458
47469
|
const path2 = formatPath(session.cwd);
|
|
46459
47470
|
const processing = session.isProcessing ? " (processing)" : "";
|
|
46460
|
-
return /* @__PURE__ */
|
|
46461
|
-
children: /* @__PURE__ */
|
|
47471
|
+
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
47472
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46462
47473
|
inverse: isSelected,
|
|
46463
47474
|
color: isActive ? "green" : undefined,
|
|
46464
47475
|
dimColor: !isSelected && !isActive,
|
|
@@ -46475,17 +47486,17 @@ function SessionSelector({
|
|
|
46475
47486
|
}, undefined, true, undefined, this)
|
|
46476
47487
|
}, session.id, false, undefined, this);
|
|
46477
47488
|
}),
|
|
46478
|
-
/* @__PURE__ */
|
|
47489
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46479
47490
|
marginTop: 1,
|
|
46480
|
-
children: /* @__PURE__ */
|
|
47491
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46481
47492
|
inverse: selectedIndex === sessions.length,
|
|
46482
47493
|
dimColor: selectedIndex !== sessions.length,
|
|
46483
47494
|
children: "+ New session (n)"
|
|
46484
47495
|
}, undefined, false, undefined, this)
|
|
46485
47496
|
}, undefined, false, undefined, this),
|
|
46486
|
-
/* @__PURE__ */
|
|
47497
|
+
/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
46487
47498
|
marginTop: 1,
|
|
46488
|
-
children: /* @__PURE__ */
|
|
47499
|
+
children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
46489
47500
|
dimColor: true,
|
|
46490
47501
|
children: [
|
|
46491
47502
|
"Enter to select | Esc to cancel | 1-",
|
|
@@ -46499,32 +47510,8 @@ function SessionSelector({
|
|
|
46499
47510
|
}
|
|
46500
47511
|
|
|
46501
47512
|
// packages/terminal/src/components/App.tsx
|
|
46502
|
-
var
|
|
47513
|
+
var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
46503
47514
|
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
47515
|
function parseErrorMessage(error) {
|
|
46529
47516
|
const lines = error.split(`
|
|
46530
47517
|
`);
|
|
@@ -46546,7 +47533,65 @@ function parseErrorMessage(error) {
|
|
|
46546
47533
|
}
|
|
46547
47534
|
var MESSAGE_CHUNK_LINES = 12;
|
|
46548
47535
|
var MESSAGE_WRAP_CHARS = 120;
|
|
46549
|
-
function
|
|
47536
|
+
function wrapTextLines(text, wrapChars) {
|
|
47537
|
+
const rawLines = text.split(`
|
|
47538
|
+
`);
|
|
47539
|
+
const lines = [];
|
|
47540
|
+
for (const line of rawLines) {
|
|
47541
|
+
if (line.length <= wrapChars) {
|
|
47542
|
+
lines.push(line);
|
|
47543
|
+
continue;
|
|
47544
|
+
}
|
|
47545
|
+
for (let i = 0;i < line.length; i += wrapChars) {
|
|
47546
|
+
lines.push(line.slice(i, i + wrapChars));
|
|
47547
|
+
}
|
|
47548
|
+
}
|
|
47549
|
+
return lines;
|
|
47550
|
+
}
|
|
47551
|
+
function stripAnsi3(text) {
|
|
47552
|
+
return text.replace(/\x1B\[[0-9;]*m/g, "");
|
|
47553
|
+
}
|
|
47554
|
+
function chunkRenderedLines(lines, chunkLines) {
|
|
47555
|
+
const chunks = [];
|
|
47556
|
+
let current = [];
|
|
47557
|
+
let i = 0;
|
|
47558
|
+
const isBoxStart = (line) => stripAnsi3(line).trimStart().startsWith("\u250C");
|
|
47559
|
+
const isBoxEnd = (line) => stripAnsi3(line).trimStart().startsWith("\u2514");
|
|
47560
|
+
while (i < lines.length) {
|
|
47561
|
+
const line = lines[i];
|
|
47562
|
+
if (isBoxStart(line)) {
|
|
47563
|
+
let end = i + 1;
|
|
47564
|
+
while (end < lines.length && !isBoxEnd(lines[end])) {
|
|
47565
|
+
end += 1;
|
|
47566
|
+
}
|
|
47567
|
+
if (end < lines.length)
|
|
47568
|
+
end += 1;
|
|
47569
|
+
const boxLines = lines.slice(i, end);
|
|
47570
|
+
if (current.length > 0 && current.length + boxLines.length > chunkLines) {
|
|
47571
|
+
chunks.push(current);
|
|
47572
|
+
current = [];
|
|
47573
|
+
}
|
|
47574
|
+
if (boxLines.length >= chunkLines) {
|
|
47575
|
+
chunks.push(boxLines);
|
|
47576
|
+
} else {
|
|
47577
|
+
current.push(...boxLines);
|
|
47578
|
+
}
|
|
47579
|
+
i = end;
|
|
47580
|
+
continue;
|
|
47581
|
+
}
|
|
47582
|
+
if (current.length >= chunkLines) {
|
|
47583
|
+
chunks.push(current);
|
|
47584
|
+
current = [];
|
|
47585
|
+
}
|
|
47586
|
+
current.push(line);
|
|
47587
|
+
i += 1;
|
|
47588
|
+
}
|
|
47589
|
+
if (current.length > 0) {
|
|
47590
|
+
chunks.push(current);
|
|
47591
|
+
}
|
|
47592
|
+
return chunks;
|
|
47593
|
+
}
|
|
47594
|
+
function buildDisplayMessages(messages, chunkLines, wrapChars, options) {
|
|
46550
47595
|
const display = [];
|
|
46551
47596
|
for (const msg of messages) {
|
|
46552
47597
|
const content = msg.content ?? "";
|
|
@@ -46555,32 +47600,34 @@ function buildDisplayMessages(messages, chunkLines, wrapChars) {
|
|
|
46555
47600
|
display.push(msg);
|
|
46556
47601
|
continue;
|
|
46557
47602
|
}
|
|
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
|
-
}
|
|
47603
|
+
const lines = wrapTextLines(content, wrapChars);
|
|
46570
47604
|
if (lines.length <= chunkLines) {
|
|
46571
|
-
|
|
47605
|
+
if (msg.role === "assistant") {
|
|
47606
|
+
const rendered2 = renderMarkdown(lines.join(`
|
|
47607
|
+
`), { maxWidth: options?.maxWidth });
|
|
47608
|
+
display.push({ ...msg, content: rendered2, __rendered: true });
|
|
47609
|
+
} else {
|
|
47610
|
+
display.push(msg);
|
|
47611
|
+
}
|
|
46572
47612
|
continue;
|
|
46573
47613
|
}
|
|
46574
|
-
const
|
|
46575
|
-
|
|
46576
|
-
|
|
47614
|
+
const baseContent = lines.join(`
|
|
47615
|
+
`);
|
|
47616
|
+
const renderAssistant = msg.role === "assistant";
|
|
47617
|
+
const rendered = renderAssistant ? renderMarkdown(baseContent, { maxWidth: options?.maxWidth }) : baseContent;
|
|
47618
|
+
const renderedLines = rendered.split(`
|
|
47619
|
+
`);
|
|
47620
|
+
const chunks = chunkRenderedLines(renderedLines, chunkLines);
|
|
47621
|
+
for (let i = 0;i < chunks.length; i++) {
|
|
47622
|
+
const chunkContent = chunks[i].join(`
|
|
46577
47623
|
`);
|
|
46578
47624
|
display.push({
|
|
46579
47625
|
...msg,
|
|
46580
47626
|
id: `${msg.id}::chunk-${i}`,
|
|
46581
47627
|
content: chunkContent,
|
|
46582
|
-
|
|
46583
|
-
|
|
47628
|
+
__rendered: renderAssistant,
|
|
47629
|
+
toolCalls: i === chunks.length - 1 ? msg.toolCalls : undefined,
|
|
47630
|
+
toolResults: i === chunks.length - 1 ? msg.toolResults : undefined
|
|
46584
47631
|
});
|
|
46585
47632
|
}
|
|
46586
47633
|
}
|
|
@@ -46615,7 +47662,7 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46615
47662
|
const toolCallsRef = import_react29.useRef([]);
|
|
46616
47663
|
const toolResultsRef = import_react29.useRef([]);
|
|
46617
47664
|
const activityLogRef = import_react29.useRef([]);
|
|
46618
|
-
const
|
|
47665
|
+
const prevDisplayLineCountRef = import_react29.useRef(0);
|
|
46619
47666
|
const skipNextDoneRef = import_react29.useRef(false);
|
|
46620
47667
|
const isProcessingRef = import_react29.useRef(isProcessing);
|
|
46621
47668
|
import_react29.useEffect(() => {
|
|
@@ -46937,9 +47984,10 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46937
47984
|
await activeSession2.client.send(nextMessage.content);
|
|
46938
47985
|
}, [activeSessionId]);
|
|
46939
47986
|
const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
|
|
46940
|
-
const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.map((msg) => msg.id)), [activeQueue]);
|
|
47987
|
+
const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.filter((msg) => msg.mode === "queued").map((msg) => msg.id)), [activeQueue]);
|
|
46941
47988
|
const wrapChars = columns ? Math.max(40, columns - 4) : MESSAGE_WRAP_CHARS;
|
|
46942
|
-
const
|
|
47989
|
+
const renderWidth = columns ? Math.max(20, columns - 2) : undefined;
|
|
47990
|
+
const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth }), [messages, wrapChars, renderWidth]);
|
|
46943
47991
|
const streamingMessages = import_react29.useMemo(() => {
|
|
46944
47992
|
if (!isProcessing || !currentResponse.trim())
|
|
46945
47993
|
return [];
|
|
@@ -46949,9 +47997,12 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46949
47997
|
content: currentResponse,
|
|
46950
47998
|
timestamp: now()
|
|
46951
47999
|
};
|
|
46952
|
-
return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars);
|
|
46953
|
-
}, [currentResponse, isProcessing, wrapChars]);
|
|
46954
|
-
const
|
|
48000
|
+
return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth });
|
|
48001
|
+
}, [currentResponse, isProcessing, wrapChars, renderWidth]);
|
|
48002
|
+
const displayLineCount = import_react29.useMemo(() => {
|
|
48003
|
+
const combined = [...displayMessages, ...streamingMessages];
|
|
48004
|
+
return combined.reduce((sum, msg) => sum + estimateMessageLines(msg), 0);
|
|
48005
|
+
}, [displayMessages, streamingMessages]);
|
|
46955
48006
|
import_react29.useEffect(() => {
|
|
46956
48007
|
if (!isProcessing && activeQueue.length > 0) {
|
|
46957
48008
|
processQueue();
|
|
@@ -46961,23 +48012,21 @@ function App2({ cwd: cwd2, version }) {
|
|
|
46961
48012
|
if (autoScroll) {
|
|
46962
48013
|
setScrollOffset(0);
|
|
46963
48014
|
}
|
|
46964
|
-
}, [
|
|
48015
|
+
}, [displayLineCount, autoScroll]);
|
|
46965
48016
|
import_react29.useEffect(() => {
|
|
46966
|
-
const prevCount =
|
|
46967
|
-
if (!autoScroll &&
|
|
46968
|
-
const delta =
|
|
48017
|
+
const prevCount = prevDisplayLineCountRef.current;
|
|
48018
|
+
if (!autoScroll && displayLineCount > prevCount) {
|
|
48019
|
+
const delta = displayLineCount - prevCount;
|
|
46969
48020
|
setScrollOffset((prev) => prev + delta);
|
|
46970
48021
|
}
|
|
46971
|
-
|
|
46972
|
-
}, [
|
|
48022
|
+
prevDisplayLineCountRef.current = displayLineCount;
|
|
48023
|
+
}, [displayLineCount, autoScroll]);
|
|
46973
48024
|
const reservedLines = 8;
|
|
46974
|
-
const
|
|
46975
|
-
const toolCallsHeight = isProcessing ? Math.min(toolCallsRef.current.length, 5) : 0;
|
|
46976
|
-
const maxVisibleMessages = Math.max(3, baseMaxVisible - toolCallsHeight);
|
|
48025
|
+
const maxVisibleLines = rows ? Math.max(6, rows - reservedLines) : 20;
|
|
46977
48026
|
import_react29.useEffect(() => {
|
|
46978
|
-
const maxOffset = Math.max(0,
|
|
48027
|
+
const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
|
|
46979
48028
|
setScrollOffset((prev) => Math.min(prev, maxOffset));
|
|
46980
|
-
}, [
|
|
48029
|
+
}, [displayLineCount, maxVisibleLines]);
|
|
46981
48030
|
const sessions = registry2.listSessions();
|
|
46982
48031
|
const activeSession = registry2.getActiveSession();
|
|
46983
48032
|
const sessionIndex = activeSessionId ? registry2.getSessionIndex(activeSessionId) : 0;
|
|
@@ -47056,8 +48105,9 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47056
48105
|
}
|
|
47057
48106
|
if (key.pageUp || key.shift && key.upArrow) {
|
|
47058
48107
|
setScrollOffset((prev) => {
|
|
47059
|
-
const maxOffset = Math.max(0,
|
|
47060
|
-
const
|
|
48108
|
+
const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
|
|
48109
|
+
const step = Math.max(3, Math.floor(maxVisibleLines / 2));
|
|
48110
|
+
const newOffset = Math.min(prev + step, maxOffset);
|
|
47061
48111
|
if (newOffset > 0)
|
|
47062
48112
|
setAutoScroll(false);
|
|
47063
48113
|
return newOffset;
|
|
@@ -47065,14 +48115,15 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47065
48115
|
}
|
|
47066
48116
|
if (key.pageDown || key.shift && key.downArrow) {
|
|
47067
48117
|
setScrollOffset((prev) => {
|
|
47068
|
-
const
|
|
48118
|
+
const step = Math.max(3, Math.floor(maxVisibleLines / 2));
|
|
48119
|
+
const newOffset = Math.max(0, prev - step);
|
|
47069
48120
|
if (newOffset === 0)
|
|
47070
48121
|
setAutoScroll(true);
|
|
47071
48122
|
return newOffset;
|
|
47072
48123
|
});
|
|
47073
48124
|
}
|
|
47074
48125
|
if (key.ctrl && input === "u") {
|
|
47075
|
-
const maxOffset = Math.max(0,
|
|
48126
|
+
const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
|
|
47076
48127
|
setScrollOffset(maxOffset);
|
|
47077
48128
|
setAutoScroll(false);
|
|
47078
48129
|
}
|
|
@@ -47103,13 +48154,19 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47103
48154
|
setShowSessionSelector(true);
|
|
47104
48155
|
return;
|
|
47105
48156
|
}
|
|
47106
|
-
if (mode === "queue") {
|
|
48157
|
+
if (mode === "queue" || mode === "inline") {
|
|
47107
48158
|
if (!activeSessionId)
|
|
47108
48159
|
return;
|
|
47109
48160
|
const queuedId = generateId();
|
|
47110
48161
|
setMessageQueue((prev) => [
|
|
47111
48162
|
...prev,
|
|
47112
|
-
{
|
|
48163
|
+
{
|
|
48164
|
+
id: queuedId,
|
|
48165
|
+
sessionId: activeSessionId,
|
|
48166
|
+
content: trimmedInput,
|
|
48167
|
+
queuedAt: now(),
|
|
48168
|
+
mode: mode === "inline" ? "inline" : "queued"
|
|
48169
|
+
}
|
|
47113
48170
|
]);
|
|
47114
48171
|
setMessages((prev) => [
|
|
47115
48172
|
...prev,
|
|
@@ -47173,19 +48230,19 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47173
48230
|
activeSessionId
|
|
47174
48231
|
]);
|
|
47175
48232
|
if (isInitializing) {
|
|
47176
|
-
return /* @__PURE__ */
|
|
48233
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47177
48234
|
flexDirection: "column",
|
|
47178
48235
|
padding: 1,
|
|
47179
|
-
children: /* @__PURE__ */
|
|
48236
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Spinner2, {
|
|
47180
48237
|
label: "Initializing..."
|
|
47181
48238
|
}, undefined, false, undefined, this)
|
|
47182
48239
|
}, undefined, false, undefined, this);
|
|
47183
48240
|
}
|
|
47184
48241
|
if (showSessionSelector) {
|
|
47185
|
-
return /* @__PURE__ */
|
|
48242
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47186
48243
|
flexDirection: "column",
|
|
47187
48244
|
padding: 1,
|
|
47188
|
-
children: /* @__PURE__ */
|
|
48245
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SessionSelector, {
|
|
47189
48246
|
sessions,
|
|
47190
48247
|
activeSessionId,
|
|
47191
48248
|
onSelect: handleSessionSwitch,
|
|
@@ -47205,19 +48262,21 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47205
48262
|
return text;
|
|
47206
48263
|
return text.slice(0, maxLen - 3) + "...";
|
|
47207
48264
|
};
|
|
48265
|
+
const queuedCount = activeQueue.filter((msg) => msg.mode === "queued").length;
|
|
48266
|
+
const inlineCount = activeQueue.filter((msg) => msg.mode === "inline").length;
|
|
47208
48267
|
const showWelcome = messages.length === 0 && !isProcessing;
|
|
47209
|
-
return /* @__PURE__ */
|
|
48268
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47210
48269
|
flexDirection: "column",
|
|
47211
48270
|
padding: 1,
|
|
47212
48271
|
children: [
|
|
47213
|
-
showWelcome && /* @__PURE__ */
|
|
47214
|
-
version: version ?? "
|
|
48272
|
+
showWelcome && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(WelcomeBanner, {
|
|
48273
|
+
version: version ?? "unknown",
|
|
47215
48274
|
model: "claude-sonnet-4",
|
|
47216
48275
|
directory: activeSession?.cwd || cwd2
|
|
47217
48276
|
}, undefined, false, undefined, this),
|
|
47218
|
-
backgroundProcessingCount > 0 && /* @__PURE__ */
|
|
48277
|
+
backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47219
48278
|
marginBottom: 1,
|
|
47220
|
-
children: /* @__PURE__ */
|
|
48279
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47221
48280
|
color: "yellow",
|
|
47222
48281
|
children: [
|
|
47223
48282
|
backgroundProcessingCount,
|
|
@@ -47227,17 +48286,17 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47227
48286
|
]
|
|
47228
48287
|
}, undefined, true, undefined, this)
|
|
47229
48288
|
}, undefined, false, undefined, this),
|
|
47230
|
-
scrollOffset > 0 && /* @__PURE__ */
|
|
47231
|
-
children: /* @__PURE__ */
|
|
48289
|
+
scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
48290
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47232
48291
|
dimColor: true,
|
|
47233
48292
|
children: [
|
|
47234
48293
|
"\u2191 ",
|
|
47235
48294
|
scrollOffset,
|
|
47236
|
-
" more
|
|
48295
|
+
" more lines above (Shift+\u2193 or Page Down to scroll down)"
|
|
47237
48296
|
]
|
|
47238
48297
|
}, undefined, true, undefined, this)
|
|
47239
48298
|
}, undefined, false, undefined, this),
|
|
47240
|
-
/* @__PURE__ */
|
|
48299
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Messages4, {
|
|
47241
48300
|
messages: displayMessages,
|
|
47242
48301
|
currentResponse: undefined,
|
|
47243
48302
|
streamingMessages,
|
|
@@ -47245,61 +48304,34 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47245
48304
|
lastToolResult: undefined,
|
|
47246
48305
|
activityLog: isProcessing ? activityLog : [],
|
|
47247
48306
|
queuedMessageIds,
|
|
47248
|
-
scrollOffset,
|
|
47249
|
-
|
|
48307
|
+
scrollOffsetLines: scrollOffset,
|
|
48308
|
+
maxVisibleLines
|
|
47250
48309
|
}, 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, {
|
|
48310
|
+
activeQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47280
48311
|
marginY: 1,
|
|
47281
48312
|
flexDirection: "column",
|
|
47282
48313
|
children: [
|
|
47283
|
-
/* @__PURE__ */
|
|
48314
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47284
48315
|
dimColor: true,
|
|
47285
48316
|
children: [
|
|
47286
48317
|
activeQueue.length,
|
|
47287
|
-
" message",
|
|
48318
|
+
" pending message",
|
|
47288
48319
|
activeQueue.length > 1 ? "s" : "",
|
|
47289
|
-
|
|
48320
|
+
inlineCount > 0 || queuedCount > 0 ? ` \xB7 ${inlineCount} in-stream \xB7 ${queuedCount} queued` : ""
|
|
47290
48321
|
]
|
|
47291
48322
|
}, undefined, true, undefined, this),
|
|
47292
|
-
activeQueue.slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */
|
|
48323
|
+
activeQueue.slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47293
48324
|
marginLeft: 2,
|
|
47294
|
-
children: /* @__PURE__ */
|
|
48325
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47295
48326
|
dimColor: true,
|
|
47296
48327
|
children: [
|
|
47297
|
-
"\
|
|
48328
|
+
queued.mode === "inline" ? "\u21B3" : "\u23F3",
|
|
48329
|
+
" ",
|
|
47298
48330
|
truncateQueued(queued.content)
|
|
47299
48331
|
]
|
|
47300
48332
|
}, undefined, true, undefined, this)
|
|
47301
48333
|
}, queued.id, false, undefined, this)),
|
|
47302
|
-
activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */
|
|
48334
|
+
activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47303
48335
|
dimColor: true,
|
|
47304
48336
|
children: [
|
|
47305
48337
|
" ... and ",
|
|
@@ -47313,18 +48345,18 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47313
48345
|
const parsed = parseErrorMessage(error);
|
|
47314
48346
|
const severity = parsed.code && /TIMEOUT|RATE_LIMITED/.test(parsed.code) ? "yellow" : "red";
|
|
47315
48347
|
const prefix = SHOW_ERROR_CODES && parsed.code ? `${parsed.code}: ` : "";
|
|
47316
|
-
return /* @__PURE__ */
|
|
48348
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
47317
48349
|
marginY: 1,
|
|
47318
48350
|
flexDirection: "column",
|
|
47319
48351
|
children: [
|
|
47320
|
-
/* @__PURE__ */
|
|
48352
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47321
48353
|
color: severity,
|
|
47322
48354
|
children: [
|
|
47323
48355
|
prefix,
|
|
47324
48356
|
parsed.message
|
|
47325
48357
|
]
|
|
47326
48358
|
}, undefined, true, undefined, this),
|
|
47327
|
-
parsed.suggestion && /* @__PURE__ */
|
|
48359
|
+
parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
47328
48360
|
color: severity,
|
|
47329
48361
|
children: [
|
|
47330
48362
|
"Suggestion: ",
|
|
@@ -47334,19 +48366,19 @@ function App2({ cwd: cwd2, version }) {
|
|
|
47334
48366
|
]
|
|
47335
48367
|
}, undefined, true, undefined, this);
|
|
47336
48368
|
})(),
|
|
47337
|
-
/* @__PURE__ */
|
|
48369
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ProcessingIndicator, {
|
|
47338
48370
|
isProcessing,
|
|
47339
48371
|
startTime: processingStartTime,
|
|
47340
48372
|
tokenCount: currentTurnTokens,
|
|
47341
48373
|
isThinking
|
|
47342
48374
|
}, undefined, false, undefined, this),
|
|
47343
|
-
/* @__PURE__ */
|
|
48375
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Input, {
|
|
47344
48376
|
onSubmit: handleSubmit,
|
|
47345
48377
|
isProcessing,
|
|
47346
48378
|
queueLength: activeQueue.length,
|
|
47347
48379
|
skills
|
|
47348
48380
|
}, undefined, false, undefined, this),
|
|
47349
|
-
/* @__PURE__ */
|
|
48381
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Status, {
|
|
47350
48382
|
isProcessing,
|
|
47351
48383
|
cwd: activeSession?.cwd || cwd2,
|
|
47352
48384
|
queueLength: activeQueue.length,
|
|
@@ -47538,8 +48570,9 @@ function formatStreamEvent(chunk) {
|
|
|
47538
48570
|
}
|
|
47539
48571
|
|
|
47540
48572
|
// packages/terminal/src/index.tsx
|
|
47541
|
-
var
|
|
47542
|
-
var VERSION3 = "0.6.
|
|
48573
|
+
var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
|
|
48574
|
+
var VERSION3 = "0.6.20";
|
|
48575
|
+
process.env.ASSISTANTS_VERSION ??= VERSION3;
|
|
47543
48576
|
function parseArgs(argv) {
|
|
47544
48577
|
const args = argv.slice(2);
|
|
47545
48578
|
const options = {
|
|
@@ -47693,7 +48726,7 @@ if (options.print !== null) {
|
|
|
47693
48726
|
process.exit(1);
|
|
47694
48727
|
});
|
|
47695
48728
|
} else {
|
|
47696
|
-
const { waitUntilExit } = render_default(/* @__PURE__ */
|
|
48729
|
+
const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(App2, {
|
|
47697
48730
|
cwd: options.cwd,
|
|
47698
48731
|
version: VERSION3
|
|
47699
48732
|
}, undefined, false, undefined, this));
|
|
@@ -47702,4 +48735,4 @@ if (options.print !== null) {
|
|
|
47702
48735
|
});
|
|
47703
48736
|
}
|
|
47704
48737
|
|
|
47705
|
-
//# debugId=
|
|
48738
|
+
//# debugId=F2C1A670F9E8793164756E2164756E21
|