@cortexkit/aft-opencode 0.45.1 → 0.47.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.
- package/dist/bash-wait-detach.d.ts +5 -0
- package/dist/bash-wait-detach.d.ts.map +1 -0
- package/dist/config.d.ts +3 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2304 -1133
- package/dist/logger.d.ts.map +1 -1
- package/dist/lsp-auto-install.d.ts +8 -3
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/lsp-github-install.d.ts +2 -0
- package/dist/lsp-github-install.d.ts.map +1 -1
- package/dist/shared/ignored-message.d.ts +9 -7
- package/dist/shared/ignored-message.d.ts.map +1 -1
- package/dist/shared/rpc-client.d.ts +23 -1
- package/dist/shared/rpc-client.d.ts.map +1 -1
- package/dist/subc-tool-schemas.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/permissions.d.ts +8 -0
- package/dist/tools/permissions.d.ts.map +1 -1
- package/dist/tools/semantic.d.ts.map +1 -1
- package/dist/tui/notification-socket.d.ts.map +1 -1
- package/package.json +17 -14
- package/src/logger.ts +5 -6
- package/src/shared/ignored-message.ts +38 -19
- package/src/shared/rpc-client.ts +116 -4
- package/src/tui/entry.mjs +16 -0
- package/src/tui/notification-socket.ts +28 -1
- package/src/tui-compiled/badge-contrast.ts +43 -0
- package/src/tui-compiled/index.tsx +992 -0
- package/src/tui-compiled/notification-socket.ts +448 -0
- package/src/tui-compiled/preferences.ts +243 -0
- package/src/tui-compiled/sidebar.tsx +936 -0
- package/src/tui-compiled/types/opencode-plugin-tui.d.ts +239 -0
- package/dist/tui.js +0 -13462
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAsEA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEzD;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3D;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE1D;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEjG;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEhG;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEjG;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;iBACV,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;kBAGpC,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;mBAGpC,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;;CAIrD,CAAC"}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* the install. This matches OpenCode's "may need restart" UX and
|
|
28
28
|
* avoids mid-session bridge restarts.
|
|
29
29
|
*/
|
|
30
|
+
import { type AftTransportPool } from "@cortexkit/aft-bridge";
|
|
30
31
|
/** Per-call configuration drawn from `lsp.*` plugin config. */
|
|
31
32
|
export interface AutoInstallConfig {
|
|
32
33
|
/** Master enable. Default: true. */
|
|
@@ -69,6 +70,8 @@ export interface AutoInstallResult {
|
|
|
69
70
|
* the array shared with the synchronous return value).
|
|
70
71
|
*/
|
|
71
72
|
installsComplete: Promise<void>;
|
|
73
|
+
/** Re-scan the cache after background installs settle. */
|
|
74
|
+
getCachedBinDirs: () => string[];
|
|
72
75
|
}
|
|
73
76
|
export declare function abortInFlightAutoInstalls(): Promise<void>;
|
|
74
77
|
/**
|
|
@@ -106,9 +109,11 @@ export declare function ensureInstallAnchor(cwd: string): void;
|
|
|
106
109
|
* have an installed binary AND kicks off background installs for missing
|
|
107
110
|
* packages relevant to this project.
|
|
108
111
|
*
|
|
109
|
-
* Caller passes `cachedBinDirs` to Rust as `lsp_paths_extra`.
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
+
* Caller passes `cachedBinDirs` to Rust as `lsp_paths_extra`. When a background
|
|
113
|
+
* install settles, the plugin calls `getCachedBinDirs()` to refresh the list and
|
|
114
|
+
* reconfigures live bridges; future bridges use the pool override.
|
|
112
115
|
*/
|
|
113
116
|
export declare function runAutoInstall(projectRoot: string, config: AutoInstallConfig, fetchImpl?: typeof fetch): AutoInstallResult;
|
|
117
|
+
/** Apply newly discovered cache paths to both future and live bridge config. */
|
|
118
|
+
export declare function pushLspPathsAfterAutoInstall(pool: Pick<AftTransportPool, "setConfigureOverride" | "reconfigure">, projectRoot: string, cachedBinDirs: readonly string[]): Promise<void>;
|
|
114
119
|
//# sourceMappingURL=lsp-auto-install.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;
|
|
1
|
+
{"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAeH,OAAO,EAAE,KAAK,gBAAgB,EAA2B,MAAM,uBAAuB,CAAC;AAuBvF,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,kGAAkG;IAClG,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;;;OAOG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;;;;;;OASG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,0DAA0D;IAC1D,gBAAgB,EAAE,MAAM,MAAM,EAAE,CAAC;CAClC;AA8DD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AA4DD;;;;;;;;;;;;;;;;GAgBG;AACH;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAYrD;AA8TD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CA4EnB;AAED,gFAAgF;AAChF,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,sBAAsB,GAAG,aAAa,CAAC,EACpE,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -84,6 +84,8 @@ export interface GithubAutoInstallResult {
|
|
|
84
84
|
* Plugin startup ignores this; tests await it.
|
|
85
85
|
*/
|
|
86
86
|
installsComplete: Promise<void>;
|
|
87
|
+
/** Re-scan the cache after background installs settle. */
|
|
88
|
+
getCachedBinDirs: () => string[];
|
|
87
89
|
}
|
|
88
90
|
export declare function abortInFlightGithubInstalls(): Promise<void>;
|
|
89
91
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lsp-github-install.d.ts","sourceRoot":"","sources":["../src/lsp-github-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAuCH,OAAO,EACL,KAAK,IAAI,EACT,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAiC/B,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAG/E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CASrF;AAsDD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAoVD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAgBrD;AAED,iBAAe,YAAY,CACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,OAAO,KAAK,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAuDf;AA6BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CA0E5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CA4BtF;AA6WD,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;OAIG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"lsp-github-install.d.ts","sourceRoot":"","sources":["../src/lsp-github-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAuCH,OAAO,EACL,KAAK,IAAI,EACT,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAiC/B,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAG/E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CASrF;AAsDD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAoVD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAgBrD;AAED,iBAAe,YAAY,CACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,OAAO,KAAK,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAuDf;AA6BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CA0E5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CA4BtF;AA6WD,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;OAIG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,0DAA0D;IAC1D,gBAAgB,EAAE,MAAM,MAAM,EAAE,CAAC;CAClC;AAsBD,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,EACpC,MAAM,EAAE,mBAAmB,EAC3B,SAAS,GAAE,OAAO,KAAa,GAC9B,uBAAuB,CAkGzB;AAID;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAyC9E;AAID;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,IAAI,EACT,wBAAwB,IAAI,mCAAmC,EAC/D,kBAAkB,EAClB,YAAY,IAAI,uBAAuB,EACvC,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,uBAAuB,IAAI,8BAA8B,GAC1D,CAAC"}
|
|
@@ -7,13 +7,15 @@
|
|
|
7
7
|
* it shows in the right place in the OpenCode UI, and carries `noReply: true`
|
|
8
8
|
* so no LLM call is made.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
10
|
+
* Model/variant ARE passed when resolvable, mirroring the session's newest
|
|
11
|
+
* context: OpenCode's `createUserMessage` resolves an omitted model as
|
|
12
|
+
* `agent.model ?? session-current ?? default` and PERSISTS the result via
|
|
13
|
+
* `setAgentModel` — so omitting the model on a session whose user picked a
|
|
14
|
+
* non-default model silently resets the session's model/variant (observed on
|
|
15
|
+
* OpenCode Desktop via /aft-status). Passing the resolved current context
|
|
16
|
+
* makes that persistence a no-op. Older OpenCode builds crashed when model
|
|
17
|
+
* was supplied on a `noReply: true` prompt, so on any failure we retry once
|
|
18
|
+
* without model/variant rather than dropping the message.
|
|
17
19
|
*/
|
|
18
20
|
export declare function sendIgnoredMessage(client: unknown, sessionID: string, text: string): Promise<void>;
|
|
19
21
|
//# sourceMappingURL=ignored-message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ignored-message.d.ts","sourceRoot":"","sources":["../../src/shared/ignored-message.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"ignored-message.d.ts","sourceRoot":"","sources":["../../src/shared/ignored-message.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAsDf"}
|
|
@@ -15,16 +15,34 @@ export interface AftRpcCallOptions {
|
|
|
15
15
|
* placeholder wins.
|
|
16
16
|
*/
|
|
17
17
|
accept?: (result: unknown) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Internal one-hop guard for verified-directory redirects. A redirected
|
|
20
|
+
* call must never redirect again (placeholder chains would otherwise
|
|
21
|
+
* ping-pong between two bridgeless instances).
|
|
22
|
+
*/
|
|
23
|
+
noRedirect?: boolean;
|
|
18
24
|
}
|
|
25
|
+
export declare function subscribeRpcRedirects(listener: (from: string, to: string) => void): () => void;
|
|
26
|
+
export declare function __resetRpcRedirectsForTest(): void;
|
|
27
|
+
export declare function __recordRpcRedirectForTest(from: string, to: string): void;
|
|
19
28
|
export declare class AftRpcClient {
|
|
20
29
|
private port;
|
|
21
30
|
private token;
|
|
22
31
|
private portsDir;
|
|
23
32
|
private legacyPortFile;
|
|
24
33
|
private stalePortFailures;
|
|
34
|
+
private storageDir;
|
|
35
|
+
private directory;
|
|
25
36
|
constructor(storageDir: string, directory: string);
|
|
26
37
|
/** Call an RPC method. Retries port resolution if the server isn't ready yet. */
|
|
27
38
|
call<T = Record<string, unknown>>(method: string, params?: Record<string, unknown>, options?: AftRpcCallOptions): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* One-hop redirect to the instance that owns the session's bridge. Returns
|
|
41
|
+
* null (caller keeps the placeholder) unless the redirected call produced a
|
|
42
|
+
* warm response — a placeholder from the target is not an improvement, and
|
|
43
|
+
* failures must not mask the original placeholder.
|
|
44
|
+
*/
|
|
45
|
+
private followVerifiedDirectory;
|
|
28
46
|
private callOne;
|
|
29
47
|
/**
|
|
30
48
|
* Heuristic for "this response is the lazy-spawn placeholder, not the real
|
|
@@ -34,7 +52,11 @@ export declare class AftRpcClient {
|
|
|
34
52
|
private looksLikePlaceholder;
|
|
35
53
|
/** Check if any RPC server is reachable. */
|
|
36
54
|
isAvailable(): Promise<boolean>;
|
|
37
|
-
/** Resolve the freshest live endpoint for the persistent TUI WebSocket.
|
|
55
|
+
/** Resolve the freshest live endpoint for the persistent TUI WebSocket.
|
|
56
|
+
* Follows a learned verified-directory redirect so the socket subscribes
|
|
57
|
+
* to the instance that owns the session's bridge (the one that will
|
|
58
|
+
* actually push status-changed frames), not this directory's bridgeless
|
|
59
|
+
* placeholder instance. */
|
|
38
60
|
resolveEndpoint(signal?: AbortSignal): Promise<AftRpcEndpoint | null>;
|
|
39
61
|
/**
|
|
40
62
|
* Discover all live RPC port files for this project. Tries the per-instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-client.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEpE,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-client.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEpE,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAuBD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAK9F;AAcD,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAEzE;AA4BD,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;gBAEd,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAOjD,iFAAiF;IAC3E,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,CAAC,CAAC;IA0Db;;;;;OAKG;YACW,uBAAuB;YAwBvB,OAAO;IAsBrB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAM5B,4CAA4C;IACtC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC;;;;gCAI4B;IACtB,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAa3E;;;;OAIG;YACW,gBAAgB;IAwB9B,OAAO,CAAC,gBAAgB;IAwDxB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,iBAAiB;YA6BX,WAAW;YAkCX,gBAAgB;IAmB9B,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subc-tool-schemas.d.ts","sourceRoot":"","sources":["../src/subc-tool-schemas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"subc-tool-schemas.d.ts","sourceRoot":"","sources":["../src/subc-tool-schemas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD,QAAA,MAAM,eAAe,sOAsBX,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,wBAAgB,qBAAqB,IAAI,aAAa,CAYrD;AAWD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqFxF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAajG;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,eAAO,MAAM,oBAAoB,EAAE,SAAS,gBAAgB,EAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAM/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,GACR,CAAC;AAOhD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAIhD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,+BAA+B,EAC/B,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAW3D;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;2BAE2B;AAC3B,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtF;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,mBAAmB,CAYvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgClC;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,cAAc,CAAC,CAyBzB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMlC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsCjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAwQtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsCjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAwQtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAyHjE;AAyoBD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0B/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAqGnF"}
|
|
@@ -64,7 +64,15 @@ export declare const _permissionsInternalsForTest: {
|
|
|
64
64
|
*/
|
|
65
65
|
export declare function assertExternalDirectoryPermission(ctx: PluginContext, context: ToolContext, target: string, options?: {
|
|
66
66
|
kind?: "file" | "directory";
|
|
67
|
+
serverValidatedRead?: boolean;
|
|
67
68
|
}): Promise<string | undefined>;
|
|
69
|
+
/**
|
|
70
|
+
* Ask OpenCode for permission to expose indexed content from a different git root.
|
|
71
|
+
* This deliberately uses a tool-specific permission id rather than
|
|
72
|
+
* `external_directory`: a user may allow ordinary path reads while still wanting
|
|
73
|
+
* a separate audit point for search results produced from borrowed indexes.
|
|
74
|
+
*/
|
|
75
|
+
export declare function assertAftSearchExternalPermission(ctx: PluginContext, context: ToolContext, target: string): Promise<string | undefined>;
|
|
68
76
|
/**
|
|
69
77
|
* Trigger the host OpenCode permission check for grep.
|
|
70
78
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/tools/permissions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/tools/permissions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAwDjD;;;;;;;;;;;GAWG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnF;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,MAAM,GACnB,MAAM,CAER;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAazF;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAE9D;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkB7B;AAED;;;GAGG;AACH,iBAAS,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAI5D;AASD,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGjD;AA6DD;;;;;;;;;;;;GAYG;AACH,iBAAS,oBAAoB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED,eAAO,MAAM,4BAA4B;;;;CAIxC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyE7B;AAwBD;;;;;GAKG;AACH,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsE7B;AAkCD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE7B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE7B;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkB7B;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOhE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../src/tools/semantic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../src/tools/semantic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAgBjD,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA+FhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-socket.d.ts","sourceRoot":"","sources":["../../src/tui/notification-socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"notification-socket.d.ts","sourceRoot":"","sources":["../../src/tui/notification-socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA8C,MAAM,sBAAsB,CAAC;AAGhG,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C,YAAY,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,CAAC,YAAY,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClF;AAED,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CACd,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,EAC5C,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GACjC,IAAI,CAAC;IACR,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;CACf;AAED,KAAK,gBAAgB,GAAG,KAAK,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;AAC3D,KAAK,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC;AAErE,UAAU,UAAU;IAClB,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,aAAa,CAAC;IACnD,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,YAAY,EAAE,OAAO,YAAY,CAAC;CACnC;AA8CD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAMjE;AAwBD,wBAAgB,gBAAgB,IAAI,IAAI,CAiBvC;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC5C,MAAM,IAAI,CAKZ;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACnC,OAAO,EAAE,MAAM,GACd;IAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAoB/C;AA4PD,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,IAAI,CAMvF;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAiBjD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/aft-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
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",
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
15
|
"src/tui",
|
|
16
|
+
"src/tui-compiled",
|
|
16
17
|
"src/shared",
|
|
17
18
|
"src/logger.ts",
|
|
18
19
|
"README.md"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
|
-
"build": "bun build src/index.ts --outdir dist --target node --format esm --external @opencode-ai/plugin --external @opencode-ai/sdk &&
|
|
22
|
-
"typecheck": "tsc --noEmit",
|
|
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
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
|
|
23
24
|
"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.'); }\"",
|
|
24
25
|
"test": "bun test",
|
|
25
26
|
"test:e2e": "bun test src/__tests__/e2e/",
|
|
@@ -27,25 +28,27 @@
|
|
|
27
28
|
"schema": "bun scripts/build-schema.ts",
|
|
28
29
|
"build:tool-schemas": "bun run scripts/build-tool-schemas.ts",
|
|
29
30
|
"prepublishOnly": "bun run build",
|
|
30
|
-
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
|
|
31
|
+
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'",
|
|
32
|
+
"build:tui": "bun scripts/build-tui.ts",
|
|
33
|
+
"smoke:tui": "bun test ./scripts/smoke-tui-pack-install.ts"
|
|
31
34
|
},
|
|
32
35
|
"dependencies": {
|
|
33
36
|
"@clack/prompts": "^1.6.0",
|
|
34
|
-
"@cortexkit/aft-bridge": "0.
|
|
35
|
-
"@opentui/core": "
|
|
36
|
-
"@opentui/solid": "
|
|
37
|
+
"@cortexkit/aft-bridge": "0.47.0",
|
|
38
|
+
"@opentui/core": "0.4.3",
|
|
39
|
+
"@opentui/solid": "0.4.3",
|
|
37
40
|
"comment-json": "^4.6.2",
|
|
38
41
|
"solid-js": "1.9.12",
|
|
39
42
|
"undici": "^7.25.0",
|
|
40
43
|
"zod": "^4.4.3"
|
|
41
44
|
},
|
|
42
45
|
"optionalDependencies": {
|
|
43
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
44
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
45
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
46
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
47
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
48
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
46
|
+
"@cortexkit/aft-darwin-arm64": "0.47.0",
|
|
47
|
+
"@cortexkit/aft-darwin-x64": "0.47.0",
|
|
48
|
+
"@cortexkit/aft-linux-arm64": "0.47.0",
|
|
49
|
+
"@cortexkit/aft-linux-x64": "0.47.0",
|
|
50
|
+
"@cortexkit/aft-win32-arm64": "0.47.0",
|
|
51
|
+
"@cortexkit/aft-win32-x64": "0.47.0"
|
|
49
52
|
},
|
|
50
53
|
"devDependencies": {
|
|
51
54
|
"@opencode-ai/plugin": "^1.17.11",
|
|
@@ -60,7 +63,7 @@
|
|
|
60
63
|
},
|
|
61
64
|
"./tui": {
|
|
62
65
|
"types": "./src/tui/index.tsx",
|
|
63
|
-
"import": "./src/tui/
|
|
66
|
+
"import": "./src/tui/entry.mjs"
|
|
64
67
|
}
|
|
65
68
|
},
|
|
66
69
|
"oc-plugin": [
|
package/src/logger.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as os from "node:os";
|
|
3
|
-
import * as path from "node:path";
|
|
1
|
+
import { RotatingLogSink, resolveAftLogPath } from "@cortexkit/aft-bridge";
|
|
4
2
|
|
|
5
3
|
const TAG = "[aft-plugin]";
|
|
6
4
|
|
|
@@ -8,11 +6,12 @@ const TAG = "[aft-plugin]";
|
|
|
8
6
|
// live session log that users read to diagnose problems. Bun sets BUN_TEST=1
|
|
9
7
|
// automatically; NODE_ENV=test covers other test harnesses.
|
|
10
8
|
const isTestEnv = process.env.BUN_TEST === "1" || process.env.NODE_ENV === "test";
|
|
11
|
-
const logFile =
|
|
9
|
+
const logFile = resolveAftLogPath(isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
10
|
+
const fileSink = new RotatingLogSink(logFile);
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* When AFT_LOG_STDERR=1, logs go to stderr (useful for subprocess tests that
|
|
15
|
-
* capture stderr output). Otherwise logs go to the
|
|
14
|
+
* capture stderr output). Otherwise logs go to the durable AFT log directory.
|
|
16
15
|
*/
|
|
17
16
|
const useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
18
17
|
|
|
@@ -29,7 +28,7 @@ function flush(): void {
|
|
|
29
28
|
if (useStderr) {
|
|
30
29
|
process.stderr.write(data);
|
|
31
30
|
} else {
|
|
32
|
-
|
|
31
|
+
fileSink.append(data);
|
|
33
32
|
}
|
|
34
33
|
} catch {
|
|
35
34
|
// Intentional: logging must never throw
|
|
@@ -9,13 +9,15 @@ import { resolvePromptContext } from "./last-assistant-model.js";
|
|
|
9
9
|
* it shows in the right place in the OpenCode UI, and carries `noReply: true`
|
|
10
10
|
* so no LLM call is made.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
12
|
+
* Model/variant ARE passed when resolvable, mirroring the session's newest
|
|
13
|
+
* context: OpenCode's `createUserMessage` resolves an omitted model as
|
|
14
|
+
* `agent.model ?? session-current ?? default` and PERSISTS the result via
|
|
15
|
+
* `setAgentModel` — so omitting the model on a session whose user picked a
|
|
16
|
+
* non-default model silently resets the session's model/variant (observed on
|
|
17
|
+
* OpenCode Desktop via /aft-status). Passing the resolved current context
|
|
18
|
+
* makes that persistence a no-op. Older OpenCode builds crashed when model
|
|
19
|
+
* was supplied on a `noReply: true` prompt, so on any failure we retry once
|
|
20
|
+
* without model/variant rather than dropping the message.
|
|
19
21
|
*/
|
|
20
22
|
export async function sendIgnoredMessage(
|
|
21
23
|
client: unknown,
|
|
@@ -30,32 +32,49 @@ export async function sendIgnoredMessage(
|
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
let agent: string | undefined;
|
|
35
|
+
let model: { providerID: string; modelID: string } | undefined;
|
|
36
|
+
let variant: string | undefined;
|
|
33
37
|
try {
|
|
34
38
|
const ctx = await resolvePromptContext(
|
|
35
39
|
client as Parameters<typeof resolvePromptContext>[0],
|
|
36
40
|
sessionID,
|
|
37
41
|
);
|
|
38
42
|
agent = ctx?.agent;
|
|
43
|
+
model = ctx?.model;
|
|
44
|
+
variant = ctx?.variant;
|
|
39
45
|
} catch {
|
|
40
46
|
agent = undefined;
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
const body: Record<string, unknown>
|
|
49
|
+
const send = async (body: Record<string, unknown>): Promise<void> => {
|
|
50
|
+
const promptInput = { path: { id: sessionID }, body };
|
|
51
|
+
if (typeof typedClient.session?.prompt === "function") {
|
|
52
|
+
await Promise.resolve(typedClient.session.prompt(promptInput));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (typeof typedClient.session?.promptAsync === "function") {
|
|
56
|
+
await typedClient.session.promptAsync(promptInput);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
throw new Error("[aft-plugin] client.session.prompt is unavailable");
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const base: Record<string, unknown> = {
|
|
44
63
|
noReply: true,
|
|
45
64
|
parts: [{ type: "text", text, ignored: true }],
|
|
46
65
|
};
|
|
47
|
-
if (agent)
|
|
48
|
-
const promptInput = { path: { id: sessionID }, body };
|
|
49
|
-
|
|
50
|
-
if (typeof typedClient.session?.prompt === "function") {
|
|
51
|
-
await Promise.resolve(typedClient.session.prompt(promptInput));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
66
|
+
if (agent) base.agent = agent;
|
|
54
67
|
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
if (model) {
|
|
69
|
+
const withModel: Record<string, unknown> = { ...base, model };
|
|
70
|
+
if (variant) withModel.variant = variant;
|
|
71
|
+
try {
|
|
72
|
+
await send(withModel);
|
|
73
|
+
return;
|
|
74
|
+
} catch {
|
|
75
|
+
// Retry below without model/variant (legacy-host compatibility).
|
|
76
|
+
}
|
|
58
77
|
}
|
|
59
78
|
|
|
60
|
-
|
|
79
|
+
await send(base);
|
|
61
80
|
}
|
package/src/shared/rpc-client.ts
CHANGED
|
@@ -25,6 +25,61 @@ export interface AftRpcCallOptions {
|
|
|
25
25
|
* placeholder wins.
|
|
26
26
|
*/
|
|
27
27
|
accept?: (result: unknown) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Internal one-hop guard for verified-directory redirects. A redirected
|
|
30
|
+
* call must never redirect again (placeholder chains would otherwise
|
|
31
|
+
* ping-pong between two bridgeless instances).
|
|
32
|
+
*/
|
|
33
|
+
noRedirect?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Verified-directory redirect registry (module-level, shared by every client
|
|
38
|
+
* in this process).
|
|
39
|
+
*
|
|
40
|
+
* Why it exists: the TUI process can run in a DIFFERENT directory than the
|
|
41
|
+
* process hosting the session's warm bridge (TUI attached to `opencode
|
|
42
|
+
* serve` / Desktop, launched from $HOME). Port-file discovery is keyed by
|
|
43
|
+
* hash(directory), so the TUI's client only ever finds its own bridgeless
|
|
44
|
+
* instance — which answers the lazy placeholder forever. The placeholder now
|
|
45
|
+
* carries `verified_directory` (the session's SDK-verified project root);
|
|
46
|
+
* `call()` follows it once, to the port files of the instance that actually
|
|
47
|
+
* owns the session's bridge.
|
|
48
|
+
*
|
|
49
|
+
* The registry remembers learned redirects so `resolveEndpoint()` (the
|
|
50
|
+
* persistent notification WebSocket) can aim at the same instance, and
|
|
51
|
+
* notifies listeners so an already-connected socket re-homes instead of
|
|
52
|
+
* staying subscribed to the bridgeless instance that will never push.
|
|
53
|
+
*/
|
|
54
|
+
const redirectTargets = new Map<string, string>();
|
|
55
|
+
const redirectListeners = new Set<(from: string, to: string) => void>();
|
|
56
|
+
|
|
57
|
+
export function subscribeRpcRedirects(listener: (from: string, to: string) => void): () => void {
|
|
58
|
+
redirectListeners.add(listener);
|
|
59
|
+
return () => {
|
|
60
|
+
redirectListeners.delete(listener);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function recordRedirect(from: string, to: string): void {
|
|
65
|
+
if (redirectTargets.get(from) === to) return;
|
|
66
|
+
redirectTargets.set(from, to);
|
|
67
|
+
for (const listener of redirectListeners) {
|
|
68
|
+
try {
|
|
69
|
+
listener(from, to);
|
|
70
|
+
} catch {
|
|
71
|
+
// one listener must not block the others
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function __resetRpcRedirectsForTest(): void {
|
|
77
|
+
redirectTargets.clear();
|
|
78
|
+
redirectListeners.clear();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function __recordRpcRedirectForTest(from: string, to: string): void {
|
|
82
|
+
recordRedirect(from, to);
|
|
28
83
|
}
|
|
29
84
|
|
|
30
85
|
function abortError(signal: AbortSignal): Error {
|
|
@@ -59,8 +114,12 @@ export class AftRpcClient {
|
|
|
59
114
|
private portsDir: string;
|
|
60
115
|
private legacyPortFile: string;
|
|
61
116
|
private stalePortFailures = new Map<string, number>();
|
|
117
|
+
private storageDir: string;
|
|
118
|
+
private directory: string;
|
|
62
119
|
|
|
63
120
|
constructor(storageDir: string, directory: string) {
|
|
121
|
+
this.storageDir = storageDir;
|
|
122
|
+
this.directory = directory;
|
|
64
123
|
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
65
124
|
this.legacyPortFile = rpcPortFilePath(storageDir, directory);
|
|
66
125
|
}
|
|
@@ -110,12 +169,54 @@ export class AftRpcClient {
|
|
|
110
169
|
}
|
|
111
170
|
}
|
|
112
171
|
|
|
113
|
-
// All ports returned placeholder OR failed.
|
|
114
|
-
//
|
|
115
|
-
|
|
172
|
+
// All ports returned placeholder OR failed. Before settling for the
|
|
173
|
+
// placeholder, follow its verified_directory once: the session's warm
|
|
174
|
+
// bridge may live in another process registered under a different
|
|
175
|
+
// directory hash (TUI attached to a serve/Desktop host). See the
|
|
176
|
+
// redirect registry doc above.
|
|
177
|
+
if (placeholder !== null) {
|
|
178
|
+
const redirected = await this.followVerifiedDirectory<T>(
|
|
179
|
+
method,
|
|
180
|
+
params,
|
|
181
|
+
options,
|
|
182
|
+
placeholder,
|
|
183
|
+
);
|
|
184
|
+
if (redirected !== null) return redirected;
|
|
185
|
+
return placeholder;
|
|
186
|
+
}
|
|
116
187
|
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
117
188
|
}
|
|
118
189
|
|
|
190
|
+
/**
|
|
191
|
+
* One-hop redirect to the instance that owns the session's bridge. Returns
|
|
192
|
+
* null (caller keeps the placeholder) unless the redirected call produced a
|
|
193
|
+
* warm response — a placeholder from the target is not an improvement, and
|
|
194
|
+
* failures must not mask the original placeholder.
|
|
195
|
+
*/
|
|
196
|
+
private async followVerifiedDirectory<T>(
|
|
197
|
+
method: string,
|
|
198
|
+
params: Record<string, unknown>,
|
|
199
|
+
options: AftRpcCallOptions,
|
|
200
|
+
placeholder: T,
|
|
201
|
+
): Promise<T | null> {
|
|
202
|
+
if (options.noRedirect) return null;
|
|
203
|
+
const verified = (placeholder as Record<string, unknown> | null)?.verified_directory;
|
|
204
|
+
if (typeof verified !== "string" || verified.length === 0 || verified === this.directory) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const target = new AftRpcClient(this.storageDir, verified);
|
|
208
|
+
try {
|
|
209
|
+
const result = await target.call<T>(method, params, { ...options, noRedirect: true });
|
|
210
|
+
if (this.looksLikePlaceholder(result)) return null;
|
|
211
|
+
// Only remember (and re-home the notification socket) once the target
|
|
212
|
+
// actually served warm data — a dead redirect must stay unlearned.
|
|
213
|
+
recordRedirect(this.directory, verified);
|
|
214
|
+
return result;
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
119
220
|
private async callOne<T>(
|
|
120
221
|
method: string,
|
|
121
222
|
params: Record<string, unknown>,
|
|
@@ -159,8 +260,19 @@ export class AftRpcClient {
|
|
|
159
260
|
}
|
|
160
261
|
}
|
|
161
262
|
|
|
162
|
-
/** Resolve the freshest live endpoint for the persistent TUI WebSocket.
|
|
263
|
+
/** Resolve the freshest live endpoint for the persistent TUI WebSocket.
|
|
264
|
+
* Follows a learned verified-directory redirect so the socket subscribes
|
|
265
|
+
* to the instance that owns the session's bridge (the one that will
|
|
266
|
+
* actually push status-changed frames), not this directory's bridgeless
|
|
267
|
+
* placeholder instance. */
|
|
163
268
|
async resolveEndpoint(signal?: AbortSignal): Promise<AftRpcEndpoint | null> {
|
|
269
|
+
const redirect = redirectTargets.get(this.directory);
|
|
270
|
+
if (redirect) {
|
|
271
|
+
const target = new AftRpcClient(this.storageDir, redirect);
|
|
272
|
+
const [info] = await target.resolvePortInfos(signal);
|
|
273
|
+
if (info) return { port: info.port, token: info.token };
|
|
274
|
+
// Redirect target gone (process exited) — fall through to own ports.
|
|
275
|
+
}
|
|
164
276
|
const [info] = await this.resolvePortInfos(signal);
|
|
165
277
|
if (!info) return null;
|
|
166
278
|
return { port: info.port, token: info.token };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Prefer the host OpenTUI runtime registry when it exists. OpenTUI 0.4.x
|
|
2
|
+
// registers these virtual modules process-wide, which lets the precompiled TUI
|
|
3
|
+
// use the host's single Solid/OpenTUI runtime even when this package is loaded
|
|
4
|
+
// from an npm cache under node_modules.
|
|
5
|
+
let mod;
|
|
6
|
+
try {
|
|
7
|
+
await import("opentui:runtime-module:" + encodeURIComponent("@opentui/solid"));
|
|
8
|
+
mod = await import("../tui-compiled/index.tsx");
|
|
9
|
+
} catch {
|
|
10
|
+
// Older hosts and bare Bun do not provide the virtual registry. Falling back
|
|
11
|
+
// to the raw TSX entry keeps development checkouts and OpenTUI 0.3.x hosts
|
|
12
|
+
// working where the Solid transform still applies to this source path.
|
|
13
|
+
mod = await import("./index.tsx");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default mod.default;
|