@databricks/appkit 0.32.0 → 0.33.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.
Files changed (153) hide show
  1. package/CLAUDE.md +53 -1
  2. package/NOTICE.md +1 -0
  3. package/dist/agents/databricks.d.ts.map +1 -1
  4. package/dist/agents/databricks.js +8 -3
  5. package/dist/agents/databricks.js.map +1 -1
  6. package/dist/appkit/package.js +1 -1
  7. package/dist/beta.d.ts +5 -3
  8. package/dist/beta.js +3 -1
  9. package/dist/connectors/mcp/client.d.ts +27 -2
  10. package/dist/connectors/mcp/client.d.ts.map +1 -1
  11. package/dist/connectors/mcp/client.js +117 -18
  12. package/dist/connectors/mcp/client.js.map +1 -1
  13. package/dist/connectors/mcp/index.d.ts +1 -1
  14. package/dist/connectors/mcp/types.d.ts +1 -1
  15. package/dist/core/agent/build-toolkit.js +3 -8
  16. package/dist/core/agent/build-toolkit.js.map +1 -1
  17. package/dist/core/agent/load-agents.d.ts +6 -1
  18. package/dist/core/agent/load-agents.d.ts.map +1 -1
  19. package/dist/core/agent/load-agents.js +67 -27
  20. package/dist/core/agent/load-agents.js.map +1 -1
  21. package/dist/core/agent/plugins-map.js +44 -0
  22. package/dist/core/agent/plugins-map.js.map +1 -0
  23. package/dist/core/agent/run-agent.d.ts +31 -7
  24. package/dist/core/agent/run-agent.d.ts.map +1 -1
  25. package/dist/core/agent/run-agent.js +138 -27
  26. package/dist/core/agent/run-agent.js.map +1 -1
  27. package/dist/core/agent/toolkit-options.js +28 -0
  28. package/dist/core/agent/toolkit-options.js.map +1 -0
  29. package/dist/core/agent/toolkit-resolver.js +44 -0
  30. package/dist/core/agent/toolkit-resolver.js.map +1 -0
  31. package/dist/core/agent/tools/define-tool.d.ts +14 -2
  32. package/dist/core/agent/tools/define-tool.d.ts.map +1 -1
  33. package/dist/core/agent/tools/define-tool.js +1 -1
  34. package/dist/core/agent/tools/define-tool.js.map +1 -1
  35. package/dist/core/agent/tools/function-tool.d.ts +13 -2
  36. package/dist/core/agent/tools/function-tool.d.ts.map +1 -1
  37. package/dist/core/agent/tools/function-tool.js +4 -3
  38. package/dist/core/agent/tools/function-tool.js.map +1 -1
  39. package/dist/core/agent/tools/index.d.ts +1 -1
  40. package/dist/core/agent/tools/tool.d.ts +32 -3
  41. package/dist/core/agent/tools/tool.d.ts.map +1 -1
  42. package/dist/core/agent/tools/tool.js +4 -3
  43. package/dist/core/agent/tools/tool.js.map +1 -1
  44. package/dist/core/agent/types.d.ts +95 -10
  45. package/dist/core/agent/types.d.ts.map +1 -1
  46. package/dist/core/agent/types.js.map +1 -1
  47. package/dist/plugin/index.d.ts +1 -1
  48. package/dist/plugin/to-plugin.d.ts +3 -13
  49. package/dist/plugin/to-plugin.d.ts.map +1 -1
  50. package/dist/plugin/to-plugin.js +1 -8
  51. package/dist/plugin/to-plugin.js.map +1 -1
  52. package/dist/plugins/agents/agents.d.ts +184 -2
  53. package/dist/plugins/agents/agents.d.ts.map +1 -0
  54. package/dist/plugins/agents/agents.js +169 -72
  55. package/dist/plugins/agents/agents.js.map +1 -1
  56. package/dist/plugins/agents/index.d.ts +2 -2
  57. package/dist/plugins/agents/index.js +1 -1
  58. package/dist/plugins/agents/manifest.js +4 -5
  59. package/dist/plugins/agents/tool-approval-gate.js.map +1 -1
  60. package/dist/plugins/analytics/analytics.d.ts +3 -4
  61. package/dist/plugins/analytics/analytics.d.ts.map +1 -1
  62. package/dist/plugins/analytics/analytics.js +8 -6
  63. package/dist/plugins/analytics/analytics.js.map +1 -1
  64. package/dist/plugins/analytics/index.js +1 -0
  65. package/dist/plugins/analytics/types.js +15 -0
  66. package/dist/plugins/analytics/types.js.map +1 -0
  67. package/dist/plugins/beta-exports.generated.d.ts +2 -0
  68. package/dist/plugins/beta-exports.generated.js +4 -0
  69. package/dist/plugins/files/plugin.d.ts +1 -2
  70. package/dist/plugins/files/plugin.d.ts.map +1 -1
  71. package/dist/plugins/files/plugin.js +30 -12
  72. package/dist/plugins/files/plugin.js.map +1 -1
  73. package/dist/plugins/genie/genie.d.ts +5 -4
  74. package/dist/plugins/genie/genie.d.ts.map +1 -1
  75. package/dist/plugins/genie/genie.js +22 -8
  76. package/dist/plugins/genie/genie.js.map +1 -1
  77. package/dist/plugins/genie/types.d.ts +10 -2
  78. package/dist/plugins/genie/types.d.ts.map +1 -1
  79. package/dist/plugins/jobs/plugin.d.ts +1 -2
  80. package/dist/plugins/jobs/plugin.d.ts.map +1 -1
  81. package/dist/plugins/lakebase/lakebase.d.ts +1 -2
  82. package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
  83. package/dist/plugins/lakebase/lakebase.js +3 -3
  84. package/dist/plugins/lakebase/lakebase.js.map +1 -1
  85. package/dist/plugins/lakebase/types.d.ts +5 -4
  86. package/dist/plugins/lakebase/types.d.ts.map +1 -1
  87. package/dist/plugins/server/index.d.ts +3 -2
  88. package/dist/plugins/server/index.d.ts.map +1 -1
  89. package/dist/plugins/server/index.js +8 -5
  90. package/dist/plugins/server/index.js.map +1 -1
  91. package/dist/plugins/server/types.d.ts +11 -0
  92. package/dist/plugins/server/types.d.ts.map +1 -1
  93. package/dist/plugins/serving/serving.d.ts +1 -2
  94. package/dist/plugins/serving/serving.d.ts.map +1 -1
  95. package/dist/shared/src/agent.d.ts +16 -4
  96. package/dist/shared/src/agent.d.ts.map +1 -1
  97. package/docs/api/appkit/Class.AppKitMcpClient.md +157 -0
  98. package/docs/api/appkit/Class.DatabricksAdapter.md +151 -0
  99. package/docs/api/appkit/Function.agentIdFromMarkdownPath.md +18 -0
  100. package/docs/api/appkit/Function.createAgent.md +33 -0
  101. package/docs/api/appkit/Function.defineTool.md +26 -0
  102. package/docs/api/appkit/Function.executeFromRegistry.md +25 -0
  103. package/docs/api/appkit/Function.functionToolToDefinition.md +16 -0
  104. package/docs/api/appkit/Function.isFunctionTool.md +16 -0
  105. package/docs/api/appkit/Function.isHostedTool.md +16 -0
  106. package/docs/api/appkit/Function.isToolkitEntry.md +18 -0
  107. package/docs/api/appkit/Function.loadAgentFromFile.md +21 -0
  108. package/docs/api/appkit/Function.loadAgentsFromDir.md +26 -0
  109. package/docs/api/appkit/Function.mcpServer.md +28 -0
  110. package/docs/api/appkit/Function.parseTextToolCalls.md +26 -0
  111. package/docs/api/appkit/Function.resolveHostedTools.md +16 -0
  112. package/docs/api/appkit/Function.runAgent.md +26 -0
  113. package/docs/api/appkit/Function.tool.md +28 -0
  114. package/docs/api/appkit/Function.toolsFromRegistry.md +20 -0
  115. package/docs/api/appkit/Interface.AgentAdapter.md +21 -0
  116. package/docs/api/appkit/Interface.AgentDefinition.md +112 -0
  117. package/docs/api/appkit/Interface.AgentInput.md +37 -0
  118. package/docs/api/appkit/Interface.AgentRunContext.md +32 -0
  119. package/docs/api/appkit/Interface.AgentToolDefinition.md +37 -0
  120. package/docs/api/appkit/Interface.AgentsPluginConfig.md +241 -0
  121. package/docs/api/appkit/Interface.AutoInheritToolsConfig.md +27 -0
  122. package/docs/api/appkit/Interface.BasePluginConfig.md +1 -0
  123. package/docs/api/appkit/Interface.FunctionTool.md +80 -0
  124. package/docs/api/appkit/Interface.McpConnectAllResult.md +38 -0
  125. package/docs/api/appkit/Interface.Message.md +55 -0
  126. package/docs/api/appkit/Interface.PluginToolkitProvider.md +22 -0
  127. package/docs/api/appkit/Interface.PromptContext.md +30 -0
  128. package/docs/api/appkit/Interface.RegisteredAgent.md +75 -0
  129. package/docs/api/appkit/Interface.RunAgentInput.md +34 -0
  130. package/docs/api/appkit/Interface.RunAgentResult.md +23 -0
  131. package/docs/api/appkit/Interface.Thread.md +46 -0
  132. package/docs/api/appkit/Interface.ThreadStore.md +103 -0
  133. package/docs/api/appkit/Interface.ToolAnnotations.md +56 -0
  134. package/docs/api/appkit/Interface.ToolConfig.md +72 -0
  135. package/docs/api/appkit/Interface.ToolEntry.md +73 -0
  136. package/docs/api/appkit/Interface.ToolProvider.md +38 -0
  137. package/docs/api/appkit/Interface.ToolkitEntry.md +59 -0
  138. package/docs/api/appkit/Interface.ToolkitOptions.md +45 -0
  139. package/docs/api/appkit/TypeAlias.AgentEvent.md +299 -0
  140. package/docs/api/appkit/TypeAlias.AgentTool.md +11 -0
  141. package/docs/api/appkit/TypeAlias.AgentTools.md +8 -0
  142. package/docs/api/appkit/TypeAlias.AgentToolsFn.md +20 -0
  143. package/docs/api/appkit/TypeAlias.BaseSystemPromptOption.md +9 -0
  144. package/docs/api/appkit/TypeAlias.HostedTool.md +10 -0
  145. package/docs/api/appkit/TypeAlias.Plugins.md +26 -0
  146. package/docs/api/appkit/TypeAlias.ResolvedToolEntry.md +29 -0
  147. package/docs/api/appkit/TypeAlias.ToolRegistry.md +6 -0
  148. package/docs/api/appkit/Variable.agents.md +19 -0
  149. package/docs/api/appkit.md +113 -62
  150. package/docs/plugins/agents.md +441 -0
  151. package/llms.txt +53 -1
  152. package/package.json +1 -1
  153. package/sbom.cdx.json +1 -1
@@ -6,8 +6,16 @@ import "../../connectors/genie/index.js";
6
6
 
7
7
  //#region src/plugins/genie/types.d.ts
8
8
  interface IGenieConfig extends BasePluginConfig {
9
- /** Map of alias → Genie Space ID. Defaults to { default: DATABRICKS_GENIE_SPACE_ID } if omitted. */
10
- spaces?: Record<string, string>;
9
+ /**
10
+ * Map of alias → Genie Space ID. Defaults to { default: DATABRICKS_GENIE_SPACE_ID } if omitted.
11
+ *
12
+ * Values are typed as `string | undefined` so callers can pass `process.env.X`
13
+ * directly (which is `string | undefined`) without a hoist-and-narrow dance.
14
+ * At construction the plugin validates that every configured alias has a
15
+ * defined ID — undefined values throw a clear error so a missing env var
16
+ * fails fast rather than masquerading as an unknown-alias 404 at request time.
17
+ */
18
+ spaces?: Record<string, string | undefined>;
11
19
  /** Genie polling timeout in ms. Set to 0 for indefinite. Default: 120000 (2 min) */
12
20
  timeout?: number;
13
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/plugins/genie/types.ts"],"mappings":";;;;;;;UAMiB,YAAA,SAAqB,gBAAA;;EAEpC,MAAA,GAAS,MAAA;;EAET,OAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/plugins/genie/types.ts"],"mappings":";;;;;;;UAMiB,YAAA,SAAqB,gBAAA;;;;AAAtC;;;;;;EAUE,MAAA,GAAS,MAAA;EAET;EAAA,OAAA;AAAA"}
@@ -1,7 +1,6 @@
1
1
  import { IAppRouter, ToPlugin } from "../../shared/src/plugin.js";
2
2
  import "../../shared/src/index.js";
3
3
  import { Plugin } from "../../plugin/plugin.js";
4
- import { NamedPluginFactory } from "../../plugin/to-plugin.js";
5
4
  import "../../plugin/index.js";
6
5
  import { PluginManifest, ResourceRequirement } from "../../registry/types.js";
7
6
  import "../../registry/index.js";
@@ -61,7 +60,7 @@ declare class JobsPlugin extends Plugin {
61
60
  /**
62
61
  * @internal
63
62
  */
64
- declare const jobs: ToPlugin<typeof JobsPlugin, IJobsConfig, string> & NamedPluginFactory<string>;
63
+ declare const jobs: ToPlugin<typeof JobsPlugin, IJobsConfig, string>;
65
64
  //#endregion
66
65
  export { jobs };
67
66
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../src/plugins/jobs/plugin.ts"],"mappings":";;;;;;;;;;cAsFM,UAAA,SAAmB,MAAA;EAAA,OAChB,QAAA,EAAuB,cAAA;EAAA,UAEZ,MAAA,EAAQ,WAAA;EAAA,QAClB,SAAA;EAAA,QACA,MAAA;EAAA,QACA,UAAA;EAAA,QACA,OAAA;EAPO;;;;EAAA,OAaR,YAAA,CAAa,MAAA,EAAQ,WAAA,GAAc,MAAA,SAAe,SAAA;EAAA;;;;EAAA,OAgClD,uBAAA,CAAwB,MAAA,EAAQ,WAAA,GAAc,mBAAA;cAqBzC,MAAA,EAAQ,WAAA;EA0Bd,KAAA,CAAA,GAAK,OAAA;EAAA,YAMC,MAAA,CAAA;EAAA,QAIJ,QAAA;EAAA,QAcA,aAAA;EAAA,QAYA,cAAA;EAhIqB;;;;EAAA,QA6IrB,eAAA;EA1IU;;;;EAAA,UAoKR,YAAA,CAAa,MAAA,WAAiB,MAAA;EAhKhC;;;;EAAA,QAsXA,WAAA;EAAA,QA0BA,gBAAA;EA1WD;;;;;EAAA,QAsXC,eAAA;EAAA,QAuCM,UAAA;EA4Cd,YAAA,CAAa,MAAA,EAAQ,UAAA;EA6IrB,OAAA,CAAA,GAAW,UAAA;EAsBX,YAAA,CAAA,GAAgB,MAAA;AAAA;;;;cAiBL,IAAA,EAAI,QAAA,QAAA,UAAA,EAAA,WAAA,YAAA,kBAAA"}
1
+ {"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../src/plugins/jobs/plugin.ts"],"mappings":";;;;;;;;;cAsFM,UAAA,SAAmB,MAAA;EAAA,OAChB,QAAA,EAAuB,cAAA;EAAA,UAEZ,MAAA,EAAQ,WAAA;EAAA,QAClB,SAAA;EAAA,QACA,MAAA;EAAA,QACA,UAAA;EAAA,QACA,OAAA;;;;;SAMD,YAAA,CAAa,MAAA,EAAQ,WAAA,GAAc,MAAA,SAAe,SAAA;EAAf;;;;EAAA,OAgCnC,uBAAA,CAAwB,MAAA,EAAQ,WAAA,GAAc,mBAAA;cAqBzC,MAAA,EAAQ,WAAA;EA0Bd,KAAA,CAAA,GAAK,OAAA;EAAA,YAMC,MAAA,CAAA;EAAA,QAIJ,QAAA;EAAA,QAcA,aAAA;EAAA,QAYA,cAAA;EAhIqB;;;;EAAA,QA6IrB,eAAA;EA1IkB;;;;EAAA,UAoKhB,YAAA,CAAa,MAAA,WAAiB,MAAA;EA1JjC;;;;EAAA,QAgXC,WAAA;EAAA,QA0BA,gBAAA;EA1W+B;;;;;EAAA,QAsX/B,eAAA;EAAA,QAuCM,UAAA;EA4Cd,YAAA,CAAa,MAAA,EAAQ,UAAA;EA6IrB,OAAA,CAAA,GAAW,UAAA;EAsBX,YAAA,CAAA,GAAgB,MAAA;AAAA;;;;cAiBL,IAAA,EAAI,QAAA,QAAA,UAAA,EAAA,WAAA"}
@@ -3,7 +3,6 @@ import { ToPlugin } from "../../shared/src/plugin.js";
3
3
  import "../../shared/src/index.js";
4
4
  import { ToolkitEntry, ToolkitOptions } from "../../core/agent/types.js";
5
5
  import { Plugin } from "../../plugin/plugin.js";
6
- import { NamedPluginFactory } from "../../plugin/to-plugin.js";
7
6
  import "../../plugin/index.js";
8
7
  import { PluginManifest } from "../../registry/types.js";
9
8
  import "../../registry/index.js";
@@ -141,7 +140,7 @@ declare class LakebasePlugin extends Plugin implements ToolProvider {
141
140
  /**
142
141
  * @internal
143
142
  */
144
- declare const lakebase: ToPlugin<typeof LakebasePlugin, ILakebaseConfig, "lakebase"> & NamedPluginFactory<"lakebase">;
143
+ declare const lakebase: ToPlugin<typeof LakebasePlugin, ILakebaseConfig, "lakebase">;
145
144
  //#endregion
146
145
  export { LakebasePlugin, lakebase };
147
146
  //# sourceMappingURL=lakebase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lakebase.d.ts","names":[],"sources":["../../../src/plugins/lakebase/lakebase.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA;;;;;;cAAa,cAAA,SAAuB,MAAA,YAAkB,YAAA;EAuC7B;EAAA,OArChB,QAAA,EAAuB,cAAA;EAAA,UAEZ,MAAA,EAAQ,eAAA;EAAA,QAClB,IAAA;EAsJS;;;;;;;EA7IX,KAAA,CAAA,GAAK,OAAA;EAyBY;;;;;;;;;;;;;;;EAHjB,KAAA,WAAgB,cAAA,OAAA,CACpB,IAAA,UACA,MAAA,eACC,OAAA,CAAQ,WAAA,CAAY,CAAA;EArCO;;;;;;;;;;;;;;EAAA,QAwDhB,oBAAA;EAuBd;;;;EAAA,qBAAA,CAAA;EAuCQ;;;;;;;;EA2CL;;;;;EAAA,QAzDK,KAAA;cAEI,MAAA,EAAQ,eAAA;EAAA,QAYZ,cAAA;EAmCR,aAAA,CAAA,GAAiB,mBAAA;EAIX,gBAAA,CACJ,IAAA,UACA,IAAA,WACA,MAAA,GAAS,WAAA,GACR,OAAA;EAIH,OAAA,CAAQ,IAAA,GAJE,cAAA,GAIoD,MAAA,SAAA,YAAA;EAI9D,OAAA,CAAA;;sBAvIsB,cAAA,QAAc,IAAA,UACtB,MAAA,iBAEX,OAAA,CAAQ,WAAA,CAAY,CAAA;;;;;;;;;;iBA5ByB,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA8KrC,QAAA,EAAQ,QAAA,QAAA,cAAA,EAAA,eAAA,gBAAA,kBAAA"}
1
+ {"version":3,"file":"lakebase.d.ts","names":[],"sources":["../../../src/plugins/lakebase/lakebase.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyCA;;;;;;;cAAa,cAAA,SAAuB,MAAA,YAAkB,YAAA;EAuCzC;EAAA,OArCJ,QAAA,EAAuB,cAAA;EAAA,UAEZ,MAAA,EAAQ,eAAA;EAAA,QAClB,IAAA;EAoKG;;;;;;;EA3JL,KAAA,CAAA,GAAK,OAAA;EAyBA;;;;;;;;;;;;;;;EAHL,KAAA,WAAgB,cAAA,OAAA,CACpB,IAAA,UACA,MAAA,eACC,OAAA,CAAQ,WAAA,CAAY,CAAA;EAnCL;;;;;;;;;;;;;;EAAA,QAsDJ,oBAAA;EAgDN;;;;EAzBR,qBAAA,CAAA;EAiFA;;;;;;;;EAYA;;;;;EAAA,QApEQ,KAAA;cAEI,MAAA,EAAQ,eAAA;EAAA,QAYZ,cAAA;EA0CR,aAAA,CAAA,GAAiB,mBAAA;EAIX,gBAAA,CACJ,IAAA,UACA,IAAA,WACA,MAAA,GAAS,WAAA,GACR,OAAA;EAIH,OAAA,CAAQ,IAAA,GAJE,cAAA,GAIoD,MAAA,SAAA,YAAA;EAI9D,OAAA,CAAA;;sBA9IsB,cAAA,QAAc,IAAA,UACtB,MAAA,iBAEX,OAAA,CAAQ,WAAA,CAAY,CAAA;;;;;;;;;;iBA5ByB,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqLrC,QAAA,EAAQ,QAAA,QAAA,cAAA,EAAA,eAAA"}
@@ -138,11 +138,11 @@ var LakebasePlugin = class extends Plugin {
138
138
  values: z.array(z.unknown()).optional().describe("Parameter values corresponding to placeholders")
139
139
  }),
140
140
  annotations: {
141
- readOnly,
142
- destructive: !readOnly,
141
+ effect: readOnly ? "read" : "destructive",
143
142
  idempotent: false
144
143
  },
145
- handler: async (args) => {
144
+ execute: async (args, signal) => {
145
+ signal?.throwIfAborted();
146
146
  if (readOnly) {
147
147
  assertReadOnlySql(args.text);
148
148
  return this.runReadOnlyStatement(args.text, args.values);
@@ -1 +1 @@
1
- {"version":3,"file":"lakebase.js","names":["manifest"],"sources":["../../../src/plugins/lakebase/lakebase.ts"],"sourcesContent":["import type { Pool, QueryResult, QueryResultRow } from \"pg\";\nimport type { AgentToolDefinition, ToolProvider } from \"shared\";\nimport { z } from \"zod\";\nimport {\n createLakebasePool,\n getLakebaseOrmConfig,\n getLakebasePgConfig,\n getUsernameWithApiLookup,\n} from \"../../connectors/lakebase\";\nimport { buildToolkitEntries } from \"../../core/agent/build-toolkit\";\nimport {\n defineTool,\n executeFromRegistry,\n toolsFromRegistry,\n} from \"../../core/agent/tools/define-tool\";\nimport { assertReadOnlySql } from \"../../core/agent/tools/sql-policy\";\nimport { createLogger } from \"../../logging/logger\";\nimport { Plugin, toPlugin } from \"../../plugin\";\nimport type { PluginManifest } from \"../../registry\";\nimport manifest from \"./manifest.json\";\nimport type { ILakebaseConfig } from \"./types\";\n\nconst logger = createLogger(\"lakebase\");\n\n/**\n * AppKit plugin for Databricks Lakebase Autoscaling.\n *\n * Wraps `@databricks/lakebase` to provide a standard `pg.Pool` with automatic\n * OAuth token refresh, integrated with AppKit's logger and OpenTelemetry setup.\n *\n * @example\n * ```ts\n * import { createApp, lakebase, server } from \"@databricks/appkit\";\n *\n * const AppKit = await createApp({\n * plugins: [server(), lakebase()],\n * });\n *\n * const result = await AppKit.lakebase.query(\"SELECT * FROM users WHERE id = $1\", [userId]);\n * ```\n */\nexport class LakebasePlugin extends Plugin implements ToolProvider {\n /** Plugin manifest declaring metadata and resource requirements */\n static manifest = manifest as PluginManifest<\"lakebase\">;\n\n protected declare config: ILakebaseConfig;\n private pool: Pool | null = null;\n\n /**\n * Initializes the Lakebase connection pool.\n * Called automatically by AppKit during the plugin setup phase.\n *\n * Resolves the PostgreSQL username via {@link getUsernameWithApiLookup},\n * which tries config, env vars, and finally the Databricks workspace API.\n */\n async setup() {\n const poolConfig = this.config.pool;\n const user = await getUsernameWithApiLookup(poolConfig);\n this.pool = createLakebasePool({ ...poolConfig, user });\n logger.info(\"Lakebase pool initialized\");\n }\n\n /**\n * Executes a parameterized SQL query against the Lakebase pool.\n *\n * @param text - SQL query string, using `$1`, `$2`, ... placeholders\n * @param values - Parameter values corresponding to placeholders\n * @returns Query result with typed rows\n *\n * @example\n * ```ts\n * const result = await AppKit.lakebase.query<{ id: number; name: string }>(\n * \"SELECT id, name FROM users WHERE active = $1\",\n * [true],\n * );\n * ```\n */\n async query<T extends QueryResultRow = any>(\n text: string,\n values?: unknown[],\n ): Promise<QueryResult<T>> {\n // biome-ignore lint/style/noNonNullAssertion: pool is guaranteed non-null after setup(), which AppKit always awaits before exposing the plugin API\n return this.pool!.query<T>(text, values);\n }\n\n /**\n * Execute a single statement inside a `BEGIN READ ONLY … ROLLBACK`\n * transaction on a dedicated client.\n *\n * The three commands MUST share a connection — a naive\n * `pool.query(\"BEGIN READ ONLY; <stmt>; ROLLBACK\")` batch cannot accept\n * parameter values (PostgreSQL's Extended Query protocol rejects multi-\n * statement prepared queries), which would silently break every\n * parameterized query the agent tool issues.\n *\n * Returns the raw `rows` array for the user's statement. Side effects the\n * statement may attempt (writes, writable-function side effects) are\n * rejected by PostgreSQL under the read-only transaction posture.\n */\n private async runReadOnlyStatement(\n text: string,\n values?: unknown[],\n ): Promise<unknown[]> {\n // biome-ignore lint/style/noNonNullAssertion: pool is guaranteed non-null after setup()\n const client = await this.pool!.connect();\n try {\n await client.query(\"BEGIN READ ONLY\");\n const result = await client.query(text, values);\n return result.rows;\n } finally {\n try {\n await client.query(\"ROLLBACK\");\n } finally {\n client.release();\n }\n }\n }\n\n /**\n * Gracefully drains and closes the connection pool.\n * Called automatically by AppKit during shutdown.\n */\n abortActiveOperations(): void {\n super.abortActiveOperations();\n if (this.pool) {\n logger.info(\"Closing Lakebase pool\");\n this.pool.end().catch((err) => {\n logger.error(\"Error closing Lakebase pool: %O\", err);\n });\n this.pool = null;\n }\n }\n\n /**\n * Returns the plugin's public API, accessible via `AppKit.lakebase`.\n *\n * - `pool` — The raw `pg.Pool` instance, for use with ORMs or advanced scenarios\n * - `query` — Convenience method for executing parameterized SQL queries\n * - `getOrmConfig()` — Returns a config object compatible with Drizzle, TypeORM, Sequelize, etc.\n * - `getPgConfig()` — Returns a `pg.PoolConfig` object for manual pool construction\n */\n\n /**\n * Agent tool registry. Empty by default — the Lakebase plugin does NOT\n * expose its SQL connection to LLM agents unless the developer explicitly\n * opts in via `config.exposeAsAgentTool`. See {@link buildQueryTool}.\n */\n private tools: Record<string, ReturnType<typeof this.buildQueryTool>> = {};\n\n constructor(config: ILakebaseConfig) {\n super(config);\n this.config = config;\n if (config.exposeAsAgentTool) {\n this.tools = { query: this.buildQueryTool(config.exposeAsAgentTool) };\n logger.warn(\n \"Lakebase agent tool is enabled (readOnly=%s). Every agent with access to this plugin can execute SQL against the Lakebase database as the service principal.\",\n config.exposeAsAgentTool.readOnly !== false,\n );\n }\n }\n\n private buildQueryTool(\n opt: NonNullable<ILakebaseConfig[\"exposeAsAgentTool\"]>,\n ) {\n const readOnly = opt.readOnly !== false;\n return defineTool({\n description: readOnly\n ? \"Execute a read-only SQL query against the Lakebase PostgreSQL database. Only SELECT, WITH, SHOW, EXPLAIN, and DESCRIBE statements are accepted. Use $1, $2, etc. as placeholders and pass values separately. Runs as the application's service principal.\"\n : \"Execute a parameterized SQL statement against the Lakebase PostgreSQL database. Use $1, $2, etc. as placeholders and pass values separately. Runs as the application's service principal. This tool can modify data; every invocation requires explicit human approval.\",\n schema: z.object({\n text: z\n .string()\n .describe(\n \"SQL statement with $1, $2, ... placeholders for parameters\",\n ),\n values: z\n .array(z.unknown())\n .optional()\n .describe(\"Parameter values corresponding to placeholders\"),\n }),\n annotations: {\n readOnly,\n destructive: !readOnly,\n idempotent: false,\n },\n handler: async (args) => {\n if (readOnly) {\n assertReadOnlySql(args.text);\n return this.runReadOnlyStatement(args.text, args.values);\n }\n const result = await this.query(args.text, args.values);\n return result.rows;\n },\n });\n }\n\n getAgentTools(): AgentToolDefinition[] {\n return toolsFromRegistry(this.tools);\n }\n\n async executeAgentTool(\n name: string,\n args: unknown,\n signal?: AbortSignal,\n ): Promise<unknown> {\n return executeFromRegistry(this.tools, name, args, signal);\n }\n\n toolkit(opts?: import(\"../../core/agent/types\").ToolkitOptions) {\n return buildToolkitEntries(this.name, this.tools, opts);\n }\n\n exports() {\n return {\n // biome-ignore lint/style/noNonNullAssertion: pool is guaranteed non-null after setup(), which AppKit always awaits before exposing the plugin API\n pool: this.pool!,\n query: this.query.bind(this),\n getOrmConfig: () => getLakebaseOrmConfig(this.config.pool),\n getPgConfig: () => getLakebasePgConfig(this.config.pool),\n };\n }\n}\n\n/**\n * @internal\n */\nexport const lakebase = toPlugin(LakebasePlugin);\n"],"mappings":";;;;;;;;;;;;AAsBA,MAAM,SAAS,aAAa,WAAW;;;;;;;;;;;;;;;;;;AAmBvC,IAAa,iBAAb,cAAoC,OAA+B;;CAEjE,OAAO,WAAWA;CAGlB,AAAQ,OAAoB;;;;;;;;CAS5B,MAAM,QAAQ;EACZ,MAAM,aAAa,KAAK,OAAO;EAC/B,MAAM,OAAO,MAAM,yBAAyB,WAAW;AACvD,OAAK,OAAO,mBAAmB;GAAE,GAAG;GAAY;GAAM,CAAC;AACvD,SAAO,KAAK,4BAA4B;;;;;;;;;;;;;;;;;CAkB1C,MAAM,MACJ,MACA,QACyB;AAEzB,SAAO,KAAK,KAAM,MAAS,MAAM,OAAO;;;;;;;;;;;;;;;;CAiB1C,MAAc,qBACZ,MACA,QACoB;EAEpB,MAAM,SAAS,MAAM,KAAK,KAAM,SAAS;AACzC,MAAI;AACF,SAAM,OAAO,MAAM,kBAAkB;AAErC,WADe,MAAM,OAAO,MAAM,MAAM,OAAO,EACjC;YACN;AACR,OAAI;AACF,UAAM,OAAO,MAAM,WAAW;aACtB;AACR,WAAO,SAAS;;;;;;;;CAStB,wBAA8B;AAC5B,QAAM,uBAAuB;AAC7B,MAAI,KAAK,MAAM;AACb,UAAO,KAAK,wBAAwB;AACpC,QAAK,KAAK,KAAK,CAAC,OAAO,QAAQ;AAC7B,WAAO,MAAM,mCAAmC,IAAI;KACpD;AACF,QAAK,OAAO;;;;;;;;;;;;;;;;CAkBhB,AAAQ,QAAgE,EAAE;CAE1E,YAAY,QAAyB;AACnC,QAAM,OAAO;AACb,OAAK,SAAS;AACd,MAAI,OAAO,mBAAmB;AAC5B,QAAK,QAAQ,EAAE,OAAO,KAAK,eAAe,OAAO,kBAAkB,EAAE;AACrE,UAAO,KACL,gKACA,OAAO,kBAAkB,aAAa,MACvC;;;CAIL,AAAQ,eACN,KACA;EACA,MAAM,WAAW,IAAI,aAAa;AAClC,SAAO,WAAW;GAChB,aAAa,WACT,8PACA;GACJ,QAAQ,EAAE,OAAO;IACf,MAAM,EACH,QAAQ,CACR,SACC,6DACD;IACH,QAAQ,EACL,MAAM,EAAE,SAAS,CAAC,CAClB,UAAU,CACV,SAAS,iDAAiD;IAC9D,CAAC;GACF,aAAa;IACX;IACA,aAAa,CAAC;IACd,YAAY;IACb;GACD,SAAS,OAAO,SAAS;AACvB,QAAI,UAAU;AACZ,uBAAkB,KAAK,KAAK;AAC5B,YAAO,KAAK,qBAAqB,KAAK,MAAM,KAAK,OAAO;;AAG1D,YADe,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,OAAO,EACzC;;GAEjB,CAAC;;CAGJ,gBAAuC;AACrC,SAAO,kBAAkB,KAAK,MAAM;;CAGtC,MAAM,iBACJ,MACA,MACA,QACkB;AAClB,SAAO,oBAAoB,KAAK,OAAO,MAAM,MAAM,OAAO;;CAG5D,QAAQ,MAAwD;AAC9D,SAAO,oBAAoB,KAAK,MAAM,KAAK,OAAO,KAAK;;CAGzD,UAAU;AACR,SAAO;GAEL,MAAM,KAAK;GACX,OAAO,KAAK,MAAM,KAAK,KAAK;GAC5B,oBAAoB,qBAAqB,KAAK,OAAO,KAAK;GAC1D,mBAAmB,oBAAoB,KAAK,OAAO,KAAK;GACzD;;;;;;AAOL,MAAa,WAAW,SAAS,eAAe"}
1
+ {"version":3,"file":"lakebase.js","names":["manifest"],"sources":["../../../src/plugins/lakebase/lakebase.ts"],"sourcesContent":["import type { Pool, QueryResult, QueryResultRow } from \"pg\";\nimport type { AgentToolDefinition, ToolProvider } from \"shared\";\nimport { z } from \"zod\";\nimport {\n createLakebasePool,\n getLakebaseOrmConfig,\n getLakebasePgConfig,\n getUsernameWithApiLookup,\n} from \"../../connectors/lakebase\";\nimport { buildToolkitEntries } from \"../../core/agent/build-toolkit\";\nimport {\n defineTool,\n executeFromRegistry,\n toolsFromRegistry,\n} from \"../../core/agent/tools/define-tool\";\nimport { assertReadOnlySql } from \"../../core/agent/tools/sql-policy\";\nimport { createLogger } from \"../../logging/logger\";\nimport { Plugin, toPlugin } from \"../../plugin\";\nimport type { PluginManifest } from \"../../registry\";\nimport manifest from \"./manifest.json\";\nimport type { ILakebaseConfig } from \"./types\";\n\nconst logger = createLogger(\"lakebase\");\n\n/**\n * AppKit plugin for Databricks Lakebase Autoscaling.\n *\n * Wraps `@databricks/lakebase` to provide a standard `pg.Pool` with automatic\n * OAuth token refresh, integrated with AppKit's logger and OpenTelemetry setup.\n *\n * @example\n * ```ts\n * import { createApp, lakebase, server } from \"@databricks/appkit\";\n *\n * const AppKit = await createApp({\n * plugins: [server(), lakebase()],\n * });\n *\n * const result = await AppKit.lakebase.query(\"SELECT * FROM users WHERE id = $1\", [userId]);\n * ```\n */\nexport class LakebasePlugin extends Plugin implements ToolProvider {\n /** Plugin manifest declaring metadata and resource requirements */\n static manifest = manifest as PluginManifest<\"lakebase\">;\n\n protected declare config: ILakebaseConfig;\n private pool: Pool | null = null;\n\n /**\n * Initializes the Lakebase connection pool.\n * Called automatically by AppKit during the plugin setup phase.\n *\n * Resolves the PostgreSQL username via {@link getUsernameWithApiLookup},\n * which tries config, env vars, and finally the Databricks workspace API.\n */\n async setup() {\n const poolConfig = this.config.pool;\n const user = await getUsernameWithApiLookup(poolConfig);\n this.pool = createLakebasePool({ ...poolConfig, user });\n logger.info(\"Lakebase pool initialized\");\n }\n\n /**\n * Executes a parameterized SQL query against the Lakebase pool.\n *\n * @param text - SQL query string, using `$1`, `$2`, ... placeholders\n * @param values - Parameter values corresponding to placeholders\n * @returns Query result with typed rows\n *\n * @example\n * ```ts\n * const result = await AppKit.lakebase.query<{ id: number; name: string }>(\n * \"SELECT id, name FROM users WHERE active = $1\",\n * [true],\n * );\n * ```\n */\n async query<T extends QueryResultRow = any>(\n text: string,\n values?: unknown[],\n ): Promise<QueryResult<T>> {\n // biome-ignore lint/style/noNonNullAssertion: pool is guaranteed non-null after setup(), which AppKit always awaits before exposing the plugin API\n return this.pool!.query<T>(text, values);\n }\n\n /**\n * Execute a single statement inside a `BEGIN READ ONLY … ROLLBACK`\n * transaction on a dedicated client.\n *\n * The three commands MUST share a connection — a naive\n * `pool.query(\"BEGIN READ ONLY; <stmt>; ROLLBACK\")` batch cannot accept\n * parameter values (PostgreSQL's Extended Query protocol rejects multi-\n * statement prepared queries), which would silently break every\n * parameterized query the agent tool issues.\n *\n * Returns the raw `rows` array for the user's statement. Side effects the\n * statement may attempt (writes, writable-function side effects) are\n * rejected by PostgreSQL under the read-only transaction posture.\n */\n private async runReadOnlyStatement(\n text: string,\n values?: unknown[],\n ): Promise<unknown[]> {\n // biome-ignore lint/style/noNonNullAssertion: pool is guaranteed non-null after setup()\n const client = await this.pool!.connect();\n try {\n await client.query(\"BEGIN READ ONLY\");\n const result = await client.query(text, values);\n return result.rows;\n } finally {\n try {\n await client.query(\"ROLLBACK\");\n } finally {\n client.release();\n }\n }\n }\n\n /**\n * Gracefully drains and closes the connection pool.\n * Called automatically by AppKit during shutdown.\n */\n abortActiveOperations(): void {\n super.abortActiveOperations();\n if (this.pool) {\n logger.info(\"Closing Lakebase pool\");\n this.pool.end().catch((err) => {\n logger.error(\"Error closing Lakebase pool: %O\", err);\n });\n this.pool = null;\n }\n }\n\n /**\n * Returns the plugin's public API, accessible via `AppKit.lakebase`.\n *\n * - `pool` — The raw `pg.Pool` instance, for use with ORMs or advanced scenarios\n * - `query` — Convenience method for executing parameterized SQL queries\n * - `getOrmConfig()` — Returns a config object compatible with Drizzle, TypeORM, Sequelize, etc.\n * - `getPgConfig()` — Returns a `pg.PoolConfig` object for manual pool construction\n */\n\n /**\n * Agent tool registry. Empty by default — the Lakebase plugin does NOT\n * expose its SQL connection to LLM agents unless the developer explicitly\n * opts in via `config.exposeAsAgentTool`. See {@link buildQueryTool}.\n */\n private tools: Record<string, ReturnType<typeof this.buildQueryTool>> = {};\n\n constructor(config: ILakebaseConfig) {\n super(config);\n this.config = config;\n if (config.exposeAsAgentTool) {\n this.tools = { query: this.buildQueryTool(config.exposeAsAgentTool) };\n logger.warn(\n \"Lakebase agent tool is enabled (readOnly=%s). Every agent with access to this plugin can execute SQL against the Lakebase database as the service principal.\",\n config.exposeAsAgentTool.readOnly !== false,\n );\n }\n }\n\n private buildQueryTool(\n opt: NonNullable<ILakebaseConfig[\"exposeAsAgentTool\"]>,\n ) {\n const readOnly = opt.readOnly !== false;\n return defineTool({\n description: readOnly\n ? \"Execute a read-only SQL query against the Lakebase PostgreSQL database. Only SELECT, WITH, SHOW, EXPLAIN, and DESCRIBE statements are accepted. Use $1, $2, etc. as placeholders and pass values separately. Runs as the application's service principal.\"\n : \"Execute a parameterized SQL statement against the Lakebase PostgreSQL database. Use $1, $2, etc. as placeholders and pass values separately. Runs as the application's service principal. This tool can modify data; every invocation requires explicit human approval.\",\n schema: z.object({\n text: z\n .string()\n .describe(\n \"SQL statement with $1, $2, ... placeholders for parameters\",\n ),\n values: z\n .array(z.unknown())\n .optional()\n .describe(\"Parameter values corresponding to placeholders\"),\n }),\n annotations: {\n effect: readOnly ? \"read\" : \"destructive\",\n idempotent: false,\n },\n execute: async (args, signal) => {\n // Matches the files plugin pattern: the pg connection API\n // doesn't accept AbortSignal in its current shape, so deeper\n // mid-call cancellation needs a separate plumbing pass on the\n // connector. This entry check still catches the common case —\n // a tool dispatched after the user already cancelled the\n // stream — and unwinds cleanly instead of running to\n // completion against the SQL warehouse.\n signal?.throwIfAborted();\n if (readOnly) {\n assertReadOnlySql(args.text);\n return this.runReadOnlyStatement(args.text, args.values);\n }\n const result = await this.query(args.text, args.values);\n return result.rows;\n },\n });\n }\n\n getAgentTools(): AgentToolDefinition[] {\n return toolsFromRegistry(this.tools);\n }\n\n async executeAgentTool(\n name: string,\n args: unknown,\n signal?: AbortSignal,\n ): Promise<unknown> {\n return executeFromRegistry(this.tools, name, args, signal);\n }\n\n toolkit(opts?: import(\"../../core/agent/types\").ToolkitOptions) {\n return buildToolkitEntries(this.name, this.tools, opts);\n }\n\n exports() {\n return {\n // biome-ignore lint/style/noNonNullAssertion: pool is guaranteed non-null after setup(), which AppKit always awaits before exposing the plugin API\n pool: this.pool!,\n query: this.query.bind(this),\n getOrmConfig: () => getLakebaseOrmConfig(this.config.pool),\n getPgConfig: () => getLakebasePgConfig(this.config.pool),\n };\n }\n}\n\n/**\n * @internal\n */\nexport const lakebase = toPlugin(LakebasePlugin);\n"],"mappings":";;;;;;;;;;;;AAsBA,MAAM,SAAS,aAAa,WAAW;;;;;;;;;;;;;;;;;;AAmBvC,IAAa,iBAAb,cAAoC,OAA+B;;CAEjE,OAAO,WAAWA;CAGlB,AAAQ,OAAoB;;;;;;;;CAS5B,MAAM,QAAQ;EACZ,MAAM,aAAa,KAAK,OAAO;EAC/B,MAAM,OAAO,MAAM,yBAAyB,WAAW;AACvD,OAAK,OAAO,mBAAmB;GAAE,GAAG;GAAY;GAAM,CAAC;AACvD,SAAO,KAAK,4BAA4B;;;;;;;;;;;;;;;;;CAkB1C,MAAM,MACJ,MACA,QACyB;AAEzB,SAAO,KAAK,KAAM,MAAS,MAAM,OAAO;;;;;;;;;;;;;;;;CAiB1C,MAAc,qBACZ,MACA,QACoB;EAEpB,MAAM,SAAS,MAAM,KAAK,KAAM,SAAS;AACzC,MAAI;AACF,SAAM,OAAO,MAAM,kBAAkB;AAErC,WADe,MAAM,OAAO,MAAM,MAAM,OAAO,EACjC;YACN;AACR,OAAI;AACF,UAAM,OAAO,MAAM,WAAW;aACtB;AACR,WAAO,SAAS;;;;;;;;CAStB,wBAA8B;AAC5B,QAAM,uBAAuB;AAC7B,MAAI,KAAK,MAAM;AACb,UAAO,KAAK,wBAAwB;AACpC,QAAK,KAAK,KAAK,CAAC,OAAO,QAAQ;AAC7B,WAAO,MAAM,mCAAmC,IAAI;KACpD;AACF,QAAK,OAAO;;;;;;;;;;;;;;;;CAkBhB,AAAQ,QAAgE,EAAE;CAE1E,YAAY,QAAyB;AACnC,QAAM,OAAO;AACb,OAAK,SAAS;AACd,MAAI,OAAO,mBAAmB;AAC5B,QAAK,QAAQ,EAAE,OAAO,KAAK,eAAe,OAAO,kBAAkB,EAAE;AACrE,UAAO,KACL,gKACA,OAAO,kBAAkB,aAAa,MACvC;;;CAIL,AAAQ,eACN,KACA;EACA,MAAM,WAAW,IAAI,aAAa;AAClC,SAAO,WAAW;GAChB,aAAa,WACT,8PACA;GACJ,QAAQ,EAAE,OAAO;IACf,MAAM,EACH,QAAQ,CACR,SACC,6DACD;IACH,QAAQ,EACL,MAAM,EAAE,SAAS,CAAC,CAClB,UAAU,CACV,SAAS,iDAAiD;IAC9D,CAAC;GACF,aAAa;IACX,QAAQ,WAAW,SAAS;IAC5B,YAAY;IACb;GACD,SAAS,OAAO,MAAM,WAAW;AAQ/B,YAAQ,gBAAgB;AACxB,QAAI,UAAU;AACZ,uBAAkB,KAAK,KAAK;AAC5B,YAAO,KAAK,qBAAqB,KAAK,MAAM,KAAK,OAAO;;AAG1D,YADe,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,OAAO,EACzC;;GAEjB,CAAC;;CAGJ,gBAAuC;AACrC,SAAO,kBAAkB,KAAK,MAAM;;CAGtC,MAAM,iBACJ,MACA,MACA,QACkB;AAClB,SAAO,oBAAoB,KAAK,OAAO,MAAM,MAAM,OAAO;;CAG5D,QAAQ,MAAwD;AAC9D,SAAO,oBAAoB,KAAK,MAAM,KAAK,OAAO,KAAK;;CAGzD,UAAU;AACR,SAAO;GAEL,MAAM,KAAK;GACX,OAAO,KAAK,MAAM,KAAK,KAAK;GAC5B,oBAAoB,qBAAqB,KAAK,OAAO,KAAK;GAC1D,mBAAmB,oBAAoB,KAAK,OAAO,KAAK;GACzD;;;;;;AAOL,MAAa,WAAW,SAAS,eAAe"}
@@ -20,16 +20,17 @@ import { LakebasePoolConfig } from "../../connectors/lakebase/index.js";
20
20
  * PostgreSQL server rejects writes that slip past the classifier (e.g., a
21
21
  * `SELECT` over a function with side effects).
22
22
  *
23
- * When `readOnly: false`, the tool is annotated `destructive: true` and the
24
- * agents plugin will require human approval for every invocation (see
23
+ * When `readOnly: false`, the tool is annotated `effect: "destructive"` and
24
+ * the agents plugin will require human approval for every invocation (see
25
25
  * `AgentsPluginConfig.approval`).
26
26
  */
27
27
  interface LakebaseExposeAsAgentTool {
28
28
  /**
29
29
  * Enforce read-only execution. Defaults to `true`. Set to `false` to allow
30
30
  * destructive statements — highly discouraged outside of tightly controlled
31
- * single-user deployments. Combined with the `destructive: true` annotation,
32
- * the agents plugin will require explicit human approval for each call.
31
+ * single-user deployments. Combined with the `effect: "destructive"`
32
+ * annotation, the agents plugin will require explicit human approval for
33
+ * each call.
33
34
  */
34
35
  readOnly?: boolean;
35
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/plugins/lakebase/types.ts"],"mappings":";;;;;;;;AAwBA;;;;;AAkBA;;;;;;;;;;;;;UAlBiB,yBAAA;EAgCK;;;;;;EAzBpB,QAAA;AAAA;;;;;;;;;UAWe,eAAA,SAAwB,gBAAA;;;;;;;EAOvC,IAAA,GAAO,OAAA,CAAQ,kBAAA;;;;;;;EAOf,iBAAA,GAAoB,yBAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/plugins/lakebase/types.ts"],"mappings":";;;;;;;;AAwBA;;;;;AAmBA;;;;;;;;;;;;;UAnBiB,yBAAA;EAiCK;;;;;;;EAzBpB,QAAA;AAAA;;;;;;;;;UAWe,eAAA,SAAwB,gBAAA;;;;;;;EAOvC,IAAA,GAAO,OAAA,CAAQ,kBAAA;;;;;;;EAOf,iBAAA,GAAoB,yBAAA;AAAA"}
@@ -1,7 +1,6 @@
1
1
  import { PluginPhase, TelemetryOptions, ToPlugin } from "../../shared/src/plugin.js";
2
2
  import "../../shared/src/index.js";
3
3
  import { Plugin } from "../../plugin/plugin.js";
4
- import { NamedPluginFactory } from "../../plugin/to-plugin.js";
5
4
  import "../../plugin/index.js";
6
5
  import { PluginManifest } from "../../registry/types.js";
7
6
  import "../../registry/index.js";
@@ -59,6 +58,7 @@ declare class ServerPlugin extends Plugin {
59
58
  port?: number;
60
59
  staticPath?: string;
61
60
  host?: string;
61
+ bodyLimit?: string;
62
62
  name?: string;
63
63
  telemetry?: TelemetryOptions;
64
64
  };
@@ -133,6 +133,7 @@ declare class ServerPlugin extends Plugin {
133
133
  port?: number;
134
134
  staticPath?: string;
135
135
  host?: string;
136
+ bodyLimit?: string;
136
137
  name?: string;
137
138
  telemetry?: TelemetryOptions;
138
139
  }; /** @deprecated Server is now started automatically by createApp. */
@@ -142,7 +143,7 @@ declare class ServerPlugin extends Plugin {
142
143
  /**
143
144
  * @internal
144
145
  */
145
- declare const server: ToPlugin<typeof ServerPlugin, ServerConfig, "server"> & NamedPluginFactory<"server">;
146
+ declare const server: ToPlugin<typeof ServerPlugin, ServerConfig, "server">;
146
147
  //#endregion
147
148
  export { server };
148
149
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/plugins/server/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;AAkDA;;;;;;;;;;;;;;;;cAAa,YAAA,SAAqB,MAAA;EAAA,OAClB,cAAA;;;;EADwB;EAAA,OAO/B,QAAA,EAAuB,cAAA;EAAA,QACtB,iBAAA;EAAA,QACA,MAAA;EAAA,QACA,aAAA;EAAA,QACA,sBAAA;EAJsB;EAAA,QAMtB,kBAAA;EAAA,UACU,MAAA,EAAQ,YAAA;EAAA,QAClB,gBAAA;EAAA,QACA,YAAA;EAAA,OACD,KAAA,EAAO,WAAA;cAEF,MAAA,EAAQ,YAAA;EAepB,aAAA,CAAc,IAAA,GAAM,UAAA,CAAW,MAAA;EAnBvB;EA6BF,KAAA,CAAA,GAAK,OAAA;EA3BJ;EA8BP,SAAA,CAAA;IAAA;;;;;gBAHW,gBAAA;EAAA;EAAL;;;;;;;;EAiBA,KAAA,CAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,WAAA;;;;;;;;;EA8D/B,SAAA,CAAA,GAAa,MAAA;EAiBY;;;;;;;;;EAAzB,MAAA,CAAO,EAAA,GAAK,GAAA,EAAK,OAAA,CAAQ,WAAA;EAqIV;;;;;;EA1Hf,YAAA,CAAa,EAAA,GAAK,GAAA,EAAK,OAAA,CAAQ,WAAA;EAwPF;;;;;;;EAAA,QA7Of,YAAA;;;;;;;UAmEA,aAAA;EAAA,eA4CC,cAAA;EAoLJ;;;;;EAAA,QAlKG,iBAAA;EAAA,QAqBN,cAAA;EAAA,QA+BM,iBAAA;EA8GG;;;;EA1DjB,OAAA,CAAA;IA0DiB,qEAtDD,GAAA,EAAK,OAAA,CAAQ,WAAA,YAsDZ;qBA1UJ,MAAA;;;;;;;kBAAU,gBAAA;IAAA;;;;;;;cA0UZ,MAAA,EAAM,QAAA,QAAA,YAAA,EAAA,YAAA,cAAA,kBAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/plugins/server/index.ts"],"mappings":";;;;;;;;;;;;;;;;AAkDA;;;;;;;;;;;;;;;;;cAAa,YAAA,SAAqB,MAAA;EAAA,OAClB,cAAA;;;;EADkB;EAAA,OAOzB,QAAA,EAAuB,cAAA;EAAA,QACtB,iBAAA;EAAA,QACA,MAAA;EAAA,QACA,aAAA;EAAA,QACA,sBAAA;EAHA;EAAA,QAKA,kBAAA;EAAA,UACU,MAAA,EAAQ,YAAA;EAAA,QAClB,gBAAA;EAAA,QACA,YAAA;EAAA,OACD,KAAA,EAAO,WAAA;cAEF,MAAA,EAAQ,YAAA;EAepB,aAAA,CAAc,IAAA,GAAM,UAAA,CAAW,MAAA;EAlBvB;EA4BF,KAAA,CAAA,GAAK,OAAA;EA3BG;EA8Bd,SAAA,CAAA;IAAA;;;;;;gBAHW,gBAAA;EAAA;EAGX;;;;;;;;EAcM,KAAA,CAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,WAAA;EAAzB;;;;;;;;EAqEN,SAAA,CAAA,GAAa,MAAA;EAiBD;;;;;;;;;EAAZ,MAAA,CAAO,EAAA,GAAK,GAAA,EAAK,OAAA,CAAQ,WAAA;EAuJX;;;;;;EA5Id,YAAA,CAAa,EAAA,GAAK,GAAA,EAAK,OAAA,CAAQ,WAAA;EAwPf;;;;;;;EAAA,QA7OF,YAAA;;;;;;;UAmEA,aAAA;EAAA,eA4CC,cAAA;EAoLJ;;;;;EAAA,QAlKG,iBAAA;EAAA,QAqBN,cAAA;EAAA,QA+BM,iBAAA;EA8GG;;;;EA1DjB,OAAA,CAAA;yEAIgB,GAAA,EAAK,OAAA,CAAQ,WAAA;qBApRhB,MAAA;;;;;;;;kBAAU,gBAAA;IAAA;;;;;;;cA0UZ,MAAA,EAAM,QAAA,QAAA,YAAA,EAAA,YAAA"}
@@ -94,11 +94,14 @@ var ServerPlugin = class ServerPlugin extends Plugin {
94
94
  */
95
95
  async start() {
96
96
  this.serverApplication.use(requestMetricsMiddleware);
97
- this.serverApplication.use(express.json({ type: (req) => {
98
- const urlPath = req.url?.split("?")[0];
99
- if (urlPath && this.rawBodyPaths.has(urlPath)) return false;
100
- return (req.headers["content-type"] ?? "").includes("json");
101
- } }));
97
+ this.serverApplication.use(express.json({
98
+ limit: this.config.bodyLimit ?? "1mb",
99
+ type: (req) => {
100
+ const urlPath = req.url?.split("?")[0];
101
+ if (urlPath && this.rawBodyPaths.has(urlPath)) return false;
102
+ return (req.headers["content-type"] ?? "").includes("json");
103
+ }
104
+ }));
102
105
  const { endpoints, pluginConfigs } = await this.extendRoutes();
103
106
  for (const extension of this.serverExtensions) extension(this.serverApplication);
104
107
  this.remoteTunnelController = new RemoteTunnelController(this.devFileReader);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["manifest"],"sources":["../../../src/plugins/server/index.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport type { Server as HTTPServer } from \"node:http\";\nimport path from \"node:path\";\nimport dotenv from \"dotenv\";\nimport express from \"express\";\nimport getPort, { portNumbers } from \"get-port\";\nimport type { PluginClientConfigs, PluginPhase } from \"shared\";\nimport { ServerError } from \"../../errors\";\nimport { TelemetryReporter } from \"../../internal-telemetry\";\nimport { createLogger } from \"../../logging/logger\";\nimport { Plugin, toPlugin } from \"../../plugin\";\nimport type { PluginManifest } from \"../../registry\";\nimport { instrumentations } from \"../../telemetry\";\nimport { sanitizeClientConfig } from \"./client-config-sanitizer\";\nimport manifest from \"./manifest.json\";\nimport { RemoteTunnelController } from \"./remote-tunnel/remote-tunnel-controller\";\nimport { StaticServer } from \"./static-server\";\nimport type { ServerConfig } from \"./types\";\nimport { getRoutes, type PluginEndpoints, printRoutes } from \"./utils\";\nimport { ViteDevServer } from \"./vite-dev-server\";\n\ndotenv.config({ path: path.resolve(process.cwd(), \"./.env\") });\n\nconst logger = createLogger(\"server\");\n\n/** Dev-only: try `requested` then consecutive ports (see `get-port` `portNumbers`). */\nconst devListenPortSpan = 100;\n\n/**\n * Server plugin for the AppKit.\n *\n * This plugin is responsible for starting the server and serving the static files.\n * It also handles the remote tunneling for development purposes.\n *\n * The server is started automatically by `createApp` after all plugins are set up\n * and the optional `onPluginsReady` callback has run.\n *\n * @example\n * ```ts\n * createApp({\n * plugins: [server(), analytics({})],\n * onPluginsReady(appkit) {\n * appkit.server.extend((app) => {\n * app.get(\"/custom\", (_req, res) => res.json({ ok: true }));\n * });\n * },\n * });\n * ```\n *\n */\nexport class ServerPlugin extends Plugin {\n public static DEFAULT_CONFIG = {\n host: process.env.FLASK_RUN_HOST || \"0.0.0.0\",\n port: Number(process.env.DATABRICKS_APP_PORT) || 8000,\n };\n\n /** Plugin manifest declaring metadata and resource requirements */\n static manifest = manifest as PluginManifest<\"server\">;\n private serverApplication: express.Application;\n private server: HTTPServer | null;\n private viteDevServer?: ViteDevServer;\n private remoteTunnelController?: RemoteTunnelController;\n /** Bound listen port after optional dev-time resolution. */\n private resolvedListenPort?: number;\n protected declare config: ServerConfig;\n private serverExtensions: ((app: express.Application) => void)[] = [];\n private rawBodyPaths: Set<string> = new Set();\n static phase: PluginPhase = \"deferred\";\n\n constructor(config: ServerConfig) {\n super(config);\n if (\"autoStart\" in config) {\n throw new ServerError(\n \"server({ autoStart }) has been removed. \" +\n \"The server is now started automatically by createApp.\\n\\n\" +\n \"Run `npx appkit codemod on-plugins-ready --write` to auto-migrate.\",\n );\n }\n this.config = config;\n this.serverApplication = express();\n this.server = null;\n this.serverExtensions = [];\n }\n\n attachContext(deps: Parameters<Plugin[\"attachContext\"]>[0] = {}): void {\n super.attachContext(deps);\n this.telemetry.registerInstrumentations([\n instrumentations.http,\n instrumentations.express,\n ]);\n this.context?.registerAsRouteTarget(this);\n }\n\n /** Setup the server plugin. */\n async setup() {}\n\n /** Get the server configuration. */\n getConfig() {\n const { plugins: _plugins, ...config } = this.config;\n\n return config;\n }\n\n /**\n * Start the server.\n *\n * This method starts the server and sets up the frontend.\n * It also sets up the remote tunneling if enabled.\n *\n * @returns The express application.\n */\n async start(): Promise<express.Application> {\n this.serverApplication.use(requestMetricsMiddleware);\n this.serverApplication.use(\n express.json({\n type: (req) => {\n // Skip JSON parsing for routes that declared skipBodyParsing\n // (e.g. file uploads where the raw body must flow through).\n // rawBodyPaths is populated by extendRoutes() below; the type\n // callback runs per-request so the set is already filled.\n const urlPath = req.url?.split(\"?\")[0];\n if (urlPath && this.rawBodyPaths.has(urlPath)) return false;\n const ct = req.headers[\"content-type\"] ?? \"\";\n return ct.includes(\"json\");\n },\n }),\n );\n\n const { endpoints, pluginConfigs } = await this.extendRoutes();\n\n for (const extension of this.serverExtensions) {\n extension(this.serverApplication);\n }\n\n // register remote tunnel controller (before static/vite)\n this.remoteTunnelController = new RemoteTunnelController(\n this.devFileReader,\n );\n this.serverApplication.use(this.remoteTunnelController.middleware);\n\n await this.setupFrontend(endpoints, pluginConfigs);\n\n const listenPort = await this.resolveListenPort();\n\n const server = this.serverApplication.listen(\n listenPort,\n this.config.host ?? ServerPlugin.DEFAULT_CONFIG.host,\n () => this.logStartupInfo(),\n );\n\n this.server = server;\n\n // attach server to remote tunnel controller\n this.remoteTunnelController.setServer(server);\n\n process.on(\"SIGTERM\", () => this._gracefulShutdown());\n process.on(\"SIGINT\", () => this._gracefulShutdown());\n\n if (process.env.NODE_ENV === \"development\") {\n const allRoutes = getRoutes(this.serverApplication._router.stack);\n printRoutes(allRoutes);\n }\n return this.serverApplication;\n }\n\n /**\n * Get the low level node.js http server instance.\n *\n * Only use this method if you need to access the server instance for advanced usage like a custom websocket server, etc.\n *\n * @throws {Error} If the server has not started yet.\n * @returns {HTTPServer} The server instance.\n */\n getServer(): HTTPServer {\n if (!this.server) {\n throw ServerError.notStarted();\n }\n\n return this.server;\n }\n\n /**\n * Extend the server with custom routes or middleware.\n *\n * Call this inside the `onPluginsReady` callback of `createApp` to register\n * custom Express routes or middleware before the server starts listening.\n *\n * @param fn - A function that receives the express application.\n * @returns The server plugin instance for chaining.\n */\n extend(fn: (app: express.Application) => void) {\n this.serverExtensions.push(fn);\n return this;\n }\n\n /**\n * Register a server extension from another plugin during setup.\n * Unlike extend(), this is designed for internal plugin-to-plugin\n * coordination where extensions are registered before the server starts\n * listening — typically called by PluginContext when flushing buffered routes.\n */\n addExtension(fn: (app: express.Application) => void) {\n this.serverExtensions.push(fn);\n }\n\n /**\n * Setup the routes with the plugins.\n *\n * This method goes through all the plugins and injects the routes into the server application.\n * Returns a map of plugin names to their registered named endpoints,\n * and a map of plugin names to their client-exposed configs.\n */\n private async extendRoutes(): Promise<{\n endpoints: PluginEndpoints;\n pluginConfigs: PluginClientConfigs;\n }> {\n const endpoints: PluginEndpoints = {};\n const pluginConfigs: PluginClientConfigs = {};\n\n const plugins = this.context?.getPlugins();\n if (!plugins || plugins.size === 0) return { endpoints, pluginConfigs };\n\n this.serverApplication.get(\"/health\", (_, res) => {\n res.status(200).json({ status: \"ok\" });\n });\n this.registerEndpoint(\"health\", \"/health\");\n\n for (const plugin of plugins.values()) {\n if (EXCLUDED_PLUGINS.includes(plugin.name)) continue;\n\n if (plugin?.injectRoutes && typeof plugin.injectRoutes === \"function\") {\n const router = express.Router();\n\n plugin.injectRoutes(router);\n\n const basePath = `/api/${plugin.name}`;\n this.serverApplication.use(basePath, router);\n\n endpoints[plugin.name] = plugin.getEndpoints();\n\n // Collect paths that should skip body parsing\n if (\n plugin.getSkipBodyParsingPaths &&\n typeof plugin.getSkipBodyParsingPaths === \"function\"\n ) {\n for (const p of plugin.getSkipBodyParsingPaths()) {\n this.rawBodyPaths.add(p);\n }\n }\n }\n\n if (typeof plugin.clientConfig === \"function\") {\n try {\n const raw = plugin.clientConfig();\n if (raw != null) {\n const sanitized = sanitizeClientConfig(plugin.name, raw);\n if (Object.keys(sanitized).length > 0) {\n pluginConfigs[plugin.name] = sanitized;\n }\n }\n } catch (error) {\n logger.error(\n \"Plugin '%s' clientConfig() failed, skipping its config: %O\",\n plugin.name,\n error,\n );\n }\n }\n }\n\n return { endpoints, pluginConfigs };\n }\n\n /**\n * Setup frontend serving based on environment:\n * - If staticPath is explicitly provided: use static server\n * - Dev mode (no staticPath): Vite for HMR\n * - Production (no staticPath): Static files auto-detected\n */\n private async setupFrontend(\n endpoints: PluginEndpoints,\n pluginConfigs: PluginClientConfigs,\n ) {\n const isDev = process.env.NODE_ENV === \"development\";\n const hasExplicitStaticPath = this.config.staticPath !== undefined;\n\n // explict static path provided\n if (hasExplicitStaticPath) {\n const staticServer = new StaticServer(\n this.serverApplication,\n this.config.staticPath as string,\n endpoints,\n pluginConfigs,\n );\n staticServer.setup();\n return;\n }\n\n // auto-detection based on environment\n if (isDev) {\n this.viteDevServer = new ViteDevServer(\n this.serverApplication,\n endpoints,\n pluginConfigs,\n );\n await this.viteDevServer.setup();\n return;\n }\n\n // auto-detection based on static path\n const staticPath = ServerPlugin.findStaticPath();\n if (staticPath) {\n const staticServer = new StaticServer(\n this.serverApplication,\n staticPath,\n endpoints,\n pluginConfigs,\n );\n\n staticServer.setup();\n }\n }\n\n private static findStaticPath() {\n const staticPaths = [\"dist\", \"client/dist\", \"build\", \"public\", \"out\"];\n const cwd = process.cwd();\n for (const p of staticPaths) {\n const fullPath = path.resolve(cwd, p);\n if (fs.existsSync(path.resolve(fullPath, \"index.html\"))) {\n logger.debug(\"Static files: serving from %s\", fullPath);\n return fullPath;\n }\n }\n return undefined;\n }\n\n /**\n * In development, prefers {@link ServerConfig.port} / env / default (8000), then\n * scans upward using `get-port`'s `portNumbers()` on the listen host until one binds.\n * In non-development, uses config / env / default only (no fallback).\n */\n private async resolveListenPort(): Promise<number> {\n const requested = this.config.port ?? ServerPlugin.DEFAULT_CONFIG.port;\n\n if (process.env.NODE_ENV !== \"development\") {\n this.resolvedListenPort = requested;\n return requested;\n }\n\n const host = this.config.host ?? ServerPlugin.DEFAULT_CONFIG.host;\n const upper = Math.min(requested + devListenPortSpan - 1, 65_535);\n const port = await getPort({\n host,\n port: portNumbers(requested, upper),\n });\n this.resolvedListenPort = port;\n if (port !== requested) {\n logger.info(\"Port %d was busy, picking %d\", requested, port);\n }\n return port;\n }\n\n private logStartupInfo() {\n const isDev = process.env.NODE_ENV === \"development\";\n const hasExplicitStaticPath = this.config.staticPath !== undefined;\n const port =\n this.resolvedListenPort ??\n this.config.port ??\n ServerPlugin.DEFAULT_CONFIG.port;\n const host = this.config.host ?? ServerPlugin.DEFAULT_CONFIG.host;\n\n logger.info(\"Server running on http://%s:%d\", host, port);\n\n if (hasExplicitStaticPath) {\n logger.info(\"Mode: static (%s)\", this.config.staticPath);\n } else if (isDev) {\n logger.info(\"Mode: development (Vite HMR)\");\n } else {\n logger.info(\"Mode: production (static)\");\n }\n\n const remoteServerController = this.remoteTunnelController;\n if (!remoteServerController) {\n logger.debug(\"Remote tunnel: disabled (controller not initialized)\");\n } else {\n logger.debug(\n \"Remote tunnel: %s; %s\",\n remoteServerController.isAllowedByEnv() ? \"allowed\" : \"blocked\",\n remoteServerController.isActive() ? \"active\" : \"inactive\",\n );\n }\n }\n\n private async _gracefulShutdown() {\n logger.info(\"Starting graceful shutdown...\");\n\n if (this.viteDevServer) {\n await this.viteDevServer.close();\n }\n\n if (this.remoteTunnelController) {\n this.remoteTunnelController.cleanup();\n }\n\n TelemetryReporter.getInstance()?.stop();\n\n // 1. abort active operations from plugins\n const shutdownPlugins = this.context?.getPlugins();\n if (shutdownPlugins) {\n for (const plugin of shutdownPlugins.values()) {\n if (plugin.abortActiveOperations) {\n try {\n plugin.abortActiveOperations();\n } catch (err) {\n logger.error(\n \"Error aborting operations for plugin %s: %O\",\n plugin.name,\n err,\n );\n }\n }\n }\n }\n\n // 2. close the server\n if (this.server) {\n this.server.close(() => {\n logger.debug(\"Server closed gracefully\");\n process.exit(0);\n });\n\n // 3. timeout to force shutdown after 15 seconds\n setTimeout(() => {\n logger.debug(\"Force shutdown after timeout\");\n process.exit(1);\n }, 15000);\n } else {\n process.exit(0);\n }\n }\n\n /**\n * Returns the public exports for the server plugin.\n * Exposes server management methods.\n */\n exports() {\n const self = this;\n return {\n /** Extend the server with custom routes or middleware */\n extend(fn: (app: express.Application) => void) {\n self.extend(fn);\n return this;\n },\n /** Get the underlying HTTP server instance */\n getServer: this.getServer,\n /** Get the server configuration */\n getConfig: this.getConfig,\n /** @deprecated Server is now started automatically by createApp. */\n start() {\n throw new ServerError(\n \"server.start() has been removed. Use the onPluginsReady callback instead:\\n\\n\" +\n \" createApp({\\n\" +\n \" plugins: [server(), ...],\\n\" +\n \" onPluginsReady(appkit) {\\n\" +\n \" appkit.server.extend(...);\\n\" +\n \" },\\n\" +\n \" });\\n\\n\" +\n \"Run `npx appkit codemod on-plugins-ready --write` to auto-migrate.\",\n );\n },\n };\n }\n}\n\nconst EXCLUDED_PLUGINS: string[] = [ServerPlugin.manifest.name];\n\n/** @internal Exported for unit tests. */\nexport function requestMetricsMiddleware(\n req: express.Request,\n res: express.Response,\n next: express.NextFunction,\n) {\n const startMs = Date.now();\n res.on(\"finish\", () => {\n const reporter = TelemetryReporter.getInstance();\n if (!reporter) return;\n const routePath = (req.route as { path?: string } | undefined)?.path;\n if (!routePath) return;\n const baseUrl = req.baseUrl ?? \"\";\n const template = `${baseUrl}${routePath}`;\n reporter.recordRequest(\n req.method,\n template,\n res.statusCode,\n Date.now() - startMs,\n );\n });\n next();\n}\n\n/**\n * @internal\n */\nexport const server = toPlugin(ServerPlugin);\n// Export manifest and types\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["manifest"],"sources":["../../../src/plugins/server/index.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport type { Server as HTTPServer } from \"node:http\";\nimport path from \"node:path\";\nimport dotenv from \"dotenv\";\nimport express from \"express\";\nimport getPort, { portNumbers } from \"get-port\";\nimport type { PluginClientConfigs, PluginPhase } from \"shared\";\nimport { ServerError } from \"../../errors\";\nimport { TelemetryReporter } from \"../../internal-telemetry\";\nimport { createLogger } from \"../../logging/logger\";\nimport { Plugin, toPlugin } from \"../../plugin\";\nimport type { PluginManifest } from \"../../registry\";\nimport { instrumentations } from \"../../telemetry\";\nimport { sanitizeClientConfig } from \"./client-config-sanitizer\";\nimport manifest from \"./manifest.json\";\nimport { RemoteTunnelController } from \"./remote-tunnel/remote-tunnel-controller\";\nimport { StaticServer } from \"./static-server\";\nimport type { ServerConfig } from \"./types\";\nimport { getRoutes, type PluginEndpoints, printRoutes } from \"./utils\";\nimport { ViteDevServer } from \"./vite-dev-server\";\n\ndotenv.config({ path: path.resolve(process.cwd(), \"./.env\") });\n\nconst logger = createLogger(\"server\");\n\n/** Dev-only: try `requested` then consecutive ports (see `get-port` `portNumbers`). */\nconst devListenPortSpan = 100;\n\n/**\n * Server plugin for the AppKit.\n *\n * This plugin is responsible for starting the server and serving the static files.\n * It also handles the remote tunneling for development purposes.\n *\n * The server is started automatically by `createApp` after all plugins are set up\n * and the optional `onPluginsReady` callback has run.\n *\n * @example\n * ```ts\n * createApp({\n * plugins: [server(), analytics({})],\n * onPluginsReady(appkit) {\n * appkit.server.extend((app) => {\n * app.get(\"/custom\", (_req, res) => res.json({ ok: true }));\n * });\n * },\n * });\n * ```\n *\n */\nexport class ServerPlugin extends Plugin {\n public static DEFAULT_CONFIG = {\n host: process.env.FLASK_RUN_HOST || \"0.0.0.0\",\n port: Number(process.env.DATABRICKS_APP_PORT) || 8000,\n };\n\n /** Plugin manifest declaring metadata and resource requirements */\n static manifest = manifest as PluginManifest<\"server\">;\n private serverApplication: express.Application;\n private server: HTTPServer | null;\n private viteDevServer?: ViteDevServer;\n private remoteTunnelController?: RemoteTunnelController;\n /** Bound listen port after optional dev-time resolution. */\n private resolvedListenPort?: number;\n protected declare config: ServerConfig;\n private serverExtensions: ((app: express.Application) => void)[] = [];\n private rawBodyPaths: Set<string> = new Set();\n static phase: PluginPhase = \"deferred\";\n\n constructor(config: ServerConfig) {\n super(config);\n if (\"autoStart\" in config) {\n throw new ServerError(\n \"server({ autoStart }) has been removed. \" +\n \"The server is now started automatically by createApp.\\n\\n\" +\n \"Run `npx appkit codemod on-plugins-ready --write` to auto-migrate.\",\n );\n }\n this.config = config;\n this.serverApplication = express();\n this.server = null;\n this.serverExtensions = [];\n }\n\n attachContext(deps: Parameters<Plugin[\"attachContext\"]>[0] = {}): void {\n super.attachContext(deps);\n this.telemetry.registerInstrumentations([\n instrumentations.http,\n instrumentations.express,\n ]);\n this.context?.registerAsRouteTarget(this);\n }\n\n /** Setup the server plugin. */\n async setup() {}\n\n /** Get the server configuration. */\n getConfig() {\n const { plugins: _plugins, ...config } = this.config;\n\n return config;\n }\n\n /**\n * Start the server.\n *\n * This method starts the server and sets up the frontend.\n * It also sets up the remote tunneling if enabled.\n *\n * @returns The express application.\n */\n async start(): Promise<express.Application> {\n this.serverApplication.use(requestMetricsMiddleware);\n this.serverApplication.use(\n express.json({\n // Express's stock 100kb default is too tight for modern apps —\n // agent chat payloads and any base64-encoded upload (e.g. the\n // dev playground's smart-dashboard \"save view\" screenshot at\n // ~105KB) blow past it instantly. Raise to 1mb by default and\n // let consumers tune via `server({ bodyLimit })` if they need\n // more headroom.\n limit: this.config.bodyLimit ?? \"1mb\",\n type: (req) => {\n // Skip JSON parsing for routes that declared skipBodyParsing\n // (e.g. file uploads where the raw body must flow through).\n // rawBodyPaths is populated by extendRoutes() below; the type\n // callback runs per-request so the set is already filled.\n const urlPath = req.url?.split(\"?\")[0];\n if (urlPath && this.rawBodyPaths.has(urlPath)) return false;\n const ct = req.headers[\"content-type\"] ?? \"\";\n return ct.includes(\"json\");\n },\n }),\n );\n\n const { endpoints, pluginConfigs } = await this.extendRoutes();\n\n for (const extension of this.serverExtensions) {\n extension(this.serverApplication);\n }\n\n // register remote tunnel controller (before static/vite)\n this.remoteTunnelController = new RemoteTunnelController(\n this.devFileReader,\n );\n this.serverApplication.use(this.remoteTunnelController.middleware);\n\n await this.setupFrontend(endpoints, pluginConfigs);\n\n const listenPort = await this.resolveListenPort();\n\n const server = this.serverApplication.listen(\n listenPort,\n this.config.host ?? ServerPlugin.DEFAULT_CONFIG.host,\n () => this.logStartupInfo(),\n );\n\n this.server = server;\n\n // attach server to remote tunnel controller\n this.remoteTunnelController.setServer(server);\n\n process.on(\"SIGTERM\", () => this._gracefulShutdown());\n process.on(\"SIGINT\", () => this._gracefulShutdown());\n\n if (process.env.NODE_ENV === \"development\") {\n const allRoutes = getRoutes(this.serverApplication._router.stack);\n printRoutes(allRoutes);\n }\n return this.serverApplication;\n }\n\n /**\n * Get the low level node.js http server instance.\n *\n * Only use this method if you need to access the server instance for advanced usage like a custom websocket server, etc.\n *\n * @throws {Error} If the server has not started yet.\n * @returns {HTTPServer} The server instance.\n */\n getServer(): HTTPServer {\n if (!this.server) {\n throw ServerError.notStarted();\n }\n\n return this.server;\n }\n\n /**\n * Extend the server with custom routes or middleware.\n *\n * Call this inside the `onPluginsReady` callback of `createApp` to register\n * custom Express routes or middleware before the server starts listening.\n *\n * @param fn - A function that receives the express application.\n * @returns The server plugin instance for chaining.\n */\n extend(fn: (app: express.Application) => void) {\n this.serverExtensions.push(fn);\n return this;\n }\n\n /**\n * Register a server extension from another plugin during setup.\n * Unlike extend(), this is designed for internal plugin-to-plugin\n * coordination where extensions are registered before the server starts\n * listening — typically called by PluginContext when flushing buffered routes.\n */\n addExtension(fn: (app: express.Application) => void) {\n this.serverExtensions.push(fn);\n }\n\n /**\n * Setup the routes with the plugins.\n *\n * This method goes through all the plugins and injects the routes into the server application.\n * Returns a map of plugin names to their registered named endpoints,\n * and a map of plugin names to their client-exposed configs.\n */\n private async extendRoutes(): Promise<{\n endpoints: PluginEndpoints;\n pluginConfigs: PluginClientConfigs;\n }> {\n const endpoints: PluginEndpoints = {};\n const pluginConfigs: PluginClientConfigs = {};\n\n const plugins = this.context?.getPlugins();\n if (!plugins || plugins.size === 0) return { endpoints, pluginConfigs };\n\n this.serverApplication.get(\"/health\", (_, res) => {\n res.status(200).json({ status: \"ok\" });\n });\n this.registerEndpoint(\"health\", \"/health\");\n\n for (const plugin of plugins.values()) {\n if (EXCLUDED_PLUGINS.includes(plugin.name)) continue;\n\n if (plugin?.injectRoutes && typeof plugin.injectRoutes === \"function\") {\n const router = express.Router();\n\n plugin.injectRoutes(router);\n\n const basePath = `/api/${plugin.name}`;\n this.serverApplication.use(basePath, router);\n\n endpoints[plugin.name] = plugin.getEndpoints();\n\n // Collect paths that should skip body parsing\n if (\n plugin.getSkipBodyParsingPaths &&\n typeof plugin.getSkipBodyParsingPaths === \"function\"\n ) {\n for (const p of plugin.getSkipBodyParsingPaths()) {\n this.rawBodyPaths.add(p);\n }\n }\n }\n\n if (typeof plugin.clientConfig === \"function\") {\n try {\n const raw = plugin.clientConfig();\n if (raw != null) {\n const sanitized = sanitizeClientConfig(plugin.name, raw);\n if (Object.keys(sanitized).length > 0) {\n pluginConfigs[plugin.name] = sanitized;\n }\n }\n } catch (error) {\n logger.error(\n \"Plugin '%s' clientConfig() failed, skipping its config: %O\",\n plugin.name,\n error,\n );\n }\n }\n }\n\n return { endpoints, pluginConfigs };\n }\n\n /**\n * Setup frontend serving based on environment:\n * - If staticPath is explicitly provided: use static server\n * - Dev mode (no staticPath): Vite for HMR\n * - Production (no staticPath): Static files auto-detected\n */\n private async setupFrontend(\n endpoints: PluginEndpoints,\n pluginConfigs: PluginClientConfigs,\n ) {\n const isDev = process.env.NODE_ENV === \"development\";\n const hasExplicitStaticPath = this.config.staticPath !== undefined;\n\n // explict static path provided\n if (hasExplicitStaticPath) {\n const staticServer = new StaticServer(\n this.serverApplication,\n this.config.staticPath as string,\n endpoints,\n pluginConfigs,\n );\n staticServer.setup();\n return;\n }\n\n // auto-detection based on environment\n if (isDev) {\n this.viteDevServer = new ViteDevServer(\n this.serverApplication,\n endpoints,\n pluginConfigs,\n );\n await this.viteDevServer.setup();\n return;\n }\n\n // auto-detection based on static path\n const staticPath = ServerPlugin.findStaticPath();\n if (staticPath) {\n const staticServer = new StaticServer(\n this.serverApplication,\n staticPath,\n endpoints,\n pluginConfigs,\n );\n\n staticServer.setup();\n }\n }\n\n private static findStaticPath() {\n const staticPaths = [\"dist\", \"client/dist\", \"build\", \"public\", \"out\"];\n const cwd = process.cwd();\n for (const p of staticPaths) {\n const fullPath = path.resolve(cwd, p);\n if (fs.existsSync(path.resolve(fullPath, \"index.html\"))) {\n logger.debug(\"Static files: serving from %s\", fullPath);\n return fullPath;\n }\n }\n return undefined;\n }\n\n /**\n * In development, prefers {@link ServerConfig.port} / env / default (8000), then\n * scans upward using `get-port`'s `portNumbers()` on the listen host until one binds.\n * In non-development, uses config / env / default only (no fallback).\n */\n private async resolveListenPort(): Promise<number> {\n const requested = this.config.port ?? ServerPlugin.DEFAULT_CONFIG.port;\n\n if (process.env.NODE_ENV !== \"development\") {\n this.resolvedListenPort = requested;\n return requested;\n }\n\n const host = this.config.host ?? ServerPlugin.DEFAULT_CONFIG.host;\n const upper = Math.min(requested + devListenPortSpan - 1, 65_535);\n const port = await getPort({\n host,\n port: portNumbers(requested, upper),\n });\n this.resolvedListenPort = port;\n if (port !== requested) {\n logger.info(\"Port %d was busy, picking %d\", requested, port);\n }\n return port;\n }\n\n private logStartupInfo() {\n const isDev = process.env.NODE_ENV === \"development\";\n const hasExplicitStaticPath = this.config.staticPath !== undefined;\n const port =\n this.resolvedListenPort ??\n this.config.port ??\n ServerPlugin.DEFAULT_CONFIG.port;\n const host = this.config.host ?? ServerPlugin.DEFAULT_CONFIG.host;\n\n logger.info(\"Server running on http://%s:%d\", host, port);\n\n if (hasExplicitStaticPath) {\n logger.info(\"Mode: static (%s)\", this.config.staticPath);\n } else if (isDev) {\n logger.info(\"Mode: development (Vite HMR)\");\n } else {\n logger.info(\"Mode: production (static)\");\n }\n\n const remoteServerController = this.remoteTunnelController;\n if (!remoteServerController) {\n logger.debug(\"Remote tunnel: disabled (controller not initialized)\");\n } else {\n logger.debug(\n \"Remote tunnel: %s; %s\",\n remoteServerController.isAllowedByEnv() ? \"allowed\" : \"blocked\",\n remoteServerController.isActive() ? \"active\" : \"inactive\",\n );\n }\n }\n\n private async _gracefulShutdown() {\n logger.info(\"Starting graceful shutdown...\");\n\n if (this.viteDevServer) {\n await this.viteDevServer.close();\n }\n\n if (this.remoteTunnelController) {\n this.remoteTunnelController.cleanup();\n }\n\n TelemetryReporter.getInstance()?.stop();\n\n // 1. abort active operations from plugins\n const shutdownPlugins = this.context?.getPlugins();\n if (shutdownPlugins) {\n for (const plugin of shutdownPlugins.values()) {\n if (plugin.abortActiveOperations) {\n try {\n plugin.abortActiveOperations();\n } catch (err) {\n logger.error(\n \"Error aborting operations for plugin %s: %O\",\n plugin.name,\n err,\n );\n }\n }\n }\n }\n\n // 2. close the server\n if (this.server) {\n this.server.close(() => {\n logger.debug(\"Server closed gracefully\");\n process.exit(0);\n });\n\n // 3. timeout to force shutdown after 15 seconds\n setTimeout(() => {\n logger.debug(\"Force shutdown after timeout\");\n process.exit(1);\n }, 15000);\n } else {\n process.exit(0);\n }\n }\n\n /**\n * Returns the public exports for the server plugin.\n * Exposes server management methods.\n */\n exports() {\n const self = this;\n return {\n /** Extend the server with custom routes or middleware */\n extend(fn: (app: express.Application) => void) {\n self.extend(fn);\n return this;\n },\n /** Get the underlying HTTP server instance */\n getServer: this.getServer,\n /** Get the server configuration */\n getConfig: this.getConfig,\n /** @deprecated Server is now started automatically by createApp. */\n start() {\n throw new ServerError(\n \"server.start() has been removed. Use the onPluginsReady callback instead:\\n\\n\" +\n \" createApp({\\n\" +\n \" plugins: [server(), ...],\\n\" +\n \" onPluginsReady(appkit) {\\n\" +\n \" appkit.server.extend(...);\\n\" +\n \" },\\n\" +\n \" });\\n\\n\" +\n \"Run `npx appkit codemod on-plugins-ready --write` to auto-migrate.\",\n );\n },\n };\n }\n}\n\nconst EXCLUDED_PLUGINS: string[] = [ServerPlugin.manifest.name];\n\n/** @internal Exported for unit tests. */\nexport function requestMetricsMiddleware(\n req: express.Request,\n res: express.Response,\n next: express.NextFunction,\n) {\n const startMs = Date.now();\n res.on(\"finish\", () => {\n const reporter = TelemetryReporter.getInstance();\n if (!reporter) return;\n const routePath = (req.route as { path?: string } | undefined)?.path;\n if (!routePath) return;\n const baseUrl = req.baseUrl ?? \"\";\n const template = `${baseUrl}${routePath}`;\n reporter.recordRequest(\n req.method,\n template,\n res.statusCode,\n Date.now() - startMs,\n );\n });\n next();\n}\n\n/**\n * @internal\n */\nexport const server = toPlugin(ServerPlugin);\n// Export manifest and types\n"],"mappings":"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"}
@@ -6,6 +6,17 @@ interface ServerConfig extends BasePluginConfig {
6
6
  port?: number;
7
7
  staticPath?: string;
8
8
  host?: string;
9
+ /**
10
+ * Max request body size accepted by the built-in `express.json()`
11
+ * middleware. Accepts any string the `bytes` library understands
12
+ * (`"1mb"`, `"10mb"`, `"512kb"`, …). Defaults to `"1mb"` — high enough
13
+ * for agent chat payloads and modest base64 uploads (the dev
14
+ * playground's smart-dashboard "save view" screenshot is the
15
+ * motivating case), low enough that an attacker can't trivially
16
+ * exhaust memory by spamming oversized JSON. Raise it explicitly if
17
+ * your app routinely posts larger JSON bodies.
18
+ */
19
+ bodyLimit?: string;
9
20
  }
10
21
  //#endregion
11
22
  export { ServerConfig };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/plugins/server/types.ts"],"mappings":";;;;UAEiB,YAAA,SAAqB,gBAAA;EACpC,IAAA;EACA,UAAA;EACA,IAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/plugins/server/types.ts"],"mappings":";;;;UAEiB,YAAA,SAAqB,gBAAA;EACpC,IAAA;EACA,UAAA;EACA,IAAA;EAH4B;;;;;;;;;;EAc5B,SAAA;AAAA"}
@@ -2,7 +2,6 @@ import { IAppRouter, ToPlugin } from "../../shared/src/plugin.js";
2
2
  import "../../shared/src/index.js";
3
3
  import { ExecutionResult } from "../../plugin/execution-result.js";
4
4
  import { Plugin } from "../../plugin/plugin.js";
5
- import { NamedPluginFactory } from "../../plugin/to-plugin.js";
6
5
  import "../../plugin/index.js";
7
6
  import { PluginManifest, ResourceRequirement } from "../../registry/types.js";
8
7
  import "../../registry/index.js";
@@ -33,7 +32,7 @@ declare class ServingPlugin extends Plugin {
33
32
  /**
34
33
  * @internal
35
34
  */
36
- declare const serving: ToPlugin<typeof ServingPlugin, IServingConfig, "serving"> & NamedPluginFactory<"serving">;
35
+ declare const serving: ToPlugin<typeof ServingPlugin, IServingConfig, "serving">;
37
36
  //#endregion
38
37
  export { ServingPlugin, serving };
39
38
  //# sourceMappingURL=serving.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serving.d.ts","names":[],"sources":["../../../src/plugins/serving/serving.ts"],"mappings":";;;;;;;;;;;;cAyCa,aAAA,SAAsB,MAAA;EAAA,OAC1B,QAAA,EAAuB,cAAA;EAAA,iBAEb,WAAA;EAAA,UAEC,MAAA,EAAQ,cAAA;EAAA,iBAET,SAAA;EAAA,iBACA,WAAA;EAAA,QACT,gBAAA;cAEI,MAAA,EAAQ,cAAA;EAed,KAAA,CAAA,GAAS,OAAA;EAAA,OAiBR,uBAAA,CACL,MAAA,EAAQ,cAAA,GACP,mBAAA;EAAA,QAqBK,gBAAA;EA0BR,YAAA,CAAa,MAAA,EAAQ,UAAA;EAgEf,aAAA,CACJ,GAAA,EAAK,OAAA,CAAQ,OAAA,EACb,GAAA,EAAK,OAAA,CAAQ,QAAA,GACZ,OAAA;EA0BG,aAAA,CACJ,GAAA,EAAK,OAAA,CAAQ,OAAA,EACb,GAAA,EAAK,OAAA,CAAQ,QAAA,GACZ,OAAA;EA2DG,MAAA,CACJ,KAAA,UACA,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,eAAA;EAiBX,YAAA,CAAA,GAAgB,MAAA;EAOV,QAAA,CAAA,GAAY,OAAA;EAAA,UAIR,iBAAA,CAAkB,KAAA,WAAgB,sBAAA;EAM5C,OAAA,CAAA,GAAW,cAAA;AAAA;;;;cAmBA,OAAA,EAAO,QAAA,QAAA,aAAA,EAAA,cAAA,eAAA,kBAAA"}
1
+ {"version":3,"file":"serving.d.ts","names":[],"sources":["../../../src/plugins/serving/serving.ts"],"mappings":";;;;;;;;;;;cAyCa,aAAA,SAAsB,MAAA;EAAA,OAC1B,QAAA,EAAuB,cAAA;EAAA,iBAEb,WAAA;EAAA,UAEC,MAAA,EAAQ,cAAA;EAAA,iBAET,SAAA;EAAA,iBACA,WAAA;EAAA,QACT,gBAAA;cAEI,MAAA,EAAQ,cAAA;EAed,KAAA,CAAA,GAAS,OAAA;EAAA,OAiBR,uBAAA,CACL,MAAA,EAAQ,cAAA,GACP,mBAAA;EAAA,QAqBK,gBAAA;EA0BR,YAAA,CAAa,MAAA,EAAQ,UAAA;EAgEf,aAAA,CACJ,GAAA,EAAK,OAAA,CAAQ,OAAA,EACb,GAAA,EAAK,OAAA,CAAQ,QAAA,GACZ,OAAA;EA0BG,aAAA,CACJ,GAAA,EAAK,OAAA,CAAQ,OAAA,EACb,GAAA,EAAK,OAAA,CAAQ,QAAA,GACZ,OAAA;EA2DG,MAAA,CACJ,KAAA,UACA,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,eAAA;EAiBX,YAAA,CAAA,GAAgB,MAAA;EAOV,QAAA,CAAA,GAAY,OAAA;EAAA,UAIR,iBAAA,CAAkB,KAAA,WAAgB,sBAAA;EAM5C,OAAA,CAAA,GAAW,cAAA;AAAA;;;;cAmBA,OAAA,EAAO,QAAA,QAAA,aAAA,EAAA,cAAA"}
@@ -60,6 +60,16 @@ interface ToolCall {
60
60
  id: string;
61
61
  name: string;
62
62
  args: unknown;
63
+ /**
64
+ * Vendor-opaque "thought signature" blob attached by Vertex AI / Gemini
65
+ * 2.x models to every function call they emit. Resumed threads must
66
+ * echo this back verbatim on the next request or Vertex rejects with
67
+ * `INVALID_ARGUMENT: function call X is missing a thought_signature`.
68
+ * Stored here so adapters can preserve it across persistence
69
+ * boundaries. Non-Gemini endpoints leave this undefined.
70
+ * See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/thought-signatures
71
+ */
72
+ thoughtSignature?: string;
63
73
  }
64
74
  interface Thread {
65
75
  id: string;
@@ -103,10 +113,12 @@ type AgentEvent = {
103
113
  data: Record<string, unknown>;
104
114
  } | {
105
115
  /**
106
- * Emitted by the agents plugin (not adapters) when a tool call annotated
107
- * `destructive: true` is awaiting human approval. Clients should render
108
- * an approval prompt and POST to `/chat/approve` with the matching
109
- * `approvalId` and a `decision` of `approve` or `deny`.
116
+ * Emitted by the agents plugin (not adapters) when a mutating tool call
117
+ * is awaiting human approval fires for tools annotated with
118
+ * `effect: "write" | "update" | "destructive"` (preferred) or the
119
+ * legacy `destructive: true` boolean. Clients should render an approval
120
+ * prompt and POST to `/chat/approve` with the matching `approvalId` and
121
+ * a `decision` of `approve` or `deny`.
110
122
  */
111
123
  type: "approval_pending";
112
124
  approvalId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","names":[],"sources":["../../../../shared/src/agent.ts"],"mappings":";;;;;AAsBA;;;;;AAEA;;;;;;;;;KAFY,UAAA;AAAA,UAEK,eAAA;EAkBI;AAGrB;;;EAhBE,MAAA,GAAS,UAAA;EAiBT;;;;EAZA,QAAA;EAec;;;AAGhB;;EAZE,WAAA;EACA,UAAA;EACA,mBAAA;AAAA;AAAA,UAGe,mBAAA;EACf,IAAA;EACA,WAAA;EACA,UAAA,EAAY,WAAA;EACZ,WAAA,GAAc,eAAA;AAAA;AAAA,UAGC,YAAA;EACf,aAAA,IAAiB,mBAAA;EACjB,gBAAA,CACE,IAAA,UACA,IAAA,WACA,MAAA,GAAS,WAAA,GACR,OAAA;AAAA;AAAA,UAOY,OAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,UAAA;EACA,SAAA,GAAY,QAAA;EACZ,SAAA,EAAW,IAAA;AAAA;AAAA,UAGI,QAAA;EACf,EAAA;EACA,IAAA;EACA,IAAA;AAAA;AAAA,UAGe,MAAA;EACf,EAAA;EACA,MAAA;EACA,QAAA,EAAU,OAAA;EACV,SAAA,EAAW,IAAA;EACX,SAAA,EAAW,IAAA;AAAA;AAAA,UAOI,WAAA;EACf,MAAA,CAAO,MAAA,WAAiB,OAAA,CAAQ,MAAA;EAChC,GAAA,CAAI,QAAA,UAAkB,MAAA,WAAiB,OAAA,CAAQ,MAAA;EAC/C,IAAA,CAAK,MAAA,WAAiB,OAAA,CAAQ,MAAA;EAC9B,UAAA,CAAW,QAAA,UAAkB,MAAA,UAAgB,OAAA,EAAS,OAAA,GAAU,OAAA;EAChE,MAAA,CAAO,QAAA,UAAkB,MAAA,WAAiB,OAAA;AAAA;AAAA,KAOhC,UAAA;EACN,IAAA;EAAuB,OAAA;AAAA;EACvB,IAAA;EAAiB,OAAA;AAAA;EACjB,IAAA;EAAmB,MAAA;EAAgB,IAAA;EAAc,IAAA;AAAA;EAEjD,IAAA;EACA,MAAA;EACA,MAAA;EACA,KAAA;AAAA;EAEA,IAAA;EAAkB,OAAA;AAAA;EAElB,IAAA;EACA,MAAA;EACA,KAAA;AAAA;EAEA,IAAA;EAAkB,IAAA,EAAM,MAAA;AAAA;EAvBc;;;;;;EA+BtC,IAAA;EACA,UAAA;EACA,QAAA;EACA,QAAA;EACA,IAAA;EACA,WAAA,GAAc,eAAA;AAAA;AAAA,UA6HH,UAAA;EACf,QAAA,EAAU,OAAA;EACV,KAAA,EAAO,mBAAA;EACP,QAAA;EACA,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,eAAA;EAUa;EAR5B,WAAA,GAAc,IAAA,UAAc,IAAA,cAAkB,OAAA;EAC9C,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,YAAA;EACf,GAAA,CACE,KAAA,EAAO,UAAA,EACP,OAAA,EAAS,eAAA,GACR,cAAA,CAAe,UAAA;AAAA"}
1
+ {"version":3,"file":"agent.d.ts","names":[],"sources":["../../../../shared/src/agent.ts"],"mappings":";;;;;AAsBA;;;;;AAEA;;;;;;;;;KAFY,UAAA;AAAA,UAEK,eAAA;EAkBI;AAGrB;;;EAhBE,MAAA,GAAS,UAAA;EAiBT;;;;EAZA,QAAA;EAec;;;AAGhB;;EAZE,WAAA;EACA,UAAA;EACA,mBAAA;AAAA;AAAA,UAGe,mBAAA;EACf,IAAA;EACA,WAAA;EACA,UAAA,EAAY,WAAA;EACZ,WAAA,GAAc,eAAA;AAAA;AAAA,UAGC,YAAA;EACf,aAAA,IAAiB,mBAAA;EACjB,gBAAA,CACE,IAAA,UACA,IAAA,WACA,MAAA,GAAS,WAAA,GACR,OAAA;AAAA;AAAA,UAOY,OAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,UAAA;EACA,SAAA,GAAY,QAAA;EACZ,SAAA,EAAW,IAAA;AAAA;AAAA,UAGI,QAAA;EACf,EAAA;EACA,IAAA;EACA,IAAA;EANA;;;;AAGF;;;;;EAaE,gBAAA;AAAA;AAAA,UAGe,MAAA;EACf,EAAA;EACA,MAAA;EACA,QAAA,EAAU,OAAA;EACV,SAAA,EAAW,IAAA;EACX,SAAA,EAAW,IAAA;AAAA;AAAA,UAOI,WAAA;EACf,MAAA,CAAO,MAAA,WAAiB,OAAA,CAAQ,MAAA;EAChC,GAAA,CAAI,QAAA,UAAkB,MAAA,WAAiB,OAAA,CAAQ,MAAA;EAC/C,IAAA,CAAK,MAAA,WAAiB,OAAA,CAAQ,MAAA;EAC9B,UAAA,CAAW,QAAA,UAAkB,MAAA,UAAgB,OAAA,EAAS,OAAA,GAAU,OAAA;EAChE,MAAA,CAAO,QAAA,UAAkB,MAAA,WAAiB,OAAA;AAAA;AAAA,KAOhC,UAAA;EACN,IAAA;EAAuB,OAAA;AAAA;EACvB,IAAA;EAAiB,OAAA;AAAA;EACjB,IAAA;EAAmB,MAAA;EAAgB,IAAA;EAAc,IAAA;AAAA;EAEjD,IAAA;EACA,MAAA;EACA,MAAA;EACA,KAAA;AAAA;EAEA,IAAA;EAAkB,OAAA;AAAA;EAElB,IAAA;EACA,MAAA;EACA,KAAA;AAAA;EAEA,IAAA;EAAkB,IAAA,EAAM,MAAA;AAAA;EA1BN;;;;;;;;EAoClB,IAAA;EACA,UAAA;EACA,QAAA;EACA,QAAA;EACA,IAAA;EACA,WAAA,GAAc,eAAA;AAAA;AAAA,UA+HH,UAAA;EACf,QAAA,EAAU,OAAA;EACV,KAAA,EAAO,mBAAA;EACP,QAAA;EACA,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,eAAA;;EAEf,WAAA,GAAc,IAAA,UAAc,IAAA,cAAkB,OAAA;EAC9C,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,YAAA;EACf,GAAA,CACE,KAAA,EAAO,UAAA,EACP,OAAA,EAAS,eAAA,GACR,cAAA,CAAe,UAAA;AAAA"}
@@ -0,0 +1,157 @@
1
+ # Class: AppKitMcpClient
2
+
3
+ Lightweight MCP client for Databricks-hosted MCP servers.
4
+
5
+ Uses raw fetch() with JSON-RPC 2.0 over HTTP — no @modelcontextprotocol/sdk or LangChain dependency. Supports the Streamable HTTP transport only (POST with JSON-RPC request, single JSON-RPC response). Implements exactly four methods: `initialize`, `notifications/initialized`, `tools/list`, `tools/call`. No prompts/resources/completion/sampling.
6
+
7
+ All outbound URLs are gated by an McpHostPolicy: unallowlisted hosts are rejected before the first byte is sent, and workspace credentials are only forwarded to the same-origin workspace. See `mcp-host-policy.ts`.
8
+
9
+ Rationale for hand-rolling JSON-RPC instead of `@modelcontextprotocol/sdk`: see the file-level comment at the top of this module.
10
+
11
+ ## Constructors[​](#constructors "Direct link to Constructors")
12
+
13
+ ### Constructor[​](#constructor "Direct link to Constructor")
14
+
15
+ ```ts
16
+ new AppKitMcpClient(
17
+ workspaceHost: string,
18
+ authenticate: () => Promise<Record<string, string>>,
19
+ policy: McpHostPolicy,
20
+ options: {
21
+ dnsLookup?: DnsLookup;
22
+ fetchImpl?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
23
+ }): AppKitMcpClient;
24
+
25
+ ```
26
+
27
+ #### Parameters[​](#parameters "Direct link to Parameters")
28
+
29
+ | Parameter | Type |
30
+ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
31
+ | `workspaceHost` | `string` |
32
+ | `authenticate` | () => `Promise`<`Record`<`string`, `string`>> |
33
+ | `policy` | `McpHostPolicy` |
34
+ | `options` | { `dnsLookup?`: `DnsLookup`; `fetchImpl?`: (`input`: `string` \| `URL` \| `Request`, `init?`: `RequestInit`) => `Promise`<`Response`>; } |
35
+ | `options.dnsLookup?` | `DnsLookup` |
36
+ | `options.fetchImpl?` | (`input`: `string` \| `URL` \| `Request`, `init?`: `RequestInit`) => `Promise`<`Response`> |
37
+
38
+ #### Returns[​](#returns "Direct link to Returns")
39
+
40
+ `AppKitMcpClient`
41
+
42
+ ## Methods[​](#methods "Direct link to Methods")
43
+
44
+ ### callTool()[​](#calltool "Direct link to callTool()")
45
+
46
+ ```ts
47
+ callTool(
48
+ qualifiedName: string,
49
+ args: unknown,
50
+ authHeaders?: Record<string, string>,
51
+ callerSignal?: AbortSignal): Promise<string>;
52
+
53
+ ```
54
+
55
+ #### Parameters[​](#parameters-1 "Direct link to Parameters")
56
+
57
+ | Parameter | Type |
58
+ | --------------- | ---------------------------- |
59
+ | `qualifiedName` | `string` |
60
+ | `args` | `unknown` |
61
+ | `authHeaders?` | `Record`<`string`, `string`> |
62
+ | `callerSignal?` | `AbortSignal` |
63
+
64
+ #### Returns[​](#returns-1 "Direct link to Returns")
65
+
66
+ `Promise`<`string`>
67
+
68
+ ***
69
+
70
+ ### canForwardWorkspaceAuth()[​](#canforwardworkspaceauth "Direct link to canForwardWorkspaceAuth()")
71
+
72
+ ```ts
73
+ canForwardWorkspaceAuth(serverName: string): boolean;
74
+
75
+ ```
76
+
77
+ Whether the named MCP server may receive workspace-scoped auth headers (e.g., an OBO bearer token from an end-user request). Callers should gate auth-forwarding decisions on this to prevent credential exfiltration to non-workspace hosts.
78
+
79
+ #### Parameters[​](#parameters-2 "Direct link to Parameters")
80
+
81
+ | Parameter | Type |
82
+ | ------------ | -------- |
83
+ | `serverName` | `string` |
84
+
85
+ #### Returns[​](#returns-2 "Direct link to Returns")
86
+
87
+ `boolean`
88
+
89
+ ***
90
+
91
+ ### close()[​](#close "Direct link to close()")
92
+
93
+ ```ts
94
+ close(): Promise<void>;
95
+
96
+ ```
97
+
98
+ #### Returns[​](#returns-3 "Direct link to Returns")
99
+
100
+ `Promise`<`void`>
101
+
102
+ ***
103
+
104
+ ### connect()[​](#connect "Direct link to connect()")
105
+
106
+ ```ts
107
+ connect(endpoint: McpEndpointConfig): Promise<void>;
108
+
109
+ ```
110
+
111
+ #### Parameters[​](#parameters-3 "Direct link to Parameters")
112
+
113
+ | Parameter | Type |
114
+ | ---------- | ------------------- |
115
+ | `endpoint` | `McpEndpointConfig` |
116
+
117
+ #### Returns[​](#returns-4 "Direct link to Returns")
118
+
119
+ `Promise`<`void`>
120
+
121
+ ***
122
+
123
+ ### connectAll()[​](#connectall "Direct link to connectAll()")
124
+
125
+ ```ts
126
+ connectAll(endpoints: McpEndpointConfig[]): Promise<McpConnectAllResult>;
127
+
128
+ ```
129
+
130
+ Connects every endpoint in parallel and returns a structured summary so callers can distinguish "all connected" from "some failed".
131
+
132
+ Returning the result instead of throwing is deliberate: one misconfigured MCP server should not take down the entire agents plugin at boot, and the agents plugin uses the summary to warn at startup with the failed-endpoint names. Errors are also logged here so a caller that ignores the return still gets per-endpoint diagnostics.
133
+
134
+ #### Parameters[​](#parameters-4 "Direct link to Parameters")
135
+
136
+ | Parameter | Type |
137
+ | ----------- | ---------------------- |
138
+ | `endpoints` | `McpEndpointConfig`\[] |
139
+
140
+ #### Returns[​](#returns-5 "Direct link to Returns")
141
+
142
+ `Promise`<[`McpConnectAllResult`](./docs/api/appkit/Interface.McpConnectAllResult.md)>
143
+
144
+ `connected` lists the endpoint names that initialised successfully; `failed` carries `{ name, error }` for the rest.
145
+
146
+ ***
147
+
148
+ ### getAllToolDefinitions()[​](#getalltooldefinitions "Direct link to getAllToolDefinitions()")
149
+
150
+ ```ts
151
+ getAllToolDefinitions(): AgentToolDefinition[];
152
+
153
+ ```
154
+
155
+ #### Returns[​](#returns-6 "Direct link to Returns")
156
+
157
+ [`AgentToolDefinition`](./docs/api/appkit/Interface.AgentToolDefinition.md)\[]