@actant/pi 0.2.0
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/acp-bridge.js +127 -0
- package/dist/acp-bridge.js.map +1 -0
- package/dist/chunk-SNNF3S5S.js +125 -0
- package/dist/chunk-SNNF3S5S.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +239 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createPiAgent
|
|
4
|
+
} from "./chunk-SNNF3S5S.js";
|
|
5
|
+
|
|
6
|
+
// src/acp-bridge.ts
|
|
7
|
+
import { Writable, Readable } from "stream";
|
|
8
|
+
import {
|
|
9
|
+
AgentSideConnection,
|
|
10
|
+
ndJsonStream
|
|
11
|
+
} from "@agentclientprotocol/sdk";
|
|
12
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
13
|
+
var sessionCounter = 0;
|
|
14
|
+
function buildAgentHandler(conn) {
|
|
15
|
+
return {
|
|
16
|
+
initialize: async (_params) => {
|
|
17
|
+
return {
|
|
18
|
+
protocolVersion: 1,
|
|
19
|
+
agentCapabilities: {},
|
|
20
|
+
agentInfo: {
|
|
21
|
+
name: "pi-acp-bridge",
|
|
22
|
+
version: "0.1.0"
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
newSession: async (params) => {
|
|
27
|
+
const sessionId = `pi-session-${++sessionCounter}`;
|
|
28
|
+
const cwd = params.cwd ?? process.cwd();
|
|
29
|
+
const agentOpts = {
|
|
30
|
+
workspaceDir: cwd,
|
|
31
|
+
provider: process.env["ACTANT_PROVIDER"] ?? "anthropic",
|
|
32
|
+
model: process.env["ACTANT_MODEL"] ?? "claude-sonnet-4-20250514",
|
|
33
|
+
apiKey: process.env["ANTHROPIC_API_KEY"] ?? process.env["OPENAI_API_KEY"],
|
|
34
|
+
thinkingLevel: process.env["ACTANT_THINKING_LEVEL"] ?? void 0,
|
|
35
|
+
systemPrompt: "You are a helpful coding assistant. You have access to file and command tools."
|
|
36
|
+
};
|
|
37
|
+
const agent = createPiAgent(agentOpts);
|
|
38
|
+
sessions.set(sessionId, {
|
|
39
|
+
agent,
|
|
40
|
+
cwd,
|
|
41
|
+
abortController: new AbortController()
|
|
42
|
+
});
|
|
43
|
+
return { sessionId };
|
|
44
|
+
},
|
|
45
|
+
prompt: async (params) => {
|
|
46
|
+
const session = sessions.get(params.sessionId);
|
|
47
|
+
if (!session) {
|
|
48
|
+
throw new Error(`Session "${params.sessionId}" not found`);
|
|
49
|
+
}
|
|
50
|
+
const promptText = params.prompt?.filter((b) => b.type === "text").map((b) => "text" in b ? b.text : "").join("") ?? "";
|
|
51
|
+
if (!promptText) {
|
|
52
|
+
return { stopReason: "end_turn" };
|
|
53
|
+
}
|
|
54
|
+
session.abortController = new AbortController();
|
|
55
|
+
const { agent } = session;
|
|
56
|
+
const unsub = agent.subscribe((event) => {
|
|
57
|
+
if (event.type === "message_update" && event.assistantMessageEvent?.type === "text_delta") {
|
|
58
|
+
conn.sessionUpdate({
|
|
59
|
+
sessionId: params.sessionId,
|
|
60
|
+
update: {
|
|
61
|
+
sessionUpdate: "agent_message_chunk",
|
|
62
|
+
content: { type: "text", text: event.assistantMessageEvent.delta ?? "" }
|
|
63
|
+
}
|
|
64
|
+
}).catch(() => {
|
|
65
|
+
});
|
|
66
|
+
} else if (event.type === "tool_execution_start") {
|
|
67
|
+
conn.sessionUpdate({
|
|
68
|
+
sessionId: params.sessionId,
|
|
69
|
+
update: {
|
|
70
|
+
sessionUpdate: "tool_call",
|
|
71
|
+
content: { type: "text", text: `[Tool: ${event.toolName ?? "unknown"}]` }
|
|
72
|
+
}
|
|
73
|
+
}).catch(() => {
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
await agent.prompt(promptText);
|
|
79
|
+
return { stopReason: "end_turn" };
|
|
80
|
+
} catch (err) {
|
|
81
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
82
|
+
conn.sessionUpdate({
|
|
83
|
+
sessionId: params.sessionId,
|
|
84
|
+
update: {
|
|
85
|
+
sessionUpdate: "agent_message_chunk",
|
|
86
|
+
content: { type: "text", text: `[Error] ${message}` }
|
|
87
|
+
}
|
|
88
|
+
}).catch(() => {
|
|
89
|
+
});
|
|
90
|
+
return { stopReason: "end_turn" };
|
|
91
|
+
} finally {
|
|
92
|
+
unsub();
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
cancel: async (params) => {
|
|
96
|
+
const session = sessions.get(params.sessionId);
|
|
97
|
+
if (session) {
|
|
98
|
+
session.agent.abort();
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
loadSession: async () => ({}),
|
|
102
|
+
authenticate: async () => ({}),
|
|
103
|
+
setSessionMode: async () => {
|
|
104
|
+
},
|
|
105
|
+
setSessionConfigOption: async () => ({})
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
var webWritable = Writable.toWeb(process.stdout);
|
|
109
|
+
var webReadable = Readable.toWeb(process.stdin);
|
|
110
|
+
var stream = ndJsonStream(webWritable, webReadable);
|
|
111
|
+
new AgentSideConnection(
|
|
112
|
+
(conn) => buildAgentHandler(conn),
|
|
113
|
+
stream
|
|
114
|
+
);
|
|
115
|
+
process.on("SIGTERM", () => {
|
|
116
|
+
for (const session of sessions.values()) {
|
|
117
|
+
session.agent.abort();
|
|
118
|
+
}
|
|
119
|
+
process.exit(0);
|
|
120
|
+
});
|
|
121
|
+
process.on("SIGINT", () => {
|
|
122
|
+
for (const session of sessions.values()) {
|
|
123
|
+
session.agent.abort();
|
|
124
|
+
}
|
|
125
|
+
process.exit(0);
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=acp-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/acp-bridge.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Writable, Readable } from \"node:stream\";\nimport {\n AgentSideConnection,\n ndJsonStream,\n type Agent as AcpAgent,\n type InitializeResponse,\n type NewSessionResponse,\n type PromptResponse,\n} from \"@agentclientprotocol/sdk\";\nimport { Agent as PiAgent } from \"@mariozechner/pi-agent-core\";\n// @mariozechner/pi-ai imports removed — SDK API drift (#121)\nimport { createPiAgent, type PiAgentOptions } from \"./pi-tool-bridge\";\n\ninterface SessionState {\n agent: PiAgent;\n cwd: string;\n abortController: AbortController;\n}\n\nconst sessions = new Map<string, SessionState>();\nlet sessionCounter = 0;\n\nfunction buildAgentHandler(conn: AgentSideConnection): AcpAgent {\n return {\n initialize: async (_params): Promise<InitializeResponse> => {\n return {\n protocolVersion: 1,\n agentCapabilities: {},\n agentInfo: {\n name: \"pi-acp-bridge\",\n version: \"0.1.0\",\n },\n } as InitializeResponse;\n },\n\n newSession: async (params): Promise<NewSessionResponse> => {\n const sessionId = `pi-session-${++sessionCounter}`;\n const cwd = params.cwd ?? process.cwd();\n\n const agentOpts: PiAgentOptions = {\n workspaceDir: cwd,\n provider: process.env[\"ACTANT_PROVIDER\"] ?? \"anthropic\",\n model: process.env[\"ACTANT_MODEL\"] ?? \"claude-sonnet-4-20250514\",\n apiKey: process.env[\"ANTHROPIC_API_KEY\"] ?? process.env[\"OPENAI_API_KEY\"],\n thinkingLevel: (process.env[\"ACTANT_THINKING_LEVEL\"] as PiAgentOptions[\"thinkingLevel\"]) ?? undefined,\n systemPrompt: \"You are a helpful coding assistant. You have access to file and command tools.\",\n };\n\n const agent = createPiAgent(agentOpts);\n sessions.set(sessionId, {\n agent,\n cwd,\n abortController: new AbortController(),\n });\n\n return { sessionId } as NewSessionResponse;\n },\n\n prompt: async (params): Promise<PromptResponse> => {\n const session = sessions.get(params.sessionId);\n if (!session) {\n throw new Error(`Session \"${params.sessionId}\" not found`);\n }\n\n const promptText = params.prompt\n ?.filter((b) => b.type === \"text\")\n .map((b) => (\"text\" in b ? (b as { text: string }).text : \"\"))\n .join(\"\") ?? \"\";\n\n if (!promptText) {\n return { stopReason: \"end_turn\" } as PromptResponse;\n }\n\n session.abortController = new AbortController();\n const { agent } = session;\n\n const unsub = agent.subscribe((event: {\n type: string;\n assistantMessageEvent?: { type?: string; delta?: string };\n toolName?: string;\n message?: { role?: string; content?: unknown };\n }) => {\n if (event.type === \"message_update\" && event.assistantMessageEvent?.type === \"text_delta\") {\n conn.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: event.assistantMessageEvent.delta ?? \"\" },\n },\n } as never).catch(() => {});\n } else if (event.type === \"tool_execution_start\") {\n conn.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: \"tool_call\",\n content: { type: \"text\", text: `[Tool: ${event.toolName ?? \"unknown\"}]` },\n },\n } as never).catch(() => {});\n }\n });\n\n try {\n await agent.prompt(promptText);\n return { stopReason: \"end_turn\" } as PromptResponse;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n conn.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: `[Error] ${message}` },\n },\n } as never).catch(() => {});\n return { stopReason: \"end_turn\" } as PromptResponse;\n } finally {\n unsub();\n }\n },\n\n cancel: async (params) => {\n const session = sessions.get(params.sessionId);\n if (session) {\n session.agent.abort();\n }\n },\n\n loadSession: async () => ({} as never),\n authenticate: async () => ({}),\n setSessionMode: async () => {},\n setSessionConfigOption: async () => ({} as never),\n };\n}\n\nconst webWritable = Writable.toWeb(process.stdout) as WritableStream<Uint8Array>;\nconst webReadable = Readable.toWeb(process.stdin) as ReadableStream<Uint8Array>;\nconst stream = ndJsonStream(webWritable, webReadable);\n\nnew AgentSideConnection(\n (conn: AgentSideConnection): AcpAgent => buildAgentHandler(conn),\n stream,\n);\n\nprocess.on(\"SIGTERM\", () => {\n for (const session of sessions.values()) {\n session.agent.abort();\n }\n process.exit(0);\n});\n\nprocess.on(\"SIGINT\", () => {\n for (const session of sessions.values()) {\n session.agent.abort();\n }\n process.exit(0);\n});\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/pi-tool-bridge.ts
|
|
2
|
+
import { execFile } from "child_process";
|
|
3
|
+
import { readFile, writeFile, readdir } from "fs/promises";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
import { Agent } from "@mariozechner/pi-agent-core";
|
|
7
|
+
import { getModel, Type } from "@mariozechner/pi-ai";
|
|
8
|
+
var execFileAsync = promisify(execFile);
|
|
9
|
+
var ALL_TOOLS = ["read_file", "write_file", "list_directory", "run_command"];
|
|
10
|
+
function resolvePath(workspaceDir, path) {
|
|
11
|
+
const abs = resolve(workspaceDir, path);
|
|
12
|
+
const base = resolve(workspaceDir);
|
|
13
|
+
if (!abs.startsWith(base)) {
|
|
14
|
+
throw new Error(`Path "${path}" resolves outside workspace`);
|
|
15
|
+
}
|
|
16
|
+
return abs;
|
|
17
|
+
}
|
|
18
|
+
function buildTools(workspaceDir, toolNames) {
|
|
19
|
+
const enabled = toolNames && toolNames.length > 0 ? toolNames : [...ALL_TOOLS];
|
|
20
|
+
const tools = [];
|
|
21
|
+
if (enabled.includes("read_file")) {
|
|
22
|
+
tools.push({
|
|
23
|
+
name: "read_file",
|
|
24
|
+
label: "Read File",
|
|
25
|
+
description: "Read the contents of a file. Path is relative to workspace.",
|
|
26
|
+
parameters: Type.Object({
|
|
27
|
+
path: Type.String({ description: "File path relative to workspace" })
|
|
28
|
+
}),
|
|
29
|
+
execute: (async (_toolCallId, params) => {
|
|
30
|
+
const { path } = params;
|
|
31
|
+
const absPath = resolvePath(workspaceDir, path);
|
|
32
|
+
const content = await readFile(absPath, "utf-8");
|
|
33
|
+
return { content: [{ type: "text", text: content }], details: void 0 };
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (enabled.includes("write_file")) {
|
|
38
|
+
tools.push({
|
|
39
|
+
name: "write_file",
|
|
40
|
+
label: "Write File",
|
|
41
|
+
description: "Write content to a file. Path is relative to workspace.",
|
|
42
|
+
parameters: Type.Object({
|
|
43
|
+
path: Type.String({ description: "File path relative to workspace" }),
|
|
44
|
+
content: Type.String({ description: "Content to write" })
|
|
45
|
+
}),
|
|
46
|
+
execute: (async (_toolCallId, params) => {
|
|
47
|
+
const { path, content } = params;
|
|
48
|
+
const absPath = resolvePath(workspaceDir, path);
|
|
49
|
+
await writeFile(absPath, content, "utf-8");
|
|
50
|
+
return { content: [{ type: "text", text: `Wrote ${path}` }], details: void 0 };
|
|
51
|
+
})
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (enabled.includes("list_directory")) {
|
|
55
|
+
tools.push({
|
|
56
|
+
name: "list_directory",
|
|
57
|
+
label: "List Directory",
|
|
58
|
+
description: "List files and directories. Path is relative to workspace.",
|
|
59
|
+
parameters: Type.Object({
|
|
60
|
+
path: Type.String({ description: "Directory path relative to workspace" })
|
|
61
|
+
}),
|
|
62
|
+
execute: (async (_toolCallId, params) => {
|
|
63
|
+
const { path } = params;
|
|
64
|
+
const absPath = resolvePath(workspaceDir, path);
|
|
65
|
+
const entries = await readdir(absPath, { withFileTypes: true });
|
|
66
|
+
const lines = entries.map((e) => e.isDirectory() ? `${e.name}/` : e.name);
|
|
67
|
+
return { content: [{ type: "text", text: lines.join("\n") }], details: void 0 };
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (enabled.includes("run_command")) {
|
|
72
|
+
tools.push({
|
|
73
|
+
name: "run_command",
|
|
74
|
+
label: "Run Command",
|
|
75
|
+
description: "Execute a shell command. command is the executable, args are the arguments.",
|
|
76
|
+
parameters: Type.Object({
|
|
77
|
+
command: Type.String({ description: "Executable to run" }),
|
|
78
|
+
args: Type.Optional(Type.Array(Type.String(), { description: "Command arguments" }))
|
|
79
|
+
}),
|
|
80
|
+
execute: (async (_toolCallId, params, signal) => {
|
|
81
|
+
const { command, args: argList } = params;
|
|
82
|
+
const args = argList ?? [];
|
|
83
|
+
const { stdout, stderr } = await execFileAsync(
|
|
84
|
+
command,
|
|
85
|
+
args,
|
|
86
|
+
{ cwd: workspaceDir, signal, encoding: "utf-8" }
|
|
87
|
+
);
|
|
88
|
+
const out = [stdout, stderr].filter(Boolean).join("\n").trim() || "(no output)";
|
|
89
|
+
return { content: [{ type: "text", text: out }], details: void 0 };
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return tools;
|
|
94
|
+
}
|
|
95
|
+
function createPiAgent(options) {
|
|
96
|
+
const {
|
|
97
|
+
workspaceDir,
|
|
98
|
+
provider = "anthropic",
|
|
99
|
+
model = "claude-sonnet-4-20250514",
|
|
100
|
+
apiKey,
|
|
101
|
+
thinkingLevel,
|
|
102
|
+
tools: toolNames,
|
|
103
|
+
systemPrompt = "You are a helpful coding assistant. You have access to file and command tools."
|
|
104
|
+
} = options;
|
|
105
|
+
const modelInstance = getModel(provider, model);
|
|
106
|
+
const agentOptions = {
|
|
107
|
+
initialState: {
|
|
108
|
+
systemPrompt,
|
|
109
|
+
model: modelInstance,
|
|
110
|
+
tools: buildTools(workspaceDir, toolNames)
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
if (thinkingLevel) {
|
|
114
|
+
agentOptions.initialState.thinkingLevel = thinkingLevel;
|
|
115
|
+
}
|
|
116
|
+
if (apiKey) {
|
|
117
|
+
agentOptions.getApiKey = async () => apiKey;
|
|
118
|
+
}
|
|
119
|
+
return new Agent(agentOptions);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
createPiAgent
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=chunk-SNNF3S5S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pi-tool-bridge.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { readFile, writeFile, readdir } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { Agent, type AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { getModel, Type } from \"@mariozechner/pi-ai\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface PiAgentOptions {\n workspaceDir: string;\n provider?: string;\n model?: string;\n apiKey?: string;\n thinkingLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n tools?: string[];\n systemPrompt?: string;\n}\n\nconst ALL_TOOLS = [\"read_file\", \"write_file\", \"list_directory\", \"run_command\"] as const;\n\nfunction resolvePath(workspaceDir: string, path: string): string {\n const abs = resolve(workspaceDir, path);\n const base = resolve(workspaceDir);\n if (!abs.startsWith(base)) {\n throw new Error(`Path \"${path}\" resolves outside workspace`);\n }\n return abs;\n}\n\nfunction buildTools(workspaceDir: string, toolNames?: string[]): AgentTool[] {\n const enabled = toolNames && toolNames.length > 0 ? toolNames : [...ALL_TOOLS];\n const tools: AgentTool[] = [];\n\n if (enabled.includes(\"read_file\")) {\n tools.push({\n name: \"read_file\",\n label: \"Read File\",\n description: \"Read the contents of a file. Path is relative to workspace.\",\n parameters: Type.Object({\n path: Type.String({ description: \"File path relative to workspace\" }),\n }),\n execute: (async (_toolCallId, params) => {\n const { path } = params as { path: string };\n const absPath = resolvePath(workspaceDir, path);\n const content = await readFile(absPath, \"utf-8\");\n return { content: [{ type: \"text\" as const, text: content }], details: undefined };\n }) as AgentTool[\"execute\"],\n });\n }\n\n if (enabled.includes(\"write_file\")) {\n tools.push({\n name: \"write_file\",\n label: \"Write File\",\n description: \"Write content to a file. Path is relative to workspace.\",\n parameters: Type.Object({\n path: Type.String({ description: \"File path relative to workspace\" }),\n content: Type.String({ description: \"Content to write\" }),\n }),\n execute: (async (_toolCallId, params) => {\n const { path, content } = params as { path: string; content: string };\n const absPath = resolvePath(workspaceDir, path);\n await writeFile(absPath, content, \"utf-8\");\n return { content: [{ type: \"text\" as const, text: `Wrote ${path}` }], details: undefined };\n }) as AgentTool[\"execute\"],\n });\n }\n\n if (enabled.includes(\"list_directory\")) {\n tools.push({\n name: \"list_directory\",\n label: \"List Directory\",\n description: \"List files and directories. Path is relative to workspace.\",\n parameters: Type.Object({\n path: Type.String({ description: \"Directory path relative to workspace\" }),\n }),\n execute: (async (_toolCallId, params) => {\n const { path } = params as { path: string };\n const absPath = resolvePath(workspaceDir, path);\n const entries = await readdir(absPath, { withFileTypes: true });\n const lines = entries.map((e) => (e.isDirectory() ? `${e.name}/` : e.name));\n return { content: [{ type: \"text\" as const, text: lines.join(\"\\n\") }], details: undefined };\n }) as AgentTool[\"execute\"],\n });\n }\n\n if (enabled.includes(\"run_command\")) {\n tools.push({\n name: \"run_command\",\n label: \"Run Command\",\n description: \"Execute a shell command. command is the executable, args are the arguments.\",\n parameters: Type.Object({\n command: Type.String({ description: \"Executable to run\" }),\n args: Type.Optional(Type.Array(Type.String(), { description: \"Command arguments\" })),\n }),\n execute: (async (_toolCallId, params, signal) => {\n const { command, args: argList } = params as { command: string; args?: string[] };\n const args = argList ?? [];\n const { stdout, stderr } = await execFileAsync(\n command,\n args,\n { cwd: workspaceDir, signal, encoding: \"utf-8\" },\n );\n const out = [stdout, stderr].filter(Boolean).join(\"\\n\").trim() || \"(no output)\";\n return { content: [{ type: \"text\" as const, text: out }], details: undefined };\n }) as AgentTool[\"execute\"],\n });\n }\n\n return tools;\n}\n\nexport function createPiAgent(options: PiAgentOptions): Agent {\n const {\n workspaceDir,\n provider = \"anthropic\",\n model = \"claude-sonnet-4-20250514\",\n apiKey,\n thinkingLevel,\n tools: toolNames,\n systemPrompt = \"You are a helpful coding assistant. You have access to file and command tools.\",\n } = options;\n\n const modelInstance = getModel(provider as never, model);\n\n const agentOptions: Record<string, unknown> = {\n initialState: {\n systemPrompt,\n model: modelInstance,\n tools: buildTools(workspaceDir, toolNames),\n },\n };\n\n if (thinkingLevel) {\n (agentOptions.initialState as Record<string, unknown>).thinkingLevel = thinkingLevel;\n }\n\n if (apiKey) {\n agentOptions.getApiKey = async () => apiKey;\n }\n\n return new Agent(agentOptions as ConstructorParameters<typeof Agent>[0]);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SkillDefinition, PromptDefinition, McpServerDefinition, PluginDefinition, WorkflowDefinition, PermissionsInput } from '@actant/shared';
|
|
2
|
+
import { BackendBuilder, VerifyResult, AgentCommunicator, RunPromptOptions, PromptResult, StreamChunk } from '@actant/core';
|
|
3
|
+
import { Agent } from '@mariozechner/pi-agent-core';
|
|
4
|
+
|
|
5
|
+
declare class PiBuilder implements BackendBuilder {
|
|
6
|
+
readonly backendType: "pi";
|
|
7
|
+
scaffold(workspaceDir: string): Promise<void>;
|
|
8
|
+
materializeSkills(workspaceDir: string, skills: SkillDefinition[]): Promise<void>;
|
|
9
|
+
materializePrompts(workspaceDir: string, prompts: PromptDefinition[]): Promise<void>;
|
|
10
|
+
materializeMcpConfig(_workspaceDir: string, servers: McpServerDefinition[]): Promise<void>;
|
|
11
|
+
materializePlugins(_workspaceDir: string, _plugins: PluginDefinition[]): Promise<void>;
|
|
12
|
+
materializeWorkflow(workspaceDir: string, workflow: WorkflowDefinition): Promise<void>;
|
|
13
|
+
injectPermissions(workspaceDir: string, _servers: McpServerDefinition[], permissions?: PermissionsInput): Promise<void>;
|
|
14
|
+
verify(workspaceDir: string): Promise<VerifyResult>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface PiCommunicatorConfig {
|
|
18
|
+
provider?: string;
|
|
19
|
+
model?: string;
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
22
|
+
tools?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Extract PiCommunicatorConfig from a template's backend.config record.
|
|
26
|
+
* Falls back to ACTANT_* environment variables, then to pi-ai built-in env resolution.
|
|
27
|
+
*/
|
|
28
|
+
declare function configFromBackend(backendConfig?: Record<string, unknown>): PiCommunicatorConfig;
|
|
29
|
+
declare class PiCommunicator implements AgentCommunicator {
|
|
30
|
+
private readonly config;
|
|
31
|
+
constructor(config?: PiCommunicatorConfig);
|
|
32
|
+
runPrompt(workspaceDir: string, prompt: string, options?: RunPromptOptions): Promise<PromptResult>;
|
|
33
|
+
streamPrompt(workspaceDir: string, prompt: string, options?: RunPromptOptions): AsyncIterable<StreamChunk>;
|
|
34
|
+
private buildAgent;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface PiAgentOptions {
|
|
38
|
+
workspaceDir: string;
|
|
39
|
+
provider?: string;
|
|
40
|
+
model?: string;
|
|
41
|
+
apiKey?: string;
|
|
42
|
+
thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
43
|
+
tools?: string[];
|
|
44
|
+
systemPrompt?: string;
|
|
45
|
+
}
|
|
46
|
+
declare function createPiAgent(options: PiAgentOptions): Agent;
|
|
47
|
+
|
|
48
|
+
declare const ACP_BRIDGE_PATH: string;
|
|
49
|
+
|
|
50
|
+
export { ACP_BRIDGE_PATH, type PiAgentOptions, PiBuilder, PiCommunicator, type PiCommunicatorConfig, configFromBackend, createPiAgent };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPiAgent
|
|
3
|
+
} from "./chunk-SNNF3S5S.js";
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { dirname, join as join3 } from "path";
|
|
8
|
+
|
|
9
|
+
// src/pi-builder.ts
|
|
10
|
+
import { writeFile, mkdir, stat } from "fs/promises";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { createLogger } from "@actant/shared";
|
|
13
|
+
import { resolvePermissions } from "@actant/core";
|
|
14
|
+
var logger = createLogger("pi-builder");
|
|
15
|
+
var PiBuilder = class {
|
|
16
|
+
backendType = "pi";
|
|
17
|
+
async scaffold(workspaceDir) {
|
|
18
|
+
await mkdir(join(workspaceDir, ".pi", "skills"), { recursive: true });
|
|
19
|
+
await mkdir(join(workspaceDir, ".pi", "prompts"), { recursive: true });
|
|
20
|
+
await writeFile(join(workspaceDir, "AGENTS.md"), "# Agent Skills\n", "utf-8");
|
|
21
|
+
}
|
|
22
|
+
async materializeSkills(workspaceDir, skills) {
|
|
23
|
+
const skillsDir = join(workspaceDir, ".pi", "skills");
|
|
24
|
+
await mkdir(skillsDir, { recursive: true });
|
|
25
|
+
const sections = skills.map((s) => {
|
|
26
|
+
const header = `## ${s.name}`;
|
|
27
|
+
const desc = s.description ? `
|
|
28
|
+
> ${s.description}
|
|
29
|
+
` : "";
|
|
30
|
+
return `${header}${desc}
|
|
31
|
+
${s.content}`;
|
|
32
|
+
});
|
|
33
|
+
const agentsContent = `# Agent Skills
|
|
34
|
+
|
|
35
|
+
${sections.join("\n\n---\n\n")}
|
|
36
|
+
`;
|
|
37
|
+
await writeFile(join(workspaceDir, "AGENTS.md"), agentsContent, "utf-8");
|
|
38
|
+
for (const skill of skills) {
|
|
39
|
+
const fileName = `${skill.name.replace(/[/\\]/g, "-")}.md`;
|
|
40
|
+
const content = [
|
|
41
|
+
skill.description ? `> ${skill.description}
|
|
42
|
+
` : "",
|
|
43
|
+
skill.content,
|
|
44
|
+
""
|
|
45
|
+
].filter(Boolean).join("\n");
|
|
46
|
+
await writeFile(join(skillsDir, fileName), content, "utf-8");
|
|
47
|
+
}
|
|
48
|
+
logger.debug({ workspaceDir, count: skills.length }, "Skills materialized");
|
|
49
|
+
}
|
|
50
|
+
async materializePrompts(workspaceDir, prompts) {
|
|
51
|
+
const promptsDir = join(workspaceDir, ".pi", "prompts");
|
|
52
|
+
await mkdir(promptsDir, { recursive: true });
|
|
53
|
+
for (const p of prompts) {
|
|
54
|
+
const fileName = `${p.name.replace(/[/\\]/g, "-")}.md`;
|
|
55
|
+
const lines = p.description ? [`> ${p.description}
|
|
56
|
+
`, p.content] : [p.content];
|
|
57
|
+
await writeFile(join(promptsDir, fileName), lines.join("\n") + "\n", "utf-8");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async materializeMcpConfig(_workspaceDir, servers) {
|
|
61
|
+
if (servers.length > 0) {
|
|
62
|
+
logger.warn(
|
|
63
|
+
{ serverCount: servers.length },
|
|
64
|
+
"Pi does not support MCP; MCP config will be skipped"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async materializePlugins(_workspaceDir, _plugins) {
|
|
69
|
+
}
|
|
70
|
+
async materializeWorkflow(workspaceDir, workflow) {
|
|
71
|
+
const trellisDir = join(workspaceDir, ".trellis");
|
|
72
|
+
await mkdir(trellisDir, { recursive: true });
|
|
73
|
+
await writeFile(join(trellisDir, "workflow.md"), workflow.content + "\n", "utf-8");
|
|
74
|
+
}
|
|
75
|
+
async injectPermissions(workspaceDir, _servers, permissions) {
|
|
76
|
+
if (!permissions) return;
|
|
77
|
+
const resolved = resolvePermissions(permissions);
|
|
78
|
+
const tools = resolved.allow ?? [];
|
|
79
|
+
if (tools.length === 0) return;
|
|
80
|
+
const piDir = join(workspaceDir, ".pi");
|
|
81
|
+
await mkdir(piDir, { recursive: true });
|
|
82
|
+
const settings = { tools };
|
|
83
|
+
await writeFile(
|
|
84
|
+
join(piDir, "settings.json"),
|
|
85
|
+
JSON.stringify(settings, null, 2) + "\n",
|
|
86
|
+
"utf-8"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
async verify(workspaceDir) {
|
|
90
|
+
const errors = [];
|
|
91
|
+
const warnings = [];
|
|
92
|
+
try {
|
|
93
|
+
const s = await stat(join(workspaceDir, "AGENTS.md"));
|
|
94
|
+
if (!s.isFile()) {
|
|
95
|
+
errors.push("Expected file: AGENTS.md");
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
errors.push("Missing: AGENTS.md");
|
|
99
|
+
}
|
|
100
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// src/pi-communicator.ts
|
|
105
|
+
import { readFile } from "fs/promises";
|
|
106
|
+
import { join as join2 } from "path";
|
|
107
|
+
import { createLogger as createLogger2 } from "@actant/shared";
|
|
108
|
+
var logger2 = createLogger2("pi-communicator");
|
|
109
|
+
function configFromBackend(backendConfig) {
|
|
110
|
+
return {
|
|
111
|
+
provider: asString(backendConfig?.["provider"]) ?? process.env["ACTANT_PROVIDER"],
|
|
112
|
+
model: asString(backendConfig?.["model"]) ?? process.env["ACTANT_MODEL"],
|
|
113
|
+
apiKey: asString(backendConfig?.["apiKey"]),
|
|
114
|
+
thinkingLevel: asString(backendConfig?.["thinkingLevel"]) ?? process.env["ACTANT_THINKING_LEVEL"],
|
|
115
|
+
tools: Array.isArray(backendConfig?.["tools"]) ? backendConfig["tools"] : void 0
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function asString(v) {
|
|
119
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
120
|
+
}
|
|
121
|
+
var PiCommunicator = class {
|
|
122
|
+
config;
|
|
123
|
+
constructor(config = {}) {
|
|
124
|
+
this.config = config;
|
|
125
|
+
}
|
|
126
|
+
async runPrompt(workspaceDir, prompt, options) {
|
|
127
|
+
logger2.debug({ workspaceDir }, "Running Pi prompt");
|
|
128
|
+
const agent = await this.buildAgent(workspaceDir, options);
|
|
129
|
+
let text = "";
|
|
130
|
+
const unsub = agent.subscribe((event) => {
|
|
131
|
+
if (event.type === "message_update" && event.assistantMessageEvent?.type === "text_delta") {
|
|
132
|
+
text += event.assistantMessageEvent.delta ?? "";
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
try {
|
|
136
|
+
await agent.prompt(prompt);
|
|
137
|
+
const messages = agent.state.messages;
|
|
138
|
+
const last = messages[messages.length - 1];
|
|
139
|
+
if (last?.role === "assistant" && last.content) {
|
|
140
|
+
const fullText = last.content.filter((b) => "type" in b && b.type === "text").map((b) => b.text ?? "").join("");
|
|
141
|
+
text = fullText || text;
|
|
142
|
+
}
|
|
143
|
+
return { text, sessionId: agent.sessionId };
|
|
144
|
+
} finally {
|
|
145
|
+
unsub();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async *streamPrompt(workspaceDir, prompt, options) {
|
|
149
|
+
logger2.debug({ workspaceDir }, "Streaming Pi prompt");
|
|
150
|
+
const agent = await this.buildAgent(workspaceDir, options);
|
|
151
|
+
const queue = [];
|
|
152
|
+
let resolve = null;
|
|
153
|
+
let done = false;
|
|
154
|
+
let promptError = null;
|
|
155
|
+
const unsub = agent.subscribe((event) => {
|
|
156
|
+
if (event.type === "message_update" && event.assistantMessageEvent?.type === "text_delta") {
|
|
157
|
+
queue.push({ type: "text", content: event.assistantMessageEvent.delta ?? "" });
|
|
158
|
+
} else if (event.type === "tool_execution_start") {
|
|
159
|
+
const content = event.toolName ? `[Tool: ${event.toolName}] ${JSON.stringify(event.args ?? {})}` : "";
|
|
160
|
+
queue.push({ type: "tool_use", content });
|
|
161
|
+
} else if (event.type === "tool_execution_end") {
|
|
162
|
+
const parts = event.result?.content ?? [];
|
|
163
|
+
const text = parts.filter((p) => p.text).map((p) => p.text).join("");
|
|
164
|
+
queue.push({ type: "result", content: text });
|
|
165
|
+
} else if (event.type === "agent_end") {
|
|
166
|
+
done = true;
|
|
167
|
+
}
|
|
168
|
+
if (resolve) {
|
|
169
|
+
resolve();
|
|
170
|
+
resolve = null;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
const promptPromise = agent.prompt(prompt).then(() => {
|
|
174
|
+
done = true;
|
|
175
|
+
if (resolve) {
|
|
176
|
+
resolve();
|
|
177
|
+
resolve = null;
|
|
178
|
+
}
|
|
179
|
+
}).catch((err) => {
|
|
180
|
+
promptError = err instanceof Error ? err : new Error(String(err));
|
|
181
|
+
queue.push({ type: "error", content: promptError.message });
|
|
182
|
+
done = true;
|
|
183
|
+
if (resolve) {
|
|
184
|
+
resolve();
|
|
185
|
+
resolve = null;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
try {
|
|
189
|
+
while (!done || queue.length > 0) {
|
|
190
|
+
if (queue.length > 0) {
|
|
191
|
+
yield queue.shift();
|
|
192
|
+
} else {
|
|
193
|
+
await new Promise((r) => {
|
|
194
|
+
resolve = r;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
await promptPromise;
|
|
199
|
+
if (promptError) throw promptError;
|
|
200
|
+
} finally {
|
|
201
|
+
unsub();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async buildAgent(workspaceDir, options) {
|
|
205
|
+
let systemPrompt = "You are a helpful coding assistant. You have access to file and command tools.";
|
|
206
|
+
if (options?.systemPromptFile) {
|
|
207
|
+
const path = join2(workspaceDir, options.systemPromptFile);
|
|
208
|
+
systemPrompt = await readFile(path, "utf-8");
|
|
209
|
+
}
|
|
210
|
+
if (options?.appendSystemPrompt) {
|
|
211
|
+
systemPrompt += "\n\n" + options.appendSystemPrompt;
|
|
212
|
+
}
|
|
213
|
+
const opts = {
|
|
214
|
+
workspaceDir,
|
|
215
|
+
provider: this.config.provider,
|
|
216
|
+
model: options?.model ?? this.config.model,
|
|
217
|
+
apiKey: this.config.apiKey,
|
|
218
|
+
thinkingLevel: this.config.thinkingLevel,
|
|
219
|
+
tools: this.config.tools,
|
|
220
|
+
systemPrompt
|
|
221
|
+
};
|
|
222
|
+
const agent = createPiAgent(opts);
|
|
223
|
+
if (options?.sessionId) {
|
|
224
|
+
agent.sessionId = options.sessionId;
|
|
225
|
+
}
|
|
226
|
+
return agent;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// src/index.ts
|
|
231
|
+
var ACP_BRIDGE_PATH = join3(dirname(fileURLToPath(import.meta.url)), "acp-bridge.js");
|
|
232
|
+
export {
|
|
233
|
+
ACP_BRIDGE_PATH,
|
|
234
|
+
PiBuilder,
|
|
235
|
+
PiCommunicator,
|
|
236
|
+
configFromBackend,
|
|
237
|
+
createPiAgent
|
|
238
|
+
};
|
|
239
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/pi-builder.ts","../src/pi-communicator.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nexport { PiBuilder } from \"./pi-builder\";\nexport { PiCommunicator, configFromBackend, type PiCommunicatorConfig } from \"./pi-communicator\";\nexport { createPiAgent, type PiAgentOptions } from \"./pi-tool-bridge\";\n\nexport const ACP_BRIDGE_PATH = join(dirname(fileURLToPath(import.meta.url)), \"acp-bridge.js\");\n","import { writeFile, mkdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n SkillDefinition,\n PromptDefinition,\n McpServerDefinition,\n WorkflowDefinition,\n PluginDefinition,\n PermissionsInput,\n} from \"@actant/shared\";\nimport { createLogger } from \"@actant/shared\";\nimport { resolvePermissions } from \"@actant/core\";\nimport type { BackendBuilder, VerifyResult } from \"@actant/core\";\n\nconst logger = createLogger(\"pi-builder\");\n\nexport class PiBuilder implements BackendBuilder {\n readonly backendType = \"pi\" as const;\n\n async scaffold(workspaceDir: string): Promise<void> {\n await mkdir(join(workspaceDir, \".pi\", \"skills\"), { recursive: true });\n await mkdir(join(workspaceDir, \".pi\", \"prompts\"), { recursive: true });\n await writeFile(join(workspaceDir, \"AGENTS.md\"), \"# Agent Skills\\n\", \"utf-8\");\n }\n\n async materializeSkills(workspaceDir: string, skills: SkillDefinition[]): Promise<void> {\n const skillsDir = join(workspaceDir, \".pi\", \"skills\");\n await mkdir(skillsDir, { recursive: true });\n const sections = skills.map((s) => {\n const header = `## ${s.name}`;\n const desc = s.description ? `\\n> ${s.description}\\n` : \"\";\n return `${header}${desc}\\n${s.content}`;\n });\n const agentsContent = `# Agent Skills\\n\\n${sections.join(\"\\n\\n---\\n\\n\")}\\n`;\n await writeFile(join(workspaceDir, \"AGENTS.md\"), agentsContent, \"utf-8\");\n for (const skill of skills) {\n const fileName = `${skill.name.replace(/[/\\\\]/g, \"-\")}.md`;\n const content = [\n skill.description ? `> ${skill.description}\\n` : \"\",\n skill.content,\n \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n await writeFile(join(skillsDir, fileName), content, \"utf-8\");\n }\n logger.debug({ workspaceDir, count: skills.length }, \"Skills materialized\");\n }\n\n async materializePrompts(workspaceDir: string, prompts: PromptDefinition[]): Promise<void> {\n const promptsDir = join(workspaceDir, \".pi\", \"prompts\");\n await mkdir(promptsDir, { recursive: true });\n for (const p of prompts) {\n const fileName = `${p.name.replace(/[/\\\\]/g, \"-\")}.md`;\n const lines = p.description ? [`> ${p.description}\\n`, p.content] : [p.content];\n await writeFile(join(promptsDir, fileName), lines.join(\"\\n\") + \"\\n\", \"utf-8\");\n }\n }\n\n async materializeMcpConfig(\n _workspaceDir: string,\n servers: McpServerDefinition[],\n ): Promise<void> {\n if (servers.length > 0) {\n logger.warn(\n { serverCount: servers.length },\n \"Pi does not support MCP; MCP config will be skipped\",\n );\n }\n }\n\n async materializePlugins(\n _workspaceDir: string,\n _plugins: PluginDefinition[],\n ): Promise<void> {}\n\n async materializeWorkflow(workspaceDir: string, workflow: WorkflowDefinition): Promise<void> {\n const trellisDir = join(workspaceDir, \".trellis\");\n await mkdir(trellisDir, { recursive: true });\n await writeFile(join(trellisDir, \"workflow.md\"), workflow.content + \"\\n\", \"utf-8\");\n }\n\n async injectPermissions(\n workspaceDir: string,\n _servers: McpServerDefinition[],\n permissions?: PermissionsInput,\n ): Promise<void> {\n if (!permissions) return;\n const resolved = resolvePermissions(permissions);\n const tools = resolved.allow ?? [];\n if (tools.length === 0) return;\n\n const piDir = join(workspaceDir, \".pi\");\n await mkdir(piDir, { recursive: true });\n const settings: { tools: string[] } = { tools };\n await writeFile(\n join(piDir, \"settings.json\"),\n JSON.stringify(settings, null, 2) + \"\\n\",\n \"utf-8\",\n );\n }\n\n async verify(workspaceDir: string): Promise<VerifyResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n try {\n const s = await stat(join(workspaceDir, \"AGENTS.md\"));\n if (!s.isFile()) {\n errors.push(\"Expected file: AGENTS.md\");\n }\n } catch {\n errors.push(\"Missing: AGENTS.md\");\n }\n\n return { valid: errors.length === 0, errors, warnings };\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n AgentCommunicator,\n PromptResult,\n RunPromptOptions,\n StreamChunk,\n} from \"@actant/core\";\nimport { createLogger } from \"@actant/shared\";\nimport { createPiAgent, type PiAgentOptions } from \"./pi-tool-bridge\";\n\nconst logger = createLogger(\"pi-communicator\");\n\nexport interface PiCommunicatorConfig {\n provider?: string;\n model?: string;\n apiKey?: string;\n thinkingLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n tools?: string[];\n}\n\n/**\n * Extract PiCommunicatorConfig from a template's backend.config record.\n * Falls back to ACTANT_* environment variables, then to pi-ai built-in env resolution.\n */\nexport function configFromBackend(backendConfig?: Record<string, unknown>): PiCommunicatorConfig {\n return {\n provider: asString(backendConfig?.[\"provider\"]) ?? process.env[\"ACTANT_PROVIDER\"],\n model: asString(backendConfig?.[\"model\"]) ?? process.env[\"ACTANT_MODEL\"],\n apiKey: asString(backendConfig?.[\"apiKey\"]),\n thinkingLevel: asString(backendConfig?.[\"thinkingLevel\"]) as PiCommunicatorConfig[\"thinkingLevel\"] ?? (process.env[\"ACTANT_THINKING_LEVEL\"] as PiCommunicatorConfig[\"thinkingLevel\"]),\n tools: Array.isArray(backendConfig?.[\"tools\"]) ? (backendConfig[\"tools\"] as string[]) : undefined,\n };\n}\n\nfunction asString(v: unknown): string | undefined {\n return typeof v === \"string\" && v.length > 0 ? v : undefined;\n}\n\nexport class PiCommunicator implements AgentCommunicator {\n private readonly config: PiCommunicatorConfig;\n\n constructor(config: PiCommunicatorConfig = {}) {\n this.config = config;\n }\n\n async runPrompt(\n workspaceDir: string,\n prompt: string,\n options?: RunPromptOptions,\n ): Promise<PromptResult> {\n logger.debug({ workspaceDir }, \"Running Pi prompt\");\n const agent = await this.buildAgent(workspaceDir, options);\n let text = \"\";\n\n const unsub = agent.subscribe((event: { type: string; assistantMessageEvent?: { type?: string; delta?: string } }) => {\n if (event.type === \"message_update\" && event.assistantMessageEvent?.type === \"text_delta\") {\n text += event.assistantMessageEvent.delta ?? \"\";\n }\n });\n\n try {\n await agent.prompt(prompt);\n const messages = agent.state.messages;\n const last = messages[messages.length - 1];\n if (last?.role === \"assistant\" && last.content) {\n const fullText = last.content\n .filter((b): b is { type: \"text\"; text: string } => \"type\" in b && b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n text = fullText || text;\n }\n return { text, sessionId: agent.sessionId };\n } finally {\n unsub();\n }\n }\n\n async *streamPrompt(\n workspaceDir: string,\n prompt: string,\n options?: RunPromptOptions,\n ): AsyncIterable<StreamChunk> {\n logger.debug({ workspaceDir }, \"Streaming Pi prompt\");\n const agent = await this.buildAgent(workspaceDir, options);\n const queue: StreamChunk[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n let promptError: Error | null = null;\n\n const unsub = agent.subscribe((event: {\n type: string;\n assistantMessageEvent?: { type?: string; delta?: string };\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: { content?: Array<{ text?: string }> };\n }) => {\n if (event.type === \"message_update\" && event.assistantMessageEvent?.type === \"text_delta\") {\n queue.push({ type: \"text\", content: event.assistantMessageEvent.delta ?? \"\" });\n } else if (event.type === \"tool_execution_start\") {\n const content = event.toolName\n ? `[Tool: ${event.toolName}] ${JSON.stringify(event.args ?? {})}`\n : \"\";\n queue.push({ type: \"tool_use\", content });\n } else if (event.type === \"tool_execution_end\") {\n const parts = event.result?.content ?? [];\n const text = parts\n .filter((p) => p.text)\n .map((p) => p.text)\n .join(\"\");\n queue.push({ type: \"result\", content: text });\n } else if (event.type === \"agent_end\") {\n done = true;\n }\n if (resolve) {\n resolve();\n resolve = null;\n }\n });\n\n const promptPromise = agent\n .prompt(prompt)\n .then(() => {\n done = true;\n if (resolve) {\n resolve();\n resolve = null;\n }\n })\n .catch((err: unknown) => {\n promptError = err instanceof Error ? err : new Error(String(err));\n queue.push({ type: \"error\", content: promptError.message });\n done = true;\n if (resolve) {\n resolve();\n resolve = null;\n }\n });\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift() as StreamChunk;\n } else {\n await new Promise<void>((r) => {\n resolve = r;\n });\n }\n }\n await promptPromise;\n if (promptError) throw promptError;\n } finally {\n unsub();\n }\n }\n\n private async buildAgent(\n workspaceDir: string,\n options?: RunPromptOptions,\n ): Promise<ReturnType<typeof createPiAgent>> {\n let systemPrompt =\n \"You are a helpful coding assistant. You have access to file and command tools.\";\n\n if (options?.systemPromptFile) {\n const path = join(workspaceDir, options.systemPromptFile);\n systemPrompt = await readFile(path, \"utf-8\");\n }\n if (options?.appendSystemPrompt) {\n systemPrompt += \"\\n\\n\" + options.appendSystemPrompt;\n }\n\n const opts: PiAgentOptions = {\n workspaceDir,\n provider: this.config.provider,\n model: options?.model ?? this.config.model,\n apiKey: this.config.apiKey,\n thinkingLevel: this.config.thinkingLevel,\n tools: this.config.tools,\n systemPrompt,\n };\n\n const agent = createPiAgent(opts);\n if (options?.sessionId) {\n agent.sessionId = options.sessionId;\n }\n return agent;\n }\n}\n"],"mappings":"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","names":["join","join","createLogger","logger","createLogger","join","join"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@actant/pi",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Pi Agent backend for the Actant platform — built on pi-agent-core and pi-ai",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "blackplume <blackplume233@gmail.com>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/blackplume233/Actant.git",
|
|
11
|
+
"directory": "packages/pi"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/blackplume233/Actant#readme",
|
|
14
|
+
"bugs": "https://github.com/blackplume233/Actant/issues",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"actant",
|
|
17
|
+
"ai-agent",
|
|
18
|
+
"pi",
|
|
19
|
+
"pi-agent",
|
|
20
|
+
"backend"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"bin": {
|
|
31
|
+
"pi-acp-bridge": "./dist/acp-bridge.js"
|
|
32
|
+
},
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"types": "./dist/index.d.ts"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@agentclientprotocol/sdk": "^0.14.1",
|
|
41
|
+
"@mariozechner/pi-agent-core": "^0.54.2",
|
|
42
|
+
"@mariozechner/pi-ai": "^0.54.2",
|
|
43
|
+
"@actant/core": "0.2.0",
|
|
44
|
+
"@actant/shared": "0.2.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"dev": "tsup --watch",
|
|
49
|
+
"type-check": "tsc --noEmit",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"clean": "rimraf dist"
|
|
52
|
+
}
|
|
53
|
+
}
|