@mediadatafusion/pi-workflow-suite 0.0.1
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/CHANGELOG.md +13 -0
- package/CONTRIBUTING.md +9 -0
- package/LICENSE.md +201 -0
- package/NOTICE +6 -0
- package/README.md +1208 -0
- package/SECURITY.md +7 -0
- package/SUPPORT.md +9 -0
- package/TRADEMARKS.md +14 -0
- package/VERSION +1 -0
- package/agents/codebase-research.md +42 -0
- package/agents/general-worker.md +26 -0
- package/agents/implementation-planning.md +46 -0
- package/agents/quality-validation.md +43 -0
- package/agents/workflow-orchestrator.md +44 -0
- package/config/prompts/execute-approved-plan.md +43 -0
- package/config/prompts/mission-checkpoint.md +26 -0
- package/config/prompts/mission-final-validation.md +21 -0
- package/config/prompts/mission-plan.md +129 -0
- package/config/prompts/mission-repair.md +33 -0
- package/config/prompts/mission-run.md +37 -0
- package/config/prompts/validate-approved-plan.md +42 -0
- package/config/prompts/workflow-plan-prompt.md +93 -0
- package/config/prompts/workflow-repair.md +20 -0
- package/config/prompts/workflow-summary.md +23 -0
- package/config/workflow-settings.example.json +335 -0
- package/docs/assets/mediadatafusion-logo.png +0 -0
- package/docs/assets/pi-workflow-suite-card.png +0 -0
- package/docs/assets/pi-workflow-suite-header.png +0 -0
- package/docs/assets/pi-workflow-suite-video-thumb.png +0 -0
- package/docs/assets/readme-link-commands.svg +10 -0
- package/docs/assets/readme-link-install.svg +10 -0
- package/docs/assets/readme-link-quick-start.svg +10 -0
- package/docs/assets/readme-link-settings.svg +10 -0
- package/extensions/subagent/agents.ts +149 -0
- package/extensions/subagent/index.ts +1136 -0
- package/extensions/subagent/runner.ts +291 -0
- package/extensions/workflow-model-router.ts +1485 -0
- package/extensions/workflow-modes.ts +14778 -0
- package/extensions/workflow-parsers.ts +212 -0
- package/extensions/workflow-settings-capabilities.ts +282 -0
- package/extensions/workflow-state.ts +978 -0
- package/extensions/workflow-subagent-policy.ts +180 -0
- package/extensions/workflow-summary.ts +381 -0
- package/extensions/workflow-tool-guard.ts +302 -0
- package/extensions/workflow-validation-classifier.ts +102 -0
- package/extensions/workflow-web-tools.ts +356 -0
- package/package.json +1 -0
- package/scripts/audit-live.sh +69 -0
- package/scripts/audit-settings.sh +136 -0
- package/scripts/backup-live.sh +63 -0
- package/scripts/bootstrap-project.sh +220 -0
- package/scripts/install-to-live.sh +87 -0
- package/scripts/quarantine-live-junk.sh +69 -0
- package/scripts/verify-live.sh +128 -0
- package/skills/codebase-discovery/SKILL.md +20 -0
- package/skills/find-skills/SKILL.md +155 -0
- package/skills/git-safe-summary/SKILL.md +20 -0
- package/skills/implementation-planning/SKILL.md +20 -0
- package/skills/project-rules-audit/SKILL.md +20 -0
- package/skills/safe-execution/SKILL.md +20 -0
- package/skills/validation-review/SKILL.md +20 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent discovery and configuration.
|
|
3
|
+
*
|
|
4
|
+
* Vendored from @earendil-works/pi-coding-agent examples/extensions/subagent
|
|
5
|
+
* and adapted for Pi Workflow Suite package-local agents.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import { subagentSuitableForForcedPhase, subagentToolProfileLabel, subagentToolsAllowMutation, type SubagentPhase } from "../workflow-subagent-policy.js";
|
|
13
|
+
|
|
14
|
+
export type AgentScope = "user" | "project" | "both";
|
|
15
|
+
export type AgentSource = "package" | "user" | "project";
|
|
16
|
+
|
|
17
|
+
const PACKAGE_AGENTS_DIR = path.join(path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url)))), "agents");
|
|
18
|
+
|
|
19
|
+
export interface AgentConfig {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
tools?: string[];
|
|
23
|
+
model?: string;
|
|
24
|
+
systemPrompt: string;
|
|
25
|
+
source: AgentSource;
|
|
26
|
+
filePath: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AgentDiscoveryResult {
|
|
30
|
+
agents: AgentConfig[];
|
|
31
|
+
projectAgentsDir: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
|
|
35
|
+
const agents: AgentConfig[] = [];
|
|
36
|
+
|
|
37
|
+
if (!fs.existsSync(dir)) {
|
|
38
|
+
return agents;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let entries: fs.Dirent[];
|
|
42
|
+
try {
|
|
43
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
44
|
+
} catch {
|
|
45
|
+
return agents;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
if (!entry.name.endsWith(".md")) continue;
|
|
50
|
+
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
51
|
+
|
|
52
|
+
const filePath = path.join(dir, entry.name);
|
|
53
|
+
let content: string;
|
|
54
|
+
try {
|
|
55
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
56
|
+
} catch {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
|
|
61
|
+
|
|
62
|
+
if (!frontmatter.name || !frontmatter.description) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const tools = frontmatter.tools
|
|
67
|
+
?.split(",")
|
|
68
|
+
.map((t: string) => t.trim())
|
|
69
|
+
.filter(Boolean);
|
|
70
|
+
|
|
71
|
+
agents.push({
|
|
72
|
+
name: frontmatter.name,
|
|
73
|
+
description: frontmatter.description,
|
|
74
|
+
tools: tools && tools.length > 0 ? tools : undefined,
|
|
75
|
+
model: frontmatter.model,
|
|
76
|
+
systemPrompt: body,
|
|
77
|
+
source,
|
|
78
|
+
filePath,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return agents;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isDirectory(p: string): boolean {
|
|
86
|
+
try {
|
|
87
|
+
return fs.statSync(p).isDirectory();
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function findNearestProjectAgentsDir(cwd: string): string | null {
|
|
94
|
+
let currentDir = cwd;
|
|
95
|
+
while (true) {
|
|
96
|
+
const candidate = path.join(currentDir, ".pi", "agents");
|
|
97
|
+
if (isDirectory(candidate)) return candidate;
|
|
98
|
+
|
|
99
|
+
const parentDir = path.dirname(currentDir);
|
|
100
|
+
if (parentDir === currentDir) return null;
|
|
101
|
+
currentDir = parentDir;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
|
|
106
|
+
const userDir = path.join(getAgentDir(), "agents");
|
|
107
|
+
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
108
|
+
|
|
109
|
+
const packageAgents = scope === "project" ? [] : loadAgentsFromDir(PACKAGE_AGENTS_DIR, "package");
|
|
110
|
+
const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
|
|
111
|
+
const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
|
|
112
|
+
|
|
113
|
+
const agentMap = new Map<string, AgentConfig>();
|
|
114
|
+
|
|
115
|
+
if (scope === "both") {
|
|
116
|
+
for (const agent of packageAgents) agentMap.set(agent.name, agent);
|
|
117
|
+
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
118
|
+
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
119
|
+
} else if (scope === "user") {
|
|
120
|
+
for (const agent of packageAgents) agentMap.set(agent.name, agent);
|
|
121
|
+
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
122
|
+
} else {
|
|
123
|
+
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { agents: Array.from(agentMap.values()), projectAgentsDir };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function agentAllowsMutation(agent: AgentConfig): boolean {
|
|
130
|
+
return subagentToolsAllowMutation(agent.tools);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function agentSuitableForForcedPhase(agent: AgentConfig, phase: SubagentPhase, label: string): boolean {
|
|
134
|
+
return subagentSuitableForForcedPhase({ name: agent.name, source: agent.source, tools: agent.tools }, phase, label);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function formatAgentToolProfile(agent: AgentConfig): string {
|
|
138
|
+
return subagentToolProfileLabel({ name: agent.name, source: agent.source, tools: agent.tools });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function formatAgentList(agents: AgentConfig[], maxItems: number): { text: string; remaining: number } {
|
|
142
|
+
if (agents.length === 0) return { text: "none", remaining: 0 };
|
|
143
|
+
const listed = agents.slice(0, maxItems);
|
|
144
|
+
const remaining = agents.length - listed.length;
|
|
145
|
+
return {
|
|
146
|
+
text: listed.map((a) => `${formatAgentToolProfile(a)}: ${a.description}`).join("; "),
|
|
147
|
+
remaining,
|
|
148
|
+
};
|
|
149
|
+
}
|