@cortexkit/aft-opencode 0.15.5 → 0.16.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/bridge.d.ts CHANGED
@@ -3,6 +3,12 @@
3
3
  * Returns: negative if a < b, 0 if equal, positive if a > b.
4
4
  */
5
5
  export declare function compareSemver(a: string, b: string): number;
6
+ interface ConfigureWarningsContext {
7
+ projectRoot: string;
8
+ sessionId?: string;
9
+ client?: unknown;
10
+ warnings: unknown[];
11
+ }
6
12
  export interface BridgeOptions {
7
13
  /** Request timeout in milliseconds. Default: 30000 */
8
14
  timeoutMs?: number;
@@ -12,6 +18,12 @@ export interface BridgeOptions {
12
18
  minVersion?: string;
13
19
  /** Called when binary version is older than minVersion. Receives (binaryVersion, minVersion). */
14
20
  onVersionMismatch?: (binaryVersion: string, minVersion: string) => void;
21
+ /** Called after the first successful configure returns user-visible warnings. */
22
+ onConfigureWarnings?: (context: ConfigureWarningsContext) => void | Promise<void>;
23
+ }
24
+ interface SendOptions {
25
+ timeoutMs?: number;
26
+ configureWarningClient?: unknown;
15
27
  }
16
28
  /**
17
29
  * Manages a persistent `aft` child process, communicating via NDJSON over
@@ -39,6 +51,7 @@ export declare class BinaryBridge {
39
51
  private configOverrides;
40
52
  private minVersion;
41
53
  private onVersionMismatch;
54
+ private onConfigureWarnings;
42
55
  private restartResetTimer;
43
56
  constructor(binaryPath: string, cwd: string, options?: BridgeOptions, configOverrides?: Record<string, unknown>);
44
57
  /** Number of times the binary has been restarted after a crash. */
@@ -49,9 +62,8 @@ export declare class BinaryBridge {
49
62
  * Send a command to the binary and return the parsed response.
50
63
  * Lazy-spawns the binary on first call.
51
64
  */
52
- send(command: string, params?: Record<string, unknown>, options?: {
53
- timeoutMs?: number;
54
- }): Promise<Record<string, unknown>>;
65
+ send(command: string, params?: Record<string, unknown>, options?: SendOptions): Promise<Record<string, unknown>>;
66
+ private deliverConfigureWarnings;
55
67
  /** Kill the child process and reject all pending requests. */
56
68
  shutdown(): Promise<void>;
57
69
  /** Query binary version and compare against minVersion. Calls onVersionMismatch if outdated. */
@@ -72,4 +84,5 @@ export declare class BinaryBridge {
72
84
  private scheduleRestartCountReset;
73
85
  private clearRestartResetTimer;
74
86
  }
87
+ export {};
75
88
  //# sourceMappingURL=bridge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAkC1D;AA4CD,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qGAAqG;IACrG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACzE;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAiB;IACzD,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAM;IAE7C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,YAAY,CAAM;IAC1B,sEAAsE;IACtE,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,iBAAiB,CAAoE;IAC7F,OAAO,CAAC,iBAAiB,CAA8C;gBAGrE,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAW3C,mEAAmE;IACnE,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,oDAAoD;IACpD,OAAO,IAAI,OAAO;IAIlB;;;OAGG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAgGnC,8DAA8D;IACxD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B/B,gGAAgG;YAClF,YAAY;IAoB1B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,YAAY;IAkHpB,OAAO,CAAC,cAAc;IAOtB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,WAAW;IAgDnB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,sBAAsB;CAM/B"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAkC1D;AA4CD,UAAU,wBAAwB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qGAAqG;IACrG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AAED,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAiB;IACzD,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAM;IAE7C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,YAAY,CAAM;IAC1B,sEAAsE;IACtE,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,iBAAiB,CAAoE;IAC7F,OAAO,CAAC,mBAAmB,CAEb;IACd,OAAO,CAAC,iBAAiB,CAA8C;gBAGrE,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAY3C,mEAAmE;IACnE,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,oDAAoD;IACpD,OAAO,IAAI,OAAO;IAIlB;;;OAGG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAiGrB,wBAAwB;IAuBtC,8DAA8D;IACxD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B/B,gGAAgG;YAClF,YAAY;IAoB1B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,YAAY;IAkHpB,OAAO,CAAC,cAAc;IAOtB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,WAAW;IAgDnB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,sBAAsB;CAM/B"}
package/dist/config.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import { z } from "zod";
2
+ export declare const LspServerSchema: z.ZodObject<{
3
+ extensions: z.ZodArray<z.ZodString>;
4
+ binary: z.ZodString;
5
+ args: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
6
+ root_markers: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
7
+ disabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
8
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
9
+ initialization_options: z.ZodOptional<z.ZodUnknown>;
10
+ id: z.ZodString;
11
+ }, z.core.$strip>;
2
12
  export declare const AftConfigSchema: z.ZodObject<{
3
13
  format_on_edit: z.ZodOptional<z.ZodBoolean>;
4
14
  validate_on_edit: z.ZodOptional<z.ZodEnum<{
@@ -36,6 +46,24 @@ export declare const AftConfigSchema: z.ZodObject<{
36
46
  restrict_to_project_root: z.ZodOptional<z.ZodBoolean>;
37
47
  experimental_search_index: z.ZodOptional<z.ZodBoolean>;
38
48
  experimental_semantic_search: z.ZodOptional<z.ZodBoolean>;
49
+ experimental_lsp_ty: z.ZodOptional<z.ZodBoolean>;
50
+ lsp: z.ZodOptional<z.ZodObject<{
51
+ servers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
52
+ extensions: z.ZodArray<z.ZodString>;
53
+ binary: z.ZodString;
54
+ args: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
55
+ root_markers: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
56
+ disabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
57
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
58
+ initialization_options: z.ZodOptional<z.ZodUnknown>;
59
+ }, z.core.$strip>>>;
60
+ disabled: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
+ python: z.ZodOptional<z.ZodEnum<{
62
+ pyright: "pyright";
63
+ ty: "ty";
64
+ auto: "auto";
65
+ }>>;
66
+ }, z.core.$strip>>;
39
67
  url_fetch_allow_private: z.ZodOptional<z.ZodBoolean>;
40
68
  semantic: z.ZodOptional<z.ZodObject<{
41
69
  backend: z.ZodOptional<z.ZodEnum<{
@@ -52,6 +80,23 @@ export declare const AftConfigSchema: z.ZodObject<{
52
80
  max_callgraph_files: z.ZodOptional<z.ZodNumber>;
53
81
  }, z.core.$strip>;
54
82
  export type AftConfig = z.infer<typeof AftConfigSchema>;
83
+ export type LspServerConfig = z.infer<typeof LspServerSchema>;
84
+ export interface ConfigureLspServer {
85
+ id: string;
86
+ extensions: string[];
87
+ binary: string;
88
+ args: string[];
89
+ root_markers: string[];
90
+ disabled: boolean;
91
+ env?: Record<string, string>;
92
+ initialization_options?: unknown;
93
+ }
94
+ export interface ConfigureLspOverrides {
95
+ experimental_lsp_ty?: boolean;
96
+ lsp_servers?: ConfigureLspServer[];
97
+ disabled_lsp?: string[];
98
+ }
99
+ export declare function resolveLspConfigForConfigure(config: AftConfig): ConfigureLspOverrides;
55
100
  /**
56
101
  * Load AFT config using the same two-level pattern as oh-my-opencode:
57
102
  *
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+CxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmD1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AA2KxD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAiCjE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmExB,eAAO,MAAM,eAAe;;;;;;;;;iBAE1B,CAAC;AAQH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuD1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAMD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,qBAAqB,CAgDrF;AAoLD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAiCjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA8GlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,MAAM,EAAE,MAwXb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA+HlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,MAAM,EAAE,MAwYb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -21443,6 +21443,26 @@ var SemanticConfigSchema = exports_external.object({
21443
21443
  timeout_ms: exports_external.number().int().positive().optional(),
21444
21444
  max_batch_size: exports_external.number().int().positive().optional()
21445
21445
  });
21446
+ var LspExtensionSchema = exports_external.string().trim().min(1).refine((value) => value.replace(/^\.+/, "").length > 0, {
21447
+ message: "Extension must include characters other than leading dots"
21448
+ });
21449
+ var LspServerEntrySchema = exports_external.object({
21450
+ extensions: exports_external.array(LspExtensionSchema).min(1),
21451
+ binary: exports_external.string().trim().min(1),
21452
+ args: exports_external.array(exports_external.string()).optional().default([]),
21453
+ root_markers: exports_external.array(exports_external.string().trim().min(1)).optional().default([".git"]),
21454
+ disabled: exports_external.boolean().optional().default(false),
21455
+ env: exports_external.record(exports_external.string().min(1), exports_external.string()).optional(),
21456
+ initialization_options: exports_external.unknown().optional()
21457
+ });
21458
+ var LspServerSchema = LspServerEntrySchema.extend({
21459
+ id: exports_external.string().trim().min(1)
21460
+ });
21461
+ var LspConfigSchema = exports_external.object({
21462
+ servers: exports_external.record(exports_external.string().trim().min(1), LspServerEntrySchema).optional(),
21463
+ disabled: exports_external.array(exports_external.string().trim().min(1)).optional(),
21464
+ python: exports_external.enum(["pyright", "ty", "auto"]).optional()
21465
+ });
21446
21466
  var AftConfigSchema = exports_external.object({
21447
21467
  format_on_edit: exports_external.boolean().optional(),
21448
21468
  validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
@@ -21454,10 +21474,59 @@ var AftConfigSchema = exports_external.object({
21454
21474
  restrict_to_project_root: exports_external.boolean().optional(),
21455
21475
  experimental_search_index: exports_external.boolean().optional(),
21456
21476
  experimental_semantic_search: exports_external.boolean().optional(),
21477
+ experimental_lsp_ty: exports_external.boolean().optional(),
21478
+ lsp: LspConfigSchema.optional(),
21457
21479
  url_fetch_allow_private: exports_external.boolean().optional(),
21458
21480
  semantic: SemanticConfigSchema.optional(),
21459
21481
  max_callgraph_files: exports_external.number().int().positive().optional()
21460
21482
  });
21483
+ function normalizeLspExtension(extension) {
21484
+ return extension.trim().replace(/^\.+/, "");
21485
+ }
21486
+ function resolveLspConfigForConfigure(config2) {
21487
+ const overrides = {};
21488
+ const disabled = new Set(config2.lsp?.disabled ?? []);
21489
+ let experimentalTy = config2.experimental_lsp_ty;
21490
+ switch (config2.lsp?.python ?? "auto") {
21491
+ case "ty":
21492
+ experimentalTy = true;
21493
+ disabled.add("pyright");
21494
+ break;
21495
+ case "pyright":
21496
+ experimentalTy = false;
21497
+ disabled.add("ty");
21498
+ break;
21499
+ case "auto":
21500
+ break;
21501
+ }
21502
+ if (experimentalTy !== undefined) {
21503
+ overrides.experimental_lsp_ty = experimentalTy;
21504
+ }
21505
+ const servers = Object.entries(config2.lsp?.servers ?? {}).map(([id, server]) => {
21506
+ const entry = {
21507
+ id,
21508
+ extensions: server.extensions.map(normalizeLspExtension),
21509
+ binary: server.binary,
21510
+ args: server.args,
21511
+ root_markers: server.root_markers,
21512
+ disabled: server.disabled
21513
+ };
21514
+ if (server.env && Object.keys(server.env).length > 0) {
21515
+ entry.env = server.env;
21516
+ }
21517
+ if (server.initialization_options !== undefined) {
21518
+ entry.initialization_options = server.initialization_options;
21519
+ }
21520
+ return entry;
21521
+ });
21522
+ if (servers.length > 0) {
21523
+ overrides.lsp_servers = servers;
21524
+ }
21525
+ if (disabled.size > 0) {
21526
+ overrides.disabled_lsp = [...disabled];
21527
+ }
21528
+ return overrides;
21529
+ }
21461
21530
  function detectConfigFile(basePath) {
21462
21531
  const jsoncPath = `${basePath}.jsonc`;
21463
21532
  const jsonPath = `${basePath}.json`;
@@ -21540,12 +21609,21 @@ function mergeConfigs(base, override) {
21540
21609
  const formatter = { ...base.formatter, ...override.formatter };
21541
21610
  const checker = { ...base.checker, ...override.checker };
21542
21611
  const semantic = mergeSemanticConfig(base.semantic, override.semantic);
21612
+ const lspServers = { ...base.lsp?.servers, ...override.lsp?.servers };
21613
+ const disabledLsp = [...base.lsp?.disabled ?? [], ...override.lsp?.disabled ?? []];
21614
+ const lsp = {
21615
+ ...base.lsp,
21616
+ ...override.lsp,
21617
+ ...Object.keys(lspServers).length > 0 ? { servers: lspServers } : {},
21618
+ ...disabledLsp.length > 0 ? { disabled: [...new Set(disabledLsp)] } : {}
21619
+ };
21543
21620
  const { semantic: _stripSemantic, ...safeOverride } = override;
21544
21621
  return {
21545
21622
  ...base,
21546
21623
  ...safeOverride,
21547
21624
  ...Object.keys(formatter).length > 0 ? { formatter } : {},
21548
21625
  ...Object.keys(checker).length > 0 ? { checker } : {},
21626
+ ...Object.values(lsp).some((value) => value !== undefined) ? { lsp } : {},
21549
21627
  semantic,
21550
21628
  ...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
21551
21629
  };
@@ -21814,6 +21892,7 @@ var AFT_MARKER = "\uD83D\uDD27 AFT:";
21814
21892
  var FEATURE_MARKER = `${AFT_MARKER} New in`;
21815
21893
  var WARNING_MARKER = `${AFT_MARKER} \u26A0\uFE0F`;
21816
21894
  var STATUS_MARKER = `${AFT_MARKER} \u2705`;
21895
+ var WARNED_TOOLS_FILE = "warned_tools.json";
21817
21896
  function getDesktopStatePath() {
21818
21897
  const os2 = platform();
21819
21898
  const home = homedir3();
@@ -21958,6 +22037,86 @@ async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
21958
22037
  } catch {}
21959
22038
  }
21960
22039
  }
22040
+ function readWarnedTools(storageDir) {
22041
+ try {
22042
+ const warnedToolsPath = join4(storageDir, WARNED_TOOLS_FILE);
22043
+ if (!existsSync3(warnedToolsPath))
22044
+ return {};
22045
+ const parsed = JSON.parse(readFileSync2(warnedToolsPath, "utf-8"));
22046
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
22047
+ return {};
22048
+ const warned = {};
22049
+ for (const [key, version2] of Object.entries(parsed)) {
22050
+ if (typeof version2 === "string") {
22051
+ warned[key] = version2;
22052
+ }
22053
+ }
22054
+ return warned;
22055
+ } catch {
22056
+ return {};
22057
+ }
22058
+ }
22059
+ function writeWarnedTools(storageDir, warned) {
22060
+ try {
22061
+ mkdirSync2(storageDir, { recursive: true });
22062
+ const warnedToolsPath = join4(storageDir, WARNED_TOOLS_FILE);
22063
+ writeFileSync(warnedToolsPath, `${JSON.stringify(warned, null, 2)}
22064
+ `);
22065
+ } catch {}
22066
+ }
22067
+ function warningKey(warning, projectRoot) {
22068
+ return [
22069
+ projectRoot ?? "_",
22070
+ warning.kind,
22071
+ warning.language ?? warning.server ?? "_",
22072
+ warning.tool ?? warning.binary ?? "_",
22073
+ warning.hint
22074
+ ].map((part) => encodeURIComponent(part)).join(":");
22075
+ }
22076
+ function warningTitle(warning) {
22077
+ switch (warning.kind) {
22078
+ case "formatter_not_installed":
22079
+ return "Formatter is not installed";
22080
+ case "checker_not_installed":
22081
+ return "Checker is not installed";
22082
+ case "lsp_binary_missing":
22083
+ return "LSP binary is missing";
22084
+ }
22085
+ }
22086
+ function formatConfigureWarning(warning) {
22087
+ const details = [];
22088
+ if (warning.language)
22089
+ details.push(`language: ${warning.language}`);
22090
+ if (warning.server)
22091
+ details.push(`server: ${warning.server}`);
22092
+ if (warning.tool)
22093
+ details.push(`tool: ${warning.tool}`);
22094
+ if (warning.binary && warning.binary !== warning.tool) {
22095
+ details.push(`binary: ${warning.binary}`);
22096
+ }
22097
+ const suffix = details.length > 0 ? ` (${details.join(", ")})` : "";
22098
+ return `${WARNING_MARKER} ${warningTitle(warning)}${suffix}
22099
+ ${warning.hint}`;
22100
+ }
22101
+ async function deliverConfigureWarnings(opts, warnings) {
22102
+ if (warnings.length === 0)
22103
+ return;
22104
+ const warned = readWarnedTools(opts.storageDir);
22105
+ let changed = false;
22106
+ for (const warning of warnings) {
22107
+ const key = warningKey(warning, opts.projectRoot);
22108
+ if (Object.hasOwn(warned, key))
22109
+ continue;
22110
+ const delivered = await sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
22111
+ if (!delivered)
22112
+ continue;
22113
+ warned[key] = opts.pluginVersion;
22114
+ changed = true;
22115
+ }
22116
+ if (changed) {
22117
+ writeWarnedTools(opts.storageDir, warned);
22118
+ }
22119
+ }
21961
22120
  async function cleanupWarnings(opts) {
21962
22121
  if (isTuiMode())
21963
22122
  return;
@@ -22279,6 +22438,7 @@ class BinaryBridge {
22279
22438
  configOverrides;
22280
22439
  minVersion;
22281
22440
  onVersionMismatch;
22441
+ onConfigureWarnings;
22282
22442
  restartResetTimer = null;
22283
22443
  constructor(binaryPath, cwd, options, configOverrides) {
22284
22444
  this.binaryPath = binaryPath;
@@ -22288,6 +22448,7 @@ class BinaryBridge {
22288
22448
  this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
22289
22449
  this.minVersion = options?.minVersion;
22290
22450
  this.onVersionMismatch = options?.onVersionMismatch;
22451
+ this.onConfigureWarnings = options?.onConfigureWarnings;
22291
22452
  }
22292
22453
  get restartCount() {
22293
22454
  return this._restartCount;
@@ -22312,6 +22473,7 @@ class BinaryBridge {
22312
22473
  if (configResult.success === false) {
22313
22474
  throw new Error(`[aft-plugin] Configure failed: ${configResult.message ?? "unknown error"}`);
22314
22475
  }
22476
+ await this.deliverConfigureWarnings(configResult, params, options);
22315
22477
  await this.checkVersion();
22316
22478
  if (!this.isAlive()) {
22317
22479
  throw new Error(`[aft-plugin] Bridge died during version check. Check logs: ${getLogFilePath()}`);
@@ -22356,6 +22518,23 @@ class BinaryBridge {
22356
22518
  });
22357
22519
  });
22358
22520
  }
22521
+ async deliverConfigureWarnings(configResult, params, options) {
22522
+ if (!this.onConfigureWarnings || !Array.isArray(configResult.warnings))
22523
+ return;
22524
+ if (configResult.warnings.length === 0)
22525
+ return;
22526
+ try {
22527
+ const sessionId = typeof params.session_id === "string" ? params.session_id : undefined;
22528
+ await this.onConfigureWarnings({
22529
+ projectRoot: this.cwd,
22530
+ sessionId,
22531
+ client: options?.configureWarningClient,
22532
+ warnings: configResult.warnings
22533
+ });
22534
+ } catch (err) {
22535
+ warn(`configure warning delivery failed: ${err instanceof Error ? err.message : String(err)}`);
22536
+ }
22537
+ }
22359
22538
  async shutdown() {
22360
22539
  this._shuttingDown = true;
22361
22540
  this.clearRestartResetTimer();
@@ -22598,7 +22777,8 @@ class BridgePool {
22598
22777
  timeoutMs: options.timeoutMs,
22599
22778
  maxRestarts: options.maxRestarts,
22600
22779
  minVersion: options.minVersion,
22601
- onVersionMismatch: options.onVersionMismatch
22780
+ onVersionMismatch: options.onVersionMismatch,
22781
+ onConfigureWarnings: options.onConfigureWarnings
22602
22782
  };
22603
22783
  this.configOverrides = configOverrides;
22604
22784
  if (Number.isFinite(this.idleTimeoutMs)) {
@@ -23538,7 +23718,11 @@ function callBridge(ctx, runtime, command, params = {}) {
23538
23718
  merged.session_id = runtime.sessionID;
23539
23719
  }
23540
23720
  const timeoutMs = timeoutForCommand(command);
23541
- return bridgeFor(ctx, runtime).send(command, merged, timeoutMs !== undefined ? { timeoutMs } : undefined);
23721
+ const sendOptions = {
23722
+ ...timeoutMs !== undefined ? { timeoutMs } : {},
23723
+ configureWarningClient: ctx.client
23724
+ };
23725
+ return bridgeFor(ctx, runtime).send(command, merged, Object.keys(sendOptions).length > 0 ? sendOptions : undefined);
23542
23726
  }
23543
23727
 
23544
23728
  // src/tools/permissions.ts
@@ -23654,8 +23838,24 @@ function astTools(ctx) {
23654
23838
  const filesSearched = data.files_searched ?? 0;
23655
23839
  const filesWithMatches = data.files_with_matches ?? filesSearched;
23656
23840
  let output;
23657
- if (matchCount === 0) {
23841
+ if (data.no_files_matched_scope) {
23842
+ output = "No files matched the scope (paths/globs resolved to zero files)";
23843
+ if (data.scope_warnings && data.scope_warnings.length > 0) {
23844
+ output += `
23845
+
23846
+ Scope warnings:
23847
+ ${data.scope_warnings.map((w) => ` ${w}`).join(`
23848
+ `)}`;
23849
+ }
23850
+ } else if (matchCount === 0) {
23658
23851
  output = `No matches found (searched ${filesSearched} files)`;
23852
+ if (data.scope_warnings && data.scope_warnings.length > 0) {
23853
+ output += `
23854
+
23855
+ Scope warnings:
23856
+ ${data.scope_warnings.map((w) => ` ${w}`).join(`
23857
+ `)}`;
23858
+ }
23659
23859
  const hint = getEmptyResultHint(args.pattern, args.lang);
23660
23860
  if (hint) {
23661
23861
  output += `
@@ -23743,8 +23943,24 @@ ${hint}`;
23743
23943
  const filesSearched = data.files_searched ?? data.total_files ?? 0;
23744
23944
  const filesWithMatches = data.files_with_matches ?? data.total_files ?? filesSearched;
23745
23945
  let output;
23746
- if (matchCount === 0) {
23946
+ if (data.no_files_matched_scope) {
23947
+ output = "No files matched the scope (paths/globs resolved to zero files)";
23948
+ if (data.scope_warnings && data.scope_warnings.length > 0) {
23949
+ output += `
23950
+
23951
+ Scope warnings:
23952
+ ${data.scope_warnings.map((w) => ` ${w}`).join(`
23953
+ `)}`;
23954
+ }
23955
+ } else if (matchCount === 0) {
23747
23956
  output = `No matches found (searched ${filesSearched} files)`;
23957
+ if (data.scope_warnings && data.scope_warnings.length > 0) {
23958
+ output += `
23959
+
23960
+ Scope warnings:
23961
+ ${data.scope_warnings.map((w) => ` ${w}`).join(`
23962
+ `)}`;
23963
+ }
23748
23964
  } else {
23749
23965
  output = isDryRun ? `[DRY RUN] Would replace ${matchCount} match(es) in ${filesWithMatches} file(s) (${filesSearched} searched)
23750
23966
 
@@ -24074,6 +24290,31 @@ function buildUnifiedDiff(fp, before, after) {
24074
24290
  }
24075
24291
  return diff;
24076
24292
  }
24293
+ function lineCount(content) {
24294
+ if (content.length === 0)
24295
+ return 0;
24296
+ const parts = content.split(`
24297
+ `);
24298
+ if (parts[parts.length - 1] === "")
24299
+ parts.pop();
24300
+ return parts.length;
24301
+ }
24302
+ function countDiffLines(before, after) {
24303
+ const beforeLines = before.split(`
24304
+ `);
24305
+ const afterLines = after.split(`
24306
+ `);
24307
+ const ops = diffLines(beforeLines, afterLines);
24308
+ let additions = 0;
24309
+ let deletions = 0;
24310
+ for (const op of ops) {
24311
+ if (op.tag === "ins")
24312
+ additions++;
24313
+ else if (op.tag === "del")
24314
+ deletions++;
24315
+ }
24316
+ return { additions, deletions };
24317
+ }
24077
24318
  function diffLines(a, b) {
24078
24319
  const n = a.length;
24079
24320
  const m = b.length;
@@ -24704,15 +24945,24 @@ function createApplyPatchTool(ctx) {
24704
24945
  switch (hunk.type) {
24705
24946
  case "add": {
24706
24947
  try {
24707
- await callBridge(ctx, context, "write", {
24708
- file: filePath,
24709
- content: hunk.contents.endsWith(`
24948
+ const content = hunk.contents.endsWith(`
24710
24949
  `) ? hunk.contents : `${hunk.contents}
24711
- `,
24950
+ `;
24951
+ const writeResult = await callBridge(ctx, context, "write", {
24952
+ file: filePath,
24953
+ content,
24712
24954
  create_dirs: true,
24713
- diagnostics: true
24955
+ diagnostics: true,
24956
+ include_diff: true
24957
+ });
24958
+ const wrDiff = writeResult.diff;
24959
+ perFileDiffs.push({
24960
+ filePath,
24961
+ before: "",
24962
+ after: hunk.contents,
24963
+ additions: wrDiff?.additions ?? lineCount(content),
24964
+ deletions: wrDiff?.deletions ?? 0
24714
24965
  });
24715
- perFileDiffs.push({ filePath, before: "", after: hunk.contents });
24716
24966
  results.push(`Created ${hunk.path}`);
24717
24967
  } catch (e) {
24718
24968
  patchFailed = true;
@@ -24724,7 +24974,13 @@ function createApplyPatchTool(ctx) {
24724
24974
  try {
24725
24975
  const before = await fs3.promises.readFile(filePath, "utf-8").catch(() => "");
24726
24976
  await callBridge(ctx, context, "delete_file", { file: filePath });
24727
- perFileDiffs.push({ filePath, before, after: "" });
24977
+ perFileDiffs.push({
24978
+ filePath,
24979
+ before,
24980
+ after: "",
24981
+ additions: 0,
24982
+ deletions: lineCount(before)
24983
+ });
24728
24984
  results.push(`Deleted ${hunk.path}`);
24729
24985
  } catch (e) {
24730
24986
  patchFailed = true;
@@ -24741,7 +24997,8 @@ function createApplyPatchTool(ctx) {
24741
24997
  file: targetPath,
24742
24998
  content: newContent,
24743
24999
  create_dirs: true,
24744
- diagnostics: true
25000
+ diagnostics: true,
25001
+ include_diff: true
24745
25002
  });
24746
25003
  const diags = writeResult.lsp_diagnostics;
24747
25004
  if (diags && diags.length > 0) {
@@ -24755,7 +25012,19 @@ LSP errors detected in ${relPath}, please fix:
24755
25012
  ${diagLines}`);
24756
25013
  }
24757
25014
  }
24758
- perFileDiffs.push({ filePath, before: original, after: newContent });
25015
+ const wrDiff = writeResult.diff;
25016
+ const isMove = Boolean(hunk.move_path);
25017
+ const { additions, deletions } = isMove || wrDiff?.additions === undefined || wrDiff.deletions === undefined ? countDiffLines(original, newContent) : {
25018
+ additions: wrDiff.additions,
25019
+ deletions: wrDiff.deletions
25020
+ };
25021
+ perFileDiffs.push({
25022
+ filePath,
25023
+ before: original,
25024
+ after: newContent,
25025
+ additions,
25026
+ deletions
25027
+ });
24759
25028
  if (hunk.move_path) {
24760
25029
  await callBridge(ctx, context, "delete_file", { file: filePath });
24761
25030
  results.push(`Updated and moved ${hunk.path} \u2192 ${hunk.move_path}`);
@@ -24804,20 +25073,6 @@ ${diagLines}`);
24804
25073
  const callID = getCallID(context);
24805
25074
  if (callID) {
24806
25075
  const diffByPath = new Map(perFileDiffs.map((d) => [d.filePath, d]));
24807
- const countAddDel = (patch) => {
24808
- let additions = 0;
24809
- let deletions = 0;
24810
- for (const line of patch.split(`
24811
- `)) {
24812
- if (line.startsWith("---") || line.startsWith("+++"))
24813
- continue;
24814
- if (line.startsWith("+"))
24815
- additions++;
24816
- else if (line.startsWith("-"))
24817
- deletions++;
24818
- }
24819
- return { additions, deletions };
24820
- };
24821
25076
  const files = hunks.map((h) => {
24822
25077
  const filePath = path4.resolve(context.directory, h.path);
24823
25078
  const rawMovePath = h.type === "update" ? h.move_path : undefined;
@@ -24826,7 +25081,8 @@ ${diagLines}`);
24826
25081
  const relPath = path4.relative(context.worktree, displayPath);
24827
25082
  const diffEntry = diffByPath.get(filePath);
24828
25083
  const patch = diffEntry ? buildUnifiedDiff(displayPath, diffEntry.before, diffEntry.after) : "";
24829
- const { additions, deletions } = countAddDel(patch);
25084
+ const additions = diffEntry?.additions ?? 0;
25085
+ const deletions = diffEntry?.deletions ?? 0;
24830
25086
  const uiType = h.type === "update" && rawMovePath ? "move" : h.type;
24831
25087
  return {
24832
25088
  filePath,
@@ -25019,12 +25275,28 @@ import { tool as tool5 } from "@opencode-ai/plugin";
25019
25275
  var z5 = tool5.schema;
25020
25276
  function lspTools(ctx) {
25021
25277
  const diagnosticsTool = {
25022
- description: "Get errors, warnings, hints from a language server. " + "Returns: { diagnostics: Array<{ file, line, column, end_line, end_column, severity, message, code }>, total: number, files_with_errors: number }.",
25278
+ description: "On-demand LSP file/scope check. Spawns the relevant language server (if " + "registered for the file's extension), opens the document, prefers LSP 3.17 " + "pull diagnostics when supported, and falls back to push + waitMs otherwise. " + "NOT a project-wide type checker \u2014 for full coverage run `tsc --noEmit`, " + "`cargo check`, `pyright`, etc.\n" + `
25279
+ ` + `Returns: {
25280
+ ` + ` diagnostics: Array<{file, line, column, end_line, end_column, severity, message, code, source}>,
25281
+ ` + ` total: number,
25282
+ ` + ` files_with_errors: number,
25283
+ ` + ` complete: boolean, // true = trustable absence; false = partial
25284
+ ` + ` lsp_servers_used: Array<{ // honest per-server status
25285
+ ` + ` server_id, scope: 'file'|'workspace', status: 'pull_ok'|'pull_unchanged'|'push_only'|'no_root_marker (...)' |
25286
+ ` + ` 'binary_not_installed: <name>'|'spawn_failed: ...'|'pull_failed: ...'|'workspace_pull_unsupported'|...
25287
+ ` + ` }>,
25288
+ ` + ` unchecked_files?: string[], // directory mode only \u2014 files we have no info for
25289
+ ` + ` walk_truncated?: boolean, // directory walk hit the 200-file cap
25290
+ ` + ` note?: string // present when no LSP server is registered for the file's extension
25291
+ ` + `}
25292
+ ` + `
25293
+ ` + `**Reading the response honestly:**
25294
+ ` + "- `total: 0, complete: true, lsp_servers_used: [{status: 'pull_ok'}]` \u2192 file is genuinely clean.\n" + "- `total: 0, lsp_servers_used: []` \u2192 no server registered for this extension; nothing was checked.\n" + "- `lsp_servers_used: [{status: 'binary_not_installed: bash-language-server'}]` \u2192 install the server to get diagnostics.\n" + "- `complete: false` (directory mode) \u2192 some files in the directory weren't checked; see `unchecked_files`.",
25023
25295
  args: {
25024
- filePath: z5.string().optional().describe("Path to file to get diagnostics for. Provide 'filePath' for a single file, 'directory' for all files under a path, or omit both for all tracked files"),
25025
- directory: z5.string().optional().describe("Path to directory to get diagnostics for all files under it. Mutually exclusive with 'filePath'"),
25026
- severity: z5.enum(["error", "warning", "information", "hint", "all"]).optional().describe("Filter by severity \u2014 'error', 'warning', 'information', 'hint', 'all' (default: 'all')"),
25027
- waitMs: z5.number().optional().describe("Wait N ms for fresh diagnostics before returning (max 10000, default: 0). Use after edits to let the server re-analyze.")
25296
+ filePath: z5.string().optional().describe("Path to a file to check. Mutually exclusive with 'directory'. Omit both to dump all cached diagnostics."),
25297
+ directory: z5.string().optional().describe("Path to a directory. Returns cached diagnostics + workspace pull from active servers; lists files we have no info for in 'unchecked_files'. Capped at 200 walked files."),
25298
+ severity: z5.enum(["error", "warning", "information", "hint", "all"]).optional().describe("Filter by severity (default: 'all')."),
25299
+ waitMs: z5.number().optional().describe("Wait up to N ms (max 10000, default 0) for push diagnostics to arrive. Only matters for servers that don't support LSP 3.17 pull (bash-language-server, yaml-language-server). Use after an edit to let the server re-analyze.")
25028
25300
  },
25029
25301
  execute: async (args, context) => {
25030
25302
  const filePath = args.filePath || undefined;
@@ -25201,20 +25473,20 @@ function readingTools(ctx) {
25201
25473
  if (response2.success === false) {
25202
25474
  throw new Error(response2.message || "outline failed");
25203
25475
  }
25204
- return response2.text;
25476
+ return formatOutlineText(response2);
25205
25477
  }
25206
25478
  if (Array.isArray(args.files) && args.files.length > 0) {
25207
25479
  const response2 = await callBridge(ctx, context, "outline", { files: args.files });
25208
25480
  if (response2.success === false) {
25209
25481
  throw new Error(response2.message || "outline failed");
25210
25482
  }
25211
- return response2.text;
25483
+ return formatOutlineText(response2);
25212
25484
  }
25213
25485
  const response = await callBridge(ctx, context, "outline", { file: args.filePath });
25214
25486
  if (response.success === false) {
25215
25487
  throw new Error(response.message || "outline failed");
25216
25488
  }
25217
- return response.text;
25489
+ return formatOutlineText(response);
25218
25490
  }
25219
25491
  },
25220
25492
  aft_zoom: {
@@ -25311,6 +25583,20 @@ async function discoverSourceFiles(dir, maxFiles = 200) {
25311
25583
  files.sort();
25312
25584
  return files;
25313
25585
  }
25586
+ function formatOutlineText(response) {
25587
+ const text = response.text ?? "";
25588
+ const skipped = response.skipped_files;
25589
+ if (!skipped || skipped.length === 0) {
25590
+ return text;
25591
+ }
25592
+ const lines = skipped.map(({ file: file2, reason }) => ` ${file2} \u2014 ${reason}`).join(`
25593
+ `);
25594
+ const header = text.length > 0 ? `${text}
25595
+
25596
+ ` : "";
25597
+ return `${header}Skipped ${skipped.length} file(s):
25598
+ ${lines}`;
25599
+ }
25314
25600
 
25315
25601
  // src/tools/refactoring.ts
25316
25602
  import { tool as tool8 } from "@opencode-ai/plugin";
@@ -25651,10 +25937,27 @@ function arg2(schema) {
25651
25937
  }
25652
25938
  function semanticTools(ctx) {
25653
25939
  const searchTool = {
25654
- description: "Search code by meaning using semantic similarity. Use when you don't know the exact name or text \u2014 describe what you're looking for in natural language and get the most relevant symbols, functions, and types.",
25940
+ description: [
25941
+ "Find symbols by concept when grep keywords fall short. Returns ranked code matches with similarity scores.",
25942
+ "",
25943
+ "When to reach for it:",
25944
+ "- Exploring an unfamiliar area: 'where is rate limiting handled', 'how does auth flow work'",
25945
+ "- Concept doesn't appear as a literal string: 'retry logic', 'cache invalidation', 'graceful shutdown'",
25946
+ "- After 2+ grep attempts that came back empty or noisy",
25947
+ "- You know roughly what the function does but not what it's named",
25948
+ "",
25949
+ "When NOT to use:",
25950
+ "- You have a specific symbol name \u2192 use grep",
25951
+ "- You have an error message or stack trace \u2192 use grep",
25952
+ "- You want the file/module structure \u2192 use aft_outline",
25953
+ "- You're following a call chain \u2192 use aft_navigate",
25954
+ "",
25955
+ "Scores below ~0.4 are usually weak matches; treat them as 'maybe relevant' and verify with read."
25956
+ ].join(`
25957
+ `),
25655
25958
  args: {
25656
- query: arg2(exports_external.string().describe("Natural language search query")),
25657
- topK: arg2(exports_external.number().optional().describe("Number of results (default: 10)"))
25959
+ query: arg2(exports_external.string().describe("Concept or capability to find, phrased as a programmer would describe the code. Examples: 'fuzzy match with whitespace tolerance', 'undo backup before edit', 'retry failed network request'.")),
25960
+ topK: arg2(exports_external.number().optional().describe("Number of results (default: 10, max: 100)"))
25658
25961
  },
25659
25962
  execute: async (args, context) => {
25660
25963
  const response = await callBridge(ctx, context, "semantic_search", {
@@ -25803,6 +26106,15 @@ function isTuiMode2() {
25803
26106
  function throwSentinel(command) {
25804
26107
  throw new Error(`${SENTINEL_PREFIX}${command.toUpperCase().replace(/-/g, "_")}_HANDLED__`);
25805
26108
  }
26109
+ function isConfigureWarning(value) {
26110
+ if (!value || typeof value !== "object" || Array.isArray(value))
26111
+ return false;
26112
+ const warning = value;
26113
+ return (warning.kind === "formatter_not_installed" || warning.kind === "checker_not_installed" || warning.kind === "lsp_binary_missing") && typeof warning.hint === "string";
26114
+ }
26115
+ function coerceConfigureWarnings(warnings) {
26116
+ return warnings.filter(isConfigureWarning);
26117
+ }
25806
26118
  async function sendIgnoredMessage2(client, sessionID, text) {
25807
26119
  const typedClient = client;
25808
26120
  const promptInput = {
@@ -25849,6 +26161,7 @@ var plugin = async (input) => {
25849
26161
  configOverrides.experimental_search_index = aftConfig.experimental_search_index;
25850
26162
  if (aftConfig.experimental_semantic_search !== undefined)
25851
26163
  configOverrides.experimental_semantic_search = aftConfig.experimental_semantic_search;
26164
+ Object.assign(configOverrides, resolveLspConfigForConfigure(aftConfig));
25852
26165
  if (aftConfig.semantic !== undefined)
25853
26166
  configOverrides.semantic = aftConfig.semantic;
25854
26167
  if (aftConfig.max_callgraph_files !== undefined)
@@ -25890,6 +26203,20 @@ var plugin = async (input) => {
25890
26203
  }, (err) => {
25891
26204
  error48(`Auto-download failed: ${err.message}. Install manually: cargo install agent-file-tools@${minVersion}`);
25892
26205
  });
26206
+ },
26207
+ onConfigureWarnings: async ({ projectRoot, sessionId, client, warnings }) => {
26208
+ if (!sessionId)
26209
+ return;
26210
+ const validWarnings = coerceConfigureWarnings(warnings);
26211
+ if (validWarnings.length === 0)
26212
+ return;
26213
+ await deliverConfigureWarnings({
26214
+ client: client ?? input.client,
26215
+ sessionId,
26216
+ storageDir: configOverrides.storage_dir,
26217
+ pluginVersion: PLUGIN_VERSION,
26218
+ projectRoot
26219
+ }, validWarnings);
25893
26220
  }
25894
26221
  }, configOverrides);
25895
26222
  const ctx = {
@@ -21,6 +21,21 @@ export interface NotificationOptions {
21
21
  /** Server URL for message deletion (optional — from ctx.serverUrl) */
22
22
  serverUrl?: string;
23
23
  }
24
+ export interface ConfigureWarning {
25
+ kind: "formatter_not_installed" | "checker_not_installed" | "lsp_binary_missing";
26
+ language?: string;
27
+ server?: string;
28
+ tool?: string;
29
+ binary?: string;
30
+ hint: string;
31
+ }
32
+ export interface ConfigureWarningOptions {
33
+ client: unknown;
34
+ sessionId: string;
35
+ storageDir: string;
36
+ pluginVersion: string;
37
+ projectRoot?: string;
38
+ }
24
39
  /**
25
40
  * Send a persistent warning notification.
26
41
  * Desktop: ignored message, cleaned up on next startup when resolved.
@@ -40,6 +55,7 @@ export declare function sendStatus(opts: NotificationOptions, message: string):
40
55
  * TUI: toast with info variant.
41
56
  */
42
57
  export declare function sendFeatureAnnouncement(opts: NotificationOptions, version: string, features: string[], storageDir?: string): Promise<void>;
58
+ export declare function deliverConfigureWarnings(opts: ConfigureWarningOptions, warnings: ConfigureWarning[]): Promise<void>;
43
59
  /**
44
60
  * Clean up stale AFT warning messages from previous runs.
45
61
  * Desktop only — TUI toasts are inherently transient and don't need cleanup.
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA+NH,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;;;;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;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;AAiOH,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;AAuED,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 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAY5D,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAU;IACrB,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,YAAY,CAA+C;gBAGjE,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,WAAgB,EACzB,eAAe,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAmB/C;;;;;;;OAOG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAgB5D;;;;;;;OAOG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY;IAmB5C,wEAAwE;IACxE,OAAO,CAAC,OAAO;IAUf,yDAAyD;IACzD,OAAO,CAAC,QAAQ;IAgBhB,wDAAwD;IAClD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAU/B;;;OAGG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnD,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAY5D,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAU;IACrB,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,YAAY,CAA+C;gBAGjE,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,WAAgB,EACzB,eAAe,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAoB/C;;;;;;;OAOG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAgB5D;;;;;;;OAOG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY;IAmB5C,wEAAwE;IACxE,OAAO,CAAC,OAAO;IAUf,yDAAyD;IACzD,OAAO,CAAC,QAAQ;IAgBhB,wDAAwD;IAClD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAU/B;;;OAGG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnD,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQlE,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE;AAED;;;;;;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;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAa3D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAEhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAWlC"}
1
+ {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQlE,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE;AAED;;;;;;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;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAa3D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAEhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAelC"}
@@ -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;AAyCjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAqM3E"}
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;AAyCjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA2N3E"}
@@ -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;AAcjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AA2OtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA4IjE;AAkxBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAS/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAuBnF"}
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;AAcjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AA+QtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA4IjE;AA00BD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAS/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAuBnF"}
@@ -1 +1 @@
1
- {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/tools/lsp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0D3E"}
1
+ {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/tools/lsp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA+E3E"}
@@ -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;AASjD,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAoChF"}
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;AASjD,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAyDhF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.15.5",
3
+ "version": "0.16.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",
@@ -32,11 +32,11 @@
32
32
  "zod": "^4.1.8"
33
33
  },
34
34
  "optionalDependencies": {
35
- "@cortexkit/aft-darwin-arm64": "0.15.5",
36
- "@cortexkit/aft-darwin-x64": "0.15.5",
37
- "@cortexkit/aft-linux-arm64": "0.15.5",
38
- "@cortexkit/aft-linux-x64": "0.15.5",
39
- "@cortexkit/aft-win32-x64": "0.15.5"
35
+ "@cortexkit/aft-darwin-arm64": "0.16.0",
36
+ "@cortexkit/aft-darwin-x64": "0.16.0",
37
+ "@cortexkit/aft-linux-arm64": "0.16.0",
38
+ "@cortexkit/aft-linux-x64": "0.16.0",
39
+ "@cortexkit/aft-win32-x64": "0.16.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^22.0.0",