@weaveio/weave-adapter-opencode 0.0.0-preview-20260708084849

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.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Projection Helpers — adapter-internal shared utilities.
3
+ *
4
+ * Provides the two helpers that are shared across the OpenCode adapter's
5
+ * projection modules:
6
+ *
7
+ * - `buildProjectEffect` — builds the adapter-owned `projectEffect` callback
8
+ * that calls `adapter.spawnSubagent` for each `DispatchAgentEffect`.
9
+ * - `deriveRunWorkflowResult` — maps `ExecutionStartedData`-shaped data to
10
+ * the adapter-owned `RunWorkflowResult` discriminated union.
11
+ *
12
+ * ## Boundary rule
13
+ *
14
+ * This module is adapter-internal. It must not be imported by engine packages.
15
+ * It exists solely to eliminate duplication across `run-workflow.ts`,
16
+ * `start-plan-execution.ts`, and `runtime-command-projection.ts`.
17
+ *
18
+ * @see packages/adapters/opencode/src/run-workflow.ts
19
+ * @see packages/adapters/opencode/src/start-plan-execution.ts
20
+ * @see packages/adapters/opencode/src/runtime-command-projection.ts
21
+ * @see docs/adapter-boundary.md
22
+ */
23
+ import type { DispatchAgentEffect, WorkflowRunnerError } from "@weaveio/weave-engine";
24
+ import type { ResultAsync } from "neverthrow";
25
+ import type { OpenCodeAdapter } from "./adapter.js";
26
+ import type { RunWorkflowResult } from "./run-workflow.js";
27
+ /**
28
+ * Build the adapter-owned `projectEffect` callback for engine operations.
29
+ *
30
+ * The callback calls `adapter.spawnSubagent` for each `DispatchAgentEffect`
31
+ * emitted by the engine's workflow runner. On failure, maps
32
+ * `OpenCodeAdapterError` to `WorkflowRunnerError` so the engine can propagate
33
+ * it as a typed `projection_error`.
34
+ *
35
+ * This is adapter-owned — the engine never calls `spawnSubagent` directly.
36
+ *
37
+ * @param adapter - The OpenCode adapter instance.
38
+ * @returns A `projectEffect` callback suitable for engine operation calls.
39
+ */
40
+ export declare function buildProjectEffect(adapter: OpenCodeAdapter): (effect: DispatchAgentEffect) => ResultAsync<void, WorkflowRunnerError>;
41
+ /**
42
+ * Derive a `RunWorkflowResult` from the engine's `ExecutionStartedData`.
43
+ *
44
+ * `ExecutionStartedData.effects` carries all lifecycle effects emitted during
45
+ * the run. We derive:
46
+ * - `status`: "paused" if a `pause-execution` effect is present, else "completed".
47
+ * - `stepsDispatched`: count of `dispatch-agent` effects.
48
+ * - `appliedEffects`: all effects (forwarded as-is).
49
+ *
50
+ * @param data - Execution data with a `workflowInstanceId` and `effects` array.
51
+ * @returns A normalized `RunWorkflowResult`.
52
+ */
53
+ export declare function deriveRunWorkflowResult(data: {
54
+ readonly workflowInstanceId: string;
55
+ readonly effects: readonly {
56
+ readonly kind: string;
57
+ }[];
58
+ }): RunWorkflowResult;
59
+ //# sourceMappingURL=projection-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection-helpers.d.ts","sourceRoot":"","sources":["../src/projection-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAQ3D;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,GACvB,CAAC,MAAM,EAAE,mBAAmB,KAAK,WAAW,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAkBzE;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxD,GAAG,iBAAiB,CAYpB"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Adapter-local reconciliation logic for Weave-managed OpenCode agents.
3
+ *
4
+ * This module encapsulates the `list existing → reconcile decision →
5
+ * create/update call` flow that `spawnSubagent()` uses to materialize a Weave
6
+ * agent into a running OpenCode instance.
7
+ *
8
+ * ## Reconciliation flow
9
+ *
10
+ * ```
11
+ * 1. listAgents() — fetch the current agent list from OpenCode
12
+ * 2. find by name — look for an existing agent whose name matches
13
+ * descriptor.name (the Canonical Agent Name)
14
+ * 3. ownership check — if found, verify the agent is Weave-managed
15
+ * (presence of WEAVE_OWNERSHIP_TAG in description)
16
+ * 4. create or update — call createAgent() for new agents, updateAgent()
17
+ * for existing Weave-managed agents
18
+ * 5. collision error — return ReconcileCollisionError when a same-named
19
+ * foreign agent is found (no forced takeover)
20
+ * ```
21
+ *
22
+ * ## Ownership marker
23
+ *
24
+ * Weave marks every agent it creates by embedding `WEAVE_OWNERSHIP_TAG` in the
25
+ * agent's `description` field. This is a lightweight, human-readable signal
26
+ * that lets the reconciler distinguish Weave-managed agents from manually
27
+ * created ones without requiring a separate metadata store.
28
+ *
29
+ * The tag is appended to the description when the agent is first created and
30
+ * checked on every subsequent reconciliation pass. Agents without the tag are
31
+ * treated as foreign and protected from overwrite.
32
+ *
33
+ * ## First-slice constraints
34
+ *
35
+ * - Upsert-only: no automatic delete, prune, or forced takeover.
36
+ * - Collision errors are returned as typed `Result` values — callers decide
37
+ * how to surface them.
38
+ *
39
+ * Boundary rule: this module imports SDK types only through `./sdk-types` and
40
+ * the client facade only through `./opencode-client`. It must not import
41
+ * directly from `@opencode-ai/sdk`.
42
+ */
43
+ import { type ResultAsync } from "neverthrow";
44
+ import type { OpenCodeClientFacade } from "./opencode-client.js";
45
+ import type { OpenCodeAgent, OpenCodeAgentConfig } from "./sdk-types.js";
46
+ /**
47
+ * Ownership tag embedded in the `description` of every Weave-managed agent.
48
+ *
49
+ * The tag is a short, human-readable string that signals to the reconciler
50
+ * (and to human operators) that the agent was created by Weave. It is
51
+ * intentionally visible in the OpenCode UI so users know which agents are
52
+ * managed by Weave.
53
+ */
54
+ export declare const WEAVE_OWNERSHIP_TAG = "[weave-managed]";
55
+ /**
56
+ * Discriminated union of errors that `reconcileAgent` can return.
57
+ */
58
+ export type ReconcileAgentError = {
59
+ /** Listing the current OpenCode agents failed. */
60
+ type: "ListAgentsError";
61
+ message: string;
62
+ cause?: unknown;
63
+ } | {
64
+ /** Creating a new agent in OpenCode failed. */
65
+ type: "CreateAgentError";
66
+ agentName: string;
67
+ message: string;
68
+ cause?: unknown;
69
+ } | {
70
+ /** Updating an existing Weave-managed agent in OpenCode failed. */
71
+ type: "UpdateAgentError";
72
+ agentName: string;
73
+ message: string;
74
+ cause?: unknown;
75
+ } | {
76
+ /**
77
+ * A same-named agent exists in OpenCode but is not Weave-managed.
78
+ * Weave refuses to overwrite it without explicit ownership.
79
+ */
80
+ type: "CollisionError";
81
+ agentName: string;
82
+ message: string;
83
+ };
84
+ /**
85
+ * The decision produced by `classifyExistingAgent`.
86
+ *
87
+ * - `"create"` — no existing agent with this name; create a new one.
88
+ * - `"update"` — an existing Weave-managed agent was found; update it.
89
+ * - `"collision"` — a same-named foreign agent was found; refuse to overwrite.
90
+ */
91
+ export type ReconcileDecision = "create" | "update" | "collision";
92
+ /**
93
+ * Classifies the reconciliation decision for a given agent name against the
94
+ * current OpenCode agent list.
95
+ *
96
+ * @param agentName - The Canonical Agent Name to look up.
97
+ * @param existingAgents - The current list of agents from OpenCode.
98
+ * @returns The reconciliation decision.
99
+ */
100
+ export declare function classifyExistingAgent(agentName: string, existingAgents: OpenCodeAgent[]): ReconcileDecision;
101
+ /**
102
+ * Returns a copy of `config` with `WEAVE_OWNERSHIP_TAG` appended to the
103
+ * `description` field.
104
+ *
105
+ * The tag is appended only when it is not already present, so calling this
106
+ * function on an already-tagged config is idempotent.
107
+ *
108
+ * @param config - The translated OpenCode agent config.
109
+ * @returns A new config object with the ownership tag in `description`.
110
+ */
111
+ export declare function tagWithOwnership(config: OpenCodeAgentConfig): OpenCodeAgentConfig;
112
+ /**
113
+ * Reconciles a translated OpenCode agent config against the current OpenCode
114
+ * agent list, then creates or updates the agent via the injected client.
115
+ *
116
+ * ## Flow
117
+ *
118
+ * 1. Call `client.listAgents()` to fetch the current agent list.
119
+ * 2. Classify the reconciliation decision using `classifyExistingAgent`.
120
+ * 3. Tag the config with `WEAVE_OWNERSHIP_TAG` before writing.
121
+ * 4. Call `client.createAgent()` or `client.updateAgent()` based on the
122
+ * decision.
123
+ * 5. Return `err(CollisionError)` when a foreign agent blocks the write.
124
+ *
125
+ * @param agentName - The Canonical Agent Name (matches `descriptor.name`).
126
+ * @param config - The translated OpenCode agent config to materialize.
127
+ * @param client - The injected `OpenCodeClientFacade` to use for SDK calls.
128
+ * @returns `ok(void)` on success, or `err(ReconcileAgentError)` on failure.
129
+ */
130
+ export declare function reconcileAgent(agentName: string, config: OpenCodeAgentConfig, client: OpenCodeClientFacade): ResultAsync<void, ReconcileAgentError>;
131
+ //# sourceMappingURL=reconcile-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile-agent.d.ts","sourceRoot":"","sources":["../src/reconcile-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAMzE;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAMrD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IACE,kDAAkD;IAClD,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACD;IACE,+CAA+C;IAC/C,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACD;IACE,mEAAmE;IACnE,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACD;IACE;;;OAGG;IACH,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAMN;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElE;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,aAAa,EAAE,GAC9B,iBAAiB,CASnB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,mBAAmB,GAC1B,mBAAmB,CAUrB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,oBAAoB,GAC3B,WAAW,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAkCxC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Explicit named-workflow execution loop for the OpenCode adapter.
3
+ *
4
+ * `runWorkflow` is the adapter-owned helper for **explicit named-workflow
5
+ * execution** — the path where a caller (command handler, script, or
6
+ * user-authorized trigger) names a specific workflow declared in
7
+ * `.weave/config.weave` and requests that it run end-to-end.
8
+ *
9
+ * This is distinct from ordinary Loom-led usage (the `/weave:start` path),
10
+ * which is plan-first and does not require the caller to name a workflow.
11
+ * `runWorkflow` is never called from idle hooks, session events, or
12
+ * continuation hooks — it requires explicit, user-authorized invocation.
13
+ *
14
+ * ## Delegation to shared engine operation
15
+ *
16
+ * `runWorkflow` delegates lifecycle semantics to the engine's reusable
17
+ * `runNamedWorkflow` command operation. The adapter supplies a `projectEffect`
18
+ * callback that calls `adapter.spawnSubagent` for each `DispatchAgentEffect`
19
+ * emitted by the engine. The engine never applies harness-specific behavior.
20
+ *
21
+ * ## Execution lifecycle (engine-owned)
22
+ *
23
+ * 1. `startExecution` — acquire lease, create/update WorkflowInstance
24
+ * 2. `dispatchStep` — resolve next step, emit DispatchAgentEffect
25
+ * 3. Project effects — call `projectEffect` (→ `adapter.spawnSubagent`)
26
+ * 4. `completeStep` — record step completion, advance to next step or finish
27
+ *
28
+ * The loop continues until a `complete-execution` or `pause-execution` effect
29
+ * is emitted, or until an error is returned.
30
+ *
31
+ * Boundary rule: this module calls the engine's `runNamedWorkflow` operation
32
+ * and the adapter interface. It must not import directly from `@opencode-ai/sdk`.
33
+ *
34
+ * @see docs/adapter-boundary.md — Execution Lifecycle Surface section
35
+ * @see start-plan-execution.ts — the `/weave:start` ordinary-usage path
36
+ * @see packages/engine/src/runtime-command-operations/run-named-workflow.ts
37
+ */
38
+ import type { WeaveConfig } from "@weaveio/weave-core";
39
+ import type { LifecycleEffect, LifecycleError, PlanStateProvider, RuntimeStore } from "@weaveio/weave-engine";
40
+ import type { ResultAsync } from "neverthrow";
41
+ import type { OpenCodeAdapter } from "./index.js";
42
+ /**
43
+ * Discriminated union of errors that `runWorkflow` can return.
44
+ */
45
+ export type RunWorkflowError = {
46
+ readonly type: "LifecycleError";
47
+ readonly cause: LifecycleError;
48
+ } | {
49
+ readonly type: "WorkflowNotFound";
50
+ readonly workflowName: string;
51
+ } | {
52
+ readonly type: "MaxStepsExceeded";
53
+ readonly maxSteps: number;
54
+ };
55
+ /**
56
+ * Input for `runWorkflow`.
57
+ *
58
+ * Provides everything the execution loop needs:
59
+ * - `config` — the full WeaveConfig containing workflow definitions
60
+ * - `workflowName` — the name of the workflow to execute
61
+ * - `goal` — human-readable goal for this execution instance
62
+ * - `slug` — URL-safe slug derived from the goal
63
+ * - `adapter` — the OpenCode adapter instance (for `spawnSubagent`)
64
+ * - `store` — the Runtime Store (defaults to a fresh InMemoryRuntimeStore)
65
+ * - `planStateProvider` — optional plan state provider for plan_created/plan_complete steps
66
+ * - `ownerId` — owner identifier for the execution lease (defaults to "run-workflow")
67
+ * - `maxSteps` — safety cap on the number of steps dispatched (default: 100)
68
+ */
69
+ export interface RunWorkflowInput {
70
+ /** Full WeaveConfig containing workflow definitions. */
71
+ readonly config: WeaveConfig;
72
+ /** Name of the workflow to execute (must exist in `config.workflows`). */
73
+ readonly workflowName: string;
74
+ /** Human-readable goal for this execution instance. */
75
+ readonly goal: string;
76
+ /** URL-safe slug for this execution instance. */
77
+ readonly slug: string;
78
+ /** OpenCode adapter instance — `spawnSubagent` is called for each DispatchAgentEffect. */
79
+ readonly adapter: OpenCodeAdapter;
80
+ /** Runtime Store instance. Defaults to a fresh InMemoryRuntimeStore when omitted. */
81
+ readonly store?: RuntimeStore;
82
+ /** Optional plan state provider for plan_created/plan_complete completion methods. */
83
+ readonly planStateProvider?: PlanStateProvider;
84
+ /** Owner identifier for the execution lease. Defaults to "run-workflow". */
85
+ readonly ownerId?: string;
86
+ /** Safety cap on the number of steps dispatched. Defaults to 100. */
87
+ readonly maxSteps?: number;
88
+ }
89
+ /**
90
+ * Output from `runWorkflow`.
91
+ *
92
+ * Reports the final status of the execution and the effects that were applied.
93
+ */
94
+ export interface RunWorkflowResult {
95
+ /** The workflow instance ID that was created. */
96
+ readonly workflowInstanceId: string;
97
+ /** All lifecycle effects that were applied during the execution. */
98
+ readonly appliedEffects: readonly LifecycleEffect[];
99
+ /** Final execution status. */
100
+ readonly status: "completed" | "paused";
101
+ /** Number of steps that were dispatched. */
102
+ readonly stepsDispatched: number;
103
+ }
104
+ /**
105
+ * Execute a named workflow end-to-end using the engine's lifecycle surface.
106
+ *
107
+ * This is the **explicit named-workflow execution** entry point. The caller
108
+ * must supply the name of a workflow declared in `config.workflows`. This
109
+ * function is not the ordinary Loom-led path — for that, see
110
+ * `startPlanExecution` (the `/weave:start` delivery path).
111
+ *
112
+ * `runWorkflow` must be called by a user-authorized trigger (command handler,
113
+ * script, or UI action). It is never wired to idle hooks, session events, or
114
+ * continuation hooks.
115
+ *
116
+ * ## Delegation
117
+ *
118
+ * Lifecycle semantics are delegated to the engine's `runNamedWorkflow`
119
+ * command operation. The adapter supplies a `projectEffect` callback that
120
+ * calls `adapter.spawnSubagent` for each `DispatchAgentEffect`. The engine
121
+ * never applies harness-specific behavior.
122
+ *
123
+ * @param input - Named-workflow execution parameters.
124
+ * @returns `ok(RunWorkflowResult)` on success, or `err(RunWorkflowError)`.
125
+ */
126
+ export declare function runWorkflow(input: RunWorkflowInput): ResultAsync<RunWorkflowResult, RunWorkflowError>;
127
+ //# sourceMappingURL=run-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-workflow.d.ts","sourceRoot":"","sources":["../src/run-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAEV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,YAAY,EACb,MAAM,uBAAuB,CAAC;AAM/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAYlD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAMrE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,qFAAqF;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,sFAAsF;IACtF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;IACpD,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IACxC,4CAA4C;IAC5C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAmDD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,gBAAgB,GACtB,WAAW,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAqClD"}