@spacefast/common 0.0.5 → 0.0.7

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 (183) hide show
  1. package/brand-assets/spacefast-favicon.svg +16 -0
  2. package/brand-assets/spacefast-sf-full-bleed.svg +13 -0
  3. package/brand-assets/spacefast-wordmark.svg +5 -0
  4. package/dist/agents/connect-targets.d.ts +138 -0
  5. package/dist/agents/connect-targets.js +243 -0
  6. package/dist/brand-assets-build.d.ts +26 -0
  7. package/dist/brand-assets-build.js +81 -0
  8. package/dist/brand-assets.d.ts +42 -0
  9. package/dist/brand-assets.js +30 -0
  10. package/dist/brand.d.ts +1 -0
  11. package/dist/brand.js +5 -0
  12. package/dist/config/domains.d.ts +12 -6
  13. package/dist/config/domains.js +30 -38
  14. package/dist/contracts/access.d.ts +967 -124
  15. package/dist/contracts/access.js +804 -148
  16. package/dist/contracts/activity.d.ts +1 -1
  17. package/dist/contracts/activity.js +28 -2
  18. package/dist/contracts/annotations.d.ts +2 -4
  19. package/dist/contracts/api-keys.d.ts +126 -4
  20. package/dist/contracts/api-keys.js +74 -6
  21. package/dist/contracts/archives.d.ts +8 -2
  22. package/dist/contracts/archives.js +11 -4
  23. package/dist/contracts/billing.d.ts +0 -9
  24. package/dist/contracts/builds.d.ts +65 -21
  25. package/dist/contracts/builds.js +29 -0
  26. package/dist/contracts/common.d.ts +2 -0
  27. package/dist/contracts/common.js +4 -0
  28. package/dist/contracts/continuation.d.ts +0 -3
  29. package/dist/contracts/countries.d.ts +2 -0
  30. package/dist/contracts/countries.js +261 -0
  31. package/dist/contracts/deployments.d.ts +34 -34
  32. package/dist/contracts/device-auth.d.ts +4 -11
  33. package/dist/contracts/device-auth.js +4 -0
  34. package/dist/contracts/docs.d.ts +119 -0
  35. package/dist/contracts/docs.js +51 -0
  36. package/dist/contracts/domains.d.ts +96 -54
  37. package/dist/contracts/domains.js +26 -4
  38. package/dist/contracts/enums.d.ts +15 -16
  39. package/dist/contracts/enums.js +26 -14
  40. package/dist/contracts/error-code-meta.d.ts +184 -0
  41. package/dist/contracts/error-code-meta.js +124 -10
  42. package/dist/contracts/error-codes.d.ts +1 -1
  43. package/dist/contracts/error-codes.js +42 -0
  44. package/dist/contracts/events.d.ts +1 -1
  45. package/dist/contracts/feature-lifecycle-core.d.ts +36 -0
  46. package/dist/contracts/feature-lifecycle-core.js +220 -0
  47. package/dist/contracts/feature-lifecycle.d.ts +7 -0
  48. package/dist/contracts/feature-lifecycle.js +31 -0
  49. package/dist/contracts/features.d.ts +76 -6
  50. package/dist/contracts/features.js +178 -13
  51. package/dist/contracts/generated-feature-launch-entries.d.ts +2 -0
  52. package/dist/contracts/generated-feature-launch-entries.js +518 -0
  53. package/dist/contracts/git.d.ts +2 -8
  54. package/dist/contracts/ids.d.ts +9 -0
  55. package/dist/contracts/ids.js +13 -0
  56. package/dist/contracts/mcp.d.ts +8 -10
  57. package/dist/contracts/me.js +1 -1
  58. package/dist/contracts/oauth-resources.d.ts +19 -8
  59. package/dist/contracts/oauth-resources.js +44 -13
  60. package/dist/contracts/operations.d.ts +161 -1
  61. package/dist/contracts/operations.js +49 -1
  62. package/dist/contracts/platform.d.ts +6 -102
  63. package/dist/contracts/platform.js +6 -50
  64. package/dist/contracts/publishes.d.ts +130 -0
  65. package/dist/contracts/publishes.js +145 -0
  66. package/dist/contracts/push-new.d.ts +4 -4
  67. package/dist/contracts/quotas.d.ts +2 -0
  68. package/dist/contracts/quotas.js +8 -0
  69. package/dist/contracts/repository-connections.d.ts +9 -8
  70. package/dist/contracts/repository-connections.js +13 -0
  71. package/dist/contracts/resources.d.ts +99 -13
  72. package/dist/contracts/resources.js +36 -4
  73. package/dist/contracts/routes.d.ts +0 -2
  74. package/dist/contracts/runtime-api.d.ts +363 -39
  75. package/dist/contracts/runtime-api.js +276 -6
  76. package/dist/contracts/sf-config-v1.d.ts +75 -0
  77. package/dist/contracts/sf-config-v1.js +6 -0
  78. package/dist/contracts/sites.d.ts +19 -2
  79. package/dist/contracts/sites.js +21 -0
  80. package/dist/contracts/space-config.d.ts +201 -2
  81. package/dist/contracts/space-config.js +135 -5
  82. package/dist/contracts/spaces.d.ts +376 -196
  83. package/dist/contracts/spaces.js +62 -10
  84. package/dist/contracts/superadmin-emails.d.ts +4 -2
  85. package/dist/contracts/superadmin-emails.js +8 -0
  86. package/dist/contracts/superadmin-queues.d.ts +26 -26
  87. package/dist/contracts/superadmin-spaces.d.ts +172 -42
  88. package/dist/contracts/superadmin-tenants.d.ts +6 -6
  89. package/dist/contracts/superadmin-tenants.js +6 -11
  90. package/dist/contracts/superadmin.d.ts +6 -93
  91. package/dist/contracts/superadmin.js +6 -14
  92. package/dist/contracts/tags.d.ts +10 -9
  93. package/dist/contracts/tags.js +2 -1
  94. package/dist/contracts/teams.d.ts +26 -30
  95. package/dist/contracts/teams.js +11 -17
  96. package/dist/contracts/theme-json.d.ts +30 -0
  97. package/dist/contracts/theme-json.js +48 -0
  98. package/dist/contracts/variables.d.ts +0 -2
  99. package/dist/contracts/variables.js +0 -5
  100. package/dist/contracts/webhooks.d.ts +2 -0
  101. package/dist/contracts/webhooks.js +1 -1
  102. package/dist/contracts/zero.d.ts +5 -10
  103. package/dist/docs/agent-prose.d.ts +43 -3
  104. package/dist/docs/agent-prose.js +146 -7
  105. package/dist/docs/agent-setup.d.ts +51 -0
  106. package/dist/docs/agent-setup.js +211 -14
  107. package/dist/docs/agent-solutions.d.ts +5 -5
  108. package/dist/docs/agent-solutions.js +2 -2
  109. package/dist/docs/catalog.d.ts +650 -0
  110. package/dist/docs/catalog.js +758 -0
  111. package/dist/docs/error-docs.d.ts +0 -2
  112. package/dist/docs/error-docs.js +189 -35
  113. package/dist/docs/index-build.d.ts +17 -0
  114. package/dist/docs/index-build.js +24 -0
  115. package/dist/docs/search.d.ts +54 -0
  116. package/dist/docs/search.js +96 -0
  117. package/dist/docs/skill-distribution.d.ts +5 -3
  118. package/dist/docs/skill-distribution.js +8 -8
  119. package/dist/slug-policy/blocklist.d.ts +4 -0
  120. package/dist/slug-policy/blocklist.js +122 -0
  121. package/dist/slug-policy/index.d.ts +17 -0
  122. package/dist/slug-policy/index.js +86 -0
  123. package/dist/utils/access-match.d.ts +39 -0
  124. package/dist/utils/access-match.js +296 -0
  125. package/dist/utils/auth-redirect.d.ts +3 -1
  126. package/dist/utils/auth-redirect.js +21 -1
  127. package/dist/utils/build-settings.d.ts +6 -0
  128. package/dist/utils/build-settings.js +429 -46
  129. package/dist/utils/claim-token.d.ts +8 -0
  130. package/dist/utils/claim-token.js +23 -2
  131. package/dist/utils/concurrency.d.ts +1 -0
  132. package/dist/utils/concurrency.js +22 -0
  133. package/dist/utils/content-type.d.ts +1 -0
  134. package/dist/utils/content-type.js +1 -1
  135. package/dist/utils/credential-policy.d.ts +54 -0
  136. package/dist/utils/{access-policy.js → credential-policy.js} +28 -2
  137. package/dist/utils/email.d.ts +1 -0
  138. package/dist/utils/email.js +3 -0
  139. package/dist/utils/gate-theme.d.ts +61 -0
  140. package/dist/utils/gate-theme.js +217 -0
  141. package/dist/utils/git-repository.d.ts +0 -1
  142. package/dist/utils/git-repository.js +0 -3
  143. package/dist/utils/id-hints.d.ts +8 -0
  144. package/dist/utils/id-hints.js +61 -0
  145. package/dist/utils/local-space-state.d.ts +91 -0
  146. package/dist/utils/local-space-state.js +251 -0
  147. package/dist/utils/oauth-signed-query.d.ts +8 -0
  148. package/dist/utils/oauth-signed-query.js +26 -0
  149. package/dist/utils/publish-detection.d.ts +0 -8
  150. package/dist/utils/publish-detection.js +0 -93
  151. package/dist/utils/publish-policy.d.ts +6 -5
  152. package/dist/utils/publish-policy.js +71 -7
  153. package/dist/utils/query-keys.d.ts +16 -4
  154. package/dist/utils/query-keys.js +31 -4
  155. package/dist/utils/runtime-paths.d.ts +0 -1
  156. package/dist/utils/runtime-paths.js +0 -1
  157. package/dist/utils/runtime-upload-batch.d.ts +18 -0
  158. package/dist/utils/runtime-upload-batch.js +90 -0
  159. package/dist/utils/runtime-upload.d.ts +2 -0
  160. package/dist/utils/runtime-upload.js +5 -0
  161. package/dist/utils/sf-config-v1.d.ts +2 -0
  162. package/dist/utils/sf-config-v1.js +542 -0
  163. package/dist/utils/space-config.d.ts +4 -0
  164. package/dist/utils/space-config.js +10 -1
  165. package/dist/utils/space-theme.d.ts +2 -0
  166. package/dist/utils/space-theme.js +9 -0
  167. package/dist/utils/static-runtime-policy.d.ts +0 -21
  168. package/dist/utils/static-runtime-policy.js +19 -103
  169. package/dist/utils/upload-session.d.ts +1 -1
  170. package/dist/utils/wpcom-auth-redirects.d.ts +32 -2
  171. package/dist/utils/wpcom-auth-redirects.js +26 -10
  172. package/dist/vocabulary.d.ts +130 -30
  173. package/dist/vocabulary.js +77 -36
  174. package/package.json +35 -1
  175. package/dist/contracts/account.d.ts +0 -28
  176. package/dist/contracts/account.js +0 -54
  177. package/dist/contracts/intercom.d.ts +0 -6
  178. package/dist/contracts/intercom.js +0 -5
  179. package/dist/contracts/telemetry.d.ts +0 -2
  180. package/dist/contracts/telemetry.js +0 -1
  181. package/dist/utils/access-policy.d.ts +0 -39
  182. package/dist/utils/error-display.d.ts +0 -7
  183. package/dist/utils/error-display.js +0 -42
@@ -1,11 +1,176 @@
1
- import { BRAND } from "@spacefast/common/brand";
2
- import { PUBLISH_SEQUENCE_PROSE, RECEIPT_SHAPE_PROSE, SECRET_RULES_PROSE, SIGNED_UPLOAD_PROSE, } from "@spacefast/common/docs/agent-prose";
3
- import { spacefastInstallCurlCommand, spacefastInstallPowerShellCommand, spacefastSkillInstallCommand, spacefastSkillUrl, } from "@spacefast/common/docs/skill-distribution";
1
+ import { getConnectTarget, } from "../agents/connect-targets.js";
2
+ import { BRAND } from "../brand.js";
3
+ import { CHECK_BEFORE_PUBLISH_PROSE, CONTINUE_AFTER_CLAIM_PROSE, ENV_NOTES_PROSE, FAILURE_CONDUCT_PROSE, HOW_TO_RESEARCH_PROSE, LANE_PICKER_PROSE, POSITIONING_PROSE, PUBLISH_SEQUENCE_PROSE, RECEIPT_SHAPE_PROSE, SAVE_STATE_PROSE, SECRET_RULES_PROSE, SIGNED_UPLOAD_PROSE, UPDATE_SPACE_PROSE, } from "./agent-prose.js";
4
+ import { spacefastInstallCurlCommand, spacefastInstallPowerShellCommand, spacefastSkillFetchCommand, spacefastSkillInstallCommand, spacefastSkillUrl, } from "./skill-distribution.js";
4
5
  export const agentSetupUrl = `${BRAND.agentSetupOrigin}/ai`;
5
6
  export const agentSetupTextUrl = `${BRAND.agentSetupOrigin}/ai.txt`;
6
7
  const agentSetupParsedUrl = new URL(agentSetupUrl);
7
8
  export const agentSetupHostLabel = agentSetupParsedUrl.host + agentSetupParsedUrl.pathname;
8
- export const agentSetupPrompt = `Fetch ${agentSetupUrl} and follow the instructions to publish for me. Ask me what I want to publish if it isn't obvious.`;
9
+ export const agentSetupPrompt = `Fetch ${agentSetupUrl} and follow it to publish this project — or update it if it's already on ${BRAND.productName}. Ask me what I want to publish if it isn't obvious.`;
10
+ /*
11
+ * Agent handoff contract: links use https://<app-origin>/agent/<documentId>#<secret>, with
12
+ * opaque document IDs and secrets. The fragment is the secret, so ordinary document fetches
13
+ * never send or reveal it. Fetching never consumes a handoff; exactly one successful redemption
14
+ * does. Redemption is app-private, reuses the existing device/OAuth approval service, and returns
15
+ * the already-approved finite Space-scoped credential: there is no public AgentGrant resource,
16
+ * durable key table, or team-wide publisher key. The CLI accepts links only through stdin or a
17
+ * browser callback and redacts them from JSON output, telemetry, shell history, doctor, and
18
+ * receipts. The dashboard can revoke an unused handoff.
19
+ */
20
+ const opaqueHandoffDocumentId = /^[A-Za-z0-9_-]{1,512}$/;
21
+ const opaqueHandoffSecret = /^[A-Za-z0-9_-]{16,512}$/;
22
+ const shellSafeMcpEndpoint = /^[A-Za-z0-9%+,\-./:=_[\]~]+$/;
23
+ /**
24
+ * Typed, safe decline states for the app-private redemption exchange.
25
+ * `invalid_handoff` is the single answer for both an unknown document ID and a wrong secret, so a
26
+ * decline never becomes an existence oracle; state-specific reasons are returned only after the
27
+ * supplied secret authenticates the handoff. `already_redeemed` makes one-use explicit: after the
28
+ * first exchange succeeds, the second fails with this reason. Declines are terminal and never
29
+ * reveal whether a secret was close to correct.
30
+ */
31
+ export const AGENT_HANDOFF_DECLINE_REASONS = [
32
+ "invalid_handoff",
33
+ "expired",
34
+ "already_redeemed",
35
+ "revoked",
36
+ "client_mismatch",
37
+ "origin_mismatch",
38
+ ];
39
+ function isSafeHttpUrl(url) {
40
+ return ((url.protocol === "https:" ||
41
+ (url.protocol === "http:" &&
42
+ (url.hostname === "localhost" ||
43
+ url.hostname === "127.0.0.1" ||
44
+ url.hostname === "[::1]"))) &&
45
+ !url.username &&
46
+ !url.password);
47
+ }
48
+ /**
49
+ * The single shared grammar for handoff links:
50
+ * `https://<app-origin>/agent/<documentId>#<secret>`. The document ID must match
51
+ * `[A-Za-z0-9_-]{1,512}` and the secret `[A-Za-z0-9_-]{16,512}` (the minimum keeps secrets
52
+ * high-entropy and makes the public-projection leak check meaningful); the two must differ;
53
+ * queries and embedded credentials are forbidden; HTTPS is required except on loopback hosts.
54
+ * Normalization is part of the contract: the input is WHATWG-URL-normalized first (backslashes,
55
+ * dot segments, stray tab/CR/LF, empty userinfo, case, default ports), the grammar is enforced on
56
+ * the normalized URL, and only the reconstructed canonical URL ever leaves this function.
57
+ * Dashboard minting, CLI ingestion, and control-plane validation must all use this parser so the
58
+ * grammar can never fork.
59
+ */
60
+ export function parseAgentHandoffUrl(value, expectedOrigin) {
61
+ let canonicalExpectedOrigin;
62
+ try {
63
+ canonicalExpectedOrigin = new URL(expectedOrigin).origin;
64
+ }
65
+ catch {
66
+ throw new TypeError("Agent handoff expectedOrigin must be a valid URL origin.");
67
+ }
68
+ let url;
69
+ try {
70
+ url = new URL(value);
71
+ }
72
+ catch {
73
+ throw new TypeError("Agent handoff URL must be a valid HTTP(S) URL.");
74
+ }
75
+ const documentId = /^\/agent\/([^/]+)$/.exec(url.pathname)?.[1];
76
+ const secret = url.hash.slice(1);
77
+ if (!isSafeHttpUrl(url) ||
78
+ url.origin !== canonicalExpectedOrigin ||
79
+ value.includes("?") ||
80
+ !documentId ||
81
+ !opaqueHandoffDocumentId.test(documentId) ||
82
+ !opaqueHandoffSecret.test(secret) ||
83
+ documentId === secret) {
84
+ throw new TypeError("Agent handoff URL must be an HTTPS /agent/<id> URL with one opaque fragment secret (16-512 chars, distinct from the id) and no credentials or query (HTTP is allowed on loopback hosts).");
85
+ }
86
+ return { documentId, documentUrl: `${url.origin}${url.pathname}`, secret };
87
+ }
88
+ function validateMcpEndpoint(value) {
89
+ let url;
90
+ try {
91
+ url = new URL(value);
92
+ }
93
+ catch {
94
+ throw new TypeError("MCP endpoint must be a valid HTTP(S) URL.");
95
+ }
96
+ if (!shellSafeMcpEndpoint.test(value) || !isSafeHttpUrl(url)) {
97
+ throw new TypeError("MCP endpoint must be a shell-safe HTTPS URL with no credentials, query, fragment, or control characters (HTTP is allowed on loopback hosts).");
98
+ }
99
+ return url.href.replace(/\/$/, "");
100
+ }
101
+ function renderAgentHandoffInstructions(documentUrl, target) {
102
+ const setupSections = [target.primary, target.config].flatMap((setup) => setup ? [[setup.label, `\`\`\`${setup.language}`, setup.value, "```"].join("\n")] : []);
103
+ const connectSections = [
104
+ target.blurb,
105
+ ...setupSections,
106
+ target.deeplink ? `${target.deeplink.label}: ${target.deeplink.href}` : null,
107
+ target.download ? `${target.download.label}: ${target.download.href}` : null,
108
+ ].filter((section) => section !== null);
109
+ const approvalGuidance = target.id === "claude-code" || target.id === "codex"
110
+ ? `Run \`sf setup agent\` to initiate the handoff exchange; if \`sf\` is missing, install it first (macOS/Linux: \`${spacefastInstallCurlCommand}\`; Windows PowerShell: \`${spacefastInstallPowerShellCommand}\`). When it asks for the handoff link on stdin, paste the original link into that prompt; never pass the link as an argv value. Ask the user to approve in the browser, then wait for the CLI's approval result before publishing.`
111
+ : "When the client opens browser approval, ask the user to approve there before publishing.";
112
+ const sections = [
113
+ `# Set up ${BRAND.productName} with ${target.name}`,
114
+ `This is the public setup document for ${documentUrl}.`,
115
+ "Talk to the user before installing tools or publishing. Confirm the file or folder they want to make public.",
116
+ ["## Connect", ...connectSections].join("\n\n"),
117
+ [
118
+ "## Continue the approved handoff",
119
+ "Keep the original handoff link private. Fetching this document did not use the link or send its fragment secret; the secret is spent only by one successful exchange. An expired, used, or revoked link fails safely, so ask the user for a fresh one from the dashboard.",
120
+ approvalGuidance,
121
+ "Keep its fragment out of commands, request URLs, logs, and replies.",
122
+ ].join("\n\n"),
123
+ [
124
+ "## Publish",
125
+ "After approval, confirm the selected Space and permissions, then publish only the files the user approved. Share the live URL and immutable version URL from the receipt.",
126
+ ].join("\n\n"),
127
+ `General agent instructions: ${agentSetupTextUrl}`,
128
+ ];
129
+ return `${sections.join("\n\n")}\n`;
130
+ }
131
+ /** Builds every copy-ready handoff artifact from one validated URL and target catalog row. */
132
+ export function buildAgentHandoff(input) {
133
+ const { documentUrl, secret } = parseAgentHandoffUrl(input.url, input.expectedOrigin);
134
+ const mcpEndpoint = validateMcpEndpoint(input.mcpEndpoint);
135
+ const target = getConnectTarget(input.targetId, {
136
+ mcpEndpoint,
137
+ });
138
+ const prompt = `Fetch ${documentUrl}#${secret} and follow the ${target.name} setup instructions to publish with ${BRAND.productName}. Ask me what I want to publish if it isn't obvious.`;
139
+ const instructions = renderAgentHandoffInstructions(documentUrl, target);
140
+ const actions = [
141
+ { kind: "copy", label: "Copy for my agent", sensitive: true, value: prompt },
142
+ { kind: "copy", label: "Copy Markdown", sensitive: false, value: instructions },
143
+ ];
144
+ if (target.deeplink) {
145
+ actions.push({
146
+ kind: "open",
147
+ label: target.deeplink.label,
148
+ href: target.deeplink.href,
149
+ });
150
+ }
151
+ if (target.download) {
152
+ actions.push({
153
+ kind: "open",
154
+ label: target.download.label,
155
+ href: target.download.href,
156
+ });
157
+ }
158
+ // The scanner-safe invariant is total, not statistical: no public projection may contain the
159
+ // secret, no matter what the caller fed in (a pathological mint, a poisoned MCP endpoint).
160
+ const publicProjections = [
161
+ documentUrl,
162
+ instructions,
163
+ ...actions.flatMap((action) => {
164
+ if (action.kind === "open")
165
+ return [action.href];
166
+ return action.sensitive ? [] : [action.value];
167
+ }),
168
+ ];
169
+ if (publicProjections.some((projection) => projection.includes(secret))) {
170
+ throw new TypeError("Agent handoff inputs would leak the fragment secret into a public projection.");
171
+ }
172
+ return { actions, documentUrl, instructions, prompt };
173
+ }
9
174
  export function renderAgentSetupTemplate(value) {
10
175
  return value
11
176
  .replaceAll("{{AGENT_SETUP_URL}}", agentSetupUrl)
@@ -19,9 +184,13 @@ export function aiInstructionsText() {
19
184
  return [
20
185
  `# ${BRAND.productName} for AI agents`,
21
186
  "",
22
- `Official instructions for AI agents publishing to ${BRAND.productName}, the static host where`,
23
- "AI-made things are kept: permanent URLs, immutable versions, anonymous publish",
24
- "with a claim link. Static files only — server code is never executed.",
187
+ `Official instructions for AI agents publishing to ${BRAND.productName}.`,
188
+ "",
189
+ POSITIONING_PROSE,
190
+ "",
191
+ "## Before you publish (check for an existing space)",
192
+ "",
193
+ CHECK_BEFORE_PUBLISH_PROSE,
25
194
  "",
26
195
  "## Publish with curl (no install, no account)",
27
196
  "",
@@ -29,6 +198,14 @@ export function aiInstructionsText() {
29
198
  "",
30
199
  RECEIPT_SHAPE_PROSE,
31
200
  "",
201
+ "## Save your state",
202
+ "",
203
+ SAVE_STATE_PROSE,
204
+ "",
205
+ "## Update a space",
206
+ "",
207
+ UPDATE_SPACE_PROSE,
208
+ "",
32
209
  "## Big files and cloud agents",
33
210
  "",
34
211
  SIGNED_UPLOAD_PROSE,
@@ -37,6 +214,14 @@ export function aiInstructionsText() {
37
214
  "",
38
215
  SECRET_RULES_PROSE,
39
216
  "",
217
+ "## Failure conduct",
218
+ "",
219
+ FAILURE_CONDUCT_PROSE,
220
+ "",
221
+ "## How to research",
222
+ "",
223
+ HOW_TO_RESEARCH_PROSE,
224
+ "",
40
225
  'Add a bearer access token with `-H "Authorization: Bearer ..."` to publish into the user\'s',
41
226
  "team instead of anonymously. Agent clients should prefer OAuth client credentials. Errors come back as JSON with stable `code` values and a",
42
227
  "`docsUrl`; fetch the `docsUrl` when you need recovery steps.",
@@ -69,15 +254,17 @@ export function aiInstructionsText() {
69
254
  "```",
70
255
  "",
71
256
  "Use `--json` on any command when the output will be parsed. Publishing the same",
72
- "directory again updates the space saved in `.stattic/state.json`.",
257
+ "directory again updates the space saved in `.spacefast/state.json`.",
73
258
  "",
74
259
  "## MCP for agent clients",
75
260
  "",
261
+ LANE_PICKER_PROSE,
262
+ "",
76
263
  "Hosted MCP is the no-download cloud lane for ChatGPT, Codex, Claude, Cursor, and browser",
77
264
  "clients that can authenticate with OAuth/API bearer credentials:",
78
265
  "",
79
266
  "```text",
80
- "https://mcp.spacefast.com/mcp",
267
+ "https://mcp.spacefast.com",
81
268
  "```",
82
269
  "",
83
270
  "Request `mcp:tools` plus the API scopes the tools need: `teams:read` for team context,",
@@ -98,8 +285,8 @@ export function aiInstructionsText() {
98
285
  "`spacefast://account/current`, `spacefast://teams/current`, `spacefast://spaces/recent`,",
99
286
  "`spacefast://spaces/{spaceId}`, and `spacefast://policy/current` for bounded read-only",
100
287
  "context.",
101
- "`execute_spacefast` is dry-run-first; mutating multi-step workflows can return",
102
- "`approval_required` and continue through `resume_spacefast` after the user approves.",
288
+ "`execute` is dry-run-first; mutating multi-step workflows can return",
289
+ "`approval_required` and continue through `resume` after the user approves.",
103
290
  "",
104
291
  "Use On-Device MCP when the agent needs the user's checkout, path-based publish, or file edits:",
105
292
  "",
@@ -115,15 +302,19 @@ export function aiInstructionsText() {
115
302
  "`SPACEFAST_AGENT_CONFIG` with private_key_jwt when available; otherwise use one-job",
116
303
  "`SPACEFAST_TOKEN` secrets and mask logs. Do not persist personal auth in ephemeral runners.",
117
304
  "",
118
- "If your environment supports skill import, fetch the official skill for the",
119
- `complete command reference: \`${spacefastSkillInstallCommand}\` (source: ${spacefastSkillUrl}).`,
305
+ "If your environment supports skill import, install the official skill:",
306
+ `\`${spacefastSkillInstallCommand}\`. Raw markdown source: \`${spacefastSkillFetchCommand}\` (${spacefastSkillUrl}).`,
120
307
  "",
121
308
  "## After publishing",
122
309
  "",
123
310
  "- Share the live URL, the immutable version URL when ready, and — for anonymous spaces —",
124
311
  " the claim link with its expiry. If the receipt's immutable URL is null, poll the",
125
312
  " operation and version links with the claim token as bearer auth until the version is ready.",
126
- "- Never print access tokens, claim tokens, auth files, or `.stattic/state.json`.",
313
+ "- Never print access tokens, claim tokens, auth files, or `.spacefast/state.json`.",
314
+ "",
315
+ "## After the user claims",
316
+ "",
317
+ CONTINUE_AFTER_CLAIM_PROSE,
127
318
  "",
128
319
  "## Space conventions",
129
320
  "",
@@ -152,14 +343,20 @@ export function aiInstructionsText() {
152
343
  "## Going deeper",
153
344
  "",
154
345
  "- Docs index for agents: https://spacefast.com/llms.txt",
346
+ "- One-click connect (Claude Code, Claude, Codex, Cursor, VS Code): https://spacefast.com/agents",
155
347
  "- Agent guide: https://spacefast.com/docs/agents",
156
348
  "- CLI reference: https://spacefast.com/docs/cli",
157
349
  "- REST API + OpenAPI: https://spacefast.com/docs/api",
158
350
  "- Publish contract (machine-readable): https://spacefast.com/publish-spec.json",
351
+ "- Connectors-directory manifest (hosted MCP listing): https://spacefast.com/.well-known/connector.json",
159
352
  "- Every error code: https://spacefast.com/docs/errors",
160
353
  "",
161
354
  "Append `.md` to any docs URL for Markdown, or just fetch — agent user agents get",
162
355
  "Markdown automatically.",
163
356
  "",
357
+ "## Environment notes",
358
+ "",
359
+ ENV_NOTES_PROSE,
360
+ "",
164
361
  ].join("\n");
165
362
  }
@@ -1,4 +1,4 @@
1
- export declare const hostedMcpEndpointUrl = "https://mcp.spacefast.com/mcp";
1
+ export declare const hostedMcpEndpointUrl = "https://mcp.spacefast.com";
2
2
  export type AgentSolutionLane = "plugin" | "hosted-mcp" | "local-mcp" | "cli" | "prompt";
3
3
  export type AgentSolutionId = "codex" | "claude-code" | "claude-cowork" | "chatgpt" | "claude-ai" | "raycast" | "cursor" | "terminal" | "generic";
4
4
  export type AgentSolution = {
@@ -20,7 +20,7 @@ export declare const agentSolutions: readonly [{
20
20
  readonly lane: "plugin";
21
21
  readonly summary: "Recommended: Codex plugin.";
22
22
  readonly description: "Install the Spacefast skill/plugin so Codex can publish, update, and inspect spaces from the same setup path.";
23
- readonly commands: readonly ["npx skills add spacefast/plugins --skill spacefast -g"];
23
+ readonly commands: readonly ["npx -y skills add spacefast/plugins --skill spacefast -g -a codex -y"];
24
24
  readonly guideUrl: `${string}/for-codex`;
25
25
  readonly detailGuideUrl: `${string}/guides/how-to-use-with-codex`;
26
26
  readonly setupText: string;
@@ -53,7 +53,7 @@ export declare const agentSolutions: readonly [{
53
53
  readonly lane: "hosted-mcp";
54
54
  readonly summary: "Recommended: direct hosted MCP.";
55
55
  readonly description: "Connect ChatGPT-style cloud agents to Spacefast through hosted MCP; use the virtual workspace or signed uploads instead of local paths.";
56
- readonly commands: readonly ["https://mcp.spacefast.com/mcp"];
56
+ readonly commands: readonly ["https://mcp.spacefast.com"];
57
57
  readonly guideUrl: `${string}/docs/agents`;
58
58
  readonly setupText: string;
59
59
  }, {
@@ -63,7 +63,7 @@ export declare const agentSolutions: readonly [{
63
63
  readonly lane: "hosted-mcp";
64
64
  readonly summary: "Recommended: direct hosted MCP.";
65
65
  readonly description: "Connect the web Claude app to Spacefast through hosted MCP when it cannot read your local checkout.";
66
- readonly commands: readonly ["https://mcp.spacefast.com/mcp"];
66
+ readonly commands: readonly ["https://mcp.spacefast.com"];
67
67
  readonly guideUrl: `${string}/docs/agents`;
68
68
  readonly setupText: string;
69
69
  }, {
@@ -73,7 +73,7 @@ export declare const agentSolutions: readonly [{
73
73
  readonly lane: "hosted-mcp";
74
74
  readonly summary: "Recommended: direct hosted MCP.";
75
75
  readonly description: "Use hosted MCP for Raycast and similar clients that can connect to a remote MCP server but should not need a local Spacefast install.";
76
- readonly commands: readonly ["https://mcp.spacefast.com/mcp"];
76
+ readonly commands: readonly ["https://mcp.spacefast.com"];
77
77
  readonly guideUrl: `${string}/docs/agents`;
78
78
  readonly setupText: string;
79
79
  }, {
@@ -1,7 +1,7 @@
1
1
  import { BRAND } from "../brand.js";
2
2
  import { agentSetupPrompt, agentSetupTextUrl, agentSetupUrl } from "./agent-setup.js";
3
3
  import { spacefastClaudePluginAddCommand, spacefastClaudePluginInstallCommand, spacefastCodexSkillInstallCommand, spacefastInstallCurlCommand, } from "./skill-distribution.js";
4
- export const hostedMcpEndpointUrl = "https://mcp.spacefast.com/mcp";
4
+ export const hostedMcpEndpointUrl = "https://mcp.spacefast.com";
5
5
  function pluginText(label, commands, guideUrl) {
6
6
  return [
7
7
  `Set up ${BRAND.productName} for ${label}.`,
@@ -20,7 +20,7 @@ function hostedMcpText(label, guideUrl) {
20
20
  "",
21
21
  `MCP endpoint: ${hostedMcpEndpointUrl}`,
22
22
  "Transport: Streamable HTTP",
23
- "Resource: https://api.spacefast.com/mcp",
23
+ "Resource: https://mcp.spacefast.com",
24
24
  "Minimum scope: mcp:tools",
25
25
  "Common scopes: teams:read spaces:read spaces:write publish:write domains:read domains:write",
26
26
  "",