@bolt-foundry/gambit-core 0.8.3 → 0.8.5-rc.4

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 (230) hide show
  1. package/README.md +32 -2
  2. package/{script/deps/jsr.io/@std/collections/1.1.4 → esm/deps/jsr.io/@std/collections/1.1.5}/deep_merge.d.ts +2 -2
  3. package/esm/deps/jsr.io/@std/collections/{1.1.4 → 1.1.5}/deep_merge.d.ts.map +1 -1
  4. package/esm/deps/jsr.io/@std/collections/{1.1.4 → 1.1.5}/deep_merge.js +29 -19
  5. package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.js +1 -1
  6. package/esm/mod.d.ts +9 -1
  7. package/esm/mod.d.ts.map +1 -1
  8. package/esm/mod.js +4 -0
  9. package/esm/schemas/graders/contexts/conversation.d.ts +22 -0
  10. package/esm/schemas/graders/contexts/conversation.d.ts.map +1 -0
  11. package/esm/schemas/graders/contexts/conversation.js +17 -0
  12. package/esm/schemas/graders/contexts/conversation.zod.d.ts +3 -0
  13. package/esm/schemas/graders/contexts/conversation.zod.d.ts.map +1 -0
  14. package/esm/schemas/graders/contexts/conversation.zod.js +2 -0
  15. package/esm/schemas/graders/contexts/conversation_tools.d.ts +31 -0
  16. package/esm/schemas/graders/contexts/conversation_tools.d.ts.map +1 -0
  17. package/esm/schemas/graders/contexts/conversation_tools.js +25 -0
  18. package/esm/schemas/graders/contexts/conversation_tools.zod.d.ts +3 -0
  19. package/esm/schemas/graders/contexts/conversation_tools.zod.d.ts.map +1 -0
  20. package/esm/schemas/graders/contexts/conversation_tools.zod.js +2 -0
  21. package/esm/schemas/graders/contexts/tools.d.ts +4 -0
  22. package/esm/schemas/graders/contexts/tools.d.ts.map +1 -0
  23. package/esm/schemas/graders/contexts/tools.js +3 -0
  24. package/esm/schemas/graders/contexts/tools.zod.d.ts +3 -0
  25. package/esm/schemas/graders/contexts/tools.zod.d.ts.map +1 -0
  26. package/esm/schemas/graders/contexts/tools.zod.js +2 -0
  27. package/esm/schemas/graders/contexts/turn.d.ts +10 -0
  28. package/esm/schemas/graders/contexts/turn.d.ts.map +1 -0
  29. package/esm/schemas/graders/contexts/turn.js +8 -0
  30. package/esm/schemas/graders/contexts/turn.zod.d.ts +3 -0
  31. package/esm/schemas/graders/contexts/turn.zod.d.ts.map +1 -0
  32. package/esm/schemas/graders/contexts/turn.zod.js +2 -0
  33. package/esm/schemas/graders/contexts/turn_tools.d.ts +32 -0
  34. package/esm/schemas/graders/contexts/turn_tools.d.ts.map +1 -0
  35. package/esm/schemas/graders/contexts/turn_tools.js +28 -0
  36. package/esm/schemas/graders/contexts/turn_tools.zod.d.ts +3 -0
  37. package/esm/schemas/graders/contexts/turn_tools.zod.d.ts.map +1 -0
  38. package/esm/schemas/graders/contexts/turn_tools.zod.js +2 -0
  39. package/esm/schemas/graders/grader_output.d.ts +10 -0
  40. package/esm/schemas/graders/grader_output.d.ts.map +1 -0
  41. package/esm/schemas/graders/grader_output.js +8 -0
  42. package/esm/schemas/graders/grader_output.zod.d.ts +3 -0
  43. package/esm/schemas/graders/grader_output.zod.d.ts.map +1 -0
  44. package/esm/schemas/graders/grader_output.zod.js +2 -0
  45. package/esm/schemas/graders/respond.d.ts +12 -0
  46. package/esm/schemas/graders/respond.d.ts.map +1 -0
  47. package/esm/schemas/graders/respond.js +10 -0
  48. package/esm/schemas/graders/respond.zod.d.ts +3 -0
  49. package/esm/schemas/graders/respond.zod.d.ts.map +1 -0
  50. package/esm/schemas/graders/respond.zod.js +2 -0
  51. package/esm/schemas/scenarios/plain_chat_input_optional.d.ts +5 -0
  52. package/esm/schemas/scenarios/plain_chat_input_optional.d.ts.map +1 -0
  53. package/esm/schemas/scenarios/plain_chat_input_optional.js +5 -0
  54. package/esm/schemas/scenarios/plain_chat_input_optional.zod.d.ts +3 -0
  55. package/esm/schemas/scenarios/plain_chat_input_optional.zod.d.ts.map +1 -0
  56. package/esm/schemas/scenarios/plain_chat_input_optional.zod.js +2 -0
  57. package/esm/schemas/scenarios/plain_chat_output.d.ts +5 -0
  58. package/esm/schemas/scenarios/plain_chat_output.d.ts.map +1 -0
  59. package/esm/schemas/scenarios/plain_chat_output.js +4 -0
  60. package/esm/schemas/scenarios/plain_chat_output.zod.d.ts +3 -0
  61. package/esm/schemas/scenarios/plain_chat_output.zod.d.ts.map +1 -0
  62. package/esm/schemas/scenarios/plain_chat_output.zod.js +2 -0
  63. package/esm/src/builtins.d.ts +2 -0
  64. package/esm/src/builtins.d.ts.map +1 -1
  65. package/esm/src/builtins.js +45 -1
  66. package/esm/src/loader.d.ts.map +1 -1
  67. package/esm/src/loader.js +58 -11
  68. package/esm/src/markdown.d.ts.map +1 -1
  69. package/esm/src/markdown.js +167 -41
  70. package/esm/src/permissions.d.ts +143 -0
  71. package/esm/src/permissions.d.ts.map +1 -0
  72. package/esm/src/permissions.js +406 -0
  73. package/esm/src/runtime.d.ts +27 -2
  74. package/esm/src/runtime.d.ts.map +1 -1
  75. package/esm/src/runtime.js +2755 -63
  76. package/esm/src/runtime_exec_host.d.ts +6 -0
  77. package/esm/src/runtime_exec_host.d.ts.map +1 -0
  78. package/esm/src/runtime_exec_host.js +17 -0
  79. package/esm/src/runtime_exec_host_contract.d.ts +23 -0
  80. package/esm/src/runtime_exec_host_contract.d.ts.map +1 -0
  81. package/esm/src/runtime_exec_host_contract.js +14 -0
  82. package/esm/src/runtime_exec_host_deno.d.ts +3 -0
  83. package/esm/src/runtime_exec_host_deno.d.ts.map +1 -0
  84. package/esm/src/runtime_exec_host_deno.js +35 -0
  85. package/esm/src/runtime_exec_host_unsupported.d.ts +3 -0
  86. package/esm/src/runtime_exec_host_unsupported.d.ts.map +1 -0
  87. package/esm/src/runtime_exec_host_unsupported.js +8 -0
  88. package/esm/src/runtime_worker_host.d.ts +6 -0
  89. package/esm/src/runtime_worker_host.d.ts.map +1 -0
  90. package/esm/src/runtime_worker_host.js +17 -0
  91. package/esm/src/runtime_worker_host_contract.d.ts +33 -0
  92. package/esm/src/runtime_worker_host_contract.d.ts.map +1 -0
  93. package/esm/src/runtime_worker_host_contract.js +14 -0
  94. package/esm/src/runtime_worker_host_deno.d.ts +3 -0
  95. package/esm/src/runtime_worker_host_deno.d.ts.map +1 -0
  96. package/esm/src/runtime_worker_host_deno.js +26 -0
  97. package/esm/src/runtime_worker_host_unsupported.d.ts +3 -0
  98. package/esm/src/runtime_worker_host_unsupported.d.ts.map +1 -0
  99. package/esm/src/runtime_worker_host_unsupported.js +8 -0
  100. package/esm/src/state.d.ts +1 -0
  101. package/esm/src/state.d.ts.map +1 -1
  102. package/esm/src/types.d.ts +235 -3
  103. package/esm/src/types.d.ts.map +1 -1
  104. package/package.json +73 -1
  105. package/schemas/graders/contexts/conversation.ts +32 -9
  106. package/schemas/graders/contexts/conversation.zod.ts +1 -0
  107. package/schemas/graders/contexts/conversation_tools.ts +63 -0
  108. package/schemas/graders/contexts/conversation_tools.zod.ts +1 -0
  109. package/schemas/graders/contexts/tools.ts +5 -0
  110. package/schemas/graders/contexts/tools.zod.ts +1 -0
  111. package/schemas/graders/contexts/turn.ts +8 -1
  112. package/schemas/graders/contexts/turn.zod.ts +1 -0
  113. package/schemas/graders/contexts/turn_tools.ts +63 -0
  114. package/schemas/graders/contexts/turn_tools.zod.ts +1 -0
  115. package/schemas/graders/grader_output.ts +9 -1
  116. package/schemas/graders/grader_output.zod.ts +1 -0
  117. package/schemas/graders/respond.ts +13 -3
  118. package/schemas/graders/respond.zod.ts +1 -0
  119. package/schemas/scenarios/plain_chat_input_optional.ts +6 -0
  120. package/schemas/scenarios/plain_chat_input_optional.zod.ts +1 -0
  121. package/schemas/scenarios/plain_chat_output.ts +5 -0
  122. package/schemas/scenarios/plain_chat_output.zod.ts +1 -0
  123. package/{esm/deps/jsr.io/@std/collections/1.1.4 → script/deps/jsr.io/@std/collections/1.1.5}/deep_merge.d.ts +2 -2
  124. package/script/deps/jsr.io/@std/collections/{1.1.4 → 1.1.5}/deep_merge.d.ts.map +1 -1
  125. package/script/deps/jsr.io/@std/collections/{1.1.4 → 1.1.5}/deep_merge.js +29 -19
  126. package/script/deps/jsr.io/@std/toml/1.0.11/_parser.js +1 -1
  127. package/script/mod.d.ts +9 -1
  128. package/script/mod.d.ts.map +1 -1
  129. package/script/mod.js +12 -1
  130. package/script/schemas/graders/contexts/conversation.d.ts +22 -0
  131. package/script/schemas/graders/contexts/conversation.d.ts.map +1 -0
  132. package/script/schemas/graders/contexts/conversation.js +20 -0
  133. package/script/schemas/graders/contexts/conversation.zod.d.ts +3 -0
  134. package/script/schemas/graders/contexts/conversation.zod.d.ts.map +1 -0
  135. package/script/schemas/graders/contexts/conversation.zod.js +9 -0
  136. package/script/schemas/graders/contexts/conversation_tools.d.ts +31 -0
  137. package/script/schemas/graders/contexts/conversation_tools.d.ts.map +1 -0
  138. package/script/schemas/graders/contexts/conversation_tools.js +28 -0
  139. package/script/schemas/graders/contexts/conversation_tools.zod.d.ts +3 -0
  140. package/script/schemas/graders/contexts/conversation_tools.zod.d.ts.map +1 -0
  141. package/script/schemas/graders/contexts/conversation_tools.zod.js +9 -0
  142. package/script/schemas/graders/contexts/tools.d.ts +4 -0
  143. package/script/schemas/graders/contexts/tools.d.ts.map +1 -0
  144. package/script/schemas/graders/contexts/tools.js +12 -0
  145. package/script/schemas/graders/contexts/tools.zod.d.ts +3 -0
  146. package/script/schemas/graders/contexts/tools.zod.d.ts.map +1 -0
  147. package/script/schemas/graders/contexts/tools.zod.js +9 -0
  148. package/script/schemas/graders/contexts/turn.d.ts +10 -0
  149. package/script/schemas/graders/contexts/turn.d.ts.map +1 -0
  150. package/script/schemas/graders/contexts/turn.js +10 -0
  151. package/script/schemas/graders/contexts/turn.zod.d.ts +3 -0
  152. package/script/schemas/graders/contexts/turn.zod.d.ts.map +1 -0
  153. package/script/schemas/graders/contexts/turn.zod.js +9 -0
  154. package/script/schemas/graders/contexts/turn_tools.d.ts +32 -0
  155. package/script/schemas/graders/contexts/turn_tools.d.ts.map +1 -0
  156. package/script/schemas/graders/contexts/turn_tools.js +31 -0
  157. package/script/schemas/graders/contexts/turn_tools.zod.d.ts +3 -0
  158. package/script/schemas/graders/contexts/turn_tools.zod.d.ts.map +1 -0
  159. package/script/schemas/graders/contexts/turn_tools.zod.js +9 -0
  160. package/script/schemas/graders/grader_output.d.ts +10 -0
  161. package/script/schemas/graders/grader_output.d.ts.map +1 -0
  162. package/script/schemas/graders/grader_output.js +10 -0
  163. package/script/schemas/graders/grader_output.zod.d.ts +3 -0
  164. package/script/schemas/graders/grader_output.zod.d.ts.map +1 -0
  165. package/script/schemas/graders/grader_output.zod.js +9 -0
  166. package/script/schemas/graders/respond.d.ts +12 -0
  167. package/script/schemas/graders/respond.d.ts.map +1 -0
  168. package/script/schemas/graders/respond.js +12 -0
  169. package/script/schemas/graders/respond.zod.d.ts +3 -0
  170. package/script/schemas/graders/respond.zod.d.ts.map +1 -0
  171. package/script/schemas/graders/respond.zod.js +9 -0
  172. package/script/schemas/scenarios/plain_chat_input_optional.d.ts +5 -0
  173. package/script/schemas/scenarios/plain_chat_input_optional.d.ts.map +1 -0
  174. package/script/schemas/scenarios/plain_chat_input_optional.js +7 -0
  175. package/script/schemas/scenarios/plain_chat_input_optional.zod.d.ts +3 -0
  176. package/script/schemas/scenarios/plain_chat_input_optional.zod.d.ts.map +1 -0
  177. package/script/schemas/scenarios/plain_chat_input_optional.zod.js +9 -0
  178. package/script/schemas/scenarios/plain_chat_output.d.ts +5 -0
  179. package/script/schemas/scenarios/plain_chat_output.d.ts.map +1 -0
  180. package/script/schemas/scenarios/plain_chat_output.js +6 -0
  181. package/script/schemas/scenarios/plain_chat_output.zod.d.ts +3 -0
  182. package/script/schemas/scenarios/plain_chat_output.zod.d.ts.map +1 -0
  183. package/script/schemas/scenarios/plain_chat_output.zod.js +9 -0
  184. package/script/src/builtins.d.ts +2 -0
  185. package/script/src/builtins.d.ts.map +1 -1
  186. package/script/src/builtins.js +47 -1
  187. package/script/src/loader.d.ts.map +1 -1
  188. package/script/src/loader.js +57 -10
  189. package/script/src/markdown.d.ts.map +1 -1
  190. package/script/src/markdown.js +167 -41
  191. package/script/src/permissions.d.ts +143 -0
  192. package/script/src/permissions.d.ts.map +1 -0
  193. package/script/src/permissions.js +453 -0
  194. package/script/src/runtime.d.ts +27 -2
  195. package/script/src/runtime.d.ts.map +1 -1
  196. package/script/src/runtime.js +2758 -63
  197. package/script/src/runtime_exec_host.d.ts +6 -0
  198. package/script/src/runtime_exec_host.d.ts.map +1 -0
  199. package/script/src/runtime_exec_host.js +56 -0
  200. package/script/src/runtime_exec_host_contract.d.ts +23 -0
  201. package/script/src/runtime_exec_host_contract.d.ts.map +1 -0
  202. package/script/src/runtime_exec_host_contract.js +18 -0
  203. package/script/src/runtime_exec_host_deno.d.ts +3 -0
  204. package/script/src/runtime_exec_host_deno.d.ts.map +1 -0
  205. package/script/src/runtime_exec_host_deno.js +71 -0
  206. package/script/src/runtime_exec_host_unsupported.d.ts +3 -0
  207. package/script/src/runtime_exec_host_unsupported.d.ts.map +1 -0
  208. package/script/src/runtime_exec_host_unsupported.js +11 -0
  209. package/script/src/runtime_worker_host.d.ts +6 -0
  210. package/script/src/runtime_worker_host.d.ts.map +1 -0
  211. package/script/src/runtime_worker_host.js +56 -0
  212. package/script/src/runtime_worker_host_contract.d.ts +33 -0
  213. package/script/src/runtime_worker_host_contract.d.ts.map +1 -0
  214. package/script/src/runtime_worker_host_contract.js +18 -0
  215. package/script/src/runtime_worker_host_deno.d.ts +3 -0
  216. package/script/src/runtime_worker_host_deno.d.ts.map +1 -0
  217. package/script/src/runtime_worker_host_deno.js +62 -0
  218. package/script/src/runtime_worker_host_unsupported.d.ts +3 -0
  219. package/script/src/runtime_worker_host_unsupported.d.ts.map +1 -0
  220. package/script/src/runtime_worker_host_unsupported.js +11 -0
  221. package/script/src/state.d.ts +1 -0
  222. package/script/src/state.d.ts.map +1 -1
  223. package/script/src/types.d.ts +235 -3
  224. package/script/src/types.d.ts.map +1 -1
  225. package/esm/deps/jsr.io/@std/collections/1.1.4/_utils.d.ts +0 -6
  226. package/esm/deps/jsr.io/@std/collections/1.1.4/_utils.d.ts.map +0 -1
  227. package/esm/deps/jsr.io/@std/collections/1.1.4/_utils.js +0 -18
  228. package/script/deps/jsr.io/@std/collections/1.1.4/_utils.d.ts +0 -6
  229. package/script/deps/jsr.io/@std/collections/1.1.4/_utils.d.ts.map +0 -1
  230. package/script/deps/jsr.io/@std/collections/1.1.4/_utils.js +0 -21
@@ -0,0 +1,5 @@
1
+ import "../../_dnt.polyfills.js";
2
+ import { z } from "zod";
3
+ declare const plainChatInputOptionalSchema: z.ZodType<string | undefined>;
4
+ export default plainChatInputOptionalSchema;
5
+ //# sourceMappingURL=plain_chat_input_optional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain_chat_input_optional.d.ts","sourceRoot":"","sources":["../../../src/schemas/scenarios/plain_chat_input_optional.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,4BAA4B,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,SAAS,CACnD,CAAC;AAEd,eAAe,4BAA4B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import "../../_dnt.polyfills.js";
2
+ import { z } from "zod";
3
+ const plainChatInputOptionalSchema = z.string()
4
+ .optional();
5
+ export default plainChatInputOptionalSchema;
@@ -0,0 +1,3 @@
1
+ import "../../_dnt.polyfills.js";
2
+ export { default } from "./plain_chat_input_optional.js";
3
+ //# sourceMappingURL=plain_chat_input_optional.zod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain_chat_input_optional.zod.d.ts","sourceRoot":"","sources":["../../../src/schemas/scenarios/plain_chat_input_optional.zod.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import "../../_dnt.polyfills.js";
2
+ export { default } from "./plain_chat_input_optional.js";
@@ -0,0 +1,5 @@
1
+ import "../../_dnt.polyfills.js";
2
+ import { z } from "zod";
3
+ declare const plainChatOutputSchema: z.ZodType<string>;
4
+ export default plainChatOutputSchema;
5
+ //# sourceMappingURL=plain_chat_output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain_chat_output.d.ts","sourceRoot":"","sources":["../../../src/schemas/scenarios/plain_chat_output.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAc,CAAC;AAE5D,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import "../../_dnt.polyfills.js";
2
+ import { z } from "zod";
3
+ const plainChatOutputSchema = z.string();
4
+ export default plainChatOutputSchema;
@@ -0,0 +1,3 @@
1
+ import "../../_dnt.polyfills.js";
2
+ export { default } from "./plain_chat_output.js";
3
+ //# sourceMappingURL=plain_chat_output.zod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain_chat_output.zod.d.ts","sourceRoot":"","sources":["../../../src/schemas/scenarios/plain_chat_output.zod.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import "../../_dnt.polyfills.js";
2
+ export { default } from "./plain_chat_output.js";
@@ -1,3 +1,5 @@
1
1
  export declare function resolveBuiltinCardPath(target: string): string | undefined;
2
+ export declare function resolveBuiltinSnippetPath(target: string): string | undefined;
2
3
  export declare function resolveBuiltinSchemaPath(target: string): string | undefined;
4
+ export declare function resolveBuiltinDeckPath(target: string): string | undefined;
3
5
  //# sourceMappingURL=builtins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/src/builtins.ts"],"names":[],"mappings":"AAYA,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOzE;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3E"}
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/src/builtins.ts"],"names":[],"mappings":"AAqBA,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAazE;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO5E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgB3E;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBzE"}
@@ -1,26 +1,70 @@
1
1
  import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
2
2
  const CARDS_PREFIX = "gambit://cards/";
3
+ const SNIPPETS_PREFIX = "gambit://snippets/";
3
4
  const SCHEMAS_PREFIX = "gambit://schemas/";
5
+ const DECKS_PREFIX = "gambit://decks/";
4
6
  const CARDS_BASE_URL = new URL("../cards/", globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
7
+ const SNIPPETS_BASE_URL = new URL("../snippets/", globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
5
8
  const SCHEMAS_BASE_URL = new URL("../schemas/", globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
9
+ const DECKS_BASE_URL = new URL("../decks/", globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
10
+ const LEGACY_CARD_WARNINGS = new Set();
11
+ const LEGACY_SCHEMA_WARNINGS = new Set();
12
+ const LEGACY_DECK_WARNINGS = new Set();
13
+ const logger = console;
6
14
  function resolveFromBase(base, relative) {
7
15
  return path.fromFileUrl(new URL(relative, base));
8
16
  }
9
17
  export function resolveBuiltinCardPath(target) {
10
18
  if (!target.startsWith(CARDS_PREFIX))
11
19
  return undefined;
20
+ if (!LEGACY_CARD_WARNINGS.has(target)) {
21
+ LEGACY_CARD_WARNINGS.add(target);
22
+ logger.warn(`[gambit] "${target}" is deprecated; use gambit://snippets instead.`);
23
+ }
12
24
  const relative = target.slice(CARDS_PREFIX.length);
13
25
  if (!relative) {
14
26
  throw new Error(`Invalid gambit card specifier: ${target}`);
15
27
  }
16
28
  return resolveFromBase(CARDS_BASE_URL, relative);
17
29
  }
30
+ export function resolveBuiltinSnippetPath(target) {
31
+ if (!target.startsWith(SNIPPETS_PREFIX))
32
+ return undefined;
33
+ const relative = target.slice(SNIPPETS_PREFIX.length);
34
+ if (!relative) {
35
+ throw new Error(`Invalid gambit snippet specifier: ${target}`);
36
+ }
37
+ return resolveFromBase(SNIPPETS_BASE_URL, relative);
38
+ }
18
39
  export function resolveBuiltinSchemaPath(target) {
19
40
  if (!target.startsWith(SCHEMAS_PREFIX))
20
41
  return undefined;
21
- const relative = target.slice(SCHEMAS_PREFIX.length);
42
+ let relative = target.slice(SCHEMAS_PREFIX.length);
22
43
  if (!relative) {
23
44
  throw new Error(`Invalid gambit schema specifier: ${target}`);
24
45
  }
46
+ if (relative.endsWith(".ts") && !relative.endsWith(".zod.ts")) {
47
+ if (!LEGACY_SCHEMA_WARNINGS.has(target)) {
48
+ LEGACY_SCHEMA_WARNINGS.add(target);
49
+ logger.warn(`[gambit] "${target}" is deprecated; use .zod.ts schema URIs instead.`);
50
+ }
51
+ relative = `${relative.slice(0, -3)}.zod.ts`;
52
+ }
25
53
  return resolveFromBase(SCHEMAS_BASE_URL, relative);
26
54
  }
55
+ export function resolveBuiltinDeckPath(target) {
56
+ if (!target.startsWith(DECKS_PREFIX))
57
+ return undefined;
58
+ let relative = target.slice(DECKS_PREFIX.length);
59
+ if (!relative) {
60
+ throw new Error(`Invalid gambit deck specifier: ${target}`);
61
+ }
62
+ if (!relative.endsWith("/PROMPT.md")) {
63
+ if (!LEGACY_DECK_WARNINGS.has(target)) {
64
+ LEGACY_DECK_WARNINGS.add(target);
65
+ logger.warn(`[gambit] "${target}" is deprecated; use gambit://decks/.../PROMPT.md instead.`);
66
+ }
67
+ relative = `${relative.replace(/\/?$/, "/")}PROMPT.md`;
68
+ }
69
+ return resolveFromBase(DECKS_BASE_URL, relative);
70
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/src/loader.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAKV,UAAU,EACV,UAAU,EAEX,MAAM,YAAY,CAAC;AAgMpB,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,GAAE,KAAK,CAAC,MAAM,CAAM,GACxB,OAAO,CAAC,UAAU,CAAC,CAOrB;AAED,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAsIrB"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/src/loader.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAMV,UAAU,EACV,UAAU,EAEX,MAAM,YAAY,CAAC;AAiPpB,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,GAAE,KAAK,CAAC,MAAM,CAAM,GACxB,OAAO,CAAC,UAAU,CAAC,CAQrB;AAED,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CA4JrB"}
package/esm/src/loader.js CHANGED
@@ -1,9 +1,11 @@
1
+ import * as dntShim from "../_dnt.shims.js";
1
2
  import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
2
3
  import { BUILTIN_TOOL_NAME_SET, MAX_TOOL_NAME_LENGTH, RESERVED_TOOL_PREFIX, TOOL_NAME_PATTERN, } from "./constants.js";
3
4
  import { isCardDefinition, isDeckDefinition } from "./definitions.js";
5
+ import { normalizePermissionDeclaration, } from "./permissions.js";
4
6
  import { mergeZodObjects } from "./schema.js";
5
7
  import { isMarkdownFile, loadMarkdownCard, loadMarkdownDeck, } from "./markdown.js";
6
- import { resolveBuiltinCardPath } from "./builtins.js";
8
+ import { resolveBuiltinCardPath, resolveBuiltinDeckPath, resolveBuiltinSnippetPath, } from "./builtins.js";
7
9
  const logger = console;
8
10
  const LEGACY_SCHEMA_WARNINGS = new Set();
9
11
  const LEGACY_FRAGMENT_WARNINGS = new Set();
@@ -62,7 +64,10 @@ function normalizeActionDecks(actions, basePath) {
62
64
  return [];
63
65
  return actions.map((a) => ({
64
66
  ...a,
65
- path: basePath ? path.resolve(path.dirname(basePath), a.path) : a.path,
67
+ path: a.path.startsWith("gambit://") || !basePath
68
+ ? a.path
69
+ : path.resolve(path.dirname(basePath), a.path),
70
+ permissions: normalizePermissionDeclaration(a.permissions, basePath ? path.dirname(basePath) : dntShim.Deno.cwd()),
66
71
  }));
67
72
  }
68
73
  function normalizeCompanionDecks(decks, basePath) {
@@ -70,9 +75,10 @@ function normalizeCompanionDecks(decks, basePath) {
70
75
  return [];
71
76
  return decks.map((deck) => ({
72
77
  ...deck,
73
- path: basePath
74
- ? path.resolve(path.dirname(basePath), deck.path)
75
- : deck.path,
78
+ path: deck.path.startsWith("gambit://") || !basePath
79
+ ? deck.path
80
+ : path.resolve(path.dirname(basePath), deck.path),
81
+ permissions: normalizePermissionDeclaration(deck.permissions, basePath ? path.dirname(basePath) : dntShim.Deno.cwd()),
76
82
  }));
77
83
  }
78
84
  function checkReserved(action) {
@@ -85,6 +91,30 @@ function checkReserved(action) {
85
91
  throw new Error(`Action name ${action.name} must match ${TOOL_NAME_PATTERN} and be <= ${MAX_TOOL_NAME_LENGTH} characters`);
86
92
  }
87
93
  }
94
+ function normalizeExternalTools(tools, resolvedPath) {
95
+ if (!tools)
96
+ return [];
97
+ return tools.map((tool) => {
98
+ const name = String(tool.name ?? "").trim();
99
+ if (!name) {
100
+ throw new Error(`External tool must include a name (${resolvedPath})`);
101
+ }
102
+ if (name.startsWith(RESERVED_TOOL_PREFIX)) {
103
+ throw new Error(`External tool name ${name} is reserved (prefix ${RESERVED_TOOL_PREFIX})`);
104
+ }
105
+ if (!TOOL_NAME_PATTERN.test(name) ||
106
+ name.length > MAX_TOOL_NAME_LENGTH) {
107
+ throw new Error(`External tool name ${name} must match ${TOOL_NAME_PATTERN} and be <= ${MAX_TOOL_NAME_LENGTH} characters`);
108
+ }
109
+ return {
110
+ name,
111
+ description: typeof tool.description === "string"
112
+ ? tool.description
113
+ : undefined,
114
+ inputSchema: tool.inputSchema,
115
+ };
116
+ });
117
+ }
88
118
  async function loadCardInternal(cardPath, parentPath, stack = []) {
89
119
  const resolved = parentPath
90
120
  ? path.resolve(path.dirname(parentPath), cardPath)
@@ -120,28 +150,36 @@ async function loadCardInternal(cardPath, parentPath, stack = []) {
120
150
  path: resolved,
121
151
  cards: [],
122
152
  ...fragments,
153
+ permissions: normalizePermissionDeclaration(card.permissions, path.dirname(resolved)),
123
154
  };
124
155
  }
125
156
  export async function loadCard(cardPath, parentPath, stack = []) {
126
157
  const builtinPath = resolveBuiltinCardPath(cardPath);
127
- const normalizedPath = builtinPath ?? cardPath;
158
+ const snippetPath = resolveBuiltinSnippetPath(cardPath);
159
+ const normalizedPath = snippetPath ?? builtinPath ?? cardPath;
128
160
  if (isMarkdownFile(normalizedPath)) {
129
161
  return await loadMarkdownCard(normalizedPath, parentPath, stack);
130
162
  }
131
163
  return await loadCardInternal(normalizedPath, parentPath, stack);
132
164
  }
133
165
  export async function loadDeck(deckPath, parentPath) {
134
- if (isMarkdownFile(deckPath)) {
135
- return await loadMarkdownDeck(deckPath, parentPath);
166
+ const builtinDeck = resolveBuiltinDeckPath(deckPath);
167
+ const normalizedDeckPath = builtinDeck ?? deckPath;
168
+ const markdownParent = builtinDeck ? undefined : parentPath;
169
+ if (isMarkdownFile(normalizedDeckPath)) {
170
+ return await loadMarkdownDeck(normalizedDeckPath, markdownParent);
136
171
  }
137
- const resolved = parentPath
138
- ? path.resolve(path.dirname(parentPath), deckPath)
139
- : path.resolve(deckPath);
172
+ const resolved = markdownParent
173
+ ? path.resolve(path.dirname(markdownParent), normalizedDeckPath)
174
+ : path.resolve(normalizedDeckPath);
140
175
  const mod = await import(toFileUrl(resolved));
141
176
  const deck = mod.default;
142
177
  if (!isDeckDefinition(deck)) {
143
178
  throw new Error(`Deck at ${resolved} did not export a valid deck definition`);
144
179
  }
180
+ if (deck.mcpServers !== undefined) {
181
+ throw new Error(`Deck-level [[mcpServers]] is unsupported in this phase (${resolved})`);
182
+ }
145
183
  const deckLabel = deck.label;
146
184
  const cards = [];
147
185
  const mergedActions = {};
@@ -161,6 +199,13 @@ export async function loadDeck(deckPath, parentPath) {
161
199
  mergedActions[action.name] = action;
162
200
  }
163
201
  const actionDecks = Object.values(mergedActions);
202
+ const tools = normalizeExternalTools(deck.tools, resolved);
203
+ const actionNames = new Set(actionDecks.map((action) => action.name));
204
+ for (const tool of tools) {
205
+ if (actionNames.has(tool.name)) {
206
+ logger.warn(`[gambit] tool ${tool.name} is shadowed by an action in ${resolved}`);
207
+ }
208
+ }
164
209
  const schemaAliases = normalizeDeckSchemas(deck, resolved);
165
210
  let inputSchema = schemaAliases.inputSchema;
166
211
  let outputSchema = schemaAliases.outputSchema;
@@ -220,6 +265,7 @@ export async function loadDeck(deckPath, parentPath) {
220
265
  actions: actionDecks,
221
266
  testDecks: normalizeCompanionDecks(deck.testDecks, resolved),
222
267
  graderDecks: normalizeCompanionDecks(deck.graderDecks, resolved),
268
+ tools,
223
269
  contextSchema,
224
270
  responseSchema,
225
271
  inputSchema,
@@ -227,6 +273,7 @@ export async function loadDeck(deckPath, parentPath) {
227
273
  executor,
228
274
  handlers,
229
275
  respond: deck.respond,
276
+ permissions: normalizePermissionDeclaration(deck.permissions, path.dirname(resolved)),
230
277
  };
231
278
  }
232
279
  function flattenCards(cards) {
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/src/markdown.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAIV,UAAU,EACV,UAAU,EAEX,MAAM,YAAY,CAAC;AA+LpB,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,GAAE,KAAK,CAAC,MAAM,CAAM,GACxB,OAAO,CAAC,UAAU,CAAC,CA0GrB;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAgMrB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/src/markdown.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAKV,UAAU,EACV,UAAU,EAEX,MAAM,YAAY,CAAC;AAuVpB,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,GAAE,KAAK,CAAC,MAAM,CAAM,GACxB,OAAO,CAAC,UAAU,CAAC,CAsGrB;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAqPrB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD"}
@@ -4,6 +4,7 @@ import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
4
4
  import { BUILTIN_TOOL_NAME_SET, GAMBIT_TOOL_CONTEXT, GAMBIT_TOOL_END, GAMBIT_TOOL_RESPOND, MAX_TOOL_NAME_LENGTH, RESERVED_TOOL_PREFIX, TOOL_NAME_PATTERN, } from "./constants.js";
5
5
  import { isCardDefinition } from "./definitions.js";
6
6
  import { loadCard } from "./loader.js";
7
+ import { normalizePermissionDeclaration, } from "./permissions.js";
7
8
  import { mergeZodObjects } from "./schema.js";
8
9
  import { resolveBuiltinSchemaPath } from "./builtins.js";
9
10
  const logger = console;
@@ -50,6 +51,23 @@ function toFileUrl(p) {
50
51
  const abs = path.resolve(p);
51
52
  return path.toFileUrl(abs).href;
52
53
  }
54
+ function startsWithFrontMatterDelimiter(raw) {
55
+ const normalized = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
56
+ const trimmed = normalized.trimStart();
57
+ return /^(\+\+\+|---)\s*(\r?\n|$)/.test(trimmed);
58
+ }
59
+ function parseFrontMatterOrRaw(raw, resolvedPath) {
60
+ try {
61
+ return extract(raw);
62
+ }
63
+ catch (err) {
64
+ if (!startsWithFrontMatterDelimiter(raw)) {
65
+ return { attrs: {}, body: raw };
66
+ }
67
+ const message = err instanceof Error ? err.message : String(err);
68
+ throw new Error(`Failed to parse front matter in ${resolvedPath}: ${message}`);
69
+ }
70
+ }
53
71
  async function maybeLoadSchema(schemaPath, basePath) {
54
72
  if (!schemaPath || typeof schemaPath !== "string")
55
73
  return undefined;
@@ -59,7 +77,7 @@ async function maybeLoadSchema(schemaPath, basePath) {
59
77
  const mod = await import(toFileUrl(resolved));
60
78
  return mod.default;
61
79
  }
62
- function normalizeDeckRefs(refs, basePath) {
80
+ function normalizeDeckRefs(refs, basePath, opts) {
63
81
  if (!Array.isArray(refs))
64
82
  return [];
65
83
  return refs
@@ -70,14 +88,32 @@ function normalizeDeckRefs(refs, basePath) {
70
88
  if (!p) {
71
89
  throw new Error("Deck reference must include a path");
72
90
  }
91
+ if (opts?.requirePrompt && !p.endsWith("PROMPT.md")) {
92
+ throw new Error(`Deck reference must point to PROMPT.md (${basePath})`);
93
+ }
73
94
  const normalized = { ...rec };
74
- normalized.path = path.resolve(path.dirname(basePath), p);
95
+ normalized.path = p.startsWith("gambit://")
96
+ ? p
97
+ : path.resolve(path.dirname(basePath), p);
75
98
  if (typeof rec.description !== "string")
76
99
  delete normalized.description;
77
100
  if (typeof rec.label !== "string")
78
101
  delete normalized.label;
79
102
  if (typeof rec.id !== "string")
80
103
  delete normalized.id;
104
+ if (rec.permissions !== undefined) {
105
+ const parsed = normalizePermissionDeclaration(rec.permissions, path.dirname(basePath));
106
+ if (parsed)
107
+ normalized.permissions = parsed;
108
+ }
109
+ if (opts?.requireDescription) {
110
+ const desc = typeof rec.description === "string"
111
+ ? rec.description.trim()
112
+ : "";
113
+ if (!desc) {
114
+ throw new Error(`Action deck must include a description (${basePath})`);
115
+ }
116
+ }
81
117
  return normalized;
82
118
  });
83
119
  }
@@ -94,14 +130,92 @@ function mergeDeckRefs(...lists) {
94
130
  }
95
131
  return Array.from(merged.values());
96
132
  }
97
- function normalizeActionDecks(entries, basePath) {
98
- return normalizeDeckRefs(entries, basePath).map((entry) => {
99
- const name = "name" in entry ? String(entry.name ?? "").trim() : "";
133
+ async function normalizeActionDecks(entries, basePath, opts) {
134
+ if (!Array.isArray(entries))
135
+ return [];
136
+ const out = [];
137
+ for (const rawEntry of entries) {
138
+ if (!rawEntry || typeof rawEntry !== "object")
139
+ continue;
140
+ const rec = rawEntry;
141
+ const name = String(rec.name ?? "").trim();
100
142
  if (!name) {
101
143
  throw new Error(`Action deck must include a name (${basePath})`);
102
144
  }
103
- return { ...entry, name };
104
- });
145
+ const desc = typeof rec.description === "string"
146
+ ? rec.description.trim()
147
+ : "";
148
+ if (opts?.requireDescription && !desc) {
149
+ throw new Error(`Action deck must include a description (${basePath})`);
150
+ }
151
+ const rawPath = typeof rec.path === "string" ? rec.path.trim() : "";
152
+ const rawExecute = typeof rec.execute === "string"
153
+ ? rec.execute.trim()
154
+ : "";
155
+ const hasPath = rawPath.length > 0;
156
+ const hasExecute = rawExecute.length > 0;
157
+ if (hasPath === hasExecute) {
158
+ throw new Error(`Action deck must include exactly one of path or execute (${basePath})`);
159
+ }
160
+ if (hasPath && opts?.requirePrompt && !rawPath.endsWith("PROMPT.md")) {
161
+ throw new Error(`Deck reference must point to PROMPT.md (${basePath})`);
162
+ }
163
+ const actionContextSchema = await maybeLoadSchema(rec.contextSchema, basePath);
164
+ const actionResponseSchema = await maybeLoadSchema(rec.responseSchema, basePath);
165
+ if (hasExecute && (!actionContextSchema || !actionResponseSchema)) {
166
+ throw new Error(`Action execute target must include contextSchema and responseSchema (${basePath})`);
167
+ }
168
+ const selectedTarget = hasPath ? rawPath : rawExecute;
169
+ const normalizedPath = selectedTarget.startsWith("gambit://")
170
+ ? selectedTarget
171
+ : path.resolve(path.dirname(basePath), selectedTarget);
172
+ const normalized = {
173
+ name,
174
+ path: normalizedPath,
175
+ description: desc || undefined,
176
+ label: typeof rec.label === "string" ? rec.label : undefined,
177
+ id: typeof rec.id === "string" ? rec.id : undefined,
178
+ execute: hasExecute ? normalizedPath : undefined,
179
+ contextSchema: actionContextSchema,
180
+ responseSchema: actionResponseSchema,
181
+ };
182
+ if (rec.permissions !== undefined) {
183
+ const parsed = normalizePermissionDeclaration(rec.permissions, path.dirname(basePath));
184
+ if (parsed)
185
+ normalized.permissions = parsed;
186
+ }
187
+ out.push(normalized);
188
+ }
189
+ return out;
190
+ }
191
+ async function normalizeExternalTools(refs, basePath) {
192
+ if (!Array.isArray(refs))
193
+ return [];
194
+ const out = [];
195
+ for (const entry of refs) {
196
+ if (!entry || typeof entry !== "object")
197
+ continue;
198
+ const rec = entry;
199
+ const name = String(rec.name ?? "").trim();
200
+ if (!name) {
201
+ throw new Error(`External tool must include a name (${basePath})`);
202
+ }
203
+ if (name.startsWith(RESERVED_TOOL_PREFIX)) {
204
+ throw new Error(`External tool name ${name} is reserved (prefix ${RESERVED_TOOL_PREFIX})`);
205
+ }
206
+ if (!TOOL_NAME_PATTERN.test(name) || name.length > MAX_TOOL_NAME_LENGTH) {
207
+ throw new Error(`External tool name ${name} must match ${TOOL_NAME_PATTERN} and be <= ${MAX_TOOL_NAME_LENGTH} characters`);
208
+ }
209
+ const inputSchema = await maybeLoadSchema(rec.inputSchema, basePath);
210
+ out.push({
211
+ name,
212
+ description: typeof rec.description === "string"
213
+ ? rec.description
214
+ : undefined,
215
+ inputSchema,
216
+ });
217
+ }
218
+ return out;
105
219
  }
106
220
  async function expandEmbedsInBody(args) {
107
221
  const { body, resolvedPath, stack } = args;
@@ -117,17 +231,17 @@ async function expandEmbedsInBody(args) {
117
231
  const target = match[1];
118
232
  out += body.slice(lastIndex, matchIndex);
119
233
  if (target === RESPOND_MARKER) {
120
- warnLegacyMarker("respond", "gambit://cards/respond.card.md");
234
+ warnLegacyMarker("respond", "gambit://snippets/respond.md");
121
235
  respond = true;
122
236
  out += RESPOND_TEXT;
123
237
  }
124
238
  else if (target === INIT_MARKER) {
125
- warnLegacyMarker("init", "gambit://cards/context.card.md");
239
+ warnLegacyMarker("init", "gambit://snippets/context.md");
126
240
  initHint = true;
127
241
  out += INIT_TEXT;
128
242
  }
129
243
  else if (target === END_MARKER) {
130
- warnLegacyMarker("end", "gambit://cards/end.card.md");
244
+ warnLegacyMarker("end", "gambit://snippets/end.md");
131
245
  endHint = true;
132
246
  out += END_TEXT;
133
247
  }
@@ -151,17 +265,7 @@ export async function loadMarkdownCard(filePath, parentPath, stack = []) {
151
265
  }
152
266
  const nextStack = [...stack, resolved];
153
267
  const raw = await dntShim.Deno.readTextFile(resolved);
154
- let attrs;
155
- let body;
156
- try {
157
- const parsed = extract(raw);
158
- attrs = parsed.attrs;
159
- body = parsed.body;
160
- }
161
- catch (err) {
162
- const message = err instanceof Error ? err.message : String(err);
163
- throw new Error(`Failed to parse front matter in ${resolved}: ${message}`);
164
- }
268
+ const { attrs, body } = parseFrontMatterOrRaw(raw, resolved);
165
269
  const candidate = attrs;
166
270
  if (isCardDefinition(candidate)) {
167
271
  // treat attrs as ts-shaped card
@@ -171,7 +275,7 @@ export async function loadMarkdownCard(filePath, parentPath, stack = []) {
171
275
  }
172
276
  const hasNewActionField = attrs.actionDecks;
173
277
  const legacyActions = attrs.actions;
174
- const actionDecks = normalizeActionDecks(hasNewActionField ?? legacyActions, resolved);
278
+ const actionDecks = await normalizeActionDecks(hasNewActionField ?? legacyActions, resolved);
175
279
  if (!hasNewActionField && legacyActions) {
176
280
  logger.warn(`[gambit] card at ${resolved} uses deprecated "actions"; rename to "actionDecks"`);
177
281
  }
@@ -205,6 +309,7 @@ export async function loadMarkdownCard(filePath, parentPath, stack = []) {
205
309
  const embeddedCards = replaced.embeds;
206
310
  const respondFlag = Boolean(attrs.respond);
207
311
  const allowEndFlag = Boolean(attrs.allowEnd);
312
+ const permissions = normalizePermissionDeclaration(attrs.permissions, path.dirname(resolved));
208
313
  return {
209
314
  kind: "gambit.card",
210
315
  path: resolved,
@@ -215,6 +320,7 @@ export async function loadMarkdownCard(filePath, parentPath, stack = []) {
215
320
  testDecks: normalizeDeckRefs(attrs.testDecks, resolved),
216
321
  graderDecks: normalizeDeckRefs(attrs.graderDecks, resolved),
217
322
  cards: embeddedCards,
323
+ permissions,
218
324
  contextFragment,
219
325
  responseFragment,
220
326
  inputFragment: contextFragment,
@@ -227,26 +333,35 @@ export async function loadMarkdownDeck(filePath, parentPath) {
227
333
  ? path.resolve(path.dirname(parentPath), filePath)
228
334
  : path.resolve(filePath);
229
335
  const raw = await dntShim.Deno.readTextFile(resolved);
230
- let attrs;
231
- let body;
232
- try {
233
- const parsed = extract(raw);
234
- attrs = parsed.attrs;
235
- body = parsed.body;
236
- }
237
- catch (err) {
238
- const message = err instanceof Error ? err.message : String(err);
239
- throw new Error(`Failed to parse front matter in ${resolved}: ${message}`);
240
- }
336
+ const { attrs, body } = parseFrontMatterOrRaw(raw, resolved);
241
337
  const deckAttrs = attrs;
242
338
  const deckMeta = (deckAttrs.deck ?? deckAttrs);
339
+ if (deckMeta.mcpServers !== undefined) {
340
+ throw new Error(`Deck-level [[mcpServers]] is unsupported in this phase (${resolved})`);
341
+ }
342
+ if (deckMeta.execute !== undefined) {
343
+ throw new Error(`Top-level execute in PROMPT.md is unsupported (${resolved})`);
344
+ }
243
345
  const hasNewActionDecks = deckMeta.actionDecks;
244
- const legacyDeckActions = deckMeta.actions;
245
- const actionDecks = normalizeActionDecks(hasNewActionDecks ?? legacyDeckActions, resolved);
246
- if (!hasNewActionDecks && legacyDeckActions) {
247
- logger.warn(`[gambit] deck at ${resolved} uses deprecated "actions"; rename to "actionDecks"`);
346
+ const canonicalActions = deckMeta.actions;
347
+ const actionDecks = await normalizeActionDecks(canonicalActions, resolved, {
348
+ requirePrompt: true,
349
+ requireDescription: true,
350
+ });
351
+ const legacyActionDecks = await normalizeActionDecks(hasNewActionDecks, resolved);
352
+ if (hasNewActionDecks) {
353
+ logger.warn(`[gambit] deck at ${resolved} uses deprecated "actionDecks"; use "[[actions]]" instead.`);
248
354
  }
249
- actionDecks.forEach((a) => {
355
+ if (deckMeta.testDecks) {
356
+ logger.warn(`[gambit] deck at ${resolved} uses deprecated "testDecks"; use "[[scenarios]]" instead.`);
357
+ }
358
+ if (deckMeta.graderDecks) {
359
+ logger.warn(`[gambit] deck at ${resolved} uses deprecated "graderDecks"; use "[[graders]]" instead.`);
360
+ }
361
+ const scenarioDecks = normalizeDeckRefs(deckMeta.scenarios, resolved, { requirePrompt: true });
362
+ const graderDecks = normalizeDeckRefs(deckMeta.graders, resolved, { requirePrompt: true });
363
+ const allActionDecks = [...actionDecks, ...legacyActionDecks];
364
+ allActionDecks.forEach((a) => {
250
365
  if (a.name.startsWith(RESERVED_TOOL_PREFIX) &&
251
366
  !BUILTIN_TOOL_NAME_SET.has(a.name)) {
252
367
  throw new Error(`Action name ${a.name} is reserved`);
@@ -284,7 +399,7 @@ export async function loadMarkdownDeck(filePath, parentPath) {
284
399
  mergedActions[action.name] = action;
285
400
  }
286
401
  }
287
- for (const action of actionDecks) {
402
+ for (const action of allActionDecks) {
288
403
  mergedActions[action.name] = action;
289
404
  }
290
405
  let mergedContextSchema = contextSchema;
@@ -327,10 +442,18 @@ export async function loadMarkdownDeck(filePath, parentPath) {
327
442
  }
328
443
  : undefined;
329
444
  const mergedActionDecks = Object.values(mergedActions);
445
+ const tools = await normalizeExternalTools(deckMeta.tools, resolved);
446
+ const actionNameSet = new Set(mergedActionDecks.map((action) => action.name));
447
+ for (const tool of tools) {
448
+ if (actionNameSet.has(tool.name)) {
449
+ logger.warn(`[gambit] tool ${tool.name} is shadowed by an action in ${resolved}`);
450
+ }
451
+ }
330
452
  const rootTestDecks = normalizeDeckRefs(deckMeta.testDecks, resolved);
331
453
  const rootGraderDecks = normalizeDeckRefs(deckMeta.graderDecks, resolved);
332
454
  const embeddedTestDecks = allCards.flatMap((card) => card.testDecks ?? []);
333
455
  const embeddedGraderDecks = allCards.flatMap((card) => card.graderDecks ?? []);
456
+ const permissions = normalizePermissionDeclaration(deckMeta.permissions, path.dirname(resolved));
334
457
  return {
335
458
  kind: "gambit.deck",
336
459
  path: resolved,
@@ -338,8 +461,9 @@ export async function loadMarkdownDeck(filePath, parentPath) {
338
461
  allowEnd,
339
462
  actionDecks: mergedActionDecks,
340
463
  actions: mergedActionDecks,
341
- testDecks: mergeDeckRefs(rootTestDecks, embeddedTestDecks),
342
- graderDecks: mergeDeckRefs(rootGraderDecks, embeddedGraderDecks),
464
+ tools,
465
+ testDecks: mergeDeckRefs(scenarioDecks, rootTestDecks, embeddedTestDecks),
466
+ graderDecks: mergeDeckRefs(graderDecks, rootGraderDecks, embeddedGraderDecks),
343
467
  cards: allCards,
344
468
  label: deckMeta.label,
345
469
  startMode: deckMeta.startMode,
@@ -349,11 +473,13 @@ export async function loadMarkdownDeck(filePath, parentPath) {
349
473
  responseSchema: mergedResponseSchema,
350
474
  inputSchema: mergedInputSchema,
351
475
  outputSchema: mergedOutputSchema,
476
+ executor: undefined,
352
477
  handlers,
353
478
  respond: Boolean(deckMeta.respond) ||
354
479
  replaced.respond ||
355
480
  allCards.some((c) => c.respond),
356
481
  inlineEmbeds: true,
482
+ permissions,
357
483
  };
358
484
  }
359
485
  export function isMarkdownFile(filePath) {