@opencode_weave/weave 0.7.0-preview.1 → 0.7.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.
Files changed (2) hide show
  1. package/dist/index.js +59 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -688,7 +688,12 @@ FORMAT RULES:
688
688
  - Max 5 visible todos at any time
689
689
  - in_progress = yellow highlight — use for ACTIVE work only
690
690
  - Prefix delegations with agent name
691
- - After all work done: mark everything completed (sidebar hides)
691
+
692
+ BEFORE FINISHING (MANDATORY):
693
+ - ALWAYS issue a final todowrite before your last response
694
+ - Mark ALL in_progress items → "completed" (or "cancelled")
695
+ - Never leave in_progress items when done
696
+ - This is NON-NEGOTIABLE — skipping it breaks the UI
692
697
  </SidebarTodos>`;
693
698
  }
694
699
  function buildDelegationSection(disabled) {
@@ -979,6 +984,12 @@ FORMAT RULES:
979
984
  - Summary todo always present during execution
980
985
  - Max 5 visible todos (1 summary + 1 in_progress + 2-3 pending)
981
986
  - in_progress = yellow highlight — use for CURRENT task only
987
+
988
+ BEFORE FINISHING (MANDATORY):
989
+ - ALWAYS issue a final todowrite before your last response
990
+ - Mark ALL in_progress items → "completed" (or "cancelled")
991
+ - Never leave in_progress items when done
992
+ - This is NON-NEGOTIABLE — skipping it breaks the UI
982
993
  </SidebarTodos>`;
983
994
  }
984
995
  function buildTapestryPlanExecutionSection(disabled = new Set) {
@@ -4705,10 +4716,12 @@ function generateMetricsReport(directory, state) {
4705
4716
  }
4706
4717
 
4707
4718
  // src/plugin/plugin-interface.ts
4719
+ var FINALIZE_TODOS_MARKER = "<!-- weave:finalize-todos -->";
4708
4720
  function createPluginInterface(args) {
4709
4721
  const { pluginConfig, hooks, tools, configHandler, agents, client, directory = "", tracker } = args;
4710
4722
  const lastAssistantMessageText = new Map;
4711
4723
  const lastUserMessageText = new Map;
4724
+ const todoFinalizedSessions = new Set;
4712
4725
  return {
4713
4726
  tool: tools,
4714
4727
  config: async (config) => {
@@ -4791,6 +4804,9 @@ ${result.contextInjection}`;
4791
4804
  `).trim() ?? "";
4792
4805
  if (userText && sessionID) {
4793
4806
  lastUserMessageText.set(sessionID, userText);
4807
+ if (!userText.includes(FINALIZE_TODOS_MARKER)) {
4808
+ todoFinalizedSessions.delete(sessionID);
4809
+ }
4794
4810
  }
4795
4811
  }
4796
4812
  if (hooks.workflowCommand) {
@@ -4825,11 +4841,12 @@ ${cmdResult.contextInjection}`;
4825
4841
  const isStartWork = promptText.includes("<session-context>");
4826
4842
  const isContinuation = promptText.includes(CONTINUATION_MARKER);
4827
4843
  const isWorkflowContinuation = promptText.includes(WORKFLOW_CONTINUATION_MARKER);
4844
+ const isTodoFinalize = promptText.includes(FINALIZE_TODOS_MARKER);
4828
4845
  const isActiveWorkflow = (() => {
4829
4846
  const wf = getActiveWorkflowInstance(directory);
4830
4847
  return wf != null && wf.status === "running";
4831
4848
  })();
4832
- if (!isStartWork && !isContinuation && !isWorkflowContinuation && !isActiveWorkflow) {
4849
+ if (!isStartWork && !isContinuation && !isWorkflowContinuation && !isTodoFinalize && !isActiveWorkflow) {
4833
4850
  const state = readWorkState(directory);
4834
4851
  if (state && !state.paused) {
4835
4852
  pauseWork(directory);
@@ -4866,6 +4883,7 @@ ${cmdResult.contextInjection}`;
4866
4883
  if (event.type === "session.deleted") {
4867
4884
  const evt = event;
4868
4885
  clearSession2(evt.properties.info.id);
4886
+ todoFinalizedSessions.delete(evt.properties.info.id);
4869
4887
  if (tracker && hooks.analyticsEnabled) {
4870
4888
  try {
4871
4889
  tracker.endSession(evt.properties.info.id);
@@ -4953,6 +4971,7 @@ ${cmdResult.contextInjection}`;
4953
4971
  lastAssistantMessageText.set(part.sessionID, part.text);
4954
4972
  }
4955
4973
  }
4974
+ let continuationFired = false;
4956
4975
  if (hooks.workflowContinuation && event.type === "session.idle") {
4957
4976
  const evt = event;
4958
4977
  const sessionId = evt.properties?.sessionID ?? "";
@@ -4997,6 +5016,7 @@ ${cmdResult.contextInjection}`;
4997
5016
  }
4998
5017
  });
4999
5018
  log("[work-continuation] Injected continuation prompt", { sessionId });
5019
+ continuationFired = true;
5000
5020
  } catch (err) {
5001
5021
  log("[work-continuation] Failed to inject continuation", { sessionId, error: String(err) });
5002
5022
  }
@@ -5005,6 +5025,43 @@ ${cmdResult.contextInjection}`;
5005
5025
  }
5006
5026
  }
5007
5027
  }
5028
+ if (event.type === "session.idle" && client && !continuationFired) {
5029
+ const evt = event;
5030
+ const sessionId = evt.properties?.sessionID ?? "";
5031
+ if (sessionId && !todoFinalizedSessions.has(sessionId)) {
5032
+ try {
5033
+ const todosResponse = await client.session.todo({ path: { id: sessionId } });
5034
+ const todos = todosResponse.data ?? [];
5035
+ const hasInProgress = todos.some((t) => t.status === "in_progress");
5036
+ if (hasInProgress) {
5037
+ todoFinalizedSessions.add(sessionId);
5038
+ const inProgressItems = todos.filter((t) => t.status === "in_progress").map((t) => ` - "${t.content}"`).join(`
5039
+ `);
5040
+ await client.session.promptAsync({
5041
+ path: { id: sessionId },
5042
+ body: {
5043
+ parts: [
5044
+ {
5045
+ type: "text",
5046
+ text: `${FINALIZE_TODOS_MARKER}
5047
+ You have finished your work but left these todos as in_progress:
5048
+ ${inProgressItems}
5049
+
5050
+ Use todowrite NOW to mark all of them as "completed" (or "cancelled" if abandoned). Do not do any other work — just update the todos and stop.`
5051
+ }
5052
+ ]
5053
+ }
5054
+ });
5055
+ log("[todo-finalize] Injected finalize prompt for in_progress todos", {
5056
+ sessionId,
5057
+ count: todos.filter((t) => t.status === "in_progress").length
5058
+ });
5059
+ }
5060
+ } catch (err) {
5061
+ log("[todo-finalize] Failed to check/finalize todos (non-fatal)", { sessionId, error: String(err) });
5062
+ }
5063
+ }
5064
+ }
5008
5065
  },
5009
5066
  "tool.execute.before": async (input, _output) => {
5010
5067
  const toolArgs = _output.args;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencode_weave/weave",
3
- "version": "0.7.0-preview.1",
3
+ "version": "0.7.0",
4
4
  "description": "Weave — lean OpenCode plugin with multi-agent orchestration",
5
5
  "author": "Weave",
6
6
  "license": "MIT",