@meetopenbot/pi 0.1.1 → 0.1.3
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/runtime.js +2 -7
- package/dist/stream.js +52 -55
- package/package.json +2 -2
package/dist/runtime.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { resolveConfig } from './config.js';
|
|
2
|
-
import { remapPiError } from './credits.js';
|
|
3
2
|
import { getOrCreatePiSession } from './session.js';
|
|
4
3
|
import { runPiPrompt } from './stream.js';
|
|
5
|
-
export async function runPiTurn({ prompt, handlerCtx, context }) {
|
|
4
|
+
export async function* runPiTurn({ prompt, handlerCtx, context, }) {
|
|
6
5
|
const config = resolveConfig(context, handlerCtx.state.channelDetails?.cwd);
|
|
7
6
|
const { session } = await getOrCreatePiSession({
|
|
8
7
|
config,
|
|
9
8
|
state: handlerCtx.state,
|
|
10
9
|
storage: context.storage,
|
|
11
10
|
});
|
|
12
|
-
|
|
13
|
-
if (text.startsWith('Pi error: ')) {
|
|
14
|
-
return `Pi error: ${remapPiError(text.slice('Pi error: '.length))}`;
|
|
15
|
-
}
|
|
16
|
-
return text;
|
|
11
|
+
yield* runPiPrompt(session, prompt, { streaming: session.isStreaming });
|
|
17
12
|
}
|
package/dist/stream.js
CHANGED
|
@@ -1,36 +1,53 @@
|
|
|
1
|
+
import { createTextReplyBuffer, textReply, yieldFromBackgroundQueue, } from '@meetopenbot/plugin-sdk';
|
|
2
|
+
import { remapPiError } from './credits.js';
|
|
1
3
|
const isAssistantMessage = (message) => message.role === 'assistant';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
4
|
+
export const classifyPiEvent = (event) => {
|
|
5
|
+
if (event.type === 'tool_execution_start') {
|
|
6
|
+
return {
|
|
7
|
+
type: 'tool_call',
|
|
8
|
+
id: event.toolCallId,
|
|
9
|
+
name: event.toolName,
|
|
10
|
+
input: event.args,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (event.type === 'tool_execution_end') {
|
|
14
|
+
return {
|
|
15
|
+
type: 'tool_result',
|
|
16
|
+
id: event.toolCallId,
|
|
17
|
+
name: event.toolName,
|
|
18
|
+
output: event.result,
|
|
19
|
+
error: event.isError,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (event.type === 'message_update') {
|
|
23
|
+
const assistantEvent = event.assistantMessageEvent;
|
|
24
|
+
if (assistantEvent.type === 'text_delta')
|
|
25
|
+
return { type: 'delta', text: assistantEvent.delta };
|
|
26
|
+
return { type: 'skip' };
|
|
27
|
+
}
|
|
28
|
+
if (event.type === 'message_end')
|
|
29
|
+
return { type: 'flush' };
|
|
30
|
+
return { type: 'skip' };
|
|
31
|
+
};
|
|
32
|
+
function* consumePiEvent(event, replies) {
|
|
33
|
+
if (event.type === 'agent_end') {
|
|
34
|
+
yield* replies.end();
|
|
35
|
+
const lastAssistant = [...event.messages].reverse().find(isAssistantMessage);
|
|
36
|
+
if (lastAssistant?.stopReason === 'error' && lastAssistant.errorMessage?.trim()) {
|
|
37
|
+
yield textReply(`Pi error: ${remapPiError(lastAssistant.errorMessage.trim())}`);
|
|
30
38
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
yield* replies.apply(classifyPiEvent(event));
|
|
42
|
+
}
|
|
43
|
+
/** Run a Pi prompt and yield each completed assistant turn and tool widget. */
|
|
44
|
+
export async function* runPiPrompt(session, prompt, options) {
|
|
45
|
+
const replies = createTextReplyBuffer({ groupId: 'pi:tools' });
|
|
46
|
+
yield* yieldFromBackgroundQueue(async (enqueue) => {
|
|
47
|
+
const unsubscribe = session.subscribe((event) => {
|
|
48
|
+
for (const item of consumePiEvent(event, replies))
|
|
49
|
+
enqueue(item);
|
|
50
|
+
});
|
|
34
51
|
try {
|
|
35
52
|
if (options?.streaming && session.isStreaming) {
|
|
36
53
|
await session.followUp(prompt);
|
|
@@ -39,30 +56,10 @@ export async function runPiPrompt(session, prompt, options) {
|
|
|
39
56
|
await session.prompt(prompt);
|
|
40
57
|
}
|
|
41
58
|
}
|
|
42
|
-
catch (err) {
|
|
43
|
-
error = err instanceof Error ? err : new Error(String(err));
|
|
44
|
-
}
|
|
45
59
|
finally {
|
|
46
|
-
|
|
47
|
-
|
|
60
|
+
unsubscribe();
|
|
61
|
+
for (const item of replies.end())
|
|
62
|
+
enqueue(item);
|
|
48
63
|
}
|
|
49
|
-
})
|
|
50
|
-
try {
|
|
51
|
-
while (!finished) {
|
|
52
|
-
await new Promise((resolve) => {
|
|
53
|
-
if (finished) {
|
|
54
|
-
resolve();
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
wake = resolve;
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
await run;
|
|
61
|
-
if (error)
|
|
62
|
-
throw error;
|
|
63
|
-
return result.trim();
|
|
64
|
-
}
|
|
65
|
-
finally {
|
|
66
|
-
unsubscribe();
|
|
67
|
-
}
|
|
64
|
+
});
|
|
68
65
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetopenbot/pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "OpenBot agent plugin powered by the Pi coding agent SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@earendil-works/pi-ai": "^0.79.1",
|
|
23
23
|
"@earendil-works/pi-coding-agent": "^0.79.1",
|
|
24
|
-
"@meetopenbot/plugin-sdk": "^0.
|
|
24
|
+
"@meetopenbot/plugin-sdk": "^0.5.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^25.9.2",
|