@cortexkit/aft-opencode 0.45.0 → 0.46.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/config.d.ts +0 -22
- package/dist/config.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/types.d.ts +0 -3
- package/dist/hooks/auto-update-checker/types.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +347 -127
- package/dist/lsp-github-table.d.ts +0 -8
- package/dist/lsp-github-table.d.ts.map +1 -1
- package/dist/notifications.d.ts +2 -9
- package/dist/notifications.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 +0 -7
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/permissions.d.ts +7 -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/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
|
@@ -20,14 +20,6 @@
|
|
|
20
20
|
*/
|
|
21
21
|
export type Platform = "darwin" | "linux" | "win32";
|
|
22
22
|
export type Arch = "x64" | "arm64";
|
|
23
|
-
/**
|
|
24
|
-
* Asset name template — receives platform/arch (already mapped to the
|
|
25
|
-
* project's naming convention) and the resolved version, returns the
|
|
26
|
-
* literal asset filename to look for in the release `assets[]`.
|
|
27
|
-
*
|
|
28
|
-
* Returns `null` when this platform/arch combo is unsupported.
|
|
29
|
-
*/
|
|
30
|
-
export type AssetTemplate = (platform: Platform, arch: Arch, version: string) => string | null;
|
|
31
23
|
export type ArchiveType = "tar.gz" | "tar.xz" | "zip";
|
|
32
24
|
export interface GithubServerSpec {
|
|
33
25
|
/** AFT server-kind id (matches `crates/aft/src/lsp/registry.rs::ServerKind::id_str`). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lsp-github-table.d.ts","sourceRoot":"","sources":["../src/lsp-github-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AACpD,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC;AAEnC
|
|
1
|
+
{"version":3,"file":"lsp-github-table.d.ts","sourceRoot":"","sources":["../src/lsp-github-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AACpD,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC;AAEnC,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yFAAyF;IACzF,QAAQ,CAAC,YAAY,EAAE,CACrB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,KACZ;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3F;AA4HD,eAAO,MAAM,gBAAgB,EAAE,SAAS,gBAAgB,EAMvD,CAAC;AAEF,sCAAsC;AACtC,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE7E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAQ9E"}
|
package/dist/notifications.d.ts
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* Use cases:
|
|
9
9
|
* - Feature announcements (new version, new experimental features)
|
|
10
10
|
* - Warnings (ONNX Runtime not found, stale binary)
|
|
11
|
-
* - Status updates (semantic search ready, index built)
|
|
12
11
|
*
|
|
13
12
|
* Messages are identified by markers and cleaned up on subsequent startups
|
|
14
13
|
* when no longer relevant (Desktop only — TUI toasts are inherently transient).
|
|
@@ -30,8 +29,8 @@ type SdkMessage = {
|
|
|
30
29
|
export declare const SESSION_MESSAGES_LIMIT = 50;
|
|
31
30
|
/**
|
|
32
31
|
* @internal — exported only so tests can pin the bounded-call contract.
|
|
33
|
-
* Production callers go through `
|
|
34
|
-
*
|
|
32
|
+
* Production callers go through `cleanupWarnings`, which gates on a real
|
|
33
|
+
* `readDesktopState()` before reaching this helper.
|
|
35
34
|
*/
|
|
36
35
|
export declare function getSessionMessages(client: unknown, sessionId: string): Promise<SdkMessage[]>;
|
|
37
36
|
export interface NotificationOptions {
|
|
@@ -68,12 +67,6 @@ export interface ConfigureWarningOptions {
|
|
|
68
67
|
* TUI: toast with warning variant (inherently transient).
|
|
69
68
|
*/
|
|
70
69
|
export declare function sendWarning(opts: NotificationOptions, message: string): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* Send a transient status notification.
|
|
73
|
-
* Desktop: ignored message when sessionId is explicit, auto-deletes after 3 seconds.
|
|
74
|
-
* TUI: toast with success variant, auto-dismissed by the TUI.
|
|
75
|
-
*/
|
|
76
|
-
export declare function sendStatus(opts: NotificationOptions, message: string): Promise<void>;
|
|
77
70
|
/**
|
|
78
71
|
* Send a feature announcement for a new version.
|
|
79
72
|
* Tracked via a version file in storageDir — only fires once per version across all sessions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAwK7D,wBAAgB,gCAAgC,IAAI,IAAI,CAEvD;AAID,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACpE,CAAC;AAwBF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBvB;AAkHD,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EACA,yBAAyB,GACzB,uBAAuB,GACvB,oBAAoB,GACpB,qBAAqB,GACrB,oBAAoB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe3F;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAyLD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,uBAAuB,EAC7B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C9E"}
|
|
@@ -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"}
|
package/dist/tools/_shared.d.ts
CHANGED
|
@@ -137,11 +137,4 @@ export declare function callToolCall(ctx: PluginContext, runtime: ToolRuntime, n
|
|
|
137
137
|
* unrelated sibling requests.
|
|
138
138
|
*/
|
|
139
139
|
export declare function callBashBridge(ctx: PluginContext, runtime: ToolRuntime, command: string, params?: Record<string, unknown>, options?: BridgeRequestOptions): Promise<Record<string, unknown>>;
|
|
140
|
-
/**
|
|
141
|
-
* Eagerly warm the session-directory cache for a runtime. Safe to call from
|
|
142
|
-
* synchronous code — the lookup runs in the background and failures are
|
|
143
|
-
* logged. Useful in plugin lifecycle hooks (`chat.message`, etc.) where we
|
|
144
|
-
* want the cache filled before any tool call arrives.
|
|
145
|
-
*/
|
|
146
|
-
export declare function warmSessionDirectoryFromRuntime(ctx: PluginContext, runtime: ToolRuntime): void;
|
|
147
140
|
//# sourceMappingURL=_shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,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,CAMvF;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,CAuHjE;
|
|
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,CAuHjE;AA8mBD;;;;;;;;;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"}
|
|
@@ -65,6 +65,13 @@ export declare const _permissionsInternalsForTest: {
|
|
|
65
65
|
export declare function assertExternalDirectoryPermission(ctx: PluginContext, context: ToolContext, target: string, options?: {
|
|
66
66
|
kind?: "file" | "directory";
|
|
67
67
|
}): Promise<string | undefined>;
|
|
68
|
+
/**
|
|
69
|
+
* Ask OpenCode for permission to expose indexed content from a different git root.
|
|
70
|
+
* This deliberately uses a tool-specific permission id rather than
|
|
71
|
+
* `external_directory`: a user may allow ordinary path reads while still wanting
|
|
72
|
+
* a separate audit point for search results produced from borrowed indexes.
|
|
73
|
+
*/
|
|
74
|
+
export declare function assertAftSearchExternalPermission(ctx: PluginContext, context: ToolContext, target: string): Promise<string | undefined>;
|
|
68
75
|
/**
|
|
69
76
|
* Trigger the host OpenCode permission check for grep.
|
|
70
77
|
*
|
|
@@ -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,CAAA;CAAE,GACxC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAqE7B;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.46.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.46.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.46.0",
|
|
47
|
+
"@cortexkit/aft-darwin-x64": "0.46.0",
|
|
48
|
+
"@cortexkit/aft-linux-arm64": "0.46.0",
|
|
49
|
+
"@cortexkit/aft-linux-x64": "0.46.0",
|
|
50
|
+
"@cortexkit/aft-win32-arm64": "0.46.0",
|
|
51
|
+
"@cortexkit/aft-win32-x64": "0.46.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": [
|
|
@@ -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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AftRpcClient, type AftRpcEndpoint } from "../shared/rpc-client";
|
|
1
|
+
import { AftRpcClient, type AftRpcEndpoint, subscribeRpcRedirects } from "../shared/rpc-client";
|
|
2
2
|
import { resolveCortexKitStorageRoot } from "../shared/storage-paths";
|
|
3
3
|
|
|
4
4
|
export interface SocketNotification {
|
|
@@ -86,14 +86,41 @@ export function startAftTuiSocket(options: TuiSocketOptions): void {
|
|
|
86
86
|
opts = options;
|
|
87
87
|
closed = false;
|
|
88
88
|
generation += 1;
|
|
89
|
+
ensureRedirectSubscription();
|
|
89
90
|
void reconcileSocketScope();
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Re-home the socket when a status call learns a verified-directory redirect
|
|
95
|
+
* (see rpc-client). The socket may already be connected to this directory's
|
|
96
|
+
* bridgeless instance — which authenticates and accepts hello but will never
|
|
97
|
+
* push a status-changed frame, because the session's bridge lives in another
|
|
98
|
+
* process. Drop it and reconnect; resolveEndpoint now follows the redirect.
|
|
99
|
+
*/
|
|
100
|
+
let redirectUnsubscribe: (() => void) | null = null;
|
|
101
|
+
function ensureRedirectSubscription(): void {
|
|
102
|
+
if (redirectUnsubscribe) return;
|
|
103
|
+
redirectUnsubscribe = subscribeRpcRedirects((from) => {
|
|
104
|
+
if (closed) return;
|
|
105
|
+
const scope = currentScope();
|
|
106
|
+
if (!scope || scope.directory !== from) return;
|
|
107
|
+
generation += 1;
|
|
108
|
+
connectingGeneration = null;
|
|
109
|
+
connectingScope = null;
|
|
110
|
+
closeCurrentSocket(false);
|
|
111
|
+
void connect(scope, generation);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
92
115
|
export function stopAftTuiSocket(): void {
|
|
93
116
|
closed = true;
|
|
94
117
|
generation += 1;
|
|
95
118
|
connectingGeneration = null;
|
|
96
119
|
connectingScope = null;
|
|
120
|
+
if (redirectUnsubscribe) {
|
|
121
|
+
redirectUnsubscribe();
|
|
122
|
+
redirectUnsubscribe = null;
|
|
123
|
+
}
|
|
97
124
|
if (reconnectTimer) {
|
|
98
125
|
deps.clearTimeout(reconnectTimer);
|
|
99
126
|
reconnectTimer = undefined;
|