@dungle-scrubs/tallow 0.8.21 → 0.8.23
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/cli.js +35 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/interactive-mode-patch.d.ts +2 -0
- package/dist/interactive-mode-patch.d.ts.map +1 -1
- package/dist/interactive-mode-patch.js +82 -0
- package/dist/interactive-mode-patch.js.map +1 -1
- package/dist/sdk.d.ts +17 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +68 -1
- package/dist/sdk.js.map +1 -1
- package/dist/workspace-transition-relay.d.ts +40 -7
- package/dist/workspace-transition-relay.d.ts.map +1 -1
- package/dist/workspace-transition-relay.js +81 -16
- package/dist/workspace-transition-relay.js.map +1 -1
- package/extensions/__integration__/background-task-widget-ownership.test.ts +216 -0
- package/extensions/__integration__/claude-hooks-compat.test.ts +156 -0
- package/extensions/__integration__/slash-command-bridge.test.ts +169 -23
- package/extensions/_shared/atomic-write.ts +1 -1
- package/extensions/_shared/bordered-box.ts +102 -0
- package/extensions/_shared/interop-events.ts +5 -0
- package/extensions/_shared/pid-registry.ts +1 -1
- package/extensions/agent-commands-tool/index.ts +4 -1
- package/extensions/background-task-tool/__tests__/lifecycle.test.ts +50 -25
- package/extensions/background-task-tool/index.ts +139 -221
- package/extensions/bash-tool-enhanced/index.ts +1 -75
- package/extensions/cd-tool/index.ts +2 -2
- package/extensions/context-fork/spawn.ts +4 -1
- package/extensions/health/index.ts +6 -6
- package/extensions/hooks/__tests__/claude-compat.test.ts +35 -0
- package/extensions/hooks/__tests__/subprocess-hardening.test.ts +73 -0
- package/extensions/hooks/index.ts +27 -4
- package/extensions/loop/__tests__/loop.test.ts +168 -4
- package/extensions/loop/extension.json +6 -5
- package/extensions/loop/index.ts +242 -31
- package/extensions/plan-mode-tool/__tests__/agent-end-execution.test.ts +373 -0
- package/extensions/plan-mode-tool/index.ts +103 -41
- package/extensions/prompt-suggestions/__tests__/editor-compatibility.test.ts +42 -0
- package/extensions/prompt-suggestions/index.ts +41 -6
- package/extensions/slash-command-bridge/__tests__/slash-command-bridge.test.ts +267 -671
- package/extensions/slash-command-bridge/extension.json +1 -1
- package/extensions/slash-command-bridge/index.ts +230 -116
- package/extensions/subagent-tool/index.ts +2 -2
- package/extensions/subagent-tool/process.ts +4 -5
- package/extensions/tasks/commands/register-tasks-extension.ts +41 -0
- package/extensions/teams-tool/__tests__/peer-messaging.test.ts +29 -24
- package/extensions/teams-tool/dashboard.ts +3 -5
- package/extensions/teams-tool/dispatch/auto-dispatch.ts +18 -1
- package/extensions/teams-tool/tools/teammate-tools.ts +9 -6
- package/extensions/wezterm-pane-control/__tests__/index.test.ts +88 -4
- package/extensions/wezterm-pane-control/index.ts +113 -8
- package/package.json +6 -4
- package/packages/tallow-tui/README.md +51 -0
- package/packages/tallow-tui/dist/autocomplete.d.ts +48 -0
- package/packages/tallow-tui/dist/autocomplete.d.ts.map +1 -0
- package/packages/tallow-tui/dist/autocomplete.js +564 -0
- package/packages/tallow-tui/dist/autocomplete.js.map +1 -0
- package/packages/tallow-tui/dist/border-styles.d.ts +32 -0
- package/packages/tallow-tui/dist/border-styles.d.ts.map +1 -0
- package/packages/tallow-tui/dist/border-styles.js +46 -0
- package/packages/tallow-tui/dist/border-styles.js.map +1 -0
- package/packages/tallow-tui/dist/components/bordered-box.d.ts +52 -0
- package/packages/tallow-tui/dist/components/bordered-box.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/bordered-box.js +89 -0
- package/packages/tallow-tui/dist/components/bordered-box.js.map +1 -0
- package/packages/tallow-tui/dist/components/box.d.ts +22 -0
- package/packages/tallow-tui/dist/components/box.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/box.js +104 -0
- package/packages/tallow-tui/dist/components/box.js.map +1 -0
- package/packages/tallow-tui/dist/components/cancellable-loader.d.ts +22 -0
- package/packages/tallow-tui/dist/components/cancellable-loader.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/cancellable-loader.js +35 -0
- package/packages/tallow-tui/dist/components/cancellable-loader.js.map +1 -0
- package/packages/tallow-tui/dist/components/editor.d.ts +240 -0
- package/packages/tallow-tui/dist/components/editor.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/editor.js +1766 -0
- package/packages/tallow-tui/dist/components/editor.js.map +1 -0
- package/packages/tallow-tui/dist/components/image.d.ts +126 -0
- package/packages/tallow-tui/dist/components/image.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/image.js +245 -0
- package/packages/tallow-tui/dist/components/image.js.map +1 -0
- package/packages/tallow-tui/dist/components/input.d.ts +37 -0
- package/packages/tallow-tui/dist/components/input.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/input.js +439 -0
- package/packages/tallow-tui/dist/components/input.js.map +1 -0
- package/packages/tallow-tui/dist/components/loader.d.ts +88 -0
- package/packages/tallow-tui/dist/components/loader.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/loader.js +146 -0
- package/packages/tallow-tui/dist/components/loader.js.map +1 -0
- package/packages/tallow-tui/dist/components/markdown.d.ts +95 -0
- package/packages/tallow-tui/dist/components/markdown.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/markdown.js +633 -0
- package/packages/tallow-tui/dist/components/markdown.js.map +1 -0
- package/packages/tallow-tui/dist/components/select-list.d.ts +32 -0
- package/packages/tallow-tui/dist/components/select-list.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/select-list.js +156 -0
- package/packages/tallow-tui/dist/components/select-list.js.map +1 -0
- package/packages/tallow-tui/dist/components/settings-list.d.ts +50 -0
- package/packages/tallow-tui/dist/components/settings-list.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/settings-list.js +189 -0
- package/packages/tallow-tui/dist/components/settings-list.js.map +1 -0
- package/packages/tallow-tui/dist/components/spacer.d.ts +12 -0
- package/packages/tallow-tui/dist/components/spacer.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/spacer.js +23 -0
- package/packages/tallow-tui/dist/components/spacer.js.map +1 -0
- package/packages/tallow-tui/dist/components/text.d.ts +19 -0
- package/packages/tallow-tui/dist/components/text.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/text.js +91 -0
- package/packages/tallow-tui/dist/components/text.js.map +1 -0
- package/packages/tallow-tui/dist/components/truncated-text.d.ts +13 -0
- package/packages/tallow-tui/dist/components/truncated-text.d.ts.map +1 -0
- package/packages/tallow-tui/dist/components/truncated-text.js +51 -0
- package/packages/tallow-tui/dist/components/truncated-text.js.map +1 -0
- package/packages/tallow-tui/dist/editor-component.d.ts +50 -0
- package/packages/tallow-tui/dist/editor-component.d.ts.map +1 -0
- package/packages/tallow-tui/dist/editor-component.js +2 -0
- package/packages/tallow-tui/dist/editor-component.js.map +1 -0
- package/packages/tallow-tui/dist/fuzzy.d.ts +16 -0
- package/packages/tallow-tui/dist/fuzzy.d.ts.map +1 -0
- package/packages/tallow-tui/dist/fuzzy.js +107 -0
- package/packages/tallow-tui/dist/fuzzy.js.map +1 -0
- package/packages/tallow-tui/dist/index.d.ts +25 -0
- package/packages/tallow-tui/dist/index.d.ts.map +1 -0
- package/packages/tallow-tui/dist/index.js +35 -0
- package/packages/tallow-tui/dist/index.js.map +1 -0
- package/packages/tallow-tui/dist/keybindings.d.ts +39 -0
- package/packages/tallow-tui/dist/keybindings.d.ts.map +1 -0
- package/packages/tallow-tui/dist/keybindings.js +114 -0
- package/packages/tallow-tui/dist/keybindings.js.map +1 -0
- package/packages/tallow-tui/dist/keys.d.ts +168 -0
- package/packages/tallow-tui/dist/keys.d.ts.map +1 -0
- package/packages/tallow-tui/dist/keys.js +971 -0
- package/packages/tallow-tui/dist/keys.js.map +1 -0
- package/packages/tallow-tui/dist/kill-ring.d.ts +28 -0
- package/packages/tallow-tui/dist/kill-ring.d.ts.map +1 -0
- package/packages/tallow-tui/dist/kill-ring.js +44 -0
- package/packages/tallow-tui/dist/kill-ring.js.map +1 -0
- package/packages/tallow-tui/dist/stdin-buffer.d.ts +48 -0
- package/packages/tallow-tui/dist/stdin-buffer.d.ts.map +1 -0
- package/packages/tallow-tui/dist/stdin-buffer.js +317 -0
- package/packages/tallow-tui/dist/stdin-buffer.js.map +1 -0
- package/packages/tallow-tui/dist/terminal-image.d.ts +161 -0
- package/packages/tallow-tui/dist/terminal-image.d.ts.map +1 -0
- package/packages/tallow-tui/dist/terminal-image.js +460 -0
- package/packages/tallow-tui/dist/terminal-image.js.map +1 -0
- package/packages/tallow-tui/dist/terminal.d.ts +102 -0
- package/packages/tallow-tui/dist/terminal.d.ts.map +1 -0
- package/packages/tallow-tui/dist/terminal.js +263 -0
- package/packages/tallow-tui/dist/terminal.js.map +1 -0
- package/packages/tallow-tui/dist/test-utils/capability-env.d.ts +14 -0
- package/packages/tallow-tui/dist/test-utils/capability-env.d.ts.map +1 -0
- package/packages/tallow-tui/dist/test-utils/capability-env.js +55 -0
- package/packages/tallow-tui/dist/test-utils/capability-env.js.map +1 -0
- package/packages/tallow-tui/dist/tui.d.ts +239 -0
- package/packages/tallow-tui/dist/tui.d.ts.map +1 -0
- package/packages/tallow-tui/dist/tui.js +1058 -0
- package/packages/tallow-tui/dist/tui.js.map +1 -0
- package/packages/tallow-tui/dist/undo-stack.d.ts +17 -0
- package/packages/tallow-tui/dist/undo-stack.d.ts.map +1 -0
- package/packages/tallow-tui/dist/undo-stack.js +25 -0
- package/packages/tallow-tui/dist/undo-stack.js.map +1 -0
- package/packages/tallow-tui/dist/utils.d.ts +96 -0
- package/packages/tallow-tui/dist/utils.d.ts.map +1 -0
- package/packages/tallow-tui/dist/utils.js +843 -0
- package/packages/tallow-tui/dist/utils.js.map +1 -0
- package/packages/tallow-tui/package.json +24 -0
- package/packages/tallow-tui/src/__tests__/__snapshots__/render.test.ts.snap +121 -0
- package/packages/tallow-tui/src/__tests__/editor-border.test.ts +72 -0
- package/packages/tallow-tui/src/__tests__/editor-change-listener.test.ts +121 -0
- package/packages/tallow-tui/src/__tests__/editor-ghost-text.test.ts +112 -0
- package/packages/tallow-tui/src/__tests__/fuzzy.test.ts +91 -0
- package/packages/tallow-tui/src/__tests__/image-component.test.ts +113 -0
- package/packages/tallow-tui/src/__tests__/keys.test.ts +141 -0
- package/packages/tallow-tui/src/__tests__/render.test.ts +179 -0
- package/packages/tallow-tui/src/__tests__/stdin-buffer.test.ts +82 -0
- package/packages/tallow-tui/src/__tests__/terminal-image.test.ts +363 -0
- package/packages/tallow-tui/src/__tests__/tui-diff-regression.test.ts +454 -0
- package/packages/tallow-tui/src/__tests__/tui-render-scheduling.test.ts +256 -0
- package/packages/tallow-tui/src/__tests__/utils.test.ts +259 -0
- package/packages/tallow-tui/src/autocomplete.ts +716 -0
- package/packages/tallow-tui/src/border-styles.ts +60 -0
- package/packages/tallow-tui/src/components/bordered-box.ts +113 -0
- package/packages/tallow-tui/src/components/box.ts +137 -0
- package/packages/tallow-tui/src/components/cancellable-loader.ts +40 -0
- package/packages/tallow-tui/src/components/editor.ts +2143 -0
- package/packages/tallow-tui/src/components/image.ts +315 -0
- package/packages/tallow-tui/src/components/input.ts +522 -0
- package/packages/tallow-tui/src/components/loader.ts +187 -0
- package/packages/tallow-tui/src/components/markdown.ts +780 -0
- package/packages/tallow-tui/src/components/select-list.ts +197 -0
- package/packages/tallow-tui/src/components/settings-list.ts +264 -0
- package/packages/tallow-tui/src/components/spacer.ts +28 -0
- package/packages/tallow-tui/src/components/text.ts +113 -0
- package/packages/tallow-tui/src/components/truncated-text.ts +65 -0
- package/packages/tallow-tui/src/editor-component.ts +92 -0
- package/packages/tallow-tui/src/fuzzy.ts +133 -0
- package/packages/tallow-tui/src/index.ts +118 -0
- package/packages/tallow-tui/src/keybindings.ts +183 -0
- package/packages/tallow-tui/src/keys.ts +1189 -0
- package/packages/tallow-tui/src/kill-ring.ts +46 -0
- package/packages/tallow-tui/src/stdin-buffer.ts +386 -0
- package/packages/tallow-tui/src/terminal-image.ts +619 -0
- package/packages/tallow-tui/src/terminal.ts +350 -0
- package/packages/tallow-tui/src/test-utils/capability-env.ts +56 -0
- package/packages/tallow-tui/src/tui.ts +1336 -0
- package/packages/tallow-tui/src/undo-stack.ts +28 -0
- package/packages/tallow-tui/src/utils.ts +948 -0
- package/packages/tallow-tui/tsconfig.build.json +21 -0
- package/runtime/agent-runner.ts +20 -0
- package/runtime/atomic-write.ts +8 -0
- package/runtime/otel.ts +12 -0
- package/runtime/resolve-module.ts +23 -0
- package/runtime/runtime-path-provider.ts +12 -0
- package/runtime/runtime-provenance.ts +17 -0
- package/runtime/workspace-transition-relay.ts +21 -0
- package/runtime/workspace-transition.ts +29 -0
|
@@ -79,11 +79,12 @@ describe("peer-to-peer teammate messaging", () => {
|
|
|
79
79
|
// Alice sends a message to bob
|
|
80
80
|
const result = await messageTool.execute("call-1", { to: "bob", content: "I found 42 files" });
|
|
81
81
|
|
|
82
|
-
// Message was stored
|
|
83
|
-
|
|
84
|
-
expect(
|
|
85
|
-
expect(
|
|
86
|
-
expect(
|
|
82
|
+
// Message was stored and marked as read (forwarded via wakeTeammate)
|
|
83
|
+
expect(team.messages.length).toBe(1);
|
|
84
|
+
expect(team.messages[0].from).toBe("alice");
|
|
85
|
+
expect(team.messages[0].content).toBe("I found 42 files");
|
|
86
|
+
expect(team.messages[0].readBy.has("bob")).toBe(true);
|
|
87
|
+
expect(getUnread(team, "bob").length).toBe(0);
|
|
87
88
|
|
|
88
89
|
// Bob was auto-woken: wakeTeammate called prompt() which resolves
|
|
89
90
|
// instantly with our mock, so status cycles working → idle.
|
|
@@ -132,24 +133,25 @@ describe("peer-to-peer teammate messaging", () => {
|
|
|
132
133
|
|
|
133
134
|
await messageTool.execute("call-4", { to: "all", content: "Step 1 done" });
|
|
134
135
|
|
|
135
|
-
// Both bob and carol
|
|
136
|
-
expect(getUnread(team, "bob").length).toBe(1);
|
|
137
|
-
expect(getUnread(team, "carol").length).toBe(1);
|
|
138
|
-
|
|
139
|
-
// Both were woken (they were idle)
|
|
136
|
+
// Both bob and carol were woken (they were idle)
|
|
140
137
|
expect(bobPrompts.length).toBe(1);
|
|
141
138
|
expect(carolPrompts.length).toBe(1);
|
|
142
139
|
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
// Messages marked as read for recipients who were forwarded the content
|
|
141
|
+
expect(getUnread(team, "bob").length).toBe(0);
|
|
142
|
+
expect(getUnread(team, "carol").length).toBe(0);
|
|
143
|
+
|
|
144
|
+
// Alice doesn't get her own broadcast forwarded (she sent it),
|
|
145
|
+
// but to="all" includes sender in the store
|
|
146
|
+
expect(getUnread(team, "alice").length).toBe(1);
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
it("message to working teammate is
|
|
149
|
+
it("message to working teammate is queued as followUp", async () => {
|
|
150
150
|
const team = freshTeam();
|
|
151
151
|
const { mate: alice } = mockTeammate("alice");
|
|
152
152
|
const { mate: bob, prompts: bobPrompts } = mockTeammate("bob", "working");
|
|
153
|
+
// Mark bob's session as streaming so wakeTeammate queues a followUp
|
|
154
|
+
(bob.session as unknown as { isStreaming: boolean }).isStreaming = true;
|
|
153
155
|
team.teammates.set("alice", alice);
|
|
154
156
|
team.teammates.set("bob", bob);
|
|
155
157
|
|
|
@@ -158,12 +160,13 @@ describe("peer-to-peer teammate messaging", () => {
|
|
|
158
160
|
|
|
159
161
|
await messageTool.execute("call-5", { to: "bob", content: "update for you" });
|
|
160
162
|
|
|
161
|
-
// Message stored
|
|
162
|
-
expect(
|
|
163
|
+
// Message stored and marked as read (forwarded via followUp)
|
|
164
|
+
expect(team.messages.length).toBe(1);
|
|
165
|
+
expect(team.messages[0].readBy.has("bob")).toBe(true);
|
|
163
166
|
|
|
164
|
-
// Bob
|
|
165
|
-
|
|
166
|
-
expect(bobPrompts
|
|
167
|
+
// Bob received the message as a followUp (mock records both prompt and followUp)
|
|
168
|
+
expect(bobPrompts.length).toBe(1);
|
|
169
|
+
expect(bobPrompts[0]).toContain("update for you");
|
|
167
170
|
});
|
|
168
171
|
|
|
169
172
|
it("message to nonexistent teammate still stores message", async () => {
|
|
@@ -194,15 +197,17 @@ describe("peer-to-peer teammate messaging", () => {
|
|
|
194
197
|
const aliceMsg = findTool(aliceTools, "team_message");
|
|
195
198
|
const bobMsg = findTool(bobTools, "team_message");
|
|
196
199
|
|
|
197
|
-
// Alice → Bob
|
|
200
|
+
// Alice → Bob (bob is idle, gets woken)
|
|
198
201
|
await aliceMsg.execute("c1", { to: "bob", content: "Found 42 files" });
|
|
199
202
|
expect(bobPrompts.length).toBe(1);
|
|
200
203
|
|
|
201
|
-
//
|
|
202
|
-
|
|
204
|
+
// After wakeTeammate resolves (mock is instant), bob goes idle.
|
|
205
|
+
// Simulate bob being in working state for the next message.
|
|
206
|
+
bob.status = "working";
|
|
207
|
+
(bob.session as unknown as { isStreaming: boolean }).isStreaming = true;
|
|
203
208
|
alice.status = "idle"; // alice finished her task
|
|
204
209
|
|
|
205
|
-
// Bob → Alice
|
|
210
|
+
// Bob → Alice (alice is idle, gets woken)
|
|
206
211
|
await bobMsg.execute("c2", { to: "alice", content: "Thanks, I need the list" });
|
|
207
212
|
expect(alicePrompts.length).toBe(1);
|
|
208
213
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { KeybindingsManager, Theme } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
import { CustomEditor } from "@mariozechner/pi-coding-agent";
|
|
3
3
|
import {
|
|
4
|
-
BorderedBox,
|
|
5
4
|
type EditorTheme,
|
|
6
5
|
Key,
|
|
7
6
|
matchesKey,
|
|
@@ -10,6 +9,7 @@ import {
|
|
|
10
9
|
visibleWidth,
|
|
11
10
|
} from "@mariozechner/pi-tui";
|
|
12
11
|
import { getIcon, getSpinner } from "../_icons/index.js";
|
|
12
|
+
import { renderBorderedBox } from "../_shared/bordered-box.js";
|
|
13
13
|
import {
|
|
14
14
|
formatIdentityText,
|
|
15
15
|
formatPresentationText,
|
|
@@ -927,11 +927,10 @@ export class TeamDashboardEditor extends CustomEditor {
|
|
|
927
927
|
): string[] {
|
|
928
928
|
if (width <= 0) return [];
|
|
929
929
|
if (team.teammates.length === 0) {
|
|
930
|
-
|
|
930
|
+
return renderBorderedBox(["No teammates yet."], width, {
|
|
931
931
|
borderColorFn: (str) => this.colorTheme.fg("borderMuted", str),
|
|
932
932
|
title: "empty",
|
|
933
933
|
});
|
|
934
|
-
return empty.render(width);
|
|
935
934
|
}
|
|
936
935
|
|
|
937
936
|
const columns = calculateDashboardGridColumns(width);
|
|
@@ -1013,14 +1012,13 @@ export class TeamDashboardEditor extends CustomEditor {
|
|
|
1013
1012
|
...outputLines.map((line) => ` ${formatDashboardRole(t, "process_output", line)}`),
|
|
1014
1013
|
];
|
|
1015
1014
|
|
|
1016
|
-
|
|
1015
|
+
return renderBorderedBox(body, width, {
|
|
1017
1016
|
borderColorFn: selected
|
|
1018
1017
|
? (str) => colorMemberText(str, teammate.name, true)
|
|
1019
1018
|
: (str) => t.fg("borderMuted", str),
|
|
1020
1019
|
title: `@${teammate.name}`,
|
|
1021
1020
|
titleColorFn: (str) => colorMemberText(str, teammate.name, selected),
|
|
1022
1021
|
});
|
|
1023
|
-
return box.render(width);
|
|
1024
1022
|
}
|
|
1025
1023
|
|
|
1026
1024
|
/**
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "../dashboard/state.js";
|
|
13
13
|
import { getRuntimeTeam } from "../state/team-view.js";
|
|
14
14
|
import type { Teammate } from "../state/types.js";
|
|
15
|
-
import { getReadyTasks, getTeammatesByStatus, type Team } from "../store.js";
|
|
15
|
+
import { getReadyTasks, getTeammatesByStatus, getUnread, markRead, type Team } from "../store.js";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Check for ready (unblocked, unclaimed) tasks and idle teammates,
|
|
@@ -106,6 +106,23 @@ export function wakeTeammate(
|
|
|
106
106
|
if (team) {
|
|
107
107
|
refreshTeamView(team);
|
|
108
108
|
autoDispatch(team, piEvents);
|
|
109
|
+
|
|
110
|
+
// Drain unread messages that arrived while working.
|
|
111
|
+
// team_message now queues follow-ups for working teammates,
|
|
112
|
+
// but messages can still slip through during status transitions.
|
|
113
|
+
if (mate.status === "idle") {
|
|
114
|
+
const unread = getUnread(team, mate.name);
|
|
115
|
+
if (unread.length > 0) {
|
|
116
|
+
markRead(team, mate.name);
|
|
117
|
+
const digest = unread.map((m) => `[${m.from}] ${m.content}`).join("\n\n");
|
|
118
|
+
wakeTeammate(
|
|
119
|
+
mate,
|
|
120
|
+
`You have ${unread.length} unread message(s) that arrived while you were busy:\n\n${digest}`,
|
|
121
|
+
teamName,
|
|
122
|
+
piEvents
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
109
126
|
}
|
|
110
127
|
}
|
|
111
128
|
})
|
|
@@ -158,14 +158,18 @@ export function createTeammateTools(
|
|
|
158
158
|
}),
|
|
159
159
|
// biome-ignore lint/suspicious/noExplicitAny: ToolDefinition params inferred from TypeBox schema
|
|
160
160
|
execute: async (_toolCallId: string, params: any) => {
|
|
161
|
-
addTeamMessage(team, myName, params.to, params.content);
|
|
161
|
+
const msg = addTeamMessage(team, myName, params.to, params.content);
|
|
162
162
|
appendDashboardFeedEvent(team.name, myName, params.to, params.content);
|
|
163
163
|
|
|
164
|
-
//
|
|
164
|
+
// Wake recipients — wakeTeammate handles all states:
|
|
165
|
+
// idle → prompt(), working/streaming → followUp(), shutdown/error → no-op
|
|
166
|
+
// Mark as read after forwarding: content was delivered via prompt/followUp,
|
|
167
|
+
// so the idle-transition drain won't re-deliver it.
|
|
165
168
|
if (params.to === "all") {
|
|
166
169
|
for (const [name, mate] of team.teammates) {
|
|
167
|
-
if (name !== myName
|
|
170
|
+
if (name !== myName) {
|
|
168
171
|
wakeTeammate(mate, `Broadcast from ${myName}: ${params.content}`, team.name, piEvents);
|
|
172
|
+
msg.readBy.add(name);
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
175
|
} else {
|
|
@@ -182,9 +186,8 @@ export function createTeammateTools(
|
|
|
182
186
|
details: {},
|
|
183
187
|
};
|
|
184
188
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
189
|
+
wakeTeammate(recipient, `Message from ${myName}: ${params.content}`, team.name, piEvents);
|
|
190
|
+
msg.readBy.add(params.to);
|
|
188
191
|
}
|
|
189
192
|
|
|
190
193
|
refreshTeamView(team as Team<Teammate>);
|
|
@@ -5,6 +5,9 @@ import weztermPaneControl, {
|
|
|
5
5
|
buildWeztermPaneGuidance,
|
|
6
6
|
executeWeztermAction,
|
|
7
7
|
filterPanesToCurrentTab,
|
|
8
|
+
hasExplicitPaneRequest,
|
|
9
|
+
hasSensitiveOutputMention,
|
|
10
|
+
isPaneCreatingAction,
|
|
8
11
|
unescapeText,
|
|
9
12
|
type WeztermCliResult,
|
|
10
13
|
type WeztermPaneInfo,
|
|
@@ -92,16 +95,45 @@ describe("wezterm-pane-control registration", () => {
|
|
|
92
95
|
});
|
|
93
96
|
|
|
94
97
|
describe("buildWeztermPaneGuidance", () => {
|
|
95
|
-
it("includes pane
|
|
98
|
+
it("includes bg_bash-first default, pane exceptions, sending, and privacy guidance", () => {
|
|
96
99
|
const guidance = buildWeztermPaneGuidance(116);
|
|
97
100
|
expect(guidance).toContain("WezTerm pane 116");
|
|
98
|
-
|
|
99
|
-
expect(guidance).toContain("
|
|
100
|
-
expect(guidance).toContain("
|
|
101
|
+
// bg_bash-first default
|
|
102
|
+
expect(guidance).toContain("use bg_bash");
|
|
103
|
+
expect(guidance).toContain("bg_bash");
|
|
104
|
+
// Pane exceptions — exactly 2
|
|
105
|
+
expect(guidance).toContain("User explicitly requests it");
|
|
106
|
+
expect(guidance).toContain("Sensitive output");
|
|
107
|
+
// Anti-speculative clause
|
|
108
|
+
expect(guidance).toContain("Never open a pane speculatively");
|
|
109
|
+
// bg_bash handles everything
|
|
110
|
+
expect(guidance).toContain(
|
|
111
|
+
"bg_bash\nhandles dev servers, builds, watchers, TUI apps, progress bars"
|
|
112
|
+
);
|
|
113
|
+
// Sending commands
|
|
101
114
|
expect(guidance).toContain("appending \\n");
|
|
115
|
+
// Privacy
|
|
102
116
|
expect(guidance).toContain("Do NOT call read_text on that pane");
|
|
103
117
|
expect(guidance).toContain("LLM must not consume secrets");
|
|
104
118
|
});
|
|
119
|
+
|
|
120
|
+
it("lists exactly 2 numbered exceptions", () => {
|
|
121
|
+
const guidance = buildWeztermPaneGuidance(116);
|
|
122
|
+
const numberedLines = guidance.split("\n").filter((l) => /^\d+\.\s/.test(l));
|
|
123
|
+
expect(numberedLines.length).toBe(2);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("does not contain removed over-permissive guidance", () => {
|
|
127
|
+
const guidance = buildWeztermPaneGuidance(116);
|
|
128
|
+
expect(guidance).not.toContain("Long-running process the user wants to visually monitor");
|
|
129
|
+
expect(guidance).not.toContain("Process that needs a proper shell environment");
|
|
130
|
+
expect(guidance).not.toContain("ask_user_question");
|
|
131
|
+
expect(guidance).not.toContain("just create the pane and run it");
|
|
132
|
+
// Removed TTY exception
|
|
133
|
+
expect(guidance).not.toContain("Interactive TTY required");
|
|
134
|
+
expect(guidance).not.toContain("curses/TUI interface");
|
|
135
|
+
expect(guidance).not.toContain("progress bars that require a real terminal");
|
|
136
|
+
});
|
|
105
137
|
});
|
|
106
138
|
|
|
107
139
|
describe("filterPanesToCurrentTab", () => {
|
|
@@ -378,3 +410,55 @@ describe("unescapeText", () => {
|
|
|
378
410
|
expect(unescapeText("no escapes here")).toBe("no escapes here");
|
|
379
411
|
});
|
|
380
412
|
});
|
|
413
|
+
|
|
414
|
+
describe("isPaneCreatingAction", () => {
|
|
415
|
+
it("returns true for pane-creating actions", () => {
|
|
416
|
+
expect(isPaneCreatingAction("split")).toBe(true);
|
|
417
|
+
expect(isPaneCreatingAction("spawn_tab")).toBe(true);
|
|
418
|
+
expect(isPaneCreatingAction("move_to_tab")).toBe(true);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it("returns false for non-creating actions", () => {
|
|
422
|
+
expect(isPaneCreatingAction("list")).toBe(false);
|
|
423
|
+
expect(isPaneCreatingAction("read_text")).toBe(false);
|
|
424
|
+
expect(isPaneCreatingAction("send_text")).toBe(false);
|
|
425
|
+
expect(isPaneCreatingAction("close")).toBe(false);
|
|
426
|
+
expect(isPaneCreatingAction("focus")).toBe(false);
|
|
427
|
+
expect(isPaneCreatingAction("zoom")).toBe(false);
|
|
428
|
+
expect(isPaneCreatingAction("resize")).toBe(false);
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
describe("hasExplicitPaneRequest", () => {
|
|
433
|
+
it("returns true for explicit pane/tab requests", () => {
|
|
434
|
+
expect(hasExplicitPaneRequest("open a pane for the server")).toBe(true);
|
|
435
|
+
expect(hasExplicitPaneRequest("new tab please")).toBe(true);
|
|
436
|
+
expect(hasExplicitPaneRequest("split the terminal")).toBe(true);
|
|
437
|
+
expect(hasExplicitPaneRequest("use wezterm to show logs")).toBe(true);
|
|
438
|
+
expect(hasExplicitPaneRequest("spawn a tab for this")).toBe(true);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it("returns false for non-pane prompts", () => {
|
|
442
|
+
expect(hasExplicitPaneRequest("start the dev server")).toBe(false);
|
|
443
|
+
expect(hasExplicitPaneRequest("run the build")).toBe(false);
|
|
444
|
+
expect(hasExplicitPaneRequest("left align the text")).toBe(false);
|
|
445
|
+
expect(hasExplicitPaneRequest("watch for file changes")).toBe(false);
|
|
446
|
+
expect(hasExplicitPaneRequest("open the browser")).toBe(false);
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
describe("hasSensitiveOutputMention", () => {
|
|
451
|
+
it("returns true for sensitive output mentions", () => {
|
|
452
|
+
expect(hasSensitiveOutputMention("show me the api key")).toBe(true);
|
|
453
|
+
expect(hasSensitiveOutputMention("generate a token")).toBe(true);
|
|
454
|
+
expect(hasSensitiveOutputMention("display the password")).toBe(true);
|
|
455
|
+
expect(hasSensitiveOutputMention("fetch my credentials")).toBe(true);
|
|
456
|
+
expect(hasSensitiveOutputMention("read the secret from 1password")).toBe(true);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it("returns false for non-sensitive prompts", () => {
|
|
460
|
+
expect(hasSensitiveOutputMention("start the dev server")).toBe(false);
|
|
461
|
+
expect(hasSensitiveOutputMention("run the tests")).toBe(false);
|
|
462
|
+
expect(hasSensitiveOutputMention("build the project")).toBe(false);
|
|
463
|
+
});
|
|
464
|
+
});
|
|
@@ -84,6 +84,71 @@ interface ToolResult {
|
|
|
84
84
|
isError?: boolean;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* WezTerm pane actions that create new panes or tabs.
|
|
89
|
+
* These are gated by the guardrail hook — blocked unless the user's prompt
|
|
90
|
+
* explicitly requests pane/tab creation.
|
|
91
|
+
*/
|
|
92
|
+
export const PANE_CREATING_ACTIONS: ReadonlySet<string> = new Set([
|
|
93
|
+
"split",
|
|
94
|
+
"spawn_tab",
|
|
95
|
+
"move_to_tab",
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Patterns that indicate the user explicitly wants pane/tab creation.
|
|
100
|
+
* Only unambiguous pane vocabulary — no generic words like "window", "left", "right".
|
|
101
|
+
*/
|
|
102
|
+
export const EXPLICIT_PANE_REQUEST_PATTERNS: readonly RegExp[] = [
|
|
103
|
+
/\bwezterm\b/i,
|
|
104
|
+
/\bpane(?:s)?\b/i,
|
|
105
|
+
/\btab(?:s)?\b/i,
|
|
106
|
+
/\bsplit\b/i,
|
|
107
|
+
/\bspawn\b/i,
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Patterns that indicate sensitive output the LLM should not see.
|
|
112
|
+
* Pane creation is allowed for these so the user can view secrets directly.
|
|
113
|
+
*/
|
|
114
|
+
export const SENSITIVE_OUTPUT_PATTERNS: readonly RegExp[] = [
|
|
115
|
+
/\bsecret(?:s)?\b/i,
|
|
116
|
+
/\btoken(?:s)?\b/i,
|
|
117
|
+
/\bpassword(?:s)?\b/i,
|
|
118
|
+
/\bapi[- ]?key(?:s)?\b/i,
|
|
119
|
+
/\bcredential(?:s)?\b/i,
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Check whether a wezterm_pane action creates a new pane or tab.
|
|
124
|
+
*
|
|
125
|
+
* @param action - The action string from tool parameters
|
|
126
|
+
* @returns True when the action would create a pane/tab
|
|
127
|
+
*/
|
|
128
|
+
export function isPaneCreatingAction(action: string): boolean {
|
|
129
|
+
return PANE_CREATING_ACTIONS.has(action);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check whether user prompt text contains an explicit pane/tab request.
|
|
134
|
+
*
|
|
135
|
+
* @param prompt - The user's prompt text
|
|
136
|
+
* @returns True when the prompt explicitly mentions panes/tabs
|
|
137
|
+
*/
|
|
138
|
+
export function hasExplicitPaneRequest(prompt: string): boolean {
|
|
139
|
+
return EXPLICIT_PANE_REQUEST_PATTERNS.some((pattern) => pattern.test(prompt));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check whether user prompt text mentions sensitive output.
|
|
144
|
+
*
|
|
145
|
+
* @param prompt - The user's prompt text
|
|
146
|
+
* @returns True when the prompt mentions secrets/tokens/passwords
|
|
147
|
+
*/
|
|
148
|
+
export function hasSensitiveOutputMention(prompt: string): boolean {
|
|
149
|
+
return SENSITIVE_OUTPUT_PATTERNS.some((pattern) => pattern.test(prompt));
|
|
150
|
+
}
|
|
151
|
+
|
|
87
152
|
const ACTIONS: readonly WeztermAction[] = [
|
|
88
153
|
"list",
|
|
89
154
|
"split",
|
|
@@ -424,6 +489,11 @@ function runOrThrow(runCli: WeztermCliRunner, args: readonly string[]): string {
|
|
|
424
489
|
/**
|
|
425
490
|
* Build system-prompt guidance for WezTerm pane control behavior.
|
|
426
491
|
*
|
|
492
|
+
* Encodes a bg_bash-first policy: panes are the exception, not the default.
|
|
493
|
+
* Long-running processes (dev servers, watchers, builds) should use bg_bash.
|
|
494
|
+
* Panes are reserved for explicit user requests and sensitive output that the
|
|
495
|
+
* LLM must not see.
|
|
496
|
+
*
|
|
427
497
|
* @param currentPaneId - Current WezTerm pane ID
|
|
428
498
|
* @returns Guidance block appended to the system prompt
|
|
429
499
|
*/
|
|
@@ -435,16 +505,24 @@ export function buildWeztermPaneGuidance(currentPaneId: number): string {
|
|
|
435
505
|
"Use the wezterm_pane tool to manage panes: split, close, focus, zoom, resize, send/read text, or spawn new tabs.",
|
|
436
506
|
'Use action "list" to see panes in the current tab.',
|
|
437
507
|
"",
|
|
438
|
-
"##
|
|
508
|
+
"## Default: use bg_bash, not panes",
|
|
509
|
+
"",
|
|
510
|
+
"For long-running processes (dev servers, watchers, builds, tests, compilers),",
|
|
511
|
+
"use `bg_bash` with `background: true`. Monitor output with `task_output`.",
|
|
512
|
+
"This is the default — do NOT open a pane unless one of the exceptions below applies.",
|
|
513
|
+
"",
|
|
514
|
+
"## When to open a pane (exceptions only)",
|
|
515
|
+
"",
|
|
516
|
+
"Open a pane or tab ONLY when one of these is true:",
|
|
439
517
|
"",
|
|
440
|
-
|
|
441
|
-
"
|
|
442
|
-
"
|
|
443
|
-
"
|
|
518
|
+
'1. **User explicitly requests it** — they said "open a pane", "use a pane",',
|
|
519
|
+
' "split", "new tab", or similar. Without an explicit request, do NOT open a pane.',
|
|
520
|
+
"2. **Sensitive output** — secrets, tokens, passwords the LLM must not see.",
|
|
521
|
+
" Spawn the pane, send the command, do NOT read_text the output.",
|
|
444
522
|
"",
|
|
445
|
-
"
|
|
446
|
-
"
|
|
447
|
-
"
|
|
523
|
+
"If uncertain, ALWAYS use bg_bash. Never open a pane speculatively — bg_bash",
|
|
524
|
+
"handles dev servers, builds, watchers, TUI apps, progress bars, and",
|
|
525
|
+
"interactive prompts fine.",
|
|
448
526
|
"",
|
|
449
527
|
"## Sending commands",
|
|
450
528
|
"",
|
|
@@ -713,4 +791,31 @@ export default function weztermPaneControl(pi: ExtensionAPI): void {
|
|
|
713
791
|
systemPrompt: `${event.systemPrompt}\n\n${buildWeztermPaneGuidance(currentPaneId)}`,
|
|
714
792
|
};
|
|
715
793
|
});
|
|
794
|
+
|
|
795
|
+
// Track the current turn's user prompt for the guardrail hook.
|
|
796
|
+
// Updated via "input" event which fires before agent processing.
|
|
797
|
+
let currentTurnPrompt = "";
|
|
798
|
+
|
|
799
|
+
pi.on("input", async (event) => {
|
|
800
|
+
currentTurnPrompt = event.text ?? "";
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
// Guardrail: block pane-creating actions unless the user explicitly asked for panes
|
|
804
|
+
// or mentioned sensitive output. This is the enforcement mechanism — prompt guidance
|
|
805
|
+
// alone has failed repeatedly (see plan 186 history).
|
|
806
|
+
pi.on("tool_call", async (event) => {
|
|
807
|
+
if (event.toolName !== "wezterm_pane") return;
|
|
808
|
+
|
|
809
|
+
const params = event.input as { action?: string } | undefined;
|
|
810
|
+
if (!params?.action || !isPaneCreatingAction(params.action)) return;
|
|
811
|
+
|
|
812
|
+
if (hasExplicitPaneRequest(currentTurnPrompt)) return;
|
|
813
|
+
if (hasSensitiveOutputMention(currentTurnPrompt)) return;
|
|
814
|
+
|
|
815
|
+
return {
|
|
816
|
+
block: true,
|
|
817
|
+
reason:
|
|
818
|
+
"Pane creation blocked — no explicit pane/tab request detected in this turn. Use bg_bash for long-running processes. The user must say 'pane', 'tab', 'split', etc. to open a WezTerm pane.",
|
|
819
|
+
};
|
|
820
|
+
});
|
|
716
821
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dungle-scrubs/tallow",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.23",
|
|
4
4
|
"description": "An opinionated coding agent. Built on pi.",
|
|
5
5
|
"piConfig": {
|
|
6
6
|
"name": "tallow",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
27
|
"extensions",
|
|
28
|
+
"packages/tallow-tui",
|
|
29
|
+
"runtime",
|
|
28
30
|
"schemas",
|
|
29
31
|
"skills",
|
|
30
32
|
"templates",
|
|
@@ -70,7 +72,7 @@
|
|
|
70
72
|
"dependencies": {
|
|
71
73
|
"@clack/prompts": "^1.0.0",
|
|
72
74
|
"@dungle-scrubs/synapse": "0.1.6",
|
|
73
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
75
|
+
"@mariozechner/pi-coding-agent": "^0.58.1",
|
|
74
76
|
"@opentelemetry/api": "^1.9.0",
|
|
75
77
|
"@sinclair/typebox": "0.34.48",
|
|
76
78
|
"ai": "^6.0.86",
|
|
@@ -80,8 +82,8 @@
|
|
|
80
82
|
},
|
|
81
83
|
"devDependencies": {
|
|
82
84
|
"@biomejs/biome": "2.4.2",
|
|
83
|
-
"@mariozechner/pi-agent-core": "^0.
|
|
84
|
-
"@mariozechner/pi-ai": "^0.
|
|
85
|
+
"@mariozechner/pi-agent-core": "^0.58.1",
|
|
86
|
+
"@mariozechner/pi-ai": "^0.58.1",
|
|
85
87
|
"@mariozechner/pi-tui": "workspace:*",
|
|
86
88
|
"@types/node": "25.2.3",
|
|
87
89
|
"husky": "^9.1.7",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# @mariozechner/pi-tui (Tallow fork)
|
|
2
|
+
|
|
3
|
+
Tallow's fork of `@mariozechner/pi-tui` (v0.52.9). Adds customizable
|
|
4
|
+
loader, border styles, and input middleware — changes that require
|
|
5
|
+
modifying pi-tui internals.
|
|
6
|
+
|
|
7
|
+
## What's different from upstream
|
|
8
|
+
|
|
9
|
+
### Configurable Loader
|
|
10
|
+
|
|
11
|
+
`Loader` accepts optional `frames` and `intervalMs` via constructor
|
|
12
|
+
options. Static `Loader.defaultFrames` / `Loader.defaultIntervalMs`
|
|
13
|
+
let extensions set global defaults at session start.
|
|
14
|
+
|
|
15
|
+
### Border styles
|
|
16
|
+
|
|
17
|
+
New `BorderStyle` interface with three presets: `SHARP` (┌┐└┘),
|
|
18
|
+
`ROUNDED` (╭╮╰╯), `FLAT` (horizontal rules only).
|
|
19
|
+
`BorderedBox` component wraps content in a full border with optional
|
|
20
|
+
title, padding, and color functions.
|
|
21
|
+
|
|
22
|
+
### Input middleware
|
|
23
|
+
|
|
24
|
+
`TUI.addInputMiddleware(fn)` inserts a hook before `handleInput`
|
|
25
|
+
forwards to the focused component. Middleware returns `true` to
|
|
26
|
+
consume input. Used by the which-key overlay extension.
|
|
27
|
+
|
|
28
|
+
## Upstream sync
|
|
29
|
+
|
|
30
|
+
Source extracted from `@mariozechner/pi-tui@0.52.9` source maps.
|
|
31
|
+
|
|
32
|
+
### Modified files (conflict surface on sync)
|
|
33
|
+
|
|
34
|
+
| File | Change |
|
|
35
|
+
|------|--------|
|
|
36
|
+
| `components/loader.ts` | Constructor options, static defaults |
|
|
37
|
+
| `tui.ts` | Input middleware array + add/remove methods |
|
|
38
|
+
|
|
39
|
+
### Added files (zero conflict)
|
|
40
|
+
|
|
41
|
+
| File | Purpose |
|
|
42
|
+
|------|---------|
|
|
43
|
+
| `border-styles.ts` | BorderStyle interface + presets |
|
|
44
|
+
| `components/bordered-box.ts` | Box component with configurable borders |
|
|
45
|
+
|
|
46
|
+
### How to sync
|
|
47
|
+
|
|
48
|
+
1. Extract new upstream source from source maps (same script)
|
|
49
|
+
2. Diff against `src/` — conflicts only in modified files above
|
|
50
|
+
3. Apply upstream changes, keep our additions
|
|
51
|
+
4. Rebuild: `cd packages/tallow-tui && npm run build`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface AutocompleteItem {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SlashCommand {
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
getArgumentCompletions?(argumentPrefix: string): AutocompleteItem[] | null;
|
|
10
|
+
}
|
|
11
|
+
export interface AutocompleteProvider {
|
|
12
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): {
|
|
13
|
+
items: AutocompleteItem[];
|
|
14
|
+
prefix: string;
|
|
15
|
+
} | null;
|
|
16
|
+
applyCompletion(lines: string[], cursorLine: number, cursorCol: number, item: AutocompleteItem, prefix: string): {
|
|
17
|
+
lines: string[];
|
|
18
|
+
cursorLine: number;
|
|
19
|
+
cursorCol: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
23
|
+
private commands;
|
|
24
|
+
private basePath;
|
|
25
|
+
private fdPath;
|
|
26
|
+
constructor(commands?: (SlashCommand | AutocompleteItem)[], basePath?: string, fdPath?: string | null);
|
|
27
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): {
|
|
28
|
+
items: AutocompleteItem[];
|
|
29
|
+
prefix: string;
|
|
30
|
+
} | null;
|
|
31
|
+
applyCompletion(lines: string[], cursorLine: number, cursorCol: number, item: AutocompleteItem, prefix: string): {
|
|
32
|
+
lines: string[];
|
|
33
|
+
cursorLine: number;
|
|
34
|
+
cursorCol: number;
|
|
35
|
+
};
|
|
36
|
+
private extractAtPrefix;
|
|
37
|
+
private extractPathPrefix;
|
|
38
|
+
private expandHomePath;
|
|
39
|
+
private getFileSuggestions;
|
|
40
|
+
private scoreEntry;
|
|
41
|
+
private getFuzzyFileSuggestions;
|
|
42
|
+
getForceFileSuggestions(lines: string[], cursorLine: number, cursorCol: number): {
|
|
43
|
+
items: AutocompleteItem[];
|
|
44
|
+
prefix: string;
|
|
45
|
+
} | null;
|
|
46
|
+
shouldTriggerFileCompletion(lines: string[], cursorLine: number, cursorCol: number): boolean;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=autocomplete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AA2JA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAgB;gBAG7B,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAClD,QAAQ,GAAE,MAAsB,EAChC,MAAM,GAAE,MAAM,GAAG,IAAW;IAO7B,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAqGvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAwF7D,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,kBAAkB;IAoI1B,OAAO,CAAC,UAAU;IAuBlB,OAAO,CAAC,uBAAuB;IAkD/B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAyBvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}
|