mastracode 0.22.3 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/dist/HarnessCompat.d.ts +2 -2
- package/dist/HarnessCompat.d.ts.map +1 -1
- package/dist/agents/mastracode-gateway.d.ts +58 -0
- package/dist/agents/mastracode-gateway.d.ts.map +1 -0
- package/dist/agents/model.d.ts +26 -28
- package/dist/agents/model.d.ts.map +1 -1
- package/dist/agents/{subagents/execute.d.ts → modes/build.d.ts} +3 -3
- package/dist/agents/modes/build.d.ts.map +1 -0
- package/dist/agents/{subagents → modes}/explore.d.ts +2 -2
- package/dist/agents/modes/explore.d.ts.map +1 -0
- package/dist/agents/modes/plan.d.ts +6 -0
- package/dist/agents/modes/plan.d.ts.map +1 -0
- package/dist/{chunk-EATS4KOR.cjs → chunk-3CO7PY6M.cjs} +1094 -239
- package/dist/chunk-3CO7PY6M.cjs.map +1 -0
- package/dist/{chunk-DJEQBK7L.cjs → chunk-CBPEMMRV.cjs} +1659 -2010
- package/dist/chunk-CBPEMMRV.cjs.map +1 -0
- package/dist/{chunk-W7Y7QIJA.js → chunk-FXYM4OEI.js} +14 -805
- package/dist/chunk-FXYM4OEI.js.map +1 -0
- package/dist/{chunk-OXYE6SUY.js → chunk-GKGPZBID.js} +836 -1187
- package/dist/chunk-GKGPZBID.js.map +1 -0
- package/dist/{chunk-FDDVVRPH.js → chunk-RDIIIT54.js} +1076 -221
- package/dist/chunk-RDIIIT54.js.map +1 -0
- package/dist/{chunk-NKTZDFIU.cjs → chunk-XPPJHUAD.cjs} +12 -809
- package/dist/chunk-XPPJHUAD.cjs.map +1 -0
- package/dist/cli.cjs +18 -18
- package/dist/cli.js +3 -3
- package/dist/index.cjs +3 -3
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/onboarding/onboarding-inline.d.ts +2 -2
- package/dist/onboarding/onboarding-inline.d.ts.map +1 -1
- package/dist/onboarding/settings.d.ts.map +1 -1
- package/dist/providers/claude-max.d.ts.map +1 -1
- package/dist/tui/chat-boundary-reconciliation.d.ts +18 -1
- package/dist/tui/chat-boundary-reconciliation.d.ts.map +1 -1
- package/dist/tui/command-dispatch.d.ts.map +1 -1
- package/dist/tui/commands/browser.d.ts.map +1 -1
- package/dist/tui/commands/goal.d.ts.map +1 -1
- package/dist/tui/commands/mode.d.ts.map +1 -1
- package/dist/tui/commands/new.d.ts.map +1 -1
- package/dist/tui/commands/settings.d.ts.map +1 -1
- package/dist/tui/commands/skills.d.ts.map +1 -1
- package/dist/tui/components/api-key-dialog.d.ts +2 -2
- package/dist/tui/components/api-key-dialog.d.ts.map +1 -1
- package/dist/tui/components/ask-question-dialog.d.ts +2 -2
- package/dist/tui/components/ask-question-dialog.d.ts.map +1 -1
- package/dist/tui/components/ask-question-inline.d.ts +4 -2
- package/dist/tui/components/ask-question-inline.d.ts.map +1 -1
- package/dist/tui/components/assistant-message.d.ts +2 -2
- package/dist/tui/components/assistant-message.d.ts.map +1 -1
- package/dist/tui/components/chat-boundary-spacer.d.ts +9 -9
- package/dist/tui/components/chat-boundary-spacer.d.ts.map +1 -1
- package/dist/tui/components/chat-spacing.d.ts +1 -1
- package/dist/tui/components/chat-spacing.d.ts.map +1 -1
- package/dist/tui/components/collapsible.d.ts +2 -2
- package/dist/tui/components/collapsible.d.ts.map +1 -1
- package/dist/tui/components/custom-editor.d.ts +2 -2
- package/dist/tui/components/custom-editor.d.ts.map +1 -1
- package/dist/tui/components/diff-output.d.ts +3 -1
- package/dist/tui/components/diff-output.d.ts.map +1 -1
- package/dist/tui/components/error-display.d.ts +4 -2
- package/dist/tui/components/error-display.d.ts.map +1 -1
- package/dist/tui/components/goal-cycles-dialog.d.ts +2 -2
- package/dist/tui/components/goal-cycles-dialog.d.ts.map +1 -1
- package/dist/tui/components/idle-counter.d.ts +1 -1
- package/dist/tui/components/idle-counter.d.ts.map +1 -1
- package/dist/tui/components/judge-display.d.ts +14 -2
- package/dist/tui/components/judge-display.d.ts.map +1 -1
- package/dist/tui/components/login-dialog.d.ts +2 -2
- package/dist/tui/components/login-dialog.d.ts.map +1 -1
- package/dist/tui/components/login-mode-selector.d.ts +2 -2
- package/dist/tui/components/login-mode-selector.d.ts.map +1 -1
- package/dist/tui/components/login-selector.d.ts +1 -1
- package/dist/tui/components/login-selector.d.ts.map +1 -1
- package/dist/tui/components/masked-input.d.ts +1 -1
- package/dist/tui/components/masked-input.d.ts.map +1 -1
- package/dist/tui/components/mcp-selector.d.ts +2 -2
- package/dist/tui/components/mcp-selector.d.ts.map +1 -1
- package/dist/tui/components/model-selector.d.ts +2 -2
- package/dist/tui/components/model-selector.d.ts.map +1 -1
- package/dist/tui/components/multi-step-progress.d.ts +3 -1
- package/dist/tui/components/multi-step-progress.d.ts.map +1 -1
- package/dist/tui/components/multiline-input.d.ts +1 -1
- package/dist/tui/components/multiline-input.d.ts.map +1 -1
- package/dist/tui/components/notification-summary.d.ts +1 -1
- package/dist/tui/components/notification-summary.d.ts.map +1 -1
- package/dist/tui/components/notification.d.ts +1 -1
- package/dist/tui/components/notification.d.ts.map +1 -1
- package/dist/tui/components/om-marker.d.ts +3 -1
- package/dist/tui/components/om-marker.d.ts.map +1 -1
- package/dist/tui/components/om-output.d.ts +3 -1
- package/dist/tui/components/om-output.d.ts.map +1 -1
- package/dist/tui/components/om-progress.d.ts +1 -1
- package/dist/tui/components/om-progress.d.ts.map +1 -1
- package/dist/tui/components/om-settings.d.ts +2 -2
- package/dist/tui/components/om-settings.d.ts.map +1 -1
- package/dist/tui/components/plan-approval-inline.d.ts +2 -2
- package/dist/tui/components/plan-approval-inline.d.ts.map +1 -1
- package/dist/tui/components/reactive-signal.d.ts +1 -1
- package/dist/tui/components/reactive-signal.d.ts.map +1 -1
- package/dist/tui/components/settings.d.ts +2 -2
- package/dist/tui/components/settings.d.ts.map +1 -1
- package/dist/tui/components/shell-output.d.ts +3 -1
- package/dist/tui/components/shell-output.d.ts.map +1 -1
- package/dist/tui/components/simple-progress.d.ts +1 -1
- package/dist/tui/components/simple-progress.d.ts.map +1 -1
- package/dist/tui/components/slash-command.d.ts +3 -1
- package/dist/tui/components/slash-command.d.ts.map +1 -1
- package/dist/tui/components/state-signal.d.ts +1 -1
- package/dist/tui/components/state-signal.d.ts.map +1 -1
- package/dist/tui/components/subagent-execution.d.ts +2 -2
- package/dist/tui/components/subagent-execution.d.ts.map +1 -1
- package/dist/tui/components/system-reminder.d.ts +1 -1
- package/dist/tui/components/system-reminder.d.ts.map +1 -1
- package/dist/tui/components/task-progress.d.ts +1 -1
- package/dist/tui/components/task-progress.d.ts.map +1 -1
- package/dist/tui/components/temporal-gap.d.ts +3 -1
- package/dist/tui/components/temporal-gap.d.ts.map +1 -1
- package/dist/tui/components/thinking-settings.d.ts +2 -2
- package/dist/tui/components/thinking-settings.d.ts.map +1 -1
- package/dist/tui/components/thread-selector.d.ts +2 -2
- package/dist/tui/components/thread-selector.d.ts.map +1 -1
- package/dist/tui/components/tool-approval-dialog.d.ts +2 -2
- package/dist/tui/components/tool-approval-dialog.d.ts.map +1 -1
- package/dist/tui/components/tool-execution-enhanced.d.ts +2 -2
- package/dist/tui/components/tool-execution-enhanced.d.ts.map +1 -1
- package/dist/tui/components/tool-validation-error.d.ts +2 -2
- package/dist/tui/components/tool-validation-error.d.ts.map +1 -1
- package/dist/tui/components/user-message.d.ts +2 -2
- package/dist/tui/components/user-message.d.ts.map +1 -1
- package/dist/tui/components/wrapping-autocomplete-list.d.ts +1 -1
- package/dist/tui/components/wrapping-autocomplete-list.d.ts.map +1 -1
- package/dist/tui/components/wrapping-select-list.d.ts +1 -1
- package/dist/tui/components/wrapping-select-list.d.ts.map +1 -1
- package/dist/tui/display.d.ts.map +1 -1
- package/dist/tui/event-dispatch.d.ts.map +1 -1
- package/dist/tui/goal-manager.d.ts +48 -40
- package/dist/tui/goal-manager.d.ts.map +1 -1
- package/dist/tui/handlers/agent-lifecycle.d.ts +13 -0
- package/dist/tui/handlers/agent-lifecycle.d.ts.map +1 -1
- package/dist/tui/handlers/index.d.ts +1 -1
- package/dist/tui/handlers/index.d.ts.map +1 -1
- package/dist/tui/handlers/message.d.ts.map +1 -1
- package/dist/tui/handlers/om.d.ts.map +1 -1
- package/dist/tui/handlers/tool.d.ts.map +1 -1
- package/dist/tui/handlers/types.d.ts +1 -1
- package/dist/tui/handlers/types.d.ts.map +1 -1
- package/dist/tui/mastra-tui.d.ts.map +1 -1
- package/dist/tui/modal-question.d.ts +1 -1
- package/dist/tui/modal-question.d.ts.map +1 -1
- package/dist/tui/overlay.d.ts +1 -1
- package/dist/tui/overlay.d.ts.map +1 -1
- package/dist/tui/prompt-api-key.d.ts +1 -1
- package/dist/tui/prompt-api-key.d.ts.map +1 -1
- package/dist/tui/render-messages.d.ts +1 -1
- package/dist/tui/render-messages.d.ts.map +1 -1
- package/dist/tui/setup.d.ts.map +1 -1
- package/dist/tui/shell.d.ts.map +1 -1
- package/dist/tui/state.d.ts +2 -2
- package/dist/tui/state.d.ts.map +1 -1
- package/dist/tui/status-line.d.ts.map +1 -1
- package/dist/tui/theme.d.ts +1 -1
- package/dist/tui/theme.d.ts.map +1 -1
- package/dist/tui.cjs +19 -19
- package/dist/tui.js +2 -2
- package/package.json +20 -20
- package/dist/agents/coding.d.ts +0 -2
- package/dist/agents/coding.d.ts.map +0 -1
- package/dist/agents/subagents/execute.d.ts.map +0 -1
- package/dist/agents/subagents/explore.d.ts.map +0 -1
- package/dist/agents/subagents/plan.d.ts +0 -10
- package/dist/agents/subagents/plan.d.ts.map +0 -1
- package/dist/chunk-DJEQBK7L.cjs.map +0 -1
- package/dist/chunk-EATS4KOR.cjs.map +0 -1
- package/dist/chunk-FDDVVRPH.js.map +0 -1
- package/dist/chunk-NKTZDFIU.cjs.map +0 -1
- package/dist/chunk-OXYE6SUY.js.map +0 -1
- package/dist/chunk-W7Y7QIJA.js.map +0 -1
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import { tintHex, mastra, theme, getMarkdownTheme, CHAT_INDENT, BOX_INDENT, getTermWidth, ensureTerminalGlyphContrast, TERM_WIDTH_BUFFER, getEditorTheme, loadSettings, MEMORY_GATEWAY_PROVIDER, getAvailableModePacks, resolveThreadActiveModelPackId, saveSettings, getAvailableOmPacks, ONBOARDING_VERSION, THREAD_ACTIVE_MODEL_PACK_ID_KEY, BOX_INDENT_STR,
|
|
1
|
+
import { tintHex, mastra, theme, getMarkdownTheme, CHAT_INDENT, BOX_INDENT, getTermWidth, ensureTerminalGlyphContrast, TERM_WIDTH_BUFFER, getEditorTheme, loadSettings, MEMORY_GATEWAY_PROVIDER, getAvailableModePacks, resolveThreadActiveModelPackId, saveSettings, getAvailableOmPacks, ONBOARDING_VERSION, THREAD_ACTIVE_MODEL_PACK_ID_KEY, BOX_INDENT_STR, ThreadLockError, getSelectListTheme, luminance, extendedColors, MEMORY_GATEWAY_DEFAULT_URL, getThemeMode, applyThemeMode, createBrowserFromSettings, setProfileProvider, getCustomProviderId, mastraBrand, OBSERVABILITY_AUTH_PREFIX, checkProfileProviderMismatch, getSettingsListTheme, toCustomProviderModelId } from './chunk-FXYM4OEI.js';
|
|
2
2
|
import { getOAuthProviders, detectProject, DEFAULT_CONFIG_DIR, getUserId, getCurrentGitBranchAsync, getUserName, PROVIDER_DEFAULT_MODELS, getAppDataDir } from './chunk-5FT2NNFO.js';
|
|
3
3
|
import { MC_TOOLS, getToolCategory, TOOL_CATEGORIES } from './chunk-UOFNLVKF.js';
|
|
4
4
|
import { exec, spawn, execFile, execSync, execFileSync } from 'child_process';
|
|
5
|
-
import { visibleWidth, Box, Text, Spacer, Input, Container, fuzzyFilter, getKeybindings, Markdown, ProcessTerminal, TUI, truncateToWidth, Editor, matchesKey, CombinedAutocompleteProvider, SelectList, wrapTextWithAnsi, SettingsList, parseKey } from '@
|
|
6
|
-
import
|
|
5
|
+
import { visibleWidth, Box, Text, Spacer, Input, Container, fuzzyFilter, getKeybindings, Markdown, ProcessTerminal, TUI, truncateToWidth, Editor, matchesKey, CombinedAutocompleteProvider, SelectList, wrapTextWithAnsi, SettingsList, parseKey } from '@earendil-works/pi-tui';
|
|
6
|
+
import chalk12 from 'chalk';
|
|
7
7
|
import fs2, { statSync, readFileSync, realpathSync, promises, unlinkSync } from 'fs';
|
|
8
8
|
import * as path5 from 'path';
|
|
9
9
|
import path5__default, { extname, join } from 'path';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
|
-
import stripAnsi2 from 'strip-ansi';
|
|
12
11
|
import { randomUUID } from 'crypto';
|
|
13
|
-
import {
|
|
14
|
-
import { StreamErrorRetryProcessor, PrefillErrorHandler, ProviderHistoryCompat } from '@mastra/core/processors';
|
|
15
|
-
import { createWorkspaceTools, formatSkillActivation } from '@mastra/core/workspace';
|
|
16
|
-
import { z } from 'zod';
|
|
12
|
+
import { formatSkillActivation } from '@mastra/core/workspace';
|
|
17
13
|
import { defaultOMProgressState, parseSubagentMeta, assignTaskIds } from '@mastra/core/harness';
|
|
18
14
|
import { TASKS_STATE_ID } from '@mastra/core/tools';
|
|
19
15
|
import { safeStringify } from '@mastra/core/utils';
|
|
20
16
|
import process2 from 'process';
|
|
17
|
+
import stripAnsi from 'strip-ansi';
|
|
21
18
|
import * as os from 'os';
|
|
22
19
|
import { tmpdir, homedir } from 'os';
|
|
23
20
|
import { highlight } from 'cli-highlight';
|
|
@@ -480,7 +477,6 @@ var AskQuestionInlineComponent = class _AskQuestionInlineComponent extends Conta
|
|
|
480
477
|
this.borderedBox = new AskQuestionBorderedBox([], "", [], void 0, void 0, true);
|
|
481
478
|
}
|
|
482
479
|
this.addChild(this.borderedBox);
|
|
483
|
-
this.addChild(new Spacer(1));
|
|
484
480
|
}
|
|
485
481
|
/**
|
|
486
482
|
* Update the question text and options from streaming partial args.
|
|
@@ -639,6 +635,9 @@ var AskQuestionInlineComponent = class _AskQuestionInlineComponent extends Conta
|
|
|
639
635
|
this.input.handleInput(data);
|
|
640
636
|
}
|
|
641
637
|
}
|
|
638
|
+
getChatSpacingKind() {
|
|
639
|
+
return "other";
|
|
640
|
+
}
|
|
642
641
|
};
|
|
643
642
|
|
|
644
643
|
// src/onboarding/onboarding-inline.ts
|
|
@@ -751,7 +750,7 @@ var OnboardingInlineComponent = class extends Box {
|
|
|
751
750
|
box.addChild(new Text(theme.bold(theme.fg("accent", "\u{1F44B} Welcome to Mastra Code")), 0, 0));
|
|
752
751
|
box.addChild(new Spacer(1));
|
|
753
752
|
box.addChild(new Text(theme.fg("text", "Let's configure your models and preferences."), 0, 0));
|
|
754
|
-
box.addChild(new Text(
|
|
753
|
+
box.addChild(new Text(chalk12.white("You can re-run this anytime with /setup."), 0, 0));
|
|
755
754
|
box.addChild(new Spacer(1));
|
|
756
755
|
const items = [
|
|
757
756
|
{ value: "continue", label: ` ${theme.fg("success", "Continue")}` },
|
|
@@ -886,9 +885,9 @@ var OnboardingInlineComponent = class extends Box {
|
|
|
886
885
|
this.modePackDetail.setText(theme.fg("dim", " You'll pick a model for each mode in the next steps."));
|
|
887
886
|
} else {
|
|
888
887
|
const detail = [
|
|
889
|
-
` ${
|
|
890
|
-
` ${
|
|
891
|
-
` ${
|
|
888
|
+
` ${chalk12.hex(mastra.blue)("plan")} \u2192 ${theme.fg("text", pack.models.plan)}`,
|
|
889
|
+
` ${chalk12.hex(mastra.purple)("build")} \u2192 ${theme.fg("text", pack.models.build)}`,
|
|
890
|
+
` ${chalk12.hex(mastra.green)("fast")} \u2192 ${theme.fg("text", pack.models.fast)}`
|
|
892
891
|
].join("\n");
|
|
893
892
|
this.modePackDetail.setText(detail);
|
|
894
893
|
}
|
|
@@ -959,7 +958,7 @@ var OnboardingInlineComponent = class extends Box {
|
|
|
959
958
|
models: { build: models.build, plan: models.plan, fast: models.fast }
|
|
960
959
|
};
|
|
961
960
|
this.collapseStep(
|
|
962
|
-
`Model pack \u2192 ${theme.bold(packName)} ${
|
|
961
|
+
`Model pack \u2192 ${theme.bold(packName)} ${chalk12.hex(mastra.blue)("plan")} ${models.plan} ${chalk12.hex(mastra.purple)("build")} ${models.build} ${chalk12.hex(mastra.green)("fast")} ${models.fast}`
|
|
963
962
|
);
|
|
964
963
|
this.renderStep("omPack");
|
|
965
964
|
this.tui.requestRender();
|
|
@@ -1073,9 +1072,9 @@ var OnboardingInlineComponent = class extends Box {
|
|
|
1073
1072
|
box.addChild(new Spacer(1));
|
|
1074
1073
|
const lines = [
|
|
1075
1074
|
`Model pack: ${theme.bold(this.selectedModePack.name)}`,
|
|
1076
|
-
` ${
|
|
1077
|
-
` ${
|
|
1078
|
-
` ${
|
|
1075
|
+
` ${chalk12.hex(mastra.blue)("plan")} \u2192 ${this.selectedModePack.models.plan}`,
|
|
1076
|
+
` ${chalk12.hex(mastra.purple)("build")} \u2192 ${this.selectedModePack.models.build}`,
|
|
1077
|
+
` ${chalk12.hex(mastra.green)("fast")} \u2192 ${this.selectedModePack.models.fast}`,
|
|
1079
1078
|
`Observational memory: ${theme.bold(this.selectedOmPack.name)}`,
|
|
1080
1079
|
`YOLO mode: ${theme.bold(this.selectedYolo ? "enabled" : "disabled")}`
|
|
1081
1080
|
];
|
|
@@ -1175,7 +1174,7 @@ function getInstallCommand(pm, version) {
|
|
|
1175
1174
|
}
|
|
1176
1175
|
function getCurrentVersion() {
|
|
1177
1176
|
{
|
|
1178
|
-
return "0.
|
|
1177
|
+
return "0.23.0";
|
|
1179
1178
|
}
|
|
1180
1179
|
}
|
|
1181
1180
|
async function fetchLatestVersion() {
|
|
@@ -1274,6 +1273,15 @@ function buildInstallArgs(pm, version) {
|
|
|
1274
1273
|
return ["install", "-g", pkg];
|
|
1275
1274
|
}
|
|
1276
1275
|
}
|
|
1276
|
+
var ChatBoundarySpacer = class extends Spacer {
|
|
1277
|
+
isChatBoundarySpacer = true;
|
|
1278
|
+
constructor(lines = 1) {
|
|
1279
|
+
super(lines);
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
function isChatBoundarySpacer(component) {
|
|
1283
|
+
return !!component && component.isChatBoundarySpacer === true;
|
|
1284
|
+
}
|
|
1277
1285
|
|
|
1278
1286
|
// src/tui/components/chat-spacing.ts
|
|
1279
1287
|
function getChatSpacingKind(component) {
|
|
@@ -1309,84 +1317,13 @@ function isToolSpacingKind(kind) {
|
|
|
1309
1317
|
return kind === "quiet-compact-tool" || kind === "quiet-shell-tool" || kind === "normal-tool";
|
|
1310
1318
|
}
|
|
1311
1319
|
|
|
1312
|
-
// src/tui/components/chat-boundary-spacer.ts
|
|
1313
|
-
var ChatBoundarySpacer = class {
|
|
1314
|
-
constructor(getPrev, getNext, getPrevPrev = () => void 0, getNextNext = () => void 0) {
|
|
1315
|
-
this.getPrev = getPrev;
|
|
1316
|
-
this.getNext = getNext;
|
|
1317
|
-
this.getPrevPrev = getPrevPrev;
|
|
1318
|
-
this.getNextNext = getNextNext;
|
|
1319
|
-
}
|
|
1320
|
-
getPrev;
|
|
1321
|
-
getNext;
|
|
1322
|
-
getPrevPrev;
|
|
1323
|
-
getNextNext;
|
|
1324
|
-
isChatBoundarySpacer = true;
|
|
1325
|
-
invalidate() {
|
|
1326
|
-
}
|
|
1327
|
-
render() {
|
|
1328
|
-
const spacing = getSpacingBetweenComponents(this.getPrev(), this.getNext(), this.getPrevPrev(), this.getNextNext());
|
|
1329
|
-
return Array.from({ length: spacing }, () => "");
|
|
1330
|
-
}
|
|
1331
|
-
};
|
|
1332
|
-
function isChatBoundarySpacer(component) {
|
|
1333
|
-
return !!component && component.isChatBoundarySpacer === true;
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
1320
|
// src/tui/chat-boundary-reconciliation.ts
|
|
1337
1321
|
function insertChatComponentWithBoundarySpacing(chatContainer, child, index = chatContainer.children.length) {
|
|
1338
1322
|
const children = chatContainer.children;
|
|
1339
1323
|
const boundedIndex = Math.max(0, Math.min(index, children.length));
|
|
1340
|
-
|
|
1341
|
-
const previousPrevious = findPreviousSpacingComponent(children, previous ? children.indexOf(previous) : -1);
|
|
1342
|
-
const next = findNextSpacingComponent(children, boundedIndex);
|
|
1343
|
-
const nextNext = findNextSpacingComponent(children, next ? children.indexOf(next) + 1 : children.length);
|
|
1344
|
-
const inserted = [];
|
|
1345
|
-
if (previous) {
|
|
1346
|
-
inserted.push(
|
|
1347
|
-
new ChatBoundarySpacer(
|
|
1348
|
-
() => previous,
|
|
1349
|
-
() => child,
|
|
1350
|
-
() => previousPrevious,
|
|
1351
|
-
() => next
|
|
1352
|
-
)
|
|
1353
|
-
);
|
|
1354
|
-
}
|
|
1355
|
-
inserted.push(child);
|
|
1356
|
-
if (next) {
|
|
1357
|
-
inserted.push(
|
|
1358
|
-
new ChatBoundarySpacer(
|
|
1359
|
-
() => child,
|
|
1360
|
-
() => next,
|
|
1361
|
-
() => previous,
|
|
1362
|
-
() => nextNext
|
|
1363
|
-
)
|
|
1364
|
-
);
|
|
1365
|
-
}
|
|
1366
|
-
children.splice(boundedIndex, 0, ...inserted);
|
|
1324
|
+
children.splice(boundedIndex, 0, child);
|
|
1367
1325
|
reconcileChatBoundarySpacers(chatContainer);
|
|
1368
1326
|
}
|
|
1369
|
-
function findPreviousSpacingComponent(children, index) {
|
|
1370
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
1371
|
-
const child = children[i];
|
|
1372
|
-
if (child && !isChatBoundarySpacer(child) && getChatSpacingKind(child)) return child;
|
|
1373
|
-
}
|
|
1374
|
-
return void 0;
|
|
1375
|
-
}
|
|
1376
|
-
function findNextSpacingComponent(children, index) {
|
|
1377
|
-
for (let i = index; i < children.length; i++) {
|
|
1378
|
-
const child = children[i];
|
|
1379
|
-
if (child && !isChatBoundarySpacer(child) && getChatSpacingKind(child)) return child;
|
|
1380
|
-
}
|
|
1381
|
-
return void 0;
|
|
1382
|
-
}
|
|
1383
|
-
function findPreviousSpacingComponentInList(components, index) {
|
|
1384
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
1385
|
-
const child = components[i];
|
|
1386
|
-
if (child && getChatSpacingKind(child)) return child;
|
|
1387
|
-
}
|
|
1388
|
-
return void 0;
|
|
1389
|
-
}
|
|
1390
1327
|
function findNextSpacingComponentInList(components, index) {
|
|
1391
1328
|
for (let i = index + 1; i < components.length; i++) {
|
|
1392
1329
|
const child = components[i];
|
|
@@ -1395,11 +1332,15 @@ function findNextSpacingComponentInList(components, index) {
|
|
|
1395
1332
|
return void 0;
|
|
1396
1333
|
}
|
|
1397
1334
|
function reconcileChatBoundarySpacers(chatContainer) {
|
|
1398
|
-
const
|
|
1335
|
+
const children = chatContainer.children;
|
|
1336
|
+
const components = children.filter((child) => !isChatBoundarySpacer(child));
|
|
1337
|
+
const spacerPool = children.filter(isChatBoundarySpacer);
|
|
1338
|
+
let poolIndex = 0;
|
|
1399
1339
|
const nextChildren = [];
|
|
1400
1340
|
let previousCompactToolGroupKey;
|
|
1401
1341
|
let previousCompactToolSummary;
|
|
1402
1342
|
let currentCompactRun = [];
|
|
1343
|
+
let previousSpacingComponent;
|
|
1403
1344
|
const flushCompactRunColor = () => {
|
|
1404
1345
|
const color = getCompactRunLabelColor(currentCompactRun);
|
|
1405
1346
|
for (const participant of currentCompactRun) {
|
|
@@ -1431,22 +1372,24 @@ function reconcileChatBoundarySpacers(chatContainer) {
|
|
|
1431
1372
|
previousCompactToolGroupKey = compactToolGroupKey;
|
|
1432
1373
|
previousCompactToolSummary = compactToolGroupSummary;
|
|
1433
1374
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
)
|
|
1447
|
-
);
|
|
1375
|
+
if (getChatSpacingKind(component) && previousSpacingComponent) {
|
|
1376
|
+
const spacing = getSpacingBetweenComponents(previousSpacingComponent, component);
|
|
1377
|
+
if (spacing > 0) {
|
|
1378
|
+
let spacer;
|
|
1379
|
+
if (poolIndex < spacerPool.length) {
|
|
1380
|
+
spacer = spacerPool[poolIndex];
|
|
1381
|
+
spacer.setLines(spacing);
|
|
1382
|
+
poolIndex++;
|
|
1383
|
+
} else {
|
|
1384
|
+
spacer = new ChatBoundarySpacer(spacing);
|
|
1385
|
+
}
|
|
1386
|
+
nextChildren.push(spacer);
|
|
1448
1387
|
}
|
|
1449
1388
|
}
|
|
1389
|
+
if (getChatSpacingKind(component)) {
|
|
1390
|
+
previousSpacingComponent = component;
|
|
1391
|
+
}
|
|
1392
|
+
nextChildren.push(component);
|
|
1450
1393
|
}
|
|
1451
1394
|
flushCompactRunColor();
|
|
1452
1395
|
chatContainer.children = nextChildren;
|
|
@@ -1569,116 +1512,6 @@ var GoalCyclesDialogComponent = class extends Box {
|
|
|
1569
1512
|
this.input.handleInput(data);
|
|
1570
1513
|
}
|
|
1571
1514
|
};
|
|
1572
|
-
var JUDGE_COLOR = mastraBrand.blue;
|
|
1573
|
-
var MUTED_COLOR = "#8a8a8a";
|
|
1574
|
-
var PAUSED_COLOR = "#f5a524";
|
|
1575
|
-
var WAITING_COLOR = "#8a8a8a";
|
|
1576
|
-
var JudgeDisplayComponent = class extends Container {
|
|
1577
|
-
result;
|
|
1578
|
-
turnsUsed;
|
|
1579
|
-
maxTurns;
|
|
1580
|
-
activity = [];
|
|
1581
|
-
constructor(result = null, turnsUsed = 0, maxTurns = 0) {
|
|
1582
|
-
super();
|
|
1583
|
-
this.result = result;
|
|
1584
|
-
this.turnsUsed = turnsUsed;
|
|
1585
|
-
this.maxTurns = maxTurns;
|
|
1586
|
-
this.renderContent();
|
|
1587
|
-
}
|
|
1588
|
-
addActivity(line) {
|
|
1589
|
-
if (this.activity[this.activity.length - 1] !== line) {
|
|
1590
|
-
this.activity.push(line);
|
|
1591
|
-
}
|
|
1592
|
-
if (this.activity.length > 6) {
|
|
1593
|
-
this.activity = this.activity.slice(-6);
|
|
1594
|
-
}
|
|
1595
|
-
this.renderContent();
|
|
1596
|
-
}
|
|
1597
|
-
setResult(result, turnsUsed, maxTurns) {
|
|
1598
|
-
this.result = result;
|
|
1599
|
-
this.turnsUsed = turnsUsed;
|
|
1600
|
-
this.maxTurns = maxTurns;
|
|
1601
|
-
this.renderContent();
|
|
1602
|
-
}
|
|
1603
|
-
setInterrupted() {
|
|
1604
|
-
this.setResult({ decision: "paused", reason: "Judge evaluation was interrupted." }, this.turnsUsed, this.maxTurns);
|
|
1605
|
-
}
|
|
1606
|
-
renderContent() {
|
|
1607
|
-
this.clear();
|
|
1608
|
-
const border = (char) => chalk14.hex(JUDGE_COLOR)(char);
|
|
1609
|
-
const title = chalk14.hex(JUDGE_COLOR).bold("Goal");
|
|
1610
|
-
const termWidth = getTermWidth();
|
|
1611
|
-
const innerWidth = Math.max(20, termWidth - BOX_INDENT * 2 - 4);
|
|
1612
|
-
const horizontal = "\u2500".repeat(innerWidth + 1);
|
|
1613
|
-
this.addChild(new Spacer(1));
|
|
1614
|
-
this.addChild(new Text(`${border("\u256D")}${border(horizontal)}${border("\u256E")}`, BOX_INDENT, 0));
|
|
1615
|
-
this.addChild(new Text(this.renderRow(this.renderHeader(title), innerWidth, border), BOX_INDENT, 0));
|
|
1616
|
-
if (!this.result && this.activity.length === 0) {
|
|
1617
|
-
this.addChild(new Text(this.renderRow(chalk14.dim("evaluating\u2026"), innerWidth, border), BOX_INDENT, 0));
|
|
1618
|
-
}
|
|
1619
|
-
for (const line of this.activity) {
|
|
1620
|
-
this.addChild(new Text(this.renderRow(this.renderActivityLine(line), innerWidth, border), BOX_INDENT, 0));
|
|
1621
|
-
}
|
|
1622
|
-
if (this.activity.length > 0 && this.result) {
|
|
1623
|
-
this.addChild(new Text(this.renderRow("", innerWidth, border), BOX_INDENT, 0));
|
|
1624
|
-
}
|
|
1625
|
-
if (this.result) {
|
|
1626
|
-
for (const line of this.wrapLine(this.result.reason, innerWidth)) {
|
|
1627
|
-
this.addChild(new Text(this.renderRow(chalk14.dim(line), innerWidth, border), BOX_INDENT, 0));
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
this.addChild(new Text(`${border("\u2570")}${border(horizontal)}${border("\u256F")}`, BOX_INDENT, 0));
|
|
1631
|
-
}
|
|
1632
|
-
renderActivityLine(line) {
|
|
1633
|
-
const toolName = getActivityToolName(line);
|
|
1634
|
-
if (!toolName) return theme.fg("dim", `\u2022 ${line}`);
|
|
1635
|
-
const rest = line.slice(toolName.length);
|
|
1636
|
-
return `${theme.fg("dim", "\u2022 ")}${theme.fg("dim", theme.italic(toolName))}${theme.fg("dim", rest)}`;
|
|
1637
|
-
}
|
|
1638
|
-
renderHeader(title) {
|
|
1639
|
-
if (!this.result) {
|
|
1640
|
-
return `${title} \u25CC ${chalk14.hex(WAITING_COLOR).bold("evaluating")}`;
|
|
1641
|
-
}
|
|
1642
|
-
const decisionIcon = this.result.decision === "done" ? "\u25CF" : this.result.decision === "paused" ? "!" : this.result.decision === "waiting" ? "\u25CC" : "\u25CB";
|
|
1643
|
-
const decisionText = getDecisionText(this.result.decision);
|
|
1644
|
-
const turnInfo = this.maxTurns > 0 ? chalk14.hex(MUTED_COLOR)(`(${this.turnsUsed}/${this.maxTurns})`) : "";
|
|
1645
|
-
return `${title} ${decisionIcon} ${decisionText}${turnInfo ? ` ${turnInfo}` : ""}`;
|
|
1646
|
-
}
|
|
1647
|
-
renderRow(text, width, border) {
|
|
1648
|
-
const content = this.padLine(text, width);
|
|
1649
|
-
return `${border("\u2502")} ${content}${border("\u2502")}`;
|
|
1650
|
-
}
|
|
1651
|
-
wrapLine(text, width) {
|
|
1652
|
-
const lines = [];
|
|
1653
|
-
let remaining = text;
|
|
1654
|
-
while (remaining.length > width) {
|
|
1655
|
-
const breakAt = remaining.lastIndexOf(" ", width);
|
|
1656
|
-
const splitAt = breakAt > 0 ? breakAt : width;
|
|
1657
|
-
lines.push(remaining.slice(0, splitAt));
|
|
1658
|
-
remaining = remaining.slice(splitAt).trimStart();
|
|
1659
|
-
}
|
|
1660
|
-
lines.push(remaining);
|
|
1661
|
-
return lines;
|
|
1662
|
-
}
|
|
1663
|
-
padLine(text, width) {
|
|
1664
|
-
const visibleLength = stripAnsi2(text).length;
|
|
1665
|
-
if (visibleLength >= width) {
|
|
1666
|
-
return stripAnsi2(text).slice(0, width);
|
|
1667
|
-
}
|
|
1668
|
-
return text + " ".repeat(width - visibleLength);
|
|
1669
|
-
}
|
|
1670
|
-
};
|
|
1671
|
-
function getActivityToolName(line) {
|
|
1672
|
-
if (line.startsWith("find files ")) return "find files";
|
|
1673
|
-
const [toolName] = line.split(" ");
|
|
1674
|
-
return toolName || null;
|
|
1675
|
-
}
|
|
1676
|
-
function getDecisionText(decision) {
|
|
1677
|
-
if (decision === "done") return chalk14.hex("#16c858").bold("done");
|
|
1678
|
-
if (decision === "paused") return chalk14.hex(PAUSED_COLOR).bold("paused");
|
|
1679
|
-
if (decision === "waiting") return chalk14.hex(WAITING_COLOR).bold("waiting");
|
|
1680
|
-
return chalk14.hex(JUDGE_COLOR).bold("continue");
|
|
1681
|
-
}
|
|
1682
1515
|
function makeCustomModelItem(id, models) {
|
|
1683
1516
|
const parts = id.split("/");
|
|
1684
1517
|
const provider = parts.length > 1 ? parts[0] : "custom";
|
|
@@ -1726,7 +1559,7 @@ var ModelSelectorComponent = class extends Box {
|
|
|
1726
1559
|
this.buildUI();
|
|
1727
1560
|
}
|
|
1728
1561
|
buildUI() {
|
|
1729
|
-
const titleText = this.titleColor ?
|
|
1562
|
+
const titleText = this.titleColor ? chalk12.bgHex(this.titleColor).white.bold(` ${this.title} `) : theme.bold(theme.fg("accent", this.title));
|
|
1730
1563
|
this.addChild(new Text(titleText, 0, 0));
|
|
1731
1564
|
this.addChild(new Spacer(1));
|
|
1732
1565
|
this.addChild(new Text(theme.fg("muted", "Type to search \u2022 \u2191\u2193 navigate \u2022 Enter select \u2022 Esc cancel"), 0, 0));
|
|
@@ -1854,173 +1687,35 @@ var ModelSelectorComponent = class extends Box {
|
|
|
1854
1687
|
return this.searchInput;
|
|
1855
1688
|
}
|
|
1856
1689
|
};
|
|
1857
|
-
var GRADIENT_WIDTH = 30;
|
|
1858
|
-
var BASE_COLOR = [22, 200, 88];
|
|
1859
|
-
function getMinBrightness() {
|
|
1860
|
-
return getThemeMode() === "dark" ? 0.45 : 0.55;
|
|
1861
|
-
}
|
|
1862
|
-
function hexToRgb(hex) {
|
|
1863
|
-
const h = hex.replace("#", "");
|
|
1864
|
-
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
1865
|
-
}
|
|
1866
|
-
var IDLE_BRIGHTNESS = 0.8;
|
|
1867
|
-
function applyGradientSweep(text, offset, color, fadeProgress = 0) {
|
|
1868
|
-
const chars = [...text];
|
|
1869
|
-
const totalChars = chars.length;
|
|
1870
|
-
if (totalChars === 0) return text;
|
|
1871
|
-
const baseColor = color ? hexToRgb(color) : BASE_COLOR;
|
|
1872
|
-
const gradientCenter = offset % 1 * 100;
|
|
1873
|
-
const halfGradient = GRADIENT_WIDTH / 2;
|
|
1874
|
-
const minBrightness = getMinBrightness();
|
|
1875
|
-
const brightnessRange = 1 - minBrightness;
|
|
1876
|
-
let result = "";
|
|
1877
|
-
let batchChars = "";
|
|
1878
|
-
let batchR = -1, batchG = -1, batchB = -1;
|
|
1879
|
-
for (let i = 0; i < totalChars; i++) {
|
|
1880
|
-
const char = chars[i];
|
|
1881
|
-
if (char === " ") {
|
|
1882
|
-
if (batchChars) {
|
|
1883
|
-
result += chalk14.rgb(batchR, batchG, batchB)(batchChars);
|
|
1884
|
-
batchChars = "";
|
|
1885
|
-
}
|
|
1886
|
-
result += " ";
|
|
1887
|
-
continue;
|
|
1888
|
-
}
|
|
1889
|
-
const charPosition = i / totalChars * 100;
|
|
1890
|
-
let distance = Math.abs(charPosition - gradientCenter);
|
|
1891
|
-
if (distance > 50) distance = 100 - distance;
|
|
1892
|
-
const normalizedDistance = Math.min(distance / halfGradient, 1);
|
|
1893
|
-
const animBrightness = minBrightness + brightnessRange * (1 - normalizedDistance);
|
|
1894
|
-
const brightness = animBrightness + (IDLE_BRIGHTNESS - animBrightness) * fadeProgress;
|
|
1895
|
-
const r = Math.floor(baseColor[0] * brightness);
|
|
1896
|
-
const g = Math.floor(baseColor[1] * brightness);
|
|
1897
|
-
const b = Math.floor(baseColor[2] * brightness);
|
|
1898
|
-
if (r === batchR && g === batchG && b === batchB) {
|
|
1899
|
-
batchChars += char;
|
|
1900
|
-
} else {
|
|
1901
|
-
if (batchChars) {
|
|
1902
|
-
result += chalk14.rgb(batchR, batchG, batchB)(batchChars);
|
|
1903
|
-
}
|
|
1904
|
-
batchChars = char;
|
|
1905
|
-
batchR = r;
|
|
1906
|
-
batchG = g;
|
|
1907
|
-
batchB = b;
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
if (batchChars) {
|
|
1911
|
-
result += chalk14.rgb(batchR, batchG, batchB)(batchChars);
|
|
1912
|
-
}
|
|
1913
|
-
return result;
|
|
1914
|
-
}
|
|
1915
|
-
var GradientAnimator = class {
|
|
1916
|
-
offset = 0;
|
|
1917
|
-
intervalId = null;
|
|
1918
|
-
onTick;
|
|
1919
|
-
_isFadingOut = false;
|
|
1920
|
-
_isFadingIn = false;
|
|
1921
|
-
_fadeProgress = 0;
|
|
1922
|
-
// 0 = full animation, 1 = fully idle
|
|
1923
|
-
constructor(onTick) {
|
|
1924
|
-
this.onTick = onTick;
|
|
1925
|
-
}
|
|
1926
|
-
start() {
|
|
1927
|
-
if (this.intervalId && !this._isFadingOut) return;
|
|
1928
|
-
if (this.intervalId) {
|
|
1929
|
-
clearInterval(this.intervalId);
|
|
1930
|
-
this.intervalId = null;
|
|
1931
|
-
}
|
|
1932
|
-
this._isFadingOut = false;
|
|
1933
|
-
this._isFadingIn = true;
|
|
1934
|
-
this._fadeProgress = 1;
|
|
1935
|
-
this.offset = 0;
|
|
1936
|
-
this.intervalId = setInterval(() => {
|
|
1937
|
-
this.offset += 0.03;
|
|
1938
|
-
if (this._isFadingIn) {
|
|
1939
|
-
this._fadeProgress -= 0.06;
|
|
1940
|
-
if (this._fadeProgress <= 0) {
|
|
1941
|
-
this._fadeProgress = 0;
|
|
1942
|
-
this._isFadingIn = false;
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
this.onTick();
|
|
1946
|
-
}, 80);
|
|
1947
|
-
}
|
|
1948
|
-
/**
|
|
1949
|
-
* Smoothly fade the gradient to idle state over ~500ms.
|
|
1950
|
-
*/
|
|
1951
|
-
fadeOut() {
|
|
1952
|
-
if (!this.intervalId) return;
|
|
1953
|
-
if (this._isFadingOut) return;
|
|
1954
|
-
this._isFadingOut = true;
|
|
1955
|
-
this._isFadingIn = false;
|
|
1956
|
-
this._fadeProgress = 0;
|
|
1957
|
-
clearInterval(this.intervalId);
|
|
1958
|
-
this.intervalId = setInterval(() => {
|
|
1959
|
-
this._fadeProgress += 0.08;
|
|
1960
|
-
if (this._fadeProgress >= 1) {
|
|
1961
|
-
this._fadeProgress = 1;
|
|
1962
|
-
this.stop();
|
|
1963
|
-
}
|
|
1964
|
-
this.onTick();
|
|
1965
|
-
}, 40);
|
|
1966
|
-
}
|
|
1967
|
-
stop() {
|
|
1968
|
-
if (this.intervalId) {
|
|
1969
|
-
clearInterval(this.intervalId);
|
|
1970
|
-
this.intervalId = null;
|
|
1971
|
-
}
|
|
1972
|
-
this._isFadingOut = false;
|
|
1973
|
-
this._isFadingIn = false;
|
|
1974
|
-
this._fadeProgress = 0;
|
|
1975
|
-
this.offset = 0;
|
|
1976
|
-
}
|
|
1977
|
-
getOffset() {
|
|
1978
|
-
return this.offset;
|
|
1979
|
-
}
|
|
1980
|
-
/** 0 = full animation, 1 = fully idle. Use to interpolate colors. */
|
|
1981
|
-
getFadeProgress() {
|
|
1982
|
-
return this._fadeProgress;
|
|
1983
|
-
}
|
|
1984
|
-
isFadingOut() {
|
|
1985
|
-
return this._isFadingOut;
|
|
1986
|
-
}
|
|
1987
|
-
isFadingIn() {
|
|
1988
|
-
return this._isFadingIn;
|
|
1989
|
-
}
|
|
1990
|
-
isRunning() {
|
|
1991
|
-
return this.intervalId !== null;
|
|
1992
|
-
}
|
|
1993
|
-
};
|
|
1994
1690
|
var DEFAULT_MAX_TURNS = 50;
|
|
1995
1691
|
var THREAD_GOAL_KEY = "goal";
|
|
1996
|
-
var JUDGE_MAX_STEPS = 50;
|
|
1997
|
-
var JUDGE_RETRY_PROMPT = 'You did not produce a structured decision. You MUST respond with a JSON object containing "decision" (one of "done", "continue", or "waiting") and "reason" (a brief explanation). Do not use any tools \u2014 respond with the JSON decision immediately based on what you already know.';
|
|
1998
|
-
var JUDGE_SYSTEM_PROMPT = `You are the goal judge. Your decision directly controls whether the assistant continues working toward the goal.
|
|
1999
|
-
|
|
2000
|
-
Given a goal and the assistant's latest response, reason about whether the goal's requirements have been satisfied. Compare what the goal asks for against what the assistant has actually produced. Focus on substance, not phrasing.
|
|
2001
|
-
|
|
2002
|
-
Use "done" when the goal is fully achieved.
|
|
2003
|
-
Use "waiting" when the goal explicitly requires a user checkpoint, user feedback, human verification, human confirmation, or another external event outside the goal-judge loop before the assistant should continue, and the assistant has correctly stopped at that checkpoint.
|
|
2004
|
-
Use "waiting" when the latest user message asks a question or requests clarification and the latest assistant message answers it; let the user acknowledge the answer, ask a follow-up, or otherwise return control before continuing goal work. Use common sense and do not wait if the user explicitly asked the assistant to continue autonomously after answering.
|
|
2005
|
-
Use "continue" when the goal is not done and the assistant should keep working autonomously, including when it asked for input that the goal did not explicitly require.
|
|
2006
|
-
If your previous decision was "waiting" for an explicit user checkpoint, keep choosing "waiting" when the user's latest response asks a question, requests clarification, or otherwise does not satisfy the checkpoint. Do not continue until the required user feedback/confirmation/verification has actually been provided.
|
|
2007
|
-
If the goal says to wait for the goal judge, judge, evaluator, or you to respond, approve, verify, validate, tell the assistant to continue, or otherwise provide the next signal, treat your own decision as that judge response. Verification can be performed by you unless the goal explicitly says it needs human/user verification. Choose "continue" when the assistant should proceed to the next step. Do not choose "waiting" for judge-controlled checkpoints, because that would mean waiting for yourself.
|
|
2008
|
-
|
|
2009
|
-
Your "reason" field is sent back to the assistant as guidance when the goal is not yet done \u2014 be specific about what still needs to be accomplished. When choosing "continue", write the reason as an instruction for what the assistant should do next. When choosing "waiting", explain what specific user checkpoint is still outstanding.`;
|
|
2010
|
-
var judgeSchema = z.object({
|
|
2011
|
-
decision: z.enum(["done", "continue", "waiting"]).describe(
|
|
2012
|
-
"Whether the goal is done, should continue autonomously, or is at an explicit user checkpoint required by the goal"
|
|
2013
|
-
),
|
|
2014
|
-
reason: z.string().describe("Brief explanation of what was accomplished or what remains to be done")
|
|
2015
|
-
});
|
|
2016
1692
|
var GoalManager = class {
|
|
2017
|
-
|
|
1693
|
+
/** Synchronous in-memory view of the active objective record (source of truth is ThreadState). */
|
|
1694
|
+
record = null;
|
|
1695
|
+
/** Display-only active-timer accounting (not persisted to the objective record). */
|
|
1696
|
+
activeStartedAt = null;
|
|
1697
|
+
activeDurationMs = 0;
|
|
2018
1698
|
persistGoalOnNextThreadCreate = false;
|
|
1699
|
+
// ---------------------------------------------------------------------------
|
|
1700
|
+
// Synchronous TUI surface
|
|
1701
|
+
// ---------------------------------------------------------------------------
|
|
2019
1702
|
getGoal() {
|
|
2020
|
-
|
|
1703
|
+
if (!this.record) return null;
|
|
1704
|
+
const { judgeModelId, maxTurns } = this.effectiveSettings(this.record);
|
|
1705
|
+
return {
|
|
1706
|
+
id: this.record.id,
|
|
1707
|
+
objective: this.record.objective,
|
|
1708
|
+
status: this.record.status,
|
|
1709
|
+
turnsUsed: this.record.runsUsed,
|
|
1710
|
+
maxTurns,
|
|
1711
|
+
judgeModelId,
|
|
1712
|
+
startedAt: new Date(this.record.startedAt).toISOString(),
|
|
1713
|
+
activeStartedAt: this.activeStartedAt ?? void 0,
|
|
1714
|
+
activeDurationMs: this.activeDurationMs
|
|
1715
|
+
};
|
|
2021
1716
|
}
|
|
2022
1717
|
isActive() {
|
|
2023
|
-
return this.
|
|
1718
|
+
return this.record?.status === "active";
|
|
2024
1719
|
}
|
|
2025
1720
|
persistOnNextThreadCreate() {
|
|
2026
1721
|
this.persistGoalOnNextThreadCreate = true;
|
|
@@ -2030,404 +1725,231 @@ var GoalManager = class {
|
|
|
2030
1725
|
this.persistGoalOnNextThreadCreate = false;
|
|
2031
1726
|
return true;
|
|
2032
1727
|
}
|
|
2033
|
-
/**
|
|
2034
|
-
* Set a new goal objective. Resets turn counter.
|
|
2035
|
-
*/
|
|
2036
|
-
setGoal(objective, judgeModelId, maxTurns = DEFAULT_MAX_TURNS) {
|
|
2037
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2038
|
-
this.goal = {
|
|
2039
|
-
id: randomUUID(),
|
|
2040
|
-
objective,
|
|
2041
|
-
status: "active",
|
|
2042
|
-
turnsUsed: 0,
|
|
2043
|
-
maxTurns,
|
|
2044
|
-
judgeModelId,
|
|
2045
|
-
startedAt: now,
|
|
2046
|
-
activeStartedAt: now,
|
|
2047
|
-
activeDurationMs: 0
|
|
2048
|
-
};
|
|
2049
|
-
return this.goal;
|
|
2050
|
-
}
|
|
2051
|
-
/**
|
|
2052
|
-
* Load goal state from thread metadata (called on thread switch).
|
|
2053
|
-
*/
|
|
2054
|
-
loadFromThreadMetadata(metadata) {
|
|
2055
|
-
const saved = metadata?.[THREAD_GOAL_KEY];
|
|
2056
|
-
if (saved && saved.objective && saved.status) {
|
|
2057
|
-
this.goal = {
|
|
2058
|
-
...saved,
|
|
2059
|
-
id: saved.id ?? randomUUID(),
|
|
2060
|
-
startedAt: saved.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
2061
|
-
activeStartedAt: void 0,
|
|
2062
|
-
activeDurationMs: saved.activeDurationMs ?? 0
|
|
2063
|
-
};
|
|
2064
|
-
} else {
|
|
2065
|
-
this.goal = null;
|
|
2066
|
-
}
|
|
2067
|
-
this.persistGoalOnNextThreadCreate = false;
|
|
2068
|
-
}
|
|
2069
|
-
/**
|
|
2070
|
-
* Persist goal state to thread metadata.
|
|
2071
|
-
*/
|
|
2072
|
-
async saveToThread(state) {
|
|
2073
|
-
try {
|
|
2074
|
-
if (this.goal) {
|
|
2075
|
-
await state.harness.setThreadSetting({ key: THREAD_GOAL_KEY, value: this.goal });
|
|
2076
|
-
} else {
|
|
2077
|
-
await state.harness.setThreadSetting({ key: THREAD_GOAL_KEY, value: void 0 });
|
|
2078
|
-
}
|
|
2079
|
-
} catch {
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
pause() {
|
|
2083
|
-
if (this.goal && this.goal.status === "active") {
|
|
2084
|
-
this.stopActiveTimer();
|
|
2085
|
-
this.goal.status = "paused";
|
|
2086
|
-
}
|
|
2087
|
-
return this.goal;
|
|
2088
|
-
}
|
|
2089
|
-
resume() {
|
|
2090
|
-
if (this.goal && this.goal.status === "paused") {
|
|
2091
|
-
this.goal.status = "active";
|
|
2092
|
-
this.startActiveTimer();
|
|
2093
|
-
}
|
|
2094
|
-
return this.goal;
|
|
2095
|
-
}
|
|
2096
1728
|
startActiveTimer() {
|
|
2097
|
-
if (this.
|
|
2098
|
-
this.
|
|
1729
|
+
if (this.record?.status === "active" && !this.activeStartedAt) {
|
|
1730
|
+
this.activeStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2099
1731
|
}
|
|
2100
1732
|
}
|
|
2101
1733
|
stopActiveTimer() {
|
|
2102
|
-
if (!this.
|
|
2103
|
-
const
|
|
2104
|
-
if (Number.isFinite(
|
|
2105
|
-
this.
|
|
2106
|
-
}
|
|
2107
|
-
this.goal.activeStartedAt = void 0;
|
|
2108
|
-
}
|
|
2109
|
-
updateJudgeDefaults(judgeModelId, maxTurns) {
|
|
2110
|
-
if (this.goal) {
|
|
2111
|
-
this.goal.judgeModelId = judgeModelId;
|
|
2112
|
-
this.goal.maxTurns = maxTurns;
|
|
1734
|
+
if (!this.activeStartedAt) return;
|
|
1735
|
+
const startedMs = Date.parse(this.activeStartedAt);
|
|
1736
|
+
if (Number.isFinite(startedMs)) {
|
|
1737
|
+
this.activeDurationMs += Math.max(0, Date.now() - startedMs);
|
|
2113
1738
|
}
|
|
2114
|
-
|
|
1739
|
+
this.activeStartedAt = null;
|
|
2115
1740
|
}
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
this.
|
|
2119
|
-
|
|
2120
|
-
markDone() {
|
|
2121
|
-
if (this.goal) {
|
|
2122
|
-
this.stopActiveTimer();
|
|
2123
|
-
this.goal.status = "done";
|
|
2124
|
-
}
|
|
1741
|
+
/** Reset active-timer accounting to zero (e.g. for an untriggered plan goal). */
|
|
1742
|
+
resetActiveTimer() {
|
|
1743
|
+
this.activeStartedAt = null;
|
|
1744
|
+
this.activeDurationMs = 0;
|
|
2125
1745
|
}
|
|
1746
|
+
// ---------------------------------------------------------------------------
|
|
1747
|
+
// Objective lifecycle (ThreadState-backed via the agent)
|
|
1748
|
+
// ---------------------------------------------------------------------------
|
|
2126
1749
|
/**
|
|
2127
|
-
*
|
|
2128
|
-
*
|
|
1750
|
+
* Set a new objective. Persists to ThreadState via `agent.setObjective` and
|
|
1751
|
+
* updates the in-memory view. Only the provided settings are persisted into
|
|
1752
|
+
* the record; unset ones fall back to the agent's `goal` config at read time.
|
|
2129
1753
|
*/
|
|
2130
|
-
async
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
const
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
this.stopActiveTimer();
|
|
2146
|
-
this.goal.status = "paused";
|
|
2147
|
-
this.goal.lastPauseWasJudgeFailure = true;
|
|
2148
|
-
await this.saveToThread(state);
|
|
2149
|
-
return { continuation: null, judgeResult: result2 };
|
|
2150
|
-
}
|
|
2151
|
-
if (this.goal.turnsUsed >= this.goal.maxTurns) {
|
|
2152
|
-
this.stopActiveTimer();
|
|
2153
|
-
this.goal.status = "paused";
|
|
2154
|
-
this.goal.lastPauseWasJudgeFailure = false;
|
|
2155
|
-
await this.saveToThread(state);
|
|
2156
|
-
return { continuation: null, judgeResult: null };
|
|
2157
|
-
}
|
|
2158
|
-
await this.saveToThread(state);
|
|
2159
|
-
return { continuation: this.buildContinuationPrompt("No response yet, keep working."), judgeResult: null };
|
|
2160
|
-
}
|
|
2161
|
-
const result = await this.callJudge(
|
|
2162
|
-
state,
|
|
2163
|
-
{
|
|
2164
|
-
lastUserContent: context.lastUserContent,
|
|
2165
|
-
assistantStepsSinceLastUser: context.assistantStepsSinceLastUser,
|
|
2166
|
-
lastAssistantContent: context.lastAssistantContent
|
|
2167
|
-
},
|
|
2168
|
-
options
|
|
2169
|
-
);
|
|
2170
|
-
if (!this.goal || this.goal.id !== evaluatedGoalId || this.goal.status !== "active") {
|
|
2171
|
-
return { continuation: null, judgeResult: null };
|
|
2172
|
-
}
|
|
2173
|
-
if (result.decision === "continue" || result.decision === "done") {
|
|
2174
|
-
this.goal.turnsUsed++;
|
|
2175
|
-
this.goal.lastPauseWasJudgeFailure = false;
|
|
2176
|
-
}
|
|
2177
|
-
if (result.decision === "paused") {
|
|
2178
|
-
this.stopActiveTimer();
|
|
2179
|
-
this.goal.status = "paused";
|
|
2180
|
-
this.goal.lastPauseWasJudgeFailure = isJudgeFailureReason(result.reason);
|
|
2181
|
-
await this.saveToThread(state);
|
|
2182
|
-
return { continuation: null, judgeResult: result };
|
|
2183
|
-
}
|
|
2184
|
-
if (result.decision === "done") {
|
|
2185
|
-
this.stopActiveTimer();
|
|
2186
|
-
this.goal.status = "done";
|
|
2187
|
-
await this.saveToThread(state);
|
|
2188
|
-
return { continuation: null, judgeResult: result };
|
|
2189
|
-
}
|
|
2190
|
-
if (result.decision === "waiting") {
|
|
2191
|
-
this.stopActiveTimer();
|
|
2192
|
-
await this.saveToThread(state);
|
|
2193
|
-
return { continuation: null, judgeResult: result };
|
|
2194
|
-
}
|
|
2195
|
-
if (this.goal.turnsUsed >= this.goal.maxTurns) {
|
|
2196
|
-
this.stopActiveTimer();
|
|
2197
|
-
this.goal.status = "paused";
|
|
2198
|
-
this.goal.lastPauseWasJudgeFailure = false;
|
|
2199
|
-
await this.saveToThread(state);
|
|
2200
|
-
return { continuation: null, judgeResult: result };
|
|
2201
|
-
}
|
|
2202
|
-
this.startActiveTimer();
|
|
2203
|
-
await this.saveToThread(state);
|
|
2204
|
-
return { continuation: this.buildContinuationPrompt(result.reason), judgeResult: result };
|
|
2205
|
-
}
|
|
2206
|
-
// ===========================================================================
|
|
2207
|
-
// Private
|
|
2208
|
-
// ===========================================================================
|
|
2209
|
-
async getRecentConversationContext(state) {
|
|
2210
|
-
try {
|
|
2211
|
-
const messages = await state.harness.listMessages();
|
|
2212
|
-
let lastUserIndex = -1;
|
|
2213
|
-
let lastAssistantContent = null;
|
|
2214
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2215
|
-
const msg = messages[i];
|
|
2216
|
-
if (!lastAssistantContent && msg.role === "assistant") {
|
|
2217
|
-
lastAssistantContent = this.extractTextContent(msg.content);
|
|
2218
|
-
}
|
|
2219
|
-
if (msg.role === "user") {
|
|
2220
|
-
lastUserIndex = i;
|
|
2221
|
-
break;
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
const lastUserContent = lastUserIndex >= 0 ? this.extractTextContent(messages[lastUserIndex].content) : null;
|
|
2225
|
-
const assistantStepsSinceLastUser = lastUserIndex >= 0 ? messages.slice(lastUserIndex + 1).filter((msg) => msg.role === "assistant").length : 0;
|
|
2226
|
-
return { lastUserContent, assistantStepsSinceLastUser, lastAssistantContent };
|
|
2227
|
-
} catch {
|
|
2228
|
-
return { lastUserContent: null, assistantStepsSinceLastUser: 0, lastAssistantContent: null };
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
extractTextContent(content) {
|
|
2232
|
-
if (typeof content === "string") return content;
|
|
2233
|
-
if (Array.isArray(content)) {
|
|
2234
|
-
return content.map((part) => {
|
|
2235
|
-
if (typeof part === "string") return part;
|
|
2236
|
-
if (typeof part?.text === "string") return part.text;
|
|
2237
|
-
if (typeof part?.content === "string") return part.content;
|
|
2238
|
-
return null;
|
|
2239
|
-
}).filter((text) => Boolean(text)).join("\n");
|
|
2240
|
-
}
|
|
2241
|
-
return String(content ?? "");
|
|
2242
|
-
}
|
|
2243
|
-
async callJudge(state, context, options) {
|
|
2244
|
-
try {
|
|
2245
|
-
const memory = await this.getJudgeMemory(state);
|
|
2246
|
-
const tools = await this.createJudgeTools(state);
|
|
2247
|
-
const judgeAgent = this.createJudgeAgent(memory, tools);
|
|
2248
|
-
if (!judgeAgent) {
|
|
2249
|
-
return { decision: "paused", reason: "Judge model could not be initialized." };
|
|
2250
|
-
}
|
|
2251
|
-
const recentUser = context.lastUserContent ? `
|
|
2252
|
-
|
|
2253
|
-
Latest user message:
|
|
2254
|
-
${truncateForJudge(context.lastUserContent)}
|
|
2255
|
-
|
|
2256
|
-
Assistant steps since that user message: ${context.assistantStepsSinceLastUser}` : "";
|
|
2257
|
-
const prompt = `Goal: ${this.goal.objective}${recentUser}
|
|
2258
|
-
|
|
2259
|
-
Latest assistant message:
|
|
2260
|
-
${context.lastAssistantContent}`;
|
|
2261
|
-
const memoryOpts = memory ? { memory: { thread: this.getJudgeThreadId(state), resource: state.harness.getResourceId() } } : {};
|
|
2262
|
-
const streamOpts = {
|
|
2263
|
-
...memoryOpts,
|
|
2264
|
-
abortSignal: options.abortSignal,
|
|
2265
|
-
maxSteps: JUDGE_MAX_STEPS,
|
|
2266
|
-
structuredOutput: {
|
|
2267
|
-
schema: judgeSchema,
|
|
2268
|
-
errorStrategy: "warn"
|
|
2269
|
-
}
|
|
2270
|
-
};
|
|
2271
|
-
const stream = await judgeAgent.stream(prompt, streamOpts);
|
|
2272
|
-
await this.consumeJudgeStream(stream, options.onActivity);
|
|
2273
|
-
const output = (await stream.getFullOutput()).object;
|
|
2274
|
-
if (output) {
|
|
2275
|
-
return { decision: output.decision, reason: output.reason };
|
|
2276
|
-
}
|
|
2277
|
-
if (options.abortSignal?.aborted) {
|
|
2278
|
-
return { decision: "paused", reason: "Judge evaluation was interrupted." };
|
|
2279
|
-
}
|
|
2280
|
-
options.onActivity?.("retrying (no structured decision)");
|
|
2281
|
-
const retryStream = await judgeAgent.stream(JUDGE_RETRY_PROMPT, streamOpts);
|
|
2282
|
-
await this.consumeJudgeStream(retryStream, options.onActivity);
|
|
2283
|
-
const retryOutput = (await retryStream.getFullOutput()).object;
|
|
2284
|
-
if (retryOutput) {
|
|
2285
|
-
return { decision: retryOutput.decision, reason: retryOutput.reason };
|
|
2286
|
-
}
|
|
2287
|
-
return { decision: "paused", reason: "Judge returned no structured decision." };
|
|
2288
|
-
} catch (error) {
|
|
2289
|
-
if (options.abortSignal?.aborted) {
|
|
2290
|
-
return { decision: "paused", reason: "Judge evaluation was interrupted." };
|
|
2291
|
-
}
|
|
2292
|
-
return { decision: "paused", reason: `Judge could not evaluate this turn: ${formatError(error)}` };
|
|
1754
|
+
async setGoal(state, objective, judgeModelId, maxTurns = DEFAULT_MAX_TURNS) {
|
|
1755
|
+
const threadId = state.harness.getCurrentThreadId();
|
|
1756
|
+
const agent = this.getAgent(state);
|
|
1757
|
+
const now = Date.now();
|
|
1758
|
+
const id = randomUUID();
|
|
1759
|
+
if (agent && threadId) {
|
|
1760
|
+
const persisted = await agent.setObjective(objective, {
|
|
1761
|
+
threadId,
|
|
1762
|
+
resourceId: state.harness.getResourceId(),
|
|
1763
|
+
...judgeModelId ? { judgeModelId } : {},
|
|
1764
|
+
maxRuns: maxTurns
|
|
1765
|
+
});
|
|
1766
|
+
this.record = persisted ? { ...persisted, id } : this.localRecord(objective, judgeModelId, maxTurns, now, id);
|
|
1767
|
+
} else {
|
|
1768
|
+
this.record = this.localRecord(objective, judgeModelId, maxTurns, now, id);
|
|
2293
1769
|
}
|
|
1770
|
+
this.activeStartedAt = new Date(now).toISOString();
|
|
1771
|
+
this.activeDurationMs = 0;
|
|
1772
|
+
return this.getGoal();
|
|
2294
1773
|
}
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
const
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
1774
|
+
/**
|
|
1775
|
+
* Update the judge model / max-runs defaults. Persists into the active record
|
|
1776
|
+
* (so the override is remembered in thread state) when a goal is set.
|
|
1777
|
+
*/
|
|
1778
|
+
async updateJudgeDefaults(state, judgeModelId, maxTurns) {
|
|
1779
|
+
if (!this.record) return null;
|
|
1780
|
+
const threadId = state.harness.getCurrentThreadId();
|
|
1781
|
+
const agent = this.getAgent(state);
|
|
1782
|
+
if (agent && threadId) {
|
|
1783
|
+
const updated = await agent.updateObjectiveOptions({
|
|
1784
|
+
threadId,
|
|
1785
|
+
...judgeModelId ? { judgeModelId } : {},
|
|
1786
|
+
maxRuns: maxTurns
|
|
1787
|
+
});
|
|
1788
|
+
if (updated) this.record = { ...updated, id: this.record.id };
|
|
1789
|
+
} else {
|
|
1790
|
+
this.record = {
|
|
1791
|
+
...this.record,
|
|
1792
|
+
...judgeModelId ? { judgeModelId } : {},
|
|
1793
|
+
maxRuns: maxTurns,
|
|
1794
|
+
updatedAt: Date.now()
|
|
1795
|
+
};
|
|
2314
1796
|
}
|
|
2315
|
-
return
|
|
1797
|
+
return this.getGoal();
|
|
2316
1798
|
}
|
|
2317
|
-
|
|
2318
|
-
if (
|
|
2319
|
-
|
|
2320
|
-
|
|
1799
|
+
pause() {
|
|
1800
|
+
if (this.record && this.record.status === "active") {
|
|
1801
|
+
this.stopActiveTimer();
|
|
1802
|
+
this.record = { ...this.record, status: "paused", updatedAt: Date.now() };
|
|
2321
1803
|
}
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
}
|
|
1804
|
+
return this.getGoal();
|
|
1805
|
+
}
|
|
1806
|
+
resume() {
|
|
1807
|
+
if (this.record && this.record.status === "paused") {
|
|
1808
|
+
this.record = { ...this.record, status: "active", updatedAt: Date.now() };
|
|
1809
|
+
this.startActiveTimer();
|
|
2329
1810
|
}
|
|
1811
|
+
return this.getGoal();
|
|
2330
1812
|
}
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
const threadId = this.getJudgeThreadId(state);
|
|
2336
|
-
const existing = await memory.getThreadById({ threadId });
|
|
2337
|
-
if (!existing) {
|
|
2338
|
-
await memory.createThread({
|
|
2339
|
-
threadId,
|
|
2340
|
-
resourceId: state.harness.getResourceId(),
|
|
2341
|
-
title: `Goal judge: ${this.goal.objective.slice(0, 80)}`,
|
|
2342
|
-
metadata: {
|
|
2343
|
-
forkedSubagent: true,
|
|
2344
|
-
goalJudge: true,
|
|
2345
|
-
parentThreadId: state.harness.getCurrentThreadId(),
|
|
2346
|
-
goalId: this.goal.id
|
|
2347
|
-
}
|
|
2348
|
-
});
|
|
1813
|
+
markDone() {
|
|
1814
|
+
if (this.record) {
|
|
1815
|
+
this.stopActiveTimer();
|
|
1816
|
+
this.record = { ...this.record, status: "done", updatedAt: Date.now() };
|
|
2349
1817
|
}
|
|
2350
|
-
return memory;
|
|
2351
1818
|
}
|
|
2352
|
-
|
|
2353
|
-
|
|
1819
|
+
clear() {
|
|
1820
|
+
this.record = null;
|
|
1821
|
+
this.activeStartedAt = null;
|
|
1822
|
+
this.activeDurationMs = 0;
|
|
1823
|
+
this.persistGoalOnNextThreadCreate = false;
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Sync the latest objective record from ThreadState into the in-memory view.
|
|
1827
|
+
* Called from the `goal` stream-chunk handler after each evaluation.
|
|
1828
|
+
*/
|
|
1829
|
+
applyEvaluation(update) {
|
|
1830
|
+
if (!this.record) return null;
|
|
1831
|
+
this.record = { ...this.record, runsUsed: update.runsUsed, status: update.status, updatedAt: Date.now() };
|
|
1832
|
+
if (update.status !== "active") this.stopActiveTimer();
|
|
1833
|
+
return this.getGoal();
|
|
2354
1834
|
}
|
|
2355
|
-
|
|
2356
|
-
|
|
1835
|
+
// ---------------------------------------------------------------------------
|
|
1836
|
+
// Persistence
|
|
1837
|
+
// ---------------------------------------------------------------------------
|
|
1838
|
+
/**
|
|
1839
|
+
* Persist the active objective to ThreadState via the agent. The objective
|
|
1840
|
+
* record is the source of truth; the legacy thread-metadata key is cleared so
|
|
1841
|
+
* stale state from older sessions does not resurface.
|
|
1842
|
+
*/
|
|
1843
|
+
async saveToThread(state) {
|
|
1844
|
+
const threadId = state.harness.getCurrentThreadId();
|
|
1845
|
+
const agent = this.getAgent(state);
|
|
2357
1846
|
try {
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
1847
|
+
if (agent && threadId) {
|
|
1848
|
+
if (this.record) {
|
|
1849
|
+
const updated = await agent.updateObjectiveOptions({
|
|
1850
|
+
threadId,
|
|
1851
|
+
status: this.record.status,
|
|
1852
|
+
...this.record.judgeModelId ? { judgeModelId: this.record.judgeModelId } : {},
|
|
1853
|
+
...this.record.maxRuns !== void 0 ? { maxRuns: this.record.maxRuns } : {}
|
|
1854
|
+
});
|
|
1855
|
+
if (!updated) {
|
|
1856
|
+
const desiredStatus = this.record.status;
|
|
1857
|
+
await agent.setObjective(this.record.objective, {
|
|
1858
|
+
threadId,
|
|
1859
|
+
resourceId: state.harness.getResourceId(),
|
|
1860
|
+
...this.record.judgeModelId ? { judgeModelId: this.record.judgeModelId } : {},
|
|
1861
|
+
...this.record.maxRuns !== void 0 ? { maxRuns: this.record.maxRuns } : {}
|
|
1862
|
+
});
|
|
1863
|
+
if (desiredStatus !== "active") {
|
|
1864
|
+
await agent.updateObjectiveOptions({ threadId, status: desiredStatus });
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
} else {
|
|
1868
|
+
await agent.clearObjective({ threadId });
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
await state.harness.setThreadSetting({ key: THREAD_GOAL_KEY, value: void 0 });
|
|
2369
1872
|
} catch {
|
|
2370
|
-
return null;
|
|
2371
1873
|
}
|
|
2372
1874
|
}
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
1875
|
+
/**
|
|
1876
|
+
* Load the objective from ThreadState (called on thread switch). Falls back to
|
|
1877
|
+
* the legacy thread-metadata goal for threads created before this migration.
|
|
1878
|
+
*/
|
|
1879
|
+
async loadFromThread(state) {
|
|
1880
|
+
this.persistGoalOnNextThreadCreate = false;
|
|
1881
|
+
this.activeStartedAt = null;
|
|
1882
|
+
this.activeDurationMs = 0;
|
|
1883
|
+
const threadId = state.harness.getCurrentThreadId();
|
|
1884
|
+
const agent = this.getAgent(state);
|
|
1885
|
+
if (agent && threadId) {
|
|
1886
|
+
try {
|
|
1887
|
+
const record = await agent.getObjective({ threadId });
|
|
1888
|
+
if (record) {
|
|
1889
|
+
this.record = { ...record, id: randomUUID() };
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
} catch {
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
this.record = null;
|
|
2379
1896
|
}
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
1897
|
+
/**
|
|
1898
|
+
* Legacy entry point retained for thread-switch call sites that only have the
|
|
1899
|
+
* thread metadata available. Hydrates from a previously-persisted GoalState.
|
|
1900
|
+
*/
|
|
1901
|
+
loadFromThreadMetadata(metadata) {
|
|
1902
|
+
const saved = metadata?.[THREAD_GOAL_KEY];
|
|
1903
|
+
this.persistGoalOnNextThreadCreate = false;
|
|
1904
|
+
this.activeStartedAt = null;
|
|
1905
|
+
this.activeDurationMs = 0;
|
|
1906
|
+
if (saved && saved.objective && saved.status) {
|
|
1907
|
+
this.record = {
|
|
1908
|
+
objective: saved.objective,
|
|
1909
|
+
status: saved.status,
|
|
1910
|
+
runsUsed: saved.turnsUsed ?? 0,
|
|
1911
|
+
maxRuns: saved.maxTurns ?? DEFAULT_MAX_TURNS,
|
|
1912
|
+
judgeModelId: saved.judgeModelId ?? "",
|
|
1913
|
+
startedAt: saved.startedAt ? Date.parse(saved.startedAt) || Date.now() : Date.now(),
|
|
1914
|
+
updatedAt: Date.now(),
|
|
1915
|
+
id: saved.id ?? randomUUID()
|
|
1916
|
+
};
|
|
1917
|
+
this.activeDurationMs = saved.activeDurationMs ?? 0;
|
|
1918
|
+
} else {
|
|
1919
|
+
this.record = null;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
// ---------------------------------------------------------------------------
|
|
1923
|
+
// Private
|
|
1924
|
+
// ---------------------------------------------------------------------------
|
|
1925
|
+
getAgent(state) {
|
|
2392
1926
|
try {
|
|
2393
|
-
return
|
|
1927
|
+
return state.harness.getCurrentAgent();
|
|
2394
1928
|
} catch {
|
|
2395
|
-
return
|
|
1929
|
+
return void 0;
|
|
2396
1930
|
}
|
|
2397
1931
|
}
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
if (toolName === MC_TOOLS.LSP_INSPECT) return `inspect ${formatActivityValue(input.path)}`;
|
|
2406
|
-
return null;
|
|
2407
|
-
}
|
|
2408
|
-
function formatActivityValue(value) {
|
|
2409
|
-
if (typeof value === "string" && value.length > 0) {
|
|
2410
|
-
return value.length > 80 ? value.slice(0, 77) + "..." : value;
|
|
1932
|
+
/** Resolve effective judge model + max runs (record value → settings default). */
|
|
1933
|
+
effectiveSettings(record) {
|
|
1934
|
+
const settings = loadSettings();
|
|
1935
|
+
return {
|
|
1936
|
+
judgeModelId: record.judgeModelId ?? settings.models.goalJudgeModel ?? "",
|
|
1937
|
+
maxTurns: record.maxRuns ?? settings.models.goalMaxTurns ?? DEFAULT_MAX_TURNS
|
|
1938
|
+
};
|
|
2411
1939
|
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
"was interrupted"
|
|
2426
|
-
];
|
|
2427
|
-
function isJudgeFailureReason(reason) {
|
|
2428
|
-
const lower = reason.toLowerCase();
|
|
2429
|
-
return JUDGE_FAILURE_PATTERNS.some((p) => lower.includes(p));
|
|
2430
|
-
}
|
|
1940
|
+
localRecord(objective, judgeModelId, maxTurns, now, id) {
|
|
1941
|
+
return {
|
|
1942
|
+
objective,
|
|
1943
|
+
status: "active",
|
|
1944
|
+
runsUsed: 0,
|
|
1945
|
+
maxRuns: maxTurns,
|
|
1946
|
+
...judgeModelId ? { judgeModelId } : {},
|
|
1947
|
+
startedAt: now,
|
|
1948
|
+
updatedAt: now,
|
|
1949
|
+
id
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
2431
1953
|
function parseSizeValue(value, total) {
|
|
2432
1954
|
if (typeof value === "number") return value;
|
|
2433
1955
|
const match = value?.match(/^(\d+(?:\.\d+)?)%$/);
|
|
@@ -2647,14 +2169,8 @@ async function handleGoalCommand(ctx, args) {
|
|
|
2647
2169
|
ctx.showInfo("Goal is already done. Use /goal <text> to set a new goal.");
|
|
2648
2170
|
return;
|
|
2649
2171
|
}
|
|
2650
|
-
const wasJudgeFailure = goal.lastPauseWasJudgeFailure;
|
|
2651
2172
|
goalManager.resume();
|
|
2652
2173
|
await goalManager.saveToThread(state);
|
|
2653
|
-
if (wasJudgeFailure) {
|
|
2654
|
-
ctx.showInfo(`Goal resumed: "${goal.objective}" \u2014 retriggering judge evaluation...`);
|
|
2655
|
-
triggerGoalJudge(ctx, { requireAssistantMessage: true });
|
|
2656
|
-
return;
|
|
2657
|
-
}
|
|
2658
2174
|
ctx.showInfo(
|
|
2659
2175
|
`Goal resumed: "${goal.objective}" \u2014 ${goal.turnsUsed}/${goal.maxTurns} turns used. Sending continuation...`
|
|
2660
2176
|
);
|
|
@@ -2676,6 +2192,10 @@ async function handleGoalCommand(ctx, args) {
|
|
|
2676
2192
|
ctx.showInfo("Goal cleared.");
|
|
2677
2193
|
return;
|
|
2678
2194
|
}
|
|
2195
|
+
if (subCommand === "judge") {
|
|
2196
|
+
await handleJudgeCommand(ctx);
|
|
2197
|
+
return;
|
|
2198
|
+
}
|
|
2679
2199
|
const objective = args.join(" ");
|
|
2680
2200
|
await startGoalWithDefaults(ctx, objective);
|
|
2681
2201
|
}
|
|
@@ -2746,9 +2266,12 @@ async function showGoalActionModal(ctx) {
|
|
|
2746
2266
|
async function handleJudgeCommand(ctx) {
|
|
2747
2267
|
const defaults = await promptForJudgeDefaults(ctx, "Judge settings unchanged.");
|
|
2748
2268
|
if (!defaults) return;
|
|
2749
|
-
const activeGoal = ctx.state.goalManager.updateJudgeDefaults(
|
|
2269
|
+
const activeGoal = await ctx.state.goalManager.updateJudgeDefaults(
|
|
2270
|
+
ctx.state,
|
|
2271
|
+
defaults.judgeModelId,
|
|
2272
|
+
defaults.maxTurns
|
|
2273
|
+
);
|
|
2750
2274
|
if (activeGoal) {
|
|
2751
|
-
await ctx.state.goalManager.saveToThread(ctx.state);
|
|
2752
2275
|
ctx.showInfo(
|
|
2753
2276
|
`Judge defaults set: ${defaults.judgeModelId}, ${defaults.maxTurns} max attempts. Current goal updated.`
|
|
2754
2277
|
);
|
|
@@ -2825,105 +2348,6 @@ async function promptForJudgeDefaults(ctx, cancelMessage) {
|
|
|
2825
2348
|
selector.focused = true;
|
|
2826
2349
|
});
|
|
2827
2350
|
}
|
|
2828
|
-
function triggerGoalJudge(ctx, options = {}) {
|
|
2829
|
-
const { state } = ctx;
|
|
2830
|
-
const goal = state.goalManager.getGoal();
|
|
2831
|
-
if (!goal) return;
|
|
2832
|
-
const evaluatedGoalId = goal.id;
|
|
2833
|
-
if (!state.gradientAnimator) {
|
|
2834
|
-
state.gradientAnimator = new GradientAnimator(() => {
|
|
2835
|
-
ctx.updateStatusLine();
|
|
2836
|
-
});
|
|
2837
|
-
}
|
|
2838
|
-
const abortController = new AbortController();
|
|
2839
|
-
const judgeComponent = new JudgeDisplayComponent(null, goal.turnsUsed, goal.maxTurns);
|
|
2840
|
-
const activeGoalJudge = { modelId: goal.judgeModelId, abortController, component: judgeComponent };
|
|
2841
|
-
state.activeGoalJudge = activeGoalJudge;
|
|
2842
|
-
state.chatContainer.addChild(judgeComponent);
|
|
2843
|
-
state.gradientAnimator.start();
|
|
2844
|
-
ctx.updateStatusLine();
|
|
2845
|
-
state.ui.requestRender();
|
|
2846
|
-
state.goalManager.evaluateAfterTurn(state, {
|
|
2847
|
-
abortSignal: abortController.signal,
|
|
2848
|
-
requireAssistantMessage: options.requireAssistantMessage,
|
|
2849
|
-
onActivity: (line) => {
|
|
2850
|
-
if (state.activeGoalJudge === activeGoalJudge) {
|
|
2851
|
-
judgeComponent.addActivity(line);
|
|
2852
|
-
state.ui.requestRender();
|
|
2853
|
-
}
|
|
2854
|
-
}
|
|
2855
|
-
}).then(async ({ continuation, judgeResult }) => {
|
|
2856
|
-
if (state.activeGoalJudge !== activeGoalJudge) return;
|
|
2857
|
-
const currentGoal = state.goalManager.getGoal();
|
|
2858
|
-
if (!currentGoal || currentGoal.id !== evaluatedGoalId) return;
|
|
2859
|
-
if (judgeResult) {
|
|
2860
|
-
judgeComponent.setResult(judgeResult, currentGoal.turnsUsed, currentGoal.maxTurns);
|
|
2861
|
-
state.ui.requestRender();
|
|
2862
|
-
}
|
|
2863
|
-
if (abortController.signal.aborted) {
|
|
2864
|
-
state.userInitiatedAbort = false;
|
|
2865
|
-
return;
|
|
2866
|
-
}
|
|
2867
|
-
if (continuation) {
|
|
2868
|
-
if (currentGoal.status !== "active") return;
|
|
2869
|
-
try {
|
|
2870
|
-
await state.harness.sendSignal({
|
|
2871
|
-
type: "system-reminder",
|
|
2872
|
-
contents: continuation,
|
|
2873
|
-
attributes: { type: "goal-judge" },
|
|
2874
|
-
metadata: {
|
|
2875
|
-
goalId: currentGoal.id,
|
|
2876
|
-
turnsUsed: currentGoal.turnsUsed,
|
|
2877
|
-
maxTurns: currentGoal.maxTurns,
|
|
2878
|
-
judgeModelId: currentGoal.judgeModelId
|
|
2879
|
-
}
|
|
2880
|
-
}).accepted;
|
|
2881
|
-
} catch (error) {
|
|
2882
|
-
state.goalManager.pause();
|
|
2883
|
-
await state.goalManager.saveToThread(state);
|
|
2884
|
-
ctx.showError(`Failed to send goal continuation: ${error instanceof Error ? error.message : String(error)}`);
|
|
2885
|
-
}
|
|
2886
|
-
} else {
|
|
2887
|
-
if (judgeResult) {
|
|
2888
|
-
const harness = state.harness;
|
|
2889
|
-
try {
|
|
2890
|
-
await harness.saveSystemReminderMessage?.({
|
|
2891
|
-
reminderType: "goal-judge",
|
|
2892
|
-
message: `${judgeResult.decision} (${currentGoal.turnsUsed}/${currentGoal.maxTurns})
|
|
2893
|
-
${judgeResult.reason}`
|
|
2894
|
-
});
|
|
2895
|
-
} catch (error) {
|
|
2896
|
-
ctx.showError(
|
|
2897
|
-
`Failed to persist goal judge result: ${error instanceof Error ? error.message : String(error)}`
|
|
2898
|
-
);
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
if (currentGoal.status === "paused") {
|
|
2902
|
-
ctx.showInfo(
|
|
2903
|
-
`Goal paused (attempt ${currentGoal.turnsUsed}/${currentGoal.maxTurns}). Use /goal resume to continue.`
|
|
2904
|
-
);
|
|
2905
|
-
}
|
|
2906
|
-
if (judgeResult?.decision === "done" && currentGoal.id === state.planStartedGoalId) {
|
|
2907
|
-
const goalId = state.planStartedGoalId;
|
|
2908
|
-
state.planStartedGoalId = void 0;
|
|
2909
|
-
try {
|
|
2910
|
-
await state.harness.switchMode({ modeId: "plan" });
|
|
2911
|
-
} catch (error) {
|
|
2912
|
-
ctx.showError(`Failed to switch to Plan mode: ${error instanceof Error ? error.message : String(error)}`);
|
|
2913
|
-
state.planStartedGoalId = goalId;
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
}
|
|
2917
|
-
}).catch(() => {
|
|
2918
|
-
}).finally(() => {
|
|
2919
|
-
if (state.activeGoalJudge === activeGoalJudge) {
|
|
2920
|
-
state.activeGoalJudge = void 0;
|
|
2921
|
-
}
|
|
2922
|
-
state.gradientAnimator?.fadeOut();
|
|
2923
|
-
ctx.updateStatusLine();
|
|
2924
|
-
state.ui.requestRender();
|
|
2925
|
-
});
|
|
2926
|
-
}
|
|
2927
2351
|
async function startGoal(ctx, objective, judgeModelId, maxTurns, options = {}) {
|
|
2928
2352
|
const { state } = ctx;
|
|
2929
2353
|
const goalManager = state.goalManager;
|
|
@@ -2932,11 +2356,14 @@ async function startGoal(ctx, objective, judgeModelId, maxTurns, options = {}) {
|
|
|
2932
2356
|
state.pendingNewThread = false;
|
|
2933
2357
|
}
|
|
2934
2358
|
const shouldPersistToCreatedThread = !state.harness.getCurrentThreadId();
|
|
2935
|
-
const goal = goalManager.setGoal(objective, judgeModelId, maxTurns);
|
|
2359
|
+
const goal = await goalManager.setGoal(state, objective, judgeModelId, maxTurns);
|
|
2360
|
+
if (!goal) {
|
|
2361
|
+
ctx.showError("Failed to set goal.");
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2936
2364
|
state.planStartedGoalId = void 0;
|
|
2937
2365
|
if (options.trigger === "none") {
|
|
2938
|
-
|
|
2939
|
-
goal.activeDurationMs = 0;
|
|
2366
|
+
goalManager.resetActiveTimer();
|
|
2940
2367
|
}
|
|
2941
2368
|
if (shouldPersistToCreatedThread) {
|
|
2942
2369
|
goalManager.persistOnNextThreadCreate();
|
|
@@ -3000,7 +2427,7 @@ function getCommands(modes) {
|
|
|
3000
2427
|
{ key: "/observability", description: "Configure cloud observability" },
|
|
3001
2428
|
{ key: "/github", description: "Subscribe/sync GitHub PR signals" },
|
|
3002
2429
|
{ key: "/goal", description: "Set/manage persistent goal (Ralph loop)" },
|
|
3003
|
-
{ key: "/judge", description: "Set goal judge
|
|
2430
|
+
{ key: "/goal judge", description: "Set the goal judge model and max attempts" }
|
|
3004
2431
|
];
|
|
3005
2432
|
if (modes > 1) {
|
|
3006
2433
|
cmds.push({ key: "/mode", description: "Switch or list modes" });
|
|
@@ -3563,7 +2990,7 @@ var McpSelectorComponent = class extends Box {
|
|
|
3563
2990
|
this.startPollingIfNeeded();
|
|
3564
2991
|
}
|
|
3565
2992
|
buildUI() {
|
|
3566
|
-
const titleText =
|
|
2993
|
+
const titleText = chalk12.bgHex("#16c858").white.bold(" Manage MCP servers ");
|
|
3567
2994
|
this.addChild(new Text(titleText, 0, 0));
|
|
3568
2995
|
this.addChild(new Spacer(1));
|
|
3569
2996
|
this.listContainer = new Container();
|
|
@@ -4102,20 +3529,30 @@ function reasonToMessage(reason) {
|
|
|
4102
3529
|
}
|
|
4103
3530
|
|
|
4104
3531
|
// src/tui/display.ts
|
|
3532
|
+
var InfoMessageComponent = class extends Container {
|
|
3533
|
+
constructor(lines) {
|
|
3534
|
+
super();
|
|
3535
|
+
for (const line of lines) {
|
|
3536
|
+
this.addChild(line);
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
getChatSpacingKind() {
|
|
3540
|
+
return "system";
|
|
3541
|
+
}
|
|
3542
|
+
};
|
|
4105
3543
|
function showError(state, message) {
|
|
4106
|
-
|
|
4107
|
-
state.chatContainer
|
|
3544
|
+
const component = new InfoMessageComponent([new Text(theme.fg("error", `Error: ${message}`), 1, 0)]);
|
|
3545
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, component);
|
|
4108
3546
|
state.ui.requestRender();
|
|
4109
3547
|
}
|
|
4110
3548
|
function showInfo(state, message) {
|
|
4111
|
-
|
|
4112
|
-
state.chatContainer
|
|
3549
|
+
const component = new InfoMessageComponent([new Text(theme.fg("muted", message), 1, 0)]);
|
|
3550
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, component);
|
|
4113
3551
|
state.ui.requestRender();
|
|
4114
3552
|
}
|
|
4115
3553
|
function showFormattedError(state, event) {
|
|
4116
3554
|
const error = "error" in event ? event.error : event;
|
|
4117
3555
|
const parsed = parseError(error);
|
|
4118
|
-
state.chatContainer.addChild(new Spacer(1));
|
|
4119
3556
|
let errorText = `Error: ${parsed.message}`;
|
|
4120
3557
|
if (parsed.detail && parsed.detail !== parsed.message) {
|
|
4121
3558
|
errorText += theme.fg("muted", ` (${parsed.detail})`);
|
|
@@ -4129,11 +3566,13 @@ function showFormattedError(state, event) {
|
|
|
4129
3566
|
const seconds = Math.ceil(retryDelay / 1e3);
|
|
4130
3567
|
errorText += theme.fg("muted", ` (retry in ${seconds}s)`);
|
|
4131
3568
|
}
|
|
4132
|
-
|
|
3569
|
+
const lines = [new Text(theme.fg("error", errorText), 1, 0)];
|
|
4133
3570
|
const hint = getErrorHint(parsed.type);
|
|
4134
3571
|
if (hint) {
|
|
4135
|
-
|
|
3572
|
+
lines.push(new Text(theme.fg("muted", ` Hint: ${hint}`), 1, 0));
|
|
4136
3573
|
}
|
|
3574
|
+
const component = new InfoMessageComponent(lines);
|
|
3575
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, component);
|
|
4137
3576
|
state.ui.requestRender();
|
|
4138
3577
|
}
|
|
4139
3578
|
function getErrorHint(errorType) {
|
|
@@ -4294,7 +3733,8 @@ function showTextStatus(ctx) {
|
|
|
4294
3733
|
|
|
4295
3734
|
// src/tui/commands/mode.ts
|
|
4296
3735
|
function applyCurrentModeColorToRenderedTools(ctx) {
|
|
4297
|
-
const
|
|
3736
|
+
const color = ctx.harness.getCurrentMode?.()?.metadata?.color;
|
|
3737
|
+
const modeColor = typeof color === "string" ? color : void 0;
|
|
4298
3738
|
for (const tool of ctx.state.allToolComponents) {
|
|
4299
3739
|
tool.setCompactToolModeColor?.(modeColor);
|
|
4300
3740
|
}
|
|
@@ -4315,7 +3755,7 @@ async function handleModeCommand(ctx, args) {
|
|
|
4315
3755
|
}
|
|
4316
3756
|
} else {
|
|
4317
3757
|
const currentMode = ctx.harness.getCurrentMode();
|
|
4318
|
-
const modeList = modes.map((m) => ` ${m.id === currentMode?.id ? "* " : " "}${m.
|
|
3758
|
+
const modeList = modes.map((m) => ` ${m.id === currentMode?.id ? "* " : " "}${m.name}${m.description ? ` - ${m.description}` : ""}`).join("\n");
|
|
4319
3759
|
ctx.showInfo(`Modes:
|
|
4320
3760
|
${modeList}`);
|
|
4321
3761
|
}
|
|
@@ -4342,10 +3782,10 @@ var SlashCommandComponent = class extends Container {
|
|
|
4342
3782
|
}
|
|
4343
3783
|
rebuild() {
|
|
4344
3784
|
this.clear();
|
|
4345
|
-
const border = (char) =>
|
|
3785
|
+
const border = (char) => chalk12.bold.hex(getBorderColor())(char);
|
|
4346
3786
|
const termWidth = getTermWidth();
|
|
4347
3787
|
const maxLineWidth = termWidth - 6 - BOX_INDENT * 2;
|
|
4348
|
-
const heading =
|
|
3788
|
+
const heading = chalk12.hex(mastra.specialGray)(`/${this.commandName}`);
|
|
4349
3789
|
if (this.contentLines.length === 0) {
|
|
4350
3790
|
this.addChild(new Text(`${border("\u2570\u2500\u2500")} ${heading}`, BOX_INDENT, 0));
|
|
4351
3791
|
return;
|
|
@@ -4369,17 +3809,19 @@ var SlashCommandComponent = class extends Container {
|
|
|
4369
3809
|
const truncated = !this.expanded && wrappedLines.length > MAX_COLLAPSED_LINES + 1;
|
|
4370
3810
|
const displayLines = truncated ? wrappedLines.slice(0, MAX_COLLAPSED_LINES) : wrappedLines;
|
|
4371
3811
|
const contentText = displayLines.map(
|
|
4372
|
-
(line) => `${border("\u2502")} ${
|
|
3812
|
+
(line) => `${border("\u2502")} ${chalk12.hex(mastra.mainGray)(line.length > maxLineWidth ? line.slice(0, maxLineWidth - 1) + "\u2026" : line)}`
|
|
4373
3813
|
).join("\n");
|
|
4374
3814
|
this.addChild(new Text(contentText, BOX_INDENT, 0));
|
|
4375
3815
|
if (truncated) {
|
|
4376
|
-
const moreText =
|
|
3816
|
+
const moreText = chalk12.hex(mastra.darkGray)(
|
|
4377
3817
|
`... ${wrappedLines.length - MAX_COLLAPSED_LINES} more lines (ctrl+e to expand)`
|
|
4378
3818
|
);
|
|
4379
3819
|
this.addChild(new Text(`${border("\u2502")} ${moreText}`, BOX_INDENT, 0));
|
|
4380
3820
|
}
|
|
4381
3821
|
this.addChild(new Text(`${border("\u2570\u2500\u2500")} ${heading}`, BOX_INDENT, 0));
|
|
4382
|
-
|
|
3822
|
+
}
|
|
3823
|
+
getChatSpacingKind() {
|
|
3824
|
+
return "other";
|
|
4383
3825
|
}
|
|
4384
3826
|
};
|
|
4385
3827
|
var _compId = 0;
|
|
@@ -4472,7 +3914,7 @@ var AssistantMessageComponent = class extends Container {
|
|
|
4472
3914
|
var NotificationSummaryComponent = class extends Container {
|
|
4473
3915
|
constructor(options) {
|
|
4474
3916
|
super();
|
|
4475
|
-
const title =
|
|
3917
|
+
const title = chalk12.hex(mastra.orange).bold(`Notification summary: ${options.pending} pending`);
|
|
4476
3918
|
this.addChild(new Text(title, BOX_INDENT, 0));
|
|
4477
3919
|
const sourceSummary = Object.entries(options.bySource).sort(([a], [b]) => a.localeCompare(b)).map(([source, count]) => `${source}: ${count}`).join(", ");
|
|
4478
3920
|
const message = sourceSummary || options.message.trim();
|
|
@@ -4482,7 +3924,6 @@ var NotificationSummaryComponent = class extends Container {
|
|
|
4482
3924
|
this.addChild(
|
|
4483
3925
|
new Text(theme.fg("dim", "Use notification_inbox to inspect pending notifications."), BOX_INDENT + 2, 0)
|
|
4484
3926
|
);
|
|
4485
|
-
this.addChild(new Spacer(1));
|
|
4486
3927
|
}
|
|
4487
3928
|
getChatSpacingKind() {
|
|
4488
3929
|
return "system";
|
|
@@ -4552,14 +3993,14 @@ var NotificationComponent = class extends Container {
|
|
|
4552
3993
|
const messageLines = message ? wrapText(message, maxContentWidth) : [];
|
|
4553
3994
|
const allLines = [...titleLines, ...detailLines, ...messageLines];
|
|
4554
3995
|
const contentWidth = Math.max(...allLines.map((line) => visibleWidth(line)), 1);
|
|
4555
|
-
const borderColor =
|
|
3996
|
+
const borderColor = chalk12.hex(mastra.blue);
|
|
4556
3997
|
const top = `\u256D${"\u2500".repeat(contentWidth + 2)}\u256E`;
|
|
4557
3998
|
const bottom = `\u2570${"\u2500".repeat(contentWidth + 2)}\u256F`;
|
|
4558
3999
|
this.addChild(new Text(borderColor(top), BOX_INDENT, 0));
|
|
4559
4000
|
for (const line of titleLines) {
|
|
4560
4001
|
this.addChild(
|
|
4561
4002
|
new Text(
|
|
4562
|
-
`${borderColor("\u2502")} ${
|
|
4003
|
+
`${borderColor("\u2502")} ${chalk12.hex(priorityColor(options.priority)).bold(padLine(line, contentWidth))} ${borderColor("\u2502")}`,
|
|
4563
4004
|
BOX_INDENT,
|
|
4564
4005
|
0
|
|
4565
4006
|
)
|
|
@@ -4578,7 +4019,6 @@ var NotificationComponent = class extends Container {
|
|
|
4578
4019
|
this.addChild(new Text(`${borderColor("\u2502")} ${padLine(line, contentWidth)} ${borderColor("\u2502")}`, BOX_INDENT, 0));
|
|
4579
4020
|
}
|
|
4580
4021
|
this.addChild(new Text(borderColor(bottom), BOX_INDENT, 0));
|
|
4581
|
-
this.addChild(new Spacer(1));
|
|
4582
4022
|
}
|
|
4583
4023
|
getChatSpacingKind() {
|
|
4584
4024
|
return "system";
|
|
@@ -4606,7 +4046,6 @@ var OMMarkerComponent = class extends Container {
|
|
|
4606
4046
|
super();
|
|
4607
4047
|
this.textChild = new Text(formatMarker(data), BOX_INDENT, 0);
|
|
4608
4048
|
this.addChild(this.textChild);
|
|
4609
|
-
this.addChild(new Spacer(1));
|
|
4610
4049
|
}
|
|
4611
4050
|
/**
|
|
4612
4051
|
* Update the marker in-place (e.g., from start → end).
|
|
@@ -4614,6 +4053,9 @@ var OMMarkerComponent = class extends Container {
|
|
|
4614
4053
|
update(data) {
|
|
4615
4054
|
this.textChild.setText(formatMarker(data));
|
|
4616
4055
|
}
|
|
4056
|
+
getChatSpacingKind() {
|
|
4057
|
+
return "other";
|
|
4058
|
+
}
|
|
4617
4059
|
};
|
|
4618
4060
|
function formatMarker(data) {
|
|
4619
4061
|
const isReflection = "operationType" in data && data.operationType === "reflection";
|
|
@@ -4758,7 +4200,7 @@ var OMOutputComponent = class extends Container {
|
|
|
4758
4200
|
this.clear();
|
|
4759
4201
|
const isReflection = this.data.type === "reflection";
|
|
4760
4202
|
const color = isReflection ? getReflectorColor() : getObserverColor();
|
|
4761
|
-
const border = (char) =>
|
|
4203
|
+
const border = (char) => chalk12.bold.hex(color)(char);
|
|
4762
4204
|
const termWidth = getTermWidth();
|
|
4763
4205
|
const maxLineWidth = termWidth - 6 - BOX_INDENT * 2;
|
|
4764
4206
|
const originalLines = this.data.observations.split("\n");
|
|
@@ -4790,22 +4232,22 @@ var OMOutputComponent = class extends Container {
|
|
|
4790
4232
|
truncated = hiddenGroups > 0;
|
|
4791
4233
|
if (truncated) {
|
|
4792
4234
|
for (const line of headLines) {
|
|
4793
|
-
borderedLines.push(border("\u2502") + " " +
|
|
4235
|
+
borderedLines.push(border("\u2502") + " " + chalk12.hex(mastra.specialGray)(line));
|
|
4794
4236
|
}
|
|
4795
4237
|
borderedLines.push(
|
|
4796
|
-
border("\u2502") + " " +
|
|
4238
|
+
border("\u2502") + " " + chalk12.hex(mastra.mainGray)(`... ${originalLineCount} lines total (ctrl+e to expand)`)
|
|
4797
4239
|
);
|
|
4798
4240
|
for (const line of tailLines) {
|
|
4799
|
-
borderedLines.push(border("\u2502") + " " +
|
|
4241
|
+
borderedLines.push(border("\u2502") + " " + chalk12.hex(mastra.specialGray)(line));
|
|
4800
4242
|
}
|
|
4801
4243
|
} else {
|
|
4802
4244
|
for (const line of wrappedLines) {
|
|
4803
|
-
borderedLines.push(border("\u2502") + " " +
|
|
4245
|
+
borderedLines.push(border("\u2502") + " " + chalk12.hex(mastra.specialGray)(line));
|
|
4804
4246
|
}
|
|
4805
4247
|
}
|
|
4806
4248
|
} else {
|
|
4807
4249
|
for (const line of wrappedLines) {
|
|
4808
|
-
borderedLines.push(border("\u2502") + " " +
|
|
4250
|
+
borderedLines.push(border("\u2502") + " " + chalk12.hex(mastra.specialGray)(line));
|
|
4809
4251
|
}
|
|
4810
4252
|
}
|
|
4811
4253
|
const displayOutput = borderedLines.join("\n");
|
|
@@ -4813,15 +4255,14 @@ var OMOutputComponent = class extends Container {
|
|
|
4813
4255
|
this.addChild(new Text(displayOutput, BOX_INDENT, 0));
|
|
4814
4256
|
}
|
|
4815
4257
|
if (this.data.currentTask && (this.expanded || !truncated)) {
|
|
4816
|
-
const taskLine = border("\u2502") + " " +
|
|
4258
|
+
const taskLine = border("\u2502") + " " + chalk12.hex(color).bold("Current task: ") + chalk12.hex(mastra.specialGray)(this.data.currentTask);
|
|
4817
4259
|
this.addChild(new Text(truncateAnsi(taskLine, termWidth - 2 - BOX_INDENT * 2), BOX_INDENT, 0));
|
|
4818
4260
|
}
|
|
4819
4261
|
if (this.data.suggestedResponse && (this.expanded || !truncated)) {
|
|
4820
|
-
const sugLine = border("\u2502") + " " +
|
|
4262
|
+
const sugLine = border("\u2502") + " " + chalk12.hex(color).bold("Suggested response: ") + chalk12.hex(mastra.specialGray)(this.data.suggestedResponse);
|
|
4821
4263
|
this.addChild(new Text(truncateAnsi(sugLine, termWidth - 2 - BOX_INDENT * 2), BOX_INDENT, 0));
|
|
4822
4264
|
}
|
|
4823
4265
|
this.addChild(new Text(`${border("\u2570\u2500\u2500")} ${footerText}`, BOX_INDENT, 0));
|
|
4824
|
-
this.addChild(new Spacer(1));
|
|
4825
4266
|
}
|
|
4826
4267
|
buildFooterText(color) {
|
|
4827
4268
|
const isReflection = this.data.type === "reflection";
|
|
@@ -4832,16 +4273,19 @@ var OMOutputComponent = class extends Container {
|
|
|
4832
4273
|
const ratio = (this.data.tokensObserved ?? 0) > 0 && (this.data.compressedTokens ?? this.data.observationTokens ?? 0) > 0 ? `${Math.round((this.data.tokensObserved ?? 0) / (this.data.compressedTokens ?? this.data.observationTokens ?? 1))}x` : "";
|
|
4833
4274
|
const durationStr = this.data.durationMs ? ` in ${(this.data.durationMs / 1e3).toFixed(1)}s` : "";
|
|
4834
4275
|
const ratioStr = ratio ? ` (${ratio} compression)` : "";
|
|
4835
|
-
return `${emoji} ${
|
|
4276
|
+
return `${emoji} ${chalk12.hex(color)(`Reflected: ${observed} \u2192 ${compressed} tokens${ratioStr}${durationStr}`)} ${chalk12.hex(mastra.green)("\u2713")}`;
|
|
4836
4277
|
} else {
|
|
4837
4278
|
const observed = formatTokens2(this.data.tokensObserved ?? 0);
|
|
4838
4279
|
const compressed = formatTokens2(this.data.observationTokens ?? 0);
|
|
4839
4280
|
const ratio = (this.data.tokensObserved ?? 0) > 0 && (this.data.observationTokens ?? 0) > 0 ? `${Math.round((this.data.tokensObserved ?? 0) / (this.data.observationTokens ?? 1))}x` : "";
|
|
4840
4281
|
const durationStr = this.data.durationMs ? ` in ${(this.data.durationMs / 1e3).toFixed(1)}s` : "";
|
|
4841
4282
|
const ratioStr = ratio ? ` (${ratio} compression)` : "";
|
|
4842
|
-
return `${emoji} ${
|
|
4283
|
+
return `${emoji} ${chalk12.hex(color)(`Observed: ${observed} \u2192 ${compressed} tokens${ratioStr}${durationStr}`)} ${chalk12.hex(mastra.green)("\u2713")}`;
|
|
4843
4284
|
}
|
|
4844
4285
|
}
|
|
4286
|
+
getChatSpacingKind() {
|
|
4287
|
+
return "other";
|
|
4288
|
+
}
|
|
4845
4289
|
};
|
|
4846
4290
|
var PlanContentBox = class {
|
|
4847
4291
|
constructor(plan) {
|
|
@@ -4857,7 +4301,7 @@ var PlanContentBox = class {
|
|
|
4857
4301
|
color: (text) => theme.fg("text", text)
|
|
4858
4302
|
});
|
|
4859
4303
|
const rendered = markdown.render(innerWidth).flatMap((line) => line.length > 0 ? [line] : [""]);
|
|
4860
|
-
const border = (text) =>
|
|
4304
|
+
const border = (text) => chalk12.hex(mastra.purple)(text);
|
|
4861
4305
|
const top = `${border("\u256D")}${border("\u2500".repeat(innerWidth + 2))}${border("\u256E")}`;
|
|
4862
4306
|
const bottom = `${border("\u2570")}${border("\u2500".repeat(innerWidth + 2))}${border("\u256F")}`;
|
|
4863
4307
|
const body = rendered.map((line) => {
|
|
@@ -5113,11 +4557,10 @@ var PlanResultComponent = class extends Container {
|
|
|
5113
4557
|
var ReactiveSignalComponent = class extends Container {
|
|
5114
4558
|
constructor(options) {
|
|
5115
4559
|
super();
|
|
5116
|
-
this.addChild(new Text(
|
|
4560
|
+
this.addChild(new Text(chalk12.hex(mastra.orange).bold(`Signal: ${options.tagName}`), BOX_INDENT, 0));
|
|
5117
4561
|
if (options.message?.trim()) {
|
|
5118
4562
|
this.addChild(new Text(theme.fg("dim", options.message.trim()), BOX_INDENT + 2, 0));
|
|
5119
4563
|
}
|
|
5120
|
-
this.addChild(new Spacer(1));
|
|
5121
4564
|
}
|
|
5122
4565
|
getChatSpacingKind() {
|
|
5123
4566
|
return "system";
|
|
@@ -5126,14 +4569,13 @@ var ReactiveSignalComponent = class extends Container {
|
|
|
5126
4569
|
var StateSignalComponent = class extends Container {
|
|
5127
4570
|
constructor(options) {
|
|
5128
4571
|
super();
|
|
5129
|
-
const title =
|
|
4572
|
+
const title = chalk12.hex(mastra.blue).bold(`State ${options.mode}: ${options.stateId}`);
|
|
5130
4573
|
this.addChild(new Text(title, BOX_INDENT, 0));
|
|
5131
4574
|
const message = options.message?.trim();
|
|
5132
4575
|
if (message) {
|
|
5133
4576
|
const preview = message.length > 180 ? `${message.slice(0, 177)}...` : message;
|
|
5134
4577
|
this.addChild(new Text(theme.fg("dim", preview), BOX_INDENT + 2, 0));
|
|
5135
4578
|
}
|
|
5136
|
-
this.addChild(new Spacer(1));
|
|
5137
4579
|
}
|
|
5138
4580
|
getChatSpacingKind() {
|
|
5139
4581
|
return "system";
|
|
@@ -5295,7 +4737,6 @@ var SubagentExecutionComponent = class extends Container {
|
|
|
5295
4737
|
}
|
|
5296
4738
|
}
|
|
5297
4739
|
this.addChild(new Text(`${border("\u2570\u2500\u2500")} ${footerText}`, BOX_INDENT, 0));
|
|
5298
|
-
this.addChild(new Spacer(1));
|
|
5299
4740
|
this.invalidate();
|
|
5300
4741
|
this.ui.requestRender();
|
|
5301
4742
|
}
|
|
@@ -5384,12 +4825,12 @@ var SystemReminderComponent = class extends Container {
|
|
|
5384
4825
|
return;
|
|
5385
4826
|
}
|
|
5386
4827
|
const accent = getReminderAccent(this.reminderType);
|
|
5387
|
-
const border = (char) => accent ?
|
|
4828
|
+
const border = (char) => accent ? chalk12.hex(accent).bold(char) : theme.bold(theme.fg("toolTitle", char));
|
|
5388
4829
|
const titleText = getReminderTitle(this.reminderType, this.path, {
|
|
5389
4830
|
goalMaxTurns: this.goalMaxTurns,
|
|
5390
4831
|
judgeModelId: this.judgeModelId
|
|
5391
4832
|
});
|
|
5392
|
-
const title = accent ?
|
|
4833
|
+
const title = accent ? chalk12.hex(accent).bold(titleText) : theme.bold(theme.fg("toolTitle", titleText));
|
|
5393
4834
|
const metadataColor = (text) => theme.fg("dim", text);
|
|
5394
4835
|
const bodyColor = (text) => theme.fg("text", text);
|
|
5395
4836
|
const hintColor = (text) => theme.fg("dim", text);
|
|
@@ -5419,12 +4860,11 @@ var SystemReminderComponent = class extends Container {
|
|
|
5419
4860
|
this.addChild(new Text(renderRow(hint, innerWidth, border), BOX_INDENT, 0));
|
|
5420
4861
|
}
|
|
5421
4862
|
this.addChild(new Text(`${border("\u2570")}${border(horizontal)}${border("\u256F")}`, BOX_INDENT, 0));
|
|
5422
|
-
this.addChild(new Spacer(1));
|
|
5423
4863
|
}
|
|
5424
4864
|
};
|
|
5425
4865
|
function renderRow(text, width, border) {
|
|
5426
4866
|
const content = padLine2(text, width);
|
|
5427
|
-
const rightPadding = hasWideGlyph(
|
|
4867
|
+
const rightPadding = hasWideGlyph(stripAnsi(text)) ? " " : "";
|
|
5428
4868
|
return `${border("\u2502")} ${content}${rightPadding}${border("\u2502")}`;
|
|
5429
4869
|
}
|
|
5430
4870
|
function splitMessageLines(message) {
|
|
@@ -5493,7 +4933,7 @@ function wrapLines(lines, maxLineWidth) {
|
|
|
5493
4933
|
return wrappedLines;
|
|
5494
4934
|
}
|
|
5495
4935
|
function padLine2(text, width) {
|
|
5496
|
-
const visibleLength =
|
|
4936
|
+
const visibleLength = stripAnsi(text).length;
|
|
5497
4937
|
if (visibleLength === width) {
|
|
5498
4938
|
return text;
|
|
5499
4939
|
}
|
|
@@ -5503,17 +4943,19 @@ function padLine2(text, width) {
|
|
|
5503
4943
|
return text + " ".repeat(width - visibleLength);
|
|
5504
4944
|
}
|
|
5505
4945
|
function truncateLine(text, width) {
|
|
5506
|
-
const plain =
|
|
4946
|
+
const plain = stripAnsi(text);
|
|
5507
4947
|
return plain.length <= width ? text : plain.slice(0, Math.max(0, width - 1)) + "\u2026";
|
|
5508
4948
|
}
|
|
5509
4949
|
var TemporalGapComponent = class extends Container {
|
|
5510
4950
|
constructor(options) {
|
|
5511
4951
|
super();
|
|
5512
4952
|
this.addChild(new Text(theme.fg("dim", ` \u23F3 ${resolveGapText(options)}`), BOX_INDENT, 0));
|
|
5513
|
-
this.addChild(new Spacer(1));
|
|
5514
4953
|
}
|
|
5515
4954
|
setExpanded(_expanded) {
|
|
5516
4955
|
}
|
|
4956
|
+
getChatSpacingKind() {
|
|
4957
|
+
return "other";
|
|
4958
|
+
}
|
|
5517
4959
|
};
|
|
5518
4960
|
function resolveGapText(options) {
|
|
5519
4961
|
const gapText = options.gapText?.trim();
|
|
@@ -5766,7 +5208,9 @@ var ErrorDisplayComponent = class extends Container {
|
|
|
5766
5208
|
}
|
|
5767
5209
|
const borderBottom = new Text(theme.fg("error", "\u2570" + "\u2500".repeat(59) + "\u256F"), 0, 0);
|
|
5768
5210
|
box.addChild(borderBottom);
|
|
5769
|
-
|
|
5211
|
+
}
|
|
5212
|
+
getChatSpacingKind() {
|
|
5213
|
+
return "other";
|
|
5770
5214
|
}
|
|
5771
5215
|
createCodeContext(context, errorLine) {
|
|
5772
5216
|
const container = new Container();
|
|
@@ -5940,22 +5384,22 @@ var ToolValidationErrorComponent = class extends Container {
|
|
|
5940
5384
|
// src/tui/components/tool-execution-enhanced.ts
|
|
5941
5385
|
var CODE_HIGHLIGHT_THEME = {
|
|
5942
5386
|
default: (text) => theme.fg("toolArgs", text),
|
|
5943
|
-
keyword:
|
|
5944
|
-
built_in:
|
|
5945
|
-
type:
|
|
5946
|
-
literal:
|
|
5947
|
-
number:
|
|
5948
|
-
string:
|
|
5949
|
-
regexp:
|
|
5950
|
-
title:
|
|
5951
|
-
function:
|
|
5952
|
-
params:
|
|
5953
|
-
comment:
|
|
5954
|
-
meta:
|
|
5955
|
-
attr:
|
|
5956
|
-
variable:
|
|
5957
|
-
tag:
|
|
5958
|
-
name:
|
|
5387
|
+
keyword: chalk12.hex("#c084fc"),
|
|
5388
|
+
built_in: chalk12.hex("#93c5fd"),
|
|
5389
|
+
type: chalk12.hex("#93c5fd"),
|
|
5390
|
+
literal: chalk12.hex("#fca5a5"),
|
|
5391
|
+
number: chalk12.hex("#fbbf24"),
|
|
5392
|
+
string: chalk12.hex("#86efac"),
|
|
5393
|
+
regexp: chalk12.hex("#fca5a5"),
|
|
5394
|
+
title: chalk12.hex("#93c5fd"),
|
|
5395
|
+
function: chalk12.hex("#93c5fd"),
|
|
5396
|
+
params: chalk12.hex("#d4d4d8"),
|
|
5397
|
+
comment: chalk12.hex("#71717a"),
|
|
5398
|
+
meta: chalk12.hex("#a1a1aa"),
|
|
5399
|
+
attr: chalk12.hex("#fbbf24"),
|
|
5400
|
+
variable: chalk12.hex("#d4d4d8"),
|
|
5401
|
+
tag: chalk12.hex("#c084fc"),
|
|
5402
|
+
name: chalk12.hex("#c084fc")
|
|
5959
5403
|
};
|
|
5960
5404
|
var COMPACT_TOOL_COLOR = mastra.orange;
|
|
5961
5405
|
var COMPACT_TOOL_ARGS_BG = "#141414";
|
|
@@ -5965,23 +5409,23 @@ function normalizeHexColor(color) {
|
|
|
5965
5409
|
return color;
|
|
5966
5410
|
}
|
|
5967
5411
|
var QUIET_CODE_HIGHLIGHT_THEME = {
|
|
5968
|
-
default:
|
|
5969
|
-
keyword:
|
|
5970
|
-
built_in:
|
|
5971
|
-
type:
|
|
5972
|
-
literal:
|
|
5973
|
-
number:
|
|
5974
|
-
string:
|
|
5975
|
-
regexp:
|
|
5976
|
-
title:
|
|
5977
|
-
function:
|
|
5978
|
-
params:
|
|
5979
|
-
comment:
|
|
5980
|
-
meta:
|
|
5981
|
-
attr:
|
|
5982
|
-
variable:
|
|
5983
|
-
tag:
|
|
5984
|
-
name:
|
|
5412
|
+
default: chalk12.hex("#b4b4bd"),
|
|
5413
|
+
keyword: chalk12.hex("#c4b5fd"),
|
|
5414
|
+
built_in: chalk12.hex("#93c5fd"),
|
|
5415
|
+
type: chalk12.hex("#93c5fd"),
|
|
5416
|
+
literal: chalk12.hex("#fca5a5"),
|
|
5417
|
+
number: chalk12.hex("#fbbf24"),
|
|
5418
|
+
string: chalk12.hex("#9ecfa9"),
|
|
5419
|
+
regexp: chalk12.hex("#fca5a5"),
|
|
5420
|
+
title: chalk12.hex("#93c5fd"),
|
|
5421
|
+
function: chalk12.hex("#7dd3fc"),
|
|
5422
|
+
params: chalk12.hex("#b4b4bd"),
|
|
5423
|
+
comment: chalk12.hex("#71717a"),
|
|
5424
|
+
meta: chalk12.hex("#71717a"),
|
|
5425
|
+
attr: chalk12.hex("#fbbf24"),
|
|
5426
|
+
variable: chalk12.hex("#d4d4d8"),
|
|
5427
|
+
tag: chalk12.hex("#c4b5fd"),
|
|
5428
|
+
name: chalk12.hex("#c4b5fd")
|
|
5985
5429
|
};
|
|
5986
5430
|
var SHELL_CONTROL_WORDS = /* @__PURE__ */ new Set([
|
|
5987
5431
|
"if",
|
|
@@ -6273,22 +5717,22 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6273
5717
|
-this.quietPreviewLineLimit
|
|
6274
5718
|
);
|
|
6275
5719
|
return wrapped.map((line) => {
|
|
6276
|
-
const linePrefix = ` ${
|
|
5720
|
+
const linePrefix = ` ${chalk12.hex(this.getQuietToolRailColor())("\u2502")} `;
|
|
6277
5721
|
return truncateAnsi2(`${linePrefix}${this.formatQuietActivePreview(line)}`, maxLineWidth);
|
|
6278
5722
|
});
|
|
6279
5723
|
}
|
|
6280
5724
|
getQuietCodePreviewLines(preview, maxLineWidth) {
|
|
6281
|
-
const linePrefix = ` ${
|
|
5725
|
+
const linePrefix = ` ${chalk12.hex(this.getQuietToolRailColor())("\u2502")} `;
|
|
6282
5726
|
return this.highlightQuietCodePreview(preview).split("\n").slice(-this.quietPreviewLineLimit).map((line) => truncateAnsi2(`${linePrefix}${line}`, maxLineWidth));
|
|
6283
5727
|
}
|
|
6284
5728
|
isQuietCodePreviewTool() {
|
|
6285
5729
|
return this.toolName === MC_TOOLS.VIEW || this.toolName === MC_TOOLS.WRITE_FILE || this.toolName === MC_TOOLS.STRING_REPLACE_LSP;
|
|
6286
5730
|
}
|
|
6287
5731
|
getQuietPreviewCapLine() {
|
|
6288
|
-
return ` ${
|
|
5732
|
+
return ` ${chalk12.hex(this.getQuietToolRailColor())("\u2570\u2500\u2500")}`;
|
|
6289
5733
|
}
|
|
6290
5734
|
getQuietPreviewSpacerLine() {
|
|
6291
|
-
return ` ${
|
|
5735
|
+
return ` ${chalk12.hex(this.getQuietToolRailColor())("\u2502")}`;
|
|
6292
5736
|
}
|
|
6293
5737
|
shouldCloseQuietPreview() {
|
|
6294
5738
|
return !this.compactToolHasFollowingContinuation;
|
|
@@ -6316,7 +5760,7 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6316
5760
|
return tokens.map((token) => {
|
|
6317
5761
|
if (/^\s+$/.test(token)) return { text: token, color: (value) => value };
|
|
6318
5762
|
if (token.startsWith('"') && token.endsWith('"') || token.startsWith("'") && token.endsWith("'")) {
|
|
6319
|
-
return { text: token, color:
|
|
5763
|
+
return { text: token, color: chalk12.white };
|
|
6320
5764
|
}
|
|
6321
5765
|
if (token === "&&" || token === "||" || token === "|" || token === ";" || token === "&") {
|
|
6322
5766
|
return { text: token, color: (value) => theme.fg("muted", value) };
|
|
@@ -6325,7 +5769,7 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6325
5769
|
return { text: token, color: (value) => theme.fg("muted", value) };
|
|
6326
5770
|
}
|
|
6327
5771
|
if (SHELL_CONTROL_WORDS.has(token)) {
|
|
6328
|
-
return { text: token, color:
|
|
5772
|
+
return { text: token, color: chalk12.blue };
|
|
6329
5773
|
}
|
|
6330
5774
|
return { text: token, color: (value) => theme.fg("toolArgs", value) };
|
|
6331
5775
|
});
|
|
@@ -6425,11 +5869,11 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6425
5869
|
const color = this.getCompactToolAccentColor(toolLabelColor);
|
|
6426
5870
|
const argsBg = this.getCompactToolArgsBg(toolLabelColor);
|
|
6427
5871
|
const argsColor = this.getCompactToolArgsColor(toolLabelColor);
|
|
6428
|
-
const leftHalf =
|
|
6429
|
-
const rightHalf = summary ?
|
|
6430
|
-
const label = `${leftHalf}${
|
|
5872
|
+
const leftHalf = chalk12.hex(color)("\u2590");
|
|
5873
|
+
const rightHalf = summary ? chalk12.hex(color).bgHex(argsBg)("\u258C") : chalk12.hex(color)("\u258C");
|
|
5874
|
+
const label = `${leftHalf}${chalk12.bgHex(color).hex("#000000").bold(toolLabel)}${rightHalf}`;
|
|
6431
5875
|
const args = summary ? this.formatCompactSummaryBadge(summary, argsBg, argsColor) : "";
|
|
6432
|
-
const trail = summary ?
|
|
5876
|
+
const trail = summary ? chalk12.hex(argsBg)("\u258C") : "";
|
|
6433
5877
|
return `${label}${args}${trail}`;
|
|
6434
5878
|
}
|
|
6435
5879
|
getCompactToolAccentColor(toolLabelColor) {
|
|
@@ -6452,7 +5896,7 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6452
5896
|
return ensureTerminalGlyphContrast(color);
|
|
6453
5897
|
}
|
|
6454
5898
|
formatToolBorder(char) {
|
|
6455
|
-
return theme.bold(
|
|
5899
|
+
return theme.bold(chalk12.hex(ensureTerminalGlyphContrast(theme.getTheme().toolBorderSuccess))(char));
|
|
6456
5900
|
}
|
|
6457
5901
|
getCompactToolLabelColor() {
|
|
6458
5902
|
if (this.compactToolGroupLabelColor) return this.compactToolGroupLabelColor;
|
|
@@ -6620,9 +6064,9 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6620
6064
|
const isStreamingContinuation = !this.isComplete() && this.quietPreviewLineLimit > 0;
|
|
6621
6065
|
if (isStreamingContinuation) {
|
|
6622
6066
|
const circleColor = this.getQuietToolCircleColor(this.getCompactToolAccentColor(this.getCompactToolLabelColor()));
|
|
6623
|
-
return `${
|
|
6067
|
+
return `${chalk12.hex(circleColor)("\u25CF")}${chalk12.hex(railColor)("\u2500")}`;
|
|
6624
6068
|
}
|
|
6625
|
-
return
|
|
6069
|
+
return chalk12.hex(railColor)(this.compactToolHasFollowingContinuation ? "\u251C\u2500" : "\u2570\u2500");
|
|
6626
6070
|
}
|
|
6627
6071
|
formatCompactContinuationLine(summary) {
|
|
6628
6072
|
const lineMatch = summary.match(/^─+/);
|
|
@@ -6637,17 +6081,17 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
6637
6081
|
const railColor = this.getQuietToolRailColor();
|
|
6638
6082
|
const circleColor = this.getQuietToolCircleColor(color);
|
|
6639
6083
|
const isStreamingContinuation = this.compactToolContinuation && !this.isComplete() && this.quietPreviewLineLimit > 0;
|
|
6640
|
-
const branch = hasFollowing || isStreamingContinuation ? `${hasPreview || isStreamingContinuation ?
|
|
6084
|
+
const branch = hasFollowing || isStreamingContinuation ? `${hasPreview || isStreamingContinuation ? chalk12.hex(circleColor)("\u25CF") : chalk12.hex(railColor)("\u251C")}${chalk12.hex(railColor)(`\u2500${separator}${linePrefix}`)}` : chalk12.hex(railColor)(`\u2570\u2500${separator}${linePrefix}`);
|
|
6641
6085
|
const continuationSummary = ` ${summary.slice(linePrefix.length)}`;
|
|
6642
|
-
const trail = continuationSummary ?
|
|
6086
|
+
const trail = continuationSummary ? chalk12.hex(argsBg)("\u258C") : "";
|
|
6643
6087
|
return `${branch}${this.formatCompactSummaryBadge(continuationSummary, argsBg, argsColor)}${trail}`;
|
|
6644
6088
|
}
|
|
6645
6089
|
formatCompactSummaryBadge(summary, argsBg, argsColor) {
|
|
6646
|
-
const styleText = (text) => argsColor ?
|
|
6090
|
+
const styleText = (text) => argsColor ? chalk12.hex(argsColor)(text) : theme.fg("text", text);
|
|
6647
6091
|
const rangeMatch = summary.match(/(:\d+(?:-\d+)?)$/);
|
|
6648
|
-
if (!rangeMatch?.[1]) return
|
|
6092
|
+
if (!rangeMatch?.[1]) return chalk12.bgHex(argsBg)(styleText(summary));
|
|
6649
6093
|
const rangeStart = summary.length - rangeMatch[1].length;
|
|
6650
|
-
return `${
|
|
6094
|
+
return `${chalk12.bgHex(argsBg)(styleText(summary.slice(0, rangeStart)))}${chalk12.bgHex(argsBg)(theme.fg("dim", rangeMatch[1]))}`;
|
|
6651
6095
|
}
|
|
6652
6096
|
getCompactContinuationSummary() {
|
|
6653
6097
|
const summary = this.getCompactToolSummary();
|
|
@@ -7243,8 +6687,8 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
7243
6687
|
const t = theme.getTheme();
|
|
7244
6688
|
const color = diag.severity === "error" ? t.error : diag.severity === "warning" ? t.warning : t.muted;
|
|
7245
6689
|
const icon = diag.severity === "error" ? "\u2717" : diag.severity === "warning" ? "\u26A0" : "\u2139";
|
|
7246
|
-
const location = diag.location ?
|
|
7247
|
-
const line = ` ${
|
|
6690
|
+
const location = diag.location ? chalk12.hex(color)(diag.location) + " " : "";
|
|
6691
|
+
const line = ` ${chalk12.hex(color)(icon)} ${location}${theme.fg("thinkingText", diag.message)}`;
|
|
7248
6692
|
this.contentBox.addChild(new Text(line, 0, 0));
|
|
7249
6693
|
}
|
|
7250
6694
|
if (shouldCollapse) {
|
|
@@ -7298,8 +6742,8 @@ var ToolExecutionComponentEnhanced = class extends Container {
|
|
|
7298
6742
|
const newLines = newStr.split("\n");
|
|
7299
6743
|
const lines = [];
|
|
7300
6744
|
let firstChangeIndex = -1;
|
|
7301
|
-
const removedColor =
|
|
7302
|
-
const addedColor =
|
|
6745
|
+
const removedColor = chalk12.hex(mastra.red);
|
|
6746
|
+
const addedColor = chalk12.hex(theme.getTheme().success);
|
|
7303
6747
|
const maxLines = Math.max(oldLines.length, newLines.length);
|
|
7304
6748
|
for (let i = 0; i < maxLines; i++) {
|
|
7305
6749
|
if (i >= oldLines.length) {
|
|
@@ -8033,7 +7477,7 @@ ${stackMatch.join("\n")}`;
|
|
|
8033
7477
|
}
|
|
8034
7478
|
return err;
|
|
8035
7479
|
}
|
|
8036
|
-
function
|
|
7480
|
+
function stripAnsi2(s) {
|
|
8037
7481
|
return s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
8038
7482
|
}
|
|
8039
7483
|
var BorderedBox = class {
|
|
@@ -8051,7 +7495,7 @@ var BorderedBox = class {
|
|
|
8051
7495
|
this.child.invalidate?.();
|
|
8052
7496
|
}
|
|
8053
7497
|
render(width) {
|
|
8054
|
-
const borderColor = (s) => this.borderColor ?
|
|
7498
|
+
const borderColor = (s) => this.borderColor ? chalk12.hex(this.borderColor)(s) : this.pending ? chalk12.hex(theme.getTheme().dim)(s) : chalk12.hex(tintHex(mastra.green, 1))(s);
|
|
8055
7499
|
const maxInnerWidth = Math.max(1, width - 6 - 2 - BOX_INDENT_STR.length - 1);
|
|
8056
7500
|
const childLines = this.child.render(maxInnerWidth);
|
|
8057
7501
|
if (childLines.length === 0) {
|
|
@@ -8062,7 +7506,7 @@ var BorderedBox = class {
|
|
|
8062
7506
|
for (const line of childLines) {
|
|
8063
7507
|
const trimmed = line.replace(/\s+$/, "");
|
|
8064
7508
|
trimmedLines.push(trimmed);
|
|
8065
|
-
const w = visibleWidth(
|
|
7509
|
+
const w = visibleWidth(stripAnsi2(trimmed));
|
|
8066
7510
|
if (w > maxContentWidth) maxContentWidth = w;
|
|
8067
7511
|
}
|
|
8068
7512
|
const maxAllowedContent = maxInnerWidth;
|
|
@@ -8075,25 +7519,25 @@ var BorderedBox = class {
|
|
|
8075
7519
|
}
|
|
8076
7520
|
const boxWidth = boxInner + 4;
|
|
8077
7521
|
const lines = [];
|
|
8078
|
-
const promptPrefix =
|
|
7522
|
+
const promptPrefix = chalk12.hex(tintHex(mastra.green, 1))("\xBB") + " ";
|
|
8079
7523
|
const promptWidth = 2;
|
|
8080
7524
|
if (this.label) {
|
|
8081
7525
|
const labelText = ` ${this.label} `;
|
|
8082
7526
|
const labelLen = labelText.length;
|
|
8083
7527
|
const remaining = Math.max(0, boxWidth - 2 - labelLen);
|
|
8084
7528
|
lines.push(
|
|
8085
|
-
borderColor("\u256D") +
|
|
7529
|
+
borderColor("\u256D") + chalk12.hex(theme.getTheme().dim)(labelText) + borderColor(`${"\u2500".repeat(remaining)}\u256E`)
|
|
8086
7530
|
);
|
|
8087
7531
|
} else {
|
|
8088
7532
|
lines.push(borderColor(`\u256D${"\u2500".repeat(boxWidth - 2)}\u256E`));
|
|
8089
7533
|
}
|
|
8090
7534
|
for (let i = 0; i < trimmedLines.length; i++) {
|
|
8091
7535
|
let trimmed = trimmedLines[i];
|
|
8092
|
-
let vis = visibleWidth(
|
|
7536
|
+
let vis = visibleWidth(stripAnsi2(trimmed));
|
|
8093
7537
|
const lineMaxWidth = i === 0 ? boxInner - promptWidth : boxInner;
|
|
8094
7538
|
if (vis > lineMaxWidth) {
|
|
8095
7539
|
trimmed = truncateToWidth(trimmed, lineMaxWidth);
|
|
8096
|
-
vis = visibleWidth(
|
|
7540
|
+
vis = visibleWidth(stripAnsi2(trimmed));
|
|
8097
7541
|
}
|
|
8098
7542
|
if (i === 0) {
|
|
8099
7543
|
const padNeeded = Math.max(0, boxInner - vis - promptWidth);
|
|
@@ -8128,7 +7572,6 @@ var PendingUserMessageComponent = class extends Container {
|
|
|
8128
7572
|
const prefix = imageCount > 0 ? `[${imageCount} image${imageCount > 1 ? "s" : ""}] ` : "";
|
|
8129
7573
|
const displayText = `${prefix}${text.replace(/\[image\]\s*/g, "").trim()}`.trim();
|
|
8130
7574
|
this.addChild(new Text(theme.fg("dim", `\u21B3 ${displayText || "Message"} pending\u2026`), BOX_INDENT_STR.length, 0));
|
|
8131
|
-
this.addChild(new Spacer(1));
|
|
8132
7575
|
}
|
|
8133
7576
|
getChatSpacingKind() {
|
|
8134
7577
|
return "user-message";
|
|
@@ -8174,8 +7617,8 @@ var ToolApprovalDialogComponent = class extends Box {
|
|
|
8174
7617
|
}
|
|
8175
7618
|
this.addChild(new Spacer(1));
|
|
8176
7619
|
const categoryHint = this.categoryLabel ? `lways allow ${this.categoryLabel.toLowerCase()}` : "lways allow category";
|
|
8177
|
-
const dimColor =
|
|
8178
|
-
const key =
|
|
7620
|
+
const dimColor = chalk12.hex(theme.getTheme().dim);
|
|
7621
|
+
const key = chalk12.hex(theme.getTheme().text).bold;
|
|
8179
7622
|
this.addChild(
|
|
8180
7623
|
new Text(
|
|
8181
7624
|
theme.fg("accent", "Allow? ") + key("y") + dimColor("es ") + key("n") + dimColor("o ") + key("a") + dimColor(categoryHint + " ") + key("Y") + dimColor("olo"),
|
|
@@ -8244,7 +7687,8 @@ var ToolApprovalDialogComponent = class extends Box {
|
|
|
8244
7687
|
|
|
8245
7688
|
// src/tui/handlers/tool.ts
|
|
8246
7689
|
function getCurrentModeColor(ctx) {
|
|
8247
|
-
|
|
7690
|
+
const color = ctx.state.harness.getCurrentMode?.()?.metadata?.color;
|
|
7691
|
+
return typeof color === "string" ? color : void 0;
|
|
8248
7692
|
}
|
|
8249
7693
|
function isTaskMutationTool(toolName) {
|
|
8250
7694
|
return toolName === "task_write" || toolName === "task_update" || toolName === "task_complete";
|
|
@@ -8575,6 +8019,7 @@ function handleToolEnd(ctx, toolCallId, result, isError) {
|
|
|
8575
8019
|
// src/tui/render-messages.ts
|
|
8576
8020
|
var WHILE_ACTIVE_USER_MESSAGE_LABEL = "steer";
|
|
8577
8021
|
var HIDDEN_REACTIVE_SIGNAL_TAGS = /* @__PURE__ */ new Set(["github-subscribe-pr", "github-unsubscribe-pr"]);
|
|
8022
|
+
var GOAL_STATE_SIGNAL_ID = "goal";
|
|
8578
8023
|
function shouldRenderReactiveSignal(tagName) {
|
|
8579
8024
|
return !HIDDEN_REACTIVE_SIGNAL_TAGS.has(tagName);
|
|
8580
8025
|
}
|
|
@@ -8586,7 +8031,8 @@ function getPendingUserMessageLabel(isInterjection) {
|
|
|
8586
8031
|
return isInterjection ? WHILE_ACTIVE_USER_MESSAGE_LABEL : void 0;
|
|
8587
8032
|
}
|
|
8588
8033
|
function getCurrentModeColor2(state) {
|
|
8589
|
-
|
|
8034
|
+
const color = state.harness.getCurrentMode?.()?.metadata?.color;
|
|
8035
|
+
return typeof color === "string" ? color : void 0;
|
|
8590
8036
|
}
|
|
8591
8037
|
var TaskHistoryComponent = class extends Container {
|
|
8592
8038
|
getChatSpacingKind() {
|
|
@@ -8606,11 +8052,10 @@ function renderClearedTasksInline(state, clearedTasks, insertIndex = -1) {
|
|
|
8606
8052
|
const label = count === 1 ? "Task" : "Tasks";
|
|
8607
8053
|
container.addChild(new Text(theme.fg("accent", `${label} cleared`), BOX_INDENT, 0));
|
|
8608
8054
|
for (const task of clearedTasks) {
|
|
8609
|
-
const icon = task.status === "completed" ?
|
|
8610
|
-
const text =
|
|
8055
|
+
const icon = task.status === "completed" ? chalk12.hex(mastra.green)("\u2713") : chalk12.hex(mastra.darkGray)("\u25CB");
|
|
8056
|
+
const text = chalk12.hex(theme.getTheme().dim).strikethrough(task.content);
|
|
8611
8057
|
container.addChild(new Text(` ${icon} ${text}`, BOX_INDENT, 0));
|
|
8612
8058
|
}
|
|
8613
|
-
container.addChild(new Spacer(1));
|
|
8614
8059
|
insertTaskHistoryComponent(state, container, insertIndex);
|
|
8615
8060
|
}
|
|
8616
8061
|
function renderTaskTransitionFromHistory(state, previousTasks, nextTasks) {
|
|
@@ -8779,7 +8224,7 @@ function addUserMessage(state, message, options) {
|
|
|
8779
8224
|
return;
|
|
8780
8225
|
}
|
|
8781
8226
|
const stateSignalPart = message.content.find((content) => content.type === "state_signal");
|
|
8782
|
-
if (stateSignalPart && stateSignalPart.stateId === TASKS_STATE_ID) {
|
|
8227
|
+
if (stateSignalPart && (stateSignalPart.stateId === TASKS_STATE_ID || stateSignalPart.stateId === GOAL_STATE_SIGNAL_ID)) {
|
|
8783
8228
|
return;
|
|
8784
8229
|
}
|
|
8785
8230
|
if (stateSignalPart) {
|
|
@@ -8860,7 +8305,7 @@ function addUserMessage(state, message, options) {
|
|
|
8860
8305
|
}
|
|
8861
8306
|
const slashComp = new SlashCommandComponent(commandName, commandContent);
|
|
8862
8307
|
state.allSlashCommandComponents.push(slashComp);
|
|
8863
|
-
state.chatContainer
|
|
8308
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, slashComp);
|
|
8864
8309
|
state.ui.requestRender();
|
|
8865
8310
|
return;
|
|
8866
8311
|
}
|
|
@@ -8884,7 +8329,7 @@ function addUserMessage(state, message, options) {
|
|
|
8884
8329
|
}
|
|
8885
8330
|
const skillComp = new SlashCommandComponent(commandName, skillContent);
|
|
8886
8331
|
state.allSlashCommandComponents.push(skillComp);
|
|
8887
|
-
state.chatContainer
|
|
8332
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, skillComp);
|
|
8888
8333
|
state.ui.requestRender();
|
|
8889
8334
|
return;
|
|
8890
8335
|
}
|
|
@@ -9338,7 +8783,7 @@ ARGUMENTS: ${trimmedArgs}` : ""}`.trim();
|
|
|
9338
8783
|
if (!isCurrentThreadActive(ctx)) {
|
|
9339
8784
|
const component = new SlashCommandComponent(`skill/${skill.name}`, content);
|
|
9340
8785
|
ctx.state.allSlashCommandComponents.push(component);
|
|
9341
|
-
ctx.state.chatContainer
|
|
8786
|
+
insertChatComponentWithBoundarySpacing(ctx.state.chatContainer, component);
|
|
9342
8787
|
ctx.state.ui.requestRender();
|
|
9343
8788
|
}
|
|
9344
8789
|
const displayText = `/skill/${skill.name}${trimmedArgs ? ` ${trimmedArgs}` : ""}`;
|
|
@@ -9362,7 +8807,7 @@ ${escapeSkillBoundary(content)}
|
|
|
9362
8807
|
// src/tui/commands/new.ts
|
|
9363
8808
|
async function handleNewCommand(ctx) {
|
|
9364
8809
|
const { state } = ctx;
|
|
9365
|
-
state.harness.
|
|
8810
|
+
state.harness.detachFromCurrentThread();
|
|
9366
8811
|
state.pendingNewThread = true;
|
|
9367
8812
|
state.chatContainer.clear();
|
|
9368
8813
|
state.pendingTools.clear();
|
|
@@ -9690,11 +9135,11 @@ async function handleResourceCommand(ctx, args) {
|
|
|
9690
9135
|
}
|
|
9691
9136
|
function colorizeDiffLine(line) {
|
|
9692
9137
|
const t = theme.getTheme();
|
|
9693
|
-
const addedColor =
|
|
9694
|
-
const hunkHeaderColor =
|
|
9695
|
-
const fileHeaderColor =
|
|
9696
|
-
const removedColor =
|
|
9697
|
-
const metaColor =
|
|
9138
|
+
const addedColor = chalk12.hex(t.success);
|
|
9139
|
+
const hunkHeaderColor = chalk12.hex(t.toolBorderPending);
|
|
9140
|
+
const fileHeaderColor = chalk12.bold.hex(t.accent);
|
|
9141
|
+
const removedColor = chalk12.hex(mastra.red);
|
|
9142
|
+
const metaColor = chalk12.hex(mastra.mainGray);
|
|
9698
9143
|
if (line.startsWith("+++") || line.startsWith("---")) {
|
|
9699
9144
|
return fileHeaderColor(line);
|
|
9700
9145
|
}
|
|
@@ -9719,7 +9164,6 @@ function colorizeDiffLine(line) {
|
|
|
9719
9164
|
var DiffOutputComponent = class extends Container {
|
|
9720
9165
|
constructor(command, diffOutput) {
|
|
9721
9166
|
super();
|
|
9722
|
-
this.addChild(new Spacer(1));
|
|
9723
9167
|
this.addChild(
|
|
9724
9168
|
new Text(
|
|
9725
9169
|
`${theme.fg("success", "\u2713")} ${theme.bold(theme.fg("muted", "$"))} ${theme.fg("text", command)}`,
|
|
@@ -9735,6 +9179,9 @@ var DiffOutputComponent = class extends Container {
|
|
|
9735
9179
|
}
|
|
9736
9180
|
}
|
|
9737
9181
|
}
|
|
9182
|
+
getChatSpacingKind() {
|
|
9183
|
+
return "other";
|
|
9184
|
+
}
|
|
9738
9185
|
};
|
|
9739
9186
|
|
|
9740
9187
|
// src/tui/commands/diff.ts
|
|
@@ -10547,33 +9994,170 @@ function getLinuxClipboardImageXclip() {
|
|
|
10547
9994
|
} catch {
|
|
10548
9995
|
return null;
|
|
10549
9996
|
}
|
|
10550
|
-
}
|
|
10551
|
-
function getLinuxClipboardImageWlPaste() {
|
|
10552
|
-
try {
|
|
10553
|
-
const types = execSync("wl-paste --list-types", {
|
|
10554
|
-
encoding: "utf-8",
|
|
10555
|
-
timeout: 3e3,
|
|
10556
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
10557
|
-
});
|
|
10558
|
-
if (!types.includes("image/png")) {
|
|
10559
|
-
return null;
|
|
9997
|
+
}
|
|
9998
|
+
function getLinuxClipboardImageWlPaste() {
|
|
9999
|
+
try {
|
|
10000
|
+
const types = execSync("wl-paste --list-types", {
|
|
10001
|
+
encoding: "utf-8",
|
|
10002
|
+
timeout: 3e3,
|
|
10003
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
10004
|
+
});
|
|
10005
|
+
if (!types.includes("image/png")) {
|
|
10006
|
+
return null;
|
|
10007
|
+
}
|
|
10008
|
+
const buffer = execSync("wl-paste --type image/png", {
|
|
10009
|
+
timeout: 5e3,
|
|
10010
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
10011
|
+
maxBuffer: 50 * 1024 * 1024
|
|
10012
|
+
});
|
|
10013
|
+
if (!Buffer.isBuffer(buffer) || buffer.length === 0) {
|
|
10014
|
+
return null;
|
|
10015
|
+
}
|
|
10016
|
+
return {
|
|
10017
|
+
data: buffer.toString("base64"),
|
|
10018
|
+
mimeType: "image/png"
|
|
10019
|
+
};
|
|
10020
|
+
} catch {
|
|
10021
|
+
return null;
|
|
10022
|
+
}
|
|
10023
|
+
}
|
|
10024
|
+
var GRADIENT_WIDTH = 30;
|
|
10025
|
+
var BASE_COLOR = [22, 200, 88];
|
|
10026
|
+
function getMinBrightness() {
|
|
10027
|
+
return getThemeMode() === "dark" ? 0.45 : 0.55;
|
|
10028
|
+
}
|
|
10029
|
+
function hexToRgb(hex) {
|
|
10030
|
+
const h = hex.replace("#", "");
|
|
10031
|
+
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
10032
|
+
}
|
|
10033
|
+
var IDLE_BRIGHTNESS = 0.8;
|
|
10034
|
+
function applyGradientSweep(text, offset, color, fadeProgress = 0) {
|
|
10035
|
+
const chars = [...text];
|
|
10036
|
+
const totalChars = chars.length;
|
|
10037
|
+
if (totalChars === 0) return text;
|
|
10038
|
+
const baseColor = color ? hexToRgb(color) : BASE_COLOR;
|
|
10039
|
+
const gradientCenter = offset % 1 * 100;
|
|
10040
|
+
const halfGradient = GRADIENT_WIDTH / 2;
|
|
10041
|
+
const minBrightness = getMinBrightness();
|
|
10042
|
+
const brightnessRange = 1 - minBrightness;
|
|
10043
|
+
let result = "";
|
|
10044
|
+
let batchChars = "";
|
|
10045
|
+
let batchR = -1, batchG = -1, batchB = -1;
|
|
10046
|
+
for (let i = 0; i < totalChars; i++) {
|
|
10047
|
+
const char = chars[i];
|
|
10048
|
+
if (char === " ") {
|
|
10049
|
+
if (batchChars) {
|
|
10050
|
+
result += chalk12.rgb(batchR, batchG, batchB)(batchChars);
|
|
10051
|
+
batchChars = "";
|
|
10052
|
+
}
|
|
10053
|
+
result += " ";
|
|
10054
|
+
continue;
|
|
10055
|
+
}
|
|
10056
|
+
const charPosition = i / totalChars * 100;
|
|
10057
|
+
let distance = Math.abs(charPosition - gradientCenter);
|
|
10058
|
+
if (distance > 50) distance = 100 - distance;
|
|
10059
|
+
const normalizedDistance = Math.min(distance / halfGradient, 1);
|
|
10060
|
+
const animBrightness = minBrightness + brightnessRange * (1 - normalizedDistance);
|
|
10061
|
+
const brightness = animBrightness + (IDLE_BRIGHTNESS - animBrightness) * fadeProgress;
|
|
10062
|
+
const r = Math.floor(baseColor[0] * brightness);
|
|
10063
|
+
const g = Math.floor(baseColor[1] * brightness);
|
|
10064
|
+
const b = Math.floor(baseColor[2] * brightness);
|
|
10065
|
+
if (r === batchR && g === batchG && b === batchB) {
|
|
10066
|
+
batchChars += char;
|
|
10067
|
+
} else {
|
|
10068
|
+
if (batchChars) {
|
|
10069
|
+
result += chalk12.rgb(batchR, batchG, batchB)(batchChars);
|
|
10070
|
+
}
|
|
10071
|
+
batchChars = char;
|
|
10072
|
+
batchR = r;
|
|
10073
|
+
batchG = g;
|
|
10074
|
+
batchB = b;
|
|
10075
|
+
}
|
|
10076
|
+
}
|
|
10077
|
+
if (batchChars) {
|
|
10078
|
+
result += chalk12.rgb(batchR, batchG, batchB)(batchChars);
|
|
10079
|
+
}
|
|
10080
|
+
return result;
|
|
10081
|
+
}
|
|
10082
|
+
var GradientAnimator = class {
|
|
10083
|
+
offset = 0;
|
|
10084
|
+
intervalId = null;
|
|
10085
|
+
onTick;
|
|
10086
|
+
_isFadingOut = false;
|
|
10087
|
+
_isFadingIn = false;
|
|
10088
|
+
_fadeProgress = 0;
|
|
10089
|
+
// 0 = full animation, 1 = fully idle
|
|
10090
|
+
constructor(onTick) {
|
|
10091
|
+
this.onTick = onTick;
|
|
10092
|
+
}
|
|
10093
|
+
start() {
|
|
10094
|
+
if (this.intervalId && !this._isFadingOut) return;
|
|
10095
|
+
if (this.intervalId) {
|
|
10096
|
+
clearInterval(this.intervalId);
|
|
10097
|
+
this.intervalId = null;
|
|
10560
10098
|
}
|
|
10561
|
-
|
|
10562
|
-
|
|
10563
|
-
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10099
|
+
this._isFadingOut = false;
|
|
10100
|
+
this._isFadingIn = true;
|
|
10101
|
+
this._fadeProgress = 1;
|
|
10102
|
+
this.offset = 0;
|
|
10103
|
+
this.intervalId = setInterval(() => {
|
|
10104
|
+
this.offset += 0.03;
|
|
10105
|
+
if (this._isFadingIn) {
|
|
10106
|
+
this._fadeProgress -= 0.06;
|
|
10107
|
+
if (this._fadeProgress <= 0) {
|
|
10108
|
+
this._fadeProgress = 0;
|
|
10109
|
+
this._isFadingIn = false;
|
|
10110
|
+
}
|
|
10111
|
+
}
|
|
10112
|
+
this.onTick();
|
|
10113
|
+
}, 80);
|
|
10114
|
+
}
|
|
10115
|
+
/**
|
|
10116
|
+
* Smoothly fade the gradient to idle state over ~500ms.
|
|
10117
|
+
*/
|
|
10118
|
+
fadeOut() {
|
|
10119
|
+
if (!this.intervalId) return;
|
|
10120
|
+
if (this._isFadingOut) return;
|
|
10121
|
+
this._isFadingOut = true;
|
|
10122
|
+
this._isFadingIn = false;
|
|
10123
|
+
this._fadeProgress = 0;
|
|
10124
|
+
clearInterval(this.intervalId);
|
|
10125
|
+
this.intervalId = setInterval(() => {
|
|
10126
|
+
this._fadeProgress += 0.08;
|
|
10127
|
+
if (this._fadeProgress >= 1) {
|
|
10128
|
+
this._fadeProgress = 1;
|
|
10129
|
+
this.stop();
|
|
10130
|
+
}
|
|
10131
|
+
this.onTick();
|
|
10132
|
+
}, 40);
|
|
10133
|
+
}
|
|
10134
|
+
stop() {
|
|
10135
|
+
if (this.intervalId) {
|
|
10136
|
+
clearInterval(this.intervalId);
|
|
10137
|
+
this.intervalId = null;
|
|
10568
10138
|
}
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
} catch {
|
|
10574
|
-
return null;
|
|
10139
|
+
this._isFadingOut = false;
|
|
10140
|
+
this._isFadingIn = false;
|
|
10141
|
+
this._fadeProgress = 0;
|
|
10142
|
+
this.offset = 0;
|
|
10575
10143
|
}
|
|
10576
|
-
|
|
10144
|
+
getOffset() {
|
|
10145
|
+
return this.offset;
|
|
10146
|
+
}
|
|
10147
|
+
/** 0 = full animation, 1 = fully idle. Use to interpolate colors. */
|
|
10148
|
+
getFadeProgress() {
|
|
10149
|
+
return this._fadeProgress;
|
|
10150
|
+
}
|
|
10151
|
+
isFadingOut() {
|
|
10152
|
+
return this._isFadingOut;
|
|
10153
|
+
}
|
|
10154
|
+
isFadingIn() {
|
|
10155
|
+
return this._isFadingIn;
|
|
10156
|
+
}
|
|
10157
|
+
isRunning() {
|
|
10158
|
+
return this.intervalId !== null;
|
|
10159
|
+
}
|
|
10160
|
+
};
|
|
10577
10161
|
var OMProgressComponent = class extends Container {
|
|
10578
10162
|
state = defaultOMProgressState();
|
|
10579
10163
|
statusText;
|
|
@@ -10636,11 +10220,11 @@ var OMProgressComponent = class extends Container {
|
|
|
10636
10220
|
} else if (this.state.status === "observing") {
|
|
10637
10221
|
const elapsed = this.state.startTime ? Math.round((Date.now() - this.state.startTime) / 1e3) : 0;
|
|
10638
10222
|
const spinner = this.getSpinner();
|
|
10639
|
-
this.statusText.setText(
|
|
10223
|
+
this.statusText.setText(chalk12.hex(mastra.orange)(`${spinner} Observing... ${elapsed}s`));
|
|
10640
10224
|
} else if (this.state.status === "reflecting") {
|
|
10641
10225
|
const elapsed = this.state.startTime ? Math.round((Date.now() - this.state.startTime) / 1e3) : 0;
|
|
10642
10226
|
const spinner = this.getSpinner();
|
|
10643
|
-
this.statusText.setText(
|
|
10227
|
+
this.statusText.setText(chalk12.hex(mastra.pink)(`${spinner} Reflecting... ${elapsed}s`));
|
|
10644
10228
|
}
|
|
10645
10229
|
}
|
|
10646
10230
|
renderProgressBar(percent, width) {
|
|
@@ -10648,11 +10232,11 @@ var OMProgressComponent = class extends Container {
|
|
|
10648
10232
|
const empty = width - filled;
|
|
10649
10233
|
const bar = "\u2501".repeat(filled) + "\u2500".repeat(empty);
|
|
10650
10234
|
if (percent >= 90) {
|
|
10651
|
-
return
|
|
10235
|
+
return chalk12.hex(mastra.red)(bar);
|
|
10652
10236
|
} else if (percent >= 70) {
|
|
10653
|
-
return
|
|
10237
|
+
return chalk12.hex(mastra.orange)(bar);
|
|
10654
10238
|
} else {
|
|
10655
|
-
return
|
|
10239
|
+
return chalk12.hex(mastra.darkGray)(bar);
|
|
10656
10240
|
}
|
|
10657
10241
|
}
|
|
10658
10242
|
spinnerFrame = 0;
|
|
@@ -10678,21 +10262,21 @@ function formatTokensThreshold(n) {
|
|
|
10678
10262
|
return (s.endsWith(".0") ? s.slice(0, -2) : s) + "k";
|
|
10679
10263
|
}
|
|
10680
10264
|
function colorByPercent(text, percent) {
|
|
10681
|
-
if (percent >= 90) return
|
|
10682
|
-
if (percent >= 70) return
|
|
10683
|
-
return
|
|
10265
|
+
if (percent >= 90) return chalk12.hex(mastra.red)(text);
|
|
10266
|
+
if (percent >= 70) return chalk12.hex(mastra.orange)(text);
|
|
10267
|
+
return chalk12.hex("#71717a")(text);
|
|
10684
10268
|
}
|
|
10685
10269
|
function formatObservationStatus(state, compact, labelStyler) {
|
|
10686
10270
|
const percent = Math.round(state.thresholdPercent);
|
|
10687
10271
|
const pct = colorByPercent(`${percent}%`, percent);
|
|
10688
|
-
const defaultStyler = (s) =>
|
|
10272
|
+
const defaultStyler = (s) => chalk12.hex(mastra.specialGray)(s);
|
|
10689
10273
|
const styleLabel = labelStyler ?? defaultStyler;
|
|
10690
10274
|
if (compact === "percentOnly") {
|
|
10691
10275
|
return styleLabel("msg ") + pct;
|
|
10692
10276
|
}
|
|
10693
10277
|
const label = compact === "full" ? "messages" : "msg";
|
|
10694
10278
|
const fraction = `${formatTokensValue(state.pendingTokens)}/${formatTokensThreshold(state.threshold)}`;
|
|
10695
|
-
const buffered = compact !== "noBuffer" && state.buffered.observations.projectedMessageRemoval > 0 ?
|
|
10279
|
+
const buffered = compact !== "noBuffer" && state.buffered.observations.projectedMessageRemoval > 0 ? chalk12.italic(
|
|
10696
10280
|
theme.fg("muted", ` \u2193${formatTokensThreshold(state.buffered.observations.projectedMessageRemoval)}`)
|
|
10697
10281
|
) : "";
|
|
10698
10282
|
return styleLabel(`${label} `) + colorByPercent(fraction, percent) + buffered;
|
|
@@ -10700,7 +10284,7 @@ function formatObservationStatus(state, compact, labelStyler) {
|
|
|
10700
10284
|
function formatReflectionStatus(state, compact, labelStyler) {
|
|
10701
10285
|
const percent = Math.round(state.reflectionThresholdPercent);
|
|
10702
10286
|
const pct = colorByPercent(`${percent}%`, percent);
|
|
10703
|
-
const defaultStyler = (s) =>
|
|
10287
|
+
const defaultStyler = (s) => chalk12.hex(mastra.specialGray)(s);
|
|
10704
10288
|
const styleLabel = labelStyler ?? defaultStyler;
|
|
10705
10289
|
const label = styleLabel(compact === "full" ? "memory" : "mem") + " ";
|
|
10706
10290
|
if (compact === "percentOnly") {
|
|
@@ -10708,7 +10292,7 @@ function formatReflectionStatus(state, compact, labelStyler) {
|
|
|
10708
10292
|
}
|
|
10709
10293
|
const fraction = `${formatTokensValue(state.observationTokens)}/${formatTokensThreshold(state.reflectionThreshold)}`;
|
|
10710
10294
|
const savings = state.buffered.reflection.inputObservationTokens - state.buffered.reflection.observationTokens;
|
|
10711
|
-
const buffered = compact !== "noBuffer" && state.buffered.reflection.status === "complete" && savings > 0 ?
|
|
10295
|
+
const buffered = compact !== "noBuffer" && state.buffered.reflection.status === "complete" && savings > 0 ? chalk12.italic(theme.fg("muted", ` \u2193${formatTokensThreshold(savings)}`)) : "";
|
|
10712
10296
|
return label + colorByPercent(fraction, percent) + buffered;
|
|
10713
10297
|
}
|
|
10714
10298
|
function formatOMStatus(state) {
|
|
@@ -10737,7 +10321,7 @@ function formatGithubPrLabel(state, subscription) {
|
|
|
10737
10321
|
)
|
|
10738
10322
|
};
|
|
10739
10323
|
}
|
|
10740
|
-
return { plain: label, styled:
|
|
10324
|
+
return { plain: label, styled: chalk12.hex(color)(label) };
|
|
10741
10325
|
}
|
|
10742
10326
|
function formatGoalDuration(goal) {
|
|
10743
10327
|
const activeStartedAt = goal.activeStartedAt ?? (goal.activeDurationMs === void 0 ? goal.startedAt : void 0);
|
|
@@ -10766,7 +10350,8 @@ function updateStatusLine(state) {
|
|
|
10766
10350
|
const modes = state.harness.listModes();
|
|
10767
10351
|
const currentMode = modes.length > 1 ? state.harness.getCurrentMode() : void 0;
|
|
10768
10352
|
const judgeModeColor = mastra.blue;
|
|
10769
|
-
const
|
|
10353
|
+
const currentModeColor = currentMode?.metadata?.color;
|
|
10354
|
+
const mainModeColor = typeof currentModeColor === "string" ? currentModeColor : void 0;
|
|
10770
10355
|
const modeColor = isJudging ? judgeModeColor : showOMMode ? isObserving ? getObserverColor2() : getReflectorColor2() : mainModeColor;
|
|
10771
10356
|
const tintBg = modeColor ? tintHex(modeColor, 0.15) : void 0;
|
|
10772
10357
|
const badgeName = isJudging ? "judge" : showOMMode ? isObserving ? "observe" : "reflect" : currentMode ? currentMode.name || currentMode.id || "unknown" : void 0;
|
|
@@ -10787,8 +10372,8 @@ function updateStatusLine(state) {
|
|
|
10787
10372
|
const mr = Math.floor(mcr * badgeBrightness);
|
|
10788
10373
|
const mg = Math.floor(mcg * badgeBrightness);
|
|
10789
10374
|
const mb = Math.floor(mcb * badgeBrightness);
|
|
10790
|
-
const rightHalf = tintBg ?
|
|
10791
|
-
modeBadge =
|
|
10375
|
+
const rightHalf = tintBg ? chalk12.rgb(mr, mg, mb).bgHex(tintBg)("\u258C") : chalk12.rgb(mr, mg, mb)("\u258C");
|
|
10376
|
+
modeBadge = chalk12.rgb(mr, mg, mb)("\u2590") + chalk12.bgRgb(mr, mg, mb).hex("#000000").bold(badgeName.toLowerCase()) + rightHalf;
|
|
10792
10377
|
modeBadgeWidth = badgeName.length + 2;
|
|
10793
10378
|
} else if (badgeName) {
|
|
10794
10379
|
modeBadge = " " + theme.fg("dim", badgeName) + " ";
|
|
@@ -10834,7 +10419,7 @@ function updateStatusLine(state) {
|
|
|
10834
10419
|
const dirFull = !threadTitle && branch ? `${displayPath} (${branch})` : displayPath;
|
|
10835
10420
|
const dirBranchOnly = !threadTitle && branch ? branch : null;
|
|
10836
10421
|
const dirBranchShort = !threadTitle && branch && branch.length > 24 ? branch.slice(0, 12) + ".." + branch.slice(-8) : dirBranchOnly;
|
|
10837
|
-
const modelTrail = tintBg ?
|
|
10422
|
+
const modelTrail = tintBg ? chalk12.hex(tintBg)("\u258C") : "";
|
|
10838
10423
|
const styleModelId = (id) => {
|
|
10839
10424
|
if (!state.modelAuthStatus.hasAuth) {
|
|
10840
10425
|
const envVar = state.modelAuthStatus.apiKeyEnvVar;
|
|
@@ -10844,8 +10429,8 @@ function updateStatusLine(state) {
|
|
|
10844
10429
|
const fade = state.gradientAnimator.getFadeProgress();
|
|
10845
10430
|
const easedFade = fade * fade * (3 - 2 * fade);
|
|
10846
10431
|
const text = applyGradientSweep(id, state.gradientAnimator.getOffset(), modeColor, easedFade);
|
|
10847
|
-
const styled =
|
|
10848
|
-
const bg = tintBg ?
|
|
10432
|
+
const styled = chalk12.italic(text);
|
|
10433
|
+
const bg = tintBg ? chalk12.bgHex(tintBg)(styled) : styled;
|
|
10849
10434
|
return bg + modelTrail;
|
|
10850
10435
|
}
|
|
10851
10436
|
if (modeColor) {
|
|
@@ -10855,11 +10440,11 @@ function updateStatusLine(state) {
|
|
|
10855
10440
|
parseInt(modeColor.slice(5, 7), 16)
|
|
10856
10441
|
];
|
|
10857
10442
|
const idleBright = 0.8;
|
|
10858
|
-
const fgStyled =
|
|
10859
|
-
const bg = tintBg ?
|
|
10443
|
+
const fgStyled = chalk12.rgb(Math.floor(cr * idleBright), Math.floor(cg * idleBright), Math.floor(cb * idleBright)).bold.italic(id);
|
|
10444
|
+
const bg = tintBg ? chalk12.bgHex(tintBg)(fgStyled) : fgStyled;
|
|
10860
10445
|
return bg + modelTrail;
|
|
10861
10446
|
}
|
|
10862
|
-
return
|
|
10447
|
+
return chalk12.hex(mastra.specialGray).bold.italic(id);
|
|
10863
10448
|
};
|
|
10864
10449
|
let shortModeBadge = "";
|
|
10865
10450
|
let shortModeBadgeWidth = 0;
|
|
@@ -10882,8 +10467,8 @@ function updateStatusLine(state) {
|
|
|
10882
10467
|
const sr = Math.floor(mcr * sBadgeBrightness);
|
|
10883
10468
|
const sg = Math.floor(mcg * sBadgeBrightness);
|
|
10884
10469
|
const sb = Math.floor(mcb * sBadgeBrightness);
|
|
10885
|
-
const shortRightHalf = tintBg ?
|
|
10886
|
-
shortModeBadge =
|
|
10470
|
+
const shortRightHalf = tintBg ? chalk12.rgb(sr, sg, sb).bgHex(tintBg)("\u258C") : chalk12.rgb(sr, sg, sb)("\u258C");
|
|
10471
|
+
shortModeBadge = chalk12.rgb(sr, sg, sb)("\u2590") + chalk12.bgRgb(sr, sg, sb).hex("#000000").bold(shortName) + shortRightHalf;
|
|
10887
10472
|
shortModeBadgeWidth = shortName.length + 2;
|
|
10888
10473
|
} else if (badgeName) {
|
|
10889
10474
|
const shortName = badgeName.toLowerCase().charAt(0);
|
|
@@ -11198,9 +10783,9 @@ async function askCustomPackEditTarget(ctx, pack) {
|
|
|
11198
10783
|
const selectList = new SelectList(
|
|
11199
10784
|
[
|
|
11200
10785
|
{ value: "rename", label: ` Rename \u2192 ${theme.fg("text", pack.name)}` },
|
|
11201
|
-
{ value: "plan", label: ` ${
|
|
11202
|
-
{ value: "build", label: ` ${
|
|
11203
|
-
{ value: "fast", label: ` ${
|
|
10786
|
+
{ value: "plan", label: ` ${chalk12.hex(mastra.purple)("plan")} \u2192 ${theme.fg("text", pack.models.plan)}` },
|
|
10787
|
+
{ value: "build", label: ` ${chalk12.hex(mastra.green)("build")} \u2192 ${theme.fg("text", pack.models.build)}` },
|
|
10788
|
+
{ value: "fast", label: ` ${chalk12.hex(mastra.orange)("fast")} \u2192 ${theme.fg("text", pack.models.fast)}` },
|
|
11204
10789
|
{ value: "save", label: ` ${theme.fg("success", "Save")}` }
|
|
11205
10790
|
],
|
|
11206
10791
|
5,
|
|
@@ -11227,9 +10812,9 @@ async function askCustomPackEditTarget(ctx, pack) {
|
|
|
11227
10812
|
}
|
|
11228
10813
|
async function runCustomFlow(ctx, options) {
|
|
11229
10814
|
const modes = [
|
|
11230
|
-
{ id: "plan", label: "plan", color: mastra.purple },
|
|
11231
|
-
{ id: "build", label: "build", color: mastra.green },
|
|
11232
|
-
{ id: "fast", label: "fast", color: mastra.orange }
|
|
10815
|
+
{ id: "plan", label: "plan", metadata: { color: mastra.purple } },
|
|
10816
|
+
{ id: "build", label: "build", metadata: { color: mastra.green } },
|
|
10817
|
+
{ id: "fast", label: "fast", metadata: { color: mastra.orange } }
|
|
11233
10818
|
];
|
|
11234
10819
|
const name = options?.skipNamePrompt ? options?.name : await askCustomPackName(ctx, void 0);
|
|
11235
10820
|
if (!name) return null;
|
|
@@ -11243,7 +10828,7 @@ async function runCustomFlow(ctx, options) {
|
|
|
11243
10828
|
const modelId = await selectModel(
|
|
11244
10829
|
ctx,
|
|
11245
10830
|
`Select model for ${mode.label} mode`,
|
|
11246
|
-
mode.color,
|
|
10831
|
+
mode.metadata.color,
|
|
11247
10832
|
models[mode.id] || void 0
|
|
11248
10833
|
);
|
|
11249
10834
|
if (!modelId) return null;
|
|
@@ -11380,9 +10965,9 @@ function getPackDetail(pack) {
|
|
|
11380
10965
|
return theme.fg("dim", " Create a named custom pack and pick a model for each mode.");
|
|
11381
10966
|
}
|
|
11382
10967
|
return [
|
|
11383
|
-
` ${
|
|
11384
|
-
` ${
|
|
11385
|
-
` ${
|
|
10968
|
+
` ${chalk12.hex(mastra.purple)("plan")} \u2192 ${theme.fg("text", pack.models.plan)}`,
|
|
10969
|
+
` ${chalk12.hex(mastra.green)("build")} \u2192 ${theme.fg("text", pack.models.build)}`,
|
|
10970
|
+
` ${chalk12.hex(mastra.orange)("fast")} \u2192 ${theme.fg("text", pack.models.fast)}`
|
|
11386
10971
|
].join("\n");
|
|
11387
10972
|
}
|
|
11388
10973
|
async function saveCustomPackEdits(ctx, pack, previousPackId) {
|
|
@@ -12879,7 +12464,8 @@ async function handleApiKeysCommand(ctx) {
|
|
|
12879
12464
|
|
|
12880
12465
|
// src/tui/commands/settings.ts
|
|
12881
12466
|
function getCurrentModeColor3(ctx) {
|
|
12882
|
-
|
|
12467
|
+
const color = ctx.state.harness.getCurrentMode?.()?.metadata?.color;
|
|
12468
|
+
return typeof color === "string" ? color : void 0;
|
|
12883
12469
|
}
|
|
12884
12470
|
function commandExists(command) {
|
|
12885
12471
|
return new Promise((resolve3) => {
|
|
@@ -13140,9 +12726,11 @@ Using the same profile across different providers can cause compatibility issues
|
|
|
13140
12726
|
}
|
|
13141
12727
|
function applyBrowserToAgents(ctx, browser, browserSettings) {
|
|
13142
12728
|
const modes = ctx.harness.listModes();
|
|
12729
|
+
let harnessState;
|
|
13143
12730
|
for (const mode of modes) {
|
|
13144
|
-
const
|
|
13145
|
-
agent.
|
|
12731
|
+
const modeAgent = mode.agent;
|
|
12732
|
+
const agent = typeof modeAgent === "function" ? modeAgent(harnessState ??= ctx.state.harness.getState()) : modeAgent;
|
|
12733
|
+
agent?.setBrowser?.(browser);
|
|
13146
12734
|
}
|
|
13147
12735
|
ctx.harness.setState({ [ACTIVE_BROWSER_KEY]: browserSettings });
|
|
13148
12736
|
}
|
|
@@ -13404,8 +12992,7 @@ Run /browser on to apply.`);
|
|
|
13404
12992
|
return;
|
|
13405
12993
|
}
|
|
13406
12994
|
const currentMode = ctx.harness.getCurrentMode();
|
|
13407
|
-
const
|
|
13408
|
-
const browserInstance = agent.browser;
|
|
12995
|
+
const browserInstance = currentMode.agent?.browser;
|
|
13409
12996
|
if (!browserInstance) {
|
|
13410
12997
|
ctx.showError("Browser not enabled. Run /browser on first.");
|
|
13411
12998
|
return;
|
|
@@ -13415,9 +13002,10 @@ Run /browser on to apply.`);
|
|
|
13415
13002
|
ctx.showError("Current browser instance does not support exporting storage state.");
|
|
13416
13003
|
return;
|
|
13417
13004
|
}
|
|
13005
|
+
const exportableBrowser = browserInstance;
|
|
13418
13006
|
const expandedPath = exportPath.replace(/^~/, process.env.HOME || "~");
|
|
13419
13007
|
try {
|
|
13420
|
-
await
|
|
13008
|
+
await exportableBrowser.exportStorageState(expandedPath);
|
|
13421
13009
|
ctx.showInfo(`Storage state exported to: ${expandedPath}`);
|
|
13422
13010
|
} catch (error) {
|
|
13423
13011
|
ctx.showError(`Failed to export storage state: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -14977,9 +14565,6 @@ async function dispatchSlashCommand(input, state, buildCtx) {
|
|
|
14977
14565
|
case "goal":
|
|
14978
14566
|
await handleGoalCommand(buildCtx(), args);
|
|
14979
14567
|
return true;
|
|
14980
|
-
case "judge":
|
|
14981
|
-
await handleJudgeCommand(buildCtx());
|
|
14982
|
-
return true;
|
|
14983
14568
|
default: {
|
|
14984
14569
|
const customCommand = state.customSlashCommands.find((cmd) => cmd.name === command);
|
|
14985
14570
|
if (customCommand) {
|
|
@@ -15053,7 +14638,7 @@ async function handleCustomSlashCommand(state, command, args, ctx, displayText)
|
|
|
15053
14638
|
if (!isCurrentThreadActive(commandCtx)) {
|
|
15054
14639
|
const slashComp = new SlashCommandComponent(command.name, processedContent.trim());
|
|
15055
14640
|
state.allSlashCommandComponents.push(slashComp);
|
|
15056
|
-
state.chatContainer
|
|
14641
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, slashComp);
|
|
15057
14642
|
state.ui.requestRender();
|
|
15058
14643
|
}
|
|
15059
14644
|
const wrapped = `<slash-command name="${command.name}">
|
|
@@ -15067,6 +14652,126 @@ ${processedContent.trim()}
|
|
|
15067
14652
|
showError(state, `Error executing //${command.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
15068
14653
|
}
|
|
15069
14654
|
}
|
|
14655
|
+
function evaluationToJudgeResult(payload) {
|
|
14656
|
+
const decision = payload.passed ? "done" : payload.status === "paused" ? "paused" : "continue";
|
|
14657
|
+
return { decision, reason: payload.reason ?? "" };
|
|
14658
|
+
}
|
|
14659
|
+
var JUDGE_COLOR = mastraBrand.blue;
|
|
14660
|
+
var MUTED_COLOR = "#8a8a8a";
|
|
14661
|
+
var PAUSED_COLOR = "#f5a524";
|
|
14662
|
+
var WAITING_COLOR = "#8a8a8a";
|
|
14663
|
+
var JudgeDisplayComponent = class extends Container {
|
|
14664
|
+
result;
|
|
14665
|
+
turnsUsed;
|
|
14666
|
+
maxTurns;
|
|
14667
|
+
activity = [];
|
|
14668
|
+
constructor(result = null, turnsUsed = 0, maxTurns = 0) {
|
|
14669
|
+
super();
|
|
14670
|
+
this.result = result;
|
|
14671
|
+
this.turnsUsed = turnsUsed;
|
|
14672
|
+
this.maxTurns = maxTurns;
|
|
14673
|
+
this.renderContent();
|
|
14674
|
+
}
|
|
14675
|
+
addActivity(line) {
|
|
14676
|
+
if (this.activity[this.activity.length - 1] !== line) {
|
|
14677
|
+
this.activity.push(line);
|
|
14678
|
+
}
|
|
14679
|
+
if (this.activity.length > 6) {
|
|
14680
|
+
this.activity = this.activity.slice(-6);
|
|
14681
|
+
}
|
|
14682
|
+
this.renderContent();
|
|
14683
|
+
}
|
|
14684
|
+
setResult(result, turnsUsed, maxTurns) {
|
|
14685
|
+
this.result = result;
|
|
14686
|
+
this.turnsUsed = turnsUsed;
|
|
14687
|
+
this.maxTurns = maxTurns;
|
|
14688
|
+
this.renderContent();
|
|
14689
|
+
}
|
|
14690
|
+
/** Render the result of an in-loop goal evaluation chunk. */
|
|
14691
|
+
setEvaluation(payload) {
|
|
14692
|
+
this.setResult(evaluationToJudgeResult(payload), payload.iteration, payload.maxRuns);
|
|
14693
|
+
}
|
|
14694
|
+
setInterrupted() {
|
|
14695
|
+
this.setResult({ decision: "paused", reason: "Judge evaluation was interrupted." }, this.turnsUsed, this.maxTurns);
|
|
14696
|
+
}
|
|
14697
|
+
renderContent() {
|
|
14698
|
+
this.clear();
|
|
14699
|
+
const border = (char) => chalk12.hex(JUDGE_COLOR)(char);
|
|
14700
|
+
const title = chalk12.hex(JUDGE_COLOR).bold("Goal");
|
|
14701
|
+
const termWidth = getTermWidth();
|
|
14702
|
+
const innerWidth = Math.max(20, termWidth - BOX_INDENT * 2 - 4);
|
|
14703
|
+
const horizontal = "\u2500".repeat(innerWidth + 1);
|
|
14704
|
+
this.addChild(new Text(`${border("\u256D")}${border(horizontal)}${border("\u256E")}`, BOX_INDENT, 0));
|
|
14705
|
+
this.addChild(new Text(this.renderRow(this.renderHeader(title), innerWidth, border), BOX_INDENT, 0));
|
|
14706
|
+
if (!this.result && this.activity.length === 0) {
|
|
14707
|
+
this.addChild(new Text(this.renderRow(chalk12.dim("evaluating\u2026"), innerWidth, border), BOX_INDENT, 0));
|
|
14708
|
+
}
|
|
14709
|
+
for (const line of this.activity) {
|
|
14710
|
+
this.addChild(new Text(this.renderRow(this.renderActivityLine(line), innerWidth, border), BOX_INDENT, 0));
|
|
14711
|
+
}
|
|
14712
|
+
if (this.activity.length > 0 && this.result) {
|
|
14713
|
+
this.addChild(new Text(this.renderRow("", innerWidth, border), BOX_INDENT, 0));
|
|
14714
|
+
}
|
|
14715
|
+
if (this.result) {
|
|
14716
|
+
for (const line of this.wrapLine(this.result.reason, innerWidth)) {
|
|
14717
|
+
this.addChild(new Text(this.renderRow(chalk12.dim(line), innerWidth, border), BOX_INDENT, 0));
|
|
14718
|
+
}
|
|
14719
|
+
}
|
|
14720
|
+
this.addChild(new Text(`${border("\u2570")}${border(horizontal)}${border("\u256F")}`, BOX_INDENT, 0));
|
|
14721
|
+
}
|
|
14722
|
+
renderActivityLine(line) {
|
|
14723
|
+
const toolName = getActivityToolName(line);
|
|
14724
|
+
if (!toolName) return theme.fg("dim", `\u2022 ${line}`);
|
|
14725
|
+
const rest = line.slice(toolName.length);
|
|
14726
|
+
return `${theme.fg("dim", "\u2022 ")}${theme.fg("dim", theme.italic(toolName))}${theme.fg("dim", rest)}`;
|
|
14727
|
+
}
|
|
14728
|
+
renderHeader(title) {
|
|
14729
|
+
if (!this.result) {
|
|
14730
|
+
return `${title} \u25CC ${chalk12.hex(WAITING_COLOR).bold("evaluating")}`;
|
|
14731
|
+
}
|
|
14732
|
+
const decisionIcon = this.result.decision === "done" ? "\u25CF" : this.result.decision === "paused" ? "!" : this.result.decision === "waiting" ? "\u25CC" : "\u25CB";
|
|
14733
|
+
const decisionText = getDecisionText(this.result.decision);
|
|
14734
|
+
const turnInfo = this.maxTurns > 0 ? chalk12.hex(MUTED_COLOR)(`(${this.turnsUsed}/${this.maxTurns})`) : "";
|
|
14735
|
+
return `${title} ${decisionIcon} ${decisionText}${turnInfo ? ` ${turnInfo}` : ""}`;
|
|
14736
|
+
}
|
|
14737
|
+
renderRow(text, width, border) {
|
|
14738
|
+
const content = this.padLine(text, width);
|
|
14739
|
+
return `${border("\u2502")} ${content}${border("\u2502")}`;
|
|
14740
|
+
}
|
|
14741
|
+
wrapLine(text, width) {
|
|
14742
|
+
const lines = [];
|
|
14743
|
+
let remaining = text;
|
|
14744
|
+
while (remaining.length > width) {
|
|
14745
|
+
const breakAt = remaining.lastIndexOf(" ", width);
|
|
14746
|
+
const splitAt = breakAt > 0 ? breakAt : width;
|
|
14747
|
+
lines.push(remaining.slice(0, splitAt));
|
|
14748
|
+
remaining = remaining.slice(splitAt).trimStart();
|
|
14749
|
+
}
|
|
14750
|
+
lines.push(remaining);
|
|
14751
|
+
return lines;
|
|
14752
|
+
}
|
|
14753
|
+
padLine(text, width) {
|
|
14754
|
+
const visibleLength = stripAnsi(text).length;
|
|
14755
|
+
if (visibleLength >= width) {
|
|
14756
|
+
return stripAnsi(text).slice(0, width);
|
|
14757
|
+
}
|
|
14758
|
+
return text + " ".repeat(width - visibleLength);
|
|
14759
|
+
}
|
|
14760
|
+
getChatSpacingKind() {
|
|
14761
|
+
return "other";
|
|
14762
|
+
}
|
|
14763
|
+
};
|
|
14764
|
+
function getActivityToolName(line) {
|
|
14765
|
+
if (line.startsWith("find files ")) return "find files";
|
|
14766
|
+
const [toolName] = line.split(" ");
|
|
14767
|
+
return toolName || null;
|
|
14768
|
+
}
|
|
14769
|
+
function getDecisionText(decision) {
|
|
14770
|
+
if (decision === "done") return chalk12.hex("#16c858").bold("done");
|
|
14771
|
+
if (decision === "paused") return chalk12.hex(PAUSED_COLOR).bold("paused");
|
|
14772
|
+
if (decision === "waiting") return chalk12.hex(WAITING_COLOR).bold("waiting");
|
|
14773
|
+
return chalk12.hex(JUDGE_COLOR).bold("continue");
|
|
14774
|
+
}
|
|
15070
14775
|
|
|
15071
14776
|
// src/tui/prune-chat.ts
|
|
15072
14777
|
var MAX_CHILDREN = 5e3;
|
|
@@ -15114,6 +14819,7 @@ function handleAgentStart(ctx) {
|
|
|
15114
14819
|
}
|
|
15115
14820
|
function handleAgentEnd(ctx) {
|
|
15116
14821
|
const { state } = ctx;
|
|
14822
|
+
state.goalManager.stopActiveTimer();
|
|
15117
14823
|
if (state.gradientAnimator) {
|
|
15118
14824
|
state.gradientAnimator.fadeOut();
|
|
15119
14825
|
}
|
|
@@ -15134,10 +14840,7 @@ function handleAgentEnd(ctx) {
|
|
|
15134
14840
|
ctx.updateStatusLine();
|
|
15135
14841
|
state.ui.requestRender();
|
|
15136
14842
|
ctx.notify("agent_done");
|
|
15137
|
-
|
|
15138
|
-
return;
|
|
15139
|
-
}
|
|
15140
|
-
maybeGoalContinuation(ctx);
|
|
14843
|
+
drainQueuedAction(ctx);
|
|
15141
14844
|
}
|
|
15142
14845
|
function drainQueuedAction(ctx) {
|
|
15143
14846
|
const { state } = ctx;
|
|
@@ -15203,8 +14906,7 @@ function handleAgentAborted(ctx) {
|
|
|
15203
14906
|
state.streamingComponent = void 0;
|
|
15204
14907
|
state.streamingMessage = void 0;
|
|
15205
14908
|
} else if (state.userInitiatedAbort) {
|
|
15206
|
-
state
|
|
15207
|
-
state.chatContainer.addChild(new Spacer(1));
|
|
14909
|
+
showError(state, "Interrupted");
|
|
15208
14910
|
}
|
|
15209
14911
|
state.userInitiatedAbort = false;
|
|
15210
14912
|
if (state.activeGoalJudge) {
|
|
@@ -15250,117 +14952,46 @@ function handleAgentError(ctx) {
|
|
|
15250
14952
|
state.ui.requestRender();
|
|
15251
14953
|
}
|
|
15252
14954
|
function removeJudgeComponent(state, component) {
|
|
15253
|
-
|
|
15254
|
-
|
|
15255
|
-
if (index >= 0) {
|
|
15256
|
-
children.splice(index, 1);
|
|
15257
|
-
state.chatContainer.invalidate?.();
|
|
14955
|
+
if (state.chatContainer.children.includes(component)) {
|
|
14956
|
+
state.chatContainer.removeChild(component);
|
|
15258
14957
|
}
|
|
15259
14958
|
}
|
|
15260
|
-
function
|
|
14959
|
+
function handleGoalEvaluation(ctx, payload) {
|
|
15261
14960
|
const { state } = ctx;
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
|
|
15269
|
-
|
|
14961
|
+
let activeGoalJudge = state.activeGoalJudge;
|
|
14962
|
+
if (!activeGoalJudge) {
|
|
14963
|
+
const goal = state.goalManager.getGoal();
|
|
14964
|
+
const component = new JudgeDisplayComponent(null, payload.iteration, payload.maxRuns);
|
|
14965
|
+
activeGoalJudge = {
|
|
14966
|
+
modelId: goal?.judgeModelId ?? "",
|
|
14967
|
+
abortController: new AbortController(),
|
|
14968
|
+
component
|
|
14969
|
+
};
|
|
14970
|
+
state.activeGoalJudge = activeGoalJudge;
|
|
14971
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, component);
|
|
15270
14972
|
}
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
const activeGoalJudge = { modelId: goal.judgeModelId, abortController, component: judgeComponent };
|
|
15274
|
-
state.activeGoalJudge = activeGoalJudge;
|
|
15275
|
-
state.chatContainer.addChild(judgeComponent);
|
|
15276
|
-
state.gradientAnimator.start();
|
|
14973
|
+
activeGoalJudge.component.setEvaluation(payload);
|
|
14974
|
+
state.goalManager.applyEvaluation({ runsUsed: payload.iteration, status: payload.status });
|
|
15277
14975
|
ctx.updateStatusLine();
|
|
15278
14976
|
state.ui.requestRender();
|
|
15279
|
-
|
|
15280
|
-
|
|
15281
|
-
|
|
15282
|
-
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
|
|
15289
|
-
|
|
15290
|
-
|
|
15291
|
-
const currentGoal = state.goalManager.getGoal();
|
|
15292
|
-
if (!currentGoal || currentGoal.id !== evaluatedGoalId) {
|
|
15293
|
-
removeJudgeComponent(state, judgeComponent);
|
|
15294
|
-
return;
|
|
15295
|
-
}
|
|
15296
|
-
if (judgeResult) {
|
|
15297
|
-
judgeComponent.setResult(judgeResult, currentGoal.turnsUsed, currentGoal.maxTurns);
|
|
15298
|
-
state.ui.requestRender();
|
|
15299
|
-
}
|
|
15300
|
-
if (abortController.signal.aborted) {
|
|
15301
|
-
state.userInitiatedAbort = false;
|
|
15302
|
-
return;
|
|
15303
|
-
}
|
|
15304
|
-
if (continuation) {
|
|
15305
|
-
if (currentGoal.status !== "active") {
|
|
15306
|
-
return;
|
|
15307
|
-
}
|
|
15308
|
-
if (drainQueuedAction(ctx)) {
|
|
15309
|
-
return;
|
|
15310
|
-
}
|
|
15311
|
-
try {
|
|
15312
|
-
await state.harness.sendSignal({
|
|
15313
|
-
type: "system-reminder",
|
|
15314
|
-
contents: continuation,
|
|
15315
|
-
attributes: { type: "goal-judge" },
|
|
15316
|
-
metadata: {
|
|
15317
|
-
goalId: currentGoal.id,
|
|
15318
|
-
turnsUsed: currentGoal.turnsUsed,
|
|
15319
|
-
maxTurns: currentGoal.maxTurns,
|
|
15320
|
-
judgeModelId: currentGoal.judgeModelId
|
|
15321
|
-
}
|
|
15322
|
-
}).accepted;
|
|
15323
|
-
} catch (error) {
|
|
15324
|
-
ctx.showError(`Failed to send goal continuation: ${error instanceof Error ? error.message : String(error)}`);
|
|
15325
|
-
}
|
|
15326
|
-
} else {
|
|
15327
|
-
if (judgeResult) {
|
|
15328
|
-
const harness = state.harness;
|
|
15329
|
-
await harness.saveSystemReminderMessage?.({
|
|
15330
|
-
reminderType: "goal-judge",
|
|
15331
|
-
message: `${judgeResult.decision} (${currentGoal.turnsUsed}/${currentGoal.maxTurns})
|
|
15332
|
-
${judgeResult.reason}`
|
|
15333
|
-
});
|
|
15334
|
-
}
|
|
15335
|
-
if (currentGoal.status === "paused") {
|
|
15336
|
-
showInfo(
|
|
15337
|
-
state,
|
|
15338
|
-
`Goal paused (attempt ${currentGoal.turnsUsed}/${currentGoal.maxTurns}). Use /goal resume to continue.`
|
|
15339
|
-
);
|
|
15340
|
-
}
|
|
15341
|
-
if (judgeResult?.decision === "done" && currentGoal.id === state.planStartedGoalId) {
|
|
15342
|
-
const goalId = state.planStartedGoalId;
|
|
15343
|
-
state.planStartedGoalId = void 0;
|
|
15344
|
-
try {
|
|
15345
|
-
await state.harness.switchMode({ modeId: "plan" });
|
|
15346
|
-
} catch (error) {
|
|
15347
|
-
ctx.showError(`Failed to switch to Plan mode: ${error instanceof Error ? error.message : String(error)}`);
|
|
15348
|
-
state.planStartedGoalId = goalId;
|
|
15349
|
-
}
|
|
15350
|
-
}
|
|
15351
|
-
}
|
|
15352
|
-
}).catch(() => {
|
|
15353
|
-
}).finally(() => {
|
|
15354
|
-
if (state.activeGoalJudge === activeGoalJudge) {
|
|
15355
|
-
state.activeGoalJudge = void 0;
|
|
14977
|
+
if (payload.status !== "active") {
|
|
14978
|
+
state.activeGoalJudge = void 0;
|
|
14979
|
+
}
|
|
14980
|
+
if (payload.status === "done") {
|
|
14981
|
+
const goal = state.goalManager.getGoal();
|
|
14982
|
+
if (goal && goal.id === state.planStartedGoalId) {
|
|
14983
|
+
const goalId = state.planStartedGoalId;
|
|
14984
|
+
state.planStartedGoalId = void 0;
|
|
14985
|
+
state.harness.switchMode({ modeId: "plan" }).catch((error) => {
|
|
14986
|
+
ctx.showError(`Failed to switch to Plan mode: ${error instanceof Error ? error.message : String(error)}`);
|
|
14987
|
+
state.planStartedGoalId = goalId;
|
|
14988
|
+
});
|
|
15356
14989
|
}
|
|
15357
|
-
|
|
15358
|
-
ctx.updateStatusLine();
|
|
15359
|
-
state.ui.requestRender();
|
|
15360
|
-
});
|
|
14990
|
+
}
|
|
15361
14991
|
}
|
|
15362
14992
|
function getCurrentModeColor4(ctx) {
|
|
15363
|
-
|
|
14993
|
+
const color = ctx.state.harness.getCurrentMode?.()?.metadata?.color;
|
|
14994
|
+
return typeof color === "string" ? color : void 0;
|
|
15364
14995
|
}
|
|
15365
14996
|
function getTrailingContentParts(message) {
|
|
15366
14997
|
let lastToolIndex = -1;
|
|
@@ -15377,6 +15008,7 @@ function getTrailingContentParts(message) {
|
|
|
15377
15008
|
return message.content.slice(lastToolIndex + 1);
|
|
15378
15009
|
}
|
|
15379
15010
|
var HIDDEN_REACTIVE_SIGNAL_TAGS2 = /* @__PURE__ */ new Set(["github-subscribe-pr", "github-unsubscribe-pr"]);
|
|
15011
|
+
var GOAL_STATE_SIGNAL_ID2 = "goal";
|
|
15380
15012
|
function shouldRenderReactiveSignal2(tagName) {
|
|
15381
15013
|
return !HIDDEN_REACTIVE_SIGNAL_TAGS2.has(tagName);
|
|
15382
15014
|
}
|
|
@@ -15585,7 +15217,7 @@ function handleMessageUpdate(ctx, message) {
|
|
|
15585
15217
|
const notificationSummaryParts = message.content.map(toStreamedNotificationSummaryPart).filter((part) => part !== void 0);
|
|
15586
15218
|
const notificationParts = message.content.map(toStreamedNotificationPart).filter((part) => part !== void 0);
|
|
15587
15219
|
for (const stateSignal of stateSignalParts) {
|
|
15588
|
-
if (stateSignal.stateId === TASKS_STATE_ID) continue;
|
|
15220
|
+
if (stateSignal.stateId === TASKS_STATE_ID || stateSignal.stateId === GOAL_STATE_SIGNAL_ID2) continue;
|
|
15589
15221
|
const stateSignalKey = `state:${message.id}:${stateSignal.cacheKey ?? ""}:${stateSignal.stateId}:${stateSignal.mode}:${stateSignal.version ?? ""}:${stateSignal.message ?? ""}`;
|
|
15590
15222
|
if (!state.currentRunSystemReminderKeys.has(stateSignalKey)) {
|
|
15591
15223
|
state.currentRunSystemReminderKeys.add(stateSignalKey);
|
|
@@ -15744,23 +15376,23 @@ function getInsertIndexBeforeStreaming(ctx) {
|
|
|
15744
15376
|
}
|
|
15745
15377
|
function addChildBeforeStreaming(ctx, child) {
|
|
15746
15378
|
const insertIndex = getInsertIndexBeforeStreaming(ctx);
|
|
15747
|
-
|
|
15748
|
-
ctx.state.chatContainer.children.splice(insertIndex, 0, child);
|
|
15749
|
-
ctx.state.chatContainer.invalidate();
|
|
15750
|
-
return;
|
|
15751
|
-
}
|
|
15752
|
-
ctx.state.chatContainer.addChild(child);
|
|
15379
|
+
insertChatComponentWithBoundarySpacing(ctx.state.chatContainer, child, insertIndex);
|
|
15753
15380
|
}
|
|
15754
15381
|
function isImmediatelyBeforeStreamingInsert(ctx, child) {
|
|
15755
15382
|
const insertIndex = getInsertIndexBeforeStreaming(ctx);
|
|
15756
|
-
|
|
15383
|
+
for (let i = insertIndex - 1; i >= 0; i--) {
|
|
15384
|
+
if (!isChatBoundarySpacer(ctx.state.chatContainer.children[i])) {
|
|
15385
|
+
return ctx.state.chatContainer.children[i] === child;
|
|
15386
|
+
}
|
|
15387
|
+
}
|
|
15388
|
+
return false;
|
|
15757
15389
|
}
|
|
15758
15390
|
function removeChatChild(ctx, child) {
|
|
15759
15391
|
if (!child) return;
|
|
15760
15392
|
const idx = ctx.state.chatContainer.children.indexOf(child);
|
|
15761
15393
|
if (idx >= 0) {
|
|
15762
15394
|
ctx.state.chatContainer.children.splice(idx, 1);
|
|
15763
|
-
ctx.state.chatContainer
|
|
15395
|
+
reconcileChatBoundarySpacers(ctx.state.chatContainer);
|
|
15764
15396
|
}
|
|
15765
15397
|
}
|
|
15766
15398
|
function handleOMObservationStart(ctx, cycleId, tokensToObserve) {
|
|
@@ -16552,12 +16184,12 @@ var CustomEditor = class extends Editor {
|
|
|
16552
16184
|
const promptBrightness = isPromptAnimated ? Math.max(chevronBrightness, dotBrightness) : 1;
|
|
16553
16185
|
if (this._cachedModeColorHex !== color) {
|
|
16554
16186
|
this._cachedModeColorHex = color;
|
|
16555
|
-
this._cachedColorFn =
|
|
16187
|
+
this._cachedColorFn = chalk12.hex(color);
|
|
16556
16188
|
}
|
|
16557
16189
|
const colorFn = this._cachedColorFn;
|
|
16558
16190
|
const b = colorFn;
|
|
16559
16191
|
const [r, g, bValue] = parseHex(color);
|
|
16560
|
-
const prompt =
|
|
16192
|
+
const prompt = chalk12.bold.rgb(
|
|
16561
16193
|
Math.round(r * promptBrightness),
|
|
16562
16194
|
Math.round(g * promptBrightness),
|
|
16563
16195
|
Math.round(bValue * promptBrightness)
|
|
@@ -16988,7 +16620,8 @@ function createTUIState(options) {
|
|
|
16988
16620
|
if (result.activeGoalJudge) {
|
|
16989
16621
|
return mastra.blue;
|
|
16990
16622
|
}
|
|
16991
|
-
|
|
16623
|
+
const color = options.harness.getCurrentMode()?.metadata?.color;
|
|
16624
|
+
return typeof color === "string" ? color : void 0;
|
|
16992
16625
|
};
|
|
16993
16626
|
return result;
|
|
16994
16627
|
}
|
|
@@ -17091,7 +16724,10 @@ async function dispatchEvent(event, ectx, state) {
|
|
|
17091
16724
|
state.activeGithubPrSubscriptions = getGithubPrSubscriptionsFromMetadata(metadata);
|
|
17092
16725
|
state.githubPrPollingActive = false;
|
|
17093
16726
|
state.githubPrGradientAnimator?.stop();
|
|
17094
|
-
state.goalManager
|
|
16727
|
+
await state.goalManager.loadFromThread(state);
|
|
16728
|
+
if (!state.goalManager.getGoal()) {
|
|
16729
|
+
state.goalManager.loadFromThreadMetadata(metadata);
|
|
16730
|
+
}
|
|
17095
16731
|
}
|
|
17096
16732
|
break;
|
|
17097
16733
|
}
|
|
@@ -17237,6 +16873,10 @@ async function dispatchEvent(event, ectx, state) {
|
|
|
17237
16873
|
}
|
|
17238
16874
|
break;
|
|
17239
16875
|
}
|
|
16876
|
+
case "goal_evaluation": {
|
|
16877
|
+
handleGoalEvaluation(ectx, event.payload);
|
|
16878
|
+
break;
|
|
16879
|
+
}
|
|
17240
16880
|
case "tool_suspended": {
|
|
17241
16881
|
const payload = event.suspendPayload ?? {};
|
|
17242
16882
|
if (event.toolName === "request_access" || payload.kind === "sandbox_access_request") {
|
|
@@ -17399,7 +17039,7 @@ function gradientChar(ch, colIdx, totalCols) {
|
|
|
17399
17039
|
const segment = Math.min(Math.floor(t * segmentCount), segmentCount - 1);
|
|
17400
17040
|
const frac = t * segmentCount - segment;
|
|
17401
17041
|
const [r, g, b] = lerpColor(GRADIENT_STOPS[segment], GRADIENT_STOPS[segment + 1], frac);
|
|
17402
|
-
return
|
|
17042
|
+
return chalk12.rgb(r, g, b)(ch);
|
|
17403
17043
|
}
|
|
17404
17044
|
function colorLine(line) {
|
|
17405
17045
|
const chars = [...line];
|
|
@@ -17550,7 +17190,7 @@ var TaskProgressComponent = class extends Container {
|
|
|
17550
17190
|
switch (task.status) {
|
|
17551
17191
|
case "completed": {
|
|
17552
17192
|
const icon = theme.fg("dim", "\u2713");
|
|
17553
|
-
const text =
|
|
17193
|
+
const text = chalk12.strikethrough(theme.fg("dim", task.content));
|
|
17554
17194
|
return `${icon} ${text}`;
|
|
17555
17195
|
}
|
|
17556
17196
|
case "in_progress": {
|
|
@@ -17570,7 +17210,7 @@ var TaskProgressComponent = class extends Container {
|
|
|
17570
17210
|
switch (task.status) {
|
|
17571
17211
|
case "completed": {
|
|
17572
17212
|
const icon = theme.fg("success", "\u2713");
|
|
17573
|
-
const text =
|
|
17213
|
+
const text = chalk12.hex(theme.getTheme().success).strikethrough(task.content);
|
|
17574
17214
|
return `${indent}${icon} ${text}`;
|
|
17575
17215
|
}
|
|
17576
17216
|
case "in_progress": {
|
|
@@ -17731,6 +17371,9 @@ function abortActiveGoalJudge(state) {
|
|
|
17731
17371
|
state.userInitiatedAbort = true;
|
|
17732
17372
|
activeGoalJudge.abortController.abort();
|
|
17733
17373
|
activeGoalJudge.component.setInterrupted();
|
|
17374
|
+
state.goalManager.pause();
|
|
17375
|
+
void state.goalManager.saveToThread(state);
|
|
17376
|
+
state.activeGoalJudge = void 0;
|
|
17734
17377
|
state.ui.requestRender();
|
|
17735
17378
|
return true;
|
|
17736
17379
|
}
|
|
@@ -17855,10 +17498,10 @@ function setupAutocomplete(state) {
|
|
|
17855
17498
|
{ value: "status", label: "status", description: "Show current goal status" },
|
|
17856
17499
|
{ value: "pause", label: "pause", description: "Pause the goal continuation loop" },
|
|
17857
17500
|
{ value: "resume", label: "resume", description: "Resume the current goal" },
|
|
17858
|
-
{ value: "clear", label: "clear", description: "Clear the current goal" }
|
|
17501
|
+
{ value: "clear", label: "clear", description: "Clear the current goal" },
|
|
17502
|
+
{ value: "judge", label: "judge", description: "Set the goal judge model and max attempts" }
|
|
17859
17503
|
].filter((command) => command.value.startsWith(argumentPrefix.toLowerCase()))
|
|
17860
17504
|
},
|
|
17861
|
-
{ name: "judge", description: "Set goal judge defaults" },
|
|
17862
17505
|
{ name: "exit", description: "Exit the TUI" },
|
|
17863
17506
|
{ name: "help", description: "Show available commands" }
|
|
17864
17507
|
];
|
|
@@ -18087,7 +17730,6 @@ var ShellStreamComponent = class extends Container {
|
|
|
18087
17730
|
}
|
|
18088
17731
|
rebuild() {
|
|
18089
17732
|
this.clear();
|
|
18090
|
-
this.addChild(new Spacer(1));
|
|
18091
17733
|
const border = (char) => theme.bold(theme.fg("accent", char));
|
|
18092
17734
|
const termWidth = getTermWidth();
|
|
18093
17735
|
const maxLineWidth = termWidth - 6;
|
|
@@ -18125,6 +17767,9 @@ var ShellStreamComponent = class extends Container {
|
|
|
18125
17767
|
}
|
|
18126
17768
|
this.invalidate();
|
|
18127
17769
|
}
|
|
17770
|
+
getChatSpacingKind() {
|
|
17771
|
+
return "other";
|
|
17772
|
+
}
|
|
18128
17773
|
};
|
|
18129
17774
|
|
|
18130
17775
|
// src/tui/shell-result.ts
|
|
@@ -18188,7 +17833,7 @@ async function handleShellPassthrough(state, command) {
|
|
|
18188
17833
|
component.setExpanded(true);
|
|
18189
17834
|
}
|
|
18190
17835
|
state.allShellComponents.push(component);
|
|
18191
|
-
state.chatContainer
|
|
17836
|
+
insertChatComponentWithBoundarySpacing(state.chatContainer, component);
|
|
18192
17837
|
state.ui.requestRender();
|
|
18193
17838
|
try {
|
|
18194
17839
|
const { invocation, subprocess } = await createShellPassthroughSubprocess(command, loadSettings().shellPassthrough);
|
|
@@ -18242,7 +17887,10 @@ async function syncInitialThreadState(state) {
|
|
|
18242
17887
|
}
|
|
18243
17888
|
const metadata = initThread?.metadata;
|
|
18244
17889
|
state.activeGithubPrSubscriptions = getGithubPrSubscriptionsFromMetadata(metadata);
|
|
18245
|
-
state.goalManager.
|
|
17890
|
+
await state.goalManager.loadFromThread(state);
|
|
17891
|
+
if (!state.goalManager.getGoal()) {
|
|
17892
|
+
state.goalManager.loadFromThreadMetadata(metadata);
|
|
17893
|
+
}
|
|
18246
17894
|
}
|
|
18247
17895
|
function shouldUseCaffeinate() {
|
|
18248
17896
|
return process.platform === "darwin" && process.env.MASTRACODE_DISABLE_CAFFEINATE !== "1";
|
|
@@ -19129,7 +18777,7 @@ var MastraTUI = class _MastraTUI {
|
|
|
19129
18777
|
onSelectModel: async (title, modeColor) => {
|
|
19130
18778
|
const availableModels = await this.state.harness.listAvailableModels();
|
|
19131
18779
|
if (availableModels.length === 0) return void 0;
|
|
19132
|
-
return new Promise((
|
|
18780
|
+
return new Promise((resolveModel) => {
|
|
19133
18781
|
const selector = new ModelSelectorComponent({
|
|
19134
18782
|
tui: this.state.ui,
|
|
19135
18783
|
models: availableModels,
|
|
@@ -19139,11 +18787,11 @@ var MastraTUI = class _MastraTUI {
|
|
|
19139
18787
|
onSelect: async (model) => {
|
|
19140
18788
|
this.state.ui.hideOverlay();
|
|
19141
18789
|
await promptForApiKeyIfNeeded(this.state.ui, model, this.state.authStorage);
|
|
19142
|
-
|
|
18790
|
+
resolveModel(model.id);
|
|
19143
18791
|
},
|
|
19144
18792
|
onCancel: () => {
|
|
19145
18793
|
this.state.ui.hideOverlay();
|
|
19146
|
-
|
|
18794
|
+
resolveModel(void 0);
|
|
19147
18795
|
}
|
|
19148
18796
|
});
|
|
19149
18797
|
showModalOverlay(this.state.ui, selector, { maxHeight: "75%" });
|
|
@@ -19245,7 +18893,8 @@ var MastraTUI = class _MastraTUI {
|
|
|
19245
18893
|
const tools = this.state.allToolComponents.filter(
|
|
19246
18894
|
(tool) => typeof tool.setQuietModeDisplay === "function"
|
|
19247
18895
|
);
|
|
19248
|
-
const
|
|
18896
|
+
const color = this.state.harness?.getCurrentMode?.()?.metadata?.color;
|
|
18897
|
+
const modeColor = typeof color === "string" ? color : void 0;
|
|
19249
18898
|
for (const tool of tools) {
|
|
19250
18899
|
tool.setCompactToolModeColor?.(modeColor);
|
|
19251
18900
|
tool.setQuietModeDisplay?.(enabled ? "quiet" : "normal");
|
|
@@ -19363,7 +19012,7 @@ Would you like to update now?`;
|
|
|
19363
19012
|
},
|
|
19364
19013
|
this.state.ui
|
|
19365
19014
|
);
|
|
19366
|
-
this.state.chatContainer
|
|
19015
|
+
insertChatComponentWithBoundarySpacing(this.state.chatContainer, component);
|
|
19367
19016
|
this.state.activeInlineQuestion = component;
|
|
19368
19017
|
component.focused = true;
|
|
19369
19018
|
this.state.ui.requestRender();
|
|
@@ -19391,5 +19040,5 @@ Would you like to update now?`;
|
|
|
19391
19040
|
};
|
|
19392
19041
|
|
|
19393
19042
|
export { AssistantMessageComponent, LoginDialogComponent, LoginSelectorComponent, MastraTUI, ModelSelectorComponent, OMProgressComponent, ToolExecutionComponentEnhanced, UserMessageComponent, createTUIState, detectTerminalTheme, formatOMStatus, getCurrentVersion };
|
|
19394
|
-
//# sourceMappingURL=chunk-
|
|
19395
|
-
//# sourceMappingURL=chunk-
|
|
19043
|
+
//# sourceMappingURL=chunk-GKGPZBID.js.map
|
|
19044
|
+
//# sourceMappingURL=chunk-GKGPZBID.js.map
|