blun-king-cli 9.1.527 → 9.1.536
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 +61 -0
- package/LIESMICH.txt +36 -1
- package/README.md +35 -1
- package/bin/agent-resume-snapshot.cjs +31 -0
- package/bin/assistant-message-offload-policy.cjs +21 -2
- package/bin/codebase-search-runtime.cjs +23 -0
- package/bin/empty-response-retry-policy.cjs +29 -0
- package/bin/fredrik-glm-provider.cjs +256 -0
- package/bin/history-offload-pressure-policy.cjs +33 -0
- package/bin/programmatic-context-isolation.cjs +25 -0
- package/bin/programmatic-tool-runtime.mjs +301 -0
- package/bin/skill-activation-performance-policy.cjs +9 -0
- package/bin/structured-subagent-output.cjs +252 -0
- package/bin/telegram-direct-focus-policy.cjs +25 -1
- package/bin/todo-list-turn-policy.cjs +111 -1
- package/bin/tool-result-offload-policy.cjs +29 -0
- package/bin/turn-thinking-policy.cjs +6 -15
- package/bin/turn-tool-performance-policy.cjs +5 -4
- package/bin/user-message-offload-policy.cjs +10 -1
- package/blun.mjs +656 -127
- package/codebase-index/README.md +70 -0
- package/codebase-index/codebase_index.py +358 -0
- package/fredrik-glm-profile.toml.example +26 -0
- package/package.json +24 -3
- package/scripts/check-active-work-steer-regression.js +46 -0
- package/scripts/check-codebase-search-packaging-regression.js +92 -0
- package/scripts/check-current-turn-read-pin-mutation-regression.js +72 -0
- package/scripts/check-current-turn-read-pin-regression.js +94 -0
- package/scripts/check-deepseek-native-max-regression.js +49 -0
- package/scripts/check-empty-response-effort-downgrade-regression.js +48 -0
- package/scripts/check-fredrik-glm-mutation-regression.js +18 -0
- package/scripts/check-fredrik-glm-regression.js +169 -0
- package/scripts/check-history-pressure-offload-regression.js +77 -0
- package/scripts/check-programmatic-context-isolation-regression.js +193 -0
- package/scripts/check-programmatic-tool-regression.js +294 -0
- package/scripts/check-resume-replay-regression.js +2 -0
- package/scripts/check-startup-swarm-command-regression.js +24 -0
- package/scripts/check-structured-subagent-output-regression.js +331 -0
- package/scripts/check-telegram-direct-work-resume-regression.js +53 -0
- package/scripts/check-todo-progress-regression.js +416 -0
- package/scripts/check-tool-schema-capacity-regression.js +40 -0
- package/scripts/programmatic-tool-runtime.test.mjs +365 -0
- package/scripts/structured-subagent-output.test.cjs +170 -0
package/blun.mjs
CHANGED
|
@@ -16,6 +16,7 @@ import sessionScrollbackArchive from "./bin/session-scrollback-archive.cjs";
|
|
|
16
16
|
import sessionReplayWindowPolicy from "./bin/session-replay-window-policy.cjs";
|
|
17
17
|
import globPatternPolicy from "./bin/glob-pattern-policy.cjs";
|
|
18
18
|
import userHomePathPolicy from "./bin/user-home-path-policy.cjs";
|
|
19
|
+
import fredrikGlmProviderPolicy from "./bin/fredrik-glm-provider.cjs";
|
|
19
20
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
20
21
|
import * as fs$16 from "node:fs";
|
|
21
22
|
import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
@@ -56,6 +57,18 @@ const { SessionScrollbackArchive, sessionScrollbackArchiveDirectory } = sessionS
|
|
|
56
57
|
const { replayWindowStartIndex, resolveReplayActiveTurnCount } = sessionReplayWindowPolicy;
|
|
57
58
|
const { globPatternError } = globPatternPolicy;
|
|
58
59
|
const { unsupportedUserHomePathError } = userHomePathPolicy;
|
|
60
|
+
const {
|
|
61
|
+
PROVIDER_ID: FREDRIK_GLM_PROVIDER_ID,
|
|
62
|
+
PROVIDER_TYPE: FREDRIK_GLM_PROVIDER_TYPE,
|
|
63
|
+
MODEL_EFFORTS: FREDRIK_GLM_EFFORTS,
|
|
64
|
+
configuredModels: configuredFredrikGlmModels,
|
|
65
|
+
configuredProvider: configuredFredrikGlmProvider,
|
|
66
|
+
isAllowedRuntimeAlias: isAllowedFredrikRuntimeAlias,
|
|
67
|
+
isConfiguredAlias: isConfiguredFredrikGlmAlias,
|
|
68
|
+
normalizeEffort: normalizeFredrikGlmEffort,
|
|
69
|
+
requestControls: fredrikGlmRequestControls,
|
|
70
|
+
readApiKeyFile: readFredrikGlmApiKeyFile
|
|
71
|
+
} = fredrikGlmProviderPolicy;
|
|
59
72
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
60
73
|
import { StringDecoder } from "node:string_decoder";
|
|
61
74
|
import co from "node:assert";
|
|
@@ -2720,6 +2733,7 @@ var init_blun = __esmMin((() => {
|
|
|
2720
2733
|
_defaultHeaders;
|
|
2721
2734
|
_generationKwargs;
|
|
2722
2735
|
_supportEfforts;
|
|
2736
|
+
_openAICompatible;
|
|
2723
2737
|
_client;
|
|
2724
2738
|
_clientFactory;
|
|
2725
2739
|
_files;
|
|
@@ -2733,6 +2747,7 @@ var init_blun = __esmMin((() => {
|
|
|
2733
2747
|
this._stream = options.stream ?? true;
|
|
2734
2748
|
this._generationKwargs = { ...options.generationKwargs };
|
|
2735
2749
|
this._supportEfforts = options.supportEfforts ?? [];
|
|
2750
|
+
this._openAICompatible = options.openAICompatible === true;
|
|
2736
2751
|
this._client = this._apiKey === void 0 ? void 0 : createFetchHttpClient({
|
|
2737
2752
|
apiKey: this._apiKey,
|
|
2738
2753
|
baseUrl: this._baseUrl,
|
|
@@ -2844,8 +2859,17 @@ var init_blun = __esmMin((() => {
|
|
|
2844
2859
|
delete requestExtraBody["model"];
|
|
2845
2860
|
delete requestExtraBody["messages"];
|
|
2846
2861
|
if (!thinkingDisabled && thinking?.keep !== void 0) requestExtraBody["thinking"] = { keep: thinking.keep };
|
|
2847
|
-
|
|
2848
|
-
|
|
2862
|
+
let reasoningRequested;
|
|
2863
|
+
if (this._openAICompatible) {
|
|
2864
|
+
delete requestKwargs["chat_template_kwargs"];
|
|
2865
|
+
const controls = fredrikGlmRequestControls(effectiveThinkingEffort ?? "max");
|
|
2866
|
+
requestExtraBody["thinking"] = controls.thinking;
|
|
2867
|
+
requestExtraBody["reasoning_effort"] = controls.reasoning_effort;
|
|
2868
|
+
reasoningRequested = true;
|
|
2869
|
+
} else {
|
|
2870
|
+
const effectiveTemplateKwargs = requestKwargs["chat_template_kwargs"];
|
|
2871
|
+
reasoningRequested = typeof effectiveTemplateKwargs === "object" && effectiveTemplateKwargs !== null && effectiveTemplateKwargs.thinking === true;
|
|
2872
|
+
}
|
|
2849
2873
|
const createParams = {
|
|
2850
2874
|
model: this._model,
|
|
2851
2875
|
messages,
|
|
@@ -9989,7 +10013,7 @@ var init_schema = __esmMin((() => {
|
|
|
9989
10013
|
init_matches_rule();
|
|
9990
10014
|
init_errors$8();
|
|
9991
10015
|
init_zod$1();
|
|
9992
|
-
ProviderTypeSchema = literal("blun");
|
|
10016
|
+
ProviderTypeSchema = union([literal("blun"), literal("openai_compatible")]);
|
|
9993
10017
|
OAuthRefSchema = object({
|
|
9994
10018
|
storage: _enum(["file", "keyring"]),
|
|
9995
10019
|
key: string().min(1),
|
|
@@ -9999,6 +10023,7 @@ var init_schema = __esmMin((() => {
|
|
|
9999
10023
|
ProviderConfigSchema = object({
|
|
10000
10024
|
type: ProviderTypeSchema,
|
|
10001
10025
|
apiKey: string().optional(),
|
|
10026
|
+
apiKeyFile: string().optional(),
|
|
10002
10027
|
baseUrl: string().optional(),
|
|
10003
10028
|
defaultModel: string().optional(),
|
|
10004
10029
|
oauth: OAuthRefSchema.optional(),
|
|
@@ -28546,6 +28571,7 @@ var init_agent$3 = __esmMin((() => {
|
|
|
28546
28571
|
agent_default$1 = "name: agent\ndescription: Default BLUN King agent\n\nsystemPromptPath: ./system.md\npromptVars:\n roleAdditional: ''\n\ntools:\n - Read\n - Write\n - Edit\n - Grep\n - Glob\n - Bash\n - TaskList\n - TaskOutput\n - TaskUpdate\n - TaskStop\n - CronCreate\n - CronList\n - CronDelete\n - ReadMediaFile\n - TodoList\n - Skill\n - WebSearch\n - Agent\n - AgentSwarm\n - FetchURL\n - GenerateImage\n - GenerateVideo\n - GenerateSpeech\n - UnderstandImage\n - UnderstandVideo\n - DubVideo\n - LipSyncMedia\n - GetMedia\n - AskUserQuestion\n - MistakeRecord\n - CodebaseSearch\n - EnterPlanMode\n - ExitPlanMode\n - CreateGoal\n - GetGoal\n - SetGoalBudget\n - UpdateGoal\n - mcp__*\n\nsubagents:\n coder:\n description: General software engineering agent — the only subagent type with file-editing tools; use it for any delegated task that must modify code.\n explore:\n description: Fast codebase exploration with prompt-enforced read-only behavior.\n plan:\n description: Read-only implementation planning and architecture design.\n";
|
|
28547
28572
|
agent_default$1 = agent_default$1.replace(" - Read\n", " - Read\n - ReadBatch\n");
|
|
28548
28573
|
agent_default$1 = agent_default$1.replace(" - TodoList\n", " - TodoList\n - CompactConversation\n");
|
|
28574
|
+
agent_default$1 = agent_default$1.replace(" - CodebaseSearch\n", " - CodebaseSearch\n - ProgrammaticTool\n");
|
|
28549
28575
|
}));
|
|
28550
28576
|
//#endregion
|
|
28551
28577
|
//#region ../../packages/agent-core/src/profile/default/coder.yaml?raw
|
|
@@ -28553,6 +28579,7 @@ var coder_default;
|
|
|
28553
28579
|
var init_coder = __esmMin((() => {
|
|
28554
28580
|
coder_default = "extends: agent\nname: coder\npromptVars:\n roleAdditional: |\n You are now running as a subagent. All the `user` messages are sent by the main agent. The main agent cannot see your context, it can only see your last message when you finish the task. You must treat the parent agent as your caller. Do not directly ask the end user questions. If something is unclear, explain the ambiguity in your final summary to the parent agent.\n\n Your final message is the entire handoff — the parent sees nothing else from your run. Make it technically complete: what you changed and why, the path of every file you touched, how you verified the change (tests or commands run, with results), and anything left undone or worth follow-up. A final message of only a sentence or two is treated as too brief and sent back to you for expansion, costing an extra turn.\nwhenToUse: |\n Use this agent for non-trivial software engineering work that may require reading files, editing code, running commands, and returning a compact but technically complete summary to the parent agent.\ntools:\n - Bash\n - Read\n - ReadMediaFile\n - Glob\n - Grep\n - Write\n - Edit\n - MistakeRecord\n - WebSearch\n - FetchURL\n - mcp__*\n";
|
|
28555
28581
|
coder_default = coder_default.replace(" - Read\n", " - Read\n - ReadBatch\n");
|
|
28582
|
+
coder_default = coder_default.replace(" - ReadBatch\n", " - ReadBatch\n - ProgrammaticTool\n");
|
|
28556
28583
|
}));
|
|
28557
28584
|
//#endregion
|
|
28558
28585
|
//#region ../../packages/agent-core/src/profile/default/explore.yaml?raw
|
|
@@ -28560,6 +28587,7 @@ var explore_default;
|
|
|
28560
28587
|
var init_explore = __esmMin((() => {
|
|
28561
28588
|
explore_default = "extends: agent\nname: explore\npromptVars:\n roleAdditional: |\n You are now running as a subagent. All the `user` messages are sent by the main agent. The main agent cannot see your context, it can only see your last message when you finish the task. You must treat the parent agent as your caller. Do not directly ask the end user questions. If something is unclear, explain the ambiguity in your final summary to the parent agent.\n\n You are a codebase exploration specialist. Your role is EXCLUSIVELY to search, read, and analyze existing code and resources. You do NOT have access to project file editing tools. MistakeRecord is the sole write-capable exception: it may record a concrete refutation in shared BLUN learning memory, never modify project files.\n\n Your strengths:\n - Rapidly finding files using glob patterns\n - Searching code and text with powerful regex patterns\n - Reading and analyzing file contents\n - Running read-only shell commands (git log, git diff, ls, find, etc.)\n\n Guidelines:\n - Use Glob for broad file pattern matching. Prefer patterns with a literal anchor (extension or subdirectory); pure wildcards like `*` or `**/*` are allowed but usually truncate at the match cap.\n - Use Grep for searching file contents with regex\n - Use Read when you know the specific file path\n - Use Bash ONLY for read-only operations (ls, git status, git log, git diff, find)\n - NEVER use Bash for any file creation or modification commands\n - Use WebSearch or FetchURL when a question needs external context (library documentation, error messages, upstream APIs); the local codebase remains your primary domain\n - Adapt your search depth based on the thoroughness level specified by the caller\n - Wherever possible, spawn multiple parallel tool calls for grepping and reading files to maximize speed\n\n If the prompt includes a <git-context> block, use it to orient yourself about the repository state before starting your investigation.\n\n You are meant to be a fast agent. Complete the search request efficiently and report your findings clearly in a structured format.\nwhenToUse: |\n Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (e.g. \"src/**/*.yaml\"), search code for keywords (e.g. \"database connection\"), or answer questions about the codebase (e.g. \"how does the auth module work?\"). When calling this agent, specify the desired thoroughness level: \"quick\" for basic searches, \"medium\" for moderate exploration, or \"thorough\" for comprehensive analysis across multiple locations and naming conventions. Use this agent for any read-only exploration that will clearly require more than 3 search queries. Prefer launching multiple explore agents concurrently when investigating independent questions.\ntools:\n - Bash\n - Read\n - ReadMediaFile\n - Glob\n - Grep\n - MistakeRecord\n - WebSearch\n - FetchURL\n";
|
|
28562
28589
|
explore_default = explore_default.replace(" - Read\n", " - Read\n - ReadBatch\n");
|
|
28590
|
+
explore_default = explore_default.replace(" - ReadBatch\n", " - ReadBatch\n - ProgrammaticTool\n");
|
|
28563
28591
|
}));
|
|
28564
28592
|
//#endregion
|
|
28565
28593
|
//#region ../../packages/agent-core/src/profile/default/init.md?raw
|
|
@@ -28573,6 +28601,7 @@ var plan_default;
|
|
|
28573
28601
|
var init_plan$1 = __esmMin((() => {
|
|
28574
28602
|
plan_default = "extends: agent\nname: plan\npromptVars:\n roleAdditional: |\n You are now running as a subagent. All the `user` messages are sent by the main agent. The main agent cannot see your context, it can only see your last message when you finish the task. You must treat the parent agent as your caller. Do not directly ask the end user questions. If something is unclear, explain the ambiguity in your final summary to the parent agent.\n\n Before designing your implementation plan, consider whether you fully understand the codebase areas relevant to the task. If not, recommend the parent agent to use the explore agent (subagent_type=\"explore\") to investigate key questions first. In your response, clearly state:\n 1. What you already know from the information provided\n 2. What questions remain unanswered that would benefit from explore agent investigation\n 3. Your implementation plan (either preliminary if questions remain, or final if sufficient context exists)\n\n You are a read-only planning agent: you can read and search files (Read, Glob, Grep, ReadMediaFile) and consult the web (WebSearch, FetchURL), but you have no shell and no project file-editing tools. MistakeRecord is the sole write-capable exception: it may record a concrete refutation in shared BLUN learning memory, never modify project files. Where the general instructions tell you to make changes with tools, that does not apply to you — do not attempt to run commands or modify project files. Your deliverable is the plan itself, returned as your final message.\nwhenToUse: |\n Use this agent when the parent agent needs a step-by-step implementation plan, key file identification, and architectural trade-off analysis before code changes are made.\ntools:\n - Read\n - ReadMediaFile\n - Glob\n - Grep\n - MistakeRecord\n - WebSearch\n - FetchURL\n";
|
|
28575
28603
|
plan_default = plan_default.replace(" - Read\n", " - Read\n - ReadBatch\n");
|
|
28604
|
+
plan_default = plan_default.replace(" - ReadBatch\n", " - ReadBatch\n - ProgrammaticTool\n");
|
|
28576
28605
|
}));
|
|
28577
28606
|
//#endregion
|
|
28578
28607
|
//#region ../../packages/agent-core/src/profile/default/system.md?raw
|
|
@@ -29102,6 +29131,7 @@ var init_agent_task = __esmMin((() => {
|
|
|
29102
29131
|
continuationTimeoutMs;
|
|
29103
29132
|
runInBackground;
|
|
29104
29133
|
parentToolCallId;
|
|
29134
|
+
responseFormat;
|
|
29105
29135
|
kind = "agent";
|
|
29106
29136
|
idPrefix = "agent";
|
|
29107
29137
|
agentId;
|
|
@@ -29114,6 +29144,7 @@ var init_agent_task = __esmMin((() => {
|
|
|
29114
29144
|
this.continuationTimeoutMs = options.timeoutMs;
|
|
29115
29145
|
this.runInBackground = options.runInBackground;
|
|
29116
29146
|
this.parentToolCallId = options.parentToolCallId;
|
|
29147
|
+
this.responseFormat = options.responseFormat;
|
|
29117
29148
|
this.agentId = handle.agentId;
|
|
29118
29149
|
this.subagentType = handle.profileName;
|
|
29119
29150
|
}
|
|
@@ -29133,6 +29164,7 @@ var init_agent_task = __esmMin((() => {
|
|
|
29133
29164
|
prompt: continuation.kind === "transient_provider" ? "Continue from the preserved context after a transient provider interruption. Do not repeat completed work; inspect the preserved wire and continue from the last durable boundary." : "Continue from the preserved context after the wall-clock interval.",
|
|
29134
29165
|
description: this.description,
|
|
29135
29166
|
runInBackground: this.runInBackground,
|
|
29167
|
+
responseFormat: this.responseFormat,
|
|
29136
29168
|
signal: this.abortController.signal
|
|
29137
29169
|
});
|
|
29138
29170
|
return this.handle;
|
|
@@ -30334,6 +30366,7 @@ var init_completion_budget = __esmMin((() => {
|
|
|
30334
30366
|
}));
|
|
30335
30367
|
//#endregion
|
|
30336
30368
|
//#region ../../packages/agent-core/src/loop/retry.ts
|
|
30369
|
+
var { nextThinkingEffortForExhaustedEmpty } = createRequire(import.meta.url)("./bin/empty-response-retry-policy.cjs");
|
|
30337
30370
|
async function chatWithRetry(input) {
|
|
30338
30371
|
const maxAttempts = input.maxAttempts ?? 3;
|
|
30339
30372
|
if (input.llm.isRetryableError === void 0 || maxAttempts <= 1) {
|
|
@@ -30347,9 +30380,10 @@ async function chatWithRetry(input) {
|
|
|
30347
30380
|
}
|
|
30348
30381
|
const delays = retryBackoffDelays(maxAttempts);
|
|
30349
30382
|
let completionBudgetRetry;
|
|
30383
|
+
let thinkingEffortRetry;
|
|
30350
30384
|
let emptyRetryKind;
|
|
30351
30385
|
for (let attempt = 1;; attempt += 1) try {
|
|
30352
|
-
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry));
|
|
30386
|
+
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry, thinkingEffortRetry));
|
|
30353
30387
|
} catch (error) {
|
|
30354
30388
|
if (error instanceof APIEmptyResponseError && (emptyRetryKind !== void 0 || error.emptyResponseKind === "length" || error.emptyResponseKind === "stop")) {
|
|
30355
30389
|
logEmptyResponse(input, error, attempt);
|
|
@@ -30359,6 +30393,12 @@ async function chatWithRetry(input) {
|
|
|
30359
30393
|
throw terminal;
|
|
30360
30394
|
}
|
|
30361
30395
|
completionBudgetRetry = completionBudgetRetryForEmpty(error);
|
|
30396
|
+
thinkingEffortRetry = nextThinkingEffortForExhaustedEmpty({
|
|
30397
|
+
emptyResponseKind: error.emptyResponseKind,
|
|
30398
|
+
maxCompletionTokens: error.maxCompletionTokens,
|
|
30399
|
+
completionTokens: error.completionTokens,
|
|
30400
|
+
thinkingEffort: input.llm.thinkingEffort
|
|
30401
|
+
});
|
|
30362
30402
|
emptyRetryKind = error.emptyResponseKind;
|
|
30363
30403
|
input.params.signal.throwIfAborted();
|
|
30364
30404
|
input.dispatchEvent({
|
|
@@ -30415,11 +30455,12 @@ function logRequestFailure(input, error, attempt, maxAttempts) {
|
|
|
30415
30455
|
...retryErrorFields(error)
|
|
30416
30456
|
});
|
|
30417
30457
|
}
|
|
30418
|
-
function paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry) {
|
|
30458
|
+
function paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry, thinkingEffortRetry) {
|
|
30419
30459
|
const turnStep = `${input.turnId}.${String(input.currentStep)}`;
|
|
30420
30460
|
return {
|
|
30421
30461
|
...input.params,
|
|
30422
30462
|
completionBudgetRetry,
|
|
30463
|
+
thinkingEffortRetry,
|
|
30423
30464
|
requestLogFields: attempt === 1 ? { turnStep } : {
|
|
30424
30465
|
turnStep,
|
|
30425
30466
|
attempt: `${String(attempt)}/${String(maxAttempts)}`
|
|
@@ -30427,12 +30468,19 @@ function paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry) {
|
|
|
30427
30468
|
};
|
|
30428
30469
|
}
|
|
30429
30470
|
function logEmptyResponse(input, error, attempt) {
|
|
30471
|
+
const retryThinkingEffort = nextThinkingEffortForExhaustedEmpty({
|
|
30472
|
+
emptyResponseKind: error.emptyResponseKind,
|
|
30473
|
+
maxCompletionTokens: error.maxCompletionTokens,
|
|
30474
|
+
completionTokens: error.completionTokens,
|
|
30475
|
+
thinkingEffort: input.llm.thinkingEffort
|
|
30476
|
+
});
|
|
30430
30477
|
input.log?.warn(`[leer] fall=${error.emptyResponseKind}`, {
|
|
30431
30478
|
turnStep: `${input.turnId}.${String(input.currentStep)}`,
|
|
30432
30479
|
attempt,
|
|
30433
30480
|
budget: error.maxCompletionTokens,
|
|
30434
30481
|
completion: error.completionTokens,
|
|
30435
|
-
reasoningLength: error.reasoningLength
|
|
30482
|
+
reasoningLength: error.reasoningLength,
|
|
30483
|
+
...retryThinkingEffort === void 0 ? {} : { retryThinkingEffort }
|
|
30436
30484
|
});
|
|
30437
30485
|
}
|
|
30438
30486
|
function retryBackoffDelays(maxAttempts) {
|
|
@@ -30599,6 +30647,96 @@ var init_todo_list = __esmMin((() => {
|
|
|
30599
30647
|
};
|
|
30600
30648
|
}));
|
|
30601
30649
|
//#endregion
|
|
30650
|
+
//#region ../../packages/agent-core/src/tools/builtin/state/programmatic-tool.ts
|
|
30651
|
+
var PROGRAMMATIC_TOOL_NAME, ProgrammaticTool;
|
|
30652
|
+
var init_programmatic_tool = __esmMin((() => {
|
|
30653
|
+
PROGRAMMATIC_TOOL_NAME = "ProgrammaticTool";
|
|
30654
|
+
ProgrammaticTool = class {
|
|
30655
|
+
name = PROGRAMMATIC_TOOL_NAME;
|
|
30656
|
+
description = "Run bounded JavaScript in an isolated QuickJS interpreter to coordinate several sequential BLUN tool calls without returning every intermediate value to the model context. Declare every callable tool explicitly with its current BLUN name and a JavaScript alias. Calls still pass through the normal schema, hook, permission, scheduler, event, and result pipeline; denied or unavailable tools fail inside the program. The interpreter has no host filesystem, network, process, package loader, clock, or dynamic eval. Return a JSON-serializable result and use the JSON state object only for explicit continuation.";
|
|
30657
|
+
parameters = {
|
|
30658
|
+
type: "object",
|
|
30659
|
+
properties: {
|
|
30660
|
+
code: {
|
|
30661
|
+
type: "string",
|
|
30662
|
+
maxLength: 32e3,
|
|
30663
|
+
description: "JavaScript function body. Use state for explicit JSON state and tools.<alias>(args) for declared sequential tool calls."
|
|
30664
|
+
},
|
|
30665
|
+
state: {
|
|
30666
|
+
type: "object",
|
|
30667
|
+
description: "Optional JSON-only state snapshot from a previous run."
|
|
30668
|
+
},
|
|
30669
|
+
tools: {
|
|
30670
|
+
type: "array",
|
|
30671
|
+
maxItems: 16,
|
|
30672
|
+
description: "Explicit allowlist for this program. Each name must be a tool available in the current turn.",
|
|
30673
|
+
items: {
|
|
30674
|
+
type: "object",
|
|
30675
|
+
properties: {
|
|
30676
|
+
name: {
|
|
30677
|
+
type: "string",
|
|
30678
|
+
minLength: 1,
|
|
30679
|
+
description: "Exact current BLUN tool name."
|
|
30680
|
+
},
|
|
30681
|
+
alias: {
|
|
30682
|
+
type: "string",
|
|
30683
|
+
pattern: "^[A-Za-z_$][A-Za-z0-9_$]*$",
|
|
30684
|
+
description: "JavaScript identifier exposed under tools."
|
|
30685
|
+
}
|
|
30686
|
+
},
|
|
30687
|
+
required: ["name", "alias"],
|
|
30688
|
+
additionalProperties: false
|
|
30689
|
+
}
|
|
30690
|
+
}
|
|
30691
|
+
},
|
|
30692
|
+
required: ["code"],
|
|
30693
|
+
additionalProperties: false
|
|
30694
|
+
};
|
|
30695
|
+
resolveExecution(args) {
|
|
30696
|
+
const declaredTools = Array.isArray(args.tools) ? args.tools : [];
|
|
30697
|
+
return {
|
|
30698
|
+
description: `Running bounded programmatic tool plan (${declaredTools.length} allowed tool${declaredTools.length === 1 ? "" : "s"})`,
|
|
30699
|
+
approvalRule: this.name,
|
|
30700
|
+
execute: async (context) => {
|
|
30701
|
+
if (typeof context.invokeTool !== "function") return {
|
|
30702
|
+
output: "Programmatic tool invocation boundary is unavailable.",
|
|
30703
|
+
isError: true
|
|
30704
|
+
};
|
|
30705
|
+
try {
|
|
30706
|
+
const { createProgrammaticToolRuntime } = await import(new URL("./bin/programmatic-tool-runtime.mjs", import.meta.url).href);
|
|
30707
|
+
const runtime = createProgrammaticToolRuntime({
|
|
30708
|
+
allowedTools: declaredTools,
|
|
30709
|
+
invokeTool: context.invokeTool,
|
|
30710
|
+
onEvent: (event) => context.onUpdate({
|
|
30711
|
+
kind: "programmatic_tool",
|
|
30712
|
+
event
|
|
30713
|
+
})
|
|
30714
|
+
});
|
|
30715
|
+
const outcome = await runtime.run({
|
|
30716
|
+
code: args.code,
|
|
30717
|
+
state: args.state ?? {},
|
|
30718
|
+
signal: context.signal
|
|
30719
|
+
});
|
|
30720
|
+
const result = {
|
|
30721
|
+
output: JSON.stringify(outcome),
|
|
30722
|
+
isError: false
|
|
30723
|
+
};
|
|
30724
|
+
if (context.invokeTool.stopTurn === true) result.stopTurn = true;
|
|
30725
|
+
return result;
|
|
30726
|
+
} catch (error) {
|
|
30727
|
+
const result = {
|
|
30728
|
+
output: error instanceof Error ? error.message : String(error),
|
|
30729
|
+
isError: true
|
|
30730
|
+
};
|
|
30731
|
+
if (context.invokeTool.stopTurn === true) result.stopTurn = true;
|
|
30732
|
+
return result;
|
|
30733
|
+
}
|
|
30734
|
+
}
|
|
30735
|
+
};
|
|
30736
|
+
}
|
|
30737
|
+
};
|
|
30738
|
+
}));
|
|
30739
|
+
//#endregion
|
|
30602
30740
|
//#region ../../packages/agent-core/src/tools/support/file-type.ts
|
|
30603
30741
|
function toBuffer$2(data) {
|
|
30604
30742
|
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
@@ -74747,6 +74885,9 @@ var init_kosong_llm = __esmMin((() => {
|
|
|
74747
74885
|
this.visionReader = config.visionReader;
|
|
74748
74886
|
this.onVisionUsage = config.onVisionUsage;
|
|
74749
74887
|
}
|
|
74888
|
+
get thinkingEffort() {
|
|
74889
|
+
return this.provider.thinkingEffort;
|
|
74890
|
+
}
|
|
74750
74891
|
notifyMediaDropped(dropped) {
|
|
74751
74892
|
if (this.onMediaDropped === void 0) return;
|
|
74752
74893
|
const fresh = dropped.filter((part) => {
|
|
@@ -74789,6 +74930,7 @@ var init_kosong_llm = __esmMin((() => {
|
|
|
74789
74930
|
let result;
|
|
74790
74931
|
let completionBudget;
|
|
74791
74932
|
try {
|
|
74933
|
+
const requestProvider = params.thinkingEffortRetry === void 0 ? this.provider : this.provider.withThinking(params.thinkingEffortRetry);
|
|
74792
74934
|
const enrichedMessages = this.visionReader === void 0 ? params.messages : await enrichMessagesWithVision(params.messages, this.visionReader, params.signal, this.onVisionUsage);
|
|
74793
74935
|
const tools = [...params.tools];
|
|
74794
74936
|
const outgoingMessages = downgradeUnsupportedMedia(enrichedMessages, this.capability, (dropped) => {
|
|
@@ -74798,11 +74940,11 @@ var init_kosong_llm = __esmMin((() => {
|
|
|
74798
74940
|
const reportedContextTokens = this.reportedContextTokens?.() ?? 0;
|
|
74799
74941
|
const usedContextTokens = Math.max(outgoingRequestTokens, reportedContextTokens);
|
|
74800
74942
|
completionBudget = applyCompletionBudgetWithDetails({
|
|
74801
|
-
provider:
|
|
74943
|
+
provider: requestProvider,
|
|
74802
74944
|
budget: this.completionBudgetConfig,
|
|
74803
74945
|
capability: this.capability,
|
|
74804
74946
|
usedContextTokens,
|
|
74805
|
-
retry: params.completionBudgetRetry ?? (thinkingEnabled(
|
|
74947
|
+
retry: params.completionBudgetRetry ?? (thinkingEnabled(requestProvider.thinkingEffort) ? {
|
|
74806
74948
|
minimumCompletionTokens: 1024,
|
|
74807
74949
|
multiplier: 1
|
|
74808
74950
|
} : void 0)
|
|
@@ -76041,8 +76183,9 @@ var init_full = __esmMin((() => {
|
|
|
76041
76183
|
}));
|
|
76042
76184
|
//#endregion
|
|
76043
76185
|
//#region ../../packages/agent-core/src/agent/compaction/micro.ts
|
|
76044
|
-
var selectMicroCompactionCutoff, MICRO_COMPACTION_RECENT_MESSAGES, MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED, MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS, isPersistedToolResultReference, freshToolResultIds, projectHistoricalUnaddressedTelegramMessages, dedupeRepeatedUserMessages, projectRepeatedAssistantResponses, compactHistoricalSkillActivations, dedupeRecurringCronWakeups, dedupeRepeatedInjections, projectLoopEventForRecord, projectUsageModelForRecord, projectUsageForRecord, resolveCompletedStepUuid, resolveStepEventUuid, restoreUsageFromRecord, restoreUsageModelFromRecord, DEFAULT_CONFIG, MicroCompaction;
|
|
76186
|
+
var selectMicroCompactionCutoff, MICRO_COMPACTION_RECENT_MESSAGES, MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED, MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS, isPersistedToolResultReference, freshToolResultIds, projectHistoricalUnaddressedTelegramMessages, dedupeRepeatedUserMessages, projectRepeatedAssistantResponses, compactHistoricalSkillActivations, dedupeRecurringCronWakeups, dedupeRepeatedInjections, projectLoopEventForRecord, projectUsageModelForRecord, projectUsageForRecord, resolveCompletedStepUuid, resolveStepEventUuid, restoreUsageFromRecord, restoreUsageModelFromRecord, isWireOnlyProgrammaticEvent, DEFAULT_CONFIG, MicroCompaction;
|
|
76045
76187
|
var init_micro = __esmMin((() => {
|
|
76188
|
+
({ isWireOnlyProgrammaticEvent } = createRequire(import.meta.url)("./bin/programmatic-context-isolation.cjs"));
|
|
76046
76189
|
({ selectMicroCompactionCutoff, MICRO_COMPACTION_RECENT_MESSAGES, MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED, MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS } = createRequire(import.meta.url)("./bin/micro-compaction-policy.cjs"));
|
|
76047
76190
|
({ isPersistedToolResultReference, freshToolResultIds } = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs"));
|
|
76048
76191
|
({ projectHistoricalUnaddressedTelegramMessages } = createRequire(import.meta.url)("./bin/telegram-context-projection-policy.cjs"));
|
|
@@ -79191,6 +79334,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
79191
79334
|
type: "context.append_loop_event",
|
|
79192
79335
|
event: projectLoopEventForRecord(event)
|
|
79193
79336
|
});
|
|
79337
|
+
if (isWireOnlyProgrammaticEvent(event)) return;
|
|
79194
79338
|
switch (event.type) {
|
|
79195
79339
|
case "step.begin": {
|
|
79196
79340
|
const closed = this.closePendingToolResults();
|
|
@@ -233363,6 +233507,7 @@ var init_default_tool_approve = __esmMin((() => {
|
|
|
233363
233507
|
"Agent",
|
|
233364
233508
|
"AskUserQuestion",
|
|
233365
233509
|
"Skill",
|
|
233510
|
+
"ProgrammaticTool",
|
|
233366
233511
|
"GetGoal",
|
|
233367
233512
|
"SetGoalBudget",
|
|
233368
233513
|
"UpdateGoal"
|
|
@@ -244071,6 +244216,49 @@ async function runToolCallBatch(step, response) {
|
|
|
244071
244216
|
}
|
|
244072
244217
|
return { stopTurn };
|
|
244073
244218
|
}
|
|
244219
|
+
function createNestedToolInvoker(step, parentToolCall) {
|
|
244220
|
+
let nestedSequence = 0;
|
|
244221
|
+
const invoke = async ({ name, args, callId, signal }) => {
|
|
244222
|
+
if (invoke.stopTurn === true) throw new Error("No nested tool calls are allowed after a turn-stop result.");
|
|
244223
|
+
if (name === PROGRAMMATIC_TOOL_NAME) throw new Error("Nested ProgrammaticTool calls are not allowed.");
|
|
244224
|
+
const nestedSignal = signal ?? step.signal;
|
|
244225
|
+
nestedSignal.throwIfAborted();
|
|
244226
|
+
nestedSequence += 1;
|
|
244227
|
+
const safeCallId = typeof callId === "string" && callId.length > 0 ? callId : `call_${nestedSequence}`;
|
|
244228
|
+
const nestedToolCall = {
|
|
244229
|
+
id: `${parentToolCall.id}:ptc:${safeCallId}`,
|
|
244230
|
+
name,
|
|
244231
|
+
arguments: JSON.stringify(args ?? {})
|
|
244232
|
+
};
|
|
244233
|
+
const nestedStep = {
|
|
244234
|
+
...step,
|
|
244235
|
+
signal: nestedSignal,
|
|
244236
|
+
toolCalls: [nestedToolCall],
|
|
244237
|
+
dispatchEvent: (event) => step.dispatchEvent(markProgrammaticNestedEvent(event))
|
|
244238
|
+
};
|
|
244239
|
+
const preflight = preflightToolCall(nestedStep, nestedToolCall);
|
|
244240
|
+
const prepared = await prepareToolCall(nestedStep, preflight);
|
|
244241
|
+
const started = await prepared.task.start();
|
|
244242
|
+
const pendingResult = await started.result;
|
|
244243
|
+
const finalized = await finalizePendingToolResult(nestedStep, pendingResult);
|
|
244244
|
+
if (finalized.stopTurn === true) invoke.stopTurn = true;
|
|
244245
|
+
await nestedStep.dispatchEvent({
|
|
244246
|
+
type: "tool.result",
|
|
244247
|
+
parentUuid: nestedToolCall.id,
|
|
244248
|
+
toolCallId: nestedToolCall.id,
|
|
244249
|
+
result: finalized.result
|
|
244250
|
+
});
|
|
244251
|
+
if (finalized.result.isError === true) throw new Error(nestedToolResultText(finalized.result));
|
|
244252
|
+
return finalized.result;
|
|
244253
|
+
};
|
|
244254
|
+
invoke.stopTurn = false;
|
|
244255
|
+
return invoke;
|
|
244256
|
+
}
|
|
244257
|
+
function nestedToolResultText(result) {
|
|
244258
|
+
if (typeof result.output === "string") return result.output;
|
|
244259
|
+
const text = result.output.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
244260
|
+
return text.length > 0 ? text : "Nested tool call failed.";
|
|
244261
|
+
}
|
|
244074
244262
|
/**
|
|
244075
244263
|
* Provider-order validation pass. It does not run hooks, spawn tools, or write
|
|
244076
244264
|
* events. Validator compilation may populate the local cache.
|
|
@@ -244326,11 +244514,13 @@ async function finalizePendingToolResult(step, pendingResult) {
|
|
|
244326
244514
|
async function executeTool(step, execution, toolCall, toolName, metadata) {
|
|
244327
244515
|
const { dispatchEvent, signal, turnId } = step;
|
|
244328
244516
|
signal.throwIfAborted();
|
|
244517
|
+
const invokeTool = toolName === PROGRAMMATIC_TOOL_NAME ? createNestedToolInvoker(step, toolCall) : void 0;
|
|
244329
244518
|
return raceExecuteWithGraceTimeout(execution.execute({
|
|
244330
244519
|
turnId,
|
|
244331
244520
|
toolCallId: toolCall.id,
|
|
244332
244521
|
metadata,
|
|
244333
244522
|
signal,
|
|
244523
|
+
invokeTool,
|
|
244334
244524
|
onUpdate: (update) => {
|
|
244335
244525
|
if (signal.aborted) return;
|
|
244336
244526
|
dispatchEvent({
|
|
@@ -244462,8 +244652,9 @@ async function dispatchToolCall(step, call, args, displayFields) {
|
|
|
244462
244652
|
display: displayFields?.display
|
|
244463
244653
|
});
|
|
244464
244654
|
}
|
|
244465
|
-
var GRACE_TIMEOUT_MS, TOOL_OUTPUT_EMPTY, TOOL_OUTPUT_NON_TEXT, validators;
|
|
244655
|
+
var markProgrammaticNestedEvent, GRACE_TIMEOUT_MS, TOOL_OUTPUT_EMPTY, TOOL_OUTPUT_NON_TEXT, validators;
|
|
244466
244656
|
var init_tool_call = __esmMin((() => {
|
|
244657
|
+
({ markProgrammaticNestedEvent } = createRequire(import.meta.url)("./bin/programmatic-context-isolation.cjs"));
|
|
244467
244658
|
init_args_validator();
|
|
244468
244659
|
init_path_access();
|
|
244469
244660
|
init_abort();
|
|
@@ -251417,6 +251608,7 @@ var init_task_output = __esmMin((() => {
|
|
|
251417
251608
|
init_zod$1();
|
|
251418
251609
|
init_background();
|
|
251419
251610
|
init_input_schema();
|
|
251611
|
+
init_args_validator();
|
|
251420
251612
|
init_rule_match();
|
|
251421
251613
|
init_format();
|
|
251422
251614
|
init_task_output$1();
|
|
@@ -252467,12 +252659,29 @@ function lastAssistantText(agent) {
|
|
|
252467
252659
|
}
|
|
252468
252660
|
return "";
|
|
252469
252661
|
}
|
|
252662
|
+
async function completeStructuredSubagentResult(child, childId, profileName, responseFormat, signal) {
|
|
252663
|
+
let validation = validateStructuredSubagentOutput(lastAssistantText(child), responseFormat);
|
|
252664
|
+
if (validation.validatorException === true) throw new Error(validation.error);
|
|
252665
|
+
if (!validation.ok) {
|
|
252666
|
+
signal.throwIfAborted();
|
|
252667
|
+
if (child.turn.prompt([{
|
|
252668
|
+
type: "text",
|
|
252669
|
+
text: buildStructuredResponseRepairPrompt(responseFormat, validation.error)
|
|
252670
|
+
}], SUBAGENT_PROMPT_ORIGIN) === null) throw new Error("Subagent could not start its structured-output repair turn.");
|
|
252671
|
+
await completeChildTurnWithMaxTokensHandoff(child, signal);
|
|
252672
|
+
signal.throwIfAborted();
|
|
252673
|
+
validation = validateStructuredSubagentOutput(lastAssistantText(child), responseFormat);
|
|
252674
|
+
if (validation.validatorException === true) throw new Error(validation.error);
|
|
252675
|
+
if (!validation.ok) throw new Error(`${STRUCTURED_SUBAGENT_OUTPUT_ERROR}: ${validation.error}. Resume with Agent(resume="${childId}", prompt="return the corrected JSON object", response_format=...) using the same response format.`);
|
|
252676
|
+
}
|
|
252677
|
+
return validation.value;
|
|
252678
|
+
}
|
|
252470
252679
|
function shouldSuppressQueuedAttemptFailureEvent(options, error) {
|
|
252471
252680
|
if (options.suppressRateLimitFailureEvent !== true) return false;
|
|
252472
252681
|
if (isProviderRateLimitError(error)) return true;
|
|
252473
252682
|
return isAbortError$4(error) || options.signal.aborted;
|
|
252474
252683
|
}
|
|
252475
|
-
var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, inheritSubagentAllowedTools, inheritSubagentLifecycleTools, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, isSubagentMaxTokensTurnError, shouldRequestSubagentHandoff, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
|
|
252684
|
+
var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, inheritSubagentAllowedTools, inheritSubagentLifecycleTools, STRUCTURED_SUBAGENT_OUTPUT_ERROR, prepareStructuredResponseFormat, validateStructuredSubagentOutput, buildStructuredResponseFormatReminder, buildStructuredResponseRepairPrompt, buildStructuredSubagentEnvelope, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, isSubagentMaxTokensTurnError, shouldRequestSubagentHandoff, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
|
|
252476
252685
|
var init_subagent_host = __esmMin((() => {
|
|
252477
252686
|
init_src$4();
|
|
252478
252687
|
init_errors$8();
|
|
@@ -252487,6 +252696,14 @@ var init_subagent_host = __esmMin((() => {
|
|
|
252487
252696
|
({ DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation } = createRequire(import.meta.url)("./bin/subagent-timeout-policy.cjs"));
|
|
252488
252697
|
({ buildSubagentUsageDelta } = createRequire(import.meta.url)("./bin/subagent-usage-rollup-policy.cjs"));
|
|
252489
252698
|
({ inheritSubagentAllowedTools, inheritSubagentLifecycleTools } = createRequire(import.meta.url)("./bin/subagent-tool-policy.cjs"));
|
|
252699
|
+
({
|
|
252700
|
+
STRUCTURED_SUBAGENT_OUTPUT_ERROR,
|
|
252701
|
+
prepareStructuredResponseFormat,
|
|
252702
|
+
validateStructuredSubagentOutput,
|
|
252703
|
+
buildStructuredResponseFormatReminder,
|
|
252704
|
+
buildStructuredResponseRepairPrompt,
|
|
252705
|
+
buildStructuredSubagentEnvelope
|
|
252706
|
+
} = createRequire(import.meta.url)("./bin/structured-subagent-output.cjs"));
|
|
252490
252707
|
({
|
|
252491
252708
|
SUBAGENT_MAX_TOKENS_ERROR,
|
|
252492
252709
|
SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT,
|
|
@@ -252751,6 +252968,10 @@ IMPORTANT:
|
|
|
252751
252968
|
const gitContext = await collectGitContext(child.kaos, child.config.cwd);
|
|
252752
252969
|
if (gitContext) childPrompt = `${gitContext}\n\n${childPrompt}`;
|
|
252753
252970
|
}
|
|
252971
|
+
if (options.responseFormat !== void 0) child.context.appendSystemReminder(buildStructuredResponseFormatReminder(options.responseFormat), {
|
|
252972
|
+
kind: "system_trigger",
|
|
252973
|
+
name: "subagent_response_format"
|
|
252974
|
+
});
|
|
252754
252975
|
this.emitSubagentStarted(parent, childId);
|
|
252755
252976
|
if (child.turn.prompt([{
|
|
252756
252977
|
type: "text",
|
|
@@ -252761,17 +252982,29 @@ IMPORTANT:
|
|
|
252761
252982
|
}
|
|
252762
252983
|
async waitForChildCompletion(parent, childId, child, profileName, options) {
|
|
252763
252984
|
await completeChildTurnWithMaxTokensHandoff(child, options.signal);
|
|
252764
|
-
let result
|
|
252765
|
-
|
|
252766
|
-
|
|
252767
|
-
|
|
252768
|
-
|
|
252769
|
-
|
|
252770
|
-
|
|
252771
|
-
|
|
252772
|
-
|
|
252773
|
-
|
|
252985
|
+
let result;
|
|
252986
|
+
if (options.responseFormat !== void 0) {
|
|
252987
|
+
const structuredResult = await completeStructuredSubagentResult(child, childId, profileName, options.responseFormat, options.signal);
|
|
252988
|
+
result = buildStructuredSubagentEnvelope({
|
|
252989
|
+
agentId: childId,
|
|
252990
|
+
profileName,
|
|
252991
|
+
responseFormat: options.responseFormat,
|
|
252992
|
+
result: structuredResult,
|
|
252993
|
+
usage: child.usage.data().total
|
|
252994
|
+
});
|
|
252995
|
+
} else {
|
|
252774
252996
|
result = lastAssistantText(child);
|
|
252997
|
+
let remainingContinuations = SUMMARY_CONTINUATION_ATTEMPTS;
|
|
252998
|
+
while (remainingContinuations > 0 && result.length < SUMMARY_MIN_LENGTH) {
|
|
252999
|
+
remainingContinuations -= 1;
|
|
253000
|
+
options.signal.throwIfAborted();
|
|
253001
|
+
child.turn.prompt([{
|
|
253002
|
+
type: "text",
|
|
253003
|
+
text: summary_continuation_default
|
|
253004
|
+
}], SUBAGENT_PROMPT_ORIGIN);
|
|
253005
|
+
await completeChildTurnWithMaxTokensHandoff(child, options.signal);
|
|
253006
|
+
result = lastAssistantText(child);
|
|
253007
|
+
}
|
|
252775
253008
|
}
|
|
252776
253009
|
const usage = child.usage.data().total;
|
|
252777
253010
|
parent.emitEvent({
|
|
@@ -252868,7 +253101,7 @@ var init_agent_background_disabled = __esmMin((() => {
|
|
|
252868
253101
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/agent-background-enabled.md?raw
|
|
252869
253102
|
var agent_background_enabled_default;
|
|
252870
253103
|
var init_agent_background_enabled = __esmMin((() => {
|
|
252871
|
-
agent_background_enabled_default = "Subagents run detached whenever task management is available, so the parent remains responsive while delegated work continues.
|
|
253104
|
+
agent_background_enabled_default = "Subagents run detached whenever task management is available, so the parent remains responsive while delegated work continues. A call with `response_format` is the deliberate exception: it runs in the foreground so BLUN can validate and, at most once, repair the final JSON before returning it. Detached completion arrives automatically in a later turn. Do not poll, sleep, or block on TaskOutput. Continue with other work or respond to the user. Use TaskUpdate to steer a running detached subagent and TaskStop only when it must be cancelled. Never fabricate or predict its result.";
|
|
252872
253105
|
}));
|
|
252873
253106
|
//#endregion
|
|
252874
253107
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/agent.md?raw
|
|
@@ -252910,7 +253143,7 @@ function formatForegroundAgentFailure(handle, message, timedOut) {
|
|
|
252910
253143
|
"",
|
|
252911
253144
|
`subagent error: ${message}`
|
|
252912
253145
|
];
|
|
252913
|
-
if (timedOut || message.includes(SUBAGENT_MAX_TOKENS_ERROR)) lines.push(`resume_hint: Continue with Agent(resume="${handle.agentId}", prompt="continue"). Use agent_id only; do not set subagent_type. The subagent retains its prior context; redo any unfinished tool call if its result was lost.`);
|
|
253146
|
+
if (timedOut || message.includes(SUBAGENT_MAX_TOKENS_ERROR) || message.includes(STRUCTURED_SUBAGENT_OUTPUT_ERROR)) lines.push(`resume_hint: Continue with Agent(resume="${handle.agentId}", prompt="continue"). Use agent_id only; do not set subagent_type. The subagent retains its prior context; redo any unfinished tool call if its result was lost.`);
|
|
252914
253147
|
return lines.join("\n");
|
|
252915
253148
|
}
|
|
252916
253149
|
function launchErrorMessage(error, signal) {
|
|
@@ -252954,8 +253187,12 @@ var init_agent$1 = __esmMin((() => {
|
|
|
252954
253187
|
description: string().describe("Short task description (3-5 words) for UI display"),
|
|
252955
253188
|
subagent_type: string().optional().describe("One of the available agent types (see \"Available agent types\" in this tool description). Defaults to \"coder\" when omitted."),
|
|
252956
253189
|
resume: string().optional().describe("Optional agent ID to resume instead of creating a new instance. When set, do not also pass subagent_type — the resumed agent keeps its own type, and supplying both is rejected."),
|
|
252957
|
-
run_in_background: boolean$1().optional().describe("Compatibility option.
|
|
252958
|
-
timeout_minutes: number$1().int().min(0).max(10080).optional().describe("Wall-clock interval before the same agent is continued automatically. Defaults to 240 minutes. Set 0 to disable the interval for this run.")
|
|
253190
|
+
run_in_background: boolean$1().optional().describe("Compatibility option. Normal subagents run detached when task management is available. A response_format call requires this to be false or omitted and runs in the foreground for validation."),
|
|
253191
|
+
timeout_minutes: number$1().int().min(0).max(10080).optional().describe("Wall-clock interval before the same agent is continued automatically. Defaults to 240 minutes. Set 0 to disable the interval for this run."),
|
|
253192
|
+
response_format: object({
|
|
253193
|
+
name: string().min(1).max(64).describe("Stable name for the structured result"),
|
|
253194
|
+
schema: record(string(), unknown()).describe("Restricted JSON Schema for one object result")
|
|
253195
|
+
}).optional().describe("Require a validated JSON object from a foreground subagent. Structured background agents are not supported yet.")
|
|
252959
253196
|
}));
|
|
252960
253197
|
object({
|
|
252961
253198
|
result: string().describe("Aggregated text output from the subagent"),
|
|
@@ -252967,7 +253204,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
252967
253204
|
}).describe("Cumulative token usage")
|
|
252968
253205
|
});
|
|
252969
253206
|
BACKGROUND_AGENT_UNAVAILABLE = "Background agent execution is not available for this agent because TaskList, TaskOutput, and TaskStop are not enabled.";
|
|
252970
|
-
agent_default = "Launch a subagent for substantial, multi-step work in its own context and wire file. It returns a final report while keeping intermediate file contents out of your context.\n\nThe subagent starts with zero conversation context. Give it a self-contained prompt with the goal, known facts, constraints, and required result. For a direct lookup, include the exact path or command. For an investigation, state the question and evidence needed instead of prescribing rigid steps.\n\nWhen continuing earlier work, resume the existing agent ID instead of spawning a new agent; its context remains available. A subagent report is only visible to you, so relay the relevant conclusions to the user. `timeout_minutes` sets the wall-clock interval before the same agent continues automatically with preserved context; `timeout_minutes=0` disables that interval.\n\nUse Agent for complex, context-heavy work, not a trivial one- or two-step task. Launch independent agents in parallel in one response when useful. After assigning a scope, do not duplicate its searches or reads and do not abandon it to redo the same work manually; both erase the intended context savings.";
|
|
253207
|
+
agent_default = "Launch a subagent for substantial, multi-step work in its own context and wire file. It returns a final report while keeping intermediate file contents out of your context.\n\nThe subagent starts with zero conversation context. Give it a self-contained prompt with the goal, known facts, constraints, and required result. For a direct lookup, include the exact path or command. For an investigation, state the question and evidence needed instead of prescribing rigid steps.\n\nWhen continuing earlier work, resume the existing agent ID instead of spawning a new agent; its context remains available. A subagent report is only visible to you, so relay the relevant conclusions to the user. `timeout_minutes` sets the wall-clock interval before the same agent continues automatically with preserved context; `timeout_minutes=0` disables that interval.\n\nUse Agent for complex, context-heavy work, not a trivial one- or two-step task. Launch independent agents in parallel in one response when useful. After assigning a scope, do not duplicate its searches or reads and do not abandon it to redo the same work manually; both erase the intended context savings.\n\nFor a machine-readable foreground result, pass `response_format` with a stable name and restricted object JSON Schema. The child gets no additional tools or permissions. It must return exactly one matching JSON object; BLUN validates it and allows at most one bounded repair turn. Do not combine `response_format` with `run_in_background=true`.";
|
|
252971
253208
|
AgentTool = class {
|
|
252972
253209
|
subagentHost;
|
|
252973
253210
|
backgroundManager;
|
|
@@ -252990,10 +253227,11 @@ var init_agent$1 = __esmMin((() => {
|
|
|
252990
253227
|
let profileName = args.subagent_type?.length ? args.subagent_type : "coder";
|
|
252991
253228
|
const resumeAgentId = args.resume?.trim();
|
|
252992
253229
|
if (resumeAgentId !== void 0 && resumeAgentId.length > 0) profileName = await this.subagentHost.getProfileName?.(resumeAgentId) ?? "subagent";
|
|
252993
|
-
const
|
|
253230
|
+
const resolvedRunMode = resolveSubagentRunMode({
|
|
252994
253231
|
allowBackground: this.allowBackground,
|
|
252995
253232
|
requested: args.run_in_background
|
|
252996
253233
|
});
|
|
253234
|
+
const runInBackground = args.response_format === void 0 ? resolvedRunMode.runInBackground : false;
|
|
252997
253235
|
return {
|
|
252998
253236
|
description: `${runInBackground ? "Launching background" : "Launching"} ${profileName} agent: ${args.description}`,
|
|
252999
253237
|
accesses: ToolAccesses.none(),
|
|
@@ -253011,10 +253249,24 @@ var init_agent$1 = __esmMin((() => {
|
|
|
253011
253249
|
async execution(args, { toolCallId, signal }) {
|
|
253012
253250
|
try {
|
|
253013
253251
|
signal.throwIfAborted();
|
|
253014
|
-
|
|
253252
|
+
if (args.response_format !== void 0 && args.run_in_background === true) return {
|
|
253253
|
+
output: "response_format is supported for foreground Agent runs only; remove run_in_background=true.",
|
|
253254
|
+
isError: true
|
|
253255
|
+
};
|
|
253256
|
+
let responseFormat;
|
|
253257
|
+
try {
|
|
253258
|
+
responseFormat = prepareStructuredResponseFormat(args.response_format, compileToolArgsValidator);
|
|
253259
|
+
} catch (error) {
|
|
253260
|
+
return {
|
|
253261
|
+
output: `Invalid response_format: ${error instanceof Error ? error.message : String(error)}`,
|
|
253262
|
+
isError: true
|
|
253263
|
+
};
|
|
253264
|
+
}
|
|
253265
|
+
const resolvedRunMode = resolveSubagentRunMode({
|
|
253015
253266
|
allowBackground: this.allowBackground,
|
|
253016
253267
|
requested: args.run_in_background
|
|
253017
253268
|
});
|
|
253269
|
+
const runInBackground = responseFormat === void 0 ? resolvedRunMode.runInBackground : false;
|
|
253018
253270
|
const requestedProfileName = args.subagent_type?.length ? args.subagent_type : void 0;
|
|
253019
253271
|
const resumeAgentId = args.resume?.trim();
|
|
253020
253272
|
if (resumeAgentId !== void 0 && resumeAgentId.length > 0 && requestedProfileName !== void 0) return {
|
|
@@ -253036,6 +253288,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
253036
253288
|
prompt: args.prompt,
|
|
253037
253289
|
description: args.description,
|
|
253038
253290
|
runInBackground,
|
|
253291
|
+
responseFormat,
|
|
253039
253292
|
signal: controller.signal
|
|
253040
253293
|
};
|
|
253041
253294
|
let handle;
|
|
@@ -253061,7 +253314,8 @@ var init_agent$1 = __esmMin((() => {
|
|
|
253061
253314
|
taskId = this.backgroundManager.registerTask(new AgentBackgroundTask(handle, args.description, this.subagentHost, controller, {
|
|
253062
253315
|
timeoutMs: resolveSubagentTimeoutMs({ perRunMinutes: args.timeout_minutes }),
|
|
253063
253316
|
runInBackground,
|
|
253064
|
-
parentToolCallId: toolCallId
|
|
253317
|
+
parentToolCallId: toolCallId,
|
|
253318
|
+
responseFormat
|
|
253065
253319
|
}), {
|
|
253066
253320
|
detached: runInBackground,
|
|
253067
253321
|
signal: runInBackground ? void 0 : signal
|
|
@@ -253084,7 +253338,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
253084
253338
|
}
|
|
253085
253339
|
if (runInBackground) return { output: formatBackgroundAgentResult(taskId, handle, args.description, this.allowBackground) };
|
|
253086
253340
|
if (await this.backgroundManager.waitForForegroundRelease(taskId) === "detached") return { output: formatBackgroundAgentResult(taskId, handle, args.description, this.allowBackground) };
|
|
253087
|
-
return await this.formatForegroundResult(taskId, handle);
|
|
253341
|
+
return await this.formatForegroundResult(taskId, handle, responseFormat);
|
|
253088
253342
|
} catch (error) {
|
|
253089
253343
|
return {
|
|
253090
253344
|
output: `subagent error: ${launchErrorMessage(error, signal)}`,
|
|
@@ -253092,9 +253346,12 @@ var init_agent$1 = __esmMin((() => {
|
|
|
253092
253346
|
};
|
|
253093
253347
|
}
|
|
253094
253348
|
}
|
|
253095
|
-
async formatForegroundResult(taskId, handle) {
|
|
253349
|
+
async formatForegroundResult(taskId, handle, responseFormat) {
|
|
253096
253350
|
const info = this.backgroundManager.getTask(taskId);
|
|
253097
|
-
if (info?.status === "completed")
|
|
253351
|
+
if (info?.status === "completed") {
|
|
253352
|
+
const output = await this.backgroundManager.readOutput(taskId);
|
|
253353
|
+
return { output: responseFormat === void 0 ? formatForegroundAgentSuccess(handle, output) : output };
|
|
253354
|
+
}
|
|
253098
253355
|
const timedOut = info?.status === "timed_out";
|
|
253099
253356
|
return {
|
|
253100
253357
|
output: formatForegroundAgentFailure(handle, timedOut ? "Agent timed out before automatic continuation could start." : info?.stopReason === "Interrupted by user" ? USER_INTERRUPTED_SUBAGENT_MESSAGE : info?.stopReason !== void 0 ? info.stopReason : "The subagent was stopped before it finished.", timedOut),
|
|
@@ -261161,7 +261418,7 @@ function renderHistoricalToolResultReference(toolName, toolCallId, text, outputP
|
|
|
261161
261418
|
function safeToolResultFileStem(toolName, toolCallId) {
|
|
261162
261419
|
return `${toolName}-${toolCallId}`.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80) || "tool-result";
|
|
261163
261420
|
}
|
|
261164
|
-
var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_HISTORICAL_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldKeepFreshToolResult, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, dedupeRepeatedSuccessfulToolResults, readContinuationLineOffset, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
|
|
261421
|
+
var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_HISTORICAL_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldKeepFreshToolResult, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, currentTurnReadToolResultIds, currentUserTurnStartIndex, dedupeRepeatedSuccessfulToolResults, readContinuationLineOffset, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
|
|
261165
261422
|
var init_tool_result_budget = __esmMin((() => {
|
|
261166
261423
|
init_dist$6();
|
|
261167
261424
|
const toolResultOffloadPolicy = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs");
|
|
@@ -261177,6 +261434,8 @@ var init_tool_result_budget = __esmMin((() => {
|
|
|
261177
261434
|
createToolResultPreview = toolResultOffloadPolicy.createToolResultPreview;
|
|
261178
261435
|
compactPersistedToolResultReference = toolResultOffloadPolicy.compactPersistedToolResultReference;
|
|
261179
261436
|
compactHistoricalSuccessfulToolResults = toolResultOffloadPolicy.compactHistoricalSuccessfulToolResults;
|
|
261437
|
+
currentTurnReadToolResultIds = toolResultOffloadPolicy.currentTurnReadToolResultIds;
|
|
261438
|
+
currentUserTurnStartIndex = toolResultOffloadPolicy.currentUserTurnStartIndex;
|
|
261180
261439
|
dedupeRepeatedSuccessfulToolResults = toolResultOffloadPolicy.dedupeRepeatedSuccessfulToolResults;
|
|
261181
261440
|
freshToolResultIds = toolResultOffloadPolicy.freshToolResultIds;
|
|
261182
261441
|
readContinuationLineOffset = toolResultOffloadPolicy.readContinuationLineOffset;
|
|
@@ -261194,8 +261453,9 @@ var ToolResultBatchOffload = class {
|
|
|
261194
261453
|
async detect() {
|
|
261195
261454
|
const history = this.agent.context.history;
|
|
261196
261455
|
const tailIds = freshToolResultIds(history);
|
|
261456
|
+
const pinnedReadIds = currentTurnReadToolResultIds(history);
|
|
261197
261457
|
const recentStart = Math.max(0, history.length - TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES);
|
|
261198
|
-
const historical = history.slice(0, recentStart).filter((message) => message?.role === "tool" && !tailIds.has(message.toolCallId));
|
|
261458
|
+
const historical = history.slice(0, recentStart).filter((message) => message?.role === "tool" && !tailIds.has(message.toolCallId) && !pinnedReadIds.has(message.toolCallId));
|
|
261199
261459
|
const candidateBatches = [{
|
|
261200
261460
|
messages: historical,
|
|
261201
261461
|
historical: true,
|
|
@@ -261369,7 +261629,7 @@ function renderPersistedUserMessage(text, outputPath) {
|
|
|
261369
261629
|
createUserMessagePreview(text)
|
|
261370
261630
|
].join("\n");
|
|
261371
261631
|
}
|
|
261372
|
-
var USER_MESSAGE_MAX_CHARS, USER_MESSAGE_OFFLOAD_MARKER, shouldOffloadUserMessage, shouldOffloadHistoricalUserMessage, createUserMessagePreview, compactHistoricalPersistedUserMessageReferences, projectHistoricalMediaParts;
|
|
261632
|
+
var USER_MESSAGE_MAX_CHARS, USER_MESSAGE_OFFLOAD_MARKER, shouldOffloadUserMessage, shouldOffloadHistoricalUserMessage, createUserMessagePreview, compactHistoricalPersistedUserMessageReferences, historyTextChars, projectHistoricalMediaParts;
|
|
261373
261633
|
var init_user_message_offload = __esmMin((() => {
|
|
261374
261634
|
const policy = createRequire(import.meta.url)("./bin/user-message-offload-policy.cjs");
|
|
261375
261635
|
USER_MESSAGE_MAX_CHARS = policy.USER_MESSAGE_MAX_CHARS;
|
|
@@ -261377,6 +261637,7 @@ var init_user_message_offload = __esmMin((() => {
|
|
|
261377
261637
|
shouldOffloadUserMessage = policy.shouldOffloadUserMessage;
|
|
261378
261638
|
shouldOffloadHistoricalUserMessage = policy.shouldOffloadHistoricalUserMessage;
|
|
261379
261639
|
createUserMessagePreview = policy.createUserMessagePreview;
|
|
261640
|
+
historyTextChars = policy.historyTextChars;
|
|
261380
261641
|
compactHistoricalPersistedUserMessageReferences = policy.compactHistoricalPersistedUserMessageReferences;
|
|
261381
261642
|
({ projectHistoricalMediaParts } = createRequire(import.meta.url)("./bin/historical-media-projection-policy.cjs"));
|
|
261382
261643
|
}));
|
|
@@ -261389,8 +261650,11 @@ var UserMessageOffload = class {
|
|
|
261389
261650
|
async detect() {
|
|
261390
261651
|
const history = this.agent.context.history;
|
|
261391
261652
|
if (this.agent.homedir === void 0) return 0;
|
|
261653
|
+
const currentTurnStart = currentUserTurnStartIndex(history);
|
|
261654
|
+
const totalHistoryChars = historyTextChars(history);
|
|
261392
261655
|
let offloaded = 0;
|
|
261393
261656
|
for (let historyIndex = 0; historyIndex < history.length; historyIndex++) {
|
|
261657
|
+
if (historyIndex === currentTurnStart) continue;
|
|
261394
261658
|
const message = history[historyIndex];
|
|
261395
261659
|
const text = persistableUserMessageText(message);
|
|
261396
261660
|
if (text === void 0) continue;
|
|
@@ -261398,6 +261662,7 @@ var UserMessageOffload = class {
|
|
|
261398
261662
|
const historicalOversize = shouldOffloadHistoricalUserMessage({
|
|
261399
261663
|
historyIndex,
|
|
261400
261664
|
historyLength: history.length,
|
|
261665
|
+
historyChars: totalHistoryChars,
|
|
261401
261666
|
textChars: text.length
|
|
261402
261667
|
});
|
|
261403
261668
|
if (!immediateOversize && !historicalOversize) continue;
|
|
@@ -261520,6 +261785,7 @@ var AssistantMessageOffload = class {
|
|
|
261520
261785
|
async detect() {
|
|
261521
261786
|
const history = this.agent.context.history;
|
|
261522
261787
|
if (this.agent.homedir === void 0) return 0;
|
|
261788
|
+
const totalHistoryChars = historyTextChars(history);
|
|
261523
261789
|
let offloaded = 0;
|
|
261524
261790
|
for (let historyIndex = 0; historyIndex < history.length; historyIndex++) {
|
|
261525
261791
|
const message = history[historyIndex];
|
|
@@ -261527,6 +261793,7 @@ var AssistantMessageOffload = class {
|
|
|
261527
261793
|
if (text === void 0 || !shouldOffloadHistoricalAssistantMessage({
|
|
261528
261794
|
historyIndex,
|
|
261529
261795
|
historyLength: history.length,
|
|
261796
|
+
historyChars: totalHistoryChars,
|
|
261530
261797
|
textChars: text.length
|
|
261531
261798
|
})) continue;
|
|
261532
261799
|
const messageHash = assistantMessageOffloadHash(message, text);
|
|
@@ -261563,6 +261830,7 @@ var AssistantMessageOffload = class {
|
|
|
261563
261830
|
}
|
|
261564
261831
|
compact(messages) {
|
|
261565
261832
|
const completedToolCallIds = new Set(messages.filter((message) => message?.role === "tool" && message.toolCallId !== void 0).map((message) => message.toolCallId));
|
|
261833
|
+
const totalHistoryChars = historyTextChars(messages);
|
|
261566
261834
|
let changed = false;
|
|
261567
261835
|
const projected = messages.map((message, historyIndex) => {
|
|
261568
261836
|
if (message?.role === "assistant" && message.toolCalls.length > 0) {
|
|
@@ -261572,6 +261840,7 @@ var AssistantMessageOffload = class {
|
|
|
261572
261840
|
if (shouldCompactHistoricalAssistantToolNarration({
|
|
261573
261841
|
historyIndex,
|
|
261574
261842
|
historyLength: messages.length,
|
|
261843
|
+
historyChars: totalHistoryChars,
|
|
261575
261844
|
textChars,
|
|
261576
261845
|
toolCallCount: message.toolCalls.length,
|
|
261577
261846
|
completedToolCallCount
|
|
@@ -261959,7 +262228,7 @@ function durablePromptOrigin(origin) {
|
|
|
261959
262228
|
void externalReportSources;
|
|
261960
262229
|
return durableOrigin;
|
|
261961
262230
|
}
|
|
261962
|
-
var BLUN_CORE_TOOL_NAMES, BLUN_LEAN_TOOL_NAMES, BLUN_ATTACHMENT_MARKER_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TELEGRAM_CHANNEL_RE, BLUN_TOOL_BUDGET_RATIO, createDeferredToolLoader, mediaToolNamesForTurnText, rankedSupportToolNamesForGoal, rankedToolNamesForTurnText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens, enforceSingleTodoWritePerStep, projectRecurringCronHistory, TelegramDeliveryLedger, createRuntimeCognitiveTurnLifecycle, cognitiveFocusScopesForTurn, buildCognitiveWorkFocus, buildAttentionQueueItem, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
262231
|
+
var BLUN_CORE_TOOL_NAMES, BLUN_LEAN_TOOL_NAMES, BLUN_ATTACHMENT_MARKER_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TELEGRAM_CHANNEL_RE, BLUN_TOOL_BUDGET_RATIO, createDeferredToolLoader, mediaToolNamesForTurnText, rankedSupportToolNamesForGoal, rankedToolNamesForTurnText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens, assessTodoListBounds, assessTodoMaintenanceUpdate, enforceSingleTodoWritePerStep, todoRefreshWorkCallLimit, projectRecurringCronHistory, TelegramDeliveryLedger, createRuntimeCognitiveTurnLifecycle, cognitiveFocusScopesForTurn, buildCognitiveWorkFocus, buildAttentionQueueItem, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
261963
262232
|
var init_turn = __esmMin((() => {
|
|
261964
262233
|
init_dist$4();
|
|
261965
262234
|
init_src$4();
|
|
@@ -261977,7 +262246,7 @@ var init_turn = __esmMin((() => {
|
|
|
261977
262246
|
init_user_message_offload();
|
|
261978
262247
|
init_assistant_message_offload();
|
|
261979
262248
|
({ CORE_TOOL_NAMES: BLUN_CORE_TOOL_NAMES, createDeferredToolLoader, mediaToolNamesForTurnText, rankedSupportToolNamesForGoal, rankedToolNamesForTurnText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens } = createRequire(import.meta.url)("./bin/turn-tool-performance-policy.cjs"));
|
|
261980
|
-
({ enforceSingleTodoWritePerStep } = createRequire(import.meta.url)("./bin/todo-list-turn-policy.cjs"));
|
|
262249
|
+
({ assessTodoListBounds, assessTodoMaintenanceUpdate, enforceSingleTodoWritePerStep, todoRefreshWorkCallLimit } = createRequire(import.meta.url)("./bin/todo-list-turn-policy.cjs"));
|
|
261981
262250
|
({ projectRecurringCronHistory } = createRequire(import.meta.url)("./bin/recurring-cron-history-policy.cjs"));
|
|
261982
262251
|
({ TelegramDeliveryLedger } = createRequire(import.meta.url)("./bin/repeated-user-message-projection.cjs"));
|
|
261983
262252
|
({ createRuntimeCognitiveTurnLifecycle } = createRequire(import.meta.url)("./bin/cognitive-turn-lifecycle.cjs"));
|
|
@@ -262789,6 +263058,7 @@ var init_turn = __esmMin((() => {
|
|
|
262789
263058
|
async runStepLoop(turnId, signal, input, origin) {
|
|
262790
263059
|
let stopHookContinuationUsed = false;
|
|
262791
263060
|
let goalOutcomeMessageContinuationUsed = false;
|
|
263061
|
+
let directSteerContinuationPending = false;
|
|
262792
263062
|
const directReplyTurnStop = createDirectReplyTurnStop(blunExtractText(input));
|
|
262793
263063
|
const deduper = new ToolCallDeduplicator({ telemetry: this.agent.telemetry });
|
|
262794
263064
|
if (blunTurnNeedsInitialMcp(input, origin)) await blunWaitForInitialMcpBudget(this.agent.mcp, signal);
|
|
@@ -262913,7 +263183,8 @@ var init_turn = __esmMin((() => {
|
|
|
262913
263183
|
});
|
|
262914
263184
|
return { llm: this.agent.llmForTurn(workStepThinkingEffort), tools: selectedTools };
|
|
262915
263185
|
}
|
|
262916
|
-
|
|
263186
|
+
if (pendingSteers.some((steer) => directMessageAllowsWorkContinuation(blunExtractText(steer.input)))) directSteerContinuationPending = true;
|
|
263187
|
+
const steerEfforts = pendingSteers.map((steer) => blunTurnHasAttachment(steer.input) ? void 0 : selectThinkingEffortForBufferedSteer(blunExtractText(blunThinkingIntentInput(steer.input)), steer.origin.kind));
|
|
262917
263188
|
if (steerEfforts.some((effort) => effort === void 0)) return;
|
|
262918
263189
|
const steerInput = pendingSteers.flatMap((steer) => [...steer.input]);
|
|
262919
263190
|
const steerThinkingEffort = "low";
|
|
@@ -262959,10 +263230,22 @@ var init_turn = __esmMin((() => {
|
|
|
262959
263230
|
deduper.endStep();
|
|
262960
263231
|
return stopForGoalBudget || directReplyTurnStop.shouldStop() ? { stopTurn: true } : void 0;
|
|
262961
263232
|
},
|
|
262962
|
-
|
|
262963
|
-
|
|
262964
|
-
|
|
262965
|
-
|
|
263233
|
+
shouldContinueAfterStop: async (ctx) => {
|
|
263234
|
+
const { signal } = ctx;
|
|
263235
|
+
if (this.matchingSteers().length > 0) return { continue: true };
|
|
263236
|
+
signal.throwIfAborted();
|
|
263237
|
+
if (directSteerContinuationPending) {
|
|
263238
|
+
directSteerContinuationPending = false;
|
|
263239
|
+
this.agent.context.appendUserMessage([{
|
|
263240
|
+
type: "text",
|
|
263241
|
+
text: "The private Telegram DM was handled. Continue the exact work that was active before it arrived. Do not re-read completed evidence; perform the next unfinished action now."
|
|
263242
|
+
}], {
|
|
263243
|
+
kind: "system_trigger",
|
|
263244
|
+
name: "telegram_direct_work_resume"
|
|
263245
|
+
});
|
|
263246
|
+
this.setActiveSteerAcceptance(turnId, true);
|
|
263247
|
+
return { continue: true };
|
|
263248
|
+
}
|
|
262966
263249
|
if (!goalOutcomeMessageContinuationUsed && isGoalOutcomeReminderOrigin(this.agent.context.history.at(-1)?.origin)) {
|
|
262967
263250
|
goalOutcomeMessageContinuationUsed = true;
|
|
262968
263251
|
if (!hasStepBudgetRemaining(loopControl?.maxStepsPerTurn, ctx.stepNumber)) {
|
|
@@ -262997,6 +263280,8 @@ var init_turn = __esmMin((() => {
|
|
|
262997
263280
|
prepareToolExecution: async (ctx) => {
|
|
262998
263281
|
const todoTurnPolicy = enforceSingleTodoWritePerStep(ctx);
|
|
262999
263282
|
if (todoTurnPolicy !== void 0) return todoTurnPolicy;
|
|
263283
|
+
const todoBoundsPolicy = enforceTodoListBounds(this.agent, ctx);
|
|
263284
|
+
if (todoBoundsPolicy !== void 0) return todoBoundsPolicy;
|
|
263000
263285
|
const goalTodoPolicy = enforceGoalTodoPolicy(this.agent, ctx);
|
|
263001
263286
|
if (goalTodoPolicy !== void 0) return goalTodoPolicy;
|
|
263002
263287
|
const ideaPolicy = enforceIdeaToolPolicy(this.agent, ctx);
|
|
@@ -264119,20 +264404,16 @@ var init_codebase_search$1 = __esmMin((() => {
|
|
|
264119
264404
|
* `CODEBASE_INDEX_SCRIPT` env override, then to a search from cwd.
|
|
264120
264405
|
*/
|
|
264121
264406
|
function resolveScriptPath() {
|
|
264122
|
-
|
|
264123
|
-
if (envPath !== void 0 && envPath.length > 0) return envPath;
|
|
264124
|
-
try {
|
|
264125
|
-
return fileURLToPath(new URL("../../../../../codebase-index/codebase_index.py", import.meta.url));
|
|
264126
|
-
} catch {}
|
|
264127
|
-
return "";
|
|
264407
|
+
return resolveCodebaseIndexScript(import.meta.url, process.env["CODEBASE_INDEX_SCRIPT"]);
|
|
264128
264408
|
}
|
|
264129
|
-
var CodebaseSearchInputSchema, SCRIPT_TIMEOUT_MS, CodebaseSearchTool;
|
|
264409
|
+
var resolveCodebaseIndexScript, CodebaseSearchInputSchema, SCRIPT_TIMEOUT_MS, CodebaseSearchTool;
|
|
264130
264410
|
var init_codebase_search = __esmMin((() => {
|
|
264131
264411
|
init_zod$1();
|
|
264132
264412
|
init_rule_match();
|
|
264133
264413
|
init_input_schema();
|
|
264134
264414
|
init_result_builder();
|
|
264135
264415
|
init_codebase_search$1();
|
|
264416
|
+
({ resolveCodebaseIndexScript } = createRequire(import.meta.url)("./bin/codebase-search-runtime.cjs"));
|
|
264136
264417
|
CodebaseSearchInputSchema = object({
|
|
264137
264418
|
query: string().min(1, "Query cannot be empty.").describe("A natural-language question or concept describing what the code does. Examples: \"keyboard event handling\", \"retry with exponential backoff\", \"where chat messages are routed to the model\"."),
|
|
264138
264419
|
top: number$1().int().positive().default(5).describe("Maximum number of results to return. Defaults to 5.")
|
|
@@ -264828,6 +265109,7 @@ var init_builtin = __esmMin((() => {
|
|
|
264828
265109
|
init_exit_plan_mode();
|
|
264829
265110
|
init_bash();
|
|
264830
265111
|
init_todo_list();
|
|
265112
|
+
init_programmatic_tool();
|
|
264831
265113
|
init_fetch_url();
|
|
264832
265114
|
init_web_search();
|
|
264833
265115
|
init_codebase_search();
|
|
@@ -265272,6 +265554,7 @@ var init_tool$1 = __esmMin((() => {
|
|
|
265272
265554
|
goalToolsEnabled && new UpdateGoalTool(this.agent),
|
|
265273
265555
|
this.agent.rpc?.requestQuestion && new AskUserQuestionTool(this.agent),
|
|
265274
265556
|
new TodoListTool(this.toolStore),
|
|
265557
|
+
new ProgrammaticTool(),
|
|
265275
265558
|
new CompactConversationTool(this.agent),
|
|
265276
265559
|
new TaskListTool(background),
|
|
265277
265560
|
new TaskOutputTool(background),
|
|
@@ -265461,6 +265744,9 @@ var init_fallback_llm = __esmMin((() => {
|
|
|
265461
265744
|
get capability() {
|
|
265462
265745
|
return this.current.llm.capability;
|
|
265463
265746
|
}
|
|
265747
|
+
get thinkingEffort() {
|
|
265748
|
+
return this.current.llm.thinkingEffort;
|
|
265749
|
+
}
|
|
265464
265750
|
async prepareRequestBoundary(params, rebuildMessages) {
|
|
265465
265751
|
params.signal.throwIfAborted();
|
|
265466
265752
|
this.rebuildBoundaryMessages = rebuildMessages;
|
|
@@ -314793,7 +315079,17 @@ function resolveModelCapabilities(alias, provider) {
|
|
|
314793
315079
|
};
|
|
314794
315080
|
}
|
|
314795
315081
|
function toKosongProviderConfig(provider, model, blunRequestHeaders, promptCacheKey, supportEfforts) {
|
|
314796
|
-
|
|
315082
|
+
assertSupportedProviderType(provider);
|
|
315083
|
+
if (provider.type === FREDRIK_GLM_PROVIDER_TYPE) return {
|
|
315084
|
+
type: "blun",
|
|
315085
|
+
model,
|
|
315086
|
+
baseUrl: provider.baseUrl,
|
|
315087
|
+
apiKey: readFredrikGlmApiKeyFile(provider),
|
|
315088
|
+
generationKwargs: { prompt_cache_key: promptCacheKey },
|
|
315089
|
+
supportEfforts: [...FREDRIK_GLM_EFFORTS],
|
|
315090
|
+
openAICompatible: true,
|
|
315091
|
+
defaultHeaders: { "User-Agent": "BLUN-King/Fredrik-GLM" }
|
|
315092
|
+
};
|
|
314797
315093
|
const envCustomHeaders = parseBlunCodeCustomHeaders();
|
|
314798
315094
|
return {
|
|
314799
315095
|
type: "blun",
|
|
@@ -314814,11 +315110,12 @@ function defaultHeadersField(headers) {
|
|
|
314814
315110
|
return { defaultHeaders: { ...headers } };
|
|
314815
315111
|
}
|
|
314816
315112
|
function providerApiKey(provider) {
|
|
314817
|
-
|
|
315113
|
+
assertSupportedProviderType(provider);
|
|
315114
|
+
if (provider.type === FREDRIK_GLM_PROVIDER_TYPE) return readFredrikGlmApiKeyFile(provider);
|
|
314818
315115
|
return providerValue(provider.apiKey, provider.env, "BLUN_API_KEY");
|
|
314819
315116
|
}
|
|
314820
|
-
function
|
|
314821
|
-
if (provider.type !== "blun") throw new BlunError(ErrorCodes.MODEL_CONFIG_INVALID, "Only
|
|
315117
|
+
function assertSupportedProviderType(provider) {
|
|
315118
|
+
if (provider.type !== "blun" && provider.type !== FREDRIK_GLM_PROVIDER_TYPE) throw new BlunError(ErrorCodes.MODEL_CONFIG_INVALID, "Only approved BLUN Code provider types are supported.");
|
|
314822
315119
|
}
|
|
314823
315120
|
function providerValue(configured, env, envKey) {
|
|
314824
315121
|
return nonEmptyString$2(configured) ?? envValue(env, envKey);
|
|
@@ -314856,7 +315153,9 @@ var init_provider_manager = __esmMin((() => {
|
|
|
314856
315153
|
if (providerName === void 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, `Model "${model}" must define a provider in config.toml.`);
|
|
314857
315154
|
const providerConfig = this.config.providers[providerName];
|
|
314858
315155
|
if (providerConfig === void 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" for model "${model}" is not configured.`);
|
|
314859
|
-
|
|
315156
|
+
assertSupportedProviderType(providerConfig);
|
|
315157
|
+
if (providerConfig.type === FREDRIK_GLM_PROVIDER_TYPE && (providerName !== FREDRIK_GLM_PROVIDER_ID || !isConfiguredFredrikGlmAlias(model, alias))) throw new BlunError(ErrorCodes.CONFIG_INVALID, "Fredrik GLM provider aliases must match the approved profile-local model catalog.");
|
|
315158
|
+
if (providerConfig.type !== FREDRIK_GLM_PROVIDER_TYPE && isConfiguredFredrikGlmAlias(model, alias)) throw new BlunError(ErrorCodes.CONFIG_INVALID, "Fredrik GLM aliases require the approved profile-local provider.");
|
|
314860
315159
|
const runtimeContext = this.runtimeModelContexts.get(model);
|
|
314861
315160
|
const maxContextSize = runtimeContext?.providerName === providerName && runtimeContext.model === alias.model ? runtimeContext.maxContextTokens : effectiveAlias.maxContextSize;
|
|
314862
315161
|
if (!Number.isInteger(maxContextSize) || maxContextSize <= 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, `Model "${model}" must define a positive max_context_size in config.toml.`);
|
|
@@ -314870,7 +315169,7 @@ var init_provider_manager = __esmMin((() => {
|
|
|
314870
315169
|
}, provider),
|
|
314871
315170
|
alwaysThinking: (effectiveAlias.capabilities ?? []).some((c) => c.trim().toLowerCase() === "always_thinking"),
|
|
314872
315171
|
maxOutputSize: effectiveAlias.maxOutputSize,
|
|
314873
|
-
type:
|
|
315172
|
+
type: providerConfig.type
|
|
314874
315173
|
};
|
|
314875
315174
|
}
|
|
314876
315175
|
setRuntimeModelContext(input) {
|
|
@@ -314890,7 +315189,7 @@ var init_provider_manager = __esmMin((() => {
|
|
|
314890
315189
|
resolveAuth(model, options) {
|
|
314891
315190
|
const { providerName } = this.resolveProviderConfig(model);
|
|
314892
315191
|
const providerConfig = this.config.providers[providerName];
|
|
314893
|
-
const apiKey = providerConfig ===
|
|
315192
|
+
const apiKey = providerConfig?.type === "blun" ? providerApiKey(providerConfig) : void 0;
|
|
314894
315193
|
const revocationStore = this.options.managedApiKeyRevocationStore;
|
|
314895
315194
|
if (providerName === MANAGED_PROVIDER_NAME$2 && providerConfig?.oauth === void 0 && apiKey !== void 0 && revocationStore !== void 0) return this.resolveManagedApiKeyAuth(providerName, apiKey, revocationStore, options?.log);
|
|
314896
315195
|
if (providerConfig?.oauth === void 0) return void 0;
|
|
@@ -402988,7 +403287,7 @@ function createProgram(version, onMain, onPluginNodeRunner = () => {}) {
|
|
|
402988
403287
|
"high",
|
|
402989
403288
|
"xhigh",
|
|
402990
403289
|
"max"
|
|
402991
|
-
])).addOption(new Option("--permission-mode <mode>", "Permission mode for this invocation (auto, manual, yolo).").choices([
|
|
403290
|
+
])).option("--swarm", "Start in swarm mode.", false).addOption(new Option("--permission-mode <mode>", "Permission mode for this invocation (auto, manual, yolo).").choices([
|
|
402992
403291
|
"auto",
|
|
402993
403292
|
"manual",
|
|
402994
403293
|
"yolo"
|
|
@@ -403022,6 +403321,7 @@ function createProgram(version, onMain, onPluginNodeRunner = () => {}) {
|
|
|
403022
403321
|
plan: raw["plan"],
|
|
403023
403322
|
model: raw["model"],
|
|
403024
403323
|
effort: raw["effort"],
|
|
403324
|
+
swarm: raw["swarm"] === true,
|
|
403025
403325
|
permissionMode: raw["permissionMode"],
|
|
403026
403326
|
forkSession: raw["forkSession"],
|
|
403027
403327
|
outputFormat: raw["outputFormat"],
|
|
@@ -403908,6 +404208,13 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
|
|
|
403908
404208
|
completeArgs: swarmArgumentCompletions,
|
|
403909
404209
|
availability: "idle-only"
|
|
403910
404210
|
},
|
|
404211
|
+
{
|
|
404212
|
+
name: "model",
|
|
404213
|
+
aliases: [],
|
|
404214
|
+
descriptionKey: "command.model.description",
|
|
404215
|
+
priority: 96,
|
|
404216
|
+
availability: "always"
|
|
404217
|
+
},
|
|
403911
404218
|
{
|
|
403912
404219
|
name: "effort",
|
|
403913
404220
|
aliases: ["thinking"],
|
|
@@ -404359,7 +404666,6 @@ registerUiCatalogFragment({
|
|
|
404359
404666
|
//#endregion
|
|
404360
404667
|
//#region src/tui/commands/resolve.ts
|
|
404361
404668
|
const LEGACY_EFFORT_COMMANDS = new Set([
|
|
404362
|
-
"model",
|
|
404363
404669
|
"automodel",
|
|
404364
404670
|
"router"
|
|
404365
404671
|
]);
|
|
@@ -416599,7 +416905,7 @@ const EFFORT_STAGE_LABELS = {
|
|
|
416599
416905
|
medium: "Deep",
|
|
416600
416906
|
high: "Forge",
|
|
416601
416907
|
xhigh: "Apex",
|
|
416602
|
-
max: "
|
|
416908
|
+
max: "Max"
|
|
416603
416909
|
};
|
|
416604
416910
|
const EFFORT_DISPLAY_LABEL_KEYS = {
|
|
416605
416911
|
off: "effort.value.off",
|
|
@@ -416728,15 +417034,13 @@ var EffortSelectorComponent = class extends Container {
|
|
|
416728
417034
|
}
|
|
416729
417035
|
if (matchesKey(data, Key.alt("s")) && this.opts.onSessionOnlySelect !== void 0) {
|
|
416730
417036
|
const effort = this.selectedEffort;
|
|
416731
|
-
if (effort
|
|
416732
|
-
else if (effort !== void 0) this.opts.onSessionOnlySelect(effort);
|
|
417037
|
+
if (effort !== void 0) this.opts.onSessionOnlySelect(effort);
|
|
416733
417038
|
return;
|
|
416734
417039
|
}
|
|
416735
417040
|
if (matchesKey(data, Key.enter)) if (this.isBlunSwarmSelected) this.opts.onBlunSwarmSelect?.();
|
|
416736
417041
|
else {
|
|
416737
417042
|
const effort = this.selectedEffort;
|
|
416738
|
-
if (effort
|
|
416739
|
-
else if (effort !== void 0) this.opts.onSelect(effort);
|
|
417043
|
+
if (effort !== void 0) this.opts.onSelect(effort);
|
|
416740
417044
|
}
|
|
416741
417045
|
}
|
|
416742
417046
|
render(width) {
|
|
@@ -416766,9 +417070,6 @@ var EffortSelectorComponent = class extends Container {
|
|
|
416766
417070
|
get isBlunSwarmSelected() {
|
|
416767
417071
|
return this.hasSeparatedBlunSwarm && this.activeIndex === this.efforts.length;
|
|
416768
417072
|
}
|
|
416769
|
-
get usesLegacyServerStageScale() {
|
|
416770
|
-
return isServerStageScale(this.efforts);
|
|
416771
|
-
}
|
|
416772
417073
|
get hasSeparatedBlunSwarm() {
|
|
416773
417074
|
return this.opts.onBlunSwarmSelect !== void 0 && !usesInlineStageScale(this.efforts);
|
|
416774
417075
|
}
|
|
@@ -417401,6 +417702,168 @@ function segmentsFor(model) {
|
|
|
417401
417702
|
if (availability === "unsupported") return ["off"];
|
|
417402
417703
|
return ["off", "on"];
|
|
417403
417704
|
}
|
|
417705
|
+
function fredrikSelectableModels(models) {
|
|
417706
|
+
return Object.fromEntries(Object.entries(models).filter(([alias]) => isAllowedFredrikRuntimeAlias(alias, models)));
|
|
417707
|
+
}
|
|
417708
|
+
function fredrikProviderDisplayName(provider) {
|
|
417709
|
+
if (provider === "managed:blun") return PRODUCT_NAME;
|
|
417710
|
+
if (provider.startsWith("managed:")) return provider.slice(8);
|
|
417711
|
+
return provider;
|
|
417712
|
+
}
|
|
417713
|
+
function fredrikCreateModelChoices(models) {
|
|
417714
|
+
return Object.entries(fredrikSelectableModels(models)).map(([alias, configured]) => {
|
|
417715
|
+
const model = effectiveModelAlias(configured);
|
|
417716
|
+
const name = modelDisplayName$1(alias, model);
|
|
417717
|
+
const provider = fredrikProviderDisplayName(model.provider);
|
|
417718
|
+
return {
|
|
417719
|
+
alias,
|
|
417720
|
+
model,
|
|
417721
|
+
name,
|
|
417722
|
+
provider,
|
|
417723
|
+
label: `${name} (${provider})`
|
|
417724
|
+
};
|
|
417725
|
+
});
|
|
417726
|
+
}
|
|
417727
|
+
function fredrikEffortLabel(effort) {
|
|
417728
|
+
const label = effortDisplayLabel(effort);
|
|
417729
|
+
if (label !== effort || effort.length === 0) return label;
|
|
417730
|
+
return effort.charAt(0).toUpperCase() + effort.slice(1);
|
|
417731
|
+
}
|
|
417732
|
+
function fredrikDefaultThinkingEffort(model) {
|
|
417733
|
+
if (thinkingAvailability(model) === "unsupported") return "off";
|
|
417734
|
+
const efforts = effortsOf(model);
|
|
417735
|
+
if (efforts.length > 0) return model.defaultEffort ?? efforts[Math.floor(efforts.length / 2)];
|
|
417736
|
+
return "on";
|
|
417737
|
+
}
|
|
417738
|
+
function fredrikCommitEffort(choice, draft) {
|
|
417739
|
+
if (draft === "on") return fredrikDefaultThinkingEffort(choice.model);
|
|
417740
|
+
return draft;
|
|
417741
|
+
}
|
|
417742
|
+
var FredrikModelSelectorComponent = class extends Container {
|
|
417743
|
+
focused = false;
|
|
417744
|
+
opts;
|
|
417745
|
+
list;
|
|
417746
|
+
thinkingOverrides = /* @__PURE__ */ new Map();
|
|
417747
|
+
ignoreSubmitTailUntil = Date.now() + 250;
|
|
417748
|
+
constructor(opts) {
|
|
417749
|
+
super();
|
|
417750
|
+
this.opts = opts;
|
|
417751
|
+
const choices = fredrikCreateModelChoices(opts.models);
|
|
417752
|
+
const selectedIndex = choices.findIndex((choice) => choice.alias === (opts.selectedValue ?? opts.currentValue));
|
|
417753
|
+
this.list = new SearchableList({
|
|
417754
|
+
items: choices,
|
|
417755
|
+
toSearchText: (choice) => choice.label,
|
|
417756
|
+
initialIndex: Math.max(selectedIndex, 0),
|
|
417757
|
+
searchable: opts.searchable === true
|
|
417758
|
+
});
|
|
417759
|
+
}
|
|
417760
|
+
draftFor(choice) {
|
|
417761
|
+
const override = this.thinkingOverrides.get(choice.alias);
|
|
417762
|
+
if (override !== void 0) return override;
|
|
417763
|
+
if (choice.alias === this.opts.currentValue) return this.opts.currentThinkingEffort;
|
|
417764
|
+
const efforts = effortsOf(choice.model);
|
|
417765
|
+
if (efforts.length > 0) {
|
|
417766
|
+
const fallback = choice.model.defaultEffort ?? efforts[Math.floor(efforts.length / 2)];
|
|
417767
|
+
if (fallback !== void 0 && efforts.includes(fallback)) return fallback;
|
|
417768
|
+
return efforts[0];
|
|
417769
|
+
}
|
|
417770
|
+
return thinkingAvailability(choice.model) !== "unsupported" ? "on" : "off";
|
|
417771
|
+
}
|
|
417772
|
+
effectiveEffort(choice) {
|
|
417773
|
+
const draft = this.draftFor(choice);
|
|
417774
|
+
const segments = segmentsFor(choice.model);
|
|
417775
|
+
return segments.includes(draft) ? draft : segments[0];
|
|
417776
|
+
}
|
|
417777
|
+
handleInput(data) {
|
|
417778
|
+
if (isKeyRelease(data)) return;
|
|
417779
|
+
if (Date.now() <= this.ignoreSubmitTailUntil && /^[\r\n]+$/.test(data)) return;
|
|
417780
|
+
this.ignoreSubmitTailUntil = 0;
|
|
417781
|
+
if (matchesKey(data, Key.escape)) {
|
|
417782
|
+
if (this.list.clearQuery()) return;
|
|
417783
|
+
this.opts.onCancel();
|
|
417784
|
+
return;
|
|
417785
|
+
}
|
|
417786
|
+
if (this.list.handleKey(data)) return;
|
|
417787
|
+
if (matchesKey(data, Key.left) || matchesKey(data, Key.right)) {
|
|
417788
|
+
const selected = this.selectedChoice();
|
|
417789
|
+
if (selected !== void 0) {
|
|
417790
|
+
const segments = segmentsFor(selected.model);
|
|
417791
|
+
if (segments.length > 1) {
|
|
417792
|
+
const current = this.effectiveEffort(selected);
|
|
417793
|
+
const index = segments.indexOf(current);
|
|
417794
|
+
const delta = matchesKey(data, Key.left) ? -1 : 1;
|
|
417795
|
+
const next = Math.max(0, Math.min(segments.length - 1, index + delta));
|
|
417796
|
+
if (next !== index) this.thinkingOverrides.set(selected.alias, segments[next]);
|
|
417797
|
+
}
|
|
417798
|
+
}
|
|
417799
|
+
return;
|
|
417800
|
+
}
|
|
417801
|
+
if (matchesKey(data, Key.enter)) {
|
|
417802
|
+
const selected = this.selectedChoice();
|
|
417803
|
+
if (selected === void 0) return;
|
|
417804
|
+
this.opts.onSelect({
|
|
417805
|
+
alias: selected.alias,
|
|
417806
|
+
thinking: fredrikCommitEffort(selected, this.effectiveEffort(selected))
|
|
417807
|
+
});
|
|
417808
|
+
return;
|
|
417809
|
+
}
|
|
417810
|
+
if (matchesKey(data, Key.alt("s")) && this.opts.onSessionOnlySelect !== void 0) {
|
|
417811
|
+
const selected = this.selectedChoice();
|
|
417812
|
+
if (selected === void 0) return;
|
|
417813
|
+
this.opts.onSessionOnlySelect({
|
|
417814
|
+
alias: selected.alias,
|
|
417815
|
+
thinking: fredrikCommitEffort(selected, this.effectiveEffort(selected))
|
|
417816
|
+
});
|
|
417817
|
+
}
|
|
417818
|
+
}
|
|
417819
|
+
render(width) {
|
|
417820
|
+
const view = this.list.view();
|
|
417821
|
+
const totalCount = Object.keys(fredrikSelectableModels(this.opts.models)).length;
|
|
417822
|
+
const titleSuffix = this.opts.searchable === true && view.query.length === 0 ? currentTheme.fg("textMuted", ` (${uiText("model.typeToSearch")})`) : "";
|
|
417823
|
+
const lines = [
|
|
417824
|
+
currentTheme.fg("primary", "-".repeat(width)),
|
|
417825
|
+
currentTheme.boldFg("primary", ` ${uiText("model.title")}`) + titleSuffix,
|
|
417826
|
+
currentTheme.fg("textMuted", ` ${uiText("model.navigate")} | ${uiText("model.thinking")} (Left/Right) | Enter ${uiText("model.select")} | Esc ${uiText("model.cancel")}`),
|
|
417827
|
+
""
|
|
417828
|
+
];
|
|
417829
|
+
if (view.query.length > 0) lines.push(currentTheme.fg("primary", ` ${uiText("model.search")}: `) + currentTheme.fg("text", view.query));
|
|
417830
|
+
if (view.items.length === 0) lines.push(currentTheme.fg("textMuted", ` ${uiText("model.noMatches")}`));
|
|
417831
|
+
for (let index = view.page.start; index < view.page.end; index++) {
|
|
417832
|
+
const choice = view.items[index];
|
|
417833
|
+
if (choice === void 0) continue;
|
|
417834
|
+
const selected = index === view.selectedIndex;
|
|
417835
|
+
const current = choice.alias === this.opts.currentValue;
|
|
417836
|
+
const pointer = selected ? ">" : " ";
|
|
417837
|
+
let line = currentTheme.fg(selected ? "primary" : "textDim", ` ${pointer} `);
|
|
417838
|
+
line += selected ? currentTheme.boldFg("primary", choice.name) : currentTheme.fg("text", choice.name);
|
|
417839
|
+
line += " " + currentTheme.fg("textMuted", choice.provider);
|
|
417840
|
+
if (current) line += " " + currentTheme.fg("success", currentMark());
|
|
417841
|
+
lines.push(line);
|
|
417842
|
+
}
|
|
417843
|
+
if (view.query.length > 0) lines.push("", currentTheme.fg("textMuted", ` ${String(view.items.length)} / ${String(totalCount)}`));
|
|
417844
|
+
lines.push("");
|
|
417845
|
+
const selected = this.selectedChoice();
|
|
417846
|
+
if (selected !== void 0) {
|
|
417847
|
+
lines.push(currentTheme.fg("textMuted", ` ${uiText("model.thinking")} (Left/Right ${uiText("model.toSwitch")})`));
|
|
417848
|
+
lines.push(this.renderThinkingControl(selected));
|
|
417849
|
+
}
|
|
417850
|
+
lines.push("", currentTheme.fg("primary", "-".repeat(width)));
|
|
417851
|
+
return lines.map((line) => truncateToWidth(line, width));
|
|
417852
|
+
}
|
|
417853
|
+
selectedChoice() {
|
|
417854
|
+
return this.list.selected();
|
|
417855
|
+
}
|
|
417856
|
+
renderThinkingControl(choice) {
|
|
417857
|
+
const segment = (label, active) => active ? currentTheme.boldFg("primary", `[ ${label} ]`) : currentTheme.fg("text", ` ${label} `);
|
|
417858
|
+
const unavailable = (label) => currentTheme.fg("textMuted", ` ${label} (${uiText("model.unsupported")}) `);
|
|
417859
|
+
const efforts = effortsOf(choice.model);
|
|
417860
|
+
const availability = thinkingAvailability(choice.model);
|
|
417861
|
+
if (efforts.length === 0 && availability === "always-on") return ` ${segment(uiText("model.on"), true)} ${unavailable(uiText("model.off"))}`;
|
|
417862
|
+
if (efforts.length === 0 && availability === "unsupported") return ` ${unavailable(uiText("model.on"))} ${segment(uiText("model.off"), true)}`;
|
|
417863
|
+
const active = this.effectiveEffort(choice);
|
|
417864
|
+
return ` ${segmentsFor(choice.model).map((effort) => segment(fredrikEffortLabel(effort), effort === active)).join(" ")}`;
|
|
417865
|
+
}
|
|
417866
|
+
};
|
|
417404
417867
|
//#endregion
|
|
417405
417868
|
//#region src/tui/components/dialogs/permission-selector.ts
|
|
417406
417869
|
function permissionOptions() {
|
|
@@ -419762,7 +420225,7 @@ registerUiCatalogFragment({
|
|
|
419762
420225
|
*/
|
|
419763
420226
|
var { projectUnaddressedTelegramContext } = createRequire(import.meta.url)("./bin/telegram-context-projection-policy.cjs");
|
|
419764
420227
|
var { enqueueTelegramUrgent, rewriteTelegramUrgentEnvelope, telegramUrgentMessage } = createRequire(import.meta.url)("./bin/telegram-urgent-policy.cjs");
|
|
419765
|
-
var { createDirectFocusController, createDirectReplyTurnStop, enqueueTelegramDirect, readDirectFocusCheckpoint, rewriteTelegramDirectEnvelope, telegramDirectMessage, writeDirectFocusCheckpoint } = createRequire(import.meta.url)("./bin/telegram-direct-focus-policy.cjs");
|
|
420228
|
+
var { createDirectFocusController, createDirectReplyTurnStop, directMessageAllowsWorkContinuation, enqueueTelegramDirect, readDirectFocusCheckpoint, rewriteTelegramDirectEnvelope, telegramDirectMessage, writeDirectFocusCheckpoint } = createRequire(import.meta.url)("./bin/telegram-direct-focus-policy.cjs");
|
|
419766
420229
|
var { enqueueTelegramAddressed } = createRequire(import.meta.url)("./bin/telegram-addressed-priority.cjs");
|
|
419767
420230
|
var { enqueueTelegramBotPriority, telegramBotPriorityMessage } = createRequire(import.meta.url)("./bin/telegram-bot-priority.cjs");
|
|
419768
420231
|
var { createAddressedChannelFocusStore } = createRequire(import.meta.url)("./bin/telegram-addressed-focus.cjs");
|
|
@@ -421206,6 +421669,47 @@ async function handleThemeCommand(host, args) {
|
|
|
421206
421669
|
}
|
|
421207
421670
|
await applyThemeChoice(host, theme);
|
|
421208
421671
|
}
|
|
421672
|
+
function resolveFredrikModelArgument(models, raw) {
|
|
421673
|
+
const query = raw.trim().toLowerCase();
|
|
421674
|
+
if (query.length === 0) return void 0;
|
|
421675
|
+
return Object.entries(models).filter(([alias]) => isAllowedFredrikRuntimeAlias(alias, models)).find(([alias, model]) => [alias, model.model, model.displayName].filter((value) => typeof value === "string").some((value) => value.toLowerCase() === query))?.[0];
|
|
421676
|
+
}
|
|
421677
|
+
function showFredrikModelPicker(host, selectedValue = host.state.appState.model) {
|
|
421678
|
+
const models = fredrikSelectableModels(host.state.appState.availableModels);
|
|
421679
|
+
host.mountEditorReplacement(new FredrikModelSelectorComponent({
|
|
421680
|
+
models,
|
|
421681
|
+
currentValue: host.state.appState.model,
|
|
421682
|
+
selectedValue,
|
|
421683
|
+
currentThinkingEffort: host.state.appState.thinkingEffort,
|
|
421684
|
+
searchable: true,
|
|
421685
|
+
onSelect: (selection) => {
|
|
421686
|
+
host.restoreEditorAfter(() => performModelSwitch(host, selection.alias, selection.thinking, false));
|
|
421687
|
+
},
|
|
421688
|
+
onSessionOnlySelect: (selection) => {
|
|
421689
|
+
host.restoreEditorAfter(() => performModelSwitch(host, selection.alias, selection.thinking, false));
|
|
421690
|
+
},
|
|
421691
|
+
onCancel: () => {
|
|
421692
|
+
host.restoreEditor();
|
|
421693
|
+
}
|
|
421694
|
+
}));
|
|
421695
|
+
}
|
|
421696
|
+
async function handleModelCommand(host, args) {
|
|
421697
|
+
if (host.session === void 0) {
|
|
421698
|
+
host.showError(noActiveSessionMessage());
|
|
421699
|
+
return;
|
|
421700
|
+
}
|
|
421701
|
+
const raw = args.trim();
|
|
421702
|
+
if (raw.length === 0) {
|
|
421703
|
+
showFredrikModelPicker(host);
|
|
421704
|
+
return;
|
|
421705
|
+
}
|
|
421706
|
+
const alias = resolveFredrikModelArgument(host.state.appState.availableModels, raw);
|
|
421707
|
+
if (alias === void 0) {
|
|
421708
|
+
host.showError(uiText("config.model.unknownAlias", { alias: raw }));
|
|
421709
|
+
return;
|
|
421710
|
+
}
|
|
421711
|
+
showFredrikModelPicker(host, alias);
|
|
421712
|
+
}
|
|
421209
421713
|
async function handleEffortCommand(host, args) {
|
|
421210
421714
|
const alias = host.state.appState.model;
|
|
421211
421715
|
const model = host.state.appState.availableModels[alias];
|
|
@@ -421237,7 +421741,7 @@ async function handleEffortCommand(host, args) {
|
|
|
421237
421741
|
}));
|
|
421238
421742
|
return;
|
|
421239
421743
|
}
|
|
421240
|
-
await performEffortSelection(host, alias, arg,
|
|
421744
|
+
await performEffortSelection(host, alias, arg, !isConfiguredFredrikGlmAlias(alias, model));
|
|
421241
421745
|
}
|
|
421242
421746
|
function showEffortPicker(host, model, segments) {
|
|
421243
421747
|
const liveEffort = host.state.appState.thinkingEffort;
|
|
@@ -421248,7 +421752,7 @@ function showEffortPicker(host, model, segments) {
|
|
|
421248
421752
|
currentValue,
|
|
421249
421753
|
currentBlunSwarm: host.state.appState.swarmMode && host.state.appState.swarmModeEntry === "effort",
|
|
421250
421754
|
onSelect: (effort) => {
|
|
421251
|
-
host.restoreEditorAfter(() => performEffortSelection(host, alias, effort,
|
|
421755
|
+
host.restoreEditorAfter(() => performEffortSelection(host, alias, effort, !isConfiguredFredrikGlmAlias(alias, host.state.appState.availableModels[alias])));
|
|
421252
421756
|
},
|
|
421253
421757
|
onSessionOnlySelect: (effort) => {
|
|
421254
421758
|
host.restoreEditorAfter(() => performEffortSelection(host, alias, effort, false));
|
|
@@ -421433,7 +421937,7 @@ async function performEffortSelection(host, alias, effort, persist) {
|
|
|
421433
421937
|
host.setAppState({
|
|
421434
421938
|
thinkingEffort: effort,
|
|
421435
421939
|
modelFallbackAllowed: false,
|
|
421436
|
-
swarmMode:
|
|
421940
|
+
swarmMode: input.cliOptions.swarm === true,
|
|
421437
421941
|
swarmModeEntry: void 0
|
|
421438
421942
|
});
|
|
421439
421943
|
renderSwarmModeMarker(host, "inactive");
|
|
@@ -423409,7 +423913,6 @@ async function handleGoalCommand(host, args) {
|
|
|
423409
423913
|
}
|
|
423410
423914
|
const IDEA_CONTRACT_MARKER = "Work as a self-directing employee:";
|
|
423411
423915
|
const IDEA_ALLOWED_CHANNELS = Object.freeze([]);
|
|
423412
|
-
const GOAL_TODO_REFRESH_WORK_CALL_LIMIT = 8;
|
|
423413
423916
|
const GOAL_TODO_EVIDENCE_LIMIT = 8;
|
|
423414
423917
|
const TODO_MAINTENANCE_RECOVERY_TOOL_NAMES = new Set([
|
|
423415
423918
|
"TodoList",
|
|
@@ -423435,6 +423938,22 @@ function ideaTodos(agent) {
|
|
|
423435
423938
|
const value = agent.tools.store?.["todo"];
|
|
423436
423939
|
return Array.isArray(value) ? value : [];
|
|
423437
423940
|
}
|
|
423941
|
+
function goalTodoProgressState(agent) {
|
|
423942
|
+
return agent.goalTodoPolicyState ??= {
|
|
423943
|
+
workCallsSinceRefresh: 0,
|
|
423944
|
+
refreshRequired: false,
|
|
423945
|
+
unchangedRefreshStreak: 0,
|
|
423946
|
+
evidenceRevision: 0,
|
|
423947
|
+
lastMaintenanceEvidenceRevision: 0
|
|
423948
|
+
};
|
|
423949
|
+
}
|
|
423950
|
+
function enforceTodoListBounds(agent, context) {
|
|
423951
|
+
if (context.toolCall.name !== "TodoList" || !Array.isArray(context.args?.todos)) return;
|
|
423952
|
+
return assessTodoListBounds({
|
|
423953
|
+
currentTodos: ideaTodos(agent),
|
|
423954
|
+
nextTodos: context.args.todos
|
|
423955
|
+
});
|
|
423956
|
+
}
|
|
423438
423957
|
function validInitialIdeaPlan(value) {
|
|
423439
423958
|
if (!Array.isArray(value) || value.length === 0) return false;
|
|
423440
423959
|
let active = 0;
|
|
@@ -423471,28 +423990,21 @@ function goalTodoEvidenceLabel(toolName, args, isError) {
|
|
|
423471
423990
|
function recordGoalTodoEvidence(agent, toolName, args, isError) {
|
|
423472
423991
|
if (isIdeaGoal(agent) || agent.goal.getActiveGoal() === null) return;
|
|
423473
423992
|
const name = String(toolName ?? "");
|
|
423474
|
-
const progress = agent
|
|
423475
|
-
|
|
423476
|
-
refreshRequired: false
|
|
423477
|
-
};
|
|
423478
|
-
if (name === "TodoList") {
|
|
423479
|
-
if (isError !== true) progress.recentEvidence = [];
|
|
423480
|
-
return;
|
|
423481
|
-
}
|
|
423993
|
+
const progress = goalTodoProgressState(agent);
|
|
423994
|
+
if (name === "TodoList") return;
|
|
423482
423995
|
if (name === "UpdateGoal" || TELEGRAM_DELIVERY_TOOL_RE.test(name)) return;
|
|
423483
423996
|
const recentEvidence = Array.isArray(progress.recentEvidence) ? progress.recentEvidence : [];
|
|
423484
423997
|
recentEvidence.push(goalTodoEvidenceLabel(name, args, isError));
|
|
423485
423998
|
progress.recentEvidence = recentEvidence.slice(-GOAL_TODO_EVIDENCE_LIMIT);
|
|
423999
|
+
progress.evidenceRevision = (Number(progress.evidenceRevision) || 0) + 1;
|
|
423486
424000
|
}
|
|
423487
424001
|
function goalTodoMaintenanceMode(agent) {
|
|
423488
424002
|
if (isIdeaGoal(agent)) return null;
|
|
423489
424003
|
const todos = ideaTodos(agent);
|
|
423490
424004
|
if (todos.length === 0) return agent.goal.getActiveGoal() === null ? null : "initial";
|
|
423491
|
-
const progress = agent
|
|
423492
|
-
|
|
423493
|
-
|
|
423494
|
-
};
|
|
423495
|
-
if (!progress.refreshRequired && progress.workCallsSinceRefresh < GOAL_TODO_REFRESH_WORK_CALL_LIMIT) return null;
|
|
424005
|
+
const progress = goalTodoProgressState(agent);
|
|
424006
|
+
const refreshWorkCallLimit = todoRefreshWorkCallLimit(progress.unchangedRefreshStreak);
|
|
424007
|
+
if (!progress.refreshRequired && progress.workCallsSinceRefresh < refreshWorkCallLimit) return null;
|
|
423496
424008
|
progress.refreshRequired = true;
|
|
423497
424009
|
return "refresh";
|
|
423498
424010
|
}
|
|
@@ -423506,8 +424018,9 @@ function goalTodoMaintenanceTools(eligibleTools, selectedTools) {
|
|
|
423506
424018
|
}
|
|
423507
424019
|
function buildGoalTodoMaintenanceSystemPrompt(agent, mode) {
|
|
423508
424020
|
const todos = ideaTodos(agent);
|
|
424021
|
+
const requireConcreteProgress = mode === "refresh" && (agent.goalTodoPolicyState?.unchangedRefreshStreak ?? 0) >= 2;
|
|
423509
424022
|
const visibleTodoList = todos.length === 0 ? "The visible TodoList is empty." : ["Current visible TodoList:", ...todos.map((todo) => `- [${String(todo?.status ?? "pending")}] ${String(todo?.title ?? "").trim()}`)].join("\n");
|
|
423510
|
-
const action = mode === "initial" ? "Create the visible task-specific TodoList now. Keep exactly one item in_progress and every later item pending." : "Update the visible TodoList now, before any more task work. Mark only evidenced steps done, keep the actual current step in_progress, and leave later steps pending. If the current title is stale, refine it to the concrete verified substep.";
|
|
424023
|
+
const action = mode === "initial" ? "Create the visible task-specific TodoList now. Keep exactly one item in_progress and every later item pending." : requireConcreteProgress ? "Recent TodoList refreshes stayed semantically unchanged despite new work-tool evidence. Make a truthful concrete transition now: mark evidenced items done, refine the active title to the next verified substep, or record blocked, waiting_approval, or aborted when that is the real state. If the available evidence proves no boundary, preserve the list unchanged; the call remains executable." : "Update the visible TodoList now, before any more task work. Mark only evidenced steps done, keep the actual current step in_progress, and leave later steps pending. If the current title is stale, refine it to the concrete verified substep.";
|
|
423511
424024
|
return `<todo-maintenance>
|
|
423512
424025
|
TODO MAINTENANCE IS THE ONLY ACTION FOR THIS STEP.
|
|
423513
424026
|
${action}
|
|
@@ -423519,11 +424032,12 @@ ${visibleTodoList}
|
|
|
423519
424032
|
function buildGoalTodoMaintenanceMessages(agent, mode) {
|
|
423520
424033
|
const goal = agent.goal.getActiveGoal();
|
|
423521
424034
|
const todos = ideaTodos(agent);
|
|
424035
|
+
const requireConcreteProgress = mode === "refresh" && (agent.goalTodoPolicyState?.unchangedRefreshStreak ?? 0) >= 2;
|
|
423522
424036
|
const recentEvidence = Array.isArray(agent.goalTodoPolicyState?.recentEvidence) ? agent.goalTodoPolicyState.recentEvidence.slice(-GOAL_TODO_EVIDENCE_LIMIT) : [];
|
|
423523
424037
|
const objective = String(goal?.objective ?? "Continue the current multi-step task.").trim();
|
|
423524
424038
|
const visibleTodoList = todos.length === 0 ? "The visible TodoList is empty." : ["Current visible TodoList:", ...todos.map((todo) => `- [${String(todo?.status ?? "pending")}] ${String(todo?.title ?? "").trim()}`)].join("\n");
|
|
423525
424039
|
const verifiedEvidence = recentEvidence.length === 0 ? "No new work-tool evidence is available." : ["Recent bounded work-tool evidence since the last accepted TodoList:", ...recentEvidence.map((entry) => `- ${entry}`)].join("\n");
|
|
423526
|
-
const action = mode === "initial" ? "Create the task-specific TodoList from the active objective. Keep exactly one item in_progress and every later item pending." : "Refresh the TodoList from the current verified state. Mark finished work done, keep the actual current step in_progress, and leave later work pending. Completed items disappear automatically after this call.";
|
|
424040
|
+
const action = mode === "initial" ? "Create the task-specific TodoList from the active objective. Keep exactly one item in_progress and every later item pending." : requireConcreteProgress ? "The recent refreshes stayed semantically unchanged despite new evidence. Make a truthful concrete transition now: finish evidenced items, refine the active title to the next verified substep, or use blocked, waiting_approval, or aborted when accurate. If no boundary is proven, preserve the list unchanged; never invent progress." : "Refresh the TodoList from the current verified state. Mark finished work done, keep the actual current step in_progress, and leave later work pending. Completed items disappear automatically after this call.";
|
|
423527
424041
|
const request = [
|
|
423528
424042
|
"Return exactly one TodoList tool call and no prose.",
|
|
423529
424043
|
action,
|
|
@@ -423542,10 +424056,7 @@ function enforceGoalTodoPolicy(agent, context) {
|
|
|
423542
424056
|
if (TELEGRAM_DELIVERY_TOOL_RE.test(String(context.toolCall.name ?? ""))) return;
|
|
423543
424057
|
const activeGoal = agent.goal.getActiveGoal();
|
|
423544
424058
|
const todos = ideaTodos(agent);
|
|
423545
|
-
const progress = agent
|
|
423546
|
-
workCallsSinceRefresh: 0,
|
|
423547
|
-
refreshRequired: false
|
|
423548
|
-
};
|
|
424059
|
+
const progress = goalTodoProgressState(agent);
|
|
423549
424060
|
if (todos.length === 0) {
|
|
423550
424061
|
const startsTrackedList = context.toolCall.name === "TodoList" && Array.isArray(context.args?.todos) && context.args.todos.length > 0;
|
|
423551
424062
|
if (activeGoal === null && !startsTrackedList) return;
|
|
@@ -423561,6 +424072,9 @@ function enforceGoalTodoPolicy(agent, context) {
|
|
|
423561
424072
|
};
|
|
423562
424073
|
progress.workCallsSinceRefresh = 0;
|
|
423563
424074
|
progress.refreshRequired = false;
|
|
424075
|
+
progress.unchangedRefreshStreak = 0;
|
|
424076
|
+
progress.recentEvidence = [];
|
|
424077
|
+
progress.lastMaintenanceEvidenceRevision = Number(progress.evidenceRevision) || 0;
|
|
423564
424078
|
progress.allVisibleWorkCompleted = false;
|
|
423565
424079
|
return;
|
|
423566
424080
|
}
|
|
@@ -423584,9 +424098,26 @@ function enforceGoalTodoPolicy(agent, context) {
|
|
|
423584
424098
|
reason: "A maintained TodoList must keep exactly one item in_progress while unfinished work remains."
|
|
423585
424099
|
};
|
|
423586
424100
|
}
|
|
424101
|
+
const evidenceRevision = Number(progress.evidenceRevision) || 0;
|
|
424102
|
+
const lastMaintenanceEvidenceRevision = Number(progress.lastMaintenanceEvidenceRevision) || 0;
|
|
424103
|
+
const maintenanceUpdate = assessTodoMaintenanceUpdate({
|
|
424104
|
+
currentTodos: todos,
|
|
424105
|
+
nextTodos,
|
|
424106
|
+
unchangedRefreshStreak: progress.unchangedRefreshStreak,
|
|
424107
|
+
recentEvidenceCount: evidenceRevision > lastMaintenanceEvidenceRevision ? (progress.recentEvidence?.length ?? 0) : 0
|
|
424108
|
+
});
|
|
423587
424109
|
progress.allVisibleWorkCompleted = nextTodos.length > 0 && nextTodos.every((todo) => todo?.status === "done");
|
|
423588
424110
|
progress.workCallsSinceRefresh = 0;
|
|
423589
424111
|
progress.refreshRequired = false;
|
|
424112
|
+
progress.unchangedRefreshStreak = maintenanceUpdate.unchangedRefreshStreak;
|
|
424113
|
+
progress.lastMaintenanceEvidenceRevision = evidenceRevision;
|
|
424114
|
+
if (!maintenanceUpdate.preserveRecentEvidence) progress.recentEvidence = [];
|
|
424115
|
+
if (maintenanceUpdate.emitStalledWarning) agent.emitEvent({
|
|
424116
|
+
type: "warning",
|
|
424117
|
+
code: "todo-maintenance-stalled",
|
|
424118
|
+
message: "TodoList stayed semantically unchanged across three evidence-bearing maintenance cycles. Work tools remain available; the next maintenance check is backed off while the active step is refined.",
|
|
424119
|
+
blocked: false
|
|
424120
|
+
});
|
|
423590
424121
|
return;
|
|
423591
424122
|
}
|
|
423592
424123
|
if (activeGoal !== null && context.toolCall.name === "UpdateGoal" && (context.args?.status === "complete" || context.args?.status === "blocked")) {
|
|
@@ -423602,7 +424133,7 @@ function enforceGoalTodoPolicy(agent, context) {
|
|
|
423602
424133
|
}
|
|
423603
424134
|
if (context.toolCall.id === context.toolCalls[0]?.id) {
|
|
423604
424135
|
progress.workCallsSinceRefresh += 1;
|
|
423605
|
-
if (progress.workCallsSinceRefresh >
|
|
424136
|
+
if (progress.workCallsSinceRefresh > todoRefreshWorkCallLimit(progress.unchangedRefreshStreak)) progress.refreshRequired = true;
|
|
423606
424137
|
}
|
|
423607
424138
|
if (!progress.refreshRequired) return;
|
|
423608
424139
|
return {
|
|
@@ -496923,6 +497454,9 @@ async function handleBuiltInSlashCommand(host, name, args) {
|
|
|
496923
497454
|
case "theme":
|
|
496924
497455
|
await handleThemeCommand(host, args);
|
|
496925
497456
|
return;
|
|
497457
|
+
case "model":
|
|
497458
|
+
await handleModelCommand(host, args);
|
|
497459
|
+
return;
|
|
496926
497460
|
case "effort":
|
|
496927
497461
|
await handleEffortCommand(host, args);
|
|
496928
497462
|
return;
|
|
@@ -503142,7 +503676,10 @@ function applyManagedAccountContext(models, maxContextTokens) {
|
|
|
503142
503676
|
maxContextSize: maxContextTokens
|
|
503143
503677
|
} }
|
|
503144
503678
|
};
|
|
503145
|
-
return {
|
|
503679
|
+
return {
|
|
503680
|
+
[BLUN_KING_MODEL_ALIAS]: king,
|
|
503681
|
+
...configuredFredrikGlmModels(models)
|
|
503682
|
+
};
|
|
503146
503683
|
}
|
|
503147
503684
|
function normalizeKingProductEffort(value) {
|
|
503148
503685
|
if (value === "none" || value === "minimal" || value === "off") return "low";
|
|
@@ -503198,7 +503735,11 @@ function nextManagedQuotaWarning(windows, highestShown) {
|
|
|
503198
503735
|
//#region src/tui/controllers/auth-flow.ts
|
|
503199
503736
|
function managedProviderOnly(providers) {
|
|
503200
503737
|
const managed = providers[DEFAULT_OAUTH_PROVIDER_NAME];
|
|
503201
|
-
|
|
503738
|
+
const fredrikGlm = configuredFredrikGlmProvider(providers);
|
|
503739
|
+
return {
|
|
503740
|
+
...managed === void 0 ? {} : { [DEFAULT_OAUTH_PROVIDER_NAME]: managed },
|
|
503741
|
+
...fredrikGlm === void 0 ? {} : { [FREDRIK_GLM_PROVIDER_ID]: fredrikGlm }
|
|
503742
|
+
};
|
|
503202
503743
|
}
|
|
503203
503744
|
var AuthFlowController = class {
|
|
503204
503745
|
host;
|
|
@@ -517611,6 +518152,8 @@ var BlunTUI = class {
|
|
|
517611
518152
|
yolo: startupInput.cliOptions.yolo,
|
|
517612
518153
|
auto: startupInput.cliOptions.auto,
|
|
517613
518154
|
plan: startupInput.cliOptions.plan,
|
|
518155
|
+
effort: startupInput.cliOptions.effort,
|
|
518156
|
+
swarm: startupInput.cliOptions.swarm,
|
|
517614
518157
|
model: startupInput.cliOptions.model,
|
|
517615
518158
|
startupNotice: startupInput.startupNotice
|
|
517616
518159
|
}
|
|
@@ -518027,6 +518570,7 @@ var BlunTUI = class {
|
|
|
518027
518570
|
const createSessionOptions = {
|
|
518028
518571
|
workDir,
|
|
518029
518572
|
model: BLUN_KING_MODEL_ALIAS,
|
|
518573
|
+
thinking: startup.effort,
|
|
518030
518574
|
permission: startup.auto ? "auto" : startup.yolo ? "yolo" : void 0,
|
|
518031
518575
|
planMode: startup.plan ? true : void 0
|
|
518032
518576
|
};
|
|
@@ -518073,7 +518617,7 @@ var BlunTUI = class {
|
|
|
518073
518617
|
}
|
|
518074
518618
|
}
|
|
518075
518619
|
} else session = await this.harness.createSession(createSessionOptions);
|
|
518076
|
-
if (session !== void 0 && shouldReplayHistory) await this.applyStartupModesToResumedSession(session);
|
|
518620
|
+
if (session !== void 0 && (shouldReplayHistory || startup.effort !== void 0 || startup.swarm)) await this.applyStartupModesToResumedSession(session);
|
|
518077
518621
|
} catch (error) {
|
|
518078
518622
|
if (!isOAuthLoginRequiredError(error)) throw error;
|
|
518079
518623
|
this.authFlow.enterLoginRequiredStartupState();
|
|
@@ -518124,10 +518668,6 @@ var BlunTUI = class {
|
|
|
518124
518668
|
const sessionId = session.id;
|
|
518125
518669
|
const autostartPrompt = autostart.observation === void 0 ? GOAL_CONTINUATION_PROMPT : `${GOAL_CONTINUATION_PROMPT}\n\n${autostart.observation}`;
|
|
518126
518670
|
this.beginSessionRequest();
|
|
518127
|
-
this.setAppState({
|
|
518128
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
518129
|
-
modelFallbackAllowed: false
|
|
518130
|
-
});
|
|
518131
518671
|
try {
|
|
518132
518672
|
const result = await session.promptAccepted(autostartPrompt);
|
|
518133
518673
|
if (!result.accepted && this.session?.id === sessionId) {
|
|
@@ -519164,10 +519704,6 @@ var BlunTUI = class {
|
|
|
519164
519704
|
contextOnly: false
|
|
519165
519705
|
};
|
|
519166
519706
|
this.pendingChannelReplyGuard = installedGuard;
|
|
519167
|
-
this.setAppState({
|
|
519168
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
519169
|
-
modelFallbackAllowed: false
|
|
519170
|
-
});
|
|
519171
519707
|
session.promptAccepted(options?.parts ?? input).then((result) => {
|
|
519172
519708
|
if (result.duplicate === true) {
|
|
519173
519709
|
this.traceTelegramDelivery?.({ stage: "committed", ...context.item.channelDeliveryTrace, route: "channel_command_prompt", reason: "duplicate" });
|
|
@@ -519225,10 +519761,6 @@ var BlunTUI = class {
|
|
|
519225
519761
|
};
|
|
519226
519762
|
if (installedGuard !== void 0) this.pendingChannelReplyGuard = installedGuard;
|
|
519227
519763
|
const imagePart = channelImagePath !== void 0 ? buildChannelImagePart(channelImagePath) : void 0;
|
|
519228
|
-
this.setAppState({
|
|
519229
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
519230
|
-
modelFallbackAllowed: false
|
|
519231
|
-
});
|
|
519232
519764
|
const directNotice = channelDirect === true ? ["A private Telegram DM has priority over background, group, and loop work.", channelDirectResume === true ? "The user explicitly resumed work. Answer any remaining direct content, then continue the exact saved work checkpoint." : "The runtime saved the active work checkpoint. Answer the private conversation naturally, without exposing internal task, cron, checkpoint, queue, or lane narration. Unless the user explicitly asks to pause, stop, or wait, continue the exact saved work checkpoint automatically after the direct conversation."].join("\n") : void 0;
|
|
519233
519765
|
const focusedModelInput = directNotice === void 0 ? modelInput : `${directNotice}\n\n${modelInput}`;
|
|
519234
519766
|
const promptInput = imagePart !== void 0 && this.canReadImages() ? [{
|
|
@@ -519429,10 +519961,6 @@ var BlunTUI = class {
|
|
|
519429
519961
|
return;
|
|
519430
519962
|
}
|
|
519431
519963
|
this.beginSessionRequest();
|
|
519432
|
-
this.setAppState({
|
|
519433
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
519434
|
-
modelFallbackAllowed: false
|
|
519435
|
-
});
|
|
519436
519964
|
session.promptAccepted(TRUNCATED_REPLY_CONTINUATION_PROMPT).then((result) => {
|
|
519437
519965
|
if (!result.accepted) this.failTruncatedChannelReplyRecovery(new Error("continuation prompt rejected"));
|
|
519438
519966
|
}).catch((error) => {
|
|
@@ -519703,10 +520231,6 @@ var BlunTUI = class {
|
|
|
519703
520231
|
});
|
|
519704
520232
|
this.beginSessionRequest();
|
|
519705
520233
|
const sdkInput = options?.parts ?? input;
|
|
519706
|
-
this.setAppState({
|
|
519707
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
519708
|
-
modelFallbackAllowed: false
|
|
519709
|
-
});
|
|
519710
520234
|
session.promptAccepted(sdkInput).catch((error) => {
|
|
519711
520235
|
finishPersonalMemoryRememberIntentTurn(session.id);
|
|
519712
520236
|
const message = formatErrorMessage$2(error);
|
|
@@ -519821,18 +520345,19 @@ var BlunTUI = class {
|
|
|
519821
520345
|
}
|
|
519822
520346
|
}
|
|
519823
520347
|
setAppState(patch) {
|
|
520348
|
+
const managedAccountContextTokens = "managedAccountContextTokens" in patch ? patch.managedAccountContextTokens : this.state.appState.managedAccountContextTokens;
|
|
520349
|
+
const availableModels = applyManagedAccountContext(patch.availableModels ?? this.state.appState.availableModels, isValidManagedContextTokens(managedAccountContextTokens) ? managedAccountContextTokens : void 0);
|
|
520350
|
+
const allowedModel = (candidate) => typeof candidate === "string" && isAllowedFredrikRuntimeAlias(candidate, availableModels) ? candidate : BLUN_KING_MODEL_ALIAS;
|
|
519824
520351
|
let effectivePatch = {
|
|
519825
520352
|
...patch,
|
|
519826
520353
|
modelFallbackAllowed: false,
|
|
519827
|
-
..."model" in patch && patch.model?.trim().length ? { model:
|
|
519828
|
-
..."activeResponderModel" in patch && patch.activeResponderModel != null ? { activeResponderModel:
|
|
520354
|
+
..."model" in patch && patch.model?.trim().length ? { model: allowedModel(patch.model) } : {},
|
|
520355
|
+
..."activeResponderModel" in patch && patch.activeResponderModel != null ? { activeResponderModel: allowedModel(patch.activeResponderModel) } : {}
|
|
519829
520356
|
};
|
|
519830
520357
|
if ("availableModels" in patch || "managedAccountContextTokens" in patch) {
|
|
519831
|
-
|
|
519832
|
-
const effectiveModels = applyManagedAccountContext(patch.availableModels ?? this.state.appState.availableModels, isValidManagedContextTokens(managedAccountContextTokens) ? managedAccountContextTokens : void 0);
|
|
519833
|
-
if (effectiveModels !== patch.availableModels) effectivePatch = {
|
|
520358
|
+
if (availableModels !== patch.availableModels) effectivePatch = {
|
|
519834
520359
|
...effectivePatch,
|
|
519835
|
-
availableModels
|
|
520360
|
+
availableModels
|
|
519836
520361
|
};
|
|
519837
520362
|
}
|
|
519838
520363
|
if (!hasPatchChanges(this.state.appState, effectivePatch)) return;
|
|
@@ -519909,7 +520434,11 @@ var BlunTUI = class {
|
|
|
519909
520434
|
return this.harness.createSession(options);
|
|
519910
520435
|
}
|
|
519911
520436
|
async setSession(session, options = {}) {
|
|
519912
|
-
await session.
|
|
520437
|
+
const resumedStatus = await session.getStatus();
|
|
520438
|
+
if (!isAllowedFredrikRuntimeAlias(resumedStatus.model ?? BLUN_KING_MODEL_ALIAS, this.state.appState.availableModels)) {
|
|
520439
|
+
await session.setModel(BLUN_KING_MODEL_ALIAS, { allowFallback: false });
|
|
520440
|
+
this.showStatus(uiText("config.model.unknownAlias", { alias: resumedStatus.model ?? "" }), "warning");
|
|
520441
|
+
}
|
|
519913
520442
|
await this.personalMemoryController.clear(this.session);
|
|
519914
520443
|
const previous = this.unloadCurrentSession(approvalCancellationFeedback("switching_session"));
|
|
519915
520444
|
await this.managedQuotaWarningPersistence;
|
|
@@ -519917,10 +520446,7 @@ var BlunTUI = class {
|
|
|
519917
520446
|
resetChannelPreambleState(this.channelPreamble);
|
|
519918
520447
|
this.session = session;
|
|
519919
520448
|
this.managedQuotaWarningController.restore(session.id, managedQuotaWarningThresholdFromMetadata(session.getResumeState()?.sessionMetadata?.custom));
|
|
519920
|
-
this.setAppState({
|
|
519921
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
519922
|
-
modelFallbackAllowed: false
|
|
519923
|
-
});
|
|
520449
|
+
this.setAppState({ modelFallbackAllowed: false });
|
|
519924
520450
|
this.harness.setTelemetryContext({ sessionId: session.id });
|
|
519925
520451
|
this.registerSessionHandlers(session);
|
|
519926
520452
|
this.syncAdditionalDirs(session);
|
|
@@ -519932,7 +520458,7 @@ var BlunTUI = class {
|
|
|
519932
520458
|
const [status, goalResult, loopResult] = await Promise.all([session.getStatus(), session.getGoal(), session.getLoop()]);
|
|
519933
520459
|
this.setAppState({
|
|
519934
520460
|
sessionId: session.id,
|
|
519935
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
520461
|
+
model: status.model ?? BLUN_KING_MODEL_ALIAS,
|
|
519936
520462
|
modelFallbackAllowed: false,
|
|
519937
520463
|
activeResponderModel: null,
|
|
519938
520464
|
thinkingEffort: status.thinkingEffort,
|
|
@@ -519966,6 +520492,8 @@ var BlunTUI = class {
|
|
|
519966
520492
|
const { startup } = this.options;
|
|
519967
520493
|
if (startup.auto) await session.setPermission("auto");
|
|
519968
520494
|
else if (startup.yolo) await session.setPermission("yolo");
|
|
520495
|
+
if (startup.effort !== void 0) await session.setThinking(startup.effort);
|
|
520496
|
+
if (startup.swarm && !(await session.getStatus()).swarmMode) await session.setSwarmMode(true, "effort");
|
|
519969
520497
|
if (startup.plan) {
|
|
519970
520498
|
if (!(await session.getStatus()).planMode) await session.setPlanMode(true);
|
|
519971
520499
|
}
|
|
@@ -519974,6 +520502,8 @@ var BlunTUI = class {
|
|
|
519974
520502
|
const { startup } = this.options;
|
|
519975
520503
|
if (startup.auto) this.setAppState({ permissionMode: "auto" });
|
|
519976
520504
|
else if (startup.yolo) this.setAppState({ permissionMode: "yolo" });
|
|
520505
|
+
if (startup.effort !== void 0) this.setAppState({ thinkingEffort: startup.effort });
|
|
520506
|
+
if (startup.swarm) this.setAppState({ swarmMode: true, swarmModeEntry: "effort" });
|
|
519977
520507
|
if (startup.plan) this.setAppState({ planMode: true });
|
|
519978
520508
|
}
|
|
519979
520509
|
async activateRuntime() {
|
|
@@ -520148,7 +520678,6 @@ var BlunTUI = class {
|
|
|
520148
520678
|
this.approvalController.cancelAll(approvalCancellationFeedback("reloading_session"));
|
|
520149
520679
|
this.questionController.cancelAll("");
|
|
520150
520680
|
this.resetSessionRuntime();
|
|
520151
|
-
await session.setModel(BLUN_KING_MODEL_ALIAS, { allowFallback: false });
|
|
520152
520681
|
this.session = session;
|
|
520153
520682
|
this.harness.setTelemetryContext({ sessionId: session.id });
|
|
520154
520683
|
this.registerSessionHandlers(session);
|