@nmzpy/pi-ember-stack 0.1.2 → 0.1.4
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/ATTRIBUTION.md +3 -2
- package/README.md +8 -7
- package/package.json +1 -1
- package/plugins/index.ts +21 -13
- package/plugins/pi-compact-tools/index.ts +74 -0
- package/plugins/{ember → pi-custom-agents}/index.ts +26 -77
- /package/plugins/{ember → pi-compact-tools}/questionnaire-tool.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/LICENSE +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/README.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agent-format.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agents/architect.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agents/coder.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agents/general-purpose.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agents/reviewer.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agents/scout.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/agents/worker.md +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/agents.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/index.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/model.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/package.json +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/render.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/runner.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/service.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/thread-viewer.ts +0 -0
- /package/plugins/{subagent → pi-custom-agents/subagent}/extensions/threads.ts +0 -0
package/ATTRIBUTION.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Attribution
|
|
2
2
|
|
|
3
|
-
`plugins/subagent/extensions/` and the upstream bundled agent
|
|
3
|
+
`plugins/pi-custom-agents/subagent/extensions/` and the upstream bundled agent
|
|
4
|
+
files were vendored
|
|
4
5
|
from `@bacnh85/pi-subagent` version `0.5.0`.
|
|
5
6
|
|
|
6
7
|
The upstream package declares the MIT license. The vendored subtree retains
|
|
7
|
-
that license in `plugins/subagent/LICENSE`, along with the original README, agent
|
|
8
|
+
that license in `plugins/pi-custom-agents/subagent/LICENSE`, along with the original README, agent
|
|
8
9
|
format documentation, bundled roles, package version, and attribution.
|
|
9
10
|
Upstream project: <https://github.com/bacnh85/pi-extensions>.
|
|
10
11
|
|
package/README.md
CHANGED
|
@@ -23,15 +23,15 @@ plugins under `plugins/`. Ember projects enable them in `.pi/ember-stack.json`:
|
|
|
23
23
|
|
|
24
24
|
```json
|
|
25
25
|
{
|
|
26
|
-
"plugins": ["
|
|
26
|
+
"plugins": ["pi-compact-tools", "pi-custom-agents", "devin-auth"]
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Remove a plugin ID to disable it, or use `/stack-plugins` to toggle one from
|
|
31
31
|
the TUI. Restart pi after changing the list. The available plugins are:
|
|
32
32
|
|
|
33
|
-
- `
|
|
34
|
-
- `
|
|
33
|
+
- `pi-compact-tools`: collapsed native edit rendering and questionnaire UI.
|
|
34
|
+
- `pi-custom-agents`: primary modes, plans, subagent tool, and bundled agent definitions.
|
|
35
35
|
- `devin-auth`: Devin provider, OAuth, catalog refresh, and streaming.
|
|
36
36
|
|
|
37
37
|
## Project setup
|
|
@@ -39,7 +39,7 @@ the TUI. Restart pi after changing the list. The available plugins are:
|
|
|
39
39
|
The Ember repository contains a project-local `.pi/settings.json` entry for:
|
|
40
40
|
|
|
41
41
|
```json
|
|
42
|
-
"npm:@nmzpy/pi-ember-stack@0.1.
|
|
42
|
+
"npm:@nmzpy/pi-ember-stack@0.1.4"
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
On a new clone, start pi from the project directory. Pi will ask for a
|
|
@@ -68,9 +68,10 @@ of this repository.
|
|
|
68
68
|
|
|
69
69
|
## Development
|
|
70
70
|
|
|
71
|
-
The package entrypoint is `plugins/index.ts`.
|
|
72
|
-
`plugins/
|
|
73
|
-
|
|
71
|
+
The package entrypoint is `plugins/index.ts`. Compact tools are under
|
|
72
|
+
`plugins/pi-compact-tools/`, while primary modes, plans, subagents, and bundled
|
|
73
|
+
agents are under `plugins/pi-custom-agents/`. Devin auth is under
|
|
74
|
+
`plugins/devin-auth/`.
|
|
74
75
|
|
|
75
76
|
Run the package typecheck with:
|
|
76
77
|
|
package/package.json
CHANGED
package/plugins/index.ts
CHANGED
|
@@ -3,14 +3,19 @@ import * as path from "node:path";
|
|
|
3
3
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
|
|
5
5
|
import devinAuthPlugin from "./devin-auth/extensions/index.ts";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
6
|
+
import piCompactToolsPlugin from "./pi-compact-tools/index.ts";
|
|
7
|
+
import piCustomAgentsPlugin, {
|
|
8
|
+
type PiCustomAgentsOptions,
|
|
9
|
+
} from "./pi-custom-agents/index.ts";
|
|
8
10
|
|
|
9
|
-
type PluginId = "
|
|
11
|
+
type PluginId = "pi-compact-tools" | "pi-custom-agents" | "devin-auth";
|
|
10
12
|
type StackPlugin = {
|
|
11
13
|
id: PluginId;
|
|
12
14
|
description: string;
|
|
13
|
-
extension: (
|
|
15
|
+
extension: (
|
|
16
|
+
pi: ExtensionAPI,
|
|
17
|
+
options?: PiCustomAgentsOptions,
|
|
18
|
+
) => void | Promise<void>;
|
|
14
19
|
};
|
|
15
20
|
|
|
16
21
|
type StackPluginConfig = {
|
|
@@ -19,21 +24,21 @@ type StackPluginConfig = {
|
|
|
19
24
|
|
|
20
25
|
const CONFIG_RELATIVE_PATH = path.join(".pi", "ember-stack.json");
|
|
21
26
|
const DEFAULT_PLUGIN_IDS: readonly PluginId[] = [
|
|
22
|
-
"
|
|
23
|
-
"
|
|
27
|
+
"pi-compact-tools",
|
|
28
|
+
"pi-custom-agents",
|
|
24
29
|
"devin-auth",
|
|
25
30
|
];
|
|
26
31
|
|
|
27
32
|
const PLUGINS: readonly StackPlugin[] = [
|
|
28
33
|
{
|
|
29
|
-
id: "
|
|
30
|
-
description: "
|
|
31
|
-
extension:
|
|
34
|
+
id: "pi-compact-tools",
|
|
35
|
+
description: "Collapsed native edit rendering and questionnaire UI",
|
|
36
|
+
extension: piCompactToolsPlugin,
|
|
32
37
|
},
|
|
33
38
|
{
|
|
34
|
-
id: "
|
|
35
|
-
description: "
|
|
36
|
-
extension:
|
|
39
|
+
id: "pi-custom-agents",
|
|
40
|
+
description: "Primary modes, plans, subagents, and bundled agent definitions",
|
|
41
|
+
extension: piCustomAgentsPlugin,
|
|
37
42
|
},
|
|
38
43
|
{
|
|
39
44
|
id: "devin-auth",
|
|
@@ -130,9 +135,12 @@ function registerPluginCommand(
|
|
|
130
135
|
export default async function piEmberStackPlugin(pi: ExtensionAPI): Promise<void> {
|
|
131
136
|
const cwd = process.cwd();
|
|
132
137
|
const enabledPlugins = readEnabledPlugins(cwd);
|
|
138
|
+
const pluginOptions: PiCustomAgentsOptions = {
|
|
139
|
+
compactToolsEnabled: enabledPlugins.has("pi-compact-tools"),
|
|
140
|
+
};
|
|
133
141
|
for (const plugin of PLUGINS) {
|
|
134
142
|
if (!enabledPlugins.has(plugin.id)) continue;
|
|
135
|
-
await plugin.extension(pi);
|
|
143
|
+
await plugin.extension(pi, pluginOptions);
|
|
136
144
|
}
|
|
137
145
|
registerPluginCommand(pi, cwd, enabledPlugins);
|
|
138
146
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { createEditTool } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
5
|
+
|
|
6
|
+
import { registerQuestionnaireTool } from "./questionnaire-tool.ts";
|
|
7
|
+
|
|
8
|
+
const SOURCE_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
function registerCollapsedEditTool(extensionApi: any): void {
|
|
11
|
+
const editDefinition = createEditTool(SOURCE_ROOT);
|
|
12
|
+
extensionApi.registerTool({
|
|
13
|
+
name: "edit",
|
|
14
|
+
label: "edit",
|
|
15
|
+
description: editDefinition.description,
|
|
16
|
+
parameters: editDefinition.parameters,
|
|
17
|
+
renderShell: "self",
|
|
18
|
+
|
|
19
|
+
async execute(
|
|
20
|
+
toolCallId: string,
|
|
21
|
+
params: any,
|
|
22
|
+
signal: AbortSignal,
|
|
23
|
+
onUpdate: any,
|
|
24
|
+
ctx: any,
|
|
25
|
+
) {
|
|
26
|
+
return createEditTool(ctx.cwd).execute(
|
|
27
|
+
toolCallId,
|
|
28
|
+
params,
|
|
29
|
+
signal,
|
|
30
|
+
onUpdate,
|
|
31
|
+
);
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
renderCall(args: any, theme: any): any {
|
|
35
|
+
const filePath = String(args?.path ?? args?.file_path ?? "");
|
|
36
|
+
return new Text(
|
|
37
|
+
theme.fg("toolTitle", theme.bold("edit ")) +
|
|
38
|
+
theme.fg("accent", filePath),
|
|
39
|
+
0,
|
|
40
|
+
0,
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
renderResult(result: any, { isPartial }: any, theme: any): any {
|
|
45
|
+
if (isPartial) return new Text(theme.fg("warning", "Editing..."), 0, 0);
|
|
46
|
+
|
|
47
|
+
const content = result.content?.find((item: any) => item.type === "text");
|
|
48
|
+
if (content?.text?.startsWith("Error")) {
|
|
49
|
+
return new Text(theme.fg("error", content.text.split("\n")[0]), 0, 0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const diff = typeof result.details?.diff === "string" ? result.details.diff : "";
|
|
53
|
+
let additions = 0;
|
|
54
|
+
let removals = 0;
|
|
55
|
+
for (const line of diff.split("\n")) {
|
|
56
|
+
if (line.startsWith("+") && !line.startsWith("+++")) additions++;
|
|
57
|
+
if (line.startsWith("-") && !line.startsWith("---")) removals++;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return new Text(
|
|
61
|
+
theme.fg("success", `+${additions}`) +
|
|
62
|
+
theme.fg("dim", " / ") +
|
|
63
|
+
theme.fg("error", `-${removals}`),
|
|
64
|
+
0,
|
|
65
|
+
0,
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default function piCompactToolsPlugin(pi: any): void {
|
|
72
|
+
registerQuestionnaireTool(pi);
|
|
73
|
+
registerCollapsedEditTool(pi);
|
|
74
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pi
|
|
2
|
+
* Pi Custom Agents — Primary Modes Extension
|
|
3
3
|
*
|
|
4
4
|
* Toggleable primary modes for the Ember project, mirroring opencode's
|
|
5
5
|
* mode: primary agents. Each mode is a slash command that:
|
|
@@ -20,13 +20,12 @@ import * as fs from "node:fs";
|
|
|
20
20
|
import * as path from "node:path";
|
|
21
21
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
|
-
import {
|
|
24
|
-
import { Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
23
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
25
24
|
import {
|
|
26
25
|
askQuestionnaire,
|
|
27
|
-
registerQuestionnaireTool,
|
|
28
26
|
type QuestionnaireQuestion,
|
|
29
|
-
} from "
|
|
27
|
+
} from "../pi-compact-tools/questionnaire-tool.ts";
|
|
28
|
+
import subagentPlugin from "./subagent/extensions/index.ts";
|
|
30
29
|
|
|
31
30
|
function formatTokens(count: number): string {
|
|
32
31
|
if (count < 1000) return count.toString();
|
|
@@ -52,8 +51,8 @@ const FULL_TOOLS = ["read", "bash", "edit", "write", "grep", "find", "ls", "ques
|
|
|
52
51
|
|
|
53
52
|
const SOURCE_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
54
53
|
const SUBAGENT_FILES: Record<string, string> = {
|
|
55
|
-
coder: path.join(SOURCE_ROOT, "
|
|
56
|
-
architect: path.join(SOURCE_ROOT, "
|
|
54
|
+
coder: path.join(SOURCE_ROOT, "subagent", "agents", "coder.md"),
|
|
55
|
+
architect: path.join(SOURCE_ROOT, "subagent", "agents", "architect.md"),
|
|
57
56
|
};
|
|
58
57
|
|
|
59
58
|
interface ModeConfig {
|
|
@@ -559,73 +558,21 @@ function getLastModeFromSession(ctx: any): string | null {
|
|
|
559
558
|
return null;
|
|
560
559
|
}
|
|
561
560
|
|
|
562
|
-
export
|
|
561
|
+
export type PiCustomAgentsOptions = {
|
|
562
|
+
compactToolsEnabled: boolean;
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
export default async function piCustomAgentsPlugin(
|
|
566
|
+
pi: any,
|
|
567
|
+
options: PiCustomAgentsOptions = { compactToolsEnabled: true },
|
|
568
|
+
) {
|
|
563
569
|
let currentMode: string = DEFAULT_MODE;
|
|
564
570
|
let lastMessagedMode: string | null = null;
|
|
565
571
|
let waitingForPlan = false;
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
const editDefinition = createEditTool(SOURCE_ROOT);
|
|
571
|
-
extensionApi.registerTool({
|
|
572
|
-
name: "edit",
|
|
573
|
-
label: "edit",
|
|
574
|
-
description: editDefinition.description,
|
|
575
|
-
parameters: editDefinition.parameters,
|
|
576
|
-
renderShell: "self",
|
|
577
|
-
|
|
578
|
-
async execute(
|
|
579
|
-
toolCallId: string,
|
|
580
|
-
params: any,
|
|
581
|
-
signal: AbortSignal,
|
|
582
|
-
onUpdate: any,
|
|
583
|
-
ctx: any,
|
|
584
|
-
) {
|
|
585
|
-
return createEditTool(ctx.cwd).execute(
|
|
586
|
-
toolCallId,
|
|
587
|
-
params,
|
|
588
|
-
signal,
|
|
589
|
-
onUpdate,
|
|
590
|
-
);
|
|
591
|
-
},
|
|
592
|
-
|
|
593
|
-
renderCall(args: any, theme: any): any {
|
|
594
|
-
const filePath = String(args?.path ?? args?.file_path ?? "");
|
|
595
|
-
return new Text(
|
|
596
|
-
theme.fg("toolTitle", theme.bold("edit ")) +
|
|
597
|
-
theme.fg("accent", filePath),
|
|
598
|
-
0,
|
|
599
|
-
0,
|
|
600
|
-
);
|
|
601
|
-
},
|
|
602
|
-
|
|
603
|
-
renderResult(result: any, { isPartial }: any, theme: any): any {
|
|
604
|
-
if (isPartial) return new Text(theme.fg("warning", "Editing..."), 0, 0);
|
|
605
|
-
|
|
606
|
-
const content = result.content?.find((item: any) => item.type === "text");
|
|
607
|
-
if (content?.text?.startsWith("Error")) {
|
|
608
|
-
return new Text(theme.fg("error", content.text.split("\n")[0]), 0, 0);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
const diff = typeof result.details?.diff === "string" ? result.details.diff : "";
|
|
612
|
-
let additions = 0;
|
|
613
|
-
let removals = 0;
|
|
614
|
-
for (const line of diff.split("\n")) {
|
|
615
|
-
if (line.startsWith("+") && !line.startsWith("+++")) additions++;
|
|
616
|
-
if (line.startsWith("-") && !line.startsWith("---")) removals++;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
return new Text(
|
|
620
|
-
theme.fg("success", `+${additions}`) +
|
|
621
|
-
theme.fg("dim", " / ") +
|
|
622
|
-
theme.fg("error", `-${removals}`),
|
|
623
|
-
0,
|
|
624
|
-
0,
|
|
625
|
-
);
|
|
626
|
-
},
|
|
627
|
-
});
|
|
628
|
-
}
|
|
572
|
+
const compactToolsEnabled = options.compactToolsEnabled;
|
|
573
|
+
const toolsForMode = (tools: string[]): string[] => compactToolsEnabled
|
|
574
|
+
? tools
|
|
575
|
+
: tools.filter((toolName) => toolName !== "questionnaire");
|
|
629
576
|
|
|
630
577
|
for (const modeId of MODE_IDS) {
|
|
631
578
|
const mode = MODES[modeId];
|
|
@@ -655,11 +602,11 @@ export default function piEmberStackExtension(pi: any) {
|
|
|
655
602
|
const mode = MODES[modeId];
|
|
656
603
|
if (!mode) return;
|
|
657
604
|
currentMode = modeId;
|
|
658
|
-
pi.setActiveTools(mode.tools);
|
|
605
|
+
pi.setActiveTools(toolsForMode(mode.tools));
|
|
659
606
|
if (modeId === DEFAULT_MODE) {
|
|
660
607
|
ctx.ui.notify("Coder mode. Full access restored.");
|
|
661
608
|
} else {
|
|
662
|
-
ctx.ui.notify(`${mode.label} mode enabled. Tools: ${mode.tools.join(", ")}`);
|
|
609
|
+
ctx.ui.notify(`${mode.label} mode enabled. Tools: ${toolsForMode(mode.tools).join(", ")}`);
|
|
663
610
|
}
|
|
664
611
|
updateStatus(ctx);
|
|
665
612
|
}
|
|
@@ -956,11 +903,11 @@ export default function piEmberStackExtension(pi: any) {
|
|
|
956
903
|
if (restored && restored !== DEFAULT_MODE) {
|
|
957
904
|
currentMode = restored;
|
|
958
905
|
lastMessagedMode = restored;
|
|
959
|
-
pi.setActiveTools(MODES[restored].tools);
|
|
906
|
+
pi.setActiveTools(toolsForMode(MODES[restored].tools));
|
|
960
907
|
} else {
|
|
961
908
|
currentMode = DEFAULT_MODE;
|
|
962
909
|
lastMessagedMode = null;
|
|
963
|
-
pi.setActiveTools(FULL_TOOLS);
|
|
910
|
+
pi.setActiveTools(toolsForMode(FULL_TOOLS));
|
|
964
911
|
}
|
|
965
912
|
installCustomFooter(ctx);
|
|
966
913
|
updateStatus(ctx);
|
|
@@ -971,13 +918,15 @@ export default function piEmberStackExtension(pi: any) {
|
|
|
971
918
|
if (restored && restored !== DEFAULT_MODE) {
|
|
972
919
|
currentMode = restored;
|
|
973
920
|
lastMessagedMode = restored;
|
|
974
|
-
pi.setActiveTools(MODES[restored].tools);
|
|
921
|
+
pi.setActiveTools(toolsForMode(MODES[restored].tools));
|
|
975
922
|
} else {
|
|
976
923
|
currentMode = DEFAULT_MODE;
|
|
977
924
|
lastMessagedMode = null;
|
|
978
|
-
pi.setActiveTools(FULL_TOOLS);
|
|
925
|
+
pi.setActiveTools(toolsForMode(FULL_TOOLS));
|
|
979
926
|
}
|
|
980
927
|
updateStatus(ctx);
|
|
981
928
|
installCustomFooter(ctx);
|
|
982
929
|
});
|
|
930
|
+
|
|
931
|
+
await subagentPlugin(pi);
|
|
983
932
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|