@dungle-scrubs/tallow 0.8.24 → 0.8.26
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/auth-hardening.d.ts +12 -0
- package/dist/auth-hardening.d.ts.map +1 -1
- package/dist/auth-hardening.js +30 -7
- package/dist/auth-hardening.js.map +1 -1
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/install.js +2 -2
- package/dist/install.js.map +1 -1
- package/dist/interactive-mode-patch.d.ts.map +1 -1
- package/dist/interactive-mode-patch.js +119 -7
- package/dist/interactive-mode-patch.js.map +1 -1
- package/dist/model-metadata-overrides.d.ts +19 -0
- package/dist/model-metadata-overrides.d.ts.map +1 -0
- package/dist/model-metadata-overrides.js +38 -0
- package/dist/model-metadata-overrides.js.map +1 -0
- package/dist/sdk.d.ts +2 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +28 -1
- package/dist/sdk.js.map +1 -1
- package/extensions/__integration__/teams-runtime.test.ts +22 -1
- package/extensions/_shared/__tests__/shell-policy.test.ts +197 -0
- package/extensions/_shared/shell-policy.ts +27 -0
- package/extensions/background-task-tool/index.ts +2 -1
- package/extensions/bash-tool-enhanced/index.ts +2 -1
- package/extensions/custom-footer/__tests__/index.test.ts +29 -0
- package/extensions/custom-footer/context-display.ts +49 -0
- package/extensions/custom-footer/index.ts +10 -23
- package/extensions/permissions/index.ts +31 -10
- package/extensions/plan-mode-tool/__tests__/index.test.ts +32 -2
- package/extensions/plan-mode-tool/index.ts +6 -1
- package/extensions/skill-commands/__tests__/shared-skills-dirs.test.ts +113 -0
- package/extensions/skill-commands/index.ts +62 -5
- package/extensions/slash-command-bridge/index.ts +30 -1
- package/extensions/subagent-tool/__tests__/process-liveness.test.ts +42 -3
- package/extensions/subagent-tool/process.ts +132 -21
- package/extensions/tasks/__tests__/store.test.ts +26 -2
- package/extensions/tasks/commands/register-tasks-extension.ts +2 -2
- package/extensions/tasks/index.ts +5 -5
- package/extensions/tasks/state/index.ts +90 -36
- package/extensions/teams-tool/__tests__/archive-store.test.ts +98 -0
- package/extensions/teams-tool/__tests__/peer-messaging.test.ts +26 -0
- package/extensions/teams-tool/archive-store.ts +200 -0
- package/extensions/teams-tool/sessions/spawn.ts +244 -71
- package/extensions/teams-tool/tools/register-extension.ts +146 -105
- package/extensions/teams-tool/tools/teammate-tools.ts +43 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.js +59 -7
- package/node_modules/@mariozechner/pi-tui/dist/keys.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/package.json +1 -1
- package/node_modules/@mariozechner/pi-tui/src/keys.ts +71 -7
- package/package.json +5 -5
- package/skills/tallow-expert/SKILL.md +1 -1
- package/templates/agents/architect.md +13 -5
- package/templates/agents/debug.md +3 -3
- package/templates/agents/explore.md +9 -2
- package/templates/agents/refactor.md +2 -2
- package/templates/agents/scout.md +3 -2
- package/extensions/__integration__/plan-rejection-feedback.test.ts +0 -272
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
3
|
-
import { ExtensionHarness } from "../../test-utils/extension-harness.js";
|
|
4
|
-
import planModeExtension from "../plan-mode-tool/index.js";
|
|
5
|
-
|
|
6
|
-
const PLAN_TEXT = [
|
|
7
|
-
"Plan:",
|
|
8
|
-
"1. Inspect tool failure paths in plan execution",
|
|
9
|
-
"2. Verify fallback behavior for blocked operations",
|
|
10
|
-
"3. Finalize recovery guidance for remaining step",
|
|
11
|
-
].join("\n");
|
|
12
|
-
|
|
13
|
-
interface ContextOptions {
|
|
14
|
-
readonly confirmResponse?: boolean;
|
|
15
|
-
readonly editorResponse?: string;
|
|
16
|
-
readonly hasUI: boolean;
|
|
17
|
-
readonly selectResponse?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Create a minimal extension context with configurable UI responses.
|
|
22
|
-
*
|
|
23
|
-
* @param options - Context and UI response options
|
|
24
|
-
* @returns Extension context for direct event firing
|
|
25
|
-
*/
|
|
26
|
-
function createContext(options: ContextOptions): ExtensionContext {
|
|
27
|
-
const theme = {
|
|
28
|
-
bg(_token: string, value: string) {
|
|
29
|
-
return value;
|
|
30
|
-
},
|
|
31
|
-
fg(_token: string, value: string) {
|
|
32
|
-
return value;
|
|
33
|
-
},
|
|
34
|
-
strikethrough(value: string) {
|
|
35
|
-
return value;
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
abort: () => {},
|
|
41
|
-
compact: () => {},
|
|
42
|
-
cwd: process.cwd(),
|
|
43
|
-
getContextUsage: () => undefined,
|
|
44
|
-
getSystemPrompt: () => "",
|
|
45
|
-
hasPendingMessages: () => false,
|
|
46
|
-
hasUI: options.hasUI,
|
|
47
|
-
isIdle: () => true,
|
|
48
|
-
model: undefined,
|
|
49
|
-
modelRegistry: {
|
|
50
|
-
getApiKeyForProvider: async () => undefined,
|
|
51
|
-
} as never,
|
|
52
|
-
sessionManager: {
|
|
53
|
-
appendEntry: () => {},
|
|
54
|
-
getEntries: () => [],
|
|
55
|
-
} as never,
|
|
56
|
-
shutdown: () => {},
|
|
57
|
-
ui: {
|
|
58
|
-
async confirm() {
|
|
59
|
-
return options.confirmResponse ?? false;
|
|
60
|
-
},
|
|
61
|
-
async custom() {
|
|
62
|
-
return undefined as never;
|
|
63
|
-
},
|
|
64
|
-
async editor() {
|
|
65
|
-
return options.editorResponse;
|
|
66
|
-
},
|
|
67
|
-
async input() {
|
|
68
|
-
return undefined;
|
|
69
|
-
},
|
|
70
|
-
notify() {},
|
|
71
|
-
pasteToEditor() {},
|
|
72
|
-
async select() {
|
|
73
|
-
return options.selectResponse;
|
|
74
|
-
},
|
|
75
|
-
setEditorComponent() {},
|
|
76
|
-
setEditorText() {},
|
|
77
|
-
setFooter() {},
|
|
78
|
-
setHeader() {},
|
|
79
|
-
setStatus() {},
|
|
80
|
-
setTitle() {},
|
|
81
|
-
setToolsExpanded() {},
|
|
82
|
-
setWidget() {},
|
|
83
|
-
setWorkingMessage() {},
|
|
84
|
-
get theme() {
|
|
85
|
-
return theme as ExtensionContext["ui"]["theme"];
|
|
86
|
-
},
|
|
87
|
-
getAllThemes() {
|
|
88
|
-
return [];
|
|
89
|
-
},
|
|
90
|
-
getEditorText() {
|
|
91
|
-
return "";
|
|
92
|
-
},
|
|
93
|
-
getTheme() {
|
|
94
|
-
return undefined;
|
|
95
|
-
},
|
|
96
|
-
getToolsExpanded() {
|
|
97
|
-
return false;
|
|
98
|
-
},
|
|
99
|
-
setTheme() {
|
|
100
|
-
return { error: "Test stub", success: false };
|
|
101
|
-
},
|
|
102
|
-
} as ExtensionContext["ui"],
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Build an assistant message payload with a single text block.
|
|
108
|
-
*
|
|
109
|
-
* @param text - Assistant text content
|
|
110
|
-
* @returns Assistant message payload
|
|
111
|
-
*/
|
|
112
|
-
function assistantMessage(text: string): {
|
|
113
|
-
readonly content: readonly [{ readonly text: string; readonly type: "text" }];
|
|
114
|
-
readonly role: "assistant";
|
|
115
|
-
} {
|
|
116
|
-
return {
|
|
117
|
-
content: [{ text, type: "text" }],
|
|
118
|
-
role: "assistant",
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Initialize plan execution mode with a 3-step plan and tracking enabled.
|
|
124
|
-
*
|
|
125
|
-
* @param harness - Extension harness with plan-mode extension loaded
|
|
126
|
-
* @returns Promise that resolves once execution mode is active
|
|
127
|
-
*/
|
|
128
|
-
async function initializeExecutionMode(harness: ExtensionHarness): Promise<void> {
|
|
129
|
-
harness.setFlag("plan", true);
|
|
130
|
-
await harness.fireEvent(
|
|
131
|
-
"session_start",
|
|
132
|
-
{ type: "session_start" },
|
|
133
|
-
createContext({ hasUI: true })
|
|
134
|
-
);
|
|
135
|
-
await harness.fireEvent(
|
|
136
|
-
"agent_end",
|
|
137
|
-
{ messages: [assistantMessage(PLAN_TEXT)] },
|
|
138
|
-
createContext({
|
|
139
|
-
hasUI: true,
|
|
140
|
-
selectResponse: "Execute the plan (track progress)",
|
|
141
|
-
})
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Fire a failed tool_result event using the documented test payload shape.
|
|
147
|
-
*
|
|
148
|
-
* @param harness - Extension harness instance
|
|
149
|
-
* @param ctx - Extension context for the event
|
|
150
|
-
* @returns Promise that resolves after handlers run
|
|
151
|
-
*/
|
|
152
|
-
async function fireFailedToolResult(
|
|
153
|
-
harness: ExtensionHarness,
|
|
154
|
-
ctx: ExtensionContext
|
|
155
|
-
): Promise<void> {
|
|
156
|
-
await harness.fireEvent(
|
|
157
|
-
"tool_result",
|
|
158
|
-
{
|
|
159
|
-
content: [{ text: "blocked", type: "text" }],
|
|
160
|
-
input: { command: "echo blocked" },
|
|
161
|
-
isError: true,
|
|
162
|
-
toolCallId: "tool-call-1",
|
|
163
|
-
toolName: "bash",
|
|
164
|
-
},
|
|
165
|
-
ctx
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Fire a turn_end event that marks a plan step as complete.
|
|
171
|
-
*
|
|
172
|
-
* @param harness - Extension harness instance
|
|
173
|
-
* @param step - Step number to mark done
|
|
174
|
-
* @returns Promise that resolves after handlers run
|
|
175
|
-
*/
|
|
176
|
-
async function fireDoneStep(harness: ExtensionHarness, step: number): Promise<void> {
|
|
177
|
-
await harness.fireEvent(
|
|
178
|
-
"turn_end",
|
|
179
|
-
{ message: assistantMessage(`[DONE:${step}]`) },
|
|
180
|
-
createContext({ hasUI: true })
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
describe("Plan rejection feedback", () => {
|
|
185
|
-
it("ignores tool_result during execution when hasUI is false", async () => {
|
|
186
|
-
const harness = ExtensionHarness.create();
|
|
187
|
-
await harness.loadExtension(planModeExtension);
|
|
188
|
-
await initializeExecutionMode(harness);
|
|
189
|
-
|
|
190
|
-
await fireFailedToolResult(harness, createContext({ hasUI: false }));
|
|
191
|
-
|
|
192
|
-
expect(harness.sentUserMessages).toHaveLength(0);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("sends steer guidance with Step 1 prefix when user confirms and provides guidance", async () => {
|
|
196
|
-
const harness = ExtensionHarness.create();
|
|
197
|
-
await harness.loadExtension(planModeExtension);
|
|
198
|
-
await initializeExecutionMode(harness);
|
|
199
|
-
|
|
200
|
-
await fireFailedToolResult(
|
|
201
|
-
harness,
|
|
202
|
-
createContext({
|
|
203
|
-
confirmResponse: true,
|
|
204
|
-
editorResponse: "Use a narrower inspection command and continue.",
|
|
205
|
-
hasUI: true,
|
|
206
|
-
})
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
expect(harness.sentUserMessages).toHaveLength(1);
|
|
210
|
-
const [message] = harness.sentUserMessages;
|
|
211
|
-
if (!message || typeof message.content !== "string") {
|
|
212
|
-
throw new Error("Expected one string user message");
|
|
213
|
-
}
|
|
214
|
-
expect(message.content.startsWith("[PLAN GUIDANCE — Step 1:")).toBe(true);
|
|
215
|
-
expect(message.options?.deliverAs).toBe("steer");
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("does not send guidance when user declines confirmation", async () => {
|
|
219
|
-
const harness = ExtensionHarness.create();
|
|
220
|
-
await harness.loadExtension(planModeExtension);
|
|
221
|
-
await initializeExecutionMode(harness);
|
|
222
|
-
|
|
223
|
-
await fireFailedToolResult(
|
|
224
|
-
harness,
|
|
225
|
-
createContext({
|
|
226
|
-
confirmResponse: false,
|
|
227
|
-
hasUI: true,
|
|
228
|
-
})
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
expect(harness.sentUserMessages).toHaveLength(0);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it("advances tracked step guidance to Step 3 and stops after all steps complete", async () => {
|
|
235
|
-
const harness = ExtensionHarness.create();
|
|
236
|
-
await harness.loadExtension(planModeExtension);
|
|
237
|
-
await initializeExecutionMode(harness);
|
|
238
|
-
|
|
239
|
-
await fireDoneStep(harness, 1);
|
|
240
|
-
await fireDoneStep(harness, 2);
|
|
241
|
-
|
|
242
|
-
await fireFailedToolResult(
|
|
243
|
-
harness,
|
|
244
|
-
createContext({
|
|
245
|
-
confirmResponse: true,
|
|
246
|
-
editorResponse: "Focus on the final verification sequence.",
|
|
247
|
-
hasUI: true,
|
|
248
|
-
})
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
expect(harness.sentUserMessages).toHaveLength(1);
|
|
252
|
-
const [stepThreeGuidance] = harness.sentUserMessages;
|
|
253
|
-
if (!stepThreeGuidance || typeof stepThreeGuidance.content !== "string") {
|
|
254
|
-
throw new Error("Expected one string user message");
|
|
255
|
-
}
|
|
256
|
-
expect(stepThreeGuidance.content.startsWith("[PLAN GUIDANCE — Step 3:")).toBe(true);
|
|
257
|
-
expect(stepThreeGuidance.options?.deliverAs).toBe("steer");
|
|
258
|
-
|
|
259
|
-
await fireDoneStep(harness, 3);
|
|
260
|
-
|
|
261
|
-
await fireFailedToolResult(
|
|
262
|
-
harness,
|
|
263
|
-
createContext({
|
|
264
|
-
confirmResponse: true,
|
|
265
|
-
editorResponse: "This should not be sent after completion.",
|
|
266
|
-
hasUI: true,
|
|
267
|
-
})
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
expect(harness.sentUserMessages).toHaveLength(1);
|
|
271
|
-
});
|
|
272
|
-
});
|