opengate 0.2.8 → 0.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/dist/index.js CHANGED
@@ -95,9 +95,11 @@ Before writing any code, gather all available context:
95
95
  - Read any returned entries \u2014 they contain architecture decisions, patterns, gotchas, and conventions for this project
96
96
  - Follow these conventions in your implementation
97
97
 
98
- ### Phase 3: Plan & Announce
98
+ ### Phase 3: Plan & Announce (REQUIRED)
99
99
  4. **Post starting comment** \u2014 \`POST /api/tasks/${task.id}/activity\`
100
- Body: \`{"content": "Starting work. Plan: <your plan informed by the context you gathered, 2-4 sentences>"}\`
100
+ Body: \`{"content": "## Starting Work\\n\\n**Plan:**\\n- <step 1>\\n- <step 2>\\n\\n**Context from KB:** <what you learned>\\n\\n**Concerns:** <any blockers or risks>"}\`
101
+
102
+ This comment is REQUIRED. Do not skip it.
101
103
  - Your plan should reflect what you learned from the knowledge base, existing comments, and dependencies
102
104
 
103
105
  ${workspaceBlock}
@@ -109,15 +111,32 @@ ${workspaceBlock}
109
111
  - Run the project's test suite and fix any failures
110
112
  - Commit your changes with a descriptive message referencing the task
111
113
 
112
- ### Phase 6: Report & Complete
114
+ ### Phase 5.5: Knowledge Review (MANDATORY)
115
+ Before completing the task, review your work and ask yourself:
116
+ - Did I make an architecture or design decision? \u2192 Write it (category: "decision" or "architecture")
117
+ - Did I encounter a non-obvious gotcha or bug? \u2192 Write it (category: "gotcha")
118
+ - Did I establish or follow a pattern others should know? \u2192 Write it (category: "pattern")
119
+ - Did I discover project structure or conventions? \u2192 Write it (category: "reference")
120
+
121
+ If ANY of the above apply, write knowledge entries BEFORE completing:
122
+ \`PUT /api/projects/${projectId}/knowledge/<descriptive-key>\`
123
+ Body: \`{"title": "...", "content": "...", "tags": [...], "category": "..."}\`
124
+
125
+ Key naming: use kebab-case descriptors, e.g. "auth-middleware-pattern", "db-migration-gotcha"
126
+
127
+ IMPORTANT: Only write PROJECT-SCOPED knowledge. Do NOT write task-specific details.
128
+ Good: "The API uses tower middleware for auth, not axum extractors"
129
+ Bad: "Task T-123 required adding a new endpoint"
130
+
131
+ If nothing new was discovered, that's fine \u2014 skip this phase.
132
+
133
+ ### Phase 6: Report & Complete (REQUIRED)
113
134
  8. **Post results comment** \u2014 \`POST /api/tasks/${task.id}/activity\`
114
- Body: \`{"content": "<summary of what changed: files modified, approach taken, test results, commit hash>"}\`
135
+ Body: \`{"content": "## Results\\n\\n**Changes:**\\n- <file1>: <what changed>\\n- <file2>: <what changed>\\n\\n**Approach:** <brief explanation>\\n\\n**Tests:** <pass/fail status>\\n\\n**Commits:** <hash(es)>"}\`
115
136
 
116
- 9. **Write knowledge** (if you discovered something worth sharing) \u2014 \`PUT /api/projects/${projectId}/knowledge/<key>\`
117
- Body: \`{"title": "...", "content": "...", "tags": [...], "category": "<architecture|pattern|gotcha|decision|reference>"}\`
118
- - Write entries for: architectural decisions you made, gotchas you encountered, patterns you established
137
+ This comment is REQUIRED. Do not skip it.
119
138
 
120
- 10. **Complete the task** \u2014 \`POST /api/tasks/${task.id}/complete\`
139
+ 9. **Complete the task** \u2014 \`POST /api/tasks/${task.id}/complete\`
121
140
  Body: \`{"summary": "<what was done>", "output": {"branch": "<branch-name>", "commits": ["<hash>"]}}\`
122
141
 
123
142
  ## Handling Blockers
@@ -137,6 +156,16 @@ If a dependency is not yet done:
137
156
  - Respect existing patterns found in the knowledge base
138
157
  - Keep commits atomic and descriptive
139
158
 
159
+ ## Handling @-Mentions
160
+ If you receive a \`task.comment_mention\` notification:
161
+ 1. Read the comment content from the notification body
162
+ 2. Fetch the full task context: \`GET /api/tasks/{taskId}\`
163
+ 3. Reason about what's being asked:
164
+ - If it's a question \u2192 post a reply comment with your answer
165
+ - If it's a request for changes \u2192 update task status to in_progress, make the changes, then re-complete
166
+ - If it's a simple acknowledgment \u2192 post a brief confirmation comment
167
+ 4. Always reply with a comment so the human knows you've seen it
168
+
140
169
  Now begin. Start with Phase 1: claim the task.`;
141
170
  }
142
171
 
@@ -241,6 +270,10 @@ var TaskState = class {
241
270
  activeCount() {
242
271
  return Object.keys(this.data.spawned).length;
243
272
  }
273
+ /** Returns all task IDs currently in the spawned set. */
274
+ spawnedIds() {
275
+ return Object.keys(this.data.spawned);
276
+ }
244
277
  };
245
278
 
246
279
  // src/poller.ts
@@ -266,7 +299,10 @@ async function fetchInbox(url, apiKey) {
266
299
  throw new Error(`OpenGate inbox returned HTTP ${resp.status}`);
267
300
  }
268
301
  const body = await resp.json();
269
- return body.todo_tasks ?? [];
302
+ return {
303
+ todoTasks: body.todo_tasks ?? [],
304
+ inProgressTasks: body.in_progress_tasks ?? []
305
+ };
270
306
  }
271
307
  var OpenGatePoller = class {
272
308
  constructor(pluginCfg, openclawCfg, logger, stateDir) {
@@ -297,6 +333,35 @@ var OpenGatePoller = class {
297
333
  }
298
334
  async poll() {
299
335
  if (!this.running) return;
336
+ let inbox;
337
+ try {
338
+ inbox = await fetchInbox(this.pluginCfg.url, this.pluginCfg.apiKey);
339
+ } catch (e) {
340
+ this.logger.warn(
341
+ `[opengate] Failed to fetch inbox: ${e instanceof Error ? e.message : String(e)}`
342
+ );
343
+ return;
344
+ }
345
+ const inboxTaskIds = /* @__PURE__ */ new Set([
346
+ ...inbox.todoTasks.map((t) => t.id),
347
+ ...inbox.inProgressTasks.map((t) => t.id)
348
+ ]);
349
+ for (const spawnedId of this.state.spawnedIds()) {
350
+ if (!inboxTaskIds.has(spawnedId)) {
351
+ this.logger.info(
352
+ `[opengate] Task ${spawnedId} no longer in inbox (completed/cancelled) \u2014 freeing slot`
353
+ );
354
+ this.state.remove(spawnedId);
355
+ }
356
+ }
357
+ for (const task of inbox.inProgressTasks) {
358
+ if (!this.state.isSpawned(task.id)) {
359
+ this.logger.warn(
360
+ `[opengate] Orphaned in_progress task "${task.title}" (${task.id}) \u2014 releasing back to todo`
361
+ );
362
+ await this.releaseTask(task.id);
363
+ }
364
+ }
300
365
  const maxConcurrent = this.pluginCfg.maxConcurrent ?? 3;
301
366
  const active = this.state.activeCount();
302
367
  if (active >= maxConcurrent) {
@@ -305,18 +370,9 @@ var OpenGatePoller = class {
305
370
  );
306
371
  return;
307
372
  }
308
- let tasks;
309
- try {
310
- tasks = await fetchInbox(this.pluginCfg.url, this.pluginCfg.apiKey);
311
- } catch (e) {
312
- this.logger.warn(
313
- `[opengate] Failed to fetch inbox: ${e instanceof Error ? e.message : String(e)}`
314
- );
315
- return;
316
- }
317
- if (tasks.length === 0) return;
318
- this.logger.info(`[opengate] Found ${tasks.length} todo task(s)`);
319
- for (const task of tasks) {
373
+ if (inbox.todoTasks.length === 0) return;
374
+ this.logger.info(`[opengate] Found ${inbox.todoTasks.length} todo task(s)`);
375
+ for (const task of inbox.todoTasks) {
320
376
  if (!this.running) break;
321
377
  const currentActive = this.state.activeCount();
322
378
  if (currentActive >= maxConcurrent) {
@@ -339,6 +395,25 @@ var OpenGatePoller = class {
339
395
  if (project) this.projectCache.set(projectId, project);
340
396
  return project;
341
397
  }
398
+ async releaseTask(taskId) {
399
+ try {
400
+ const resp = await fetch(
401
+ `${this.pluginCfg.url}/api/tasks/${taskId}/release`,
402
+ {
403
+ method: "POST",
404
+ headers: { Authorization: `Bearer ${this.pluginCfg.apiKey}` },
405
+ signal: AbortSignal.timeout(1e4)
406
+ }
407
+ );
408
+ if (!resp.ok) {
409
+ this.logger.warn(`[opengate] Failed to release task ${taskId}: HTTP ${resp.status}`);
410
+ }
411
+ } catch (e) {
412
+ this.logger.warn(
413
+ `[opengate] Failed to release task ${taskId}: ${e instanceof Error ? e.message : String(e)}`
414
+ );
415
+ }
416
+ }
342
417
  async spawnTask(task) {
343
418
  this.logger.info(`[opengate] Spawning session for task: "${task.title}" (${task.id})`);
344
419
  let project = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opengate",
3
- "version": "0.2.8",
3
+ "version": "0.2.11",
4
4
  "description": "OpenGate task executor plugin for OpenClaw — polls assigned tasks and spawns isolated agent sessions",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -95,14 +95,24 @@ Specifically look for:
95
95
 
96
96
  This enforces capacity limits and dependency checks. If claiming fails, read the error — you may have too many tasks in progress or a dependency is incomplete.
97
97
 
98
- ### 5. Comment: Starting Work
98
+ ### 5. Comment: Starting Work (REQUIRED)
99
99
 
100
100
  `post_comment(task_id, content)` → Post a comment before you start
101
101
 
102
- Your starting comment should include:
103
- - What you understand the task requires
104
- - Your planned approach
105
- - Any concerns or assumptions
102
+ Your starting comment MUST use this structure:
103
+ ```
104
+ ## Starting Work
105
+
106
+ **Plan:**
107
+ - <step 1>
108
+ - <step 2>
109
+
110
+ **Context from KB:** <what you learned>
111
+
112
+ **Concerns:** <any blockers or risks>
113
+ ```
114
+
115
+ Do NOT skip this comment. It is how the team tracks work and maintains visibility.
106
116
 
107
117
  ### 6. Do the Work
108
118
 
@@ -125,7 +135,28 @@ Store useful artifacts like:
125
135
  - Links to PRs, commits, or external resources
126
136
  - Feature branch name (e.g. `task/<task_id_short>`) for workspace continuity
127
137
 
128
- ### 9. Complete the Task
138
+ ### 9. Post Results Comment (REQUIRED)
139
+
140
+ `post_comment(task_id, content)` → Post a final results comment
141
+
142
+ Your results comment MUST use this structure:
143
+ ```
144
+ ## Results
145
+
146
+ **Changes:**
147
+ - <file1>: <what changed>
148
+ - <file2>: <what changed>
149
+
150
+ **Approach:** <brief explanation>
151
+
152
+ **Tests:** <pass/fail status>
153
+
154
+ **Commits:** <hash(es)>
155
+ ```
156
+
157
+ Do NOT skip this comment. It is critical for reviewers and future reference.
158
+
159
+ ### 10. Complete the Task
129
160
 
130
161
  `complete_task(task_id, summary, output)` → Finish the task with a summary and structured output
131
162
 
@@ -181,19 +212,28 @@ If a dependency is no longer needed:
181
212
  - **References** — links, docs, external resources
182
213
  - **General** — anything else worth knowing
183
214
 
184
- ### Writing Knowledge
215
+ ### Writing Knowledge (MANDATORY Review)
185
216
 
186
- When you discover something important during work, **write it back**:
217
+ Before completing any task, review your work with this checklist:
218
+
219
+ - [ ] Did I make an architecture or design decision? → Write it (category: `decision` or `architecture`)
220
+ - [ ] Did I encounter a non-obvious gotcha or bug? → Write it (category: `gotcha`)
221
+ - [ ] Did I establish or follow a pattern others should know? → Write it (category: `pattern`)
222
+ - [ ] Did I discover project structure or conventions? → Write it (category: `reference`)
223
+
224
+ If ANY apply, write knowledge entries BEFORE completing:
187
225
 
188
226
  `set_knowledge(project_id, key, title, content, tags, category)`
189
227
 
190
- Write knowledge when you:
191
- - Discover a non-obvious pattern or constraint
192
- - Make an architecture decision that affects future work
193
- - Find a gotcha that would trip up other agents
194
- - Establish a convention through your implementation
228
+ Key naming: use kebab-case descriptors, e.g. `auth-middleware-pattern`, `db-migration-gotcha`
229
+
230
+ **IMPORTANT: Only write PROJECT-SCOPED knowledge.** Do NOT write task-specific details.
231
+ - Good: "The API uses tower middleware for auth, not axum extractors"
232
+ - Bad: "Task T-123 required adding a new endpoint"
233
+
234
+ If nothing new was discovered, that's fine — skip writing.
195
235
 
196
- Categories: `architecture`, `convention`, `gotcha`, `reference`, `general`
236
+ Categories: `architecture`, `pattern`, `gotcha`, `decision`, `reference`
197
237
 
198
238
  ## Agent Profile
199
239