@meetopenbot/pi 0.1.1 → 0.1.2

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 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
- const text = await runPiPrompt(session, prompt, { streaming: session.isStreaming });
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,36 @@
1
+ import { createTextReplyBuffer, textReply, yieldFromBackgroundQueue, } from '@meetopenbot/plugin-sdk';
2
+ import { remapPiError } from './credits.js';
1
3
  const isAssistantMessage = (message) => message.role === 'assistant';
2
- /** Run a Pi prompt and return the final assistant text. */
3
- export async function runPiPrompt(session, prompt, options) {
4
- let assistantText = '';
5
- let result = '';
6
- let wake;
7
- let finished = false;
8
- let error;
9
- const wakeUp = () => {
10
- wake?.();
11
- wake = undefined;
12
- };
13
- const onEvent = (event) => {
14
- if (event.type === 'message_update') {
15
- const assistantEvent = event.assistantMessageEvent;
16
- if (assistantEvent.type === 'text_delta')
17
- assistantText += assistantEvent.delta;
18
- return;
19
- }
20
- if (event.type === 'agent_end') {
21
- const lastAssistant = [...event.messages].reverse().find(isAssistantMessage);
22
- if (lastAssistant?.stopReason === 'error' && lastAssistant.errorMessage?.trim()) {
23
- result = `Pi error: ${lastAssistant.errorMessage.trim()}`;
24
- }
25
- else {
26
- result = assistantText;
27
- }
28
- finished = true;
29
- wakeUp();
4
+ export const classifyPiEvent = (event) => {
5
+ if (event.type === 'message_update') {
6
+ const assistantEvent = event.assistantMessageEvent;
7
+ if (assistantEvent.type === 'text_delta')
8
+ return { type: 'delta', text: assistantEvent.delta };
9
+ return { type: 'skip' };
10
+ }
11
+ if (event.type === 'message_end')
12
+ return { type: 'flush' };
13
+ return { type: 'skip' };
14
+ };
15
+ function* consumePiEvent(event, replies) {
16
+ if (event.type === 'agent_end') {
17
+ yield* replies.end();
18
+ const lastAssistant = [...event.messages].reverse().find(isAssistantMessage);
19
+ if (lastAssistant?.stopReason === 'error' && lastAssistant.errorMessage?.trim()) {
20
+ yield textReply(`Pi error: ${remapPiError(lastAssistant.errorMessage.trim())}`);
30
21
  }
31
- };
32
- const unsubscribe = session.subscribe(onEvent);
33
- const run = (async () => {
22
+ return;
23
+ }
24
+ yield* replies.apply(classifyPiEvent(event));
25
+ }
26
+ /** Run a Pi prompt and yield each completed assistant turn. */
27
+ export async function* runPiPrompt(session, prompt, options) {
28
+ const replies = createTextReplyBuffer();
29
+ yield* yieldFromBackgroundQueue(async (enqueue) => {
30
+ const unsubscribe = session.subscribe((event) => {
31
+ for (const item of consumePiEvent(event, replies))
32
+ enqueue(item);
33
+ });
34
34
  try {
35
35
  if (options?.streaming && session.isStreaming) {
36
36
  await session.followUp(prompt);
@@ -39,30 +39,10 @@ export async function runPiPrompt(session, prompt, options) {
39
39
  await session.prompt(prompt);
40
40
  }
41
41
  }
42
- catch (err) {
43
- error = err instanceof Error ? err : new Error(String(err));
44
- }
45
42
  finally {
46
- finished = true;
47
- wakeUp();
48
- }
49
- })();
50
- try {
51
- while (!finished) {
52
- await new Promise((resolve) => {
53
- if (finished) {
54
- resolve();
55
- return;
56
- }
57
- wake = resolve;
58
- });
43
+ unsubscribe();
44
+ for (const item of replies.end())
45
+ enqueue(item);
59
46
  }
60
- await run;
61
- if (error)
62
- throw error;
63
- return result.trim();
64
- }
65
- finally {
66
- unsubscribe();
67
- }
47
+ });
68
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetopenbot/pi",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
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.3.0"
24
+ "@meetopenbot/plugin-sdk": "^0.4.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^25.9.2",