@cortexkit/aft-opencode 0.55.1 → 0.56.1

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 (77) hide show
  1. package/dist/bg-notifications.d.ts +56 -10
  2. package/dist/bg-notifications.d.ts.map +1 -1
  3. package/dist/cancellation/effect-abort.d.ts +13 -0
  4. package/dist/cancellation/effect-abort.d.ts.map +1 -0
  5. package/dist/config.d.ts +85 -2
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/entry/server.js +45488 -0
  8. package/dist/index.d.ts +0 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +20437 -16564
  11. package/dist/lsp-cache.d.ts +5 -0
  12. package/dist/lsp-cache.d.ts.map +1 -1
  13. package/dist/lsp-github-install.d.ts +2 -1
  14. package/dist/lsp-github-install.d.ts.map +1 -1
  15. package/dist/permissions/v2.d.ts +51 -0
  16. package/dist/permissions/v2.d.ts.map +1 -0
  17. package/dist/plugin-version.d.ts +15 -0
  18. package/dist/plugin-version.d.ts.map +1 -0
  19. package/dist/rpc/contract.d.ts +2 -0
  20. package/dist/rpc/contract.d.ts.map +1 -0
  21. package/dist/rpc/register.d.ts +33 -0
  22. package/dist/rpc/register.d.ts.map +1 -0
  23. package/dist/shutdown-hooks.d.ts +13 -4
  24. package/dist/shutdown-hooks.d.ts.map +1 -1
  25. package/dist/subc-tool-schemas.d.ts +1 -1
  26. package/dist/subc-tool-schemas.d.ts.map +1 -1
  27. package/dist/tool-registration.d.ts +46 -1
  28. package/dist/tool-registration.d.ts.map +1 -1
  29. package/dist/tools/_shared.d.ts +2 -0
  30. package/dist/tools/_shared.d.ts.map +1 -1
  31. package/dist/tools/ast.d.ts.map +1 -1
  32. package/dist/tools/bash/executor.d.ts +10 -0
  33. package/dist/tools/bash/executor.d.ts.map +1 -0
  34. package/dist/tools/bash.d.ts +1 -1
  35. package/dist/tools/bash.d.ts.map +1 -1
  36. package/dist/tools/bash_watch.d.ts.map +1 -1
  37. package/dist/tools/definitions/v2.d.ts +57 -0
  38. package/dist/tools/definitions/v2.d.ts.map +1 -0
  39. package/dist/tools/hoisted/v2.d.ts +8 -0
  40. package/dist/tools/hoisted/v2.d.ts.map +1 -0
  41. package/dist/tools/hoisted.d.ts +2 -0
  42. package/dist/tools/hoisted.d.ts.map +1 -1
  43. package/dist/tools/inspect.d.ts.map +1 -1
  44. package/dist/tools/navigation.d.ts.map +1 -1
  45. package/dist/tools/permissions.d.ts +21 -3
  46. package/dist/tools/permissions.d.ts.map +1 -1
  47. package/dist/tools/reading.d.ts.map +1 -1
  48. package/dist/tools/semantic.d.ts.map +1 -1
  49. package/dist/tui/aft-rpc.d.ts +48 -0
  50. package/dist/tui/aft-rpc.d.ts.map +1 -0
  51. package/dist/tui/v2-status.d.ts +11 -0
  52. package/dist/tui/v2-status.d.ts.map +1 -0
  53. package/dist/wakes/runtime-consumer.d.ts +19 -0
  54. package/dist/wakes/runtime-consumer.d.ts.map +1 -0
  55. package/dist/wakes/session-delivery.d.ts +45 -0
  56. package/dist/wakes/session-delivery.d.ts.map +1 -0
  57. package/dist/workflow-hints.d.ts +12 -1
  58. package/dist/workflow-hints.d.ts.map +1 -1
  59. package/package.json +21 -16
  60. package/src/entry/server-runtime.mjs +109 -0
  61. package/src/entry/server.d.ts +10 -0
  62. package/src/entry/server.mjs +10 -0
  63. package/src/entry/tui.d.ts +8 -0
  64. package/src/entry/tui.mjs +9 -0
  65. package/src/tui/aft-rpc.ts +43 -0
  66. package/src/tui/index.tsx +3 -1
  67. package/src/tui/sidebar.tsx +1 -1
  68. package/src/tui/types/opencode-plugin-tui.d.ts +4 -3
  69. package/src/tui/v2-status.ts +56 -0
  70. package/src/tui/v2.tsx +209 -0
  71. package/src/tui-compiled/aft-rpc.ts +43 -0
  72. package/src/tui-compiled/index.tsx +3 -1
  73. package/src/tui-compiled/types/opencode-plugin-tui.d.ts +4 -3
  74. package/src/tui-compiled/v2-status.ts +56 -0
  75. package/src/tui-compiled/v2.tsx +181 -0
  76. package/dist/tools/refactoring.d.ts +0 -7
  77. package/dist/tools/refactoring.d.ts.map +0 -1
@@ -0,0 +1,48 @@
1
+ import { Schema } from "effect";
2
+ export declare const RpcSession: Schema.Struct<{
3
+ readonly sessionID: Schema.optional<Schema.String>;
4
+ }>;
5
+ export declare const IndexProgress: Schema.Struct<{
6
+ readonly index: Schema.Literals<readonly ["search", "semantic"]>;
7
+ readonly status: Schema.String;
8
+ readonly sessionID: Schema.optional<Schema.String>;
9
+ readonly stage: Schema.optional<Schema.NullOr<Schema.String>>;
10
+ readonly completed: Schema.optional<Schema.Number>;
11
+ readonly total: Schema.optional<Schema.Number>;
12
+ }>;
13
+ export type AftRpcSession = typeof RpcSession.Type;
14
+ export type AftIndexProgress = typeof IndexProgress.Type;
15
+ export declare const AftRpc: {
16
+ readonly id: "aft";
17
+ readonly methods: {
18
+ readonly getStatus: {
19
+ readonly input: Schema.Struct<{
20
+ readonly sessionID: Schema.optional<Schema.String>;
21
+ }>;
22
+ readonly output: Schema.$Record<Schema.String, Schema.Unknown>;
23
+ };
24
+ };
25
+ readonly events: {
26
+ readonly statusInvalidated: {
27
+ readonly schema: Schema.Struct<{
28
+ readonly sessionID: Schema.optional<Schema.String>;
29
+ }>;
30
+ };
31
+ readonly showStatusDialog: {
32
+ readonly schema: Schema.Struct<{
33
+ readonly sessionID: Schema.optional<Schema.String>;
34
+ }>;
35
+ };
36
+ readonly indexProgress: {
37
+ readonly schema: Schema.Struct<{
38
+ readonly index: Schema.Literals<readonly ["search", "semantic"]>;
39
+ readonly status: Schema.String;
40
+ readonly sessionID: Schema.optional<Schema.String>;
41
+ readonly stage: Schema.optional<Schema.NullOr<Schema.String>>;
42
+ readonly completed: Schema.optional<Schema.Number>;
43
+ readonly total: Schema.optional<Schema.Number>;
44
+ }>;
45
+ };
46
+ };
47
+ };
48
+ //# sourceMappingURL=aft-rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aft-rpc.d.ts","sourceRoot":"","sources":["../../src/tui/aft-rpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAahC,eAAO,MAAM,UAAU;;EAErB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;EAOxB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,UAAU,CAAC,IAAI,CAAC;AACnD,MAAM,MAAM,gBAAgB,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEzD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAajB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { AftStatusSnapshot } from "../shared/status";
2
+ export declare function formatAftStatusSegment(status: AftStatusSnapshot | null): string;
3
+ export type AftSidebarSummary = {
4
+ title: string;
5
+ version?: string;
6
+ search: string;
7
+ semantic: string;
8
+ health: string;
9
+ };
10
+ export declare function summarizeAftSidebar(status: AftStatusSnapshot | null): AftSidebarSummary;
11
+ //# sourceMappingURL=v2-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-status.d.ts","sourceRoot":"","sources":["../../src/tui/v2-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAa,MAAM,kBAAkB,CAAC;AAMrE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM,CAS/E;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAYF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,iBAAiB,CAoBvF"}
@@ -0,0 +1,19 @@
1
+ import type { BridgeOptions } from "@cortexkit/aft-bridge";
2
+ import type { V2ToolConsumers } from "../tools/definitions/v2.js";
3
+ import { type V2SessionAdmission } from "./session-delivery.js";
4
+ export interface V2WakeHostContext {
5
+ readonly session: V2SessionAdmission;
6
+ }
7
+ declare const sharedBridgeOptions: Pick<BridgeOptions, "onBashCompletion" | "onBashLongRunning">;
8
+ export interface V2RuntimeConsumer extends V2ToolConsumers {
9
+ readonly bridgeOptions: typeof sharedBridgeOptions;
10
+ dispose(): void;
11
+ }
12
+ /**
13
+ * Creates the V2 execution consumers for one OpenCode Location. The bridge owns
14
+ * one process-wide `onBashCompletion` callback, so it routes each notification
15
+ * by session to the delivery object owned by that Location's Effect scope.
16
+ */
17
+ export declare function createV2RuntimeConsumer(context: V2WakeHostContext): V2RuntimeConsumer;
18
+ export {};
19
+ //# sourceMappingURL=runtime-consumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-consumer.d.ts","sourceRoot":"","sources":["../../src/wakes/runtime-consumer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,aAAa,EACd,MAAM,uBAAuB,CAAC;AAK/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,KAAK,kBAAkB,EAAqB,MAAM,uBAAuB,CAAC;AAEnF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC;AA0DD,QAAA,MAAM,mBAAmB,EAAE,IAAI,CAAC,aAAa,EAAE,kBAAkB,GAAG,mBAAmB,CAGtF,CAAC;AAEF,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,QAAQ,CAAC,aAAa,EAAE,OAAO,mBAAmB,CAAC;IACnD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,CAwBrF"}
@@ -0,0 +1,45 @@
1
+ import { Effect } from "effect";
2
+ export interface V2SessionPromptInput {
3
+ readonly sessionID: string;
4
+ readonly text: string;
5
+ readonly delivery: "steer";
6
+ readonly metadata?: Readonly<Record<string, unknown>>;
7
+ readonly resume?: boolean;
8
+ }
9
+ export interface V2SessionSyntheticInput {
10
+ readonly sessionID: string;
11
+ readonly text: string;
12
+ readonly description?: string;
13
+ readonly metadata?: Readonly<Record<string, unknown>>;
14
+ readonly resume: false;
15
+ }
16
+ export interface V2SessionAdmission {
17
+ prompt(input: V2SessionPromptInput): Effect.Effect<unknown, unknown>;
18
+ synthetic(input: V2SessionSyntheticInput): Effect.Effect<unknown, unknown>;
19
+ }
20
+ export interface CompletionWake {
21
+ readonly sessionID: string;
22
+ readonly taskIDs: readonly string[];
23
+ readonly text: string;
24
+ readonly metadata?: Readonly<Record<string, unknown>>;
25
+ }
26
+ export interface StatusOnlyUpdate {
27
+ readonly sessionID: string;
28
+ readonly text: string;
29
+ readonly description?: string;
30
+ readonly metadata?: Readonly<Record<string, unknown>>;
31
+ }
32
+ /**
33
+ * Admit V2 session updates through the host's native inbox. Completion text is
34
+ * model-directed, while status records are synthetic and never resume a turn.
35
+ */
36
+ export declare class V2SessionDelivery {
37
+ private readonly session;
38
+ private readonly admittedCompletions;
39
+ private disposed;
40
+ constructor(session: V2SessionAdmission);
41
+ completion(input: CompletionWake): Effect.Effect<boolean, unknown>;
42
+ status(input: StatusOnlyUpdate): Effect.Effect<void, unknown>;
43
+ dispose(): void;
44
+ }
45
+ //# sourceMappingURL=session-delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-delivery.d.ts","sourceRoot":"","sources":["../../src/wakes/session-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACrE,SAAS,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IAIhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAS;gBAEI,OAAO,EAAE,kBAAkB;IAExD,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;IAuBlE,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;IAe7D,OAAO,IAAI,IAAI;CAKhB"}
@@ -12,7 +12,18 @@ export interface WorkflowHintsOpts {
12
12
  bashCompressionEnabled: boolean;
13
13
  /** Set of disabled tool names (after surface filtering). */
14
14
  disabledTools: Set<string>;
15
+ /** Whether the hashline `edit` arm is the one actually registered. */
16
+ hashlineEffective?: boolean;
15
17
  }
18
+ /**
19
+ * Routing rule for hashline sessions.
20
+ *
21
+ * Navigation tools return source that looks edit-ready but never publishes a
22
+ * snapshot, so an agent that inspects a symbol and then patches it is refused
23
+ * for a tag it believes it already has. Naming the tag-minting tools is the
24
+ * only way to distinguish "I have seen this code" from "I can address it".
25
+ */
26
+ export declare const HASHLINE_TAG_SOURCE_HINT = "**Hashline edit tags**: Only `read` (and accepted AFT `cat`/`head`/`tail` rewrites) mint hashline tags. `aft_zoom`, `aft_outline`, `grep`, `aft_search`, and conflict snippets do not. After navigation, call `read` on every file and range the patch addresses.";
16
27
  /**
17
28
  * Build the workflow hints block. Returns `null` when no hints are
18
29
  * applicable for the configured surface (e.g. `tool_surface: "minimal"`
@@ -26,7 +37,7 @@ export declare function buildWorkflowHints(opts: WorkflowHintsOpts): string | nu
26
37
  * Background-bash gating reads the resolved bash config so the graduated
27
38
  * `bash.background` setting controls whether the hint appears.
28
39
  */
29
- export declare function buildHintsFromConfig(config: AftConfig, disabledTools: Set<string>): string | null;
40
+ export declare function buildHintsFromConfig(config: AftConfig, disabledTools: Set<string>, hashlineEffective?: boolean): string | null;
30
41
  /**
31
42
  * Fold the hints block into a host `system[]` array in place.
32
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,2DAA2D;IAC3D,qBAAqB,EAAE,OAAO,CAAC;IAC/B,sCAAsC;IACtC,sBAAsB,EAAE,OAAO,CAAC;IAChC,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAgIzE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CASjG;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAQ9E"}
1
+ {"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,2DAA2D;IAC3D,qBAAqB,EAAE,OAAO,CAAC;IAC/B,sCAAsC;IACtC,sBAAsB,EAAE,OAAO,CAAC;IAChC,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAID;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,sQACgO,CAAC;AAEtQ;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CA8IzE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,iBAAiB,UAAQ,GACxB,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAQ9E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.55.1",
3
+ "version": "0.56.1",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
6
6
  "main": "dist/index.js",
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "files": [
14
14
  "dist",
15
+ "src/entry",
15
16
  "src/tui",
16
17
  "src/tui-compiled",
17
18
  "src/shared",
@@ -19,11 +20,12 @@
19
20
  "README.md"
20
21
  ],
21
22
  "scripts": {
22
- "build": "bun build src/index.ts --outdir dist --target node --format esm --external @opencode-ai/plugin --external @opencode-ai/sdk && tsc --emitDeclarationOnly && bun run build:tui",
23
+ "build": "bun build src/index.ts src/entry/server.mjs --outdir dist --target node --format esm --external effect && tsc --emitDeclarationOnly && bun run build:tui",
23
24
  "typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
24
25
  "pretest": "node -e \"if (process.env.CI !== 'true') { const { spawnSync } = require('node:child_process'); const result = spawnSync('cargo', ['build'], { cwd: '../..', stdio: 'inherit', shell: process.platform === 'win32' }); process.exit(result.status ?? 1); } else { console.log('Skipping cargo build in CI; workflow builds agent-file-tools before tests.'); }\"",
25
26
  "test": "bun test",
26
27
  "test:e2e": "bun test src/__tests__/e2e/",
28
+ "test:load-matrix": "bun test ./test/load-matrix/load-matrix.ts",
27
29
  "lint": "biome check src",
28
30
  "schema": "bun scripts/build-schema.ts",
29
31
  "build:tool-schemas": "bun run scripts/build-tool-schemas.ts",
@@ -34,25 +36,27 @@
34
36
  },
35
37
  "dependencies": {
36
38
  "@clack/prompts": "^1.6.0",
37
- "@cortexkit/aft-bridge": "0.55.1",
39
+ "@cortexkit/aft-bridge": "0.56.1",
38
40
  "@opentui/core": "0.4.3",
39
41
  "@opentui/solid": "0.4.3",
40
42
  "comment-json": "^4.6.2",
43
+ "effect": "4.0.0-rc.112",
41
44
  "solid-js": "1.9.12",
42
45
  "undici": "^7.25.0",
43
46
  "zod": "^4.4.3"
44
47
  },
45
48
  "optionalDependencies": {
46
- "@cortexkit/aft-darwin-arm64": "0.55.1",
47
- "@cortexkit/aft-darwin-x64": "0.55.1",
48
- "@cortexkit/aft-linux-arm64": "0.55.1",
49
- "@cortexkit/aft-linux-x64": "0.55.1",
50
- "@cortexkit/aft-win32-arm64": "0.55.1",
51
- "@cortexkit/aft-win32-x64": "0.55.1"
49
+ "@cortexkit/aft-darwin-arm64": "0.56.1",
50
+ "@cortexkit/aft-darwin-x64": "0.56.1",
51
+ "@cortexkit/aft-linux-arm64": "0.56.1",
52
+ "@cortexkit/aft-linux-x64": "0.56.1",
53
+ "@cortexkit/aft-win32-arm64": "0.56.1",
54
+ "@cortexkit/aft-win32-x64": "0.56.1"
52
55
  },
53
56
  "devDependencies": {
54
57
  "@opencode-ai/plugin": "^1.17.11",
55
58
  "@opencode-ai/sdk": "^1.17.11",
59
+ "@opencode/plugin": "2.0.3",
56
60
  "@types/node": "^22.0.0",
57
61
  "typescript": "^5.8.0"
58
62
  },
@@ -61,16 +65,17 @@
61
65
  "types": "./dist/index.d.ts",
62
66
  "import": "./dist/index.js"
63
67
  },
68
+ "./server": {
69
+ "types": "./src/entry/server.d.ts",
70
+ "import": "./dist/entry/server.js"
71
+ },
64
72
  "./tui": {
65
- "types": "./src/tui/index.tsx",
66
- "import": "./src/tui/entry.mjs"
73
+ "types": "./src/entry/tui.d.ts",
74
+ "import": "./src/entry/tui.mjs"
67
75
  }
68
76
  },
69
- "oc-plugin": [
70
- "server",
71
- "tui"
72
- ],
73
77
  "peerDependencies": {
74
- "@opencode-ai/plugin": ">=1.17.0"
78
+ "@opencode-ai/plugin": ">=0.0.0-beta-0",
79
+ "@opencode/plugin": "2.0.3"
75
80
  }
76
81
  }
@@ -0,0 +1,109 @@
1
+ import {
2
+ acquireBridge,
3
+ findBinary,
4
+ releaseBridge,
5
+ resolveCortexKitStorageRoot,
6
+ } from "@cortexkit/aft-bridge";
7
+ import { Effect } from "effect";
8
+
9
+ import {
10
+ buildConfigTierConfigureParams,
11
+ loadAftConfig,
12
+ resolveBridgePoolTransportOptions,
13
+ } from "../config.js";
14
+ import { resolvePluginVersion } from "../plugin-version.js";
15
+ import { registerAftRpc } from "../rpc/register.js";
16
+ import { hoistedV2ToolConsumers } from "../tools/hoisted/v2.js";
17
+ import { createV2RuntimeConsumer } from "../wakes/runtime-consumer.js";
18
+ import {
19
+ buildAftToolDefinitions,
20
+ openCodeHashlineEffective,
21
+ registerAftTools,
22
+ } from "../tool-registration.js";
23
+
24
+ const defaults = {
25
+ buildConfigureParams: buildConfigTierConfigureParams,
26
+ buildToolMap: buildAftToolDefinitions,
27
+ registerTools: registerAftTools,
28
+ registerRpc: registerAftRpc,
29
+ toolConsumers: (context) => ({
30
+ ...hoistedV2ToolConsumers(context),
31
+ ...createV2RuntimeConsumer(context),
32
+ }),
33
+ acquireBridge,
34
+ loadConfig: loadAftConfig,
35
+ releaseBridge,
36
+ resolveBinary: findBinary,
37
+ resolvePoolOptions: resolveBridgePoolTransportOptions,
38
+ resolveStorageRoot: resolveCortexKitStorageRoot,
39
+ resolveVersion: () => resolvePluginVersion(import.meta.url),
40
+ };
41
+
42
+ async function bootLocation(context, location, dependencies) {
43
+ const directory = location.directory;
44
+ const config = dependencies.loadConfig(directory);
45
+ if (config.enabled === false) return undefined;
46
+
47
+ const storageDir = dependencies.resolveStorageRoot();
48
+ const configOverrides = dependencies.buildConfigureParams(directory, {
49
+ bash_permissions: true,
50
+ harness: "opencode",
51
+ storage_dir: storageDir,
52
+ });
53
+ const binaryPath = await dependencies.resolveBinary(dependencies.resolveVersion());
54
+ const canonicalDirectory = location.project?.canonical ?? directory;
55
+ const consumers = dependencies.toolConsumers(context);
56
+ const pool = await dependencies.acquireBridge(canonicalDirectory, {
57
+ harness: "opencode",
58
+ binaryPath,
59
+ poolOptions: {
60
+ ...dependencies.resolvePoolOptions(config),
61
+ ...consumers.bridgeOptions,
62
+ },
63
+ configOverrides,
64
+ subcConnectionFile: config.subc?.connection_file,
65
+ });
66
+ const toolContext = {
67
+ pool,
68
+ client: context,
69
+ config,
70
+ hashlineEffective: openCodeHashlineEffective(config),
71
+ storageDir,
72
+ isProjectEnabled: (projectRoot) =>
73
+ projectRoot === directory ? true : dependencies.loadConfig(projectRoot).enabled !== false,
74
+ };
75
+ const tools = dependencies.buildToolMap(toolContext, config);
76
+ return { consumers, pool, tools };
77
+ }
78
+
79
+ export function makeServerEffect(overrides = {}) {
80
+ const dependencies = { ...defaults, ...overrides };
81
+
82
+ return (context) => {
83
+ // The V2 host already resolved the Location before invoking the plugin. Capture
84
+ // it now so every registration and transport route belongs to that exact scope.
85
+ const location = context.location;
86
+
87
+ return Effect.gen(function* () {
88
+ const runtime = yield* Effect.promise(() => bootLocation(context, location, dependencies));
89
+ if (!runtime) return;
90
+
91
+ yield* Effect.addFinalizer(() =>
92
+ Effect.promise(async () => {
93
+ runtime.consumers.dispose?.();
94
+ await dependencies.releaseBridge(runtime.pool);
95
+ }),
96
+ );
97
+ const rpc = yield* dependencies.registerRpc(context, location, runtime.pool);
98
+ yield* Effect.addFinalizer(() => Effect.promise(() => rpc.dispose()));
99
+ yield* dependencies.registerTools(
100
+ context,
101
+ location,
102
+ runtime.tools,
103
+ runtime.consumers,
104
+ );
105
+ });
106
+ };
107
+ }
108
+
109
+ export const serverEffect = makeServerEffect();
@@ -0,0 +1,10 @@
1
+ import type { Plugin as V1Plugin } from "@opencode-ai/plugin";
2
+
3
+ interface ServerEntry {
4
+ readonly id: string;
5
+ readonly server: V1Plugin;
6
+ readonly effect: (context: unknown) => unknown;
7
+ }
8
+
9
+ declare const entry: ServerEntry;
10
+ export default entry;
@@ -0,0 +1,10 @@
1
+ import server from "../index.js";
2
+ import { serverEffect as effect } from "./server-runtime.mjs";
3
+
4
+ const id = "aft-opencode";
5
+
6
+ export default {
7
+ id,
8
+ server,
9
+ effect,
10
+ };
@@ -0,0 +1,8 @@
1
+ interface TuiEntry {
2
+ readonly id: string;
3
+ readonly tui: (api: unknown, options?: unknown, meta?: unknown) => Promise<void>;
4
+ readonly setup: (context: unknown) => Promise<void>;
5
+ }
6
+
7
+ declare const entry: TuiEntry;
8
+ export default entry;
@@ -0,0 +1,9 @@
1
+ import legacy from "../tui/entry.mjs";
2
+
3
+ const setup = (...args) => legacy.setup(...args);
4
+
5
+ export default {
6
+ id: legacy.id,
7
+ tui: legacy.tui,
8
+ setup,
9
+ };
@@ -0,0 +1,43 @@
1
+ import { Schema } from "effect";
2
+
3
+ /**
4
+ * The V2 host's Rpc.define returns its input after checking reserved custom
5
+ * error names. AFT defines no custom RPC errors, so this local identity has the
6
+ * same result and also loads on V1, where @opencode-ai/schema is unavailable.
7
+ */
8
+ const Rpc = {
9
+ define<const Definition>(definition: Definition): Definition {
10
+ return definition;
11
+ },
12
+ };
13
+
14
+ export const RpcSession = Schema.Struct({
15
+ sessionID: Schema.optional(Schema.String),
16
+ });
17
+
18
+ export const IndexProgress = Schema.Struct({
19
+ index: Schema.Literals(["search", "semantic"]),
20
+ status: Schema.String,
21
+ sessionID: Schema.optional(Schema.String),
22
+ stage: Schema.optional(Schema.NullOr(Schema.String)),
23
+ completed: Schema.optional(Schema.Number),
24
+ total: Schema.optional(Schema.Number),
25
+ });
26
+
27
+ export type AftRpcSession = typeof RpcSession.Type;
28
+ export type AftIndexProgress = typeof IndexProgress.Type;
29
+
30
+ export const AftRpc = Rpc.define({
31
+ id: "aft",
32
+ methods: {
33
+ getStatus: {
34
+ input: RpcSession,
35
+ output: Schema.Record(Schema.String, Schema.Unknown),
36
+ },
37
+ },
38
+ events: {
39
+ statusInvalidated: { schema: RpcSession },
40
+ showStatusDialog: { schema: RpcSession },
41
+ indexProgress: { schema: IndexProgress },
42
+ },
43
+ });
package/src/tui/index.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  /** @jsxImportSource @opentui/solid */
2
2
  // @ts-nocheck
3
3
 
4
- import type { TuiPlugin, TuiPluginApi, TuiThemeCurrent } from "@opencode-ai/plugin/tui";
4
+ import type { TuiPlugin, TuiPluginApi, TuiThemeCurrent } from "@opencode/plugin/tui";
5
5
  import { createMemo, createSignal, onCleanup } from "solid-js";
6
6
 
7
7
  import { version as packageVersion } from "../../package.json";
@@ -29,6 +29,7 @@ import {
29
29
  resolveTuiStorageDir,
30
30
  shouldSuppressUninitializedDowngrade,
31
31
  } from "./sidebar";
32
+ import { setupV2Tui } from "./v2";
32
33
 
33
34
  // The TUI talks to the server plugin via AftRpcClient. The client reads the
34
35
  // JSON port file written by AftRpcServer ({ port, token }) and includes that
@@ -803,4 +804,5 @@ const id = "aft-opencode";
803
804
  export default {
804
805
  id,
805
806
  tui,
807
+ setup: setupV2Tui,
806
808
  };
@@ -7,7 +7,7 @@
7
7
  // current without polling.
8
8
 
9
9
  import { canonicalizeProjectRoot } from "@cortexkit/aft-bridge";
10
- import type { TuiPluginApi, TuiSlotPlugin, TuiThemeCurrent } from "@opencode-ai/plugin/tui";
10
+ import type { TuiPluginApi, TuiSlotPlugin, TuiThemeCurrent } from "@opencode/plugin/tui";
11
11
  import { createEffect, createMemo, createSignal, on, onCleanup } from "solid-js";
12
12
  import { AftRpcClient } from "../shared/rpc-client";
13
13
  import {
@@ -1,7 +1,8 @@
1
- // Type declarations for @opencode-ai/plugin/tui
2
- // These types are not yet exported by the installed @opencode-ai/plugin package
1
+ // Compatibility declarations for the GA @opencode/plugin/tui entrypoint.
2
+ // AFT's shared TUI still consumes the legacy callback surface while its V2 setup
3
+ // export uses the GA setup context directly.
3
4
 
4
- declare module "@opencode-ai/plugin/tui" {
5
+ declare module "@opencode/plugin/tui" {
5
6
  import type {
6
7
  createOpencodeClient as createOpencodeClientV2,
7
8
  Event as TuiEvent,
@@ -0,0 +1,56 @@
1
+ import type { AftStatusSnapshot, StatusBar } from "../shared/status";
2
+
3
+ function count(value: number | undefined): string {
4
+ return value === undefined ? "?" : String(value);
5
+ }
6
+
7
+ export function formatAftStatusSegment(status: AftStatusSnapshot | null): string {
8
+ const bar = status?.status_bar;
9
+ if (!bar) return "AFT starting…";
10
+ const stale = bar.tier2_stale ? "~" : "";
11
+ return (
12
+ `AFT E${count(bar.errors)} W${count(bar.warnings)} | ` +
13
+ `${stale}D${count(bar.dead_code)} U${count(bar.unused_exports)} ` +
14
+ `C${count(bar.duplicates)} | T${count(bar.todos)}`
15
+ );
16
+ }
17
+
18
+ export type AftSidebarSummary = {
19
+ title: string;
20
+ version?: string;
21
+ search: string;
22
+ semantic: string;
23
+ health: string;
24
+ };
25
+
26
+ function healthSummary(bar: StatusBar | undefined): string {
27
+ if (!bar) return "health pending";
28
+ const stale = bar.tier2_stale ? "~" : "";
29
+ return (
30
+ `E${count(bar.errors)} W${count(bar.warnings)} ` +
31
+ `${stale}D${count(bar.dead_code)} U${count(bar.unused_exports)} ` +
32
+ `C${count(bar.duplicates)} T${count(bar.todos)}`
33
+ );
34
+ }
35
+
36
+ export function summarizeAftSidebar(status: AftStatusSnapshot | null): AftSidebarSummary {
37
+ if (!status || status.cache_role === "not_initialized") {
38
+ return {
39
+ title: "AFT",
40
+ search: "not initialized",
41
+ semantic: "not initialized",
42
+ health: "health pending",
43
+ };
44
+ }
45
+
46
+ const semantic = status.semantic_index.stage
47
+ ? `${status.semantic_index.status} (${status.semantic_index.stage})`
48
+ : status.semantic_index.status;
49
+ return {
50
+ title: status.degraded ? "AFT · DEGRADED" : "AFT",
51
+ version: status.version || undefined,
52
+ search: status.search_index.status,
53
+ semantic,
54
+ health: healthSummary(status.status_bar),
55
+ };
56
+ }