@apifuse/provider-sdk 2.1.0-beta.9 → 2.2.0-beta.10

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 (263) hide show
  1. package/AUTHORING.md +240 -0
  2. package/CHANGELOG.md +93 -0
  3. package/README.md +26 -10
  4. package/SUBMISSION.md +11 -12
  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 +36 -0
  9. package/bin/apifuse-pack-smoke.ts +22 -81
  10. package/bin/apifuse-pack-types.ts +266 -0
  11. package/bin/apifuse-perf.ts +45 -127
  12. package/bin/apifuse-record.ts +53 -70
  13. package/bin/apifuse-submit-check.ts +2177 -353
  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/auth-turn.v1.schema.json +89 -0
  20. package/dist/auth-turn/fixtures/invalid/empty-kind.json +4 -0
  21. package/dist/auth-turn/fixtures/invalid/expires-at-not-string.json +5 -0
  22. package/dist/auth-turn/fixtures/invalid/missing-kind.json +3 -0
  23. package/dist/auth-turn/fixtures/invalid/missing-turn-id.json +3 -0
  24. package/dist/auth-turn/fixtures/invalid/timing-unknown-field.json +7 -0
  25. package/dist/auth-turn/fixtures/invalid/turn-id-snake-case.json +4 -0
  26. package/dist/auth-turn/fixtures/invalid/unknown-top-level-field.json +5 -0
  27. package/dist/auth-turn/fixtures/valid/abort.json +8 -0
  28. package/dist/auth-turn/fixtures/valid/challenge.json +17 -0
  29. package/dist/auth-turn/fixtures/valid/complete.json +13 -0
  30. package/dist/auth-turn/fixtures/valid/form.json +14 -0
  31. package/dist/auth-turn/fixtures/valid/message.json +13 -0
  32. package/dist/auth-turn/fixtures/valid/multi_choice.json +15 -0
  33. package/dist/auth-turn/fixtures/valid/pending.json +5 -0
  34. package/dist/auth-turn/fixtures/valid/poll.json +9 -0
  35. package/dist/auth-turn/fixtures/valid/redirect.json +16 -0
  36. package/dist/auth-turn/fixtures/valid/retry.json +8 -0
  37. package/dist/auth-turn/fixtures/valid/unknown-kind.json +7 -0
  38. package/dist/auth-turn/index.d.ts +195 -0
  39. package/dist/auth-turn/index.js +133 -0
  40. package/dist/auth.d.ts +76 -0
  41. package/dist/auth.js +427 -0
  42. package/dist/ceremonies/index.d.ts +1 -1
  43. package/dist/ceremonies/index.js +14 -48
  44. package/dist/cli/commands.d.ts +1 -1
  45. package/dist/cli/commands.js +8 -0
  46. package/dist/cli/create.d.ts +3 -0
  47. package/dist/cli/create.js +47 -33
  48. package/dist/cli/prompt-assets.d.ts +80 -0
  49. package/dist/cli/prompt-assets.js +743 -0
  50. package/dist/cli/templates/provider/.agents/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  51. package/dist/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  52. package/dist/cli/templates/provider/.agents/skills/normalization-standards/SKILL.md.tpl +57 -0
  53. package/dist/cli/templates/provider/.agents/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  54. package/dist/cli/templates/provider/.agents/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  55. package/dist/cli/templates/provider/.agents/skills/upstream-notes/README.md.tpl +13 -0
  56. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  57. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  58. package/dist/cli/templates/provider/AGENTS.md.tpl +96 -0
  59. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  60. package/dist/cli/templates/provider/README.md.tpl +163 -0
  61. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  62. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  63. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  64. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  65. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  66. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  67. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  68. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  69. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  70. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  71. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  72. package/dist/config/loader.d.ts +149 -8
  73. package/dist/config/loader.js +378 -89
  74. package/dist/contract-serialization.d.ts +2 -2
  75. package/dist/contract-serialization.js +3 -6
  76. package/dist/contract-types.d.ts +2 -2
  77. package/dist/contract.d.ts +3 -3
  78. package/dist/contract.js +5 -6
  79. package/dist/define.d.ts +13 -1
  80. package/dist/define.js +245 -178
  81. package/dist/dev.d.ts +1 -1
  82. package/dist/dev.js +1 -1
  83. package/dist/errors.d.ts +4 -1
  84. package/dist/errors.js +48 -0
  85. package/dist/i18n/catalog.d.ts +2 -2
  86. package/dist/i18n/catalog.js +4 -10
  87. package/dist/i18n/index.d.ts +2 -2
  88. package/dist/i18n/index.js +2 -2
  89. package/dist/i18n/keys.d.ts +2 -2
  90. package/dist/index.d.ts +44 -41
  91. package/dist/index.js +39 -36
  92. package/dist/lint.d.ts +1 -0
  93. package/dist/lint.js +35 -15
  94. package/dist/provider.d.ts +11 -9
  95. package/dist/provider.js +9 -8
  96. package/dist/public-schema-field-lint.d.ts +1 -1
  97. package/dist/recipes/gov-api.js +1 -1
  98. package/dist/runtime/auth-flow.d.ts +1 -1
  99. package/dist/runtime/auth-flow.js +4 -2
  100. package/dist/runtime/browser.d.ts +1 -1
  101. package/dist/runtime/browser.js +214 -25
  102. package/dist/runtime/cache.d.ts +1 -1
  103. package/dist/runtime/cache.js +4 -8
  104. package/dist/runtime/choice.d.ts +1 -1
  105. package/dist/runtime/choice.js +31 -35
  106. package/dist/runtime/credential.d.ts +1 -1
  107. package/dist/runtime/credential.js +1 -1
  108. package/dist/runtime/env.d.ts +1 -1
  109. package/dist/runtime/executor.d.ts +1 -1
  110. package/dist/runtime/executor.js +15 -3
  111. package/dist/runtime/http.d.ts +2 -2
  112. package/dist/runtime/http.js +160 -344
  113. package/dist/runtime/insights.d.ts +1 -1
  114. package/dist/runtime/insights.js +6 -13
  115. package/dist/runtime/instrumentation.d.ts +2 -2
  116. package/dist/runtime/instrumentation.js +56 -19
  117. package/dist/runtime/keyring.js +1 -1
  118. package/dist/runtime/namespace.js +1 -1
  119. package/dist/runtime/otlp.d.ts +1 -1
  120. package/dist/runtime/perf.d.ts +1 -1
  121. package/dist/runtime/provider.d.ts +1 -1
  122. package/dist/runtime/provider.js +1 -2
  123. package/dist/runtime/proxy-errors.d.ts +1 -1
  124. package/dist/runtime/proxy-errors.js +9 -7
  125. package/dist/runtime/proxy-nodemaven.d.ts +35 -0
  126. package/dist/runtime/proxy-nodemaven.js +128 -0
  127. package/dist/runtime/proxy-retry-policy.d.ts +40 -0
  128. package/dist/runtime/proxy-retry-policy.js +326 -0
  129. package/dist/runtime/proxy-telemetry.d.ts +2 -1
  130. package/dist/runtime/proxy-telemetry.js +55 -52
  131. package/dist/runtime/redis.d.ts +1 -1
  132. package/dist/runtime/redis.js +2 -4
  133. package/dist/runtime/request-options.d.ts +1 -1
  134. package/dist/runtime/secrets.d.ts +27 -0
  135. package/dist/runtime/secrets.js +51 -0
  136. package/dist/runtime/state.d.ts +2 -2
  137. package/dist/runtime/state.js +15 -4
  138. package/dist/runtime/stealth.d.ts +7 -4
  139. package/dist/runtime/stealth.js +257 -215
  140. package/dist/runtime/stt.d.ts +1 -1
  141. package/dist/runtime/stt.js +11 -15
  142. package/dist/runtime/trace.d.ts +2 -2
  143. package/dist/runtime/trace.js +2 -4
  144. package/dist/runtime/waterfall.d.ts +1 -1
  145. package/dist/schema.d.ts +1 -1
  146. package/dist/schema.js +7 -15
  147. package/dist/serve.d.ts +1 -1
  148. package/dist/serve.js +1 -1
  149. package/dist/server/index.d.ts +7 -3
  150. package/dist/server/index.js +6 -2
  151. package/dist/server/self-test-input-tokens.d.ts +1 -0
  152. package/dist/server/self-test-input-tokens.js +37 -0
  153. package/dist/server/self-test-redaction.d.ts +20 -0
  154. package/dist/server/self-test-redaction.js +70 -0
  155. package/dist/server/self-test-token.d.ts +30 -0
  156. package/dist/server/self-test-token.js +50 -0
  157. package/dist/server/self-test.d.ts +199 -0
  158. package/dist/server/self-test.js +1113 -0
  159. package/dist/server/serve.d.ts +14 -3
  160. package/dist/server/serve.js +135 -64
  161. package/dist/server/types.d.ts +10 -9
  162. package/dist/server/types.js +3 -7
  163. package/dist/stealth/profiles.d.ts +1 -1
  164. package/dist/stealth/profiles.js +5 -14
  165. package/dist/stream.d.ts +1 -1
  166. package/dist/testing/index.d.ts +2 -2
  167. package/dist/testing/index.js +2 -2
  168. package/dist/testing/run.d.ts +1 -1
  169. package/dist/testing/run.js +12 -15
  170. package/dist/types.d.ts +237 -1
  171. package/dist/user-input.d.ts +30 -0
  172. package/dist/user-input.js +66 -0
  173. package/package.json +16 -5
  174. package/src/auth-turn/auth-turn.v1.schema.json +89 -0
  175. package/src/auth-turn/fixtures/invalid/empty-kind.json +4 -0
  176. package/src/auth-turn/fixtures/invalid/expires-at-not-string.json +5 -0
  177. package/src/auth-turn/fixtures/invalid/missing-kind.json +3 -0
  178. package/src/auth-turn/fixtures/invalid/missing-turn-id.json +3 -0
  179. package/src/auth-turn/fixtures/invalid/timing-unknown-field.json +7 -0
  180. package/src/auth-turn/fixtures/invalid/turn-id-snake-case.json +4 -0
  181. package/src/auth-turn/fixtures/invalid/unknown-top-level-field.json +5 -0
  182. package/src/auth-turn/fixtures/valid/abort.json +8 -0
  183. package/src/auth-turn/fixtures/valid/challenge.json +17 -0
  184. package/src/auth-turn/fixtures/valid/complete.json +13 -0
  185. package/src/auth-turn/fixtures/valid/form.json +14 -0
  186. package/src/auth-turn/fixtures/valid/message.json +13 -0
  187. package/src/auth-turn/fixtures/valid/multi_choice.json +15 -0
  188. package/src/auth-turn/fixtures/valid/pending.json +5 -0
  189. package/src/auth-turn/fixtures/valid/poll.json +9 -0
  190. package/src/auth-turn/fixtures/valid/redirect.json +16 -0
  191. package/src/auth-turn/fixtures/valid/retry.json +8 -0
  192. package/src/auth-turn/fixtures/valid/unknown-kind.json +7 -0
  193. package/src/auth-turn/index.ts +177 -0
  194. package/src/auth.ts +728 -0
  195. package/src/ceremonies/index.ts +33 -121
  196. package/src/cli/commands.ts +10 -0
  197. package/src/cli/create.ts +69 -99
  198. package/src/cli/prompt-assets.ts +865 -0
  199. package/src/cli/templates/provider/.agents/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  200. package/src/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  201. package/src/cli/templates/provider/.agents/skills/normalization-standards/SKILL.md.tpl +57 -0
  202. package/src/cli/templates/provider/.agents/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  203. package/src/cli/templates/provider/.agents/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  204. package/src/cli/templates/provider/.agents/skills/upstream-notes/README.md.tpl +13 -0
  205. package/src/cli/templates/provider/AGENTS.md.tpl +96 -0
  206. package/src/cli/templates/provider/README.md.tpl +7 -4
  207. package/src/config/loader.ts +543 -208
  208. package/src/contract-serialization.ts +5 -11
  209. package/src/contract-types.ts +2 -2
  210. package/src/contract.ts +13 -28
  211. package/src/define.ts +397 -528
  212. package/src/dev.ts +4 -9
  213. package/src/errors.ts +58 -5
  214. package/src/i18n/catalog.ts +10 -32
  215. package/src/i18n/index.ts +2 -2
  216. package/src/i18n/keys.ts +5 -11
  217. package/src/index.ts +64 -41
  218. package/src/lint.ts +122 -159
  219. package/src/provider.ts +40 -9
  220. package/src/public-schema-field-lint.ts +7 -33
  221. package/src/recipes/gov-api.ts +2 -5
  222. package/src/runtime/auth-flow.ts +6 -6
  223. package/src/runtime/browser.ts +320 -151
  224. package/src/runtime/cache.ts +20 -67
  225. package/src/runtime/choice.ts +79 -132
  226. package/src/runtime/credential.ts +2 -2
  227. package/src/runtime/env.ts +1 -1
  228. package/src/runtime/executor.ts +23 -20
  229. package/src/runtime/http.ts +216 -539
  230. package/src/runtime/insights.ts +15 -53
  231. package/src/runtime/instrumentation.ts +78 -65
  232. package/src/runtime/keyring.ts +7 -19
  233. package/src/runtime/namespace.ts +2 -7
  234. package/src/runtime/otlp.ts +12 -23
  235. package/src/runtime/perf.ts +1 -1
  236. package/src/runtime/provider.ts +4 -9
  237. package/src/runtime/proxy-errors.ts +29 -42
  238. package/src/runtime/proxy-nodemaven.ts +178 -0
  239. package/src/runtime/proxy-retry-policy.ts +469 -0
  240. package/src/runtime/proxy-telemetry.ts +79 -77
  241. package/src/runtime/redis.ts +4 -12
  242. package/src/runtime/request-options.ts +4 -13
  243. package/src/runtime/secrets.ts +64 -0
  244. package/src/runtime/state.ts +41 -110
  245. package/src/runtime/stealth.ts +331 -369
  246. package/src/runtime/stt.ts +38 -94
  247. package/src/runtime/trace.ts +14 -44
  248. package/src/runtime/waterfall.ts +5 -18
  249. package/src/schema.ts +23 -84
  250. package/src/serve.ts +1 -1
  251. package/src/server/index.ts +44 -3
  252. package/src/server/self-test-input-tokens.ts +46 -0
  253. package/src/server/self-test-redaction.ts +97 -0
  254. package/src/server/self-test-token.ts +70 -0
  255. package/src/server/self-test.ts +1450 -0
  256. package/src/server/serve.ts +206 -216
  257. package/src/server/types.ts +7 -19
  258. package/src/stealth/profiles.ts +10 -26
  259. package/src/stream.ts +8 -19
  260. package/src/testing/index.ts +2 -2
  261. package/src/testing/run.ts +24 -64
  262. package/src/types.ts +274 -1
  263. package/src/user-input.ts +118 -0
@@ -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
- import { cancel, intro, isCancel, note, outro, select, text, } from "@clack/prompts";
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",
@@ -17,12 +18,7 @@ export const CATEGORY_OPTIONS = [
17
18
  "communication",
18
19
  "other",
19
20
  ];
20
- export const AUTH_MODE_OPTIONS = [
21
- "none",
22
- "platform-managed",
23
- "credentials",
24
- "oauth2",
25
- ];
21
+ export const AUTH_MODE_OPTIONS = ["none", "platform-managed", "credentials", "oauth2"];
26
22
  export const RUNTIME_OPTIONS = ["standard", "browser"];
27
23
  export const PRESET_OPTIONS = ["standalone", "monorepo"];
28
24
  const CREATE_CONFIG_SCHEMA = z.object({
@@ -64,9 +60,7 @@ export async function main() {
64
60
  return;
65
61
  }
66
62
  const parsed = parseArgs(normalizedArgs);
67
- const config = parsed.configPath
68
- ? await loadConfig(parsed.configPath)
69
- : undefined;
63
+ const config = parsed.configPath ? await loadConfig(parsed.configPath) : undefined;
70
64
  const resolved = await resolveCreateOptions(parsed, config, process.cwd());
71
65
  const plan = await buildProviderCreatePlan(resolved, process.cwd());
72
66
  if (resolved.dryRun) {
@@ -174,9 +168,7 @@ async function resolveCreateOptions(parsed, config, cwd) {
174
168
  category: parsed.category ?? config?.category,
175
169
  authMode: parsed.authMode ?? config?.authMode,
176
170
  runtime: parsed.runtime ?? config?.runtime,
177
- sdkSpecifier: parsed.sdkSpecifier ??
178
- config?.sdkSpecifier ??
179
- process.env.APIFUSE__SDK__SPECIFIER,
171
+ sdkSpecifier: parsed.sdkSpecifier ?? config?.sdkSpecifier ?? process.env.APIFUSE__SDK__SPECIFIER,
180
172
  dryRun: parsed.dryRun,
181
173
  json: parsed.json,
182
174
  yes: parsed.yes,
@@ -267,9 +259,7 @@ async function promptValue(prompt) {
267
259
  return result;
268
260
  }
269
261
  export async function buildProviderCreatePlan(options, cwd) {
270
- const resolvedWorkspaceRoot = options.preset === "monorepo"
271
- ? findApifuseInternalWorkspaceRoot(cwd)
272
- : undefined;
262
+ const resolvedWorkspaceRoot = options.preset === "monorepo" ? findApifuseInternalWorkspaceRoot(cwd) : undefined;
273
263
  if (options.preset === "monorepo" && !resolvedWorkspaceRoot) {
274
264
  throw new Error("Monorepo preset is internal to the APIFuse repository. External bounty workspaces are one-provider repositories; use the standalone default create flow.");
275
265
  }
@@ -278,9 +268,7 @@ export async function buildProviderCreatePlan(options, cwd) {
278
268
  if (options.outputDir) {
279
269
  providerRoot = resolve(cwd, options.outputDir);
280
270
  installCwd =
281
- options.preset === "monorepo" && resolvedWorkspaceRoot
282
- ? resolvedWorkspaceRoot
283
- : providerRoot;
271
+ options.preset === "monorepo" && resolvedWorkspaceRoot ? resolvedWorkspaceRoot : providerRoot;
284
272
  }
285
273
  else if (options.preset === "monorepo" && resolvedWorkspaceRoot) {
286
274
  providerRoot = resolve(resolvedWorkspaceRoot, "providers", options.name);
@@ -293,14 +281,18 @@ export async function buildProviderCreatePlan(options, cwd) {
293
281
  if (existsSync(providerRoot)) {
294
282
  throw new Error(`Target directory already exists: ${providerRoot}`);
295
283
  }
296
- if (options.sdkSpecifier?.startsWith("workspace:") &&
297
- !resolvedWorkspaceRoot) {
284
+ if (options.sdkSpecifier?.startsWith("workspace:") && !resolvedWorkspaceRoot) {
298
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.");
299
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.
300
292
  const sdkSpecifier = options.sdkSpecifier ??
301
293
  (options.preset === "monorepo" && resolvedWorkspaceRoot
302
294
  ? "workspace:*"
303
- : `^${packageJson.version}`);
295
+ : packageJson.version);
304
296
  const relativeProviderRoot = relative(cwd, providerRoot) || options.name;
305
297
  const nextDevCommand = `cd ${relativeProviderRoot} && bun run dev`;
306
298
  const packageName = options.preset === "monorepo"
@@ -420,6 +412,20 @@ export async function buildProviderCreatePlan(options, cwd) {
420
412
  }),
421
413
  },
422
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
+ });
423
429
  return {
424
430
  displayName: options.displayName,
425
431
  files,
@@ -434,7 +440,7 @@ export async function buildProviderCreatePlan(options, cwd) {
434
440
  validationCommands: [
435
441
  "bun run check",
436
442
  "bun run type-check",
437
- "bun run submit-check",
443
+ "bun run submit-check -- --smoke",
438
444
  "bun run test",
439
445
  ],
440
446
  workspaceRoot: resolvedWorkspaceRoot,
@@ -459,9 +465,9 @@ function renderPackageJson(input) {
459
465
  check: "apifuse check . && bun run type-check",
460
466
  "type-check": "tsc --noEmit",
461
467
  "submit-check": "apifuse submit-check . --markdown submission-report.md",
468
+ "sync-assets": "apifuse sync-assets .",
462
469
  test: "apifuse test .",
463
470
  record: "apifuse record .",
464
- "perf:sample": "apifuse perf . --operation ping --runs 3",
465
471
  start: "bun start.ts",
466
472
  },
467
473
  dependencies: {
@@ -544,8 +550,8 @@ function renderAuthBlock(authMode) {
544
550
  return `{
545
551
  mode: "credentials",
546
552
  flow: {
547
- start: async () => ({
548
- kind: "input",
553
+ start: async (_ctx) => ({
554
+ kind: "form",
549
555
  turnId: crypto.randomUUID(),
550
556
  expectedInput: {
551
557
  schema: {
@@ -588,7 +594,7 @@ function renderAuthBlock(authMode) {
588
594
  return `{
589
595
  mode: "oauth2",
590
596
  flow: {
591
- start: async () => ({
597
+ start: async (_ctx) => ({
592
598
  kind: "redirect",
593
599
  turnId: crypto.randomUUID(),
594
600
  data: {
@@ -679,6 +685,13 @@ function isApifuseInternalWorkspaceRoot(workspaceRoot) {
679
685
  async function writePlan(plan) {
680
686
  for (const file of plan.files) {
681
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
+ }
682
695
  await writeFile(file.path, file.content);
683
696
  }
684
697
  }
@@ -716,9 +729,7 @@ async function runCommand(command, cwd, jsonMode) {
716
729
  resolvePromise();
717
730
  return;
718
731
  }
719
- rejectPromise(new Error(`Command failed (${command}) in ${cwd}${stdout || stderr
720
- ? `\n${[stdout, stderr].filter(Boolean).join("\n")}`
721
- : ""}`));
732
+ rejectPromise(new Error(`Command failed (${command}) in ${cwd}${stdout || stderr ? `\n${[stdout, stderr].filter(Boolean).join("\n")}` : ""}`));
722
733
  });
723
734
  });
724
735
  }
@@ -739,7 +750,10 @@ function printResult(plan, jsonMode, dryRun) {
739
750
  },
740
751
  validationCommands: plan.validationCommands,
741
752
  nextDevCommand: plan.nextDevCommand,
742
- 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
+ }),
743
757
  };
744
758
  if (jsonMode) {
745
759
  console.log(JSON.stringify(payload, null, 2));
@@ -752,7 +766,7 @@ function printResult(plan, jsonMode, dryRun) {
752
766
  console.log(`Validation: (cd ${plan.providerRoot} && ${command})`);
753
767
  }
754
768
  console.log(`Next local dev: ${plan.nextDevCommand}`);
755
- console.log("Submission evidence: run `bun run submit-check`, save the generated report, and note `/health` plus `POST /v1/{operation}` smoke results.");
769
+ console.log("Submission evidence: run `bun run submit-check -- --smoke` to archive measured `/health` and `POST /v1/{operation}` results.");
756
770
  if (plan.files.some((file) => file.content.includes('runtime: "browser"'))) {
757
771
  console.log("Browser runtime: run `bunx playwright install chromium` locally or set `APIFUSE__CDP_POOL__URL` before browser-backed smoke tests.");
758
772
  }
@@ -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;