@xano/sdk 1.0.8 → 1.0.9

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 (118) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/{agent-file-refresh-QJO3MT6Q.js → agent-file-refresh-XXCQOTWN.js} +4 -4
  4. package/dist/{agent-skill-command-GBR4KUUG.js → agent-skill-command-VDSMXH4M.js} +14 -14
  5. package/dist/{backend-dir-PFUIPCV3.js → backend-dir-G44PETFO.js} +4 -4
  6. package/dist/bin.js +14 -14
  7. package/dist/{branch-commands-CR3SAHMV.js → branch-commands-Q6E66PMM.js} +3 -3
  8. package/dist/{chunk-QRKBFXIB.js → chunk-2VWSUG2B.js} +2 -2
  9. package/dist/{chunk-FN7E6XGD.js → chunk-3XSTC3TM.js} +2 -2
  10. package/dist/{chunk-RYMGK2K5.js → chunk-5BEK7YKY.js} +2 -2
  11. package/dist/{chunk-C2I4GC36.js → chunk-5VOGPS5O.js} +2 -2
  12. package/dist/{chunk-W2BVP27L.js → chunk-6IOQRBRX.js} +2 -2
  13. package/dist/{chunk-P5W6DBV6.js → chunk-ADKC3EII.js} +3 -3
  14. package/dist/{chunk-Y5ET37NN.js → chunk-BUTGFWWA.js} +2 -2
  15. package/dist/{chunk-UU7EEREQ.js → chunk-CXWCWYX3.js} +2 -2
  16. package/dist/{chunk-JPRZ4ZGU.js → chunk-DDUOMOIP.js} +6 -6
  17. package/dist/{chunk-DER2CVNC.js → chunk-DSD2NNTX.js} +2 -2
  18. package/dist/{chunk-JJGK7XGC.js → chunk-FFB3YCUO.js} +2 -2
  19. package/dist/{chunk-PAS5HOG3.js → chunk-GAU2FCT7.js} +2 -2
  20. package/dist/{chunk-XYTVP4WI.js → chunk-GHPC52TD.js} +3 -3
  21. package/dist/{chunk-CRE7P7P2.js → chunk-HBFXR4OJ.js} +2 -2
  22. package/dist/{chunk-JG642U5D.js → chunk-HETQSTGG.js} +2 -2
  23. package/dist/{chunk-V7KMIEMF.js → chunk-HVSIS47X.js} +16 -16
  24. package/dist/{chunk-QE2GNFMP.js → chunk-IFCQCM2Q.js} +3 -3
  25. package/dist/{chunk-7UWUEUVJ.js → chunk-INAM6KR6.js} +2 -2
  26. package/dist/{chunk-HKLBDSML.js → chunk-KDS4PDFD.js} +2 -2
  27. package/dist/{chunk-UKJFCEMI.js → chunk-NI56XX5Z.js} +2 -2
  28. package/dist/{chunk-77GV772V.js → chunk-OYRQLU66.js} +2 -2
  29. package/dist/{chunk-S3WN6GGO.js → chunk-QGDT52FA.js} +12 -12
  30. package/dist/{chunk-AS4G2MIE.js → chunk-S5RZYUP2.js} +2 -2
  31. package/dist/{chunk-S3STXOAO.js → chunk-SGYDFEXD.js} +7 -7
  32. package/dist/{chunk-ZT2B22VQ.js → chunk-SSOTLVOJ.js} +2 -2
  33. package/dist/{chunk-F5RPNTN7.js → chunk-T3ZVNOJC.js} +1 -1
  34. package/dist/{chunk-ZJCHS7FM.js → chunk-U7XSQXOA.js} +54 -54
  35. package/dist/{chunk-YG7S3N7P.js → chunk-UZUY6VPB.js} +20 -20
  36. package/dist/{chunk-NFZUXS7D.js → chunk-WKCA66SH.js} +5 -5
  37. package/dist/{chunk-FHQYXGAY.js → chunk-WLFANUXE.js} +2 -2
  38. package/dist/{chunk-U7XNJ33Q.js → chunk-XLQT3CCF.js} +12 -12
  39. package/dist/{chunk-WEQFI55W.js → chunk-XPLBTV77.js} +4 -4
  40. package/dist/{chunk-ZQ5WZWHF.js → chunk-XTUYIX5H.js} +16 -16
  41. package/dist/{chunk-M3RLLT4O.js → chunk-Y2LKSXFK.js} +3 -3
  42. package/dist/{chunk-2HZDWZM2.js → chunk-Y3FM4BSZ.js} +1 -1
  43. package/dist/{chunk-33KELF2X.js → chunk-YMVCKGY2.js} +39 -39
  44. package/dist/{chunk-K75BFHQQ.js → chunk-YVXUYDHC.js} +2 -2
  45. package/dist/{chunk-S2F7KVUL.js → chunk-ZYPEH64F.js} +2 -2
  46. package/dist/cli.d.ts +1 -1
  47. package/dist/cli.js +13 -13
  48. package/dist/{codegen-command-4YXDJSLU.js → codegen-command-KZJ7LYHW.js} +20 -20
  49. package/dist/{deploy-command-FIDS56ZC.js → deploy-command-RXPJAM7M.js} +17 -17
  50. package/dist/{deploy-source-FPNNNNOW.js → deploy-source-TD77W4SA.js} +7 -7
  51. package/dist/{dev-env-sync-RBJ2U3HG.js → dev-env-sync-2UCNSIJL.js} +14 -14
  52. package/dist/{emit-8lcNcRrd.d.ts → emit-D-a6JznN.d.ts} +10 -4
  53. package/dist/{env-example-refresh-6UTTMDOI.js → env-example-refresh-QKZI26F2.js} +21 -21
  54. package/dist/{env-pull-command-P5MATITQ.js → env-pull-command-72PQOMKW.js} +13 -13
  55. package/dist/{env-target-F75YF25S.js → env-target-AZJ4JXT7.js} +2 -2
  56. package/dist/{env-var-command-H3GHROVB.js → env-var-command-ALJITZDL.js} +13 -13
  57. package/dist/{ephemeral-command-NH2XW3YK.js → ephemeral-command-T276HQBO.js} +14 -14
  58. package/dist/{generate-command-IANKN6WV.js → generate-command-M6LAT4XU.js} +24 -24
  59. package/dist/{gitignore-FT2LVOMI.js → gitignore-V6QHYKIR.js} +6 -6
  60. package/dist/{impersonate-command-7B67ICPL.js → impersonate-command-S6PYDMHQ.js} +9 -9
  61. package/dist/index.d.ts +4 -4
  62. package/dist/index.js +2 -2
  63. package/dist/{init-command-QOA4TJI2.js → init-command-ENAZKPZA.js} +16 -16
  64. package/dist/{init-modules-KEEJ4HAF.js → init-modules-AIKWWTVQ.js} +2 -2
  65. package/dist/internal.d.ts +4 -4
  66. package/dist/internal.js +21 -4
  67. package/dist/{keep-data-merge-BIBW4QR4.js → keep-data-merge-3WPUPPTY.js} +4 -4
  68. package/dist/{landing-record-DO3PM7QP.js → landing-record-SJ5HG7T5.js} +5 -5
  69. package/dist/{local-engine-choice-2UF7S5QZ.js → local-engine-choice-BD5O7SAU.js} +8 -8
  70. package/dist/{local-engine-command-WGMMZRQL.js → local-engine-command-MXQUXXAA.js} +9 -9
  71. package/dist/{local-engine-mcp-command-RMVUH4FL.js → local-engine-mcp-command-6G3TDWDI.js} +9 -9
  72. package/dist/{lock-commands-5NMQWBGH.js → lock-commands-SUPQOEVU.js} +14 -14
  73. package/dist/{login-command-GLLFZWHT.js → login-command-LTYO3EK7.js} +9 -9
  74. package/dist/{logout-command-NCMKMJWF.js → logout-command-QRRT36DY.js} +3 -3
  75. package/dist/{marketplace-command-Y3RRUEWL.js → marketplace-command-POQH5GVT.js} +13 -13
  76. package/dist/{meta-client-Y7N6WDS2.js → meta-client-PDUP4EOW.js} +2 -2
  77. package/dist/node.d.ts +4 -4
  78. package/dist/node.js +16 -16
  79. package/dist/{operation-outcome-4BFISK2R.js → operation-outcome-IXMC5SBN.js} +4 -4
  80. package/dist/{output-target-MFANTVGZ.js → output-target-4XN43WIB.js} +7 -7
  81. package/dist/{preflight-command-Q6XOKRM6.js → preflight-command-QWZL4O2N.js} +19 -19
  82. package/dist/{profile-command-XPQIXFWN.js → profile-command-V6WFDYZW.js} +10 -10
  83. package/dist/{promote-command-DN64QK7O.js → promote-command-B3QODJNT.js} +27 -27
  84. package/dist/{publish-command-SLE46MQX.js → publish-command-JOL6LXH6.js} +17 -17
  85. package/dist/{pull-command-UVK3IOXM.js → pull-command-RPGL6LXP.js} +22 -22
  86. package/dist/{release-command-MKNESNGB.js → release-command-USZAWVXO.js} +19 -19
  87. package/dist/{release-ns-command-HLR46IKP.js → release-ns-command-3XDRQKJD.js} +32 -32
  88. package/dist/{routes-manifest-file-UHVVL2YB.js → routes-manifest-file-V5JJVIPH.js} +2 -2
  89. package/dist/{secrets-file-HST7BMQC.js → secrets-file-ZA6K4J6W.js} +5 -5
  90. package/dist/{secrets-fill-command-FQJ4QFBP.js → secrets-fill-command-MH53XR45.js} +16 -16
  91. package/dist/{source-resolve-LNRUITLS.js → source-resolve-I55GN6ZC.js} +3 -3
  92. package/dist/{status-command-S5CBG2SW.js → status-command-I6S2TVAY.js} +12 -12
  93. package/dist/{store-CuD1k4kV.d.ts → store-xUySg-KR.d.ts} +1 -1
  94. package/dist/{sync-contributions-O5ZRM2JN.js → sync-contributions-4HHBUGJ4.js} +2 -2
  95. package/dist/{tables-command-7KI2KZOS.js → tables-command-L4JRA7JF.js} +10 -10
  96. package/dist/{tenant-command-MQTLNETR.js → tenant-command-IZ3R4BDG.js} +33 -33
  97. package/dist/{test-command-NLYMAAPD.js → test-command-GCKZRRSL.js} +10 -10
  98. package/dist/{token-3IPTVEEW.js → token-XQCIFX7R.js} +2 -2
  99. package/dist/{toolchain-modules-K46KYJ4G.js → toolchain-modules-C53NXT3S.js} +2 -2
  100. package/dist/{tracked-backend-FQFXTTYZ.js → tracked-backend-UHKPD2JU.js} +9 -9
  101. package/dist/{update-check-FHRRUDEC.js → update-check-KMAC4VEJ.js} +15 -15
  102. package/dist/{upgrade-command-WNBPKUXN.js → upgrade-command-HQBSUFNE.js} +17 -17
  103. package/dist/{whoami-command-DPGDK35H.js → whoami-command-23UXAC6F.js} +4 -4
  104. package/dist/{workspace-2GMONZ2A.js → workspace-TZMAJ7NF.js} +2 -2
  105. package/dist/{workspace-binding-PAUOIK3V.js → workspace-binding-RBU22BBX.js} +3 -3
  106. package/dist/{workspace-command-KEKL27Y4.js → workspace-command-N4BTEHSW.js} +28 -28
  107. package/dist/{workspace-env-GGEZVZDY.js → workspace-env-O3RK26FR.js} +5 -5
  108. package/dist/{xanosdk-import-HYHABD5U.js → xanosdk-import-WPCHIVP6.js} +2 -2
  109. package/dist/{xanosdk-project-2T56DRYS.js → xanosdk-project-TEAXYQZW.js} +5 -5
  110. package/guides/cli.md +8 -7
  111. package/guides/deploying.md +11 -8
  112. package/llms/kinds-agent-mcp.md +3 -2
  113. package/llms/object-kinds.md +14 -0
  114. package/llms-full.txt +19 -4
  115. package/llms.txt +2 -2
  116. package/manifest.json +1 -1
  117. package/package.json +1 -1
  118. package/skills/xano-backend/SKILL.md +2 -2
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-R4NOZBOY.js";
5
5
  import {
6
6
  fetchWorkspaceBundle
7
- } from "./chunk-ZQ5WZWHF.js";
8
- import "./chunk-V7KMIEMF.js";
9
- import "./chunk-PAS5HOG3.js";
7
+ } from "./chunk-XTUYIX5H.js";
8
+ import "./chunk-HVSIS47X.js";
9
+ import "./chunk-GAU2FCT7.js";
10
10
  import "./chunk-QTMXJQZN.js";
11
11
  import "./chunk-O376UAZS.js";
12
12
  import "./chunk-6YOH2L3G.js";
13
- import "./chunk-XYTVP4WI.js";
13
+ import "./chunk-GHPC52TD.js";
14
14
  import {
15
15
  confirm
16
16
  } from "./chunk-HQPL34O6.js";
@@ -29,38 +29,38 @@ import {
29
29
  reachableWorkspaces,
30
30
  refuseUnreachableWorkspace,
31
31
  unreachableWorkspaceMessage
32
- } from "./chunk-FHQYXGAY.js";
33
- import "./chunk-K75BFHQQ.js";
32
+ } from "./chunk-WLFANUXE.js";
33
+ import "./chunk-YVXUYDHC.js";
34
34
  import "./chunk-OBJ7FQDX.js";
35
35
  import "./chunk-2TFRR6JV.js";
36
36
  import {
37
37
  resolveOutputTarget,
38
38
  secretsPhrase,
39
39
  writeExportFile
40
- } from "./chunk-AS4G2MIE.js";
40
+ } from "./chunk-S5RZYUP2.js";
41
41
  import {
42
42
  secretsCarriedBy
43
43
  } from "./chunk-I53OTC3O.js";
44
- import "./chunk-JG642U5D.js";
44
+ import "./chunk-HETQSTGG.js";
45
45
  import {
46
46
  assertBundleFile,
47
47
  assertBundleInput,
48
48
  assertEntryFile,
49
49
  assertValueFiles,
50
50
  loadBundleText
51
- } from "./chunk-ZJCHS7FM.js";
51
+ } from "./chunk-U7XSQXOA.js";
52
52
  import "./chunk-XQO4A4Q4.js";
53
- import "./chunk-M3RLLT4O.js";
54
- import "./chunk-S3STXOAO.js";
53
+ import "./chunk-Y2LKSXFK.js";
54
+ import "./chunk-SGYDFEXD.js";
55
55
  import "./chunk-PBK257CI.js";
56
- import "./chunk-7UWUEUVJ.js";
56
+ import "./chunk-INAM6KR6.js";
57
57
  import "./chunk-7JKNWDYN.js";
58
- import "./chunk-C2I4GC36.js";
58
+ import "./chunk-5VOGPS5O.js";
59
59
  import "./chunk-VJTTTIIB.js";
60
60
  import {
61
61
  getAccessToken
62
- } from "./chunk-QE2GNFMP.js";
63
- import "./chunk-QRKBFXIB.js";
62
+ } from "./chunk-IFCQCM2Q.js";
63
+ import "./chunk-2VWSUG2B.js";
64
64
  import "./chunk-5Y5HWQ2P.js";
65
65
  import "./chunk-F3IA3YWI.js";
66
66
  import "./chunk-LCOCRJ4K.js";
@@ -69,9 +69,9 @@ import "./chunk-YE7MHW45.js";
69
69
  import "./chunk-2MNLRIOX.js";
70
70
  import "./chunk-PFW7WFAT.js";
71
71
  import "./chunk-CJDPSCMX.js";
72
- import "./chunk-UKJFCEMI.js";
72
+ import "./chunk-NI56XX5Z.js";
73
73
  import "./chunk-VD7YTLWL.js";
74
- import "./chunk-UU7EEREQ.js";
74
+ import "./chunk-CXWCWYX3.js";
75
75
  import "./chunk-S42TFTM5.js";
76
76
  import "./chunk-ZYJP6BOO.js";
77
77
  import "./chunk-QO6BVGS5.js";
@@ -86,9 +86,9 @@ import {
86
86
  } from "./chunk-6S263KTM.js";
87
87
  import "./chunk-IB6SKACE.js";
88
88
  import "./chunk-EUUUMY7J.js";
89
- import "./chunk-W2BVP27L.js";
90
- import "./chunk-HKLBDSML.js";
91
- import "./chunk-RYMGK2K5.js";
89
+ import "./chunk-6IOQRBRX.js";
90
+ import "./chunk-KDS4PDFD.js";
91
+ import "./chunk-5BEK7YKY.js";
92
92
  import "./chunk-B3NH5UBI.js";
93
93
  import "./chunk-ZFDZKNGG.js";
94
94
  import "./chunk-FWD7AL6N.js";
@@ -144,7 +144,7 @@ import {
144
144
  writeJson,
145
145
  writeTargetPayload
146
146
  } from "./chunk-C6KBZH7M.js";
147
- import "./chunk-F5RPNTN7.js";
147
+ import "./chunk-T3ZVNOJC.js";
148
148
  import "./chunk-OHTHG3LL.js";
149
149
  import "./chunk-6JAEMMZ7.js";
150
150
  import "./chunk-6ZFJEJXZ.js";
@@ -203,7 +203,7 @@ async function runWorkspaceCommand(args) {
203
203
  case "reset-tables":
204
204
  return runResetTables(args);
205
205
  case "branch": {
206
- const { runBranchCommand } = await import("./branch-commands-CR3SAHMV.js");
206
+ const { runBranchCommand } = await import("./branch-commands-Q6E66PMM.js");
207
207
  return runBranchCommand(args);
208
208
  }
209
209
  default:
@@ -232,7 +232,7 @@ async function runDetails(args) {
232
232
  const auth = await getAccessToken(args);
233
233
  const workspaceId = auth.workspaceId;
234
234
  const all = await fetchWorkspaces(auth).catch(async (err) => {
235
- const { unansweredRead } = await import("./source-resolve-LNRUITLS.js");
235
+ const { unansweredRead } = await import("./source-resolve-I55GN6ZC.js");
236
236
  throw unansweredRead(err, "read the workspace list", "workspace");
237
237
  });
238
238
  const match = all.find((w) => w.id === workspaceId);
@@ -292,7 +292,7 @@ async function runExport(args) {
292
292
  var EXIT_DIFF_MISMATCH = 2;
293
293
  async function runDiff(args) {
294
294
  if (args.file === void 0 && args.bundle === void 0) {
295
- const { resolveProjectEntry } = await import("./deploy-source-FPNNNNOW.js");
295
+ const { resolveProjectEntry } = await import("./deploy-source-TD77W4SA.js");
296
296
  const entry = resolveProjectEntry(process.cwd());
297
297
  if (entry !== void 0) args = { ...args, file: entry };
298
298
  }
@@ -305,11 +305,11 @@ async function runDiff(args) {
305
305
  try {
306
306
  live = await fetchWorkspaceBundle(auth, args.branch);
307
307
  } catch (err) {
308
- const { unansweredRead } = await import("./source-resolve-LNRUITLS.js");
308
+ const { unansweredRead } = await import("./source-resolve-I55GN6ZC.js");
309
309
  throw unansweredRead(err, "read the workspace to compare", "workspace");
310
310
  }
311
311
  const { SETTINGS_LABEL } = await import("./live-diff-CGTGOH3S.js");
312
- const { codePinnedCanonicals, releaseCanonicalLock } = await import("./release-command-MKNESNGB.js");
312
+ const { codePinnedCanonicals, releaseCanonicalLock } = await import("./release-command-USZAWVXO.js");
313
313
  const pinned = codePinnedCanonicals(local.bundle, releaseCanonicalLock(args), args.file !== void 0);
314
314
  const listed = await listBranches(auth, { baseUrl: auth.instance, workspaceId: auth.workspaceId }).catch(
315
315
  () => void 0
@@ -317,7 +317,7 @@ async function runDiff(args) {
317
317
  const liveLabel = listed?.find((b) => b.live)?.label;
318
318
  const comparedLabel = args.branch ?? liveLabel;
319
319
  const comparedIsLive = args.branch === void 0 ? true : liveLabel === void 0 ? null : args.branch === liveLabel;
320
- const { landingLockPath } = await import("./landing-record-DO3PM7QP.js");
320
+ const { landingLockPath } = await import("./landing-record-SJ5HG7T5.js");
321
321
  const { readSyncBaseline, storedBranchLabel } = await import("./sync-record-U65BCPSP.js");
322
322
  const { directedComparison } = await import("./sync-baseline-3CDL4PKT.js");
323
323
  const syncLabel = storedBranchLabel(listed, args.branch);
@@ -560,4 +560,4 @@ export {
560
560
  EXIT_DIFF_MISMATCH,
561
561
  runWorkspaceCommand
562
562
  };
563
- //# sourceMappingURL=workspace-command-KEKL27Y4.js.map
563
+ //# sourceMappingURL=workspace-command-N4BTEHSW.js.map
@@ -14,10 +14,10 @@ import {
14
14
  renderWorkspaceEnvFile,
15
15
  valueProblem,
16
16
  workspaceEnvPathIn
17
- } from "./chunk-M3RLLT4O.js";
18
- import "./chunk-W2BVP27L.js";
19
- import "./chunk-HKLBDSML.js";
20
- import "./chunk-RYMGK2K5.js";
17
+ } from "./chunk-Y2LKSXFK.js";
18
+ import "./chunk-6IOQRBRX.js";
19
+ import "./chunk-KDS4PDFD.js";
20
+ import "./chunk-5BEK7YKY.js";
21
21
  import "./chunk-B3NH5UBI.js";
22
22
  import "./chunk-ZFDZKNGG.js";
23
23
  import "./chunk-FWD7AL6N.js";
@@ -68,4 +68,4 @@ export {
68
68
  valueProblem,
69
69
  workspaceEnvPathIn
70
70
  };
71
- //# sourceMappingURL=workspace-env-GGEZVZDY.js.map
71
+ //# sourceMappingURL=workspace-env-O3RK26FR.js.map
@@ -13,7 +13,7 @@ import {
13
13
  resetXanoSdkImportDetection,
14
14
  withDefaultBranchPointer,
15
15
  xanosdkImport
16
- } from "./chunk-FN7E6XGD.js";
16
+ } from "./chunk-3XSTC3TM.js";
17
17
  import "./chunk-3DRXWLJ5.js";
18
18
  import "./chunk-X4DVXBFY.js";
19
19
  import "./chunk-VJTTTIIB.js";
@@ -53,4 +53,4 @@ export {
53
53
  withDefaultBranchPointer,
54
54
  xanosdkImport
55
55
  };
56
- //# sourceMappingURL=xanosdk-import-HYHABD5U.js.map
56
+ //# sourceMappingURL=xanosdk-import-WPCHIVP6.js.map
@@ -3,11 +3,11 @@ import {
3
3
  enterProjectRoot,
4
4
  isProjectDir,
5
5
  projectDirFrom
6
- } from "./chunk-C2I4GC36.js";
6
+ } from "./chunk-5VOGPS5O.js";
7
7
  import "./chunk-EUUUMY7J.js";
8
- import "./chunk-W2BVP27L.js";
9
- import "./chunk-HKLBDSML.js";
10
- import "./chunk-RYMGK2K5.js";
8
+ import "./chunk-6IOQRBRX.js";
9
+ import "./chunk-KDS4PDFD.js";
10
+ import "./chunk-5BEK7YKY.js";
11
11
  import "./chunk-B3NH5UBI.js";
12
12
  import "./chunk-ZFDZKNGG.js";
13
13
  import "./chunk-FWD7AL6N.js";
@@ -39,4 +39,4 @@ export {
39
39
  isProjectDir,
40
40
  projectDirFrom
41
41
  };
42
- //# sourceMappingURL=xanosdk-project-2T56DRYS.js.map
42
+ //# sourceMappingURL=xanosdk-project-TEAXYQZW.js.map
package/guides/cli.md CHANGED
@@ -83,7 +83,7 @@ xanosdk test run-all --kind unit # only one family (unit|workflow; de
83
83
  xanosdk test run-all --concurrency 4 # run 4 at once (default: 1); tests share the backend's database, so only when yours don't share state
84
84
  xanosdk impersonate # open what this project last deployed to in the builder (--guest = read-only; --url-only prints the URL; the URL is a session — treat it as a credential)
85
85
  xanosdk impersonate ephemeral:<tenant> # …or name one: local[:<name>] or tenant:<name> (open your workspace from the Xano dashboard)
86
- xanosdk deploy ./xano/index.ts --test # THE RELEASE FLOW, step 1: stand it up and run its tests
86
+ xanosdk deploy ./xano/index.ts --ephemeral --test # THE RELEASE FLOW, step 1: stand it up on an ephemeral and run its tests (a bare deploy goes to the Xano Engine, which release create cannot cut from)
87
87
  xanosdk release create v1 # …2: cut a release from the ephemeral this project last deployed to (after a local deploy: --from ephemeral)
88
88
  xanosdk release create v1 --from ephemeral:e4f2-9ab1 --description "what shipped" # …from a named source
89
89
  xanosdk release create v1 --from workspace --branch staging # …or from a branch of your workspace (default: what it serves)
@@ -180,14 +180,15 @@ workspace or a tenant, so a bare command cannot reach something real unasked. Wi
180
180
  it falls back to the ephemeral recorded under your current credential, then to the engine
181
181
  recorded for this directory, and otherwise refuses naming the flag, `xanosdk deploy` and
182
182
  `xanosdk deploy --local`.
183
- `deploy` is the exception: bare, it compiles the project and stands it up on an ephemeral
184
- unless `--to` or `--local` says otherwise, so it writes that record rather than
185
- reading it. `generate` and `init --from` need a backend named.
183
+ `deploy` is the exception: bare, it compiles the project and stands it up on the Xano Engine
184
+ on this machine unless `--ephemeral` or `--to` says otherwise, so it writes that record rather
185
+ than reading it. `generate` and `init --from` need a backend named.
186
186
 
187
187
  A command that cannot serve a backend refuses it, whether you typed it or it came from the
188
- record, with the reason and the spellings it does take: `publish` refuses a Xano Engine (no
189
- static host — pass `--to ephemeral`), and so does `release create` (the cut runs on the
190
- instance — pass `--from ephemeral`). A write to your workspace or a tenant confirms first,
188
+ record, with the reason and the spellings it does take: `release create` refuses a Xano Engine
189
+ (the cut runs on the instance — pass `--from ephemeral`). `publish` is not one of them: it
190
+ reaches a Xano Engine (`publish --to local`, or bare after a local deploy) and puts the build on
191
+ the engine's own static host. A write to your workspace or a tenant confirms first,
191
192
  or needs `--yes` off a terminal; an ephemeral or Xano Engine never asks.
192
193
 
193
194
  ## Bundle key names vs. the names everything else uses
@@ -175,7 +175,8 @@ what ran, then `xanosdk promote <release>` lands it there as a new branch, leavi
175
175
  untouched until you say otherwise.
176
176
 
177
177
  **Static host** — `deploy --static <dir>` archives a directory and deploys it to a
178
- static host after the backend import. The frontend lands **on the ephemeral itself**, so the
178
+ static host after the backend import. The frontend lands **on the environment the backend just
179
+ went to** — the ephemeral itself, or the Xano Engine (see *A frontend on the Xano Engine, and server rendering*) — so the
179
180
  backend and the frontend live in one environment. The CLI uploads the archive to
180
181
  `/api:meta/workspace/{id}/static_host/default/build` with your ordinary bearer. That route
181
182
  auto-creates the `default` host (and only that one: a `--static-host` naming a host the target
@@ -294,7 +295,7 @@ as three environment variables** — the `type: "token"` record above, with no f
294
295
  XANO_INSTANCE_URL=https://your-instance.xano.io \
295
296
  XANO_WORKSPACE_ID=3 \
296
297
  XANO_META_TOKEN=your-meta-api-token \
297
- npx xanosdk deploy ./xano/index.ts
298
+ npx xanosdk deploy ./xano/index.ts --ephemeral
298
299
  ```
299
300
 
300
301
  Nothing is read from or written to disk, and nothing rotates, so the same three secrets keep
@@ -610,8 +611,10 @@ with `--to` (`--seed`, `--prune`, `--dry-run`, …) stay refused alongside it.
610
611
 
611
612
  ### Deploying locally
612
613
 
613
- `xanosdk deploy --local` deploys to an engine running on this machine instead of an
614
- ephemeral — no network round-trip per deploy. It needs nothing configured:
614
+ A bare `xanosdk deploy` deploys to an engine running on this machine — no network round-trip
615
+ per deploy. `--local` is that default spelled out, needed only to name an engine:
616
+ `--local=<version|url|path>` runs that one instead of the pinned version. It needs nothing
617
+ configured:
615
618
 
616
619
  - **The first run** resolves the latest published engine for this machine's platform,
617
620
  downloads it, checks it against the sha256 its release recorded, and **pins** that version in
@@ -1019,7 +1022,7 @@ instead, so stdout is never empty. Branch on `code`, not on the message:
1019
1022
 
1020
1023
  A piped stdout gets the document too, without `--json`, so a script reading the pipe never gets
1021
1024
  an empty stdout. The exception is a command whose stdout is the data itself (`export` to stdout,
1022
- `llms`, `completion`, `--help`): a failure appended to it would corrupt it, so those write one
1025
+ `completion`, `--help`): a failure appended to it would corrupt it, so those write one
1023
1026
  only under `--json`. A piped `release` or `promote` write prints its operation result (above)
1024
1027
  either way.
1025
1028
 
@@ -1127,7 +1130,7 @@ or on a second destination, nothing for a tenant to be pointed at, and no record
1127
1130
  build *was* beyond the commit you built it from. Prefer the release flow for anything you may
1128
1131
  need to repeat.
1129
1132
 
1130
- The flags that describe the ephemeral a plain deploy refreshes — `--name`, `--expires-hours`,
1133
+ The flags that describe the environment a plain deploy replaces — `--name`, `--expires-hours`,
1131
1134
  `--reset`, `--keep-data`, `--test` (with `--kind`/`--concurrency`), `--no-dev-env`,
1132
1135
  `--require-microservices`, `--open` — are refused beside `--to`, before sign-in. `--static`
1133
1136
  publishes beside the merge, but not under `--dry-run`; `--skip-liveness` needs `--static` there.
@@ -1617,10 +1620,10 @@ and `XANO_META_TOKEN`, [above](#signing-in--deploying-in-depth) — no browser,
1617
1620
  nothing that rotates:
1618
1621
 
1619
1622
  ```bash
1620
- XANO_INSTANCE_URL=… XANO_WORKSPACE_ID=… XANO_META_TOKEN=… npx xanosdk deploy ./xano/index.ts
1623
+ XANO_INSTANCE_URL=… XANO_WORKSPACE_ID=… XANO_META_TOKEN=… npx xanosdk deploy ./xano/index.ts --ephemeral
1621
1624
  ```
1622
1625
 
1623
1626
  > ⚠️ A deploy without `--keep-data` is a full replace of the target environment, including
1624
- > its table records, before importing. The blast radius is your own disposable ephemeral — but anything
1627
+ > its table records, before importing. The blast radius is your own Xano Engine or disposable ephemeral — but anything
1625
1628
  > you only ever created by hand in it (or any data it accumulated) is gone. That's exactly
1626
1629
  > why a real workspace or tenant is reached only by naming it, with `deploy --to`.
@@ -1,14 +1,15 @@
1
1
  # Agent and MCP def shapes
2
2
 
3
- > Read when defining an `agent()`, `mcpServer()`, `prompt()` or `resource()`.
3
+ > Read when building an MCP server (tools, prompts, resources) or an `agent()`.
4
4
 
5
+ - An MCP server serves THREE primitives, and each reaches the client differently: a `tool()` is an action the MODEL calls (it may write); a `resource()` is read-only context the client APPLICATION lists and attaches by `uri` (reference docs, a schema, one record through a `{variable}` template); a `prompt()` is a message template with arguments the USER picks by name. Context a session opens with is a `resource()`; a workflow a user starts by name is a `prompt()`; data the model must fetch on its own mid-task stays a `tool()`, since a client shows the model only the resources attached to the conversation. Register each kind (`registerTools`/`registerPrompts`/`registerResources`) and list it on the server.
5
6
  - `mcpServer({ name, guid?, description?, instructions?, docs?, enabled?, canonical?, spec?, tags?, history?, tools?, prompts?, resources?, oauth?, llm?, output? })` — an MCP toolset. `llm?`/`output?` are the same blocks `agent()` takes and are usually absent: an MCP server and an agent are ONE stored object distinguished by `type`. Returns a handle with `getPath()`/`getUrl(baseUrl)` for the Streamable-HTTP endpoint — `getUrl` is NOT idempotent, a `baseUrl` already carrying an `/x2/mcp/<…>/stream` path THROWS, so resolve ONCE from the instance base URL. Fires on an ephemeral. A TENANT rides AFTER the prefix (`/x2/mcp/tenant/<tenant>/<canonical>/<token>/stream`), not as a base-URL segment: `getUrl` LIFTS a `/tenant/<name>` out of the base and re-places it there, so `getUrl(window.XANO_HOST)` is correct as-is; concatenating them by hand builds an unregistered route that 404s. Pass `{ tenant }` when the base URL cannot name it (a tenant on its own domain).
6
7
  - `tools?`: a `ToolsetToolEntry[]`. Pass the `tool()` HANDLES directly (`tools: [saveNote]`); use the `{ tool, enabled?, auth?, type?, resourceUri?, toolMeta? }` wrapper when an entry needs more. `type: "resource"` (+ a required `resourceUri`) is the LEGACY way to publish a tool as an MCP resource — author a `resource()` and list it in `resources` instead; `toolMeta` is extra metadata on a tool entry. The two payload fields are per-type and supplying the other one is refused, because the engine stores it against neither. `auth` names an auth **table** (a `table({ auth: true })` handle or its name) — per-tool, and the only gate there is. ⚠ It is also what gives the tool a CALLER, on an `agent()` exactly as on an MCP server. `auth()` inside a tool whose entry names no table does NOT return null: the call answers a normal result carrying `{"code":"ERROR_FATAL","message":""}`, so the model reads a successful tool result and reports success while nothing is written. A caller token does not rescue it — the ENTRY supplies identity. Spell it `{ tool: saveNote, auth: users }`; `export()` warns. An entry naming no tool THROWS at export; a deliberate raw `id: 0` warns and carries through.
7
8
  - `prompts?` / `resources?`: `prompt()` / `resource()` HANDLES (or names), or a `{ prompt, enabled?, auth? }` / `{ resource, enabled?, auth? }` wrapper. `auth` names the auth table and is what gives the stack a caller: a prompt/resource reading `auth()` behind an entry with none answers every `prompts/get` / `resources/read` with `-32603 "Access Denied"` (`export()` warns `toolset.primitive-reads-auth-ungated`). Listing one target twice THROWS; two resources with one `uri` on one server fail `export()` (`mcp.resource-uri-duplicate`). MCP-server only — `agent()` takes tools only.
8
9
  - `history?` is the server tier for its tools, prompts AND resources alike; an object's own `history` wins. The workspace tier (`workspaceConfig({ history })`) has `prompt` and `resource` keys, both default on.
9
10
  - `oauth?`: per-server sign-in; omit and nothing changes. Union on `mode`; `authTable` (REQUIRED, auth `table()` handle or name) is whose row the signed-in user is — `auth()` on the whole server, `t.auth` in its trigger. Hosted (the platform is the authorization server): `{ mode: "hosted", authTable, loginUrl }` — clients are sent to `loginUrl` (YOUR page, which is also the consent screen) with `mcp_request`; show `s.mcp.oauth.request`, sign the user in, then your endpoint calls `s.mcp.oauth.complete` with their `decision` and the page redirects to the URL it binds. External (your IdP issues tokens): `{ mode: "external", authTable, issuer, column, audience?, audienceAck?, claim?, claimAck?, preset?, allowedClientIds? }` — token `claim` (default `sub`) matched against `column`; `preset` is `auth0|clerk|workos|entra|okta|cognito|generic`. `loginUrl`/`issuer`/`audience` take `env("NAME")` (resolved per environment).
10
11
  - `export()` FAILS: hosted without `loginUrl` (`mcp.oauth-hosted-incomplete`); external without `issuer`/`column` (`mcp.oauth-external-incomplete`); `preset: "clerk"` without `allowedClientIds` (`mcp.oauth-preset-client-ids`); `claim` other than `sub`/`oid`/`email` without `claimAck` (`mcp.oauth-claim-unacked` — users can edit it at most providers). Unknown `mode`/`preset` THROWS; so do the dropped `consent`/`branding`/`trustedClients`.
11
- - `prompt({ name, guid?, description?, docs?, title?, icons?, tags?, history?, input?, stack?, response?, responseShape?, middleware? })` — an MCP prompt; takes `registerPrompts`. `input` is the prompt's arguments (each field's `description`/`required`/enum `values` reach the client; enum values also answer completion requests). `response`: a text value is ONE user message; a list of `{ role: "user" | "assistant", content }` is sent in order: `s.set_var("m", obj({ list: [obj({ role: c.text("user"), content: ref("body") })] }))`, `response: ref("m.list")`. Without `response` or a top-level `s.return`, `prompts/get` fails.
12
+ - `prompt({ name, guid?, description?, docs?, title?, icons?, tags?, history?, input?, stack?, response?, responseShape?, middleware? })` — an MCP prompt; takes `registerPrompts`. `input` is the prompt's arguments (each field's `description`/`required`/enum `values` reach the client; enum values also answer completion requests). `response`: a text value is ONE user message; a list of `{ role: "user" | "assistant", content }` is sent in order, `content` a string or an MCP content block: `s.set_var("m", obj({ list: [obj({ role: c.text("user"), content: ref("body") })] }))`, `response: ref("m.list")`. Without `response` or a top-level `s.return`, `prompts/get` fails.
12
13
  - `resource({ name, uri, guid?, description?, docs?, mimeType?, title?, icons?, annotations?, tags?, history?, input?, stack?, response?, responseShape?, middleware? })` — an MCP resource; takes `registerResources`. Clients address it by `uri`, never `name`.
13
14
  - `uri`: a literal (`"docs://readme"`, no `input`) or an RFC 6570 LEVEL-1 template (`"orders://{region}/{order_id}"`). It must start with a scheme; each `{variable}` is letters/digits/`_`, one per brace pair, never two adjacent. `input` must be EXACTLY the template's variables, each a single `text`/`int`/`decimal`/`bool`/`enum`/`email`/`uuid` — anything else THROWS. A value that does not convert is refused before the stack runs.
14
15
  - `response`: a string is returned as text; non-UTF-8 content (a file, binary) as a base64 blob. `mimeType?` omitted → derived from what the stack returns.
@@ -4,6 +4,20 @@
4
4
 
5
5
  Author with the factory, register on the Xano instance, lands under the payload key. Each line ends with a one-liner on what the primitive is.
6
6
 
7
+ ### Choosing a kind
8
+
9
+ Choose by who or what starts the work. Each rule names the kind that fits and the one it gets mistaken for.
10
+
11
+ - **Logic other code calls** → `defineFunction`, run with `s.function.run`. A `query` is the only kind an HTTP client reaches by verb + path; a `tool` is what an `agent()` or an MCP client calls. Logic serving two callers (an endpoint AND a tool) lives in one function both call.
12
+ - **Work on a timer** → `task` (cron or interval). **Work a request starts but does not wait for** → `s.function.run({ fn, runtime: { mode: "async-shared" } })`, which binds a job id, not the result (collect with `s.await`). **Work that follows a row change** → `tableTrigger`: it fires on every insert/update/delete of the table, whichever stack writes it, so the same side effect placed in one endpoint's stack misses every other write path.
13
+ - **The same steps before or after many objects** (an auth check, a rate limit, logging) → `middleware`, attached per host (`middleware: { pre, post }` on a query, function, task, tool or API group) or to every host of a kind with `workspaceConfig({ middleware: { query, function, task, tool } })` — not a function call repeated at the top of each stack.
14
+ - **Related rows on returned rows** → an `addon` attached to the read through its `addon: [{ addon, as, input }]` option (`db.query`/`get`/`add`/`edit`/`patch`), merged onto each row under `as` and typed in `InferResponse` — not a second read plus a loop that stitches rows together.
15
+ - **AI.** An LLM running inside the backend → `agent()`, started from a stack with `s.ai.agent.run`; it has no public endpoint. An external AI client (Claude, Cursor, any MCP client) calling the backend → `mcpServer()`. Standing instructions for Xano's own builder AI → `knowledge()`; an `agent()` run never reads it. The actions either one calls → `tool()`. What an MCP server serves besides tools (`prompt()`, `resource()`) and when each fits: `llms/kinds-agent-mcp.md`.
16
+ - **Pushing to connected clients** → `realtimeServer` → `realtimeChannel` → `realtimeMessage` (the handler for a frame a client sends — the realtime analogue of a query). A server-side push from any stack is `s.realtime.publish`; a client polling a `query` is the substitute this replaces.
17
+ - **Code the typed surface cannot express** → a lambda (`s.lambda`, `fl.lambda`) for a short JavaScript body, LAST, after native filters and expressions (`llms/lambda.md`); a `microservice` for a long-running container or another language; `s.api.request` for a service that already has an HTTP API.
18
+ - **Tests** → `tests` on a `query`/`defineFunction`/`middleware` for that one object's input → output; a `workflowTest` for a flow across objects (`s.function.call`, `s.api.call`, `s.task.call`) asserted with `s.expect.*`.
19
+ - **Reacting to the platform** → `errorTrigger` (an error signature first seen, regressing, or marked fixed) and `workspaceTrigger` (branch new/merge/live). What one connection to an MCP server, agent, realtime server or channel may see or do → that object's connection trigger.
20
+
7
21
  ⚠ Composing a workspace from independently-authored modules: `register*` takes its defs however they arrive, but `modules.flatMap((m) => m.tables)` does NOT typecheck. `Array.prototype.flatMap` binds its element type to the FIRST element, so every later module's tables are checked against that one table's schema — the error compares two unrelated column names and mentions neither `flatMap` nor the cause. `.concat()` collapses the same way. Two spellings work: pass an array LITERAL (`registerTables([...a.tables, ...b.tables])` — spreads are fine, TypeScript infers the union across every element at once), or annotate the module array with the wide aliases `AnyTableDef` / `AnyQueryDef` / `AnyFunctionDef` / `AnyAddonDef`, exported for exactly the four def types whose generics can collapse this way. Widening the array costs nothing: the typing you need lives on the `table()`/`query()` handle you hold and pass to `s.db.*`, and is never read back off the registered array.
8
22
 
9
23
  - function: `defineFunction` → `Xano.registerFunctions` → payload `function` — Reusable server-side logic (a custom function) callable from any stack via `s.function.run`.
package/llms-full.txt CHANGED
@@ -1,4 +1,4 @@
1
- # xanosdk v1.0.8
1
+ # xanosdk v1.0.9
2
2
 
3
3
  > TypeScript SDK that compiles a typed Xano workspace into the importable packageExport JSON bundle.
4
4
 
@@ -43,7 +43,7 @@ plain file read resolves them at the version you have.
43
43
  - [Toolchain modules](llms/toolchain.md): Read when `package.json` has a `"xanosdk"` block or you run `xanosdk marketplace`.
44
44
  - [Error index](llms/errors.md): Read when a request, test, build, or pull fails with a message you did not write — the string, its cause, and where the fix is.
45
45
  - [Saved unit tests, assertions, and mocks](llms/tests.md): Read when authoring a `workflowTest()` stack, when a query/function/middleware carries `tests`, when a statement needs a `mock`, or when running a deployed environment's tests.
46
- - [Agent and MCP def shapes](llms/kinds-agent-mcp.md): Read when defining an `agent()`, `mcpServer()`, `prompt()` or `resource()`.
46
+ - [Agent and MCP def shapes](llms/kinds-agent-mcp.md): Read when building an MCP server (tools, prompts, resources) or an `agent()`.
47
47
  - [Knowledge def shape](llms/kinds-knowledge.md): Read when the workspace defines a `knowledge()` item for its AI agents.
48
48
  - [Realtime def shapes](llms/kinds-realtime.md): Read when the workspace defines a `realtimeServer()`, `realtimeChannel()`, or `realtimeMessage()` handler.
49
49
  - [Triggers](llms/triggers.md): Read when authoring any trigger. A trigger's `stack` is a callback rather than the plain array every other kind takes, so the shape does not carry over.
@@ -498,6 +498,20 @@ Control flow & blocks (each nests a sub-stack; block specials name it `body`):
498
498
 
499
499
  Author with the factory, register on the Xano instance, lands under the payload key. Each line ends with a one-liner on what the primitive is.
500
500
 
501
+ ### Choosing a kind
502
+
503
+ Choose by who or what starts the work. Each rule names the kind that fits and the one it gets mistaken for.
504
+
505
+ - **Logic other code calls** → `defineFunction`, run with `s.function.run`. A `query` is the only kind an HTTP client reaches by verb + path; a `tool` is what an `agent()` or an MCP client calls. Logic serving two callers (an endpoint AND a tool) lives in one function both call.
506
+ - **Work on a timer** → `task` (cron or interval). **Work a request starts but does not wait for** → `s.function.run({ fn, runtime: { mode: "async-shared" } })`, which binds a job id, not the result (collect with `s.await`). **Work that follows a row change** → `tableTrigger`: it fires on every insert/update/delete of the table, whichever stack writes it, so the same side effect placed in one endpoint's stack misses every other write path.
507
+ - **The same steps before or after many objects** (an auth check, a rate limit, logging) → `middleware`, attached per host (`middleware: { pre, post }` on a query, function, task, tool or API group) or to every host of a kind with `workspaceConfig({ middleware: { query, function, task, tool } })` — not a function call repeated at the top of each stack.
508
+ - **Related rows on returned rows** → an `addon` attached to the read through its `addon: [{ addon, as, input }]` option (`db.query`/`get`/`add`/`edit`/`patch`), merged onto each row under `as` and typed in `InferResponse` — not a second read plus a loop that stitches rows together.
509
+ - **AI.** An LLM running inside the backend → `agent()`, started from a stack with `s.ai.agent.run`; it has no public endpoint. An external AI client (Claude, Cursor, any MCP client) calling the backend → `mcpServer()`. Standing instructions for Xano's own builder AI → `knowledge()`; an `agent()` run never reads it. The actions either one calls → `tool()`. What an MCP server serves besides tools (`prompt()`, `resource()`) and when each fits: `llms/kinds-agent-mcp.md`.
510
+ - **Pushing to connected clients** → `realtimeServer` → `realtimeChannel` → `realtimeMessage` (the handler for a frame a client sends — the realtime analogue of a query). A server-side push from any stack is `s.realtime.publish`; a client polling a `query` is the substitute this replaces.
511
+ - **Code the typed surface cannot express** → a lambda (`s.lambda`, `fl.lambda`) for a short JavaScript body, LAST, after native filters and expressions (`llms/lambda.md`); a `microservice` for a long-running container or another language; `s.api.request` for a service that already has an HTTP API.
512
+ - **Tests** → `tests` on a `query`/`defineFunction`/`middleware` for that one object's input → output; a `workflowTest` for a flow across objects (`s.function.call`, `s.api.call`, `s.task.call`) asserted with `s.expect.*`.
513
+ - **Reacting to the platform** → `errorTrigger` (an error signature first seen, regressing, or marked fixed) and `workspaceTrigger` (branch new/merge/live). What one connection to an MCP server, agent, realtime server or channel may see or do → that object's connection trigger.
514
+
501
515
  ⚠ Composing a workspace from independently-authored modules: `register*` takes its defs however they arrive, but `modules.flatMap((m) => m.tables)` does NOT typecheck. `Array.prototype.flatMap` binds its element type to the FIRST element, so every later module's tables are checked against that one table's schema — the error compares two unrelated column names and mentions neither `flatMap` nor the cause. `.concat()` collapses the same way. Two spellings work: pass an array LITERAL (`registerTables([...a.tables, ...b.tables])` — spreads are fine, TypeScript infers the union across every element at once), or annotate the module array with the wide aliases `AnyTableDef` / `AnyQueryDef` / `AnyFunctionDef` / `AnyAddonDef`, exported for exactly the four def types whose generics can collapse this way. Widening the array costs nothing: the typing you need lives on the `table()`/`query()` handle you hold and pass to `s.db.*`, and is never read back off the registered array.
502
516
 
503
517
  - function: `defineFunction` → `Xano.registerFunctions` → payload `function` — Reusable server-side logic (a custom function) callable from any stack via `s.function.run`.
@@ -849,15 +863,16 @@ The run is isolated in ways that make a correct test fail for reasons the failur
849
863
 
850
864
  # Agent and MCP def shapes
851
865
 
852
- > Read when defining an `agent()`, `mcpServer()`, `prompt()` or `resource()`.
866
+ > Read when building an MCP server (tools, prompts, resources) or an `agent()`.
853
867
 
868
+ - An MCP server serves THREE primitives, and each reaches the client differently: a `tool()` is an action the MODEL calls (it may write); a `resource()` is read-only context the client APPLICATION lists and attaches by `uri` (reference docs, a schema, one record through a `{variable}` template); a `prompt()` is a message template with arguments the USER picks by name. Context a session opens with is a `resource()`; a workflow a user starts by name is a `prompt()`; data the model must fetch on its own mid-task stays a `tool()`, since a client shows the model only the resources attached to the conversation. Register each kind (`registerTools`/`registerPrompts`/`registerResources`) and list it on the server.
854
869
  - `mcpServer({ name, guid?, description?, instructions?, docs?, enabled?, canonical?, spec?, tags?, history?, tools?, prompts?, resources?, oauth?, llm?, output? })` — an MCP toolset. `llm?`/`output?` are the same blocks `agent()` takes and are usually absent: an MCP server and an agent are ONE stored object distinguished by `type`. Returns a handle with `getPath()`/`getUrl(baseUrl)` for the Streamable-HTTP endpoint — `getUrl` is NOT idempotent, a `baseUrl` already carrying an `/x2/mcp/<…>/stream` path THROWS, so resolve ONCE from the instance base URL. Fires on an ephemeral. A TENANT rides AFTER the prefix (`/x2/mcp/tenant/<tenant>/<canonical>/<token>/stream`), not as a base-URL segment: `getUrl` LIFTS a `/tenant/<name>` out of the base and re-places it there, so `getUrl(window.XANO_HOST)` is correct as-is; concatenating them by hand builds an unregistered route that 404s. Pass `{ tenant }` when the base URL cannot name it (a tenant on its own domain).
855
870
  - `tools?`: a `ToolsetToolEntry[]`. Pass the `tool()` HANDLES directly (`tools: [saveNote]`); use the `{ tool, enabled?, auth?, type?, resourceUri?, toolMeta? }` wrapper when an entry needs more. `type: "resource"` (+ a required `resourceUri`) is the LEGACY way to publish a tool as an MCP resource — author a `resource()` and list it in `resources` instead; `toolMeta` is extra metadata on a tool entry. The two payload fields are per-type and supplying the other one is refused, because the engine stores it against neither. `auth` names an auth **table** (a `table({ auth: true })` handle or its name) — per-tool, and the only gate there is. ⚠ It is also what gives the tool a CALLER, on an `agent()` exactly as on an MCP server. `auth()` inside a tool whose entry names no table does NOT return null: the call answers a normal result carrying `{"code":"ERROR_FATAL","message":""}`, so the model reads a successful tool result and reports success while nothing is written. A caller token does not rescue it — the ENTRY supplies identity. Spell it `{ tool: saveNote, auth: users }`; `export()` warns. An entry naming no tool THROWS at export; a deliberate raw `id: 0` warns and carries through.
856
871
  - `prompts?` / `resources?`: `prompt()` / `resource()` HANDLES (or names), or a `{ prompt, enabled?, auth? }` / `{ resource, enabled?, auth? }` wrapper. `auth` names the auth table and is what gives the stack a caller: a prompt/resource reading `auth()` behind an entry with none answers every `prompts/get` / `resources/read` with `-32603 "Access Denied"` (`export()` warns `toolset.primitive-reads-auth-ungated`). Listing one target twice THROWS; two resources with one `uri` on one server fail `export()` (`mcp.resource-uri-duplicate`). MCP-server only — `agent()` takes tools only.
857
872
  - `history?` is the server tier for its tools, prompts AND resources alike; an object's own `history` wins. The workspace tier (`workspaceConfig({ history })`) has `prompt` and `resource` keys, both default on.
858
873
  - `oauth?`: per-server sign-in; omit and nothing changes. Union on `mode`; `authTable` (REQUIRED, auth `table()` handle or name) is whose row the signed-in user is — `auth()` on the whole server, `t.auth` in its trigger. Hosted (the platform is the authorization server): `{ mode: "hosted", authTable, loginUrl }` — clients are sent to `loginUrl` (YOUR page, which is also the consent screen) with `mcp_request`; show `s.mcp.oauth.request`, sign the user in, then your endpoint calls `s.mcp.oauth.complete` with their `decision` and the page redirects to the URL it binds. External (your IdP issues tokens): `{ mode: "external", authTable, issuer, column, audience?, audienceAck?, claim?, claimAck?, preset?, allowedClientIds? }` — token `claim` (default `sub`) matched against `column`; `preset` is `auth0|clerk|workos|entra|okta|cognito|generic`. `loginUrl`/`issuer`/`audience` take `env("NAME")` (resolved per environment).
859
874
  - `export()` FAILS: hosted without `loginUrl` (`mcp.oauth-hosted-incomplete`); external without `issuer`/`column` (`mcp.oauth-external-incomplete`); `preset: "clerk"` without `allowedClientIds` (`mcp.oauth-preset-client-ids`); `claim` other than `sub`/`oid`/`email` without `claimAck` (`mcp.oauth-claim-unacked` — users can edit it at most providers). Unknown `mode`/`preset` THROWS; so do the dropped `consent`/`branding`/`trustedClients`.
860
- - `prompt({ name, guid?, description?, docs?, title?, icons?, tags?, history?, input?, stack?, response?, responseShape?, middleware? })` — an MCP prompt; takes `registerPrompts`. `input` is the prompt's arguments (each field's `description`/`required`/enum `values` reach the client; enum values also answer completion requests). `response`: a text value is ONE user message; a list of `{ role: "user" | "assistant", content }` is sent in order: `s.set_var("m", obj({ list: [obj({ role: c.text("user"), content: ref("body") })] }))`, `response: ref("m.list")`. Without `response` or a top-level `s.return`, `prompts/get` fails.
875
+ - `prompt({ name, guid?, description?, docs?, title?, icons?, tags?, history?, input?, stack?, response?, responseShape?, middleware? })` — an MCP prompt; takes `registerPrompts`. `input` is the prompt's arguments (each field's `description`/`required`/enum `values` reach the client; enum values also answer completion requests). `response`: a text value is ONE user message; a list of `{ role: "user" | "assistant", content }` is sent in order, `content` a string or an MCP content block: `s.set_var("m", obj({ list: [obj({ role: c.text("user"), content: ref("body") })] }))`, `response: ref("m.list")`. Without `response` or a top-level `s.return`, `prompts/get` fails.
861
876
  - `resource({ name, uri, guid?, description?, docs?, mimeType?, title?, icons?, annotations?, tags?, history?, input?, stack?, response?, responseShape?, middleware? })` — an MCP resource; takes `registerResources`. Clients address it by `uri`, never `name`.
862
877
  - `uri`: a literal (`"docs://readme"`, no `input`) or an RFC 6570 LEVEL-1 template (`"orders://{region}/{order_id}"`). It must start with a scheme; each `{variable}` is letters/digits/`_`, one per brace pair, never two adjacent. `input` must be EXACTLY the template's variables, each a single `text`/`int`/`decimal`/`bool`/`enum`/`email`/`uuid` — anything else THROWS. A value that does not convert is refused before the stack runs.
863
878
  - `response`: a string is returned as text; non-UTF-8 content (a file, binary) as a base64 blob. `mimeType?` omitted → derived from what the stack returns.
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # xanosdk v1.0.8
1
+ # xanosdk v1.0.9
2
2
 
3
3
  > TypeScript SDK that compiles a typed Xano workspace into the importable packageExport JSON bundle.
4
4
 
@@ -43,7 +43,7 @@ plain file read resolves them at the version you have.
43
43
  - [Toolchain modules](llms/toolchain.md): Read when `package.json` has a `"xanosdk"` block or you run `xanosdk marketplace`.
44
44
  - [Error index](llms/errors.md): Read when a request, test, build, or pull fails with a message you did not write — the string, its cause, and where the fix is.
45
45
  - [Saved unit tests, assertions, and mocks](llms/tests.md): Read when authoring a `workflowTest()` stack, when a query/function/middleware carries `tests`, when a statement needs a `mock`, or when running a deployed environment's tests.
46
- - [Agent and MCP def shapes](llms/kinds-agent-mcp.md): Read when defining an `agent()`, `mcpServer()`, `prompt()` or `resource()`.
46
+ - [Agent and MCP def shapes](llms/kinds-agent-mcp.md): Read when building an MCP server (tools, prompts, resources) or an `agent()`.
47
47
  - [Knowledge def shape](llms/kinds-knowledge.md): Read when the workspace defines a `knowledge()` item for its AI agents.
48
48
  - [Realtime def shapes](llms/kinds-realtime.md): Read when the workspace defines a `realtimeServer()`, `realtimeChannel()`, or `realtimeMessage()` handler.
49
49
  - [Triggers](llms/triggers.md): Read when authoring any trigger. A trigger's `stack` is a callback rather than the plain array every other kind takes, so the shape does not carry over.
package/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xanosdk",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "TypeScript SDK that compiles a typed Xano workspace into the importable packageExport JSON bundle.",
5
5
  "coverage": {
6
6
  "objectKinds": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xano/sdk",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Xano SDK — your Xano backend as TypeScript. `xanosdk deploy` ships your typed workspace (and an optional static frontend) to a live, auto-expiring ephemeral environment and prints its URL. init → deploy → URL.",
5
5
  "keywords": [
6
6
  "xanosdk",
@@ -14,8 +14,8 @@ description: >-
14
14
  FastAPI) unless the user asks for Xano.
15
15
  license: MIT
16
16
  metadata:
17
- xanosdk-version: "1.0.8"
18
- xanosdk-digest: "sha256:1473ad316197d3149c9222c5e54e206572a25319536a7fb2f3f22443db2c1088"
17
+ xanosdk-version: "1.0.9"
18
+ xanosdk-digest: "sha256:4c4c096cd062d4c4cf8066389104c392ea35aac52bffbd8220da4544f0d71f00"
19
19
  ---
20
20
 
21
21
  # Xano backend