@cortexkit/aft-opencode 0.20.1 → 0.22.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.
@@ -1 +1 @@
1
- {"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAsBH,+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;CACjC;AAkDD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AAwTD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CAwEnB"}
1
+ {"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwBH,+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;CACjC;AAkDD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AA0WD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CAwEnB"}
@@ -40,6 +40,7 @@ export interface GithubInstallConfig {
40
40
  disabled: ReadonlySet<string>;
41
41
  }
42
42
  declare function assertAllowedDownloadUrl(rawUrl: string): URL;
43
+ declare function downloadFile(url: string, destPath: string, fetchImpl: typeof fetch, assetSize?: number, signal?: AbortSignal): Promise<void>;
43
44
  /**
44
45
  * Recursively validate that every entry under `stagingRoot` is contained
45
46
  * within it (audit #3: zip-slip + symlink containment).
@@ -58,6 +59,16 @@ declare function assertAllowedDownloadUrl(rawUrl: string): URL;
58
59
  * Throws on any violation. The caller cleans up the staging dir.
59
60
  */
60
61
  export declare function validateExtraction(stagingRoot: string): void;
62
+ /**
63
+ * Extract `archivePath` into `destDir` safely:
64
+ *
65
+ * 1. Stage extraction in `<destDir>.staging-<rand>/`.
66
+ * 2. Run the platform extractor against the staging dir.
67
+ * 3. Validate the staging tree (no symlinks, no escapes).
68
+ * 4. Atomic rename: `staging → destDir`. Any prior `destDir` is removed first.
69
+ * 5. Always cleanup staging on any failure.
70
+ */
71
+ declare function precheckArchiveSize(archivePath: string, archiveType: string): void;
61
72
  export interface GithubAutoInstallResult {
62
73
  cachedBinDirs: string[];
63
74
  installsStarted: number;
@@ -97,5 +108,5 @@ export declare function discoverRelevantGithubServers(projectRoot: string): Set<
97
108
  * of `downloadFile`. We expose it here so the test suite can verify the
98
109
  * allowlist independently of full network mocking.
99
110
  */
100
- export { type Arch, assertAllowedDownloadUrl as _assertAllowedDownloadUrlForTesting, detectHostPlatform, findGithubServerById, GITHUB_LSP_TABLE, type GithubServerSpec, type Platform, };
111
+ export { type Arch, assertAllowedDownloadUrl as _assertAllowedDownloadUrlForTesting, detectHostPlatform, downloadFile as _downloadFileForTesting, findGithubServerById, GITHUB_LSP_TABLE, type GithubServerSpec, type Platform, precheckArchiveSize as _precheckArchiveSizeForTesting, };
101
112
  //# sourceMappingURL=lsp-github-install.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lsp-github-install.d.ts","sourceRoot":"","sources":["../src/lsp-github-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAsCH,OAAO,EACL,KAAK,IAAI,EACT,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAqB/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;AASD,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;AAmUD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAgBrD;AA6ED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CA0E5D;AAuTD,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;CACjC;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,CAqFzB;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,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,GACd,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;AAqB/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;AASD,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,iBAAS,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAqB3E;AAmVD,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;CACjC;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,CAwFzB;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,mBAAmB,IAAI,8BAA8B,GACtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAyOH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,yBAAyB,GAAG,uBAAuB,GAAG,oBAAoB,CAAC;IACjF,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,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C1F;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAqCf;AAwED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,uBAAuB,EAC7B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C9E"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAyOH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,yBAAyB,GAAG,uBAAuB,GAAG,oBAAoB,CAAC;IACjF,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,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C1F;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAqCf;AA8FD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,uBAAuB,EAC7B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAOA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;gBAEjB,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAIjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAuC9B,8CAA8C;IAC9C,IAAI,IAAI,IAAI;IAaZ,OAAO,CAAC,QAAQ;CAoEjB"}
1
+ {"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAOA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;gBAEjB,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAIjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IA0C9B,8CAA8C;IAC9C,IAAI,IAAI,IAAI;IAaZ,OAAO,CAAC,QAAQ;CAoEjB"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Returns `true` when the given session has a non-empty `parentID`
3
+ * (subagent). Returns `false` for primary sessions, when the SDK is
4
+ * unavailable, or when any error occurs — the false default keeps
5
+ * primary sessions working exactly as before.
6
+ *
7
+ * First call per session: one SDK round-trip. All subsequent calls:
8
+ * O(1) cache lookup.
9
+ */
10
+ export declare function resolveIsSubagent(client: unknown, sessionId: string | undefined, _fallbackDirectory?: string): Promise<boolean>;
11
+ /** Test-only cache reset. Not exported from the public surface. */
12
+ export declare function _resetSubagentCacheForTest(): void;
13
+ //# sourceMappingURL=subagent-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-detect.d.ts","sourceRoot":"","sources":["../../src/shared/subagent-detect.ts"],"names":[],"mappings":"AAqDA;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,OAAO,CAAC,CAqElB;AAWD,mEAAmE;AACnE,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/tools/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAiCjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0R3E"}
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/tools/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkDjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA6S3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqEjD,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAuMjE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAqCvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAmBrE"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAMvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA0EjD,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAwOjE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAqCvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAmBrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAkJjE;AAihCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwB/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAyEnF"}
1
+ {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA+JjE;AAkkCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwB/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA6EnF"}
@@ -1 +1 @@
1
- {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/tools/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAWjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAmF9E"}
1
+ {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/tools/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAiF9E"}
@@ -25,5 +25,74 @@ export declare function resolveRelativePattern(context: ToolContext, target: str
25
25
  export declare function resolveRelativePatterns(context: ToolContext, targets: string[]): string[];
26
26
  export declare function workspacePattern(_context: ToolContext): string;
27
27
  export declare function askEditPermission(context: ToolContext, patterns: string[], metadata?: Record<string, unknown>): Promise<string | undefined>;
28
+ /**
29
+ * Check if `child` is inside `parent`. Mirrors `AppFileSystem.contains` in
30
+ * opencode core (uses `path.relative` and ensures it doesn't start with `..`).
31
+ */
32
+ declare function containsPath(parent: string, child: string): boolean;
33
+ /**
34
+ * Normalize a path pattern (which may end in `*`) for the same reasons
35
+ * normalizePath() exists, but without trying to realpath a pattern that
36
+ * doesn't correspond to a real entry.
37
+ *
38
+ * Mirrors `AppFileSystem.normalizePathPattern` in opencode core.
39
+ *
40
+ * `*` → `*`
41
+ * `~/projects/*` → `~/projects/*` (`~` is expanded by opencode's matcher)
42
+ * `C:\some\dir\*` → `C:\some\dir\*` (drive case canonicalized via realpath of the dir part)
43
+ *
44
+ * No-op on non-Windows.
45
+ */
46
+ declare function normalizePathPattern(p: string): string;
47
+ export declare const _permissionsInternalsForTest: {
48
+ containsPath: typeof containsPath;
49
+ normalizePathPattern: typeof normalizePathPattern;
50
+ };
51
+ /**
52
+ * Trigger OpenCode's host-side `external_directory` permission check when the
53
+ * target path falls outside the current project's directory and worktree.
54
+ * Mirrors `opencode/src/tool/external-directory.ts::assertExternalDirectoryEffect`.
55
+ *
56
+ * Why this exists: AFT hoisted tools previously only called `permission: "edit"`,
57
+ * which bypassed OpenCode's separate `external_directory` rule (default `ask`).
58
+ * That meant `/tmp/anything` writes routed through AFT silently bypassed the
59
+ * prompt OpenCode native `write`/`edit`/`apply_patch`/`read` show. This helper
60
+ * closes that gap so AFT's hoisted surface matches native behavior.
61
+ *
62
+ * Returns `undefined` on allow (or when target is inside project), or a
63
+ * denial message string on deny so callers can wrap with
64
+ * `permissionDeniedResponse(...)`.
65
+ *
66
+ * Always call this BEFORE the regular `askEditPermission` so the user sees the
67
+ * external-directory prompt first (matching opencode native ordering). When the
68
+ * external-directory rule is `allow` (e.g. for `${os.tmpdir()}/opencode/*`), the
69
+ * call short-circuits and the regular permission flow continues normally.
70
+ */
71
+ export declare function assertExternalDirectoryPermission(context: ToolContext, target: string, options?: {
72
+ kind?: "file" | "directory";
73
+ }): Promise<string | undefined>;
74
+ /**
75
+ * Trigger OpenCode's host-side `grep` permission check.
76
+ *
77
+ * Mirrors `opencode/src/tool/grep.ts` shape exactly so users with
78
+ * `"permission": { "grep": { "*": "ask" } }` (or "deny") see the same
79
+ * prompt regardless of whether they're using AFT's hoisted `grep` or
80
+ * OpenCode's built-in.
81
+ */
82
+ export declare function askGrepPermission(context: ToolContext, pattern: string, metadata?: {
83
+ path?: string;
84
+ include?: string;
85
+ }): Promise<string | undefined>;
86
+ /**
87
+ * Trigger OpenCode's host-side `glob` permission check.
88
+ *
89
+ * Mirrors `opencode/src/tool/glob.ts` shape exactly so users with
90
+ * `"permission": { "glob": { "*": "ask" } }` see the same prompt
91
+ * regardless of which glob tool is used.
92
+ */
93
+ export declare function askGlobPermission(context: ToolContext, pattern: string, metadata?: {
94
+ path?: string;
95
+ }): Promise<string | undefined>;
28
96
  export declare function permissionDeniedResponse(message: string): string;
97
+ export {};
29
98
  //# sourceMappingURL=permissions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/tools/permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnF;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,CAiB7B;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOhE"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/tools/permissions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnF;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;AA6CD;;;;;;;;;;;;GAYG;AACH,iBAAS,oBAAoB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED,eAAO,MAAM,4BAA4B;;;CAAyC,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iCAAiC,CACrD,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,CAqD7B;AAED;;;;;;;GAOG;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,CAkB7B;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":"refactoring.d.ts","sourceRoot":"","sources":["../../src/tools/refactoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAajD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAgInF"}
1
+ {"version":3,"file":"refactoring.d.ts","sourceRoot":"","sources":["../../src/tools/refactoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0InF"}
@@ -1 +1 @@
1
- {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/tools/safety.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA6F9E"}
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/tools/safety.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAajD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAoH9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAwDjD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BrD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAmF9E"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA8DjD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BrD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAoI9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/tools/structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAWjD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAiKjF"}
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/tools/structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAkKjF"}
package/dist/tui.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // package.json
3
3
  var package_default = {
4
4
  name: "@cortexkit/aft-opencode",
5
- version: "0.20.1",
5
+ version: "0.22.0",
6
6
  type: "module",
7
7
  description: "OpenCode plugin for Agent File Tools (AFT) \u2014 tree-sitter and lsp powered code analysis",
8
8
  main: "dist/index.js",
@@ -30,7 +30,7 @@ var package_default = {
30
30
  },
31
31
  dependencies: {
32
32
  "@clack/prompts": "^1.2.0",
33
- "@cortexkit/aft-bridge": "0.20.1",
33
+ "@cortexkit/aft-bridge": "0.22.0",
34
34
  "@opencode-ai/plugin": "^1.14.39",
35
35
  "@opencode-ai/sdk": "^1.14.39",
36
36
  "comment-json": "^4.6.2",
@@ -38,11 +38,11 @@ var package_default = {
38
38
  zod: "^4.1.8"
39
39
  },
40
40
  optionalDependencies: {
41
- "@cortexkit/aft-darwin-arm64": "0.20.1",
42
- "@cortexkit/aft-darwin-x64": "0.20.1",
43
- "@cortexkit/aft-linux-arm64": "0.20.1",
44
- "@cortexkit/aft-linux-x64": "0.20.1",
45
- "@cortexkit/aft-win32-x64": "0.20.1"
41
+ "@cortexkit/aft-darwin-arm64": "0.22.0",
42
+ "@cortexkit/aft-darwin-x64": "0.22.0",
43
+ "@cortexkit/aft-linux-arm64": "0.22.0",
44
+ "@cortexkit/aft-linux-x64": "0.22.0",
45
+ "@cortexkit/aft-win32-x64": "0.22.0"
46
46
  },
47
47
  devDependencies: {
48
48
  "@types/node": "^22.0.0",
@@ -827,6 +827,41 @@ async function showStatusDialog(api) {
827
827
  api.ui.dialog.setSize("medium");
828
828
  });
829
829
  }
830
+ function registerStatusCommand(api) {
831
+ const apiAny = api;
832
+ if (typeof apiAny.keymap?.registerLayer === "function") {
833
+ apiAny.keymap.registerLayer({
834
+ commands: [
835
+ {
836
+ namespace: "palette",
837
+ name: "aft.status",
838
+ title: "AFT: Status",
839
+ category: "AFT",
840
+ slashName: STATUS_COMMAND,
841
+ run() {
842
+ showStatusDialog(api);
843
+ }
844
+ }
845
+ ],
846
+ bindings: []
847
+ });
848
+ return;
849
+ }
850
+ if (typeof apiAny.command?.register === "function") {
851
+ apiAny.command.register(() => [
852
+ {
853
+ title: "AFT: Status",
854
+ value: "aft.status",
855
+ category: "AFT",
856
+ slash: { name: STATUS_COMMAND },
857
+ onSelect() {
858
+ showStatusDialog(api);
859
+ }
860
+ }
861
+ ]);
862
+ return;
863
+ }
864
+ }
830
865
  async function showStartupNotifications(api) {
831
866
  const directory = api.state.path.directory ?? "";
832
867
  if (!directory)
@@ -869,17 +904,7 @@ var tui = async (api) => {
869
904
  try {
870
905
  api.slots.register(createAftSidebarSlot(api, package_default.version));
871
906
  } catch {}
872
- api.command.register(() => [
873
- {
874
- title: "AFT: Status",
875
- value: "aft.status",
876
- category: "AFT",
877
- slash: { name: STATUS_COMMAND },
878
- onSelect() {
879
- showStatusDialog(api);
880
- }
881
- }
882
- ]);
907
+ registerStatusCommand(api);
883
908
  showStartupNotifications(api);
884
909
  };
885
910
  var id = "aft-opencode";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.20.1",
3
+ "version": "0.22.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",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@clack/prompts": "^1.2.0",
31
- "@cortexkit/aft-bridge": "0.20.1",
31
+ "@cortexkit/aft-bridge": "0.22.0",
32
32
  "@opencode-ai/plugin": "^1.14.39",
33
33
  "@opencode-ai/sdk": "^1.14.39",
34
34
  "comment-json": "^4.6.2",
@@ -36,11 +36,11 @@
36
36
  "zod": "^4.1.8"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@cortexkit/aft-darwin-arm64": "0.20.1",
40
- "@cortexkit/aft-darwin-x64": "0.20.1",
41
- "@cortexkit/aft-linux-arm64": "0.20.1",
42
- "@cortexkit/aft-linux-x64": "0.20.1",
43
- "@cortexkit/aft-win32-x64": "0.20.1"
39
+ "@cortexkit/aft-darwin-arm64": "0.22.0",
40
+ "@cortexkit/aft-darwin-x64": "0.22.0",
41
+ "@cortexkit/aft-linux-arm64": "0.22.0",
42
+ "@cortexkit/aft-linux-x64": "0.22.0",
43
+ "@cortexkit/aft-win32-x64": "0.22.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^22.0.0",
@@ -46,9 +46,12 @@ export class AftRpcServer {
46
46
  // Write port file atomically
47
47
  try {
48
48
  const dir = dirname(this.portFilePath);
49
- mkdirSync(dir, { recursive: true });
49
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
50
50
  const tmpPath = `${this.portFilePath}.tmp`;
51
- writeFileSync(tmpPath, JSON.stringify({ port: this.port, token: this.token }), "utf-8");
51
+ writeFileSync(tmpPath, JSON.stringify({ port: this.port, token: this.token }), {
52
+ encoding: "utf-8",
53
+ mode: 0o600,
54
+ });
52
55
  renameSync(tmpPath, this.portFilePath);
53
56
  log(`RPC server listening on 127.0.0.1:${this.port}`);
54
57
  } catch (err) {
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Subagent detection via OpenCode SDK.
3
+ *
4
+ * AFT bash auto-promotes anything that takes more than ~5s to a background
5
+ * task. For the main agent (Alfonso), promotion is fine — the completion
6
+ * reminder fires back into the conversation and the agent picks it up on
7
+ * its next idle. For SUBAGENTS, promotion is fatal: a subagent waiting for
8
+ * a background-bash completion must end its turn to receive the reminder,
9
+ * which closes the subagent session permanently. The subagent never gets
10
+ * to commit its work.
11
+ *
12
+ * This module detects whether a session is a subagent (has a non-empty
13
+ * `parentID`) so the bash tool can:
14
+ * 1. Refuse `background: true` outright for subagents.
15
+ * 2. Disable auto-promotion: the foreground poll window extends to the
16
+ * task's full hard-kill timeout instead of the default 5s.
17
+ *
18
+ * Detection is via the OpenCode SDK `client.session.get`. The result is
19
+ * cached per sessionID for the lifetime of the plugin process — subagent
20
+ * identity is sticky (parentID never changes after session creation), so
21
+ * the cache never needs invalidation.
22
+ *
23
+ * Errors are not cached. If the SDK is briefly unavailable on the first
24
+ * call, we retry on the next bash invocation rather than permanently
25
+ * misclassifying. This is cheap because the cache is hit on every
26
+ * subsequent call within the same session.
27
+ *
28
+ * Mirrors the pattern in `session-directory.ts`.
29
+ */
30
+ import { sessionLog, sessionWarn } from "../logger.js";
31
+
32
+ interface SessionInfo {
33
+ parentID?: string;
34
+ }
35
+
36
+ interface OpenCodeClientShape {
37
+ session?: {
38
+ get?: (input: {
39
+ path: { id: string };
40
+ query?: { directory?: string };
41
+ throwOnError?: boolean;
42
+ }) => Promise<{ data?: SessionInfo } | SessionInfo | undefined>;
43
+ };
44
+ }
45
+
46
+ interface CacheEntry {
47
+ isSubagent: boolean;
48
+ recordedAt: number;
49
+ }
50
+
51
+ const CACHE_MAX_ENTRIES = 200;
52
+ const cache = new Map<string, CacheEntry>();
53
+
54
+ /**
55
+ * Returns `true` when the given session has a non-empty `parentID`
56
+ * (subagent). Returns `false` for primary sessions, when the SDK is
57
+ * unavailable, or when any error occurs — the false default keeps
58
+ * primary sessions working exactly as before.
59
+ *
60
+ * First call per session: one SDK round-trip. All subsequent calls:
61
+ * O(1) cache lookup.
62
+ */
63
+ export async function resolveIsSubagent(
64
+ client: unknown,
65
+ sessionId: string | undefined,
66
+ _fallbackDirectory?: string,
67
+ ): Promise<boolean> {
68
+ if (!sessionId) {
69
+ sessionLog(undefined, "[subagent-detect] no sessionId provided → primary");
70
+ return false;
71
+ }
72
+
73
+ const cached = cache.get(sessionId);
74
+ if (cached) {
75
+ // Refresh LRU position
76
+ cache.delete(sessionId);
77
+ cache.set(sessionId, cached);
78
+ sessionLog(sessionId, `[subagent-detect] cache hit: isSubagent=${cached.isSubagent}`);
79
+ return cached.isSubagent;
80
+ }
81
+
82
+ const c = client as OpenCodeClientShape;
83
+ const sessionApi = c?.session;
84
+ if (!sessionApi || typeof sessionApi.get !== "function") {
85
+ // SDK shape unavailable. Cache as not-subagent so we don't retry
86
+ // every call when the host doesn't expose session.get.
87
+ sessionLog(
88
+ sessionId,
89
+ `[subagent-detect] client.session.get unavailable (client=${typeof client}, session=${typeof sessionApi}, get=${typeof sessionApi?.get}) → caching as primary`,
90
+ );
91
+ setCache(sessionId, false);
92
+ return false;
93
+ }
94
+
95
+ sessionLog(
96
+ sessionId,
97
+ `[subagent-detect] cache miss, calling client.session.get(id=${sessionId})`,
98
+ );
99
+
100
+ let isSubagent = false;
101
+ let parentIdRaw: unknown;
102
+ try {
103
+ // Call as a method so the SDK's `this._client` reference resolves
104
+ // correctly. Extracting `sessionApi.get` into a local would lose
105
+ // the binding and crash the SDK with "undefined is not an object".
106
+ // SDK schema: SessionGetData uses `path: { id }`, NOT a flat `sessionID`.
107
+ // We do NOT pass `directory` — looking up a session by ID is an identity
108
+ // query, not a directory-scoped one. Passing the wrong shape returned a
109
+ // different session whose `parentID` was undefined, defeating the gate.
110
+ const result = await sessionApi.get({
111
+ path: { id: sessionId },
112
+ });
113
+ // SDK responses come either as `{ data: Session }` or directly as
114
+ // `Session` depending on `ThrowOnError`. Handle both shapes.
115
+ const session: SessionInfo | undefined =
116
+ (result as { data?: SessionInfo } | undefined)?.data ?? (result as SessionInfo | undefined);
117
+ parentIdRaw = session?.parentID;
118
+ isSubagent =
119
+ session !== undefined && typeof session.parentID === "string" && session.parentID.length > 0;
120
+ sessionLog(
121
+ sessionId,
122
+ `[subagent-detect] SDK returned session=${session !== undefined ? "present" : "undefined"}, parentID=${JSON.stringify(parentIdRaw)} → isSubagent=${isSubagent}`,
123
+ );
124
+ } catch (err) {
125
+ // Don't poison the cache on transient errors — but do log once.
126
+ // Return false so primary-session behavior is preserved.
127
+ sessionWarn(
128
+ sessionId,
129
+ `[subagent-detect] SDK lookup failed: ${err instanceof Error ? err.message : String(err)}`,
130
+ );
131
+ return false;
132
+ }
133
+
134
+ setCache(sessionId, isSubagent);
135
+ return isSubagent;
136
+ }
137
+
138
+ function setCache(sessionId: string, isSubagent: boolean): void {
139
+ if (cache.has(sessionId)) cache.delete(sessionId);
140
+ cache.set(sessionId, { isSubagent, recordedAt: Date.now() });
141
+ if (cache.size > CACHE_MAX_ENTRIES) {
142
+ const oldest = cache.keys().next().value;
143
+ if (oldest !== undefined) cache.delete(oldest);
144
+ }
145
+ }
146
+
147
+ /** Test-only cache reset. Not exported from the public surface. */
148
+ export function _resetSubagentCacheForTest(): void {
149
+ cache.clear();
150
+ }
package/src/tui/index.tsx CHANGED
@@ -138,6 +138,69 @@ async function showStatusDialog(api: TuiPluginApi): Promise<void> {
138
138
  );
139
139
  }
140
140
 
141
+ /**
142
+ * Register the `/aft-status` slash command, preferring the v1.14.42+ keymap
143
+ * API and falling back to the legacy `api.command.register` for older hosts.
144
+ *
145
+ * The `keymap.registerLayer` shape uses `name`/`title`/`run`/`namespace`/
146
+ * `slashName` (see `@opencode-ai/plugin/tui` types) and is what the host's
147
+ * own legacy command-shim translates into. Calling it directly skips the
148
+ * deprecation warning and works without depending on the (now-deprecated)
149
+ * `api.command` namespace existing at all.
150
+ */
151
+ function registerStatusCommand(api: TuiPluginApi): void {
152
+ type ApiAny = {
153
+ keymap?: {
154
+ registerLayer?: (layer: {
155
+ commands: Array<Record<string, unknown>>;
156
+ bindings: Array<Record<string, unknown>>;
157
+ }) => unknown;
158
+ };
159
+ command?: {
160
+ register?: (cb: () => Array<Record<string, unknown>>) => unknown;
161
+ };
162
+ };
163
+ const apiAny = api as unknown as ApiAny;
164
+
165
+ if (typeof apiAny.keymap?.registerLayer === "function") {
166
+ apiAny.keymap.registerLayer({
167
+ commands: [
168
+ {
169
+ namespace: "palette",
170
+ name: "aft.status",
171
+ title: "AFT: Status",
172
+ category: "AFT",
173
+ slashName: STATUS_COMMAND,
174
+ run() {
175
+ void showStatusDialog(api);
176
+ },
177
+ },
178
+ ],
179
+ bindings: [],
180
+ });
181
+ return;
182
+ }
183
+
184
+ if (typeof apiAny.command?.register === "function") {
185
+ apiAny.command.register(() => [
186
+ {
187
+ title: "AFT: Status",
188
+ value: "aft.status",
189
+ category: "AFT",
190
+ slash: { name: STATUS_COMMAND },
191
+ onSelect() {
192
+ void showStatusDialog(api);
193
+ },
194
+ },
195
+ ]);
196
+ return;
197
+ }
198
+
199
+ // Neither API surface is present. The TUI host can still load — we only
200
+ // lose the slash-command entry point. The sidebar (registered above)
201
+ // remains available so users can still see AFT status visually.
202
+ }
203
+
141
204
  async function showStartupNotifications(api: TuiPluginApi): Promise<void> {
142
205
  const directory = api.state.path.directory ?? "";
143
206
  if (!directory) return;
@@ -203,17 +266,15 @@ const tui: TuiPlugin = async (api) => {
203
266
  // and keep the slash command working.
204
267
  }
205
268
 
206
- api.command.register(() => [
207
- {
208
- title: "AFT: Status",
209
- value: "aft.status",
210
- category: "AFT",
211
- slash: { name: STATUS_COMMAND },
212
- onSelect() {
213
- void showStatusDialog(api);
214
- },
215
- },
216
- ]);
269
+ // OpenCode 1.14.42 removed `api.command.register` entirely
270
+ // (anomalyco/opencode PR #26053). Later patches reinstated it as a
271
+ // deprecated shim that translates to `api.keymap.registerLayer`. To work
272
+ // across the whole 1.14.x line — including the brief 1.14.42 / 1.14.43
273
+ // window where neither the legacy API nor a shim was present — we prefer
274
+ // `api.keymap.registerLayer` and fall back to `api.command.register` only
275
+ // when the keymap surface is missing (older hosts that predate keymap).
276
+ // See https://github.com/cortexkit/aft/issues/33.
277
+ registerStatusCommand(api);
217
278
 
218
279
  // Show startup notifications — RPC server is already running by the time TUI loads
219
280
  void showStartupNotifications(api);
@@ -1,10 +0,0 @@
1
- type BridgeLike = {
2
- getBridge: (directory: string, sessionID: string) => {
3
- send: (command: string, params?: Record<string, unknown>) => Promise<Record<string, unknown>>;
4
- };
5
- };
6
- export declare function setSharedBridgePool(pool: BridgeLike): void;
7
- export declare function getSharedBridgePool(): BridgeLike | null;
8
- export declare function clearSharedBridgePool(): void;
9
- export {};
10
- //# sourceMappingURL=runtime.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/shared/runtime.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,CACT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,KACd;QACH,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KAC/F,CAAC;CACH,CAAC;AAQF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAE1D;AAED,wBAAgB,mBAAmB,IAAI,UAAU,GAAG,IAAI,CAEvD;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}