@manifest-network/manifest-agent-core 0.14.0 → 0.16.0

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 (62) hide show
  1. package/dist/close-lease.d.ts.map +1 -1
  2. package/dist/close-lease.js +15 -3
  3. package/dist/close-lease.js.map +1 -1
  4. package/dist/deploy-app.d.ts +2 -2
  5. package/dist/deploy-app.d.ts.map +1 -1
  6. package/dist/deploy-app.js +84 -37
  7. package/dist/deploy-app.js.map +1 -1
  8. package/dist/deploy-app.test-d.d.ts +1 -0
  9. package/dist/deploy-app.test-d.js +11 -0
  10. package/dist/deploy-app.test-d.js.map +1 -0
  11. package/dist/guarded-fetch.d.ts +2 -0
  12. package/dist/guarded-fetch.js +2 -0
  13. package/dist/index.d.ts +2 -3
  14. package/dist/index.js +1 -2
  15. package/dist/internals/cancellation.d.ts +57 -0
  16. package/dist/internals/cancellation.d.ts.map +1 -0
  17. package/dist/internals/cancellation.js +79 -0
  18. package/dist/internals/cancellation.js.map +1 -0
  19. package/dist/internals/inspect-image.js +1 -1
  20. package/dist/internals/inspect-image.js.map +1 -1
  21. package/dist/internals/render-intent-recap.d.ts +13 -11
  22. package/dist/internals/render-intent-recap.d.ts.map +1 -1
  23. package/dist/internals/render-intent-recap.js +5 -4
  24. package/dist/internals/render-intent-recap.js.map +1 -1
  25. package/dist/internals/spec-normalize.d.ts +34 -28
  26. package/dist/internals/spec-normalize.d.ts.map +1 -1
  27. package/dist/internals/spec-normalize.js +28 -22
  28. package/dist/internals/spec-normalize.js.map +1 -1
  29. package/dist/manage-domain.d.ts.map +1 -1
  30. package/dist/manage-domain.js +34 -8
  31. package/dist/manage-domain.js.map +1 -1
  32. package/dist/node_modules/@vitest/pretty-format/dist/index.js +888 -0
  33. package/dist/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
  34. package/dist/node_modules/@vitest/runner/dist/chunk-artifact.js +1500 -0
  35. package/dist/node_modules/@vitest/runner/dist/chunk-artifact.js.map +1 -0
  36. package/dist/node_modules/@vitest/runner/dist/index.js +1 -0
  37. package/dist/node_modules/@vitest/runner/dist/utils.js +1 -0
  38. package/dist/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
  39. package/dist/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js.map +1 -0
  40. package/dist/node_modules/@vitest/utils/dist/display.js +558 -0
  41. package/dist/node_modules/@vitest/utils/dist/display.js.map +1 -0
  42. package/dist/node_modules/@vitest/utils/dist/helpers.js +68 -0
  43. package/dist/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
  44. package/dist/node_modules/@vitest/utils/dist/source-map.js +95 -0
  45. package/dist/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
  46. package/dist/node_modules/@vitest/utils/dist/timers.js +20 -0
  47. package/dist/node_modules/@vitest/utils/dist/timers.js.map +1 -0
  48. package/dist/node_modules/tinyrainbow/dist/index.js +86 -0
  49. package/dist/node_modules/tinyrainbow/dist/index.js.map +1 -0
  50. package/dist/node_modules/vite/dist/node/module-runner.js +22 -0
  51. package/dist/node_modules/vite/dist/node/module-runner.js.map +1 -0
  52. package/dist/node_modules/vitest/dist/index.js +6 -0
  53. package/dist/troubleshoot.d.ts.map +1 -1
  54. package/dist/troubleshoot.js +11 -1
  55. package/dist/troubleshoot.js.map +1 -1
  56. package/dist/types.d.ts +30 -51
  57. package/dist/types.d.ts.map +1 -1
  58. package/package.json +15 -7
  59. package/dist/internals/build-fred-input.d.ts +0 -46
  60. package/dist/internals/build-fred-input.d.ts.map +0 -1
  61. package/dist/internals/build-fred-input.js +0 -160
  62. package/dist/internals/build-fred-input.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"troubleshoot.js","names":["decodeLeaseState"],"sources":["../src/troubleshoot.ts"],"sourcesContent":["/**\n * Public entry point: produce a markdown-formatted diagnostic report\n * for a given lease.\n *\n * Chain-only (no provider HTTP calls — `TroubleshootOptions` has no\n * `walletProvider` for ADR-036 auth). Composes:\n *\n * - `queryClient.liftedinit.billing.v1.lease({ leaseUuid })` for the\n * authoritative chain-side lease record.\n * - `lease-state.decode` + `isTerminal` to translate the integer\n * state into a canonical `LEASE_STATE_*` name and a\n * guidance-routing terminal/non-terminal classification.\n * - `lease-items.normalizeItem` to surface each item's serviceName\n * and customDomain regardless of snake/camelCase payload shape.\n *\n * The returned `markdown` is plain text with markdown formatting — host\n * surfaces can render it in chat directly or embed in a richer\n * diagnostic UI.\n *\n * **Scope:** chain-only. `TroubleshootOptions` carries no `walletProvider`,\n * so provider-side diagnostics (`appStatus` / `getLeaseProvision` /\n * `getAppLogs`) are out of scope for this function. If the report\n * surfaces a recovery-worthy state (e.g. terminal / drift), the caller\n * composes `closeLease()` separately — agent-core's simple-form\n * `onFailure({ reason })` does not carry recovery options, so the\n * orchestration of \"report → decide → close\" lives at the host surface.\n */\n\nimport {\n ManifestMCPError,\n ManifestMCPErrorCode,\n} from '@manifest-network/manifest-mcp-core';\nimport { normalizeItem } from './internals/lease-items.js';\nimport {\n decode as decodeLeaseState,\n isTerminal,\n} from './internals/lease-state.js';\nimport type {\n LeaseStateName,\n TroubleshootArgs,\n TroubleshootCallbacks,\n TroubleshootOptions,\n TroubleshootReport,\n} from './types.js';\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Generate a diagnostic markdown report for `args.leaseUuid`.\n *\n * @throws `ManifestMCPError(INVALID_CONFIG)` for args validation.\n * @throws `ManifestMCPError(QUERY_FAILED)` in two cases, both with\n * `onFailure({ reason })` invoked first:\n * - the chain query rejects with a plain `Error` (RPC / transport\n * / decoding failure); or\n * - the chain query succeeds but returns `{ lease: null }` /\n * `undefined` (lease UUID not on-chain — the `billing.v1.lease`\n * no-such-lease response shape).\n * Structured `ManifestMCPError`s raised by the chain client\n * (e.g. `INVALID_CONFIG` from missing rpc/rest url config,\n * `RPC_CONNECTION_FAILED` from connect failure) are re-thrown\n * as-is with their original code, with `onFailure` invoked first.\n */\nexport async function troubleshootDeployment(\n args: TroubleshootArgs,\n callbacks: TroubleshootCallbacks,\n opts: TroubleshootOptions,\n): Promise<TroubleshootReport> {\n validateArgs(args);\n\n let leasePayload: unknown;\n try {\n // Pull `getQueryClient()` INSIDE the try (Copilot review PR #60,\n // comment 3276719462). `getQueryClient()` can throw\n // `INVALID_CONFIG` (neither rpcUrl nor restUrl set) or\n // `RPC_CONNECTION_FAILED` (connect failure). Catching here routes\n // those init-time failures through the same `onFailure` +\n // QUERY_FAILED / structured-passthrough normalization the chain-\n // query failure mode already gets — three modes, one disambiguation.\n const queryClient = await opts.clientManager.getQueryClient();\n const result = await queryClient.liftedinit.billing.v1.lease({\n leaseUuid: args.leaseUuid,\n });\n leasePayload = result.lease;\n } catch (err) {\n // Preserve structured `ManifestMCPError`s from the chain client\n // (Copilot review PR #60, comment 3276172289). Wrapping every\n // failure as `QUERY_FAILED` erases upstream error codes — a real\n // `INVALID_CONFIG` from the chain layer should surface to callers\n // with that code, not be collapsed to a less-specific category.\n // Mirrors the disambiguation `manage-domain.ts:lookupDomain`\n // adopted in commit aaa5cc5. Note: chain-NotFound for\n // `billing.v1.lease({ leaseUuid })` returns `{ lease: null }`\n // (handled below), so errors landing here are genuinely transport\n // or structured failures.\n const reason = `Failed to query lease ${args.leaseUuid}: ${err instanceof Error ? err.message : String(err)}`;\n if (callbacks.onFailure) {\n await callbacks.onFailure({ reason });\n }\n if (err instanceof ManifestMCPError) {\n throw err;\n }\n throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, reason);\n }\n\n if (leasePayload === null || leasePayload === undefined) {\n const reason = `Lease ${args.leaseUuid} not found on chain.`;\n if (callbacks.onFailure) {\n await callbacks.onFailure({ reason });\n }\n throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, reason);\n }\n\n const markdown = renderReport(args.leaseUuid, leasePayload);\n const report: TroubleshootReport = { markdown };\n callbacks.onComplete?.(report);\n return report;\n}\n\n// --- Helpers --------------------------------------------------------\n\nfunction validateArgs(args: TroubleshootArgs): void {\n if (typeof args.leaseUuid !== 'string' || !args.leaseUuid.match(UUID_RE)) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `troubleshootDeployment: leaseUuid must be a UUID; got \"${args.leaseUuid}\".`,\n );\n }\n}\n\ninterface LeaseShape {\n uuid?: unknown;\n state?: unknown;\n providerUuid?: unknown;\n provider_uuid?: unknown;\n createdAt?: unknown;\n created_at?: unknown;\n closedAt?: unknown;\n closed_at?: unknown;\n items?: unknown;\n}\n\nfunction renderReport(leaseUuid: string, lease: unknown): string {\n const l = (lease ?? {}) as LeaseShape;\n const rawState = l.state;\n const stateName = decodeLeaseState(\n typeof rawState === 'number' || typeof rawState === 'string'\n ? rawState\n : undefined,\n );\n const stateLabel = stateName ?? `UNKNOWN(${String(rawState)})`;\n const providerUuid =\n readString(l.providerUuid) || readString(l.provider_uuid) || '(unknown)';\n const createdAt = readTimestamp(l.createdAt) ?? readTimestamp(l.created_at);\n const closedAt = readTimestamp(l.closedAt) ?? readTimestamp(l.closed_at);\n\n const rawItems = Array.isArray(l.items) ? l.items : [];\n const items = rawItems.map(normalizeItem);\n\n const lines: string[] = [];\n lines.push(`# Lease diagnostic — ${leaseUuid}`);\n lines.push('');\n lines.push('## Chain state');\n lines.push('');\n lines.push(`- **State:** ${stateLabel}`);\n lines.push(`- **Provider:** ${providerUuid}`);\n if (createdAt) lines.push(`- **Created:** ${createdAt}`);\n if (closedAt) lines.push(`- **Closed:** ${closedAt}`);\n lines.push('');\n\n lines.push('## Items');\n lines.push('');\n if (items.length === 0) {\n lines.push('_No items found on this lease._');\n } else {\n for (const item of items) {\n const svc = item.serviceName.length > 0 ? item.serviceName : '(default)';\n const dom =\n item.customDomain.length > 0 ? item.customDomain : '(no custom domain)';\n lines.push(`- **${svc}** → ${dom}`);\n }\n }\n lines.push('');\n\n lines.push('## Guidance');\n lines.push('');\n for (const tip of guidanceFor(stateName)) {\n lines.push(`- ${tip}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction guidanceFor(state: LeaseStateName | undefined): string[] {\n if (state === undefined) {\n return [\n 'Lease state could not be decoded. Re-query in a moment, or check the chain client logs for transport errors.',\n ];\n }\n if (isTerminal(state)) {\n return [\n `Lease is in terminal state \\`${state}\\`. No further provider activity expected.`,\n 'To redeploy, create a new lease via `deployApp`.',\n ];\n }\n switch (state) {\n case 'LEASE_STATE_PENDING':\n return [\n 'Lease is awaiting provider acknowledgement.',\n 'If pending persists for more than a few minutes, the provider may be offline; consider closing and redeploying.',\n ];\n case 'LEASE_STATE_ACTIVE':\n return [\n 'Lease is active on the provider. App-level status / logs require a provider HTTP call with an ADR-036 auth token (out of scope for this chain-only diagnostic).',\n ];\n default:\n return [\n `Lease state is \\`${state}\\`. Review the chain proto for the expected next transition.`,\n ];\n }\n}\n\nfunction readString(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\nfunction readTimestamp(value: unknown): string | undefined {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) return value;\n return undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"troubleshoot.js","names":["decodeLeaseState"],"sources":["../src/troubleshoot.ts"],"sourcesContent":["/**\n * Public entry point: produce a markdown-formatted diagnostic report\n * for a given lease.\n *\n * Chain-only (no provider HTTP calls — `TroubleshootOptions` has no\n * `walletProvider` for ADR-036 auth). Composes:\n *\n * - `queryClient.liftedinit.billing.v1.lease({ leaseUuid })` for the\n * authoritative chain-side lease record.\n * - `lease-state.decode` + `isTerminal` to translate the integer\n * state into a canonical `LEASE_STATE_*` name and a\n * guidance-routing terminal/non-terminal classification.\n * - `lease-items.normalizeItem` to surface each item's serviceName\n * and customDomain regardless of snake/camelCase payload shape.\n *\n * The returned `markdown` is plain text with markdown formatting — host\n * surfaces can render it in chat directly or embed in a richer\n * diagnostic UI.\n *\n * **Scope:** chain-only. `TroubleshootOptions` carries no `walletProvider`,\n * so provider-side diagnostics (`appStatus` / `getLeaseProvision` /\n * `getAppLogs`) are out of scope for this function. If the report\n * surfaces a recovery-worthy state (e.g. terminal / drift), the caller\n * composes `closeLease()` separately — agent-core's simple-form\n * `onFailure({ reason })` does not carry recovery options, so the\n * orchestration of \"report → decide → close\" lives at the host surface.\n */\n\nimport {\n ManifestMCPError,\n ManifestMCPErrorCode,\n} from '@manifest-network/manifest-mcp-core';\nimport { makeCancellationScope } from './internals/cancellation.js';\nimport { normalizeItem } from './internals/lease-items.js';\nimport {\n decode as decodeLeaseState,\n isTerminal,\n} from './internals/lease-state.js';\nimport type {\n LeaseStateName,\n TroubleshootArgs,\n TroubleshootCallbacks,\n TroubleshootOptions,\n TroubleshootReport,\n} from './types.js';\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Generate a diagnostic markdown report for `args.leaseUuid`.\n *\n * @throws `ManifestMCPError(INVALID_CONFIG)` for args validation.\n * @throws `ManifestMCPError(QUERY_FAILED)` in two cases, both with\n * `onFailure({ reason })` invoked first:\n * - the chain query rejects with a plain `Error` (RPC / transport\n * / decoding failure); or\n * - the chain query succeeds but returns `{ lease: null }` /\n * `undefined` (lease UUID not on-chain — the `billing.v1.lease`\n * no-such-lease response shape).\n * Structured `ManifestMCPError`s raised by the chain client\n * (e.g. `INVALID_CONFIG` from missing rpc/rest url config,\n * `RPC_CONNECTION_FAILED` from connect failure) are re-thrown\n * as-is with their original code, with `onFailure` invoked first.\n */\nexport async function troubleshootDeployment(\n args: TroubleshootArgs,\n callbacks: TroubleshootCallbacks,\n opts: TroubleshootOptions,\n): Promise<TroubleshootReport> {\n validateArgs(args);\n\n const cx = makeCancellationScope({\n opts,\n onProgress: callbacks.onProgress,\n opLabel: 'Troubleshoot',\n broadcasts: false,\n });\n cx.throwIfCancelled();\n\n let leasePayload: unknown;\n try {\n // Pull `getQueryClient()` INSIDE the try (Copilot review PR #60,\n // comment 3276719462). `getQueryClient()` can throw\n // `INVALID_CONFIG` (neither rpcUrl nor restUrl set) or\n // `RPC_CONNECTION_FAILED` (connect failure). Catching here routes\n // those init-time failures through the same `onFailure` +\n // QUERY_FAILED / structured-passthrough normalization the chain-\n // query failure mode already gets — three modes, one disambiguation.\n const queryClient = await opts.clientManager.getQueryClient();\n const result = await cx.race(\n queryClient.liftedinit.billing.v1.lease({\n leaseUuid: args.leaseUuid,\n }),\n );\n leasePayload = result.lease;\n } catch (err) {\n if (\n err instanceof ManifestMCPError &&\n err.code === ManifestMCPErrorCode.OPERATION_CANCELLED\n ) {\n throw err;\n }\n // Preserve structured `ManifestMCPError`s from the chain client\n // (Copilot review PR #60, comment 3276172289). Wrapping every\n // failure as `QUERY_FAILED` erases upstream error codes — a real\n // `INVALID_CONFIG` from the chain layer should surface to callers\n // with that code, not be collapsed to a less-specific category.\n // Mirrors the disambiguation `manage-domain.ts:lookupDomain`\n // adopted in commit aaa5cc5. Note: chain-NotFound for\n // `billing.v1.lease({ leaseUuid })` returns `{ lease: null }`\n // (handled below), so errors landing here are genuinely transport\n // or structured failures.\n const reason = `Failed to query lease ${args.leaseUuid}: ${err instanceof Error ? err.message : String(err)}`;\n if (callbacks.onFailure) {\n await callbacks.onFailure({ reason });\n }\n if (err instanceof ManifestMCPError) {\n throw err;\n }\n throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, reason);\n }\n\n if (leasePayload === null || leasePayload === undefined) {\n const reason = `Lease ${args.leaseUuid} not found on chain.`;\n if (callbacks.onFailure) {\n await callbacks.onFailure({ reason });\n }\n throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, reason);\n }\n\n const markdown = renderReport(args.leaseUuid, leasePayload);\n const report: TroubleshootReport = { markdown };\n callbacks.onComplete?.(report);\n return report;\n}\n\n// --- Helpers --------------------------------------------------------\n\nfunction validateArgs(args: TroubleshootArgs): void {\n if (typeof args.leaseUuid !== 'string' || !args.leaseUuid.match(UUID_RE)) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `troubleshootDeployment: leaseUuid must be a UUID; got \"${args.leaseUuid}\".`,\n );\n }\n}\n\ninterface LeaseShape {\n uuid?: unknown;\n state?: unknown;\n providerUuid?: unknown;\n provider_uuid?: unknown;\n createdAt?: unknown;\n created_at?: unknown;\n closedAt?: unknown;\n closed_at?: unknown;\n items?: unknown;\n}\n\nfunction renderReport(leaseUuid: string, lease: unknown): string {\n const l = (lease ?? {}) as LeaseShape;\n const rawState = l.state;\n const stateName = decodeLeaseState(\n typeof rawState === 'number' || typeof rawState === 'string'\n ? rawState\n : undefined,\n );\n const stateLabel = stateName ?? `UNKNOWN(${String(rawState)})`;\n const providerUuid =\n readString(l.providerUuid) || readString(l.provider_uuid) || '(unknown)';\n const createdAt = readTimestamp(l.createdAt) ?? readTimestamp(l.created_at);\n const closedAt = readTimestamp(l.closedAt) ?? readTimestamp(l.closed_at);\n\n const rawItems = Array.isArray(l.items) ? l.items : [];\n const items = rawItems.map(normalizeItem);\n\n const lines: string[] = [];\n lines.push(`# Lease diagnostic — ${leaseUuid}`);\n lines.push('');\n lines.push('## Chain state');\n lines.push('');\n lines.push(`- **State:** ${stateLabel}`);\n lines.push(`- **Provider:** ${providerUuid}`);\n if (createdAt) lines.push(`- **Created:** ${createdAt}`);\n if (closedAt) lines.push(`- **Closed:** ${closedAt}`);\n lines.push('');\n\n lines.push('## Items');\n lines.push('');\n if (items.length === 0) {\n lines.push('_No items found on this lease._');\n } else {\n for (const item of items) {\n const svc = item.serviceName.length > 0 ? item.serviceName : '(default)';\n const dom =\n item.customDomain.length > 0 ? item.customDomain : '(no custom domain)';\n lines.push(`- **${svc}** → ${dom}`);\n }\n }\n lines.push('');\n\n lines.push('## Guidance');\n lines.push('');\n for (const tip of guidanceFor(stateName)) {\n lines.push(`- ${tip}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction guidanceFor(state: LeaseStateName | undefined): string[] {\n if (state === undefined) {\n return [\n 'Lease state could not be decoded. Re-query in a moment, or check the chain client logs for transport errors.',\n ];\n }\n if (isTerminal(state)) {\n return [\n `Lease is in terminal state \\`${state}\\`. No further provider activity expected.`,\n 'To redeploy, create a new lease via `deployApp`.',\n ];\n }\n switch (state) {\n case 'LEASE_STATE_PENDING':\n return [\n 'Lease is awaiting provider acknowledgement.',\n 'If pending persists for more than a few minutes, the provider may be offline; consider closing and redeploying.',\n ];\n case 'LEASE_STATE_ACTIVE':\n return [\n 'Lease is active on the provider. App-level status / logs require a provider HTTP call with an ADR-036 auth token (out of scope for this chain-only diagnostic).',\n ];\n default:\n return [\n `Lease state is \\`${state}\\`. Review the chain proto for the expected next transition.`,\n ];\n }\n}\n\nfunction readString(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\nfunction readTimestamp(value: unknown): string | undefined {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) return value;\n return undefined;\n}\n"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CosmosClientManager, SkuCandidate, WalletProvider } from "@manifest-network/manifest-mcp-core";
1
+ import { AppDeploySpec, CosmosClientManager, ServiceConfig, SkuCandidate, WalletProvider } from "@manifest-network/manifest-mcp-core";
2
2
 
3
3
  //#region src/types.d.ts
4
4
  interface Coin {
@@ -35,6 +35,19 @@ interface AgentCoreRuntime {
35
35
  * the optional DenomMap injection (chain-registry-driven humanization).
36
36
  */
37
37
  interface DeployAppOptions extends AgentCoreRuntime {
38
+ /**
39
+ * Caller cancellation. Composed with `timeout` via `resolveCallSignal`
40
+ * (core's `CallOptions` convention). Races ONLY the pre-broadcast
41
+ * interactive callbacks (onPlan/onConfirm/onResolveSku) + forwards into
42
+ * fred's `DeployCallOptions.abortSignal`; a post-broadcast abort routes
43
+ * INTO recovery, it never cancels it (ENG-310 / D4).
44
+ */
45
+ signal?: AbortSignal;
46
+ /**
47
+ * Per-call deadline in ms. Surfaces as a `TimeoutError` (distinct from the
48
+ * caller's `AbortError`), mapped to `OPERATION_CANCELLED` (ENG-310 / D4).
49
+ */
50
+ timeout?: number;
38
51
  /**
39
52
  * Wallet provider for ADR-036 auth-token signing.
40
53
  *
@@ -89,6 +102,10 @@ interface DeployAppOptions extends AgentCoreRuntime {
89
102
  * humanization injection.
90
103
  */
91
104
  interface ManageDomainOptions extends AgentCoreRuntime {
105
+ /** Caller cancellation (core `CallOptions` convention; ENG-310 / D4). */
106
+ signal?: AbortSignal;
107
+ /** Per-call deadline in ms (ENG-310 / D4). */
108
+ timeout?: number;
92
109
  chainDataFile?: string;
93
110
  denomMap?: DenomMap;
94
111
  }
@@ -97,6 +114,10 @@ interface ManageDomainOptions extends AgentCoreRuntime {
97
114
  * fred → no `walletProvider` required.
98
115
  */
99
116
  interface CloseLeaseOptions extends AgentCoreRuntime {
117
+ /** Caller cancellation (core `CallOptions` convention; ENG-310 / D4). */
118
+ signal?: AbortSignal;
119
+ /** Per-call deadline in ms (ENG-310 / D4). */
120
+ timeout?: number;
100
121
  chainDataFile?: string;
101
122
  denomMap?: DenomMap;
102
123
  }
@@ -105,57 +126,13 @@ interface CloseLeaseOptions extends AgentCoreRuntime {
105
126
  * broadcast through fred → no `walletProvider` required.
106
127
  */
107
128
  interface TroubleshootOptions extends AgentCoreRuntime {
129
+ /** Caller cancellation (core `CallOptions` convention; ENG-310 / D4). */
130
+ signal?: AbortSignal;
131
+ /** Per-call deadline in ms (ENG-310 / D4). */
132
+ timeout?: number;
108
133
  chainDataFile?: string;
109
134
  denomMap?: DenomMap;
110
135
  }
111
- interface ServiceDef {
112
- image: string;
113
- ports?: number[];
114
- env?: Record<string, string>;
115
- args?: string[];
116
- command?: string[];
117
- }
118
- interface SingleServiceSpec {
119
- image: string;
120
- port?: number | number[];
121
- env?: Record<string, string>;
122
- customDomain?: string;
123
- /**
124
- * Compute-tier / SKU name selecting the lease item's resources (e.g.
125
- * `'small'`, `'medium'`). Resolved to an on-chain SKU UUID by
126
- * `findSkuUuid`, then threaded into SKU selection, fee estimation,
127
- * readiness, fred's deploy input, and the persisted manifest. Optional;
128
- * `requestedSize` (`deploy-app.ts`) falls back to `'small'` when absent
129
- * or empty. ENG-275 promoted this from an undocumented cast-read
130
- * escape hatch to a first-class typed field so contract-following
131
- * callers can select a non-default SKU.
132
- */
133
- size?: string;
134
- /**
135
- * Optional SKU disambiguator: `provider_uuid` narrows a duplicate
136
- * `size` name to one provider; `sku_uuid` pins a specific SKU by uuid
137
- * (bypasses the name). Threaded into `resolveSku`. ENG-296.
138
- */
139
- providerUuid?: string;
140
- /** See {@link SingleServiceSpec.providerUuid}. Pins a specific SKU by uuid (bypasses the name). ENG-296. */
141
- skuUuid?: string;
142
- }
143
- interface StackSpec {
144
- services: Record<string, ServiceDef>;
145
- customDomain?: string;
146
- serviceName?: string;
147
- /** SKU tier for the lease items; see {@link SingleServiceSpec.size}. */
148
- size?: string;
149
- /**
150
- * Optional SKU disambiguator: `provider_uuid` narrows a duplicate
151
- * `size` name to one provider; `sku_uuid` pins a specific SKU by uuid
152
- * (bypasses the name). Threaded into `resolveSku`. ENG-296.
153
- */
154
- providerUuid?: string;
155
- /** See {@link StackSpec.providerUuid}. Pins a specific SKU by uuid (bypasses the name). ENG-296. */
156
- skuUuid?: string;
157
- }
158
- type DeploySpec = SingleServiceSpec | StackSpec;
159
136
  interface SpecSummary {
160
137
  format: 'single' | 'stack';
161
138
  serviceCount: number;
@@ -196,7 +173,7 @@ type PlanEdit = {
196
173
  env: Record<string, string>;
197
174
  } | {
198
175
  kind: 'replace_spec';
199
- spec: DeploySpec;
176
+ spec: AppDeploySpec;
200
177
  };
201
178
  interface DeploymentPlanBlock {
202
179
  text: string;
@@ -247,6 +224,8 @@ type ProgressEvent = {
247
224
  } | {
248
225
  kind: 'sku_ambiguous';
249
226
  candidates: SkuCandidate[];
227
+ } | {
228
+ kind: 'cancelled';
250
229
  };
251
230
  type FailureEnvelope = {
252
231
  outcome: 'partially_succeeded';
@@ -350,5 +329,5 @@ interface CloseLeaseCallbacks {
350
329
  }) => Promise<void>;
351
330
  }
352
331
  //#endregion
353
- export { AgentCoreRuntime, CloseLeaseArgs, CloseLeaseCallbacks, CloseLeaseOptions, CloseLeaseResult, Coin, type CosmosClientManager, DenomLookup, DenomMap, DeployAppCallbacks, DeployAppOptions, DeployResult, DeploySpec, DeploymentPlanBlock, FailureEnvelope, FeeEstimate, LeaseStateName, ManageDomainArgs, ManageDomainCallbacks, ManageDomainOptions, ManageDomainResult, Plan, PlanEdit, PlanFees, ProgressEvent, Readiness, ReadinessAction, RecoveryChoice, RecoveryOption, RecoveryOptionId, ServiceDef, SingleServiceSpec, type SkuCandidate, SpecSummary, StackSpec, TroubleshootArgs, TroubleshootCallbacks, TroubleshootOptions, TroubleshootReport, type WalletProvider };
332
+ export { AgentCoreRuntime, type AppDeploySpec, CloseLeaseArgs, CloseLeaseCallbacks, CloseLeaseOptions, CloseLeaseResult, Coin, type CosmosClientManager, DenomLookup, DenomMap, DeployAppCallbacks, DeployAppOptions, DeployResult, DeploymentPlanBlock, FailureEnvelope, FeeEstimate, LeaseStateName, ManageDomainArgs, ManageDomainCallbacks, ManageDomainOptions, ManageDomainResult, Plan, PlanEdit, PlanFees, ProgressEvent, Readiness, ReadinessAction, RecoveryChoice, RecoveryOption, RecoveryOptionId, type ServiceConfig, type SkuCandidate, SpecSummary, TroubleshootArgs, TroubleshootCallbacks, TroubleshootOptions, TroubleshootReport, type WalletProvider };
354
333
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,21 +1,27 @@
1
1
  {
2
2
  "name": "@manifest-network/manifest-agent-core",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "TypeScript orchestration surface for Manifest agent flows (deploy / manage-domain / troubleshoot / close-lease). Type contract only — see ENG-127.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
8
+ "sideEffects": false,
8
9
  "exports": {
9
10
  ".": {
10
- "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./guarded-fetch": {
15
+ "types": "./dist/guarded-fetch.d.ts",
16
+ "node": "./dist/guarded-fetch.js",
17
+ "default": null
12
18
  }
13
19
  },
14
20
  "scripts": {
15
21
  "build": "tsdown",
16
22
  "dev": "tsdown --watch",
17
23
  "lint": "tsc --noEmit",
18
- "test": "vitest run",
24
+ "test": "vitest run --typecheck",
19
25
  "test:watch": "vitest"
20
26
  },
21
27
  "keywords": [
@@ -42,11 +48,13 @@
42
48
  "files": [
43
49
  "dist"
44
50
  ],
45
- "dependencies": {
46
- "@manifest-network/manifest-mcp-core": "^0.14.0",
47
- "@manifest-network/manifest-mcp-fred": "^0.14.0"
51
+ "peerDependencies": {
52
+ "@manifest-network/manifest-mcp-core": "^0.16.0",
53
+ "@manifest-network/manifest-mcp-fred": "^0.16.0"
48
54
  },
49
55
  "devDependencies": {
56
+ "@manifest-network/manifest-mcp-core": "0.16.0",
57
+ "@manifest-network/manifest-mcp-fred": "0.16.0",
50
58
  "@types/node": "22.19.19",
51
59
  "typescript": "5.9.3",
52
60
  "vitest": "4.1.8"
@@ -1,46 +0,0 @@
1
- import { DeploySpec } from "../types.js";
2
- import { BuildManifestPreviewInput, DeployAppInput } from "@manifest-network/manifest-mcp-fred";
3
-
4
- //#region src/internals/build-fred-input.d.ts
5
- /**
6
- * Build fred's `BuildManifestPreviewInput` from a typed `DeploySpec`.
7
- *
8
- * Stack arm: each `ServiceDef.ports: number[]` is converted to
9
- * `{<port>/tcp: {}}`. Services without `ports` (or with empty `[]`)
10
- * omit the `ports` key in the output.
11
- *
12
- * Single-service arm: `port: number` and `port: [80]` both produce
13
- * `port: 80`. Multi-element arrays throw INVALID_CONFIG.
14
- *
15
- * Deploy-only fields (`customDomain`, `serviceName`) are deliberately
16
- * NOT forwarded — the preview path computes only the manifest meta-hash;
17
- * domain claims happen later in the deploy path.
18
- *
19
- * The `size` parameter is accepted for signature parity with
20
- * `buildFredDeployInput` but is NOT included in the returned object:
21
- * fred's `BuildManifestPreviewInput` type has no `size` field and
22
- * `buildManifestPreview` derives no behavior from it. The prior inline
23
- * builder emitted `size` via an `as unknown as` cast that hid the
24
- * type-contract violation; this version drops it cleanly.
25
- */
26
- declare function buildManifestPreviewInput(spec: DeploySpec, _size: string): BuildManifestPreviewInput;
27
- /**
28
- * Build fred's `DeployAppInput` from a typed `DeploySpec`.
29
- *
30
- * Same port-shape conversion as `buildManifestPreviewInput` (so the
31
- * meta-hash recorded on-chain matches the manifest actually uploaded).
32
- * Additionally threads `customDomain` (both shapes) and `serviceName`
33
- * (stack only — single-service leases have no service-name to address).
34
- *
35
- * @param pin Optional pre-resolved SKU pin (ENG-258). When supplied, spreads
36
- * `skuUuid` and `providerUuid` into the output so fred's `deployApp` skips
37
- * the name-based lookup (uses the `resolved` selector path). Existing
38
- * 2-arg callers are unaffected — the parameter is optional.
39
- */
40
- declare function buildFredDeployInput(spec: DeploySpec, size: string, pin?: {
41
- skuUuid: string;
42
- providerUuid: string;
43
- }): DeployAppInput;
44
- //#endregion
45
- export { buildFredDeployInput, buildManifestPreviewInput };
46
- //# sourceMappingURL=build-fred-input.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-fred-input.d.ts","names":[],"sources":["../../src/internals/build-fred-input.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;iBA6JgB,yBAAA,CACd,IAAA,EAAM,UAAA,EAGN,KAAA,WACC,yBAAyB;;;;;;;;;;;;;;iBAyBZ,oBAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA,UACA,GAAA;EAAQ,OAAA;EAAiB,YAAA;AAAA,IACxB,cAAkB"}
@@ -1,160 +0,0 @@
1
- import { isStackSpec } from "./spec-normalize.js";
2
- import { ManifestMCPError, ManifestMCPErrorCode } from "@manifest-network/manifest-mcp-core";
3
- //#region src/internals/build-fred-input.ts
4
- /**
5
- * Discriminated-union narrowing builders: typed `DeploySpec` → fred's
6
- * `BuildManifestPreviewInput` and `DeployAppInput`. ENG-185 sub-PR A, item 2.
7
- *
8
- * Replaces the prior inline builders in `deploy-app.ts` (PR-3 commit B) that
9
- * used `as unknown as <fred-input>` casts and silently truncated
10
- * `SingleServiceSpec.port` arrays to `port[0]`.
11
- *
12
- * Bugs this file kills:
13
- *
14
- * (a) Stack `ServiceDef.ports: number[]` (`types.ts:164`) is converted
15
- * to fred's canonical port-map shape `Record<string, Record<string,
16
- * never>>` (e.g. `{'80/tcp': {}}`). The prior inline cast passed
17
- * the raw array straight through, so `buildManifestPreview` and
18
- * fred's deploy-time builder saw different shapes — the meta-hash
19
- * recorded on-chain drifted from the manifest actually uploaded.
20
- *
21
- * (b) Single-service `SingleServiceSpec.port: number | number[]`
22
- * (`types.ts:172`) — fred's image-mode input is `port: number`
23
- * only. The prior inline builders did `port[0]`, silently dropping
24
- * every other element. We now reject multi-element arrays with
25
- * `ManifestMCPError(INVALID_CONFIG)` (strategy (a) per the task
26
- * brief) and point the caller at `StackSpec` for natively
27
- * multi-port deployments.
28
- *
29
- * No `as unknown as` casts. Discriminated narrowing uses the shared
30
- * `isStackSpec` predicate from `spec-normalize.ts`.
31
- */
32
- /**
33
- * Convert a `ServiceDef.ports: number[]` to fred's canonical port-map
34
- * shape. Protocol defaults to `tcp` (the only protocol exposed via the
35
- * agent-core surface today; UDP is deferred until a caller needs it).
36
- */
37
- function toPortMap(ports) {
38
- const map = {};
39
- for (const port of ports) map[`${port}/tcp`] = {};
40
- return map;
41
- }
42
- /**
43
- * Map a single `ServiceDef` (agent-core spec shape) → fred's
44
- * `ServiceConfig` shape. Omits optional fields when absent so callers
45
- * can compare emitted objects with `'foo' in out` checks (rather than
46
- * `out.foo === undefined`, which a `key: undefined` spread would defeat).
47
- */
48
- function convertServiceDef(svc) {
49
- const out = { image: svc.image };
50
- if (svc.ports !== void 0 && svc.ports.length > 0) out.ports = toPortMap(svc.ports);
51
- if (svc.env !== void 0) out.env = svc.env;
52
- if (svc.args !== void 0) out.args = [...svc.args];
53
- if (svc.command !== void 0) out.command = [...svc.command];
54
- return out;
55
- }
56
- function convertStackServices(spec) {
57
- const out = {};
58
- for (const [name, svc] of Object.entries(spec.services)) out[name] = convertServiceDef(svc);
59
- return out;
60
- }
61
- /**
62
- * Narrow `SingleServiceSpec.port: number | number[] | undefined` to
63
- * fred's single-service `port: number | undefined`.
64
- *
65
- * - `undefined` → `undefined`
66
- * - `80` → `80`
67
- * - `[80]` → `80` (single-element array convenience)
68
- * - `[80, 443, …]` → `ManifestMCPError(INVALID_CONFIG)`
69
- *
70
- * Strategy (a) per the ENG-185 sub-PR A brief: rejecting multi-element
71
- * arrays at the builder boundary kills the prior silent `port[0]`
72
- * truncation. The error message points the caller at the `StackSpec`
73
- * escape hatch where multi-port routing is natively expressible.
74
- */
75
- function narrowSingleServicePort(port) {
76
- if (port === void 0) return void 0;
77
- if (typeof port === "number") return port;
78
- if (Array.isArray(port)) {
79
- if (port.length === 0) return void 0;
80
- if (port.length === 1) return port[0];
81
- throw new ManifestMCPError(ManifestMCPErrorCode.INVALID_CONFIG, "SingleServiceSpec.port: multi-port single-service is not supported — use a StackSpec with explicit `services.<name>.ports` to expose multiple ports.");
82
- }
83
- }
84
- /**
85
- * Build fred's `BuildManifestPreviewInput` from a typed `DeploySpec`.
86
- *
87
- * Stack arm: each `ServiceDef.ports: number[]` is converted to
88
- * `{<port>/tcp: {}}`. Services without `ports` (or with empty `[]`)
89
- * omit the `ports` key in the output.
90
- *
91
- * Single-service arm: `port: number` and `port: [80]` both produce
92
- * `port: 80`. Multi-element arrays throw INVALID_CONFIG.
93
- *
94
- * Deploy-only fields (`customDomain`, `serviceName`) are deliberately
95
- * NOT forwarded — the preview path computes only the manifest meta-hash;
96
- * domain claims happen later in the deploy path.
97
- *
98
- * The `size` parameter is accepted for signature parity with
99
- * `buildFredDeployInput` but is NOT included in the returned object:
100
- * fred's `BuildManifestPreviewInput` type has no `size` field and
101
- * `buildManifestPreview` derives no behavior from it. The prior inline
102
- * builder emitted `size` via an `as unknown as` cast that hid the
103
- * type-contract violation; this version drops it cleanly.
104
- */
105
- function buildManifestPreviewInput(spec, _size) {
106
- if (isStackSpec(spec)) return { services: convertStackServices(spec) };
107
- const port = narrowSingleServicePort(spec.port);
108
- return {
109
- image: spec.image,
110
- ...port !== void 0 ? { port } : {},
111
- ...spec.env !== void 0 ? { env: spec.env } : {}
112
- };
113
- }
114
- /**
115
- * Build fred's `DeployAppInput` from a typed `DeploySpec`.
116
- *
117
- * Same port-shape conversion as `buildManifestPreviewInput` (so the
118
- * meta-hash recorded on-chain matches the manifest actually uploaded).
119
- * Additionally threads `customDomain` (both shapes) and `serviceName`
120
- * (stack only — single-service leases have no service-name to address).
121
- *
122
- * @param pin Optional pre-resolved SKU pin (ENG-258). When supplied, spreads
123
- * `skuUuid` and `providerUuid` into the output so fred's `deployApp` skips
124
- * the name-based lookup (uses the `resolved` selector path). Existing
125
- * 2-arg callers are unaffected — the parameter is optional.
126
- */
127
- function buildFredDeployInput(spec, size, pin) {
128
- if (isStackSpec(spec)) {
129
- const out = {
130
- size,
131
- services: convertStackServices(spec),
132
- ...pin ? {
133
- skuUuid: pin.skuUuid,
134
- providerUuid: pin.providerUuid
135
- } : {}
136
- };
137
- if (typeof spec.customDomain === "string" && spec.customDomain.length > 0) {
138
- out.customDomain = spec.customDomain;
139
- if (typeof spec.serviceName === "string" && spec.serviceName.length > 0) out.serviceName = spec.serviceName;
140
- }
141
- return out;
142
- }
143
- const port = narrowSingleServicePort(spec.port);
144
- const out = {
145
- size,
146
- image: spec.image,
147
- ...pin ? {
148
- skuUuid: pin.skuUuid,
149
- providerUuid: pin.providerUuid
150
- } : {}
151
- };
152
- if (port !== void 0) out.port = port;
153
- if (spec.env !== void 0) out.env = spec.env;
154
- if (typeof spec.customDomain === "string" && spec.customDomain.length > 0) out.customDomain = spec.customDomain;
155
- return out;
156
- }
157
- //#endregion
158
- export { buildFredDeployInput, buildManifestPreviewInput };
159
-
160
- //# sourceMappingURL=build-fred-input.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-fred-input.js","names":[],"sources":["../../src/internals/build-fred-input.ts"],"sourcesContent":["/**\n * Discriminated-union narrowing builders: typed `DeploySpec` → fred's\n * `BuildManifestPreviewInput` and `DeployAppInput`. ENG-185 sub-PR A, item 2.\n *\n * Replaces the prior inline builders in `deploy-app.ts` (PR-3 commit B) that\n * used `as unknown as <fred-input>` casts and silently truncated\n * `SingleServiceSpec.port` arrays to `port[0]`.\n *\n * Bugs this file kills:\n *\n * (a) Stack `ServiceDef.ports: number[]` (`types.ts:164`) is converted\n * to fred's canonical port-map shape `Record<string, Record<string,\n * never>>` (e.g. `{'80/tcp': {}}`). The prior inline cast passed\n * the raw array straight through, so `buildManifestPreview` and\n * fred's deploy-time builder saw different shapes — the meta-hash\n * recorded on-chain drifted from the manifest actually uploaded.\n *\n * (b) Single-service `SingleServiceSpec.port: number | number[]`\n * (`types.ts:172`) — fred's image-mode input is `port: number`\n * only. The prior inline builders did `port[0]`, silently dropping\n * every other element. We now reject multi-element arrays with\n * `ManifestMCPError(INVALID_CONFIG)` (strategy (a) per the task\n * brief) and point the caller at `StackSpec` for natively\n * multi-port deployments.\n *\n * No `as unknown as` casts. Discriminated narrowing uses the shared\n * `isStackSpec` predicate from `spec-normalize.ts`.\n */\n\nimport {\n ManifestMCPError,\n ManifestMCPErrorCode,\n} from '@manifest-network/manifest-mcp-core';\nimport type {\n BuildManifestPreviewInput,\n DeployAppInput as FredDeployAppInput,\n} from '@manifest-network/manifest-mcp-fred';\nimport type { DeploySpec, ServiceDef, StackSpec } from '../types.js';\nimport { isStackSpec } from './spec-normalize.js';\n\n/**\n * Fred's canonical service port-map shape (`{<port>/<protocol>: {}}`).\n * Mirrors `ServiceConfig.ports` and `ManifestPreviewServiceInput.ports`\n * in `packages/fred/src/tools/deployApp.ts` /\n * `packages/fred/src/tools/buildManifestPreview.ts`. The empty `{}`\n * value is required by fred's validator (see\n * `packages/fred/src/manifest.ts`).\n */\ntype FredPortMap = Record<string, Record<string, never>>;\n\n/**\n * Internal shape used to build both preview and deploy service entries.\n * Assignable to both `ManifestPreviewServiceInput` (readonly fields) and\n * fred's `ServiceConfig` (mutable fields) — mutable arrays widen to\n * readonly arrays at the assignment site.\n */\ninterface ConvertedService {\n image: string;\n ports?: FredPortMap;\n env?: Record<string, string>;\n args?: string[];\n command?: string[];\n}\n\n/**\n * Convert a `ServiceDef.ports: number[]` to fred's canonical port-map\n * shape. Protocol defaults to `tcp` (the only protocol exposed via the\n * agent-core surface today; UDP is deferred until a caller needs it).\n */\nfunction toPortMap(ports: readonly number[]): FredPortMap {\n const map: FredPortMap = {};\n for (const port of ports) {\n map[`${port}/tcp`] = {};\n }\n return map;\n}\n\n/**\n * Map a single `ServiceDef` (agent-core spec shape) → fred's\n * `ServiceConfig` shape. Omits optional fields when absent so callers\n * can compare emitted objects with `'foo' in out` checks (rather than\n * `out.foo === undefined`, which a `key: undefined` spread would defeat).\n */\nfunction convertServiceDef(svc: ServiceDef): ConvertedService {\n const out: ConvertedService = { image: svc.image };\n if (svc.ports !== undefined && svc.ports.length > 0) {\n out.ports = toPortMap(svc.ports);\n }\n if (svc.env !== undefined) out.env = svc.env;\n if (svc.args !== undefined) out.args = [...svc.args];\n if (svc.command !== undefined) out.command = [...svc.command];\n return out;\n}\n\nfunction convertStackServices(\n spec: StackSpec,\n): Record<string, ConvertedService> {\n const out: Record<string, ConvertedService> = {};\n for (const [name, svc] of Object.entries(spec.services)) {\n out[name] = convertServiceDef(svc);\n }\n return out;\n}\n\n/**\n * Narrow `SingleServiceSpec.port: number | number[] | undefined` to\n * fred's single-service `port: number | undefined`.\n *\n * - `undefined` → `undefined`\n * - `80` → `80`\n * - `[80]` → `80` (single-element array convenience)\n * - `[80, 443, …]` → `ManifestMCPError(INVALID_CONFIG)`\n *\n * Strategy (a) per the ENG-185 sub-PR A brief: rejecting multi-element\n * arrays at the builder boundary kills the prior silent `port[0]`\n * truncation. The error message points the caller at the `StackSpec`\n * escape hatch where multi-port routing is natively expressible.\n */\nfunction narrowSingleServicePort(\n port: number | number[] | undefined,\n): number | undefined {\n if (port === undefined) return undefined;\n if (typeof port === 'number') return port;\n if (Array.isArray(port)) {\n if (port.length === 0) return undefined;\n if (port.length === 1) return port[0];\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'SingleServiceSpec.port: multi-port single-service is not supported — use a StackSpec with explicit `services.<name>.ports` to expose multiple ports.',\n );\n }\n // Unreachable under the typed contract; defensive for `as unknown as`\n // callers that bypass the compile-time guard.\n return undefined;\n}\n\n/**\n * Build fred's `BuildManifestPreviewInput` from a typed `DeploySpec`.\n *\n * Stack arm: each `ServiceDef.ports: number[]` is converted to\n * `{<port>/tcp: {}}`. Services without `ports` (or with empty `[]`)\n * omit the `ports` key in the output.\n *\n * Single-service arm: `port: number` and `port: [80]` both produce\n * `port: 80`. Multi-element arrays throw INVALID_CONFIG.\n *\n * Deploy-only fields (`customDomain`, `serviceName`) are deliberately\n * NOT forwarded — the preview path computes only the manifest meta-hash;\n * domain claims happen later in the deploy path.\n *\n * The `size` parameter is accepted for signature parity with\n * `buildFredDeployInput` but is NOT included in the returned object:\n * fred's `BuildManifestPreviewInput` type has no `size` field and\n * `buildManifestPreview` derives no behavior from it. The prior inline\n * builder emitted `size` via an `as unknown as` cast that hid the\n * type-contract violation; this version drops it cleanly.\n */\nexport function buildManifestPreviewInput(\n spec: DeploySpec,\n // Reserved for signature parity with buildFredDeployInput; not consumed.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _size: string,\n): BuildManifestPreviewInput {\n if (isStackSpec(spec)) {\n return { services: convertStackServices(spec) };\n }\n const port = narrowSingleServicePort(spec.port);\n return {\n image: spec.image,\n ...(port !== undefined ? { port } : {}),\n ...(spec.env !== undefined ? { env: spec.env } : {}),\n };\n}\n\n/**\n * Build fred's `DeployAppInput` from a typed `DeploySpec`.\n *\n * Same port-shape conversion as `buildManifestPreviewInput` (so the\n * meta-hash recorded on-chain matches the manifest actually uploaded).\n * Additionally threads `customDomain` (both shapes) and `serviceName`\n * (stack only — single-service leases have no service-name to address).\n *\n * @param pin Optional pre-resolved SKU pin (ENG-258). When supplied, spreads\n * `skuUuid` and `providerUuid` into the output so fred's `deployApp` skips\n * the name-based lookup (uses the `resolved` selector path). Existing\n * 2-arg callers are unaffected — the parameter is optional.\n */\nexport function buildFredDeployInput(\n spec: DeploySpec,\n size: string,\n pin?: { skuUuid: string; providerUuid: string },\n): FredDeployAppInput {\n if (isStackSpec(spec)) {\n const out: FredDeployAppInput = {\n size,\n services: convertStackServices(spec),\n ...(pin ? { skuUuid: pin.skuUuid, providerUuid: pin.providerUuid } : {}),\n };\n if (typeof spec.customDomain === 'string' && spec.customDomain.length > 0) {\n out.customDomain = spec.customDomain;\n if (typeof spec.serviceName === 'string' && spec.serviceName.length > 0) {\n out.serviceName = spec.serviceName;\n }\n }\n return out;\n }\n const port = narrowSingleServicePort(spec.port);\n const out: FredDeployAppInput = {\n size,\n image: spec.image,\n ...(pin ? { skuUuid: pin.skuUuid, providerUuid: pin.providerUuid } : {}),\n };\n if (port !== undefined) out.port = port;\n if (spec.env !== undefined) out.env = spec.env;\n if (typeof spec.customDomain === 'string' && spec.customDomain.length > 0) {\n out.customDomain = spec.customDomain;\n }\n return out;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,SAAS,UAAU,OAAuC;CACxD,MAAM,MAAmB,CAAC;CAC1B,KAAK,MAAM,QAAQ,OACjB,IAAI,GAAG,KAAK,SAAS,CAAC;CAExB,OAAO;AACT;;;;;;;AAQA,SAAS,kBAAkB,KAAmC;CAC5D,MAAM,MAAwB,EAAE,OAAO,IAAI,MAAM;CACjD,IAAI,IAAI,UAAU,KAAA,KAAa,IAAI,MAAM,SAAS,GAChD,IAAI,QAAQ,UAAU,IAAI,KAAK;CAEjC,IAAI,IAAI,QAAQ,KAAA,GAAW,IAAI,MAAM,IAAI;CACzC,IAAI,IAAI,SAAS,KAAA,GAAW,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI;CACnD,IAAI,IAAI,YAAY,KAAA,GAAW,IAAI,UAAU,CAAC,GAAG,IAAI,OAAO;CAC5D,OAAO;AACT;AAEA,SAAS,qBACP,MACkC;CAClC,MAAM,MAAwC,CAAC;CAC/C,KAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,QAAQ,GACpD,IAAI,QAAQ,kBAAkB,GAAG;CAEnC,OAAO;AACT;;;;;;;;;;;;;;;AAgBA,SAAS,wBACP,MACoB;CACpB,IAAI,SAAS,KAAA,GAAW,OAAO,KAAA;CAC/B,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,MAAM,QAAQ,IAAI,GAAG;EACvB,IAAI,KAAK,WAAW,GAAG,OAAO,KAAA;EAC9B,IAAI,KAAK,WAAW,GAAG,OAAO,KAAK;EACnC,MAAM,IAAI,iBACR,qBAAqB,gBACrB,sJACF;CACF;AAIF;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,0BACd,MAGA,OAC2B;CAC3B,IAAI,YAAY,IAAI,GAClB,OAAO,EAAE,UAAU,qBAAqB,IAAI,EAAE;CAEhD,MAAM,OAAO,wBAAwB,KAAK,IAAI;CAC9C,OAAO;EACL,OAAO,KAAK;EACZ,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,KAAK,QAAQ,KAAA,IAAY,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;CACpD;AACF;;;;;;;;;;;;;;AAeA,SAAgB,qBACd,MACA,MACA,KACoB;CACpB,IAAI,YAAY,IAAI,GAAG;EACrB,MAAM,MAA0B;GAC9B;GACA,UAAU,qBAAqB,IAAI;GACnC,GAAI,MAAM;IAAE,SAAS,IAAI;IAAS,cAAc,IAAI;GAAa,IAAI,CAAC;EACxE;EACA,IAAI,OAAO,KAAK,iBAAiB,YAAY,KAAK,aAAa,SAAS,GAAG;GACzE,IAAI,eAAe,KAAK;GACxB,IAAI,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,SAAS,GACpE,IAAI,cAAc,KAAK;EAE3B;EACA,OAAO;CACT;CACA,MAAM,OAAO,wBAAwB,KAAK,IAAI;CAC9C,MAAM,MAA0B;EAC9B;EACA,OAAO,KAAK;EACZ,GAAI,MAAM;GAAE,SAAS,IAAI;GAAS,cAAc,IAAI;EAAa,IAAI,CAAC;CACxE;CACA,IAAI,SAAS,KAAA,GAAW,IAAI,OAAO;CACnC,IAAI,KAAK,QAAQ,KAAA,GAAW,IAAI,MAAM,KAAK;CAC3C,IAAI,OAAO,KAAK,iBAAiB,YAAY,KAAK,aAAa,SAAS,GACtE,IAAI,eAAe,KAAK;CAE1B,OAAO;AACT"}