@forloop-cc/forloop-opencode-plugin-planner 2.2.9 → 2.2.11

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@forloop-cc/forloop-opencode-plugin-planner",
4
- "version": "2.2.9",
4
+ "version": "2.2.11",
5
5
  "description": "ForLoop integration plugin for opencode — Sprint, story, and agent tools for the ForLoop platform",
6
6
  "type": "module",
7
7
  "license": "MIT",
@@ -309,6 +309,21 @@ export class ForLoopAPIClient {
309
309
  });
310
310
  }
311
311
 
312
+ async addStoryComment(storyId: number, body: string, authorAgentKey?: string): Promise<any> {
313
+ const payload: Record<string, unknown> = { body };
314
+ if (authorAgentKey) payload.authorAgentKey = authorAgentKey;
315
+ return this.request(`/api/opencode/stories/${storyId}/comments`, {
316
+ method: 'POST',
317
+ body: JSON.stringify(payload),
318
+ });
319
+ }
320
+
321
+ async summarizeConversation(sprintId: number): Promise<any> {
322
+ return this.request(`/api/opencode/sprints/${sprintId}/summarize`, {
323
+ method: 'POST',
324
+ });
325
+ }
326
+
312
327
  async listTemplates(): Promise<Template[]> {
313
328
  return this.request('/api/opencode/templates');
314
329
  }
@@ -21,7 +21,9 @@ function normalizeAgentKey(agent: string): string {
21
21
  }
22
22
 
23
23
  function buildConversationId(sprintId: number, agent: string, sessionId: string): string {
24
- return `sprint:${sprintId}:agent:${normalizeAgentKey(agent)}:opencode:${sessionId}`;
24
+ const senderType = process.env.FORLOOP_SENDER_TYPE || 'user';
25
+ const senderId = process.env.FORLOOP_SENDER_ID || 'unknown';
26
+ return `sprint:${sprintId}:agent:${agent}:${senderType}:${senderId}`;
25
27
  }
26
28
 
27
29
  function readActiveSprintId(): number | null {
@@ -49,12 +51,14 @@ async function recordAssistantMessage(
49
51
  await new Promise((resolve) => setTimeout(resolve, 600 * i));
50
52
  }
51
53
  const result = await client.recordMessage(data);
52
- // "no matching user message" is expected in Lambda — the server's
53
- // handleAICallback creates the full Conversation record separately.
54
54
  if (result?.message === 'no matching user message to update') {
55
- console.log(`[ForLoop] No matching user message (expected in Lambda) — callback handles persistence`);
55
+ console.log(`[ForLoop] No matching user message — user message may not be recorded yet`);
56
56
  return;
57
57
  }
58
+ // After recording, try summarization (no-op if < 30 rounds)
59
+ client.summarizeConversation(data.sprintId).catch((err: Error) => {
60
+ console.warn('[ForLoop] Summarization trigger failed:', err.message);
61
+ });
58
62
  return;
59
63
  } catch (err: any) {
60
64
  console.warn(`[ForLoop] Attempt ${i + 1}/${attempts} failed:`, err.message);
@@ -90,8 +94,6 @@ export function createChatMessageHook(client: ForLoopAPIClient) {
90
94
  preview: content.substring(0, 300),
91
95
  });
92
96
  }
93
- // Only record on user's local machine; Lambda records via its own system
94
- if (isLambdaExecution()) return;
95
97
 
96
98
  // Only record messages with a model (indicates actual LLM processing,
97
99
  // not system events like context compaction or summary generation)
@@ -227,9 +229,7 @@ export function createEventHook(client: ForLoopAPIClient) {
227
229
  return;
228
230
  }
229
231
 
230
- // Local machine: no streaming, just record messages
231
- if (isLambda) return;
232
-
232
+ // Record messages (works for local and Lambda)
233
233
  switch (event.type) {
234
234
  case 'message.part.updated': {
235
235
  const part = event.properties?.part;