@usabledev/usable-chat 1.149.1 → 1.151.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +267 -22
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -12309,9 +12309,9 @@ var init_markdown = __esm({
|
|
|
12309
12309
|
const startNumber = typeof token.start === "number" ? token.start : 1;
|
|
12310
12310
|
for (let i18 = 0; i18 < token.items.length; i18++) {
|
|
12311
12311
|
const item = token.items[i18];
|
|
12312
|
-
const
|
|
12312
|
+
const bullet3 = token.ordered ? this.options.preserveOrderedListMarkers ? this.getOrderedListMarker(item) ?? `${startNumber + i18}. ` : `${startNumber + i18}. ` : "- ";
|
|
12313
12313
|
const taskMarker = item.task ? `[${item.checked ? "x" : " "}] ` : "";
|
|
12314
|
-
const marker15 =
|
|
12314
|
+
const marker15 = bullet3 + taskMarker;
|
|
12315
12315
|
const firstPrefix = indent + this.theme.listBullet(marker15);
|
|
12316
12316
|
const continuationPrefix = indent + " ".repeat(visibleWidth(marker15));
|
|
12317
12317
|
const itemWidth = Math.max(1, width - visibleWidth(firstPrefix));
|
|
@@ -23746,6 +23746,109 @@ Usable is the user's long-term memory. When a task touches project domain, past
|
|
|
23746
23746
|
}
|
|
23747
23747
|
});
|
|
23748
23748
|
|
|
23749
|
+
// src/core/orchestrator/harness-compaction.ts
|
|
23750
|
+
function toolCallsOf(msg) {
|
|
23751
|
+
const out = [];
|
|
23752
|
+
const m33 = msg;
|
|
23753
|
+
if (Array.isArray(m33.tool_calls)) {
|
|
23754
|
+
for (const tc of m33.tool_calls) {
|
|
23755
|
+
const fn4 = tc.function ?? tc;
|
|
23756
|
+
const name14 = String(fn4.name ?? tc.name ?? "");
|
|
23757
|
+
let args = {};
|
|
23758
|
+
const raw = fn4.arguments ?? tc.args ?? tc.input;
|
|
23759
|
+
if (typeof raw === "string") {
|
|
23760
|
+
try {
|
|
23761
|
+
args = JSON.parse(raw);
|
|
23762
|
+
} catch {
|
|
23763
|
+
args = {};
|
|
23764
|
+
}
|
|
23765
|
+
} else if (raw && typeof raw === "object") {
|
|
23766
|
+
args = raw;
|
|
23767
|
+
}
|
|
23768
|
+
if (name14) out.push({ name: name14, args });
|
|
23769
|
+
}
|
|
23770
|
+
}
|
|
23771
|
+
if (Array.isArray(msg.content)) {
|
|
23772
|
+
for (const part of msg.content) {
|
|
23773
|
+
const type = part.type;
|
|
23774
|
+
if (type === "tool_use" || type === "tool-call") {
|
|
23775
|
+
const name14 = String(part.name ?? part.toolName ?? "");
|
|
23776
|
+
const args = part.input ?? part.args ?? {};
|
|
23777
|
+
if (name14) out.push({ name: name14, args });
|
|
23778
|
+
}
|
|
23779
|
+
}
|
|
23780
|
+
}
|
|
23781
|
+
return out;
|
|
23782
|
+
}
|
|
23783
|
+
function extractFileOps(messages4) {
|
|
23784
|
+
const read = /* @__PURE__ */ new Set();
|
|
23785
|
+
const modified = /* @__PURE__ */ new Set();
|
|
23786
|
+
for (const msg of messages4) {
|
|
23787
|
+
if (msg.role !== "assistant") continue;
|
|
23788
|
+
for (const { name: name14, args } of toolCallsOf(msg)) {
|
|
23789
|
+
const path11 = args.path ?? args.file ?? args.pattern;
|
|
23790
|
+
if (!path11 || typeof path11 !== "string") continue;
|
|
23791
|
+
if (WRITE_TOOLS.has(name14)) modified.add(path11);
|
|
23792
|
+
else if (READ_TOOLS.has(name14)) read.add(path11);
|
|
23793
|
+
}
|
|
23794
|
+
}
|
|
23795
|
+
return { read: [...read], modified: [...modified] };
|
|
23796
|
+
}
|
|
23797
|
+
function isStepStart(messages4, i18) {
|
|
23798
|
+
if (i18 <= 0) return false;
|
|
23799
|
+
return messages4[i18].role === "assistant" && messages4[i18 - 1].role !== "assistant";
|
|
23800
|
+
}
|
|
23801
|
+
function findCutIndex(messages4, keepRecentTokens, countTokens2) {
|
|
23802
|
+
let sum2 = 0;
|
|
23803
|
+
for (let i18 = messages4.length - 1; i18 >= 1; i18--) {
|
|
23804
|
+
sum2 += countTokens2(messages4[i18]);
|
|
23805
|
+
if (sum2 >= keepRecentTokens && isStepStart(messages4, i18)) return i18;
|
|
23806
|
+
}
|
|
23807
|
+
return 0;
|
|
23808
|
+
}
|
|
23809
|
+
function bullet2(label, items) {
|
|
23810
|
+
if (items.length === 0) return "";
|
|
23811
|
+
const shown = items.slice(0, 30);
|
|
23812
|
+
const more = items.length > shown.length ? ` (+${items.length - shown.length} more)` : "";
|
|
23813
|
+
return `
|
|
23814
|
+
${label}: ${shown.join(", ")}${more}`;
|
|
23815
|
+
}
|
|
23816
|
+
function goalText(messages4) {
|
|
23817
|
+
const first = messages4[0];
|
|
23818
|
+
if (!first || first.role !== "user") return "";
|
|
23819
|
+
if (typeof first.content === "string") return first.content;
|
|
23820
|
+
if (Array.isArray(first.content)) {
|
|
23821
|
+
const text2 = first.content.filter((p28) => p28.type === "text" && typeof p28.text === "string").map((p28) => p28.text).join("\n");
|
|
23822
|
+
return text2;
|
|
23823
|
+
}
|
|
23824
|
+
return "";
|
|
23825
|
+
}
|
|
23826
|
+
function buildCompactionMarker(goal, droppedCount, fileOps) {
|
|
23827
|
+
const text2 = (goal ? `Original task:
|
|
23828
|
+
${goal}
|
|
23829
|
+
|
|
23830
|
+
` : "") + `[context-compacted] ${droppedCount} earlier messages were pruned to free the context window; the original task above and the most recent steps are preserved.` + bullet2("Files read so far", fileOps.read) + bullet2("Files modified so far", fileOps.modified) + `
|
|
23831
|
+
Continue the task from where it left off \u2014 do NOT restart it. Re-read a file with the read tool if you need its current contents.`;
|
|
23832
|
+
return { role: "user", content: text2 };
|
|
23833
|
+
}
|
|
23834
|
+
function compactHarnessConversation(messages4, opts) {
|
|
23835
|
+
const minMessages = opts.minMessages ?? 8;
|
|
23836
|
+
if (messages4.length < minMessages) return { messages: messages4, compacted: false, droppedCount: 0 };
|
|
23837
|
+
const cut = findCutIndex(messages4, opts.keepRecentTokens, opts.countTokens);
|
|
23838
|
+
if (cut < 3) return { messages: messages4, compacted: false, droppedCount: 0 };
|
|
23839
|
+
const dropped = messages4.slice(0, cut);
|
|
23840
|
+
const marker15 = buildCompactionMarker(goalText(messages4), dropped.length, extractFileOps(dropped));
|
|
23841
|
+
return { messages: [marker15, ...messages4.slice(cut)], compacted: true, droppedCount: dropped.length };
|
|
23842
|
+
}
|
|
23843
|
+
var READ_TOOLS, WRITE_TOOLS;
|
|
23844
|
+
var init_harness_compaction = __esm({
|
|
23845
|
+
"src/core/orchestrator/harness-compaction.ts"() {
|
|
23846
|
+
"use strict";
|
|
23847
|
+
READ_TOOLS = /* @__PURE__ */ new Set(["read", "glob", "grep"]);
|
|
23848
|
+
WRITE_TOOLS = /* @__PURE__ */ new Set(["write", "edit"]);
|
|
23849
|
+
}
|
|
23850
|
+
});
|
|
23851
|
+
|
|
23749
23852
|
// src/core/orchestrator/ask-user-question-prompt.ts
|
|
23750
23853
|
var ASK_USER_QUESTION_PROMPT;
|
|
23751
23854
|
var init_ask_user_question_prompt = __esm({
|
|
@@ -157383,6 +157486,13 @@ var init_custom_expert = __esm({
|
|
|
157383
157486
|
type: external_exports.literal("object"),
|
|
157384
157487
|
properties: external_exports.record(external_exports.unknown()),
|
|
157385
157488
|
required: external_exports.array(external_exports.string()).optional()
|
|
157489
|
+
}).optional(),
|
|
157490
|
+
skill: external_exports.object({
|
|
157491
|
+
id: external_exports.string().min(1).max(100).optional(),
|
|
157492
|
+
title: external_exports.string().min(1).max(200).optional(),
|
|
157493
|
+
summary: external_exports.string().max(1e3).optional(),
|
|
157494
|
+
tags: external_exports.array(external_exports.string().min(1).max(100)).max(20).optional(),
|
|
157495
|
+
scope: external_exports.enum(["global", "page"]).optional()
|
|
157386
157496
|
}).optional()
|
|
157387
157497
|
});
|
|
157388
157498
|
MAX_PARENT_TOOLS = 32;
|
|
@@ -168237,29 +168347,38 @@ function buildDiscoverableSkillsPromptSection(skills) {
|
|
|
168237
168347
|
"",
|
|
168238
168348
|
"## DISCOVERABLE SKILLS IN CONTEXT",
|
|
168239
168349
|
"",
|
|
168240
|
-
"You have a catalog of reusable Skills scoped to
|
|
168350
|
+
"You have a catalog of reusable Skills scoped to this conversation. Workspace skills are Usable fragments. Parent-local skills are provided dynamically by the embedding parent app and must be loaded through their parent tool.",
|
|
168241
168351
|
"",
|
|
168242
168352
|
"**BEFORE acting on the user's request, scan this catalog.** If any listed skill matches the user's intent \u2014 by title, `/<name>`, summary keywords, or obvious topical fit \u2014 you MUST use it instead of improvising:",
|
|
168243
168353
|
"",
|
|
168244
|
-
'1.
|
|
168245
|
-
"2.
|
|
168354
|
+
'1. For workspace skills, call `add-to-conversation-context` with `contextType: "fragment"` and `contextId: <fragmentId>` from the matching entry. Attaching a fragment pulls its FULL instructions into your system prompt for the rest of the conversation.',
|
|
168355
|
+
"2. For parent-local skills, call the listed `parent_<toolName>` tool first. The parent app returns the current skill instructions/content for this page or application. Follow that returned content exactly.",
|
|
168356
|
+
"3. Do not fall back to generic search once a matching skill is loaded.",
|
|
168246
168357
|
"",
|
|
168247
168358
|
'**Example** \u2014 the user asks "what tasks do we have?" and the catalog lists a `/usable-tasks` skill. You MUST attach that skill BEFORE searching for tasks yourself; the skill knows the correct queries, tag taxonomy, and output format.',
|
|
168248
168359
|
"",
|
|
168249
168360
|
"**Rules**",
|
|
168250
|
-
"- The entries below are metadata only; their bodies are NOT loaded until you attach
|
|
168251
|
-
"- Load skills lazily \u2014 only
|
|
168252
|
-
"- If the user explicitly invokes a skill via `/<name>` or `/skill <uuid>`, the harness has already attached it; just follow its instructions.",
|
|
168253
|
-
|
|
168361
|
+
"- The entries below are metadata only; their bodies are NOT loaded until you attach the workspace fragment or call the parent-local tool.",
|
|
168362
|
+
"- Load skills lazily \u2014 only load the one(s) needed for the current request, not the whole catalog.",
|
|
168363
|
+
"- If the user explicitly invokes a workspace skill via `/<name>` or `/skill <uuid>`, the harness has already attached it; just follow its instructions.",
|
|
168364
|
+
"- If the user explicitly invokes a parent-local skill via `/<name>` or `/skill parent:<id>`, call that skill's parent tool before doing the work.",
|
|
168365
|
+
'- When a workspace skill-driven task completes (the user moves to a new topic or confirms the work is done), call `remove-from-conversation-context` with `contextType: "fragment"` and the skill\'s fragmentId to free the skill token budget for the next activation.',
|
|
168254
168366
|
""
|
|
168255
168367
|
];
|
|
168256
168368
|
for (const [workspaceId, workspaceSkills] of skillsByWorkspace.entries()) {
|
|
168257
168369
|
section.push(`### Workspace: ${workspaceSkills.workspaceName} (\`${workspaceId}\`)`);
|
|
168258
168370
|
for (const skill of workspaceSkills.skills) {
|
|
168259
168371
|
const shortcut = skill.name ? ` (\`/${skill.name}\`)` : "";
|
|
168260
|
-
|
|
168261
|
-
|
|
168262
|
-
|
|
168372
|
+
if (skill.source === "parent" && skill.parentToolName) {
|
|
168373
|
+
const scope = skill.parentScope === "global" ? "global" : "page";
|
|
168374
|
+
section.push(
|
|
168375
|
+
`- **${skill.title}**${shortcut} \u2014 parent-local \`${skill.fragmentId}\` \u2014 load with \`parent_${skill.parentToolName}\` \u2014 scope: ${scope}${skill.summary ? ` \u2014 ${skill.summary}` : ""}`
|
|
168376
|
+
);
|
|
168377
|
+
} else {
|
|
168378
|
+
section.push(
|
|
168379
|
+
`- **${skill.title}**${shortcut} \u2014 \`${skill.fragmentId}\`${skill.summary ? ` \u2014 ${skill.summary}` : ""}`
|
|
168380
|
+
);
|
|
168381
|
+
}
|
|
168263
168382
|
}
|
|
168264
168383
|
section.push("");
|
|
168265
168384
|
}
|
|
@@ -168767,14 +168886,21 @@ var init_skill_decay = __esm({
|
|
|
168767
168886
|
// src/lib/skill-command.ts
|
|
168768
168887
|
var skill_command_exports = {};
|
|
168769
168888
|
__export(skill_command_exports, {
|
|
168889
|
+
PARENT_SKILL_COMMAND_ID_REGEX: () => PARENT_SKILL_COMMAND_ID_REGEX,
|
|
168890
|
+
PARENT_SKILL_ID_PREFIX: () => PARENT_SKILL_ID_PREFIX,
|
|
168770
168891
|
SKILL_COMMAND_UUID_REGEX: () => SKILL_COMMAND_UUID_REGEX,
|
|
168771
168892
|
addSkillToPendingContext: () => addSkillToPendingContext,
|
|
168893
|
+
buildParentLocalSkillsFromTools: () => buildParentLocalSkillsFromTools,
|
|
168772
168894
|
buildSkillCommandMessage: () => buildSkillCommandMessage,
|
|
168773
168895
|
dedupeSkillsByName: () => dedupeSkillsByName,
|
|
168774
168896
|
ensureSkillConversationContext: () => ensureSkillConversationContext,
|
|
168775
168897
|
extractSkillName: () => extractSkillName,
|
|
168776
|
-
findSkillByCommandName: () => findSkillByCommandName
|
|
168898
|
+
findSkillByCommandName: () => findSkillByCommandName,
|
|
168899
|
+
isParentLocalSkill: () => isParentLocalSkill
|
|
168777
168900
|
});
|
|
168901
|
+
function isParentLocalSkill(skill) {
|
|
168902
|
+
return skill.source === "parent";
|
|
168903
|
+
}
|
|
168778
168904
|
function kebabCase(value) {
|
|
168779
168905
|
return value.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
168780
168906
|
}
|
|
@@ -168816,11 +168942,43 @@ function buildSkillCommandMessage(skill, userArgs) {
|
|
|
168816
168942
|
const name14 = extractSkillName(skill);
|
|
168817
168943
|
const shortcut = name14 ? ` (\`/${name14}\`)` : "";
|
|
168818
168944
|
const normalizedArgs = userArgs.trim();
|
|
168945
|
+
if (isParentLocalSkill(skill)) {
|
|
168946
|
+
return [
|
|
168947
|
+
`\u26A1 Activating parent skill **${skill.title}**${shortcut}. Call \`parent_${skill.parentToolName}\` to load and follow the parent-provided skill instructions.`,
|
|
168948
|
+
`Args: ${normalizedArgs || "(none)"}`
|
|
168949
|
+
].join("\n");
|
|
168950
|
+
}
|
|
168819
168951
|
return [
|
|
168820
168952
|
`\u26A1 Activating skill **${skill.title}**${shortcut}. Follow its attached instructions.`,
|
|
168821
168953
|
`Args: ${normalizedArgs || "(none)"}`
|
|
168822
168954
|
].join("\n");
|
|
168823
168955
|
}
|
|
168956
|
+
function buildParentLocalSkillsFromTools(tools) {
|
|
168957
|
+
const skills = [];
|
|
168958
|
+
const seen = /* @__PURE__ */ new Set();
|
|
168959
|
+
for (const tool of tools) {
|
|
168960
|
+
if (!tool.skill) continue;
|
|
168961
|
+
const scope = tool.skill.scope ?? "page";
|
|
168962
|
+
const id = (tool.skill.id || tool.name).trim().toLowerCase();
|
|
168963
|
+
if (!/^[a-z][a-z0-9_-]{0,99}$/i.test(id)) continue;
|
|
168964
|
+
const fragmentId = `${PARENT_SKILL_ID_PREFIX}${id}`;
|
|
168965
|
+
if (seen.has(fragmentId)) continue;
|
|
168966
|
+
seen.add(fragmentId);
|
|
168967
|
+
const tags = Array.from(/* @__PURE__ */ new Set(["skill", `skill:${id}`, ...tool.skill.tags || []]));
|
|
168968
|
+
skills.push({
|
|
168969
|
+
source: "parent",
|
|
168970
|
+
fragmentId,
|
|
168971
|
+
workspaceId: scope === "global" ? "parent-global" : "parent-page",
|
|
168972
|
+
workspaceName: scope === "global" ? "Parent app" : "Current page",
|
|
168973
|
+
title: tool.skill.title || id,
|
|
168974
|
+
summary: tool.skill.summary || tool.description,
|
|
168975
|
+
tags,
|
|
168976
|
+
parentToolName: tool.name,
|
|
168977
|
+
parentScope: scope
|
|
168978
|
+
});
|
|
168979
|
+
}
|
|
168980
|
+
return skills;
|
|
168981
|
+
}
|
|
168824
168982
|
function addSkillToPendingContext(pendingContextItems, skill) {
|
|
168825
168983
|
if (pendingContextItems.some(
|
|
168826
168984
|
(item) => item.contextType === "fragment" && item.contextId === skill.fragmentId
|
|
@@ -168874,11 +169032,13 @@ async function ensureSkillConversationContext(params) {
|
|
|
168874
169032
|
throw new Error(`Failed to attach skill context (${addResponse.status})`);
|
|
168875
169033
|
}
|
|
168876
169034
|
}
|
|
168877
|
-
var SKILL_COMMAND_UUID_REGEX, SKILL_NAME_TAG_PREFIX;
|
|
169035
|
+
var SKILL_COMMAND_UUID_REGEX, PARENT_SKILL_ID_PREFIX, PARENT_SKILL_COMMAND_ID_REGEX, SKILL_NAME_TAG_PREFIX;
|
|
168878
169036
|
var init_skill_command = __esm({
|
|
168879
169037
|
"src/lib/skill-command.ts"() {
|
|
168880
169038
|
"use strict";
|
|
168881
169039
|
SKILL_COMMAND_UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
169040
|
+
PARENT_SKILL_ID_PREFIX = "parent:";
|
|
169041
|
+
PARENT_SKILL_COMMAND_ID_REGEX = /^parent:[a-z][a-z0-9_-]{0,99}$/i;
|
|
168882
169042
|
SKILL_NAME_TAG_PREFIX = "skill:";
|
|
168883
169043
|
}
|
|
168884
169044
|
});
|
|
@@ -241711,6 +241871,26 @@ Folder behavior:
|
|
|
241711
241871
|
largeContextWarning: contextSizeWarning
|
|
241712
241872
|
});
|
|
241713
241873
|
}
|
|
241874
|
+
let discoverableSkillsSectionInjected = false;
|
|
241875
|
+
const buildParentPromptSkills = async () => {
|
|
241876
|
+
if (!context.registeredParentToolSchemas || context.registeredParentToolSchemas.size === 0) {
|
|
241877
|
+
return [];
|
|
241878
|
+
}
|
|
241879
|
+
const { buildParentLocalSkillsFromTools: buildParentLocalSkillsFromTools2, extractSkillName: extractSkillName2 } = await Promise.resolve().then(() => (init_skill_command(), skill_command_exports));
|
|
241880
|
+
return buildParentLocalSkillsFromTools2(
|
|
241881
|
+
Array.from(context.registeredParentToolSchemas.values())
|
|
241882
|
+
).map((skill) => ({
|
|
241883
|
+
source: "parent",
|
|
241884
|
+
fragmentId: skill.fragmentId,
|
|
241885
|
+
workspaceId: skill.workspaceId,
|
|
241886
|
+
workspaceName: skill.workspaceName,
|
|
241887
|
+
title: skill.title,
|
|
241888
|
+
summary: skill.summary,
|
|
241889
|
+
name: extractSkillName2(skill),
|
|
241890
|
+
parentToolName: skill.parentToolName,
|
|
241891
|
+
parentScope: skill.parentScope
|
|
241892
|
+
}));
|
|
241893
|
+
};
|
|
241714
241894
|
if (allowedWorkspaceIds.length > 0) {
|
|
241715
241895
|
const workspaceRules = [
|
|
241716
241896
|
"",
|
|
@@ -241818,18 +241998,25 @@ Folder behavior:
|
|
|
241818
241998
|
});
|
|
241819
241999
|
const { dedupeSkillsByName: dedupeSkillsByName2, extractSkillName: extractSkillName2 } = await Promise.resolve().then(() => (init_skill_command(), skill_command_exports));
|
|
241820
242000
|
const dedupedSkills = dedupeSkillsByName2(skillDiscovery.skills);
|
|
242001
|
+
const parentPromptSkills = await buildParentPromptSkills();
|
|
241821
242002
|
const discoverableSkillsSection = buildDiscoverableSkillsPromptSection(
|
|
241822
|
-
|
|
241823
|
-
...skill
|
|
241824
|
-
|
|
241825
|
-
|
|
242003
|
+
[
|
|
242004
|
+
...dedupedSkills.map((skill) => ({
|
|
242005
|
+
source: "workspace",
|
|
242006
|
+
...skill,
|
|
242007
|
+
name: extractSkillName2(skill)
|
|
242008
|
+
})),
|
|
242009
|
+
...parentPromptSkills
|
|
242010
|
+
]
|
|
241826
242011
|
);
|
|
241827
242012
|
if (discoverableSkillsSection) {
|
|
241828
242013
|
systemMessageParts.push(discoverableSkillsSection);
|
|
242014
|
+
discoverableSkillsSectionInjected = true;
|
|
241829
242015
|
orchestrationLogger.info("Discoverable skills injected into system prompt", {
|
|
241830
242016
|
workspaceCount: new Set(skillDiscovery.skills.map((skill) => skill.workspaceId)).size,
|
|
241831
|
-
skillCount: dedupedSkills.length,
|
|
242017
|
+
skillCount: dedupedSkills.length + parentPromptSkills.length,
|
|
241832
242018
|
rawSkillCount: skillDiscovery.skills.length,
|
|
242019
|
+
parentSkillCount: parentPromptSkills.length,
|
|
241833
242020
|
stale: skillDiscovery.stale
|
|
241834
242021
|
});
|
|
241835
242022
|
}
|
|
@@ -241861,6 +242048,23 @@ Folder behavior:
|
|
|
241861
242048
|
conversationId
|
|
241862
242049
|
});
|
|
241863
242050
|
}
|
|
242051
|
+
if (!discoverableSkillsSectionInjected) {
|
|
242052
|
+
try {
|
|
242053
|
+
const parentPromptSkills = await buildParentPromptSkills();
|
|
242054
|
+
const discoverableSkillsSection = buildDiscoverableSkillsPromptSection(parentPromptSkills);
|
|
242055
|
+
if (discoverableSkillsSection) {
|
|
242056
|
+
systemMessageParts.push(discoverableSkillsSection);
|
|
242057
|
+
discoverableSkillsSectionInjected = true;
|
|
242058
|
+
orchestrationLogger.info("Parent-local discoverable skills injected into system prompt", {
|
|
242059
|
+
parentSkillCount: parentPromptSkills.length
|
|
242060
|
+
});
|
|
242061
|
+
}
|
|
242062
|
+
} catch (error41) {
|
|
242063
|
+
orchestrationLogger.warn("Failed to inject parent-local skills into prompt", {
|
|
242064
|
+
error: error41 instanceof Error ? error41.message : String(error41)
|
|
242065
|
+
});
|
|
242066
|
+
}
|
|
242067
|
+
}
|
|
241864
242068
|
const contextManagementGuidance = [
|
|
241865
242069
|
"",
|
|
241866
242070
|
"## CONTEXT WINDOW MANAGEMENT - INTELLIGENT STRATEGY",
|
|
@@ -242907,6 +243111,37 @@ ${combinedSystemMessage}` : combinedSystemMessage;
|
|
|
242907
243111
|
name: msg.name
|
|
242908
243112
|
};
|
|
242909
243113
|
};
|
|
243114
|
+
if (config3.localFilesystem) {
|
|
243115
|
+
const harnessCtxLen = getModelById(selectedModelId)?.capabilities.contextLength || 128e3;
|
|
243116
|
+
const envRatio = Number(process.env.USABLE_HARNESS_COMPACT_RATIO);
|
|
243117
|
+
const compactRatio = envRatio > 0 && envRatio <= 1 ? envRatio : HARNESS_COMPACT_RATIO;
|
|
243118
|
+
const tokensOf = (m33) => countTokens(typeof m33.content === "string" ? m33.content : JSON.stringify(m33.content));
|
|
243119
|
+
const estTokens = conversationMessages.reduce((s17, m33) => s17 + tokensOf(m33), 0);
|
|
243120
|
+
if (estTokens > harnessCtxLen * compactRatio) {
|
|
243121
|
+
const beforeLen = conversationMessages.length;
|
|
243122
|
+
const envKeep = Number(process.env.USABLE_HARNESS_KEEP_TOKENS);
|
|
243123
|
+
const keepRecentTokens = envKeep > 0 ? envKeep : Math.floor(harnessCtxLen * HARNESS_KEEP_RECENT_RATIO);
|
|
243124
|
+
const res = compactHarnessConversation(conversationMessages, {
|
|
243125
|
+
keepRecentTokens,
|
|
243126
|
+
countTokens: tokensOf
|
|
243127
|
+
});
|
|
243128
|
+
if (res.compacted) {
|
|
243129
|
+
conversationMessages = ensureToolCallIntegrity(res.messages);
|
|
243130
|
+
orchestrationLogger.warn("\u{1F9F9} Harness proactive compaction", {
|
|
243131
|
+
beforeLen,
|
|
243132
|
+
afterLen: conversationMessages.length,
|
|
243133
|
+
droppedCount: res.droppedCount,
|
|
243134
|
+
estTokens,
|
|
243135
|
+
contextLength: harnessCtxLen
|
|
243136
|
+
});
|
|
243137
|
+
const compactPlan = emitter.emit("plan", {
|
|
243138
|
+
plan: `\u{1F9F9} Compacted ${res.droppedCount} older messages to free context \u2014 continuing.`,
|
|
243139
|
+
steps: config3.maxSteps
|
|
243140
|
+
});
|
|
243141
|
+
multiplexer.send(compactPlan);
|
|
243142
|
+
}
|
|
243143
|
+
}
|
|
243144
|
+
}
|
|
242910
243145
|
const filteredConversationMessages = filterImagesFromHistory(conversationMessages, {
|
|
242911
243146
|
preserveLastUserMessageImages: !!modelInfo?.capabilities?.vision
|
|
242912
243147
|
});
|
|
@@ -243096,7 +243331,7 @@ ${combinedSystemMessage}` : combinedSystemMessage;
|
|
|
243096
243331
|
});
|
|
243097
243332
|
multiplexer.send(compactionEvent);
|
|
243098
243333
|
}
|
|
243099
|
-
if (contextUsagePercent >= 85 && !forceNoTools) {
|
|
243334
|
+
if (contextUsagePercent >= 85 && !forceNoTools && !config3.localFilesystem) {
|
|
243100
243335
|
forceNoTools = true;
|
|
243101
243336
|
orchestrationLogger.warn("\u{1F6D1} Context at 85%+ - forcing synthesis, disabling tools", {
|
|
243102
243337
|
contextUsagePercent: Math.round(contextUsagePercent)
|
|
@@ -243857,7 +244092,7 @@ function createOrchestratorRequest(messages4, context, config3, persona, apiKey,
|
|
|
243857
244092
|
// Pass MCP tools through
|
|
243858
244093
|
};
|
|
243859
244094
|
}
|
|
243860
|
-
var HARD_TOOL_RESULT_CEILING_CHARS, ASK_QUESTION_PLACEHOLDER;
|
|
244095
|
+
var HARNESS_COMPACT_RATIO, HARNESS_KEEP_RECENT_RATIO, HARD_TOOL_RESULT_CEILING_CHARS, ASK_QUESTION_PLACEHOLDER;
|
|
243861
244096
|
var init_orchestrator = __esm({
|
|
243862
244097
|
"src/core/orchestrator/index.ts"() {
|
|
243863
244098
|
"use strict";
|
|
@@ -243868,6 +244103,7 @@ var init_orchestrator = __esm({
|
|
|
243868
244103
|
init_config();
|
|
243869
244104
|
init_code_execution_prompt();
|
|
243870
244105
|
init_harness_prompt();
|
|
244106
|
+
init_harness_compaction();
|
|
243871
244107
|
init_ask_user_question_prompt();
|
|
243872
244108
|
init_artifact_mention_resolver();
|
|
243873
244109
|
init_slack_mention_resolver();
|
|
@@ -243903,6 +244139,8 @@ var init_orchestrator = __esm({
|
|
|
243903
244139
|
init_mcp_server_tools_prompt();
|
|
243904
244140
|
init_spill_payload();
|
|
243905
244141
|
init_token_counter();
|
|
244142
|
+
HARNESS_COMPACT_RATIO = 0.75;
|
|
244143
|
+
HARNESS_KEEP_RECENT_RATIO = 0.35;
|
|
243906
244144
|
registerAllExperts();
|
|
243907
244145
|
HARD_TOOL_RESULT_CEILING_CHARS = 4e4;
|
|
243908
244146
|
ASK_QUESTION_PLACEHOLDER = "[Awaiting user answer \u2014 picker is open]";
|
|
@@ -261445,6 +261683,13 @@ Edit it, then /verify-extension ${arg.trim()} to check it loads, /trust (project
|
|
|
261445
261683
|
(it7) => it7.kind === "tool" && it7.id === data2.id ? { ...it7, status: data2.success === false ? "error" : "done", result, error: error41 } : it7
|
|
261446
261684
|
);
|
|
261447
261685
|
ui2.requestRender();
|
|
261686
|
+
} else if (e14.type === "plan") {
|
|
261687
|
+
const plan = e14.data?.plan;
|
|
261688
|
+
if (plan && plan.startsWith("\u{1F9F9}")) {
|
|
261689
|
+
finalize();
|
|
261690
|
+
push({ kind: "system", text: plan, tone: "info" });
|
|
261691
|
+
ui2.requestRender();
|
|
261692
|
+
}
|
|
261448
261693
|
}
|
|
261449
261694
|
};
|
|
261450
261695
|
try {
|
|
@@ -262279,7 +262524,7 @@ init_tui_select();
|
|
|
262279
262524
|
init_model_registry();
|
|
262280
262525
|
|
|
262281
262526
|
// package.json
|
|
262282
|
-
var version = "1.
|
|
262527
|
+
var version = "1.151.0";
|
|
262283
262528
|
|
|
262284
262529
|
// src/adapters/cli/model-catalog.ts
|
|
262285
262530
|
init_codex_auth();
|