@xmoon76/dsh-pi-tui 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +19 -1
- package/dist/index.mjs +186 -70
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -177,6 +177,24 @@ declare function shouldSteerOnEnter(parsed: {
|
|
|
177
177
|
declare function shouldConsumeAdvertisedMiss(execution: {
|
|
178
178
|
readonly result: unknown;
|
|
179
179
|
} | undefined, wasAdvertised: boolean): boolean;
|
|
180
|
+
/** One unsettled subagent delegation, in tool/call order. */
|
|
181
|
+
interface PendingSubagentCall {
|
|
182
|
+
readonly callId: string;
|
|
183
|
+
readonly description: string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Match the child a user is about to view against the unsettled subagent
|
|
187
|
+
* calls (pure, exported for the headless suite). The child's durable label
|
|
188
|
+
* is the delegation's `description`; duplicate descriptions take the MOST
|
|
189
|
+
* RECENT call (the one the user is most likely watching), an empty/absent
|
|
190
|
+
* label falls back to a LONE pending call, and no match disables the
|
|
191
|
+
* auto-pop (the user exits the viewer with Esc as before — never a wrong
|
|
192
|
+
* pop). Mutates `pending` by removing the matched call.
|
|
193
|
+
* @param pending - the unsettled calls, in order (oldest first).
|
|
194
|
+
* @param label - the child's durable label; '' or undefined = no description.
|
|
195
|
+
* @returns the matched call, or undefined when nothing matches.
|
|
196
|
+
*/
|
|
197
|
+
declare function matchPendingSubagentCall(pending: PendingSubagentCall[], label: string | undefined): PendingSubagentCall | undefined;
|
|
180
198
|
/**
|
|
181
199
|
* The pre-mount surface catalog resolution:
|
|
182
200
|
* - an explicit `--session` start PREFETCHES the resumed agent's effective
|
|
@@ -405,4 +423,4 @@ declare function recomposeBlank(ctx: Context, agent: {
|
|
|
405
423
|
*/
|
|
406
424
|
declare function apply(ctx: Context, config: Config): void;
|
|
407
425
|
//#endregion
|
|
408
|
-
export { AgentComposition, Config, InitialCatalogResolution, LOCAL_COMMANDS, QueueFoldResult, QueueInboxMessage, QueueNoticeSource, RecomposableSession, RecomposeOutcome, ResolveInitialCatalogOptions, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, composeAgent, dangerCommand, foldQueueRows, forkSeed, inject, isPlainExitPrompt, isSubagentSettlementNotice, name, recomposeBlank, recordedPreset, resolveInitialCatalog, resumeCommand, runningProfile, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure };
|
|
426
|
+
export { AgentComposition, Config, InitialCatalogResolution, LOCAL_COMMANDS, PendingSubagentCall, QueueFoldResult, QueueInboxMessage, QueueNoticeSource, RecomposableSession, RecomposeOutcome, ResolveInitialCatalogOptions, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, composeAgent, dangerCommand, foldQueueRows, forkSeed, inject, isPlainExitPrompt, isSubagentSettlementNotice, matchPendingSubagentCall, name, recomposeBlank, recordedPreset, resolveInitialCatalog, resumeCommand, runningProfile, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure };
|
package/dist/index.mjs
CHANGED
|
@@ -29,7 +29,7 @@ import { eastAsianWidth } from "get-east-asian-width";
|
|
|
29
29
|
import { performance } from "node:perf_hooks";
|
|
30
30
|
import { fileURLToPath } from "node:url";
|
|
31
31
|
import { EventEmitter } from "events";
|
|
32
|
-
import { isUserInvocable } from "@deepseek-ai/dsh-skill";
|
|
32
|
+
import { isUserInvocable, renderSkillContent } from "@deepseek-ai/dsh-skill";
|
|
33
33
|
//#region src/present.ts
|
|
34
34
|
/** Figma row titles per variant (design literals, not translatable copy). */
|
|
35
35
|
const VARIANT_TITLES = {
|
|
@@ -12859,10 +12859,10 @@ var TaskBrowserPanel = class {
|
|
|
12859
12859
|
this.searchInput.invalidate();
|
|
12860
12860
|
}
|
|
12861
12861
|
handleInput(data) {
|
|
12862
|
-
const isNavUp = data
|
|
12863
|
-
const isNavDown = data
|
|
12864
|
-
const isPage = data
|
|
12865
|
-
if (!isNavUp && !isNavDown && !isPage && data
|
|
12862
|
+
const isNavUp = matchesKey(data, "up") || !this.searchEnabled && data === "k";
|
|
12863
|
+
const isNavDown = matchesKey(data, "down") || !this.searchEnabled && data === "j";
|
|
12864
|
+
const isPage = matchesKey(data, "pageUp") || matchesKey(data, "pageDown");
|
|
12865
|
+
if (!isNavUp && !isNavDown && !isPage && !matchesKey(data, "enter") && !matchesKey(data, "escape") && this.searchEnabled) {
|
|
12866
12866
|
this.searchInput.handleInput(data);
|
|
12867
12867
|
this.applyFilter(this.searchInput.getValue() ?? "");
|
|
12868
12868
|
return;
|
|
@@ -12881,17 +12881,17 @@ var TaskBrowserPanel = class {
|
|
|
12881
12881
|
}
|
|
12882
12882
|
if (isPage) {
|
|
12883
12883
|
if (this.filtered.length === 0) return;
|
|
12884
|
-
if (data
|
|
12884
|
+
if (matchesKey(data, "pageUp")) this.selected = Math.max(0, this.selected - this.maxVisible);
|
|
12885
12885
|
else this.selected = Math.min(this.filtered.length - 1, this.selected + this.maxVisible);
|
|
12886
12886
|
this.ensureVisible();
|
|
12887
12887
|
return;
|
|
12888
12888
|
}
|
|
12889
|
-
if (data
|
|
12889
|
+
if (matchesKey(data, "enter")) {
|
|
12890
12890
|
const item = this.filtered[this.selected];
|
|
12891
12891
|
if (item !== void 0) this.onSelect(item.value);
|
|
12892
12892
|
return;
|
|
12893
12893
|
}
|
|
12894
|
-
if (data
|
|
12894
|
+
if (matchesKey(data, "escape")) this.onCancel();
|
|
12895
12895
|
}
|
|
12896
12896
|
ensureVisible() {
|
|
12897
12897
|
if (this.selected < this.scroll) this.scroll = this.selected;
|
|
@@ -13493,8 +13493,9 @@ var QuestionFlow = class {
|
|
|
13493
13493
|
if (draft === void 0) return;
|
|
13494
13494
|
const text = value.trim();
|
|
13495
13495
|
draft.custom = text;
|
|
13496
|
-
if (text === "")
|
|
13497
|
-
|
|
13496
|
+
if (text === "") {
|
|
13497
|
+
if (draft.selected.size === 0) draft.skipped = true;
|
|
13498
|
+
} else {
|
|
13498
13499
|
if (this.questions[this.tab]?.multiSelect !== true) draft.selected.clear();
|
|
13499
13500
|
draft.skipped = false;
|
|
13500
13501
|
}
|
|
@@ -13526,44 +13527,34 @@ var QuestionFlow = class {
|
|
|
13526
13527
|
handleInput(data) {
|
|
13527
13528
|
if (data === "\0") return;
|
|
13528
13529
|
if (this.editingOther) {
|
|
13529
|
-
if (data
|
|
13530
|
-
else if (data
|
|
13531
|
-
else if (data
|
|
13532
|
-
else if (data
|
|
13530
|
+
if (matchesKey(data, "enter")) this.commitOther(this.otherInput.getValue());
|
|
13531
|
+
else if (matchesKey(data, "escape")) this.exitOther();
|
|
13532
|
+
else if (matchesKey(data, "pageUp")) this.scrollBody(-1);
|
|
13533
|
+
else if (matchesKey(data, "pageDown")) this.scrollBody(1);
|
|
13534
|
+
else if (matchesKey(data, "left")) {
|
|
13533
13535
|
if (this.tab > 0) {
|
|
13534
13536
|
this.tab -= 1;
|
|
13535
13537
|
this.cursor = 0;
|
|
13536
13538
|
this.submitIdx = 0;
|
|
13537
13539
|
this.syncEditMode();
|
|
13538
13540
|
}
|
|
13539
|
-
} else if (data
|
|
13540
|
-
|
|
13541
|
-
this.tab += 1;
|
|
13542
|
-
this.cursor = 0;
|
|
13543
|
-
this.submitIdx = 0;
|
|
13544
|
-
this.syncEditMode();
|
|
13545
|
-
} else {
|
|
13546
|
-
this.tab = this.questions.length;
|
|
13547
|
-
this.submitIdx = 0;
|
|
13548
|
-
this.syncEditMode();
|
|
13549
|
-
}
|
|
13550
|
-
} else this.otherInput.handleInput(data);
|
|
13541
|
+
} else if (matchesKey(data, "right")) this.commitOther(this.otherInput.getValue());
|
|
13542
|
+
else this.otherInput.handleInput(data);
|
|
13551
13543
|
return;
|
|
13552
13544
|
}
|
|
13553
13545
|
const rows = this.rows();
|
|
13554
13546
|
if (this.tab >= this.questions.length) {
|
|
13555
|
-
if (data
|
|
13547
|
+
if (matchesKey(data, "enter")) {
|
|
13556
13548
|
if (this.submitIdx === 0) this.submit();
|
|
13557
13549
|
else this.onCancel();
|
|
13558
|
-
} else if (data
|
|
13559
|
-
else if (data
|
|
13560
|
-
else if (data === "\x1B[C" || data === "l") this.submitIdx = 1;
|
|
13561
|
-
else if (data === "b") {
|
|
13550
|
+
} else if (matchesKey(data, "escape")) this.onCancel();
|
|
13551
|
+
else if (matchesKey(data, "left") || data === "h") {
|
|
13562
13552
|
this.tab = Math.max(0, this.questions.length - 1);
|
|
13563
13553
|
this.cursor = 0;
|
|
13564
13554
|
this.submitIdx = 0;
|
|
13565
13555
|
this.syncEditMode();
|
|
13566
|
-
}
|
|
13556
|
+
} else if (matchesKey(data, "up") || data === "k") this.submitIdx = 0;
|
|
13557
|
+
else if (matchesKey(data, "down") || data === "j") this.submitIdx = 1;
|
|
13567
13558
|
return;
|
|
13568
13559
|
}
|
|
13569
13560
|
const digit = /^[1-9]$/.exec(data);
|
|
@@ -13576,7 +13567,7 @@ var QuestionFlow = class {
|
|
|
13576
13567
|
}
|
|
13577
13568
|
return;
|
|
13578
13569
|
}
|
|
13579
|
-
if (data
|
|
13570
|
+
if (matchesKey(data, "up") || data === "k") {
|
|
13580
13571
|
if (rows.length === 0) return;
|
|
13581
13572
|
if (this.cursor === 0 && this.bodyScroll > 0) {
|
|
13582
13573
|
this.scrollBody(-1);
|
|
@@ -13586,7 +13577,7 @@ var QuestionFlow = class {
|
|
|
13586
13577
|
this.pendingCursorScroll = true;
|
|
13587
13578
|
return;
|
|
13588
13579
|
}
|
|
13589
|
-
if (data
|
|
13580
|
+
if (matchesKey(data, "down") || data === "j") {
|
|
13590
13581
|
if (rows.length === 0) return;
|
|
13591
13582
|
const atLastRow = this.cursor === rows.length - 1;
|
|
13592
13583
|
const scrolled = this.lastExpandable && this.lastContentRows > this.bodyScroll + this.lastVisibleRows;
|
|
@@ -13598,19 +13589,19 @@ var QuestionFlow = class {
|
|
|
13598
13589
|
this.pendingCursorScroll = true;
|
|
13599
13590
|
return;
|
|
13600
13591
|
}
|
|
13601
|
-
if (data
|
|
13602
|
-
this.scrollBody(data
|
|
13592
|
+
if (matchesKey(data, "pageUp") || matchesKey(data, "pageDown")) {
|
|
13593
|
+
this.scrollBody(matchesKey(data, "pageUp") ? -1 : 1);
|
|
13603
13594
|
return;
|
|
13604
13595
|
}
|
|
13605
13596
|
if (data === "e") {
|
|
13606
13597
|
this.toggleExpanded();
|
|
13607
13598
|
return;
|
|
13608
13599
|
}
|
|
13609
|
-
if (data
|
|
13600
|
+
if (matchesKey(data, "enter")) {
|
|
13610
13601
|
this.confirm();
|
|
13611
13602
|
return;
|
|
13612
13603
|
}
|
|
13613
|
-
if (data
|
|
13604
|
+
if (matchesKey(data, "left") || data === "h") {
|
|
13614
13605
|
if (this.tab > 0) {
|
|
13615
13606
|
this.tab -= 1;
|
|
13616
13607
|
this.cursor = 0;
|
|
@@ -13619,7 +13610,11 @@ var QuestionFlow = class {
|
|
|
13619
13610
|
}
|
|
13620
13611
|
return;
|
|
13621
13612
|
}
|
|
13622
|
-
if (data
|
|
13613
|
+
if (matchesKey(data, "right") || data === "l") {
|
|
13614
|
+
if (!this.answered()) {
|
|
13615
|
+
this.skip();
|
|
13616
|
+
return;
|
|
13617
|
+
}
|
|
13623
13618
|
if (this.tab < this.questions.length - 1) {
|
|
13624
13619
|
this.tab += 1;
|
|
13625
13620
|
this.cursor = 0;
|
|
@@ -13633,11 +13628,7 @@ var QuestionFlow = class {
|
|
|
13633
13628
|
}
|
|
13634
13629
|
return;
|
|
13635
13630
|
}
|
|
13636
|
-
if (data
|
|
13637
|
-
this.skip();
|
|
13638
|
-
return;
|
|
13639
|
-
}
|
|
13640
|
-
if (data === "\x1B") this.onCancel();
|
|
13631
|
+
if (matchesKey(data, "escape")) this.onCancel();
|
|
13641
13632
|
}
|
|
13642
13633
|
invalidate() {
|
|
13643
13634
|
this.otherInput.invalidate();
|
|
@@ -13680,7 +13671,7 @@ var QuestionFlow = class {
|
|
|
13680
13671
|
const submit = this.submitIdx === 0 ? color.textStrong("Submit") : color.textDim("Submit");
|
|
13681
13672
|
const cancel = this.submitIdx === 1 ? color.textStrong("Cancel") : color.textDim("Cancel");
|
|
13682
13673
|
lines.push(`${this.submitIdx === 0 ? color.primary("→ ") : " "}${submit} ${cancel}`);
|
|
13683
|
-
lines.push(color.textDim("
|
|
13674
|
+
lines.push(color.textDim("↑↓ choose · ← back · ↵ confirm · esc cancel"));
|
|
13684
13675
|
return lines;
|
|
13685
13676
|
}
|
|
13686
13677
|
const question = this.questions[this.tab];
|
|
@@ -13736,14 +13727,14 @@ var QuestionFlow = class {
|
|
|
13736
13727
|
lines.push("");
|
|
13737
13728
|
const optionCount = Math.min(rows.length, 9);
|
|
13738
13729
|
const scrollable = this.lastExpandable;
|
|
13730
|
+
const arrowVerb = this.editingOther ? "→ next" : "→ skip";
|
|
13739
13731
|
const hintParts = [
|
|
13740
13732
|
"↑↓ select",
|
|
13741
13733
|
optionCount > 0 ? `1-${optionCount} choose` : "",
|
|
13742
13734
|
multi ? "↵ toggle" : "↵ confirm",
|
|
13743
13735
|
scrollable ? "pgup/pgdn scroll" : "",
|
|
13744
13736
|
!this.editingOther ? this.bodyExpanded ? "e collapse" : scrollable ? "e expand" : "" : "",
|
|
13745
|
-
this.questions.length > 1 ?
|
|
13746
|
-
"s skip",
|
|
13737
|
+
this.questions.length > 1 ? `← back · ${arrowVerb}` : arrowVerb,
|
|
13747
13738
|
"esc cancel"
|
|
13748
13739
|
].filter((part) => part !== "");
|
|
13749
13740
|
const cancel = "esc cancel";
|
|
@@ -15329,6 +15320,17 @@ var TuiApp = class TuiApp {
|
|
|
15329
15320
|
this.requestRender();
|
|
15330
15321
|
}
|
|
15331
15322
|
/**
|
|
15323
|
+
* Anchor the transcript view to its END (the latest content). Fullscreen
|
|
15324
|
+
* scrolls its ScrollView; the regular surface has no scroll view (it draws
|
|
15325
|
+
* into the terminal scrollback), so a forced full repaint re-renders from
|
|
15326
|
+
* row 0 and the main screen's viewport tracking lands on the bottom — the
|
|
15327
|
+
* same mechanism the fullscreen-toggle path uses to redraw cleanly.
|
|
15328
|
+
*/
|
|
15329
|
+
scrollToBottom() {
|
|
15330
|
+
if (this.fullscreenScroll !== void 0) this.fullscreenScroll.scrollToEnd();
|
|
15331
|
+
else this.tui.requestRender(true);
|
|
15332
|
+
}
|
|
15333
|
+
/**
|
|
15332
15334
|
* Set the live session's auto-generated title (from the session/title
|
|
15333
15335
|
* log) for the header; undefined clears it.
|
|
15334
15336
|
*/
|
|
@@ -17688,6 +17690,48 @@ function registerTuiCommands(runner, initial) {
|
|
|
17688
17690
|
const sessionCwd = (agent) => agent.session.header.cwd ?? cwd;
|
|
17689
17691
|
const skillTarget = (agent) => resolveLiveSkillTarget(ctx, agent, sessionCwd(agent));
|
|
17690
17692
|
/**
|
|
17693
|
+
* Split a skill invocation's trailing input into the skill name and its
|
|
17694
|
+
* arguments: the first whitespace-bounded token is the name (the public
|
|
17695
|
+
* skill-name grammar), everything after it the arguments. Used by the
|
|
17696
|
+
* per-skill wrappers and `/skill`, so `/name args` never looks up a name
|
|
17697
|
+
* containing the whole rest of the line.
|
|
17698
|
+
* @param raw - the invocation's rawInput ('' for a bare command).
|
|
17699
|
+
* @returns the name token ('' when the input is blank) plus the args.
|
|
17700
|
+
*/
|
|
17701
|
+
const splitSkillLine = (raw) => {
|
|
17702
|
+
const trimmed = raw.trimStart();
|
|
17703
|
+
const space = trimmed.search(/\s/);
|
|
17704
|
+
if (space === -1) return [trimmed.trim(), ...[]];
|
|
17705
|
+
return [trimmed.slice(0, space).trim(), trimmed.slice(space).trimStart()];
|
|
17706
|
+
};
|
|
17707
|
+
/**
|
|
17708
|
+
* Structurally validate a skill's optional resource base, so a malformed
|
|
17709
|
+
* provider-supplied value degrades to no hint instead of throwing inside
|
|
17710
|
+
* the fallback rendering (the adapter's conservative rule — hostile
|
|
17711
|
+
* entries are refused, never coerced or thrown on).
|
|
17712
|
+
* @param value - the loaded skill's `resourceBase` (opaque from the adapter).
|
|
17713
|
+
* @returns the validated resource base, or undefined when unreadable.
|
|
17714
|
+
*/
|
|
17715
|
+
const readResourceBase = (value) => {
|
|
17716
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
17717
|
+
const record = value;
|
|
17718
|
+
switch (record.kind) {
|
|
17719
|
+
case "directory": return typeof record.path === "string" && record.path !== "" ? {
|
|
17720
|
+
kind: "directory",
|
|
17721
|
+
path: record.path
|
|
17722
|
+
} : void 0;
|
|
17723
|
+
case "url": return typeof record.url === "string" && record.url !== "" ? {
|
|
17724
|
+
kind: "url",
|
|
17725
|
+
url: record.url
|
|
17726
|
+
} : void 0;
|
|
17727
|
+
case "opaque": return typeof record.description === "string" && record.description !== "" ? {
|
|
17728
|
+
kind: "opaque",
|
|
17729
|
+
description: record.description
|
|
17730
|
+
} : void 0;
|
|
17731
|
+
default: return;
|
|
17732
|
+
}
|
|
17733
|
+
};
|
|
17734
|
+
/**
|
|
17691
17735
|
* The execution boundary for loading one skill into the live session;
|
|
17692
17736
|
* shared by /skill and the per-skill slash commands. The skill is fetched
|
|
17693
17737
|
* from the CURRENT agent's registry and its invocation policy is RE-CHECKED
|
|
@@ -17695,7 +17739,7 @@ function registerTuiCommands(runner, initial) {
|
|
|
17695
17739
|
* authorization. A model-only skill is refused with an explicit error and
|
|
17696
17740
|
* never injected.
|
|
17697
17741
|
*/
|
|
17698
|
-
const loadSkill = async (agent, name) => {
|
|
17742
|
+
const loadSkill = async (agent, name, args = "") => {
|
|
17699
17743
|
const target = skillTarget(agent);
|
|
17700
17744
|
if (target === void 0) return {
|
|
17701
17745
|
kind: "error",
|
|
@@ -17717,17 +17761,37 @@ function registerTuiCommands(runner, initial) {
|
|
|
17717
17761
|
kind: "error",
|
|
17718
17762
|
text: `skill "${name}" returned a malformed definition`
|
|
17719
17763
|
};
|
|
17720
|
-
const
|
|
17721
|
-
|
|
17764
|
+
const line = args.trim() === "" ? "/" + skill.name : "/" + skill.name + " " + args.trimStart();
|
|
17765
|
+
const userMessage = createUserMessage({
|
|
17722
17766
|
content: [{
|
|
17723
17767
|
type: "text",
|
|
17724
|
-
text:
|
|
17768
|
+
text: line
|
|
17725
17769
|
}],
|
|
17726
|
-
source: {
|
|
17727
|
-
|
|
17728
|
-
|
|
17729
|
-
|
|
17730
|
-
|
|
17770
|
+
source: { kind: "user" }
|
|
17771
|
+
});
|
|
17772
|
+
const hostSkillLoader = ctx.get("tools")?.get?.("skill", agent);
|
|
17773
|
+
const hostLoadsSkillBody = hostSkillLoader !== void 0 && typeof hostSkillLoader.execute === "function";
|
|
17774
|
+
agent.steer(userMessage);
|
|
17775
|
+
if (!hostLoadsSkillBody) {
|
|
17776
|
+
const body = typeof skill.content === "string" && skill.content !== "" ? skill.content : skill.description;
|
|
17777
|
+
const resourceBase = readResourceBase(skill.resourceBase);
|
|
17778
|
+
agent.inject(createUserMessage({
|
|
17779
|
+
content: [{
|
|
17780
|
+
type: "text",
|
|
17781
|
+
text: renderSkillContent({
|
|
17782
|
+
name: skill.name,
|
|
17783
|
+
provider: typeof skill.provider === "string" && skill.provider !== "" ? skill.provider : "tui",
|
|
17784
|
+
...resourceBase === void 0 ? {} : { resourceBase },
|
|
17785
|
+
content: body
|
|
17786
|
+
})
|
|
17787
|
+
}],
|
|
17788
|
+
source: {
|
|
17789
|
+
kind: "skill-invocation",
|
|
17790
|
+
name: skill.name,
|
|
17791
|
+
form: "instructions"
|
|
17792
|
+
}
|
|
17793
|
+
}));
|
|
17794
|
+
}
|
|
17731
17795
|
return {
|
|
17732
17796
|
kind: "success",
|
|
17733
17797
|
text: "skill " + name + " loaded"
|
|
@@ -17763,9 +17827,9 @@ function registerTuiCommands(runner, initial) {
|
|
|
17763
17827
|
const dispose = commands.register({
|
|
17764
17828
|
name: skill.name,
|
|
17765
17829
|
description: "[skill] " + skill.description,
|
|
17766
|
-
handler: async () => {
|
|
17830
|
+
handler: async (invocation) => {
|
|
17767
17831
|
const agent = await requireAgent();
|
|
17768
|
-
return loadSkill(agent, skill.name);
|
|
17832
|
+
return loadSkill(agent, skill.name, invocation?.rawInput ?? "");
|
|
17769
17833
|
}
|
|
17770
17834
|
});
|
|
17771
17835
|
skillDisposers.set(skill.name, dispose);
|
|
@@ -17811,9 +17875,9 @@ function registerTuiCommands(runner, initial) {
|
|
|
17811
17875
|
const dispose = commands.register({
|
|
17812
17876
|
name,
|
|
17813
17877
|
description: `[skill: revalidating] ${name}`,
|
|
17814
|
-
handler: async () => {
|
|
17878
|
+
handler: async (invocation) => {
|
|
17815
17879
|
const agent = await requireAgent();
|
|
17816
|
-
return loadSkill(agent, name);
|
|
17880
|
+
return loadSkill(agent, name, invocation?.rawInput ?? "");
|
|
17817
17881
|
}
|
|
17818
17882
|
});
|
|
17819
17883
|
skillDisposers.set(name, dispose);
|
|
@@ -17835,8 +17899,8 @@ function registerTuiCommands(runner, initial) {
|
|
|
17835
17899
|
kind: "error",
|
|
17836
17900
|
text: "skill service unavailable"
|
|
17837
17901
|
};
|
|
17838
|
-
const name = invocation.rawInput
|
|
17839
|
-
if (name !== "") return loadSkill(liveAgent, name);
|
|
17902
|
+
const [name, ...args] = splitSkillLine(invocation.rawInput);
|
|
17903
|
+
if (name !== "") return loadSkill(liveAgent, name, args.join(" "));
|
|
17840
17904
|
const catalog = await readHumanSkillCatalog(target.registry, {
|
|
17841
17905
|
cwd: target.cwd,
|
|
17842
17906
|
scope: target.scope
|
|
@@ -20443,6 +20507,26 @@ function shouldSteerOnEnter(parsed, running, busyEnter, forceQueue) {
|
|
|
20443
20507
|
function shouldConsumeAdvertisedMiss(execution, wasAdvertised) {
|
|
20444
20508
|
return execution === void 0 && wasAdvertised;
|
|
20445
20509
|
}
|
|
20510
|
+
/**
|
|
20511
|
+
* Match the child a user is about to view against the unsettled subagent
|
|
20512
|
+
* calls (pure, exported for the headless suite). The child's durable label
|
|
20513
|
+
* is the delegation's `description`; duplicate descriptions take the MOST
|
|
20514
|
+
* RECENT call (the one the user is most likely watching), an empty/absent
|
|
20515
|
+
* label falls back to a LONE pending call, and no match disables the
|
|
20516
|
+
* auto-pop (the user exits the viewer with Esc as before — never a wrong
|
|
20517
|
+
* pop). Mutates `pending` by removing the matched call.
|
|
20518
|
+
* @param pending - the unsettled calls, in order (oldest first).
|
|
20519
|
+
* @param label - the child's durable label; '' or undefined = no description.
|
|
20520
|
+
* @returns the matched call, or undefined when nothing matches.
|
|
20521
|
+
*/
|
|
20522
|
+
function matchPendingSubagentCall(pending, label) {
|
|
20523
|
+
if (label !== void 0 && label !== "") {
|
|
20524
|
+
for (let index = pending.length - 1; index >= 0; index -= 1) if (pending[index].description === label) return pending.splice(index, 1)[0];
|
|
20525
|
+
if (pending.length === 1) return pending.splice(0, 1)[0];
|
|
20526
|
+
return;
|
|
20527
|
+
}
|
|
20528
|
+
if (pending.length === 1) return pending.splice(0, 1)[0];
|
|
20529
|
+
}
|
|
20446
20530
|
async function resolveInitialCatalog(options) {
|
|
20447
20531
|
const { liveAgent, presetId, signal, ctx, diag } = options;
|
|
20448
20532
|
if (liveAgent !== void 0) try {
|
|
@@ -21564,6 +21648,8 @@ function apply(ctx, config) {
|
|
|
21564
21648
|
};
|
|
21565
21649
|
let repaintTimer;
|
|
21566
21650
|
let viewing;
|
|
21651
|
+
const pendingSubagentCalls = [];
|
|
21652
|
+
const viewCallToChild = /* @__PURE__ */ new Map();
|
|
21567
21653
|
const activeFolder = () => viewing?.folder ?? folder;
|
|
21568
21654
|
const paintNow = () => {
|
|
21569
21655
|
if (repaintTimer !== void 0) {
|
|
@@ -21586,6 +21672,8 @@ function apply(ctx, config) {
|
|
|
21586
21672
|
const bumpSessionGeneration = () => {
|
|
21587
21673
|
sessionGeneration += 1;
|
|
21588
21674
|
callArgs.clear();
|
|
21675
|
+
pendingSubagentCalls.length = 0;
|
|
21676
|
+
viewCallToChild.clear();
|
|
21589
21677
|
searchMatches = [];
|
|
21590
21678
|
searchCurrent = -1;
|
|
21591
21679
|
app.setSearchResult(0, 0);
|
|
@@ -21613,6 +21701,8 @@ function apply(ctx, config) {
|
|
|
21613
21701
|
childFolder.apply((await persistence.inspect(childId)).events);
|
|
21614
21702
|
} catch {}
|
|
21615
21703
|
}
|
|
21704
|
+
const matched = matchPendingSubagentCall(pendingSubagentCalls, label);
|
|
21705
|
+
if (matched !== void 0) viewCallToChild.set(matched.callId, childId);
|
|
21616
21706
|
viewing = {
|
|
21617
21707
|
id: childId,
|
|
21618
21708
|
folder: childFolder
|
|
@@ -21631,6 +21721,7 @@ function apply(ctx, config) {
|
|
|
21631
21721
|
app.clearNotify();
|
|
21632
21722
|
app.setViewerMode(void 0);
|
|
21633
21723
|
repaint(app, folder);
|
|
21724
|
+
app.scrollToBottom();
|
|
21634
21725
|
refreshStatus();
|
|
21635
21726
|
return true;
|
|
21636
21727
|
};
|
|
@@ -22518,17 +22609,42 @@ function apply(ctx, config) {
|
|
|
22518
22609
|
ctx.on("session/event", (session, event) => {
|
|
22519
22610
|
if (liveAgent === void 0) return;
|
|
22520
22611
|
if (viewing !== void 0) {
|
|
22521
|
-
if (session.id
|
|
22522
|
-
|
|
22523
|
-
|
|
22524
|
-
|
|
22525
|
-
|
|
22612
|
+
if (session.id === viewing.id) {
|
|
22613
|
+
viewing.folder.apply([event]);
|
|
22614
|
+
schedulePaint();
|
|
22615
|
+
if (event.type === "turn/end") paintNow();
|
|
22616
|
+
return;
|
|
22617
|
+
}
|
|
22526
22618
|
}
|
|
22527
22619
|
if (session.id !== liveAgent.session.id) return;
|
|
22528
22620
|
if (event.type === "tool/call") {
|
|
22529
22621
|
callArgs.set(event.data.callId, typeof event.data.arguments === "string" ? event.data.arguments : JSON.stringify(event.data.arguments));
|
|
22530
|
-
if (typeof event.data.name === "string" && event.data.name.startsWith("subagent"))
|
|
22531
|
-
|
|
22622
|
+
if (typeof event.data.name === "string" && event.data.name.startsWith("subagent")) {
|
|
22623
|
+
refreshAgents();
|
|
22624
|
+
let description = "";
|
|
22625
|
+
try {
|
|
22626
|
+
const parsed = JSON.parse(event.data.arguments);
|
|
22627
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.description === "string") description = parsed.description;
|
|
22628
|
+
} catch {}
|
|
22629
|
+
pendingSubagentCalls.push({
|
|
22630
|
+
callId: event.data.callId,
|
|
22631
|
+
description
|
|
22632
|
+
});
|
|
22633
|
+
}
|
|
22634
|
+
} else if (event.type === "tool/result") {
|
|
22635
|
+
const callId = event.data.message.content[0]?.toolCallId;
|
|
22636
|
+
callArgs.delete(callId ?? "");
|
|
22637
|
+
const callIndex = pendingSubagentCalls.findIndex((call) => call.callId === callId);
|
|
22638
|
+
if (callIndex !== -1) pendingSubagentCalls.splice(callIndex, 1);
|
|
22639
|
+
const childId = callId === void 0 ? void 0 : viewCallToChild.get(callId);
|
|
22640
|
+
if (childId !== void 0) viewCallToChild.delete(callId);
|
|
22641
|
+
if (childId !== void 0 && viewing !== void 0 && viewing.id === childId) {
|
|
22642
|
+
folder.apply([event]);
|
|
22643
|
+
statsFolder.apply([event]);
|
|
22644
|
+
exitView();
|
|
22645
|
+
return;
|
|
22646
|
+
}
|
|
22647
|
+
}
|
|
22532
22648
|
folder.apply([event]);
|
|
22533
22649
|
statsFolder.apply([event]);
|
|
22534
22650
|
if (event.type === "goal/change") goalText = foldGoal([event]);
|
|
@@ -22620,4 +22736,4 @@ function apply(ctx, config) {
|
|
|
22620
22736
|
});
|
|
22621
22737
|
}
|
|
22622
22738
|
//#endregion
|
|
22623
|
-
export { Config, LOCAL_COMMANDS, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, composeAgent, dangerCommand, foldQueueRows, forkSeed, inject, isPlainExitPrompt, isSubagentSettlementNotice, name, recomposeBlank, recordedPreset, resolveInitialCatalog, resumeCommand, runningProfile, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure };
|
|
22739
|
+
export { Config, LOCAL_COMMANDS, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, composeAgent, dangerCommand, foldQueueRows, forkSeed, inject, isPlainExitPrompt, isSubagentSettlementNotice, matchPendingSubagentCall, name, recomposeBlank, recordedPreset, resolveInitialCatalog, resumeCommand, runningProfile, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure };
|
package/package.json
CHANGED