@hasna/assistants 1.1.25 → 1.1.27
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 +808 -283
- package/dist/index.js.map +21 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21563,9 +21563,10 @@ class NativeHookRegistry {
|
|
|
21563
21563
|
config = {};
|
|
21564
21564
|
register(hook) {
|
|
21565
21565
|
const eventHooks = this.hooks.get(hook.event) || [];
|
|
21566
|
-
eventHooks.
|
|
21567
|
-
|
|
21568
|
-
|
|
21566
|
+
const deduped = eventHooks.filter((existing) => existing.id !== hook.id);
|
|
21567
|
+
deduped.push(hook);
|
|
21568
|
+
deduped.sort((a, b) => a.priority - b.priority);
|
|
21569
|
+
this.hooks.set(hook.event, deduped);
|
|
21569
21570
|
}
|
|
21570
21571
|
getHooks(event) {
|
|
21571
21572
|
return this.hooks.get(event) || [];
|
|
@@ -72917,16 +72918,28 @@ class BudgetTracker {
|
|
|
72917
72918
|
case "assistant":
|
|
72918
72919
|
if (idOrAssistant) {
|
|
72919
72920
|
this.assistantUsages.set(idOrAssistant, newUsage);
|
|
72921
|
+
} else {
|
|
72922
|
+
this.assistantUsages.clear();
|
|
72920
72923
|
}
|
|
72921
72924
|
break;
|
|
72922
72925
|
case "swarm":
|
|
72923
72926
|
this.swarmUsage = newUsage;
|
|
72924
72927
|
break;
|
|
72925
72928
|
case "project":
|
|
72926
|
-
|
|
72927
|
-
|
|
72928
|
-
this.
|
|
72929
|
-
|
|
72929
|
+
if (idOrAssistant) {
|
|
72930
|
+
this.projectUsages.set(idOrAssistant, newUsage);
|
|
72931
|
+
this.saveProjectState(idOrAssistant, newUsage);
|
|
72932
|
+
break;
|
|
72933
|
+
}
|
|
72934
|
+
if (this.activeProjectId) {
|
|
72935
|
+
this.projectUsages.set(this.activeProjectId, newUsage);
|
|
72936
|
+
this.saveProjectState(this.activeProjectId, newUsage);
|
|
72937
|
+
break;
|
|
72938
|
+
}
|
|
72939
|
+
for (const projectId of this.projectUsages.keys()) {
|
|
72940
|
+
const resetProjectUsage = createEmptyUsage();
|
|
72941
|
+
this.projectUsages.set(projectId, resetProjectUsage);
|
|
72942
|
+
this.saveProjectState(projectId, resetProjectUsage);
|
|
72930
72943
|
}
|
|
72931
72944
|
break;
|
|
72932
72945
|
}
|
|
@@ -72936,6 +72949,9 @@ class BudgetTracker {
|
|
|
72936
72949
|
this.sessionUsage = createEmptyUsage();
|
|
72937
72950
|
this.assistantUsages.clear();
|
|
72938
72951
|
this.swarmUsage = createEmptyUsage();
|
|
72952
|
+
for (const projectId of this.projectUsages.keys()) {
|
|
72953
|
+
this.saveProjectState(projectId, createEmptyUsage());
|
|
72954
|
+
}
|
|
72939
72955
|
this.projectUsages.clear();
|
|
72940
72956
|
this.saveState();
|
|
72941
72957
|
}
|
|
@@ -73034,6 +73050,22 @@ var init_tracker = __esm(() => {
|
|
|
73034
73050
|
});
|
|
73035
73051
|
|
|
73036
73052
|
// packages/core/src/budget/tools.ts
|
|
73053
|
+
function normalizeScope2(value) {
|
|
73054
|
+
return String(value ?? "").trim().toLowerCase();
|
|
73055
|
+
}
|
|
73056
|
+
function isBudgetToolScope(value) {
|
|
73057
|
+
return BUDGET_TOOL_SCOPES.includes(value);
|
|
73058
|
+
}
|
|
73059
|
+
function isBudgetResetScope(value) {
|
|
73060
|
+
return value === "all" || isBudgetToolScope(value);
|
|
73061
|
+
}
|
|
73062
|
+
function parseLimitValue(value) {
|
|
73063
|
+
const numeric = Number(value);
|
|
73064
|
+
if (!Number.isFinite(numeric) || numeric < 0) {
|
|
73065
|
+
return null;
|
|
73066
|
+
}
|
|
73067
|
+
return numeric === 0 ? undefined : numeric;
|
|
73068
|
+
}
|
|
73037
73069
|
function createBudgetToolExecutors(getBudgetTracker) {
|
|
73038
73070
|
return {
|
|
73039
73071
|
budget_status: async (input) => {
|
|
@@ -73041,7 +73073,11 @@ function createBudgetToolExecutors(getBudgetTracker) {
|
|
|
73041
73073
|
if (!tracker) {
|
|
73042
73074
|
return "Budget tracking is not enabled.";
|
|
73043
73075
|
}
|
|
73044
|
-
const
|
|
73076
|
+
const scopeInput = normalizeScope2(input.scope || "session");
|
|
73077
|
+
if (!isBudgetToolScope(scopeInput)) {
|
|
73078
|
+
return `Invalid scope: ${scopeInput || "(empty)"}. Use "session", "swarm", or "project".`;
|
|
73079
|
+
}
|
|
73080
|
+
const scope = scopeInput;
|
|
73045
73081
|
const status = tracker.checkBudget(scope);
|
|
73046
73082
|
const lines = [];
|
|
73047
73083
|
lines.push(`## Budget Status (${scope})`);
|
|
@@ -73096,53 +73132,51 @@ function createBudgetToolExecutors(getBudgetTracker) {
|
|
|
73096
73132
|
if (!tracker) {
|
|
73097
73133
|
return "Budget tracking is not enabled.";
|
|
73098
73134
|
}
|
|
73099
|
-
const
|
|
73100
|
-
|
|
73101
|
-
|
|
73102
|
-
switch (scope) {
|
|
73103
|
-
case "session":
|
|
73104
|
-
limitsKey = "sessionLimits";
|
|
73105
|
-
break;
|
|
73106
|
-
case "swarm":
|
|
73107
|
-
limitsKey = "swarmLimits";
|
|
73108
|
-
break;
|
|
73109
|
-
case "project":
|
|
73110
|
-
limitsKey = "projectLimits";
|
|
73111
|
-
break;
|
|
73112
|
-
default:
|
|
73113
|
-
return `Invalid scope: ${scope}. Use "session", "swarm", or "project".`;
|
|
73135
|
+
const scopeInput = normalizeScope2(input.scope || "session");
|
|
73136
|
+
if (!isBudgetToolScope(scopeInput)) {
|
|
73137
|
+
return `Invalid scope: ${scopeInput || "(empty)"}. Use "session", "swarm", or "project".`;
|
|
73114
73138
|
}
|
|
73139
|
+
const scope = scopeInput;
|
|
73140
|
+
const config = tracker.getConfig();
|
|
73115
73141
|
const updates = {};
|
|
73116
|
-
|
|
73117
|
-
|
|
73118
|
-
|
|
73119
|
-
|
|
73120
|
-
|
|
73121
|
-
|
|
73122
|
-
|
|
73123
|
-
|
|
73124
|
-
|
|
73125
|
-
|
|
73126
|
-
|
|
73127
|
-
updates
|
|
73128
|
-
|
|
73142
|
+
const providedFields = [];
|
|
73143
|
+
const invalidFields = [];
|
|
73144
|
+
for (const field of LIMIT_FIELDS) {
|
|
73145
|
+
if (input[field] === undefined)
|
|
73146
|
+
continue;
|
|
73147
|
+
providedFields.push(field);
|
|
73148
|
+
const parsed = parseLimitValue(input[field]);
|
|
73149
|
+
if (parsed === null) {
|
|
73150
|
+
invalidFields.push(field);
|
|
73151
|
+
continue;
|
|
73152
|
+
}
|
|
73153
|
+
updates[field] = parsed;
|
|
73154
|
+
}
|
|
73155
|
+
if (providedFields.length === 0) {
|
|
73129
73156
|
return "No limits specified. Provide at least one limit to update.";
|
|
73130
73157
|
}
|
|
73158
|
+
if (invalidFields.length > 0) {
|
|
73159
|
+
return `Invalid limit values for: ${invalidFields.join(", ")}. Values must be numbers >= 0 (0 = unlimited).`;
|
|
73160
|
+
}
|
|
73131
73161
|
tracker.updateConfig({
|
|
73132
|
-
[
|
|
73133
|
-
...config[
|
|
73162
|
+
[scope]: {
|
|
73163
|
+
...config[scope] || {},
|
|
73134
73164
|
...updates
|
|
73135
73165
|
}
|
|
73136
73166
|
});
|
|
73167
|
+
const applied = Object.fromEntries(providedFields.map((field) => [field, updates[field] ?? "unlimited"]));
|
|
73137
73168
|
return `Budget limits updated for ${scope} scope:
|
|
73138
|
-
${JSON.stringify(
|
|
73169
|
+
${JSON.stringify(applied, null, 2)}`;
|
|
73139
73170
|
},
|
|
73140
73171
|
budget_reset: async (input) => {
|
|
73141
73172
|
const tracker = getBudgetTracker();
|
|
73142
73173
|
if (!tracker) {
|
|
73143
73174
|
return "Budget tracking is not enabled.";
|
|
73144
73175
|
}
|
|
73145
|
-
const scope =
|
|
73176
|
+
const scope = normalizeScope2(input.scope || "session");
|
|
73177
|
+
if (!isBudgetResetScope(scope)) {
|
|
73178
|
+
return `Invalid scope: ${scope || "(empty)"}. Use "session", "swarm", "project", or "all".`;
|
|
73179
|
+
}
|
|
73146
73180
|
if (scope === "all") {
|
|
73147
73181
|
tracker.resetAll();
|
|
73148
73182
|
return "All budget counters have been reset.";
|
|
@@ -73158,8 +73192,17 @@ function registerBudgetTools(registry, getBudgetTracker) {
|
|
|
73158
73192
|
registry.register(tool, executors[tool.name]);
|
|
73159
73193
|
}
|
|
73160
73194
|
}
|
|
73161
|
-
var budgetStatusTool, budgetGetTool, budgetSetTool, budgetResetTool, budgetTools;
|
|
73195
|
+
var BUDGET_TOOL_SCOPES, LIMIT_FIELDS, budgetStatusTool, budgetGetTool, budgetSetTool, budgetResetTool, budgetTools;
|
|
73162
73196
|
var init_tools4 = __esm(() => {
|
|
73197
|
+
BUDGET_TOOL_SCOPES = ["session", "swarm", "project"];
|
|
73198
|
+
LIMIT_FIELDS = [
|
|
73199
|
+
"maxInputTokens",
|
|
73200
|
+
"maxOutputTokens",
|
|
73201
|
+
"maxTotalTokens",
|
|
73202
|
+
"maxLlmCalls",
|
|
73203
|
+
"maxToolCalls",
|
|
73204
|
+
"maxDurationMs"
|
|
73205
|
+
];
|
|
73163
73206
|
budgetStatusTool = {
|
|
73164
73207
|
name: "budget_status",
|
|
73165
73208
|
description: "Get current budget status showing usage vs limits for the specified scope (session, swarm, or project).",
|
|
@@ -73231,8 +73274,8 @@ var init_tools4 = __esm(() => {
|
|
|
73231
73274
|
properties: {
|
|
73232
73275
|
scope: {
|
|
73233
73276
|
type: "string",
|
|
73234
|
-
description: 'Budget scope to reset: "session", "swarm", or "all"',
|
|
73235
|
-
enum: ["session", "swarm", "all"]
|
|
73277
|
+
description: 'Budget scope to reset: "session", "swarm", "project", or "all"',
|
|
73278
|
+
enum: ["session", "swarm", "project", "all"]
|
|
73236
73279
|
}
|
|
73237
73280
|
},
|
|
73238
73281
|
required: ["scope"]
|
|
@@ -78300,6 +78343,7 @@ class BuiltinCommands {
|
|
|
78300
78343
|
registerAll(loader) {
|
|
78301
78344
|
loader.register(this.helpCommand(loader));
|
|
78302
78345
|
loader.register(this.aboutCommand());
|
|
78346
|
+
loader.register(this.docsCommand());
|
|
78303
78347
|
loader.register(this.clearCommand());
|
|
78304
78348
|
loader.register(this.newCommand());
|
|
78305
78349
|
loader.register(this.sessionCommand());
|
|
@@ -78347,6 +78391,8 @@ class BuiltinCommands {
|
|
|
78347
78391
|
loader.register(this.tasksCommand());
|
|
78348
78392
|
loader.register(this.setupCommand());
|
|
78349
78393
|
loader.register(this.exitCommand());
|
|
78394
|
+
loader.register(this.diffCommand());
|
|
78395
|
+
loader.register(this.undoCommand());
|
|
78350
78396
|
}
|
|
78351
78397
|
aboutCommand() {
|
|
78352
78398
|
return {
|
|
@@ -78360,15 +78406,93 @@ class BuiltinCommands {
|
|
|
78360
78406
|
**About Hasna**
|
|
78361
78407
|
|
|
78362
78408
|
`;
|
|
78363
|
-
message += `Hasna is a
|
|
78409
|
+
message += `Hasna is on a mission to make AI more useful to everyone.
|
|
78410
|
+
`;
|
|
78411
|
+
message += `We build tools that bring the power of AI into your everyday workflow \u2014 no expertise required.
|
|
78364
78412
|
`;
|
|
78365
78413
|
message += `Website: hasna.com
|
|
78366
78414
|
`;
|
|
78367
78415
|
message += `
|
|
78368
|
-
**About
|
|
78416
|
+
**About Hasna Assistants**
|
|
78417
|
+
|
|
78418
|
+
`;
|
|
78419
|
+
message += `Hasna Assistants is a general-purpose AI assistant that lives in your terminal.
|
|
78420
|
+
`;
|
|
78421
|
+
message += `It connects natively to 100+ tools \u2014 email, calendars, databases, cloud storage, CRMs, and more \u2014 so you can get things done without switching apps.
|
|
78422
|
+
|
|
78423
|
+
`;
|
|
78424
|
+
message += `What you can do:
|
|
78425
|
+
`;
|
|
78426
|
+
message += `- Ask questions and get answers in plain language
|
|
78427
|
+
`;
|
|
78428
|
+
message += `- Automate repetitive tasks across your tools
|
|
78429
|
+
`;
|
|
78430
|
+
message += `- Read, write, and manage files on your machine
|
|
78431
|
+
`;
|
|
78432
|
+
message += `- Run multi-step workflows with built-in skills
|
|
78433
|
+
`;
|
|
78434
|
+
message += `- Schedule commands to run on a timer
|
|
78435
|
+
`;
|
|
78436
|
+
message += `- Collaborate with multiple AI agents via swarm mode
|
|
78369
78437
|
|
|
78370
78438
|
`;
|
|
78371
|
-
message += `
|
|
78439
|
+
message += `Whether you are a developer, a founder, or just someone who wants AI to handle the boring stuff \u2014 Assistants is built for you.
|
|
78440
|
+
`;
|
|
78441
|
+
context.emit("text", message);
|
|
78442
|
+
context.emit("done");
|
|
78443
|
+
return { handled: true };
|
|
78444
|
+
}
|
|
78445
|
+
};
|
|
78446
|
+
}
|
|
78447
|
+
docsCommand() {
|
|
78448
|
+
return {
|
|
78449
|
+
name: "docs",
|
|
78450
|
+
description: "Open docs panel in terminal or print full usage guide",
|
|
78451
|
+
builtin: true,
|
|
78452
|
+
selfHandled: true,
|
|
78453
|
+
content: "",
|
|
78454
|
+
handler: async (_args, context) => {
|
|
78455
|
+
let message = `
|
|
78456
|
+
**assistants Documentation**
|
|
78457
|
+
|
|
78458
|
+
`;
|
|
78459
|
+
message += "In the terminal app, `/docs` opens an interactive documentation panel with keyboard navigation.\n\n";
|
|
78460
|
+
message += `**Quick Start**
|
|
78461
|
+
`;
|
|
78462
|
+
message += " 1. Run `/init` in a project.\n";
|
|
78463
|
+
message += " 2. Run `/onboarding` to select provider, model, and API key setup.\n";
|
|
78464
|
+
message += " 3. Start work with `/new` and inspect status via `/status`, `/tokens`, and `/cost`.\n\n";
|
|
78465
|
+
message += `**Core Workflow**
|
|
78466
|
+
`;
|
|
78467
|
+
message += ` - Sessions keep history, tool calls, context, and model state.
|
|
78468
|
+
`;
|
|
78469
|
+
message += " - `/sessions` switches sessions.\n";
|
|
78470
|
+
message += " - `/compact` summarizes long context.\n";
|
|
78471
|
+
message += " - `/resume` recovers interrupted work.\n\n";
|
|
78472
|
+
message += `**Configuration and Models**
|
|
78473
|
+
`;
|
|
78474
|
+
message += " - `/model` opens interactive model selection.\n";
|
|
78475
|
+
message += " - `/config` manages user/project/local config.\n";
|
|
78476
|
+
message += " - `/memory`, `/context`, `/hooks`, and `/guardrails` control behavior and safety.\n\n";
|
|
78477
|
+
message += `**Workspaces and Projects**
|
|
78478
|
+
`;
|
|
78479
|
+
message += " - `/workspace` switches isolated workspace state.\n";
|
|
78480
|
+
message += " - `/projects` and `/plans` manage project scope and plan execution.\n\n";
|
|
78481
|
+
message += `**Resources and Operations**
|
|
78482
|
+
`;
|
|
78483
|
+
message += " - `/wallet`, `/secrets`, and `/budgets` manage cards, secrets, and limits.\n";
|
|
78484
|
+
message += " - `/tasks`, `/schedules`, `/jobs`, `/orders`, `/heartbeat`, and `/logs` manage operations.\n\n";
|
|
78485
|
+
message += `**Collaboration**
|
|
78486
|
+
`;
|
|
78487
|
+
message += " - `/assistants`, `/identity`, `/messages`, `/channels`, `/people`, `/telephony`.\n\n";
|
|
78488
|
+
message += `**Voice**
|
|
78489
|
+
`;
|
|
78490
|
+
message += " - `/voice`, `/listen`, `/talk`, `/say`.\n\n";
|
|
78491
|
+
message += `**Storage**
|
|
78492
|
+
`;
|
|
78493
|
+
message += " - Project data: `.assistants/`\n";
|
|
78494
|
+
message += " - User/global data: `~/.assistants/`\n";
|
|
78495
|
+
message += ` - Workspace switching isolates sessions, assistants, settings, and resource state.
|
|
78372
78496
|
`;
|
|
78373
78497
|
context.emit("text", message);
|
|
78374
78498
|
context.emit("done");
|
|
@@ -86888,6 +87012,140 @@ ${repoUrl}/issues/new
|
|
|
86888
87012
|
}
|
|
86889
87013
|
};
|
|
86890
87014
|
}
|
|
87015
|
+
diffCommand() {
|
|
87016
|
+
return {
|
|
87017
|
+
name: "diff",
|
|
87018
|
+
description: "Show git diff of current changes (supports --staged, <file>)",
|
|
87019
|
+
builtin: true,
|
|
87020
|
+
selfHandled: true,
|
|
87021
|
+
content: "",
|
|
87022
|
+
handler: async (args, context) => {
|
|
87023
|
+
const { exec } = await import("child_process");
|
|
87024
|
+
const { promisify } = await import("util");
|
|
87025
|
+
const execAsync = promisify(exec);
|
|
87026
|
+
const parts = splitArgs(args);
|
|
87027
|
+
try {
|
|
87028
|
+
let diffCmd = "git diff";
|
|
87029
|
+
let statCmd = "git diff --stat";
|
|
87030
|
+
if (parts.includes("--staged") || parts.includes("--cached")) {
|
|
87031
|
+
diffCmd += " --staged";
|
|
87032
|
+
statCmd += " --staged";
|
|
87033
|
+
const fileArgs = parts.filter((p) => p !== "--staged" && p !== "--cached");
|
|
87034
|
+
if (fileArgs.length > 0) {
|
|
87035
|
+
const files = fileArgs.map((f) => `'${f.replace(/'/g, "'\\''")}'`).join(" ");
|
|
87036
|
+
diffCmd += ` -- ${files}`;
|
|
87037
|
+
statCmd += ` -- ${files}`;
|
|
87038
|
+
}
|
|
87039
|
+
} else if (parts.length > 0) {
|
|
87040
|
+
const files = parts.map((f) => `'${f.replace(/'/g, "'\\''")}'`).join(" ");
|
|
87041
|
+
diffCmd += ` -- ${files}`;
|
|
87042
|
+
statCmd += ` -- ${files}`;
|
|
87043
|
+
}
|
|
87044
|
+
const opts = { cwd: context.cwd, maxBuffer: 1048576 };
|
|
87045
|
+
const [statResult, diffResult] = await Promise.all([
|
|
87046
|
+
execAsync(statCmd, opts).catch(() => ({ stdout: "" })),
|
|
87047
|
+
execAsync(diffCmd, opts).catch(() => ({ stdout: "" }))
|
|
87048
|
+
]);
|
|
87049
|
+
const statOutput = (statResult.stdout || "").trim();
|
|
87050
|
+
const diffOutput = (diffResult.stdout || "").trim();
|
|
87051
|
+
if (!statOutput && !diffOutput) {
|
|
87052
|
+
context.emit("text", `
|
|
87053
|
+
No changes detected.
|
|
87054
|
+
`);
|
|
87055
|
+
context.emit("done");
|
|
87056
|
+
return { handled: true };
|
|
87057
|
+
}
|
|
87058
|
+
let message = `
|
|
87059
|
+
**Git Diff**
|
|
87060
|
+
|
|
87061
|
+
`;
|
|
87062
|
+
if (statOutput) {
|
|
87063
|
+
message += "**Summary:**\n```\n" + statOutput + "\n```\n\n";
|
|
87064
|
+
}
|
|
87065
|
+
if (diffOutput) {
|
|
87066
|
+
message += "**Changes:**\n```diff\n" + diffOutput + "\n```\n";
|
|
87067
|
+
}
|
|
87068
|
+
context.emit("text", message);
|
|
87069
|
+
} catch {
|
|
87070
|
+
context.emit("text", `
|
|
87071
|
+
Not a git repository or git not available.
|
|
87072
|
+
`);
|
|
87073
|
+
}
|
|
87074
|
+
context.emit("done");
|
|
87075
|
+
return { handled: true };
|
|
87076
|
+
}
|
|
87077
|
+
};
|
|
87078
|
+
}
|
|
87079
|
+
undoCommand() {
|
|
87080
|
+
return {
|
|
87081
|
+
name: "undo",
|
|
87082
|
+
description: "Revert uncommitted changes (file, all, or show preview)",
|
|
87083
|
+
builtin: true,
|
|
87084
|
+
selfHandled: true,
|
|
87085
|
+
content: "",
|
|
87086
|
+
handler: async (args, context) => {
|
|
87087
|
+
const { exec } = await import("child_process");
|
|
87088
|
+
const { promisify } = await import("util");
|
|
87089
|
+
const execAsync = promisify(exec);
|
|
87090
|
+
const parts = splitArgs(args);
|
|
87091
|
+
const opts = { cwd: context.cwd };
|
|
87092
|
+
try {
|
|
87093
|
+
if (parts.length === 0) {
|
|
87094
|
+
const { stdout: stdout2 } = await execAsync("git diff --stat", opts);
|
|
87095
|
+
const statOutput = stdout2.trim();
|
|
87096
|
+
if (!statOutput) {
|
|
87097
|
+
context.emit("text", `
|
|
87098
|
+
No uncommitted changes to undo.
|
|
87099
|
+
`);
|
|
87100
|
+
context.emit("done");
|
|
87101
|
+
return { handled: true };
|
|
87102
|
+
}
|
|
87103
|
+
let message = "\n**Uncommitted Changes:**\n```\n" + statOutput + "\n```\n\n";
|
|
87104
|
+
message += "Use `/undo <file>` to revert a specific file\n";
|
|
87105
|
+
message += "Use `/undo all` to revert all changes\n";
|
|
87106
|
+
context.emit("text", message);
|
|
87107
|
+
context.emit("done");
|
|
87108
|
+
return { handled: true };
|
|
87109
|
+
}
|
|
87110
|
+
if (parts[0] === "all") {
|
|
87111
|
+
const { stdout: stdout2 } = await execAsync("git diff --stat", opts);
|
|
87112
|
+
const statOutput = stdout2.trim();
|
|
87113
|
+
if (!statOutput) {
|
|
87114
|
+
context.emit("text", `
|
|
87115
|
+
No uncommitted changes to undo.
|
|
87116
|
+
`);
|
|
87117
|
+
context.emit("done");
|
|
87118
|
+
return { handled: true };
|
|
87119
|
+
}
|
|
87120
|
+
await execAsync("git checkout -- .", opts);
|
|
87121
|
+
context.emit("text", "\n**Reverted all uncommitted changes:**\n```\n" + statOutput + "\n```\n");
|
|
87122
|
+
context.emit("done");
|
|
87123
|
+
return { handled: true };
|
|
87124
|
+
}
|
|
87125
|
+
const escaped = parts.map((f) => `'${f.replace(/'/g, "'\\''")}'`).join(" ");
|
|
87126
|
+
const { stdout } = await execAsync(`git diff --stat -- ${escaped}`, opts);
|
|
87127
|
+
const checkOutput = stdout.trim();
|
|
87128
|
+
if (!checkOutput) {
|
|
87129
|
+
context.emit("text", `
|
|
87130
|
+
No changes found for: ${parts.join(" ")}
|
|
87131
|
+
`);
|
|
87132
|
+
context.emit("done");
|
|
87133
|
+
return { handled: true };
|
|
87134
|
+
}
|
|
87135
|
+
await execAsync(`git checkout -- ${escaped}`, opts);
|
|
87136
|
+
context.emit("text", `
|
|
87137
|
+
**Reverted:** ${parts.join(" ")}
|
|
87138
|
+
`);
|
|
87139
|
+
} catch {
|
|
87140
|
+
context.emit("text", `
|
|
87141
|
+
Not a git repository or git not available.
|
|
87142
|
+
`);
|
|
87143
|
+
}
|
|
87144
|
+
context.emit("done");
|
|
87145
|
+
return { handled: true };
|
|
87146
|
+
}
|
|
87147
|
+
};
|
|
87148
|
+
}
|
|
86891
87149
|
async resolveProject(context, target) {
|
|
86892
87150
|
const byId = await readProject(context.cwd, target);
|
|
86893
87151
|
if (byId)
|
|
@@ -86918,7 +87176,7 @@ ${repoUrl}/issues/new
|
|
|
86918
87176
|
context.setProjectContext(projectContext);
|
|
86919
87177
|
}
|
|
86920
87178
|
}
|
|
86921
|
-
var VERSION2 = "1.1.
|
|
87179
|
+
var VERSION2 = "1.1.27";
|
|
86922
87180
|
var init_builtin = __esm(async () => {
|
|
86923
87181
|
init_src2();
|
|
86924
87182
|
init_store();
|
|
@@ -92083,14 +92341,22 @@ var init_conventions = __esm(() => {
|
|
|
92083
92341
|
});
|
|
92084
92342
|
|
|
92085
92343
|
// packages/core/src/heartbeat/auto-schedule-hook.ts
|
|
92086
|
-
|
|
92087
|
-
const
|
|
92344
|
+
function resolveHeartbeatConfig(input, context) {
|
|
92345
|
+
const inputHeartbeat = input.heartbeat;
|
|
92346
|
+
if (inputHeartbeat && typeof inputHeartbeat === "object") {
|
|
92347
|
+
return inputHeartbeat;
|
|
92348
|
+
}
|
|
92349
|
+
return context.config?.heartbeat;
|
|
92350
|
+
}
|
|
92351
|
+
async function autoScheduleHeartbeatHandler(input, context) {
|
|
92352
|
+
const heartbeatCfg = resolveHeartbeatConfig(input, context);
|
|
92088
92353
|
if (!heartbeatCfg?.autonomous)
|
|
92089
92354
|
return null;
|
|
92090
92355
|
const scheduleId = heartbeatScheduleId(context.sessionId);
|
|
92091
92356
|
try {
|
|
92092
92357
|
const existing = await getSchedule(context.cwd, scheduleId);
|
|
92093
|
-
|
|
92358
|
+
const hasValidNextRunAt = Number.isFinite(existing?.nextRunAt);
|
|
92359
|
+
if (existing && existing.status === "active" && hasValidNextRunAt) {
|
|
92094
92360
|
return null;
|
|
92095
92361
|
}
|
|
92096
92362
|
const maxSleep = heartbeatCfg.maxSleepMs ?? DEFAULT_MAX_SLEEP_MS;
|
|
@@ -92135,11 +92401,13 @@ var init_auto_schedule_hook = __esm(async () => {
|
|
|
92135
92401
|
async function ensureWatchdogSchedule(cwd, sessionId, intervalMs = DEFAULT_WATCHDOG_INTERVAL_MS) {
|
|
92136
92402
|
const scheduleId = watchdogScheduleId(sessionId);
|
|
92137
92403
|
const existing = await getSchedule(cwd, scheduleId);
|
|
92138
|
-
|
|
92404
|
+
const existingHasValidNextRunAt = Number.isFinite(existing?.nextRunAt);
|
|
92405
|
+
if (existing && existing.status === "active" && existingHasValidNextRunAt) {
|
|
92139
92406
|
return;
|
|
92140
92407
|
}
|
|
92141
92408
|
const legacy = await getSchedule(cwd, WATCHDOG_SCHEDULE_ID);
|
|
92142
|
-
|
|
92409
|
+
const legacyHasValidNextRunAt = Number.isFinite(legacy?.nextRunAt);
|
|
92410
|
+
if (legacy && legacy.status === "active" && legacy.sessionId === sessionId && legacyHasValidNextRunAt) {
|
|
92143
92411
|
return;
|
|
92144
92412
|
}
|
|
92145
92413
|
const intervalSeconds = Math.max(60, Math.round(intervalMs / 1000));
|
|
@@ -92170,24 +92438,33 @@ var init_watchdog = __esm(async () => {
|
|
|
92170
92438
|
|
|
92171
92439
|
// packages/core/src/heartbeat/install-skills.ts
|
|
92172
92440
|
import { join as join30 } from "path";
|
|
92173
|
-
async function
|
|
92174
|
-
const { mkdir: mkdir10, writeFile: writeFile8,
|
|
92441
|
+
async function writeSkillIfNeeded(dir, skillName, content) {
|
|
92442
|
+
const { mkdir: mkdir10, writeFile: writeFile8, readFile: readFile11 } = await import("fs/promises");
|
|
92175
92443
|
const skillDir = join30(dir, `skill-${skillName}`);
|
|
92176
92444
|
const skillFile = join30(skillDir, "SKILL.md");
|
|
92177
|
-
try {
|
|
92178
|
-
await access(skillFile);
|
|
92179
|
-
return false;
|
|
92180
|
-
} catch {}
|
|
92181
92445
|
await mkdir10(skillDir, { recursive: true });
|
|
92182
|
-
|
|
92183
|
-
|
|
92446
|
+
try {
|
|
92447
|
+
const existing = await readFile11(skillFile, "utf-8");
|
|
92448
|
+
if (existing === content) {
|
|
92449
|
+
return false;
|
|
92450
|
+
}
|
|
92451
|
+
const hasLegacyPatterns = LEGACY_SKILL_PATTERNS.some((pattern) => pattern.test(existing));
|
|
92452
|
+
if (!hasLegacyPatterns) {
|
|
92453
|
+
return false;
|
|
92454
|
+
}
|
|
92455
|
+
await writeFile8(skillFile, content, "utf-8");
|
|
92456
|
+
return true;
|
|
92457
|
+
} catch {
|
|
92458
|
+
await writeFile8(skillFile, content, "utf-8");
|
|
92459
|
+
return true;
|
|
92460
|
+
}
|
|
92184
92461
|
}
|
|
92185
92462
|
async function installHeartbeatSkills() {
|
|
92186
92463
|
const sharedSkillsDir = join30(getConfigDir(), "shared", "skills");
|
|
92187
92464
|
const installed = [];
|
|
92188
92465
|
const results = await Promise.all([
|
|
92189
|
-
|
|
92190
|
-
|
|
92466
|
+
writeSkillIfNeeded(sharedSkillsDir, "main-loop", MAIN_LOOP_SKILL),
|
|
92467
|
+
writeSkillIfNeeded(sharedSkillsDir, "watchdog", WATCHDOG_SKILL)
|
|
92191
92468
|
]);
|
|
92192
92469
|
if (results[0])
|
|
92193
92470
|
installed.push("main-loop");
|
|
@@ -92216,8 +92493,8 @@ You are running as an autonomous heartbeat turn. This is a scheduled wakeup \u20
|
|
|
92216
92493
|
- \`memory_save agent.state.lastActions "..."\` with a brief summary of what you did this turn.
|
|
92217
92494
|
- \`memory_save agent.state.pending "..."\` with any items still pending.
|
|
92218
92495
|
7. **Schedule next heartbeat** \u2014 choose when you should wake up next based on urgency:
|
|
92219
|
-
- Delete the old heartbeat schedule: \`
|
|
92220
|
-
- Create a new schedule: \`
|
|
92496
|
+
- Delete the old heartbeat schedule: call \`schedule\` with \`{ action: "delete", id: "heartbeat-{SESSION_ID}" }\`
|
|
92497
|
+
- Create a new schedule: call \`schedule\` with \`action: "create"\`, \`actionType: "message"\`, \`message: "/main-loop"\`, and either \`at\` (one-shot) or \`cron\` + \`startImmediately: true\` (recurring).
|
|
92221
92498
|
- Save your reasoning: \`memory_save agent.heartbeat.intention "..."\`
|
|
92222
92499
|
8. **Record timestamp** \u2014 \`memory_save agent.heartbeat.last\` with the current ISO timestamp.
|
|
92223
92500
|
|
|
@@ -92237,7 +92514,7 @@ You are running as an autonomous heartbeat turn. This is a scheduled wakeup \u20
|
|
|
92237
92514
|
name: watchdog
|
|
92238
92515
|
description: Safety-net watchdog \u2014 checks if the heartbeat is healthy and forces a wakeup if overdue.
|
|
92239
92516
|
user-invocable: false
|
|
92240
|
-
allowed-tools: memory_recall, memory_save,
|
|
92517
|
+
allowed-tools: memory_recall, memory_save, schedule
|
|
92241
92518
|
---
|
|
92242
92519
|
|
|
92243
92520
|
## Watchdog Check
|
|
@@ -92249,14 +92526,20 @@ You are the watchdog. Your only job is to verify the heartbeat is running and fo
|
|
|
92249
92526
|
1. Read \`memory_recall agent.heartbeat.last\` to get the last heartbeat timestamp.
|
|
92250
92527
|
2. Read \`memory_recall agent.heartbeat.next\` to get the expected next heartbeat time.
|
|
92251
92528
|
3. If the last heartbeat is more than **double** the expected interval overdue:
|
|
92252
|
-
- Call \`
|
|
92529
|
+
- Call \`schedule\` with \`{ action: "list" }\` to check if a heartbeat schedule exists.
|
|
92253
92530
|
- If no active heartbeat schedule exists, create one that fires immediately:
|
|
92254
|
-
\`
|
|
92531
|
+
call \`schedule\` with \`action: "create"\`, \`actionType: "message"\`, \`message: "/main-loop"\`, and \`cron: "* * * * *"\` + \`startImmediately: true\`.
|
|
92255
92532
|
- Save \`memory_save agent.heartbeat.intention "Watchdog forced wakeup \u2014 heartbeat was overdue."\`
|
|
92256
92533
|
4. If the heartbeat is healthy, do nothing.
|
|
92257
|
-
|
|
92534
|
+
`, LEGACY_SKILL_PATTERNS;
|
|
92258
92535
|
var init_install_skills = __esm(async () => {
|
|
92259
92536
|
await init_config();
|
|
92537
|
+
LEGACY_SKILL_PATTERNS = [
|
|
92538
|
+
/`schedule_create`/,
|
|
92539
|
+
/`schedule_delete`/,
|
|
92540
|
+
/`schedules_list`/,
|
|
92541
|
+
/allowed-tools:\s*.*schedule_create/i
|
|
92542
|
+
];
|
|
92260
92543
|
});
|
|
92261
92544
|
|
|
92262
92545
|
// packages/core/src/heartbeat/index.ts
|
|
@@ -186336,15 +186619,6 @@ var init_loop = __esm(async () => {
|
|
|
186336
186619
|
if (heartbeatCfg?.autonomous) {
|
|
186337
186620
|
nativeHookRegistry.register(createAutoScheduleHeartbeatHook());
|
|
186338
186621
|
installHeartbeatSkills().catch(() => {});
|
|
186339
|
-
nativeHookRegistry.setConfig({
|
|
186340
|
-
...nativeHookRegistry.getConfig(),
|
|
186341
|
-
heartbeat: {
|
|
186342
|
-
autonomous: heartbeatCfg.autonomous,
|
|
186343
|
-
maxSleepMs: heartbeatCfg.maxSleepMs,
|
|
186344
|
-
watchdogEnabled: heartbeatCfg.watchdogEnabled,
|
|
186345
|
-
watchdogIntervalMs: heartbeatCfg.watchdogIntervalMs
|
|
186346
|
-
}
|
|
186347
|
-
});
|
|
186348
186622
|
if (heartbeatCfg.watchdogEnabled) {
|
|
186349
186623
|
ensureWatchdogSchedule(this.cwd, this.sessionId, heartbeatCfg.watchdogIntervalMs).catch(() => {});
|
|
186350
186624
|
}
|
|
@@ -186380,8 +186654,8 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
186380
186654
|
- \`memory_save agent.state.pending "items waiting for follow-up"\`
|
|
186381
186655
|
- \`memory_save agent.state.lastActions "what you just did"\`
|
|
186382
186656
|
2. **Schedule your next heartbeat**:
|
|
186383
|
-
- Delete old: \`
|
|
186384
|
-
- Create new: \`
|
|
186657
|
+
- Delete old: call \`schedule\` with \`{ action: "delete", id: "heartbeat-${this.sessionId}" }\`
|
|
186658
|
+
- Create new: call \`schedule\` with \`action: "create"\`, \`actionType: "message"\`, \`message: "/main-loop"\`, and either \`at\` (one-shot) or \`cron\` + \`startImmediately: true\` (recurring)
|
|
186385
186659
|
3. **Save goals** when they change: \`memory_save agent.goals "..."\`
|
|
186386
186660
|
|
|
186387
186661
|
### Timing guidelines
|
|
@@ -186635,9 +186909,9 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
186635
186909
|
turn++;
|
|
186636
186910
|
this.cumulativeTurns++;
|
|
186637
186911
|
if (this.paused) {
|
|
186638
|
-
this.onBudgetWarning?.("Budget exceeded - agent paused. Use /
|
|
186912
|
+
this.onBudgetWarning?.("Budget exceeded - agent paused. Use /budgets resume to continue.");
|
|
186639
186913
|
this.emit({ type: "text", content: `
|
|
186640
|
-
[Agent paused - budget exceeded. Use /
|
|
186914
|
+
[Agent paused - budget exceeded. Use /budgets resume to continue.]
|
|
186641
186915
|
` });
|
|
186642
186916
|
await new Promise((resolve5) => {
|
|
186643
186917
|
this.pauseResolve = resolve5;
|
|
@@ -186714,11 +186988,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
186714
186988
|
});
|
|
186715
186989
|
} catch {}
|
|
186716
186990
|
try {
|
|
186717
|
-
await nativeHookRegistry.execute("Stop", {
|
|
186718
|
-
session_id: this.sessionId,
|
|
186719
|
-
hook_event_name: "Stop",
|
|
186720
|
-
cwd: this.cwd
|
|
186721
|
-
}, {
|
|
186991
|
+
await nativeHookRegistry.execute("Stop", this.buildNativeStopHookInput(), {
|
|
186722
186992
|
sessionId: this.sessionId,
|
|
186723
186993
|
cwd: this.cwd,
|
|
186724
186994
|
messages: this.context.getMessages()
|
|
@@ -186840,11 +187110,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
186840
187110
|
if (!scopeContext) {
|
|
186841
187111
|
return null;
|
|
186842
187112
|
}
|
|
186843
|
-
const result = await nativeHookRegistry.execute("Stop", {
|
|
186844
|
-
session_id: this.sessionId,
|
|
186845
|
-
hook_event_name: "Stop",
|
|
186846
|
-
cwd: this.cwd
|
|
186847
|
-
}, {
|
|
187113
|
+
const result = await nativeHookRegistry.execute("Stop", this.buildNativeStopHookInput(), {
|
|
186848
187114
|
sessionId: this.sessionId,
|
|
186849
187115
|
cwd: this.cwd,
|
|
186850
187116
|
messages: this.context.getMessages(),
|
|
@@ -186859,6 +187125,20 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
186859
187125
|
systemMessage: result.systemMessage
|
|
186860
187126
|
};
|
|
186861
187127
|
}
|
|
187128
|
+
buildNativeStopHookInput() {
|
|
187129
|
+
const heartbeatCfg = this.config?.heartbeat;
|
|
187130
|
+
return {
|
|
187131
|
+
session_id: this.sessionId,
|
|
187132
|
+
hook_event_name: "Stop",
|
|
187133
|
+
cwd: this.cwd,
|
|
187134
|
+
heartbeat: heartbeatCfg ? {
|
|
187135
|
+
autonomous: heartbeatCfg.autonomous,
|
|
187136
|
+
maxSleepMs: heartbeatCfg.maxSleepMs,
|
|
187137
|
+
watchdogEnabled: heartbeatCfg.watchdogEnabled,
|
|
187138
|
+
watchdogIntervalMs: heartbeatCfg.watchdogIntervalMs
|
|
187139
|
+
} : undefined
|
|
187140
|
+
};
|
|
187141
|
+
}
|
|
186862
187142
|
async firePostToolUseFailure(toolCall, resultContent) {
|
|
186863
187143
|
await this.hookExecutor.execute(this.hookLoader.getHooks("PostToolUseFailure"), {
|
|
186864
187144
|
session_id: this.sessionId,
|
|
@@ -187323,9 +187603,32 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
187323
187603
|
setBudgetEnabled: (enabled) => {
|
|
187324
187604
|
if (this.budgetTracker) {
|
|
187325
187605
|
this.budgetTracker.setEnabled(enabled);
|
|
187326
|
-
|
|
187327
|
-
|
|
187328
|
-
|
|
187606
|
+
this.budgetConfig = this.budgetTracker.getConfig();
|
|
187607
|
+
return;
|
|
187608
|
+
}
|
|
187609
|
+
if (!enabled) {
|
|
187610
|
+
if (this.budgetConfig) {
|
|
187611
|
+
this.budgetConfig = {
|
|
187612
|
+
...this.budgetConfig,
|
|
187613
|
+
enabled: false
|
|
187614
|
+
};
|
|
187615
|
+
}
|
|
187616
|
+
return;
|
|
187617
|
+
}
|
|
187618
|
+
const seed = this.budgetConfig || DEFAULT_BUDGET_CONFIG;
|
|
187619
|
+
this.budgetConfig = {
|
|
187620
|
+
...DEFAULT_BUDGET_CONFIG,
|
|
187621
|
+
...seed,
|
|
187622
|
+
session: { ...DEFAULT_BUDGET_CONFIG.session || {}, ...seed.session || {} },
|
|
187623
|
+
assistant: { ...DEFAULT_BUDGET_CONFIG.assistant || {}, ...seed.assistant || {} },
|
|
187624
|
+
swarm: { ...DEFAULT_BUDGET_CONFIG.swarm || {}, ...seed.swarm || {} },
|
|
187625
|
+
project: { ...DEFAULT_BUDGET_CONFIG.project || {}, ...seed.project || {} },
|
|
187626
|
+
enabled: true
|
|
187627
|
+
};
|
|
187628
|
+
this.budgetTracker = new BudgetTracker(this.sessionId, this.budgetConfig);
|
|
187629
|
+
this.budgetTracker.setEnabled(true);
|
|
187630
|
+
if (this.activeProjectId) {
|
|
187631
|
+
this.budgetTracker.setActiveProject(this.activeProjectId);
|
|
187329
187632
|
}
|
|
187330
187633
|
},
|
|
187331
187634
|
resetBudget: (scope) => {
|
|
@@ -187751,7 +188054,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
|
|
|
187751
188054
|
this.onBudgetWarning?.("Budget exceeded - stopping assistant");
|
|
187752
188055
|
this.stop();
|
|
187753
188056
|
} else if (onExceeded === "pause") {
|
|
187754
|
-
this.onBudgetWarning?.("Budget exceeded - pausing (requires /
|
|
188057
|
+
this.onBudgetWarning?.("Budget exceeded - pausing (requires /budgets resume to continue)");
|
|
187755
188058
|
this.paused = true;
|
|
187756
188059
|
}
|
|
187757
188060
|
}
|
|
@@ -210481,6 +210784,12 @@ function useSafeInput(handler, options = {}) {
|
|
|
210481
210784
|
` : "\x1B\r";
|
|
210482
210785
|
}
|
|
210483
210786
|
const key2 = { ...inkKey };
|
|
210787
|
+
if ((input2 === "m" || input2 === "j") && key2.ctrl && !key2.return) {
|
|
210788
|
+
input2 = input2 === "j" ? `
|
|
210789
|
+
` : "\r";
|
|
210790
|
+
key2.return = true;
|
|
210791
|
+
key2.ctrl = false;
|
|
210792
|
+
}
|
|
210484
210793
|
const isReturnInput = input2 === "\r" || input2 === `
|
|
210485
210794
|
` || input2 === `\r
|
|
210486
210795
|
` || input2 === `
|
|
@@ -210610,6 +210919,8 @@ var COMMANDS = [
|
|
|
210610
210919
|
{ name: "/secrets", description: "manage assistant secrets" },
|
|
210611
210920
|
{ name: "/jobs", description: "manage background jobs" },
|
|
210612
210921
|
{ name: "/docs", description: "interactive app documentation" },
|
|
210922
|
+
{ name: "/diff", description: "show git diff of changes" },
|
|
210923
|
+
{ name: "/undo", description: "revert uncommitted changes" },
|
|
210613
210924
|
{ name: "/rest", description: "enter rest mode" },
|
|
210614
210925
|
{ name: "/logs", description: "view security event logs" },
|
|
210615
210926
|
{ name: "/verification", description: "scope verification status" },
|
|
@@ -210644,6 +210955,7 @@ function isLargePaste(text, thresholds = DEFAULT_PASTE_THRESHOLDS) {
|
|
|
210644
210955
|
}
|
|
210645
210956
|
var Input = import_react28.default.forwardRef(function Input2({
|
|
210646
210957
|
onSubmit,
|
|
210958
|
+
onStopProcessing,
|
|
210647
210959
|
isProcessing,
|
|
210648
210960
|
queueLength = 0,
|
|
210649
210961
|
commands: commands9,
|
|
@@ -210657,7 +210969,8 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
210657
210969
|
pasteConfig,
|
|
210658
210970
|
isRecording = false,
|
|
210659
210971
|
recordingStatus,
|
|
210660
|
-
onStopRecording
|
|
210972
|
+
onStopRecording,
|
|
210973
|
+
onFileSearch
|
|
210661
210974
|
}, ref) {
|
|
210662
210975
|
const pasteEnabled = pasteConfig?.enabled !== false;
|
|
210663
210976
|
const pasteThresholds = pasteConfig?.thresholds ?? DEFAULT_PASTE_THRESHOLDS;
|
|
@@ -210712,8 +211025,14 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
210712
211025
|
if (value.startsWith("/") && !value.includes(" ")) {
|
|
210713
211026
|
return "command";
|
|
210714
211027
|
}
|
|
211028
|
+
if (onFileSearch) {
|
|
211029
|
+
const atMatch = value.match(/(?:^|.*\s)@([^\s]*)$/);
|
|
211030
|
+
if (atMatch) {
|
|
211031
|
+
return "file";
|
|
211032
|
+
}
|
|
211033
|
+
}
|
|
210715
211034
|
return null;
|
|
210716
|
-
}, [value, isAskingUser]);
|
|
211035
|
+
}, [value, isAskingUser, onFileSearch]);
|
|
210717
211036
|
const filteredCommands = import_react28.useMemo(() => {
|
|
210718
211037
|
if (autocompleteMode !== "command")
|
|
210719
211038
|
return [];
|
|
@@ -210726,7 +211045,18 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
210726
211045
|
const search = value.slice(1).toLowerCase();
|
|
210727
211046
|
return skills.filter((skill) => skill.name.toLowerCase().startsWith(search));
|
|
210728
211047
|
}, [value, autocompleteMode, skills]);
|
|
210729
|
-
const
|
|
211048
|
+
const fileSearchQuery = import_react28.useMemo(() => {
|
|
211049
|
+
if (autocompleteMode !== "file")
|
|
211050
|
+
return "";
|
|
211051
|
+
const atMatch = value.match(/(?:^|.*\s)@([^\s]*)$/);
|
|
211052
|
+
return atMatch ? atMatch[1] : "";
|
|
211053
|
+
}, [value, autocompleteMode]);
|
|
211054
|
+
const filteredFiles = import_react28.useMemo(() => {
|
|
211055
|
+
if (autocompleteMode !== "file" || !onFileSearch)
|
|
211056
|
+
return [];
|
|
211057
|
+
return onFileSearch(fileSearchQuery);
|
|
211058
|
+
}, [autocompleteMode, fileSearchQuery, onFileSearch]);
|
|
211059
|
+
const autocompleteItems = autocompleteMode === "skill" ? filteredSkills : autocompleteMode === "file" ? filteredFiles.map((f6) => ({ name: f6 })) : filteredCommands;
|
|
210730
211060
|
import_react28.useEffect(() => {
|
|
210731
211061
|
if (autocompleteItems.length === 0) {
|
|
210732
211062
|
setSelectedIndex(0);
|
|
@@ -210907,6 +211237,10 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
210907
211237
|
return;
|
|
210908
211238
|
}
|
|
210909
211239
|
if (key.escape && !isAskingUser) {
|
|
211240
|
+
if (isProcessing && onStopProcessing) {
|
|
211241
|
+
onStopProcessing();
|
|
211242
|
+
return;
|
|
211243
|
+
}
|
|
210910
211244
|
if (largePaste) {
|
|
210911
211245
|
setLargePaste(null);
|
|
210912
211246
|
setShowPastePreview(false);
|
|
@@ -210932,8 +211266,15 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
210932
211266
|
if (key.tab) {
|
|
210933
211267
|
if (autocompleteItems.length > 0) {
|
|
210934
211268
|
const selected = autocompleteItems[selectedIndex] || autocompleteItems[0];
|
|
210935
|
-
|
|
210936
|
-
|
|
211269
|
+
if (autocompleteMode === "file") {
|
|
211270
|
+
const atMatch = value.match(/^(.*(?:^|\s))@[^\s]*$/);
|
|
211271
|
+
const prefix2 = atMatch ? atMatch[1] : "";
|
|
211272
|
+
const nextValue = prefix2 + selected.name + " ";
|
|
211273
|
+
setValueAndCursor(nextValue);
|
|
211274
|
+
} else {
|
|
211275
|
+
const nextValue = autocompleteMode === "skill" ? `$${selected.name} ` : `${selected.name} `;
|
|
211276
|
+
setValueAndCursor(nextValue);
|
|
211277
|
+
}
|
|
210937
211278
|
return;
|
|
210938
211279
|
}
|
|
210939
211280
|
if (isProcessing && value.trim()) {
|
|
@@ -211013,12 +211354,6 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
211013
211354
|
deleteForward();
|
|
211014
211355
|
return;
|
|
211015
211356
|
}
|
|
211016
|
-
if (input === "\x1B\r" || input === `\x1B
|
|
211017
|
-
`) {
|
|
211018
|
-
insertText(`
|
|
211019
|
-
`);
|
|
211020
|
-
return;
|
|
211021
|
-
}
|
|
211022
211357
|
if (key.return) {
|
|
211023
211358
|
if (isRecording && onStopRecording) {
|
|
211024
211359
|
onStopRecording();
|
|
@@ -211029,7 +211364,8 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
211029
211364
|
setValueAndCursor("");
|
|
211030
211365
|
return;
|
|
211031
211366
|
}
|
|
211032
|
-
if (key.meta && value.trim()
|
|
211367
|
+
if (key.meta && value.trim() && input !== "\x1B\r" && input !== `\x1B
|
|
211368
|
+
`) {
|
|
211033
211369
|
onSubmit(value, "queue");
|
|
211034
211370
|
setValueAndCursor("");
|
|
211035
211371
|
return;
|
|
@@ -211068,6 +211404,8 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
211068
211404
|
};
|
|
211069
211405
|
const visibleSkills = getVisibleItems(filteredSkills);
|
|
211070
211406
|
const visibleCommands = getVisibleItems(filteredCommands);
|
|
211407
|
+
const fileItems = import_react28.useMemo(() => filteredFiles.map((f6) => ({ name: f6 })), [filteredFiles]);
|
|
211408
|
+
const visibleFiles = getVisibleItems(fileItems);
|
|
211071
211409
|
const layout = buildLayout(value, cursor, textWidth);
|
|
211072
211410
|
const lines = layout.displayLines;
|
|
211073
211411
|
const lineCount = value.split(`
|
|
@@ -211340,6 +211678,41 @@ var Input = import_react28.default.forwardRef(function Input2({
|
|
|
211340
211678
|
]
|
|
211341
211679
|
}, undefined, true, undefined, this)
|
|
211342
211680
|
]
|
|
211681
|
+
}, undefined, true, undefined, this),
|
|
211682
|
+
autocompleteMode === "file" && filteredFiles.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
211683
|
+
flexDirection: "column",
|
|
211684
|
+
marginTop: 1,
|
|
211685
|
+
marginLeft: 2,
|
|
211686
|
+
children: [
|
|
211687
|
+
visibleFiles.startIndex > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text3, {
|
|
211688
|
+
dimColor: true,
|
|
211689
|
+
children: [
|
|
211690
|
+
" \u2191 ",
|
|
211691
|
+
visibleFiles.startIndex,
|
|
211692
|
+
" more above"
|
|
211693
|
+
]
|
|
211694
|
+
}, undefined, true, undefined, this),
|
|
211695
|
+
visibleFiles.items.map((file, i5) => {
|
|
211696
|
+
const actualIndex = visibleFiles.startIndex + i5;
|
|
211697
|
+
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
211698
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text3, {
|
|
211699
|
+
color: actualIndex === selectedIndex ? "cyan" : "#5fb3a1",
|
|
211700
|
+
children: [
|
|
211701
|
+
actualIndex === selectedIndex ? "\u25B8 " : " ",
|
|
211702
|
+
file.name
|
|
211703
|
+
]
|
|
211704
|
+
}, undefined, true, undefined, this)
|
|
211705
|
+
}, file.name, false, undefined, this);
|
|
211706
|
+
}),
|
|
211707
|
+
visibleFiles.startIndex + maxVisible < filteredFiles.length && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text3, {
|
|
211708
|
+
dimColor: true,
|
|
211709
|
+
children: [
|
|
211710
|
+
" \u2193 ",
|
|
211711
|
+
filteredFiles.length - visibleFiles.startIndex - maxVisible,
|
|
211712
|
+
" more below"
|
|
211713
|
+
]
|
|
211714
|
+
}, undefined, true, undefined, this)
|
|
211715
|
+
]
|
|
211343
211716
|
}, undefined, true, undefined, this)
|
|
211344
211717
|
]
|
|
211345
211718
|
}, undefined, true, undefined, this);
|
|
@@ -213778,7 +214151,8 @@ function Status({
|
|
|
213778
214151
|
backgroundProcessingCount = 0,
|
|
213779
214152
|
processingStartTime,
|
|
213780
214153
|
verboseTools = false,
|
|
213781
|
-
recentTools = []
|
|
214154
|
+
recentTools = [],
|
|
214155
|
+
gitBranch
|
|
213782
214156
|
}) {
|
|
213783
214157
|
const [elapsed, setElapsed] = import_react30.useState(0);
|
|
213784
214158
|
const [heartbeatCountdown, setHeartbeatCountdown] = import_react30.useState("");
|
|
@@ -213879,7 +214253,8 @@ function Status({
|
|
|
213879
214253
|
dimColor: true,
|
|
213880
214254
|
children: [
|
|
213881
214255
|
"/help",
|
|
213882
|
-
sessionCount && sessionCount > 1 ? " \xB7 Ctrl+]" : ""
|
|
214256
|
+
sessionCount && sessionCount > 1 ? " \xB7 Ctrl+]" : "",
|
|
214257
|
+
gitBranch ? ` \xB7 \u2387 ${gitBranch}` : ""
|
|
213883
214258
|
]
|
|
213884
214259
|
}, undefined, true, undefined, this),
|
|
213885
214260
|
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
@@ -214851,6 +215226,7 @@ function ConnectorsPanel({
|
|
|
214851
215226
|
const [loadedConnectors, setLoadedConnectors] = import_react36.useState(new Map);
|
|
214852
215227
|
const [autoRefreshEntries, setAutoRefreshEntries] = import_react36.useState(new Map);
|
|
214853
215228
|
const [autoRefreshError, setAutoRefreshError] = import_react36.useState(null);
|
|
215229
|
+
const pendingAuthChecksRef = import_react36.useRef(new Set);
|
|
214854
215230
|
const filteredConnectors = import_react36.useMemo(() => {
|
|
214855
215231
|
if (!searchQuery.trim()) {
|
|
214856
215232
|
return connectors;
|
|
@@ -214874,24 +215250,6 @@ function ConnectorsPanel({
|
|
|
214874
215250
|
}
|
|
214875
215251
|
}
|
|
214876
215252
|
}, [initialConnector, filteredConnectors]);
|
|
214877
|
-
import_react36.useEffect(() => {
|
|
214878
|
-
const loadStatuses = async () => {
|
|
214879
|
-
const results = await Promise.all(connectors.map(async (connector) => {
|
|
214880
|
-
try {
|
|
214881
|
-
const status = await onCheckAuth(connector);
|
|
214882
|
-
return { name: connector.name, status };
|
|
214883
|
-
} catch {
|
|
214884
|
-
return { name: connector.name, status: { authenticated: false, error: "Failed to check" } };
|
|
214885
|
-
}
|
|
214886
|
-
}));
|
|
214887
|
-
const statusMap = new Map;
|
|
214888
|
-
for (const { name: name2, status } of results) {
|
|
214889
|
-
statusMap.set(name2, status);
|
|
214890
|
-
}
|
|
214891
|
-
setAuthStatuses(statusMap);
|
|
214892
|
-
};
|
|
214893
|
-
loadStatuses();
|
|
214894
|
-
}, [connectors, onCheckAuth]);
|
|
214895
215253
|
const loadAutoRefreshEntries = import_react36.useCallback(async () => {
|
|
214896
215254
|
try {
|
|
214897
215255
|
const manager = ConnectorAutoRefreshManager.getInstance();
|
|
@@ -214991,6 +215349,10 @@ function ConnectorsPanel({
|
|
|
214991
215349
|
}, [mode, loadCommandHelp]);
|
|
214992
215350
|
useSafeInput((input, key) => {
|
|
214993
215351
|
if (isSearching) {
|
|
215352
|
+
if (input === "q" || input === "Q") {
|
|
215353
|
+
onClose();
|
|
215354
|
+
return;
|
|
215355
|
+
}
|
|
214994
215356
|
if (key.escape) {
|
|
214995
215357
|
if (searchQuery) {
|
|
214996
215358
|
setSearchQuery("");
|
|
@@ -215049,7 +215411,7 @@ function ConnectorsPanel({
|
|
|
215049
215411
|
if (key.upArrow) {
|
|
215050
215412
|
if (mode === "list" && filteredConnectors.length > 0) {
|
|
215051
215413
|
setConnectorIndex((prev) => prev === 0 ? filteredConnectors.length - 1 : prev - 1);
|
|
215052
|
-
} else if (mode === "detail") {
|
|
215414
|
+
} else if (mode === "detail" && currentCommands.length > 0) {
|
|
215053
215415
|
setCommandIndex((prev) => prev === 0 ? currentCommands.length - 1 : prev - 1);
|
|
215054
215416
|
}
|
|
215055
215417
|
return;
|
|
@@ -215057,7 +215419,7 @@ function ConnectorsPanel({
|
|
|
215057
215419
|
if (key.downArrow) {
|
|
215058
215420
|
if (mode === "list" && filteredConnectors.length > 0) {
|
|
215059
215421
|
setConnectorIndex((prev) => prev === filteredConnectors.length - 1 ? 0 : prev + 1);
|
|
215060
|
-
} else if (mode === "detail") {
|
|
215422
|
+
} else if (mode === "detail" && currentCommands.length > 0) {
|
|
215061
215423
|
setCommandIndex((prev) => prev === currentCommands.length - 1 ? 0 : prev + 1);
|
|
215062
215424
|
}
|
|
215063
215425
|
return;
|
|
@@ -215071,10 +215433,6 @@ function ConnectorsPanel({
|
|
|
215071
215433
|
}
|
|
215072
215434
|
return;
|
|
215073
215435
|
}
|
|
215074
|
-
if (mode === "list" && input && /^[a-zA-Z]$/.test(input)) {
|
|
215075
|
-
setIsSearching(true);
|
|
215076
|
-
setSearchQuery(input);
|
|
215077
|
-
}
|
|
215078
215436
|
});
|
|
215079
215437
|
const getStatusIcon = (status) => {
|
|
215080
215438
|
if (!status)
|
|
@@ -215088,6 +215446,45 @@ function ConnectorsPanel({
|
|
|
215088
215446
|
const connectorRange = import_react36.useMemo(() => getVisibleRange(safeConnectorIndex, filteredConnectors.length), [safeConnectorIndex, filteredConnectors.length]);
|
|
215089
215447
|
const commandRange = import_react36.useMemo(() => getVisibleRange(commandIndex, currentCommands.length), [commandIndex, currentCommands.length]);
|
|
215090
215448
|
const visibleConnectors = filteredConnectors.slice(connectorRange.start, connectorRange.end);
|
|
215449
|
+
import_react36.useEffect(() => {
|
|
215450
|
+
const targets = mode === "list" ? visibleConnectors : currentConnector ? [currentConnector] : [];
|
|
215451
|
+
if (targets.length === 0) {
|
|
215452
|
+
return;
|
|
215453
|
+
}
|
|
215454
|
+
let cancelled = false;
|
|
215455
|
+
const loadStatuses = async () => {
|
|
215456
|
+
for (const connector of targets) {
|
|
215457
|
+
const name2 = connector.name;
|
|
215458
|
+
if (authStatuses.has(name2) || pendingAuthChecksRef.current.has(name2)) {
|
|
215459
|
+
continue;
|
|
215460
|
+
}
|
|
215461
|
+
pendingAuthChecksRef.current.add(name2);
|
|
215462
|
+
try {
|
|
215463
|
+
let status;
|
|
215464
|
+
try {
|
|
215465
|
+
status = await onCheckAuth(connector);
|
|
215466
|
+
} catch {
|
|
215467
|
+
status = { authenticated: false, error: "Failed to check" };
|
|
215468
|
+
}
|
|
215469
|
+
if (cancelled)
|
|
215470
|
+
continue;
|
|
215471
|
+
setAuthStatuses((prev) => {
|
|
215472
|
+
if (prev.has(name2))
|
|
215473
|
+
return prev;
|
|
215474
|
+
const next = new Map(prev);
|
|
215475
|
+
next.set(name2, status);
|
|
215476
|
+
return next;
|
|
215477
|
+
});
|
|
215478
|
+
} finally {
|
|
215479
|
+
pendingAuthChecksRef.current.delete(name2);
|
|
215480
|
+
}
|
|
215481
|
+
}
|
|
215482
|
+
};
|
|
215483
|
+
loadStatuses();
|
|
215484
|
+
return () => {
|
|
215485
|
+
cancelled = true;
|
|
215486
|
+
};
|
|
215487
|
+
}, [authStatuses, currentConnector, mode, onCheckAuth, visibleConnectors]);
|
|
215091
215488
|
if (connectors.length === 0) {
|
|
215092
215489
|
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
215093
215490
|
flexDirection: "column",
|
|
@@ -226654,16 +227051,16 @@ function JobsPanel({ manager, onClose }) {
|
|
|
226654
227051
|
if (!job || isWorking)
|
|
226655
227052
|
return;
|
|
226656
227053
|
if (!isActiveStatus(job.status)) {
|
|
226657
|
-
setStatusMessage(`Job ${job.id} is ${job.status}. Only pending/running jobs can be
|
|
227054
|
+
setStatusMessage(`Job ${job.id} is ${job.status}. Only pending/running jobs can be killed.`);
|
|
226658
227055
|
return;
|
|
226659
227056
|
}
|
|
226660
227057
|
setIsWorking(true);
|
|
226661
227058
|
try {
|
|
226662
227059
|
const cancelled = await manager.cancelJob(job.id);
|
|
226663
227060
|
if (cancelled) {
|
|
226664
|
-
setStatusMessage(`
|
|
227061
|
+
setStatusMessage(`Killed ${job.id}.`);
|
|
226665
227062
|
} else {
|
|
226666
|
-
setStatusMessage(`Could not
|
|
227063
|
+
setStatusMessage(`Could not kill ${job.id}.`);
|
|
226667
227064
|
}
|
|
226668
227065
|
await refreshJobs(false);
|
|
226669
227066
|
} catch (err) {
|
|
@@ -226672,6 +227069,38 @@ function JobsPanel({ manager, onClose }) {
|
|
|
226672
227069
|
setIsWorking(false);
|
|
226673
227070
|
}
|
|
226674
227071
|
}, [isWorking, manager, refreshJobs]);
|
|
227072
|
+
const killAllActiveJobs = import_react50.useCallback(async () => {
|
|
227073
|
+
if (isWorking)
|
|
227074
|
+
return;
|
|
227075
|
+
const activeJobs = jobs2.filter((job) => isActiveStatus(job.status));
|
|
227076
|
+
if (activeJobs.length === 0) {
|
|
227077
|
+
setStatusMessage("No active jobs to kill.");
|
|
227078
|
+
return;
|
|
227079
|
+
}
|
|
227080
|
+
setIsWorking(true);
|
|
227081
|
+
try {
|
|
227082
|
+
let killed = 0;
|
|
227083
|
+
for (const job of activeJobs) {
|
|
227084
|
+
try {
|
|
227085
|
+
const cancelled = await manager.cancelJob(job.id);
|
|
227086
|
+
if (cancelled)
|
|
227087
|
+
killed += 1;
|
|
227088
|
+
} catch {}
|
|
227089
|
+
}
|
|
227090
|
+
if (killed === 0) {
|
|
227091
|
+
setStatusMessage("Could not kill any active jobs.");
|
|
227092
|
+
} else if (killed === activeJobs.length) {
|
|
227093
|
+
setStatusMessage(`Killed ${killed} active job${killed === 1 ? "" : "s"}.`);
|
|
227094
|
+
} else {
|
|
227095
|
+
setStatusMessage(`Killed ${killed}/${activeJobs.length} active jobs.`);
|
|
227096
|
+
}
|
|
227097
|
+
await refreshJobs(false);
|
|
227098
|
+
} catch (err) {
|
|
227099
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
227100
|
+
} finally {
|
|
227101
|
+
setIsWorking(false);
|
|
227102
|
+
}
|
|
227103
|
+
}, [isWorking, jobs2, manager, refreshJobs]);
|
|
226675
227104
|
const openDetail = import_react50.useCallback(() => {
|
|
226676
227105
|
const selected = filteredJobs[selectedIndex];
|
|
226677
227106
|
if (!selected)
|
|
@@ -226694,7 +227123,11 @@ function JobsPanel({ manager, onClose }) {
|
|
|
226694
227123
|
refreshJobs(true);
|
|
226695
227124
|
return;
|
|
226696
227125
|
}
|
|
226697
|
-
if (input === "
|
|
227126
|
+
if (input === "K") {
|
|
227127
|
+
killAllActiveJobs();
|
|
227128
|
+
return;
|
|
227129
|
+
}
|
|
227130
|
+
if (input === "x" || input === "c" || input === "d") {
|
|
226698
227131
|
cancelJob(detailJob);
|
|
226699
227132
|
}
|
|
226700
227133
|
return;
|
|
@@ -226748,7 +227181,11 @@ function JobsPanel({ manager, onClose }) {
|
|
|
226748
227181
|
refreshJobs(true);
|
|
226749
227182
|
return;
|
|
226750
227183
|
}
|
|
226751
|
-
if (input === "
|
|
227184
|
+
if (input === "K") {
|
|
227185
|
+
killAllActiveJobs();
|
|
227186
|
+
return;
|
|
227187
|
+
}
|
|
227188
|
+
if (input === "x" || input === "c" || input === "d") {
|
|
226752
227189
|
cancelJob(filteredJobs[selectedIndex] || null);
|
|
226753
227190
|
}
|
|
226754
227191
|
});
|
|
@@ -226786,7 +227223,9 @@ function JobsPanel({ manager, onClose }) {
|
|
|
226786
227223
|
children: [
|
|
226787
227224
|
"(",
|
|
226788
227225
|
jobs2.length,
|
|
226789
|
-
" total
|
|
227226
|
+
" total, ",
|
|
227227
|
+
jobs2.filter((job) => isActiveStatus(job.status)).length,
|
|
227228
|
+
" active)"
|
|
226790
227229
|
]
|
|
226791
227230
|
}, undefined, true, undefined, this)
|
|
226792
227231
|
]
|
|
@@ -226907,7 +227346,7 @@ function JobsPanel({ manager, onClose }) {
|
|
|
226907
227346
|
marginTop: 1,
|
|
226908
227347
|
children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text3, {
|
|
226909
227348
|
color: "gray",
|
|
226910
|
-
children: "x/c
|
|
227349
|
+
children: "d/x/c kill selected K kill all active r refresh esc back q close"
|
|
226911
227350
|
}, undefined, false, undefined, this)
|
|
226912
227351
|
}, undefined, false, undefined, this)
|
|
226913
227352
|
]
|
|
@@ -227027,7 +227466,7 @@ function JobsPanel({ manager, onClose }) {
|
|
|
227027
227466
|
marginTop: 1,
|
|
227028
227467
|
children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text3, {
|
|
227029
227468
|
color: "gray",
|
|
227030
|
-
children: "j/k or arrows move enter view x/c
|
|
227469
|
+
children: "j/k or arrows move enter view d/x/c kill selected K kill all active r refresh 1/2/3 filter q close"
|
|
227031
227470
|
}, undefined, false, undefined, this)
|
|
227032
227471
|
}, undefined, false, undefined, this)
|
|
227033
227472
|
]
|
|
@@ -227116,7 +227555,7 @@ var DOCS_SECTIONS = [
|
|
|
227116
227555
|
content: [
|
|
227117
227556
|
"Use /tasks for queued local tasks with priority and pause/resume controls.",
|
|
227118
227557
|
"Use /schedules for recurring command execution with next-run visibility.",
|
|
227119
|
-
"Use /jobs for background connector/tool jobs.
|
|
227558
|
+
"Use /jobs for background connector/tool jobs. Kill jobs directly in the panel.",
|
|
227120
227559
|
"Use /orders for interactive order/store workflows (tabs, table navigation, detail views).",
|
|
227121
227560
|
"Use /logs for security events and /heartbeat for recurring assistant runs."
|
|
227122
227561
|
]
|
|
@@ -228835,20 +229274,29 @@ function GuardrailsPanel({
|
|
|
228835
229274
|
return;
|
|
228836
229275
|
}
|
|
228837
229276
|
if (mode === "policies") {
|
|
229277
|
+
const policiesListSize = policies.length + 1;
|
|
228838
229278
|
if (key.upArrow) {
|
|
228839
|
-
setSelectedIndex((prev) => prev === 0 ?
|
|
229279
|
+
setSelectedIndex((prev) => prev === 0 ? policiesListSize - 1 : prev - 1);
|
|
228840
229280
|
return;
|
|
228841
229281
|
}
|
|
228842
229282
|
if (key.downArrow) {
|
|
228843
|
-
setSelectedIndex((prev) => prev >=
|
|
229283
|
+
setSelectedIndex((prev) => prev >= policiesListSize - 1 ? 0 : prev + 1);
|
|
228844
229284
|
return;
|
|
228845
229285
|
}
|
|
228846
229286
|
if (key.return) {
|
|
228847
|
-
|
|
228848
|
-
|
|
228849
|
-
|
|
228850
|
-
|
|
228851
|
-
|
|
229287
|
+
if (selectedIndex === policies.length) {
|
|
229288
|
+
setCreateName("");
|
|
229289
|
+
setCreateScopeIdx(2);
|
|
229290
|
+
setCreateActionIdx(0);
|
|
229291
|
+
setCreateField(0);
|
|
229292
|
+
setMode("policy-create");
|
|
229293
|
+
} else {
|
|
229294
|
+
const policy = policies[selectedIndex];
|
|
229295
|
+
if (policy) {
|
|
229296
|
+
setDetailPolicyId(policy.id);
|
|
229297
|
+
setRuleIndex(0);
|
|
229298
|
+
setMode("policy-detail");
|
|
229299
|
+
}
|
|
228852
229300
|
}
|
|
228853
229301
|
return;
|
|
228854
229302
|
}
|
|
@@ -229407,54 +229855,66 @@ function GuardrailsPanel({
|
|
|
229407
229855
|
paddingX: 1,
|
|
229408
229856
|
height: Math.min(12, policies.length + 2),
|
|
229409
229857
|
overflowY: "hidden",
|
|
229410
|
-
children:
|
|
229411
|
-
|
|
229412
|
-
|
|
229413
|
-
dimColor: true,
|
|
229414
|
-
children: "No policies. Press n to create one."
|
|
229415
|
-
}, undefined, false, undefined, this)
|
|
229416
|
-
}, undefined, false, undefined, this) : policies.map((policy, index) => {
|
|
229417
|
-
const isSelected = index === selectedIndex;
|
|
229418
|
-
const scopeColor = SCOPE_COLORS[policy.scope] || "white";
|
|
229419
|
-
return /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
229858
|
+
children: [
|
|
229859
|
+
policies.length === 0 ? /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
229860
|
+
paddingY: 1,
|
|
229420
229861
|
children: /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229421
|
-
|
|
229422
|
-
children:
|
|
229423
|
-
|
|
229424
|
-
|
|
229425
|
-
|
|
229426
|
-
|
|
229427
|
-
|
|
229428
|
-
|
|
229429
|
-
|
|
229430
|
-
|
|
229431
|
-
|
|
229432
|
-
|
|
229433
|
-
|
|
229434
|
-
|
|
229435
|
-
|
|
229436
|
-
|
|
229437
|
-
|
|
229438
|
-
|
|
229439
|
-
|
|
229440
|
-
|
|
229441
|
-
|
|
229442
|
-
|
|
229443
|
-
|
|
229444
|
-
|
|
229445
|
-
|
|
229446
|
-
|
|
229447
|
-
|
|
229448
|
-
|
|
229449
|
-
|
|
229450
|
-
|
|
229451
|
-
|
|
229452
|
-
|
|
229862
|
+
dimColor: true,
|
|
229863
|
+
children: "No policies. Press n to create one."
|
|
229864
|
+
}, undefined, false, undefined, this)
|
|
229865
|
+
}, undefined, false, undefined, this) : policies.map((policy, index) => {
|
|
229866
|
+
const isSelected = index === selectedIndex;
|
|
229867
|
+
const scopeColor = SCOPE_COLORS[policy.scope] || "white";
|
|
229868
|
+
return /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
229869
|
+
children: /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229870
|
+
inverse: isSelected,
|
|
229871
|
+
children: [
|
|
229872
|
+
isSelected ? ">" : " ",
|
|
229873
|
+
" ",
|
|
229874
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229875
|
+
color: policy.enabled ? "green" : "red",
|
|
229876
|
+
children: [
|
|
229877
|
+
"[",
|
|
229878
|
+
policy.enabled ? "on " : "off",
|
|
229879
|
+
"]"
|
|
229880
|
+
]
|
|
229881
|
+
}, undefined, true, undefined, this),
|
|
229882
|
+
" ",
|
|
229883
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229884
|
+
bold: isSelected,
|
|
229885
|
+
children: (policy.name || policy.id).slice(0, 20).padEnd(20)
|
|
229886
|
+
}, undefined, false, undefined, this),
|
|
229887
|
+
" ",
|
|
229888
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229889
|
+
color: scopeColor,
|
|
229890
|
+
children: policy.scope.padEnd(10)
|
|
229891
|
+
}, undefined, false, undefined, this),
|
|
229892
|
+
" ",
|
|
229893
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229894
|
+
dimColor: true,
|
|
229895
|
+
children: policy.location
|
|
229896
|
+
}, undefined, false, undefined, this)
|
|
229897
|
+
]
|
|
229898
|
+
}, undefined, true, undefined, this)
|
|
229899
|
+
}, policy.id, false, undefined, this);
|
|
229900
|
+
}),
|
|
229901
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
229902
|
+
marginTop: policies.length > 0 ? 1 : 0,
|
|
229903
|
+
paddingY: 0,
|
|
229904
|
+
children: /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229905
|
+
inverse: selectedIndex === policies.length,
|
|
229906
|
+
dimColor: selectedIndex !== policies.length,
|
|
229907
|
+
color: selectedIndex === policies.length ? "cyan" : undefined,
|
|
229908
|
+
children: "+ New policy (n)"
|
|
229909
|
+
}, undefined, false, undefined, this)
|
|
229910
|
+
}, undefined, false, undefined, this)
|
|
229911
|
+
]
|
|
229912
|
+
}, undefined, true, undefined, this),
|
|
229453
229913
|
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
229454
229914
|
marginTop: 1,
|
|
229455
229915
|
children: /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text3, {
|
|
229456
229916
|
dimColor: true,
|
|
229457
|
-
children: "[
|
|
229917
|
+
children: "[e]nable [d]isable [Enter] detail [b]ack [q]uit | \u2191\u2193 navigate"
|
|
229458
229918
|
}, undefined, false, undefined, this)
|
|
229459
229919
|
}, undefined, false, undefined, this)
|
|
229460
229920
|
]
|
|
@@ -230616,7 +231076,7 @@ function BudgetsPanel({
|
|
|
230616
231076
|
const editSessionStatus = showingActiveProfile ? sessionStatus : createDraftStatus("session", activeOrDraftProfileForEdit?.config.session);
|
|
230617
231077
|
const editSwarmStatus = showingActiveProfile ? swarmStatus : createDraftStatus("swarm", activeOrDraftProfileForEdit?.config.swarm);
|
|
230618
231078
|
import_react57.useEffect(() => {
|
|
230619
|
-
setSelectedIndex((prev) => Math.min(prev,
|
|
231079
|
+
setSelectedIndex((prev) => Math.min(prev, profiles.length));
|
|
230620
231080
|
}, [profiles.length]);
|
|
230621
231081
|
import_react57.useEffect(() => {
|
|
230622
231082
|
if (!editingProfileId)
|
|
@@ -230701,7 +231161,9 @@ function BudgetsPanel({
|
|
|
230701
231161
|
return;
|
|
230702
231162
|
}
|
|
230703
231163
|
if (key.return) {
|
|
230704
|
-
if (
|
|
231164
|
+
if (selectedIndex === profiles.length) {
|
|
231165
|
+
startCreateForm();
|
|
231166
|
+
} else if (selectedProfile) {
|
|
230705
231167
|
onSelectProfile(selectedProfile.id);
|
|
230706
231168
|
}
|
|
230707
231169
|
return;
|
|
@@ -230711,15 +231173,11 @@ function BudgetsPanel({
|
|
|
230711
231173
|
return;
|
|
230712
231174
|
}
|
|
230713
231175
|
if (key.upArrow) {
|
|
230714
|
-
|
|
230715
|
-
return;
|
|
230716
|
-
setSelectedIndex((prev) => prev === 0 ? profiles.length - 1 : prev - 1);
|
|
231176
|
+
setSelectedIndex((prev) => prev === 0 ? profiles.length : prev - 1);
|
|
230717
231177
|
return;
|
|
230718
231178
|
}
|
|
230719
231179
|
if (key.downArrow) {
|
|
230720
|
-
|
|
230721
|
-
return;
|
|
230722
|
-
setSelectedIndex((prev) => prev === profiles.length - 1 ? 0 : prev + 1);
|
|
231180
|
+
setSelectedIndex((prev) => prev === profiles.length ? 0 : prev + 1);
|
|
230723
231181
|
return;
|
|
230724
231182
|
}
|
|
230725
231183
|
}, { isActive: true });
|
|
@@ -230972,34 +231430,46 @@ function BudgetsPanel({
|
|
|
230972
231430
|
borderStyle: "round",
|
|
230973
231431
|
borderColor: "gray",
|
|
230974
231432
|
paddingX: 1,
|
|
230975
|
-
children:
|
|
230976
|
-
|
|
230977
|
-
|
|
230978
|
-
|
|
230979
|
-
|
|
230980
|
-
|
|
230981
|
-
|
|
230982
|
-
|
|
230983
|
-
|
|
230984
|
-
|
|
231433
|
+
children: [
|
|
231434
|
+
profiles.length === 0 ? /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Box_default, {
|
|
231435
|
+
paddingY: 1,
|
|
231436
|
+
children: /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Text3, {
|
|
231437
|
+
dimColor: true,
|
|
231438
|
+
children: "No budget profiles. Press n to create one."
|
|
231439
|
+
}, undefined, false, undefined, this)
|
|
231440
|
+
}, undefined, false, undefined, this) : profiles.map((profile, index) => {
|
|
231441
|
+
const isSelected = index === selectedIndex;
|
|
231442
|
+
const isActive = profile.id === activeProfileId;
|
|
231443
|
+
return /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Box_default, {
|
|
231444
|
+
paddingY: 0,
|
|
231445
|
+
children: /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Text3, {
|
|
231446
|
+
inverse: isSelected,
|
|
231447
|
+
color: isActive ? "green" : undefined,
|
|
231448
|
+
dimColor: !isSelected && !isActive,
|
|
231449
|
+
children: [
|
|
231450
|
+
isActive ? "*" : " ",
|
|
231451
|
+
" ",
|
|
231452
|
+
index + 1,
|
|
231453
|
+
". ",
|
|
231454
|
+
profile.name.padEnd(22),
|
|
231455
|
+
" ",
|
|
231456
|
+
profile.description || ""
|
|
231457
|
+
]
|
|
231458
|
+
}, undefined, true, undefined, this)
|
|
231459
|
+
}, profile.id, false, undefined, this);
|
|
231460
|
+
}),
|
|
231461
|
+
/* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Box_default, {
|
|
231462
|
+
marginTop: profiles.length > 0 ? 1 : 0,
|
|
230985
231463
|
paddingY: 0,
|
|
230986
231464
|
children: /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Text3, {
|
|
230987
|
-
inverse:
|
|
230988
|
-
|
|
230989
|
-
|
|
230990
|
-
children:
|
|
230991
|
-
|
|
230992
|
-
|
|
230993
|
-
|
|
230994
|
-
|
|
230995
|
-
profile.name.padEnd(22),
|
|
230996
|
-
" ",
|
|
230997
|
-
profile.description || ""
|
|
230998
|
-
]
|
|
230999
|
-
}, undefined, true, undefined, this)
|
|
231000
|
-
}, profile.id, false, undefined, this);
|
|
231001
|
-
})
|
|
231002
|
-
}, undefined, false, undefined, this),
|
|
231465
|
+
inverse: selectedIndex === profiles.length,
|
|
231466
|
+
dimColor: selectedIndex !== profiles.length,
|
|
231467
|
+
color: selectedIndex === profiles.length ? "cyan" : undefined,
|
|
231468
|
+
children: "+ New profile (n)"
|
|
231469
|
+
}, undefined, false, undefined, this)
|
|
231470
|
+
}, undefined, false, undefined, this)
|
|
231471
|
+
]
|
|
231472
|
+
}, undefined, true, undefined, this),
|
|
231003
231473
|
selectedProfile && /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Box_default, {
|
|
231004
231474
|
marginTop: 1,
|
|
231005
231475
|
children: /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Text3, {
|
|
@@ -236360,7 +236830,7 @@ function SecretsPanel({
|
|
|
236360
236830
|
setIsProcessing(false);
|
|
236361
236831
|
}
|
|
236362
236832
|
};
|
|
236363
|
-
const
|
|
236833
|
+
const normalizeScope3 = (rawScope) => {
|
|
236364
236834
|
const scope = rawScope.trim().toLowerCase();
|
|
236365
236835
|
if (!scope)
|
|
236366
236836
|
return "assistant";
|
|
@@ -236369,7 +236839,7 @@ function SecretsPanel({
|
|
|
236369
236839
|
return null;
|
|
236370
236840
|
};
|
|
236371
236841
|
const normalizeAddInput = (form) => {
|
|
236372
|
-
const scope =
|
|
236842
|
+
const scope = normalizeScope3(String(form.scope));
|
|
236373
236843
|
if (!scope) {
|
|
236374
236844
|
return null;
|
|
236375
236845
|
}
|
|
@@ -236390,7 +236860,7 @@ function SecretsPanel({
|
|
|
236390
236860
|
return;
|
|
236391
236861
|
}
|
|
236392
236862
|
if (currentAddField.key === "scope") {
|
|
236393
|
-
const normalizedScope =
|
|
236863
|
+
const normalizedScope = normalizeScope3(currentValue);
|
|
236394
236864
|
if (!normalizedScope) {
|
|
236395
236865
|
setStatusMessage('Scope must be "assistant" or "global".');
|
|
236396
236866
|
return;
|
|
@@ -238870,6 +239340,18 @@ function ResumePanel({
|
|
|
238870
239340
|
}, undefined, true, undefined, this);
|
|
238871
239341
|
}
|
|
238872
239342
|
|
|
239343
|
+
// packages/terminal/src/components/queueUtils.ts
|
|
239344
|
+
function takeNextQueuedMessage(queue, sessionId) {
|
|
239345
|
+
const next = queue.find((msg) => msg.sessionId === sessionId);
|
|
239346
|
+
if (!next) {
|
|
239347
|
+
return { next: null, remaining: queue };
|
|
239348
|
+
}
|
|
239349
|
+
return {
|
|
239350
|
+
next,
|
|
239351
|
+
remaining: queue.filter((msg) => msg.id !== next.id)
|
|
239352
|
+
};
|
|
239353
|
+
}
|
|
239354
|
+
|
|
238873
239355
|
// packages/terminal/src/output/sanitize.ts
|
|
238874
239356
|
var CLEAR_SCREEN_SEQUENCE = "\x1B[2J\x1B[3J\x1B[H";
|
|
238875
239357
|
var CLEAR_SCREEN_TOKEN = "__ASSISTANTS_CLEAR_SCREEN__";
|
|
@@ -239256,6 +239738,7 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
239256
239738
|
const [heartbeatState, setHeartbeatState] = import_react72.useState();
|
|
239257
239739
|
const [identityInfo, setIdentityInfo] = import_react72.useState();
|
|
239258
239740
|
const [verboseTools, setVerboseTools] = import_react72.useState(false);
|
|
239741
|
+
const [gitBranch, setGitBranch] = import_react72.useState();
|
|
239259
239742
|
const [askUserState, setAskUserState] = import_react72.useState(null);
|
|
239260
239743
|
const [processingStartTime, setProcessingStartTime] = import_react72.useState();
|
|
239261
239744
|
const [currentTurnTokens, setCurrentTurnTokens] = import_react72.useState(0);
|
|
@@ -239269,6 +239752,42 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
239269
239752
|
const pttRecorderRef = import_react72.useRef(null);
|
|
239270
239753
|
const [skills, setSkills] = import_react72.useState([]);
|
|
239271
239754
|
const [commands9, setCommands] = import_react72.useState([]);
|
|
239755
|
+
const fileListCacheRef = import_react72.useRef({ files: [], timestamp: 0 });
|
|
239756
|
+
const searchFiles = import_react72.useCallback((query) => {
|
|
239757
|
+
const cache7 = fileListCacheRef.current;
|
|
239758
|
+
const now2 = Date.now();
|
|
239759
|
+
if (now2 - cache7.timestamp > 30000 || cache7.files.length === 0) {
|
|
239760
|
+
try {
|
|
239761
|
+
const { execSync } = __require("child_process");
|
|
239762
|
+
let output;
|
|
239763
|
+
try {
|
|
239764
|
+
output = execSync("git ls-files --cached --others --exclude-standard 2>/dev/null", {
|
|
239765
|
+
cwd: cwd2,
|
|
239766
|
+
encoding: "utf-8",
|
|
239767
|
+
maxBuffer: 1024 * 1024,
|
|
239768
|
+
timeout: 3000
|
|
239769
|
+
});
|
|
239770
|
+
} catch {
|
|
239771
|
+
output = execSync('find . -type f -not -path "*/node_modules/*" -not -path "*/.git/*" -maxdepth 5 2>/dev/null | head -1000', {
|
|
239772
|
+
cwd: cwd2,
|
|
239773
|
+
encoding: "utf-8",
|
|
239774
|
+
maxBuffer: 1024 * 1024,
|
|
239775
|
+
timeout: 3000
|
|
239776
|
+
});
|
|
239777
|
+
}
|
|
239778
|
+
cache7.files = output.trim().split(`
|
|
239779
|
+
`).filter(Boolean).slice(0, 2000);
|
|
239780
|
+
cache7.timestamp = now2;
|
|
239781
|
+
} catch {
|
|
239782
|
+
return [];
|
|
239783
|
+
}
|
|
239784
|
+
}
|
|
239785
|
+
if (!query)
|
|
239786
|
+
return cache7.files.slice(0, 20);
|
|
239787
|
+
const lower = query.toLowerCase();
|
|
239788
|
+
const matches = cache7.files.filter((f6) => f6.toLowerCase().includes(lower));
|
|
239789
|
+
return matches.slice(0, 20);
|
|
239790
|
+
}, [cwd2]);
|
|
239272
239791
|
const lastCtrlCRef = import_react72.useRef(0);
|
|
239273
239792
|
const [showExitHint, setShowExitHint] = import_react72.useState(false);
|
|
239274
239793
|
const responseRef = import_react72.useRef("");
|
|
@@ -239277,6 +239796,8 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
239277
239796
|
const activityLogRef = import_react72.useRef([]);
|
|
239278
239797
|
const skipNextDoneRef = import_react72.useRef(false);
|
|
239279
239798
|
const isProcessingRef = import_react72.useRef(isProcessing);
|
|
239799
|
+
const currentToolCallRef = import_react72.useRef(currentToolCall);
|
|
239800
|
+
const hasPendingToolsRef = import_react72.useRef(false);
|
|
239280
239801
|
const inputRef = import_react72.useRef(null);
|
|
239281
239802
|
const isListeningRef = import_react72.useRef(isListening);
|
|
239282
239803
|
const listenLoopRef = import_react72.useRef({
|
|
@@ -239357,6 +239878,9 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
239357
239878
|
import_react72.useEffect(() => {
|
|
239358
239879
|
isProcessingRef.current = isProcessing;
|
|
239359
239880
|
}, [isProcessing]);
|
|
239881
|
+
import_react72.useEffect(() => {
|
|
239882
|
+
currentToolCallRef.current = currentToolCall;
|
|
239883
|
+
}, [currentToolCall]);
|
|
239360
239884
|
import_react72.useEffect(() => {
|
|
239361
239885
|
isListeningRef.current = isListening;
|
|
239362
239886
|
}, [isListening]);
|
|
@@ -239370,6 +239894,14 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
239370
239894
|
processingStartTimeRef.current = now2;
|
|
239371
239895
|
}
|
|
239372
239896
|
}, [isProcessing, processingStartTime]);
|
|
239897
|
+
import_react72.useEffect(() => {
|
|
239898
|
+
const { exec: exec3 } = __require("child_process");
|
|
239899
|
+
exec3("git branch --show-current 2>/dev/null", { cwd: cwd2 }, (err, stdout2) => {
|
|
239900
|
+
if (!err && stdout2?.trim()) {
|
|
239901
|
+
setGitBranch(stdout2.trim());
|
|
239902
|
+
}
|
|
239903
|
+
});
|
|
239904
|
+
}, [cwd2]);
|
|
239373
239905
|
const buildFullResponse = import_react72.useCallback(() => {
|
|
239374
239906
|
const parts = activityLogRef.current.filter((entry) => entry.type === "text" && entry.content).map((entry) => entry.content);
|
|
239375
239907
|
if (responseRef.current.trim()) {
|
|
@@ -240048,7 +240580,7 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240048
240580
|
const pendingIndex = pendingSendsRef.current.findIndex((entry) => entry.sessionId === active.id);
|
|
240049
240581
|
if (pendingIndex !== -1) {
|
|
240050
240582
|
const [started] = pendingSendsRef.current.splice(pendingIndex, 1);
|
|
240051
|
-
if (started
|
|
240583
|
+
if (started) {
|
|
240052
240584
|
setInlinePending((prev) => prev.filter((msg) => msg.id !== started.id));
|
|
240053
240585
|
}
|
|
240054
240586
|
}
|
|
@@ -240702,17 +241234,10 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240702
241234
|
const activeSession2 = registryRef.current.getActiveSession();
|
|
240703
241235
|
if (!activeSession2 || !activeSessionId)
|
|
240704
241236
|
return;
|
|
240705
|
-
|
|
240706
|
-
setMessageQueue((prev) => {
|
|
240707
|
-
const idx = prev.findIndex((msg) => msg.sessionId === activeSessionId);
|
|
240708
|
-
if (idx === -1) {
|
|
240709
|
-
return prev;
|
|
240710
|
-
}
|
|
240711
|
-
nextMessage = prev[idx];
|
|
240712
|
-
return [...prev.slice(0, idx), ...prev.slice(idx + 1)];
|
|
240713
|
-
});
|
|
241237
|
+
const { next: nextMessage, remaining } = takeNextQueuedMessage(messageQueue, activeSessionId);
|
|
240714
241238
|
if (!nextMessage)
|
|
240715
241239
|
return;
|
|
241240
|
+
setMessageQueue(remaining);
|
|
240716
241241
|
const userMessage = {
|
|
240717
241242
|
id: nextMessage.id,
|
|
240718
241243
|
role: "user",
|
|
@@ -240741,7 +241266,6 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240741
241266
|
setIsProcessing(true);
|
|
240742
241267
|
isProcessingRef.current = true;
|
|
240743
241268
|
registryRef.current.setProcessing(activeSession2.id, true);
|
|
240744
|
-
pendingSendsRef.current.push({ id: nextMessage.id, sessionId: activeSessionId, mode: "queued" });
|
|
240745
241269
|
try {
|
|
240746
241270
|
await activeSession2.client.send(nextMessage.content);
|
|
240747
241271
|
} catch (err) {
|
|
@@ -240750,8 +241274,9 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240750
241274
|
setIsProcessing(false);
|
|
240751
241275
|
isProcessingRef.current = false;
|
|
240752
241276
|
registryRef.current.setProcessing(activeSession2.id, false);
|
|
241277
|
+
setQueueFlushTrigger((prev) => prev + 1);
|
|
240753
241278
|
}
|
|
240754
|
-
}, [activeSessionId, clearPendingSend]);
|
|
241279
|
+
}, [activeSessionId, clearPendingSend, messageQueue]);
|
|
240755
241280
|
const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
|
|
240756
241281
|
const activeInline = activeSessionId ? inlinePending.filter((msg) => msg.sessionId === activeSessionId) : [];
|
|
240757
241282
|
const queuedMessageIds = import_react72.useMemo(() => new Set(activeQueue.filter((msg) => msg.mode === "queued").map((msg) => msg.id)), [activeQueue]);
|
|
@@ -240811,6 +241336,9 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240811
241336
|
}
|
|
240812
241337
|
return false;
|
|
240813
241338
|
}, [activityLog]);
|
|
241339
|
+
import_react72.useEffect(() => {
|
|
241340
|
+
hasPendingToolsRef.current = hasPendingTools;
|
|
241341
|
+
}, [hasPendingTools]);
|
|
240814
241342
|
const isBusy = isProcessing || hasPendingTools;
|
|
240815
241343
|
const listenHints = import_react72.useMemo(() => {
|
|
240816
241344
|
if (!isListening)
|
|
@@ -240890,6 +241418,26 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240890
241418
|
setError(err instanceof Error ? err.message : "Failed to create session");
|
|
240891
241419
|
}
|
|
240892
241420
|
}, [cwd2, createAndActivateSession]);
|
|
241421
|
+
const stopActiveProcessing = import_react72.useCallback((status = "stopped") => {
|
|
241422
|
+
const active = registryRef.current.getActiveSession();
|
|
241423
|
+
if (!active)
|
|
241424
|
+
return false;
|
|
241425
|
+
const sessionProcessing = active.isProcessing;
|
|
241426
|
+
const shouldStopNow = isProcessingRef.current || hasPendingToolsRef.current || sessionProcessing || Boolean(currentToolCallRef.current);
|
|
241427
|
+
if (!shouldStopNow)
|
|
241428
|
+
return false;
|
|
241429
|
+
active.client.stop();
|
|
241430
|
+
const finalized = finalizeResponse2(status);
|
|
241431
|
+
if (finalized) {
|
|
241432
|
+
skipNextDoneRef.current = true;
|
|
241433
|
+
}
|
|
241434
|
+
resetTurnState();
|
|
241435
|
+
registryRef.current.setProcessing(active.id, false);
|
|
241436
|
+
setIsProcessing(false);
|
|
241437
|
+
isProcessingRef.current = false;
|
|
241438
|
+
setQueueFlushTrigger((prev) => prev + 1);
|
|
241439
|
+
return true;
|
|
241440
|
+
}, [finalizeResponse2, resetTurnState]);
|
|
240893
241441
|
useSafeInput((input, key) => {
|
|
240894
241442
|
if (isListeningRef.current && key.ctrl && input === "l") {
|
|
240895
241443
|
stopListening();
|
|
@@ -240910,18 +241458,7 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240910
241458
|
if (hasAsk) {
|
|
240911
241459
|
cancelAskUser("Cancelled by user", activeSessionId);
|
|
240912
241460
|
}
|
|
240913
|
-
|
|
240914
|
-
if ((isProcessing || hasPendingTools || sessionProcessing || currentToolCall) && activeSession) {
|
|
240915
|
-
activeSession.client.stop();
|
|
240916
|
-
const finalized = finalizeResponse2("stopped");
|
|
240917
|
-
if (finalized) {
|
|
240918
|
-
skipNextDoneRef.current = true;
|
|
240919
|
-
}
|
|
240920
|
-
resetTurnState();
|
|
240921
|
-
registryRef.current.setProcessing(activeSession.id, false);
|
|
240922
|
-
setIsProcessing(false);
|
|
240923
|
-
isProcessingRef.current = false;
|
|
240924
|
-
setQueueFlushTrigger((prev) => prev + 1);
|
|
241461
|
+
if (stopActiveProcessing("stopped")) {
|
|
240925
241462
|
lastCtrlCRef.current = 0;
|
|
240926
241463
|
setShowExitHint(false);
|
|
240927
241464
|
return;
|
|
@@ -240950,18 +241487,8 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240950
241487
|
if (activeSessionId && askUserStateRef.current.has(activeSessionId)) {
|
|
240951
241488
|
cancelAskUser("Cancelled by user", activeSessionId);
|
|
240952
241489
|
}
|
|
240953
|
-
|
|
240954
|
-
|
|
240955
|
-
activeSession.client.stop();
|
|
240956
|
-
const finalized = finalizeResponse2("stopped");
|
|
240957
|
-
if (finalized) {
|
|
240958
|
-
skipNextDoneRef.current = true;
|
|
240959
|
-
}
|
|
240960
|
-
resetTurnState();
|
|
240961
|
-
registryRef.current.setProcessing(activeSession.id, false);
|
|
240962
|
-
setIsProcessing(false);
|
|
240963
|
-
isProcessingRef.current = false;
|
|
240964
|
-
setQueueFlushTrigger((prev) => prev + 1);
|
|
241490
|
+
if (stopActiveProcessing("stopped")) {
|
|
241491
|
+
return;
|
|
240965
241492
|
}
|
|
240966
241493
|
}
|
|
240967
241494
|
if (key.ctrl && input === "a") {
|
|
@@ -240972,7 +241499,7 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
240972
241499
|
openBudgetsPanel();
|
|
240973
241500
|
return;
|
|
240974
241501
|
}
|
|
240975
|
-
if (key.ctrl && input === "m") {
|
|
241502
|
+
if (key.ctrl && input === "m" && !key.return) {
|
|
240976
241503
|
const messagesManager = registry2.getActiveSession()?.client.getMessagesManager?.();
|
|
240977
241504
|
if (messagesManager) {
|
|
240978
241505
|
messagesManager.list({ limit: 50 }).then((msgs) => {
|
|
@@ -241455,7 +241982,7 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
241455
241982
|
timestamp: now()
|
|
241456
241983
|
}
|
|
241457
241984
|
]);
|
|
241458
|
-
pendingSendsRef.current.push({ id: inlineId, sessionId: activeSessionId
|
|
241985
|
+
pendingSendsRef.current.push({ id: inlineId, sessionId: activeSessionId });
|
|
241459
241986
|
try {
|
|
241460
241987
|
await activeSession.client.send(trimmedInput);
|
|
241461
241988
|
} catch (err) {
|
|
@@ -241464,17 +241991,8 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
241464
241991
|
}
|
|
241465
241992
|
return;
|
|
241466
241993
|
}
|
|
241467
|
-
if (mode === "interrupt" &&
|
|
241468
|
-
|
|
241469
|
-
const finalized = finalizeResponse2("interrupted");
|
|
241470
|
-
if (finalized) {
|
|
241471
|
-
skipNextDoneRef.current = true;
|
|
241472
|
-
}
|
|
241473
|
-
resetTurnState();
|
|
241474
|
-
setIsProcessing(false);
|
|
241475
|
-
isProcessingRef.current = false;
|
|
241476
|
-
registry2.setProcessing(activeSession.id, false);
|
|
241477
|
-
setQueueFlushTrigger((prev) => prev + 1);
|
|
241994
|
+
if (mode === "interrupt" && isBusy) {
|
|
241995
|
+
stopActiveProcessing("interrupted");
|
|
241478
241996
|
await new Promise((r6) => setTimeout(r6, 100));
|
|
241479
241997
|
}
|
|
241480
241998
|
const userMessage = {
|
|
@@ -241516,6 +242034,7 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
241516
242034
|
}, [
|
|
241517
242035
|
activeSession,
|
|
241518
242036
|
isProcessing,
|
|
242037
|
+
isBusy,
|
|
241519
242038
|
registry2,
|
|
241520
242039
|
sessions,
|
|
241521
242040
|
handleNewSession,
|
|
@@ -241527,7 +242046,8 @@ function App2({ cwd: cwd2, version: version3 }) {
|
|
|
241527
242046
|
submitAskAnswer,
|
|
241528
242047
|
clearPendingSend,
|
|
241529
242048
|
startListening,
|
|
241530
|
-
stopListening
|
|
242049
|
+
stopListening,
|
|
242050
|
+
stopActiveProcessing
|
|
241531
242051
|
]);
|
|
241532
242052
|
import_react72.useEffect(() => {
|
|
241533
242053
|
sendListenMessageRef.current = (text) => {
|
|
@@ -243292,6 +243812,9 @@ ${msg.body || msg.preview}`);
|
|
|
243292
243812
|
/* @__PURE__ */ jsx_dev_runtime48.jsxDEV(Input, {
|
|
243293
243813
|
ref: inputRef,
|
|
243294
243814
|
onSubmit: handleSubmit,
|
|
243815
|
+
onStopProcessing: () => {
|
|
243816
|
+
stopActiveProcessing("stopped");
|
|
243817
|
+
},
|
|
243295
243818
|
isProcessing: isBusy,
|
|
243296
243819
|
queueLength: activeQueue.length + inlineCount,
|
|
243297
243820
|
commands: commands9,
|
|
@@ -243303,7 +243826,8 @@ ${msg.body || msg.preview}`);
|
|
|
243303
243826
|
assistantName: identityInfo?.assistant?.name || undefined,
|
|
243304
243827
|
isRecording: pttRecording,
|
|
243305
243828
|
recordingStatus: pttStatus,
|
|
243306
|
-
onStopRecording: togglePushToTalk
|
|
243829
|
+
onStopRecording: togglePushToTalk,
|
|
243830
|
+
onFileSearch: searchFiles
|
|
243307
243831
|
}, undefined, false, undefined, this),
|
|
243308
243832
|
/* @__PURE__ */ jsx_dev_runtime48.jsxDEV(Status, {
|
|
243309
243833
|
isProcessing: isBusy,
|
|
@@ -243318,7 +243842,8 @@ ${msg.body || msg.preview}`);
|
|
|
243318
243842
|
sessionCount,
|
|
243319
243843
|
backgroundProcessingCount,
|
|
243320
243844
|
processingStartTime,
|
|
243321
|
-
verboseTools
|
|
243845
|
+
verboseTools,
|
|
243846
|
+
gitBranch
|
|
243322
243847
|
}, undefined, false, undefined, this)
|
|
243323
243848
|
]
|
|
243324
243849
|
}, undefined, true, undefined, this);
|
|
@@ -243766,7 +244291,7 @@ Interactive Mode:
|
|
|
243766
244291
|
// packages/terminal/src/index.tsx
|
|
243767
244292
|
var jsx_dev_runtime49 = __toESM(require_jsx_dev_runtime(), 1);
|
|
243768
244293
|
setRuntime(bunRuntime);
|
|
243769
|
-
var VERSION4 = "1.1.
|
|
244294
|
+
var VERSION4 = "1.1.27";
|
|
243770
244295
|
var SYNC_START = "\x1B[?2026h";
|
|
243771
244296
|
var SYNC_END = "\x1B[?2026l";
|
|
243772
244297
|
function enableSynchronizedOutput() {
|
|
@@ -243906,4 +244431,4 @@ export {
|
|
|
243906
244431
|
main
|
|
243907
244432
|
};
|
|
243908
244433
|
|
|
243909
|
-
//# debugId=
|
|
244434
|
+
//# debugId=463A5E72A8326CA464756E2164756E21
|