@apifuse/provider-sdk 2.2.0-beta.2 → 2.2.0-beta.20

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 (290) hide show
  1. package/AUTHORING.md +487 -0
  2. package/CHANGELOG.md +85 -0
  3. package/README.md +49 -3
  4. package/SUBMISSION.md +1 -1
  5. package/bin/apifuse-check.ts +44 -59
  6. package/bin/apifuse-create.ts +1 -1
  7. package/bin/apifuse-dev.ts +27 -52
  8. package/bin/apifuse-pack-check.ts +14 -0
  9. package/bin/apifuse-pack-smoke.ts +36 -81
  10. package/bin/apifuse-pack-types.ts +305 -0
  11. package/bin/apifuse-perf.ts +45 -127
  12. package/bin/apifuse-record.ts +659 -111
  13. package/bin/apifuse-submit-check.ts +546 -48
  14. package/bin/apifuse-sync-assets.ts +117 -0
  15. package/bin/apifuse.ts +1 -1
  16. package/bin/submit-check-delimited-text.ts +50 -0
  17. package/bin/submit-check-xml-semantics.ts +204 -0
  18. package/bin/submit-check-xml.ts +134 -0
  19. package/dist/auth-turn/index.d.ts +3 -3
  20. package/dist/auth.d.ts +2 -2
  21. package/dist/auth.js +9 -18
  22. package/dist/ceremonies/index.d.ts +1 -1
  23. package/dist/ceremonies/index.js +8 -18
  24. package/dist/cli/commands.d.ts +1 -1
  25. package/dist/cli/commands.js +8 -0
  26. package/dist/cli/create.d.ts +3 -0
  27. package/dist/cli/create.js +34 -35
  28. package/dist/cli/prompt-assets.d.ts +80 -0
  29. package/dist/cli/prompt-assets.js +743 -0
  30. package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
  31. package/dist/config/loader.d.ts +176 -8
  32. package/dist/config/loader.js +424 -95
  33. package/dist/contract-serialization.d.ts +2 -2
  34. package/dist/contract-serialization.js +3 -6
  35. package/dist/contract-types.d.ts +2 -2
  36. package/dist/contract.d.ts +3 -3
  37. package/dist/contract.js +4 -6
  38. package/dist/define.d.ts +9 -1
  39. package/dist/define.js +208 -125
  40. package/dist/dev.d.ts +1 -1
  41. package/dist/dev.js +1 -1
  42. package/dist/error-resolution.d.ts +2 -0
  43. package/dist/error-resolution.js +90 -0
  44. package/dist/errors.d.ts +22 -1
  45. package/dist/errors.js +88 -0
  46. package/dist/fixture-sanitization.d.ts +26 -0
  47. package/dist/fixture-sanitization.js +216 -0
  48. package/dist/i18n/catalog.d.ts +2 -2
  49. package/dist/i18n/catalog.js +4 -10
  50. package/dist/i18n/index.d.ts +2 -2
  51. package/dist/i18n/index.js +2 -2
  52. package/dist/i18n/keys.d.ts +2 -2
  53. package/dist/index.d.ts +46 -42
  54. package/dist/index.js +41 -37
  55. package/dist/lint.js +8 -15
  56. package/dist/native-address.d.ts +43 -0
  57. package/dist/native-address.js +281 -0
  58. package/dist/native-egress-policy.d.ts +31 -0
  59. package/dist/native-egress-policy.js +288 -0
  60. package/dist/observability.d.ts +5 -2
  61. package/dist/observability.js +48 -1
  62. package/dist/provider.d.ts +12 -11
  63. package/dist/provider.js +10 -9
  64. package/dist/public-schema-field-lint.d.ts +1 -1
  65. package/dist/recipes/gov-api.js +1 -1
  66. package/dist/runtime/auth-flow.d.ts +1 -1
  67. package/dist/runtime/auth-flow.js +3 -3
  68. package/dist/runtime/browser.d.ts +1 -1
  69. package/dist/runtime/browser.js +15 -29
  70. package/dist/runtime/cache.d.ts +1 -1
  71. package/dist/runtime/cache.js +4 -8
  72. package/dist/runtime/choice.d.ts +1 -1
  73. package/dist/runtime/choice.js +31 -35
  74. package/dist/runtime/credential.d.ts +1 -1
  75. package/dist/runtime/credential.js +1 -1
  76. package/dist/runtime/env.d.ts +1 -1
  77. package/dist/runtime/executor.d.ts +1 -1
  78. package/dist/runtime/executor.js +31 -4
  79. package/dist/runtime/http.d.ts +2 -2
  80. package/dist/runtime/http.js +387 -47
  81. package/dist/runtime/insights.d.ts +1 -1
  82. package/dist/runtime/insights.js +6 -13
  83. package/dist/runtime/instrumentation.d.ts +2 -2
  84. package/dist/runtime/instrumentation.js +345 -22
  85. package/dist/runtime/keyring.js +1 -1
  86. package/dist/runtime/namespace.js +1 -1
  87. package/dist/runtime/native-network.d.ts +127 -0
  88. package/dist/runtime/native-network.js +1298 -0
  89. package/dist/runtime/otlp.d.ts +1 -1
  90. package/dist/runtime/perf.d.ts +1 -1
  91. package/dist/runtime/provider.d.ts +1 -1
  92. package/dist/runtime/provider.js +1 -2
  93. package/dist/runtime/proxy-errors.d.ts +1 -1
  94. package/dist/runtime/proxy-errors.js +9 -7
  95. package/dist/runtime/proxy-nodemaven.d.ts +56 -0
  96. package/dist/runtime/proxy-nodemaven.js +146 -0
  97. package/dist/runtime/proxy-retry-policy.d.ts +2 -2
  98. package/dist/runtime/proxy-retry-policy.js +2 -2
  99. package/dist/runtime/proxy-telemetry.d.ts +2 -1
  100. package/dist/runtime/proxy-telemetry.js +55 -52
  101. package/dist/runtime/redirects.d.ts +29 -0
  102. package/dist/runtime/redirects.js +36 -0
  103. package/dist/runtime/redis.d.ts +1 -1
  104. package/dist/runtime/redis.js +2 -4
  105. package/dist/runtime/request-options.d.ts +68 -1
  106. package/dist/runtime/request-options.js +548 -0
  107. package/dist/runtime/secrets.d.ts +27 -0
  108. package/dist/runtime/secrets.js +51 -0
  109. package/dist/runtime/state.d.ts +2 -2
  110. package/dist/runtime/state.js +15 -4
  111. package/dist/runtime/stealth.d.ts +5 -3
  112. package/dist/runtime/stealth.js +423 -143
  113. package/dist/runtime/stt.d.ts +1 -1
  114. package/dist/runtime/stt.js +11 -15
  115. package/dist/runtime/trace.d.ts +2 -2
  116. package/dist/runtime/trace.js +2 -4
  117. package/dist/runtime/waterfall.d.ts +1 -1
  118. package/dist/schema.d.ts +1 -1
  119. package/dist/schema.js +7 -15
  120. package/dist/serve.d.ts +1 -1
  121. package/dist/serve.js +1 -1
  122. package/dist/server/index.d.ts +7 -7
  123. package/dist/server/index.js +6 -6
  124. package/dist/server/self-test-input-tokens.d.ts +2 -1
  125. package/dist/server/self-test-input-tokens.js +18 -14
  126. package/dist/server/self-test-redaction.d.ts +1 -1
  127. package/dist/server/self-test-redaction.js +1 -1
  128. package/dist/server/self-test.d.ts +104 -3
  129. package/dist/server/self-test.js +673 -115
  130. package/dist/server/serve.d.ts +115 -4
  131. package/dist/server/serve.js +792 -127
  132. package/dist/server/types.d.ts +30 -9
  133. package/dist/server/types.js +8 -7
  134. package/dist/stateful/errors.d.ts +14 -0
  135. package/dist/stateful/errors.js +14 -0
  136. package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
  137. package/dist/stateful/http-provider-event-emitter.js +237 -0
  138. package/dist/stateful/http-session-owner-registry.d.ts +44 -0
  139. package/dist/stateful/http-session-owner-registry.js +210 -0
  140. package/dist/stateful/index.d.ts +18 -0
  141. package/dist/stateful/index.js +18 -0
  142. package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
  143. package/dist/stateful/provider-event-delivery-failures.js +43 -0
  144. package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
  145. package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
  146. package/dist/stateful/provider-event-pipeline.d.ts +50 -0
  147. package/dist/stateful/provider-event-pipeline.js +1 -0
  148. package/dist/stateful/provider-events.d.ts +101 -0
  149. package/dist/stateful/provider-events.js +289 -0
  150. package/dist/stateful/session-key.d.ts +15 -0
  151. package/dist/stateful/session-key.js +86 -0
  152. package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
  153. package/dist/stateful/stateful-provider-adapter-context.js +42 -0
  154. package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
  155. package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
  156. package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
  157. package/dist/stateful/stateful-provider-adapter.js +287 -0
  158. package/dist/stateful/stateful-provider-observability.d.ts +62 -0
  159. package/dist/stateful/stateful-provider-observability.js +161 -0
  160. package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
  161. package/dist/stateful/stateful-provider-owner-forwarder.js +215 -0
  162. package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
  163. package/dist/stateful/stateful-provider-runtime-context.js +60 -0
  164. package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
  165. package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
  166. package/dist/stateful/stateful-provider-session-routing.d.ts +71 -0
  167. package/dist/stateful/stateful-provider-session-routing.js +353 -0
  168. package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
  169. package/dist/stateful/stateful-provider-session-runtime.js +245 -0
  170. package/dist/stateful-signing.d.ts +18 -0
  171. package/dist/stateful-signing.js +27 -0
  172. package/dist/stealth/profiles.d.ts +1 -1
  173. package/dist/stealth/profiles.js +5 -14
  174. package/dist/stream-evidence.d.ts +74 -0
  175. package/dist/stream-evidence.js +785 -0
  176. package/dist/stream.d.ts +1 -1
  177. package/dist/testing/index.d.ts +2 -2
  178. package/dist/testing/index.js +2 -2
  179. package/dist/testing/run.d.ts +32 -2
  180. package/dist/testing/run.js +477 -33
  181. package/dist/types.d.ts +323 -11
  182. package/dist/types.js +1 -0
  183. package/dist/user-input.d.ts +30 -0
  184. package/dist/user-input.js +66 -0
  185. package/package.json +16 -5
  186. package/src/auth-turn/index.ts +1 -1
  187. package/src/auth.ts +28 -86
  188. package/src/ceremonies/index.ts +24 -78
  189. package/src/cli/commands.ts +10 -0
  190. package/src/cli/create.ts +42 -35
  191. package/src/cli/prompt-assets.ts +865 -0
  192. package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
  193. package/src/config/loader.ts +652 -204
  194. package/src/contract-serialization.ts +5 -11
  195. package/src/contract-types.ts +2 -2
  196. package/src/contract.ts +12 -28
  197. package/src/define.ts +368 -504
  198. package/src/dev.ts +4 -9
  199. package/src/error-resolution.ts +91 -0
  200. package/src/errors.ts +110 -5
  201. package/src/fixture-sanitization.ts +247 -0
  202. package/src/i18n/catalog.ts +10 -32
  203. package/src/i18n/index.ts +2 -2
  204. package/src/i18n/keys.ts +5 -11
  205. package/src/index.ts +111 -42
  206. package/src/lint.ts +89 -159
  207. package/src/native-address.ts +340 -0
  208. package/src/native-egress-policy.ts +358 -0
  209. package/src/observability.ts +51 -1
  210. package/src/provider.ts +65 -11
  211. package/src/public-schema-field-lint.ts +7 -33
  212. package/src/recipes/gov-api.ts +2 -5
  213. package/src/runtime/auth-flow.ts +5 -7
  214. package/src/runtime/browser.ts +64 -187
  215. package/src/runtime/cache.ts +20 -67
  216. package/src/runtime/choice.ts +79 -132
  217. package/src/runtime/credential.ts +2 -2
  218. package/src/runtime/env.ts +1 -1
  219. package/src/runtime/executor.ts +43 -20
  220. package/src/runtime/http.ts +494 -57
  221. package/src/runtime/insights.ts +15 -53
  222. package/src/runtime/instrumentation.ts +495 -66
  223. package/src/runtime/keyring.ts +7 -19
  224. package/src/runtime/namespace.ts +2 -7
  225. package/src/runtime/native-network.ts +1686 -0
  226. package/src/runtime/otlp.ts +12 -23
  227. package/src/runtime/perf.ts +1 -1
  228. package/src/runtime/provider.ts +4 -9
  229. package/src/runtime/proxy-errors.ts +29 -42
  230. package/src/runtime/proxy-nodemaven.ts +221 -0
  231. package/src/runtime/proxy-retry-policy.ts +3 -3
  232. package/src/runtime/proxy-telemetry.ts +79 -77
  233. package/src/runtime/redirects.ts +66 -0
  234. package/src/runtime/redis.ts +4 -12
  235. package/src/runtime/request-options.ts +679 -9
  236. package/src/runtime/secrets.ts +64 -0
  237. package/src/runtime/state.ts +41 -110
  238. package/src/runtime/stealth.ts +505 -154
  239. package/src/runtime/stt.ts +38 -94
  240. package/src/runtime/trace.ts +14 -44
  241. package/src/runtime/waterfall.ts +5 -18
  242. package/src/schema.ts +23 -84
  243. package/src/serve.ts +1 -1
  244. package/src/server/index.ts +29 -7
  245. package/src/server/self-test-input-tokens.ts +29 -14
  246. package/src/server/self-test-redaction.ts +2 -2
  247. package/src/server/self-test.ts +857 -132
  248. package/src/server/serve.ts +1141 -324
  249. package/src/server/types.ts +12 -19
  250. package/src/stateful/README.md +146 -0
  251. package/src/stateful/errors.ts +23 -0
  252. package/src/stateful/http-provider-event-emitter.ts +314 -0
  253. package/src/stateful/http-session-owner-registry.ts +306 -0
  254. package/src/stateful/index.ts +18 -0
  255. package/src/stateful/provider-event-delivery-failures.ts +80 -0
  256. package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
  257. package/src/stateful/provider-event-pipeline.ts +61 -0
  258. package/src/stateful/provider-events.ts +462 -0
  259. package/src/stateful/session-key.ts +111 -0
  260. package/src/stateful/stateful-provider-adapter-context.ts +59 -0
  261. package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
  262. package/src/stateful/stateful-provider-adapter.ts +562 -0
  263. package/src/stateful/stateful-provider-observability.ts +261 -0
  264. package/src/stateful/stateful-provider-owner-forwarder.ts +287 -0
  265. package/src/stateful/stateful-provider-runtime-context.ts +92 -0
  266. package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
  267. package/src/stateful/stateful-provider-session-routing.ts +555 -0
  268. package/src/stateful/stateful-provider-session-runtime.ts +403 -0
  269. package/src/stateful-signing.ts +46 -0
  270. package/src/stealth/profiles.ts +10 -26
  271. package/src/stream-evidence.ts +988 -0
  272. package/src/stream.ts +8 -19
  273. package/src/testing/index.ts +10 -2
  274. package/src/testing/run.ts +652 -79
  275. package/src/types.ts +369 -11
  276. package/src/user-input.ts +118 -0
  277. package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
  278. package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
  279. /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  280. /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  281. /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  282. /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  283. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  284. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
  285. /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  286. /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  287. /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  288. /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  289. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  290. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomBytes, randomUUID } from "node:crypto";
2
2
  import Ajv2020 from "ajv/dist/2020.js";
3
- import { AUTH_TURN_SCHEMA } from "../auth-turn";
4
- import { FlowExpiredError, ProviderSecretError, TurnValidationError, ValidationError, } from "../errors";
3
+ import { AUTH_TURN_SCHEMA } from "../auth-turn/index.js";
4
+ import { FlowExpiredError, ProviderSecretError, TurnValidationError, ValidationError, } from "../errors.js";
5
5
  const ajv = new Ajv2020({ allErrors: true, strict: true, strictSchema: true });
6
6
  // Runtime ceremony-output validation derives from the exported versioned
7
7
  // contract: it compiles the exact AUTH_TURN_SCHEMA document shipped at
@@ -38,11 +38,7 @@ function getRequiredEnv(ctx, key) {
38
38
  return value;
39
39
  }
40
40
  function toBase64Url(input) {
41
- return input
42
- .toString("base64")
43
- .replace(/\+/g, "-")
44
- .replace(/\//g, "_")
45
- .replace(/=+$/g, "");
41
+ return input.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
46
42
  }
47
43
  function createCodeVerifier() {
48
44
  return toBase64Url(randomBytes(32));
@@ -100,8 +96,7 @@ function withDeclaredFormFieldOrder(expectedInput) {
100
96
  return expectedInput;
101
97
  }
102
98
  const existingOrder = expectedInput[FORM_FIELD_ORDER_EXTENSION];
103
- if (Array.isArray(existingOrder) &&
104
- existingOrder.every((value) => typeof value === "string")) {
99
+ if (Array.isArray(existingOrder) && existingOrder.every((value) => typeof value === "string")) {
105
100
  return expectedInput;
106
101
  }
107
102
  return {
@@ -218,8 +213,7 @@ export function createDeviceFlowCeremony(options) {
218
213
  });
219
214
  const data = ensureRecord(response.data);
220
215
  const errorCode = getString(data, "error");
221
- if (errorCode === "authorization_pending" ||
222
- errorCode === "slow_down") {
216
+ if (errorCode === "authorization_pending" || errorCode === "slow_down") {
223
217
  return createTurn("poll", {
224
218
  data,
225
219
  hint: "Authorization pending.",
@@ -345,7 +339,7 @@ export function createFormCeremony(options) {
345
339
  return {
346
340
  start: async () => validateCeremonyOutput(buildJsonSchemaForm(options.schema, options.hint ?? "Provide the required input to continue.")),
347
341
  continue: (ctx, input = {}) => runCeremonyHandler(async () => {
348
- const { prevalidate } = await import("../runtime/prevalidate");
342
+ const { prevalidate } = await import("../runtime/prevalidate.js");
349
343
  const result = prevalidate(options.schema, input);
350
344
  if (!result.valid) {
351
345
  throw new ValidationError("Form input failed validation.", {
@@ -354,9 +348,7 @@ export function createFormCeremony(options) {
354
348
  }
355
349
  return createTurn("complete", {
356
350
  data: {
357
- credential: options.mapCredential
358
- ? options.mapCredential(input)
359
- : input,
351
+ credential: options.mapCredential ? options.mapCredential(input) : input,
360
352
  },
361
353
  hint: "Form completed.",
362
354
  });
@@ -428,9 +420,7 @@ export function createSwitchCeremony(options) {
428
420
  })),
429
421
  continue: (ctx, input = {}) => runCeremonyHandler(async () => {
430
422
  const storedChoice = ctx.context.get(SWITCH_SELECTION_KEY);
431
- const choice = typeof storedChoice === "string"
432
- ? storedChoice
433
- : getString(input, "choice");
423
+ const choice = typeof storedChoice === "string" ? storedChoice : getString(input, "choice");
434
424
  if (!choice || !options.choices[choice]) {
435
425
  throw new ValidationError("A valid choice is required.");
436
426
  }
@@ -1,4 +1,4 @@
1
- export type ApifuseCommandName = "create" | "dev" | "check" | "submit-check" | "bounty-check" | "record" | "test" | "perf";
1
+ export type ApifuseCommandName = "create" | "dev" | "check" | "sync-assets" | "submit-check" | "bounty-check" | "record" | "test" | "perf";
2
2
  export type ApifuseCommandManifest = {
3
3
  name: ApifuseCommandName;
4
4
  summary: string;
@@ -23,6 +23,13 @@ export const COMMAND_MANIFEST = {
23
23
  examples: ["apifuse check .", "apifuse check providers/korea-air-quality"],
24
24
  modulePath: "./apifuse-check",
25
25
  },
26
+ "sync-assets": {
27
+ name: "sync-assets",
28
+ summary: "Regenerate SDK-managed agent prompt assets (AGENTS.md, .agents/skills, symlinks, manifest) for the installed SDK version.",
29
+ usage: "apifuse sync-assets [path] [--check]",
30
+ examples: ["apifuse sync-assets .", "apifuse sync-assets . --check"],
31
+ modulePath: "./apifuse-sync-assets",
32
+ },
26
33
  "submit-check": {
27
34
  name: "submit-check",
28
35
  summary: "Score provider bounty submission readiness and emit checklist evidence.",
@@ -73,6 +80,7 @@ export const COMMAND_ORDER = [
73
80
  "create",
74
81
  "dev",
75
82
  "check",
83
+ "sync-assets",
76
84
  "submit-check",
77
85
  "record",
78
86
  "test",
@@ -26,7 +26,10 @@ export type CreateResolvedOptions = {
26
26
  };
27
27
  export type ProviderPlanFile = {
28
28
  path: string;
29
+ /** File content, or the symlink target (relative path) for kind "symlink". */
29
30
  content: string;
31
+ /** Absent kind means "file" (backward compatible with older consumers). */
32
+ kind?: "file" | "symlink";
30
33
  };
31
34
  export type ProviderCreatePlan = {
32
35
  displayName: string;
@@ -1,11 +1,12 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
- import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { mkdir, readFile, rm, symlink, writeFile } from "node:fs/promises";
4
4
  import { dirname, relative, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { cancel, intro, isCancel, note, outro, select, text } from "@clack/prompts";
7
7
  import { z } from "zod";
8
8
  import packageJson from "../../package.json";
9
+ import { buildPromptAssetManifest, buildPromptAssetPlanEntries, PROMPT_ASSET_MANIFEST_PATH, } from "./prompt-assets.js";
9
10
  export const PROVIDER_NAME_REGEX = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
10
11
  export const CATEGORY_OPTIONS = [
11
12
  "developer-tools",
@@ -283,10 +284,15 @@ export async function buildProviderCreatePlan(options, cwd) {
283
284
  if (options.sdkSpecifier?.startsWith("workspace:") && !resolvedWorkspaceRoot) {
284
285
  throw new Error("workspace:* is only valid inside the APIFuse monorepo because public Provider SDK scaffolds must install from npm or an explicit tarball/file specifier.");
285
286
  }
287
+ // Exact pin, not a caret range: the prompt-asset freshness gate requires
288
+ // manifest.sdkVersion === installed SDK version, and the manifest records
289
+ // this CLI's own version. A caret range would let `bun install` resolve a
290
+ // newer SDK than the create binary, making a fresh scaffold fail its own
291
+ // gate. `sync-assets` after an explicit SDK upgrade re-records the version.
286
292
  const sdkSpecifier = options.sdkSpecifier ??
287
293
  (options.preset === "monorepo" && resolvedWorkspaceRoot
288
294
  ? "workspace:*"
289
- : `^${packageJson.version}`);
295
+ : packageJson.version);
290
296
  const relativeProviderRoot = relative(cwd, providerRoot) || options.name;
291
297
  const nextDevCommand = `cd ${relativeProviderRoot} && bun run dev`;
292
298
  const packageName = options.preset === "monorepo"
@@ -405,39 +411,21 @@ export async function buildProviderCreatePlan(options, cwd) {
405
411
  PROVIDER_ID: options.name,
406
412
  }),
407
413
  },
408
- {
409
- path: resolve(providerRoot, "AGENTS.md"),
410
- content: await renderTemplate("AGENTS.md.tpl", {}),
411
- },
412
- {
413
- path: resolve(providerRoot, "CLAUDE.md"),
414
- content: await renderTemplate("CLAUDE.md.tpl", {}),
415
- },
416
- {
417
- path: resolve(providerRoot, "skills", "normalization-standards", "SKILL.md"),
418
- content: await renderTemplate("skills/normalization-standards/SKILL.md.tpl", {}),
419
- },
420
- {
421
- path: resolve(providerRoot, "skills", "upstream-contract-verification", "SKILL.md"),
422
- content: await renderTemplate("skills/upstream-contract-verification/SKILL.md.tpl", {}),
423
- },
424
- {
425
- path: resolve(providerRoot, "skills", "fixtures-and-recording", "SKILL.md"),
426
- content: await renderTemplate("skills/fixtures-and-recording/SKILL.md.tpl", {}),
427
- },
428
- {
429
- path: resolve(providerRoot, "skills", "pagination-and-counts", "SKILL.md"),
430
- content: await renderTemplate("skills/pagination-and-counts/SKILL.md.tpl", {}),
431
- },
432
- {
433
- path: resolve(providerRoot, "skills", "health-checks-and-fail-closed", "SKILL.md"),
434
- content: await renderTemplate("skills/health-checks-and-fail-closed/SKILL.md.tpl", {}),
435
- },
436
- {
437
- path: resolve(providerRoot, "skills", "upstream-notes", "README.md"),
438
- content: await renderTemplate("skills/upstream-notes/README.md.tpl", {}),
439
- },
440
414
  ];
415
+ const promptAssetEntries = await buildPromptAssetPlanEntries(renderTemplate);
416
+ for (const entry of promptAssetEntries) {
417
+ files.push({
418
+ path: resolve(providerRoot, entry.path),
419
+ content: entry.content,
420
+ ...(entry.kind === "symlink" ? { kind: "symlink" } : {}),
421
+ });
422
+ }
423
+ // Manifest last: writePlan writes in order, so a crash mid-scaffold never
424
+ // leaves a manifest that claims assets which were not written.
425
+ files.push({
426
+ path: resolve(providerRoot, PROMPT_ASSET_MANIFEST_PATH),
427
+ content: buildPromptAssetManifest(promptAssetEntries, packageJson.version),
428
+ });
441
429
  return {
442
430
  displayName: options.displayName,
443
431
  files,
@@ -477,6 +465,7 @@ function renderPackageJson(input) {
477
465
  check: "apifuse check . && bun run type-check",
478
466
  "type-check": "tsc --noEmit",
479
467
  "submit-check": "apifuse submit-check . --markdown submission-report.md",
468
+ "sync-assets": "apifuse sync-assets .",
480
469
  test: "apifuse test .",
481
470
  record: "apifuse record .",
482
471
  start: "bun start.ts",
@@ -696,6 +685,13 @@ function isApifuseInternalWorkspaceRoot(workspaceRoot) {
696
685
  async function writePlan(plan) {
697
686
  for (const file of plan.files) {
698
687
  await mkdir(dirname(file.path), { recursive: true });
688
+ if (file.kind === "symlink") {
689
+ // rm operates on the link itself (lstat semantics) and tolerates
690
+ // directories, so whatever occupies the path is replaced by the link.
691
+ await rm(file.path, { recursive: true, force: true });
692
+ await symlink(file.content, file.path);
693
+ continue;
694
+ }
699
695
  await writeFile(file.path, file.content);
700
696
  }
701
697
  }
@@ -754,7 +750,10 @@ function printResult(plan, jsonMode, dryRun) {
754
750
  },
755
751
  validationCommands: plan.validationCommands,
756
752
  nextDevCommand: plan.nextDevCommand,
757
- files: plan.files.map((file) => relative(plan.providerRoot, file.path) || file.path),
753
+ files: plan.files.map((file) => {
754
+ const relativePath = relative(plan.providerRoot, file.path) || file.path;
755
+ return file.kind === "symlink" ? `${relativePath} -> ${file.content} (symlink)` : relativePath;
756
+ }),
758
757
  };
759
758
  if (jsonMode) {
760
759
  console.log(JSON.stringify(payload, null, 2));
@@ -0,0 +1,80 @@
1
+ /**
2
+ * SDK-managed agent prompt assets.
3
+ *
4
+ * `apifuse create` scaffolds these files, `apifuse sync-assets` regenerates
5
+ * them in an existing provider root, and `apifuse check` / `submit-check`
6
+ * enforce that they byte-match the installed SDK version (fail closed).
7
+ *
8
+ * Layout contract:
9
+ * - AGENTS.md — real file (agent guide)
10
+ * - CLAUDE.md — symlink -> AGENTS.md
11
+ * - .agents/skills/<skill>/SKILL.md — real files
12
+ * - .agents/skills/upstream-notes/README.md — real file
13
+ * - .claude / .codex — symlinks -> .agents
14
+ * - .apifuse/prompt-assets.json — manifest (schema v2), written last
15
+ */
16
+ export declare const PROMPT_ASSET_MANIFEST_PATH = ".apifuse/prompt-assets.json";
17
+ export declare const PROMPT_ASSET_MANIFEST_SCHEMA_VERSION = 2;
18
+ export declare const PROMPT_ASSET_SYNC_REMEDIATION = "Run `bun run sync-assets` (or `bunx apifuse sync-assets .`) to regenerate the SDK-managed agent prompt assets.";
19
+ export declare const PROMPT_ASSET_SYMLINKS: Readonly<Record<string, string>>;
20
+ /** Relative asset paths whose content is rendered from `<path>.tpl`. */
21
+ export declare const PROMPT_ASSET_FILE_PATHS: readonly string[];
22
+ export type PromptAssetKind = "file" | "symlink";
23
+ export type PromptAssetEntry = {
24
+ /** Provider-root-relative path (POSIX separators). */
25
+ path: string;
26
+ /** File content, or the symlink target for kind "symlink". */
27
+ content: string;
28
+ kind: PromptAssetKind;
29
+ };
30
+ export type PromptAssetTemplateRenderer = (fileName: string, values: Record<string, string>) => string | Promise<string>;
31
+ export type PromptAssetVerification = {
32
+ ok: boolean;
33
+ /** Expected paths (or the manifest) absent on disk. */
34
+ missing: string[];
35
+ /** Manifest recorded for a different SDK version than the installed one. */
36
+ stale: string[];
37
+ /** Files/symlinks/manifest whose bytes or target differ from the regenerated set. */
38
+ modified: string[];
39
+ /** Legacy layout remnants (top-level skills/). */
40
+ legacy: string[];
41
+ /** Entries inside `.agents/` that are not part of the managed asset set. */
42
+ unexpected: string[];
43
+ };
44
+ export type PromptAssetSyncResult = {
45
+ changed: boolean;
46
+ removed: string[];
47
+ wroteFiles: string[];
48
+ createdSymlinks: string[];
49
+ manifestPath: string;
50
+ };
51
+ /**
52
+ * Build the full managed asset entry list (files first, symlinks after,
53
+ * manifest excluded). The renderer is injected so `apifuse create` can reuse
54
+ * its own template renderer; sync/verify use the SDK-internal renderer.
55
+ */
56
+ export declare function buildPromptAssetPlanEntries(renderTemplate: PromptAssetTemplateRenderer): Promise<PromptAssetEntry[]>;
57
+ export declare function buildPromptAssetPlanEntriesSync(): PromptAssetEntry[];
58
+ /**
59
+ * Deterministic manifest serialization: schema v2, 2-space JSON, trailing
60
+ * newline, sorted paths (including symlink paths, excluding the manifest
61
+ * itself). `sdkVersion` + `paths` keep their v1 semantics so older parsers
62
+ * keep working; `schemaVersion` and `symlinks` are additive.
63
+ */
64
+ export declare function buildPromptAssetManifest(entries: readonly PromptAssetEntry[], sdkVersion: string): string;
65
+ export declare function installedSdkVersion(): string;
66
+ /**
67
+ * Verify the on-disk prompt assets against the set regenerated from the
68
+ * installed SDK. Uses lstat/readlink for symlinks (never follows), byte
69
+ * comparison for files, and exact-version comparison for the manifest.
70
+ */
71
+ export declare function verifyPromptAssets(providerRoot: string): PromptAssetVerification;
72
+ export declare function formatPromptAssetIssues(verification: PromptAssetVerification): string[];
73
+ /**
74
+ * Regenerate the full managed asset set for the installed SDK version in an
75
+ * existing provider root. Deletes legacy managed paths first (top-level
76
+ * skills/**, plus manifest-listed paths that left the set — restricted to
77
+ * managed namespaces with no symlinked ancestors), writes files, replaces
78
+ * symlinks, and writes the manifest last. Idempotent.
79
+ */
80
+ export declare function syncPromptAssets(providerRoot: string): PromptAssetSyncResult;