@manifest-network/manifest-mcp-fred 0.13.0 → 0.13.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"fred.d.ts","names":[],"sources":["../../src/http/fred.ts"],"mappings":"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"}
1
+ {"version":3,"file":"fred.d.ts","names":[],"sources":["../../src/http/fred.ts"],"mappings":"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"}
package/dist/http/fred.js CHANGED
@@ -59,6 +59,31 @@ const CHAIN_STATE_TO_LEASE_STATE = {
59
59
  function leaseStateName(state) {
60
60
  return LeaseState[state] ?? String(state);
61
61
  }
62
+ /**
63
+ * Provider `provision_status` values (fred backend `ProvisionStatus`) that mean
64
+ * the lease is not yet confirmed healthy while the chain lease is already
65
+ * ACTIVE — keep polling. `failing` is the pre-terminal window before `failed`
66
+ * (the backend state machine only ever moves `failing → failed`, never back to
67
+ * provisioning, so waiting is bounded). `unknown` is the backend's indeterminate
68
+ * signal — an unrecognized container status or a state-machine read error — and
69
+ * likewise is "not confirmed ready", so we wait for it to settle to
70
+ * `ready`/`failed` rather than reporting it as success. A status string this
71
+ * client does not recognize at all (a genuinely future value) is NOT listed
72
+ * here; the ACTIVE branch treats it as settled (see below).
73
+ */
74
+ const PROVISION_IN_PROGRESS = new Set([
75
+ "provisioning",
76
+ "restarting",
77
+ "updating",
78
+ "failing",
79
+ "unknown"
80
+ ]);
81
+ /**
82
+ * Provider `provision_status` values that mean provisioning will not become
83
+ * healthy. The chain lease is ACTIVE, but the deployment has effectively failed
84
+ * (or is being torn down) — surface it as an error instead of a ready lease.
85
+ */
86
+ const PROVISION_FAILED = new Set(["failed", "deprovisioning"]);
62
87
  var TerminalChainStateError = class TerminalChainStateError extends ProviderApiError {
63
88
  constructor(leaseUuid, chainState, context) {
64
89
  const mapped = CHAIN_STATE_TO_LEASE_STATE[chainState];
@@ -105,6 +130,7 @@ async function pollLeaseUntilReady(providerUrl, leaseUuid, authToken, opts = {},
105
130
  const { intervalMs = 3e3, timeoutMs = 12e4, abortSignal, onProgress, checkChainState } = opts;
106
131
  const deadline = Date.now() + timeoutMs;
107
132
  let lastState;
133
+ let lastProvisionStatus;
108
134
  while (Date.now() < deadline) {
109
135
  abortSignal?.throwIfAborted();
110
136
  if (checkChainState) {
@@ -116,9 +142,17 @@ async function pollLeaseUntilReady(providerUrl, leaseUuid, authToken, opts = {},
116
142
  abortSignal?.throwIfAborted();
117
143
  const status = await getLeaseStatus(providerUrl, leaseUuid, token, fetchFn);
118
144
  lastState = status.state;
145
+ lastProvisionStatus = status.provision_status;
119
146
  onProgress?.(status);
120
147
  switch (status.state) {
121
- case LeaseState.LEASE_STATE_ACTIVE: return status;
148
+ case LeaseState.LEASE_STATE_ACTIVE: {
149
+ const ps = status.provision_status;
150
+ if (ps !== void 0) {
151
+ if (PROVISION_FAILED.has(ps)) throw new ProviderApiError(0, `Lease ${leaseUuid} is ACTIVE but provisioning ${ps}${status.last_error ? `: ${status.last_error}` : ""}`);
152
+ if (PROVISION_IN_PROGRESS.has(ps)) break;
153
+ }
154
+ return status;
155
+ }
122
156
  case LeaseState.LEASE_STATE_PENDING: break;
123
157
  case LeaseState.LEASE_STATE_CLOSED:
124
158
  case LeaseState.LEASE_STATE_REJECTED:
@@ -127,7 +161,7 @@ async function pollLeaseUntilReady(providerUrl, leaseUuid, authToken, opts = {},
127
161
  }
128
162
  await abortableSleep(intervalMs, abortSignal);
129
163
  }
130
- throw new ProviderApiError(0, `Lease ${leaseUuid} poll timed out after ${timeoutMs}ms (last state: ${lastState !== void 0 ? leaseStateName(lastState) : "unknown"})`);
164
+ throw new ProviderApiError(0, `Lease ${leaseUuid} poll timed out after ${timeoutMs}ms (last state: ${lastState !== void 0 ? leaseStateName(lastState) : "unknown"}, provision_status: ${lastProvisionStatus ?? "unknown"})`);
131
165
  }
132
166
  //#endregion
133
167
  export { MAX_TAIL, TerminalChainStateError, getLeaseInfo, getLeaseLogs, getLeaseProvision, getLeaseReleases, getLeaseStatus, pollLeaseUntilReady, restartLease, updateLease };
@@ -1 +1 @@
1
- {"version":3,"file":"fred.js","names":[],"sources":["../../src/http/fred.ts"],"sourcesContent":["import { toBase64 } from '@cosmjs/encoding';\nimport {\n LeaseState,\n leaseStateFromJSON,\n logger,\n} from '@manifest-network/manifest-mcp-core';\nimport {\n checkedFetch,\n ProviderApiError,\n parseJsonResponse,\n validateProviderUrl,\n} from './provider.js';\n\nexport const MAX_TAIL = 1000;\n\nexport interface FredInstanceInfo {\n readonly name: string;\n readonly status: string;\n readonly ports?: Record<string, number>;\n readonly fqdn?: string;\n}\n\nexport interface FredServiceStatus {\n readonly instances: readonly FredInstanceInfo[];\n}\n\nexport interface FredLeaseStatus {\n readonly state: LeaseState;\n readonly provision_status?: string;\n readonly phase?: string;\n readonly steps?: Record<string, string>;\n readonly instances?: readonly FredInstanceInfo[];\n readonly endpoints?: Record<string, string>;\n readonly last_error?: string;\n readonly fail_count?: number;\n readonly created_at?: string;\n readonly services?: Record<string, FredServiceStatus>;\n}\n\n/** Raw wire shape before LeaseState conversion */\ninterface RawLeaseStatus extends Omit<FredLeaseStatus, 'state'> {\n readonly state: string;\n}\n\nexport async function getLeaseStatus(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseStatus> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/status`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n const raw = await parseJsonResponse<RawLeaseStatus>(res, url);\n const state = leaseStateFromJSON(raw.state);\n if (state === LeaseState.UNRECOGNIZED) {\n logger.warn(\n `[getLeaseStatus] Unrecognized lease state \"${raw.state}\" for lease ${leaseUuid}. ` +\n 'The provider may be running a newer version than the client supports.',\n );\n }\n return { ...raw, state };\n}\n\nexport interface FredLeaseLogs {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly logs: Record<string, string>;\n}\n\nexport async function getLeaseLogs(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n tail?: number,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseLogs> {\n const validated = validateProviderUrl(providerUrl);\n const cappedTail = tail !== undefined ? Math.min(tail, MAX_TAIL) : undefined;\n const qs = cappedTail !== undefined ? `?tail=${cappedTail}` : '';\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/logs${qs}`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseLogs>(res, url);\n}\n\nexport interface FredLeaseProvision {\n readonly status: string;\n readonly fail_count: number;\n /**\n * Set only when the most recent provisioning attempt failed. The Fred\n * provider omits the field on success, so the optional marker matches\n * the wire shape (and matches the same field on FredLeaseStatus above).\n */\n readonly last_error?: string;\n}\n\nexport async function getLeaseProvision(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseProvision> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/provision`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseProvision>(res, url);\n}\n\nexport interface FredActionResponse {\n readonly status: string;\n}\n\nexport async function restartLease(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredActionResponse> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/restart`;\n const res = await checkedFetch(\n url,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredActionResponse>(res, url);\n}\n\nexport async function updateLease(\n providerUrl: string,\n leaseUuid: string,\n payload: Uint8Array,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredActionResponse> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/update`;\n // The provider expects JSON with a base64-encoded payload (Go []byte field).\n const b64 = toBase64(payload);\n const res = await checkedFetch(\n url,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ payload: b64 }),\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredActionResponse>(res, url);\n}\n\nexport interface FredLeaseRelease {\n readonly version: number;\n readonly image: string;\n readonly status: string;\n readonly created_at: string;\n readonly error?: string;\n readonly manifest?: string;\n}\n\nexport interface FredLeaseReleases {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly releases: readonly FredLeaseRelease[];\n}\n\nexport async function getLeaseReleases(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseReleases> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/releases`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseReleases>(res, url);\n}\n\nexport interface FredLeaseInfo {\n readonly host: string;\n readonly ports?: Record<string, unknown>;\n}\n\nexport async function getLeaseInfo(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseInfo> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/info`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseInfo>(res, url);\n}\n\nexport type TerminalChainLeaseState = 'closed' | 'rejected' | 'expired';\n\nexport interface TerminalChainState {\n readonly state: TerminalChainLeaseState;\n}\n\nexport interface PollOptions {\n readonly intervalMs?: number;\n readonly timeoutMs?: number;\n readonly abortSignal?: AbortSignal;\n readonly onProgress?: (status: FredLeaseStatus) => void;\n /** Runs once per iteration before the provider is queried. Non-null return throws; errors propagate. */\n readonly checkChainState?: () => Promise<TerminalChainState | null>;\n}\n\nconst CHAIN_STATE_TO_LEASE_STATE: Record<TerminalChainLeaseState, LeaseState> =\n {\n closed: LeaseState.LEASE_STATE_CLOSED,\n rejected: LeaseState.LEASE_STATE_REJECTED,\n expired: LeaseState.LEASE_STATE_EXPIRED,\n };\n\nfunction leaseStateName(state: LeaseState): string {\n return LeaseState[state] ?? String(state);\n}\n\n/**\n * Thrown by pollLeaseUntilReady when the caller's checkChainState callback\n * reports a terminal lease state on-chain. Extends ProviderApiError so\n * existing catchers keep working; use `instanceof TerminalChainStateError`\n * or read `chainState` to distinguish from provider-reported terminal states.\n */\nexport interface TerminalChainStateContext {\n readonly lease_uuid?: string;\n readonly providerUuid?: string;\n readonly providerUrl?: string;\n}\n\nexport class TerminalChainStateError extends ProviderApiError {\n public readonly chainState: TerminalChainLeaseState;\n public readonly leaseUuid: string;\n public readonly providerUuid?: string;\n public readonly providerUrl?: string;\n /**\n * Structured context for downstream classifiers (e.g. agent-core's\n * classify-deploy-error). `lease_uuid` is always present so callers can name\n * the affected lease without re-deriving it from the message; provider keys\n * appear once `withContext` enriches the error.\n */\n public readonly details: {\n readonly lease_uuid: string;\n readonly provider_uuid?: string;\n readonly provider_url?: string;\n };\n\n constructor(\n leaseUuid: string,\n chainState: TerminalChainLeaseState,\n context?: TerminalChainStateContext,\n ) {\n const mapped = CHAIN_STATE_TO_LEASE_STATE[chainState];\n super(\n 0,\n `Lease ${leaseUuid} entered terminal state ${leaseStateName(mapped)} on chain`,\n );\n this.name = 'TerminalChainStateError';\n this.chainState = chainState;\n this.leaseUuid = leaseUuid;\n this.providerUuid = context?.providerUuid;\n this.providerUrl = context?.providerUrl;\n this.details = {\n lease_uuid: context?.lease_uuid ?? leaseUuid,\n provider_uuid: context?.providerUuid,\n provider_url: context?.providerUrl,\n };\n Object.setPrototypeOf(this, TerminalChainStateError.prototype);\n }\n\n /**\n * Returns a new instance with the same lease/state and the supplied context,\n * preserving the original stack trace so debugging points to where the\n * terminal state was first detected.\n */\n withContext(context: TerminalChainStateContext): TerminalChainStateError {\n const enriched = new TerminalChainStateError(\n this.leaseUuid,\n this.chainState,\n context,\n );\n if (this.stack) enriched.stack = this.stack;\n return enriched;\n }\n}\n\nfunction abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));\n signal.throwIfAborted();\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(\n signal.reason ??\n new DOMException('The operation was aborted', 'AbortError'),\n );\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nexport async function pollLeaseUntilReady(\n providerUrl: string,\n leaseUuid: string,\n authToken: string | (() => Promise<string>),\n opts: PollOptions = {},\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseStatus> {\n const {\n intervalMs = 3_000,\n timeoutMs = 120_000,\n abortSignal,\n onProgress,\n checkChainState,\n } = opts;\n const deadline = Date.now() + timeoutMs;\n let lastState: LeaseState | undefined;\n\n while (Date.now() < deadline) {\n abortSignal?.throwIfAborted();\n if (checkChainState) {\n const chainState = await checkChainState();\n if (chainState) {\n throw new TerminalChainStateError(leaseUuid, chainState.state);\n }\n abortSignal?.throwIfAborted();\n }\n const token =\n typeof authToken === 'function' ? await authToken() : authToken;\n abortSignal?.throwIfAborted();\n const status = await getLeaseStatus(providerUrl, leaseUuid, token, fetchFn);\n lastState = status.state;\n onProgress?.(status);\n switch (status.state) {\n case LeaseState.LEASE_STATE_ACTIVE:\n return status;\n case LeaseState.LEASE_STATE_PENDING:\n break;\n case LeaseState.LEASE_STATE_CLOSED:\n case LeaseState.LEASE_STATE_REJECTED:\n case LeaseState.LEASE_STATE_EXPIRED:\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} entered terminal state ${leaseStateName(status.state)}`,\n );\n default:\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} returned unexpected state ${leaseStateName(status.state)}`,\n );\n }\n await abortableSleep(intervalMs, abortSignal);\n }\n\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} poll timed out after ${timeoutMs}ms (last state: ${lastState !== undefined ? leaseStateName(lastState) : 'unknown'})`,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fred.js","names":[],"sources":["../../src/http/fred.ts"],"sourcesContent":["import { toBase64 } from '@cosmjs/encoding';\nimport {\n LeaseState,\n leaseStateFromJSON,\n logger,\n} from '@manifest-network/manifest-mcp-core';\nimport {\n checkedFetch,\n ProviderApiError,\n parseJsonResponse,\n validateProviderUrl,\n} from './provider.js';\n\nexport const MAX_TAIL = 1000;\n\nexport interface FredInstanceInfo {\n readonly name: string;\n readonly status: string;\n readonly ports?: Record<string, number>;\n readonly fqdn?: string;\n}\n\nexport interface FredServiceStatus {\n readonly instances: readonly FredInstanceInfo[];\n}\n\nexport interface FredLeaseStatus {\n readonly state: LeaseState;\n readonly provision_status?: string;\n readonly phase?: string;\n readonly steps?: Record<string, string>;\n readonly instances?: readonly FredInstanceInfo[];\n readonly endpoints?: Record<string, string>;\n readonly last_error?: string;\n readonly fail_count?: number;\n readonly created_at?: string;\n readonly services?: Record<string, FredServiceStatus>;\n}\n\n/** Raw wire shape before LeaseState conversion */\ninterface RawLeaseStatus extends Omit<FredLeaseStatus, 'state'> {\n readonly state: string;\n}\n\nexport async function getLeaseStatus(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseStatus> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/status`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n const raw = await parseJsonResponse<RawLeaseStatus>(res, url);\n const state = leaseStateFromJSON(raw.state);\n if (state === LeaseState.UNRECOGNIZED) {\n logger.warn(\n `[getLeaseStatus] Unrecognized lease state \"${raw.state}\" for lease ${leaseUuid}. ` +\n 'The provider may be running a newer version than the client supports.',\n );\n }\n return { ...raw, state };\n}\n\nexport interface FredLeaseLogs {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly logs: Record<string, string>;\n}\n\nexport async function getLeaseLogs(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n tail?: number,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseLogs> {\n const validated = validateProviderUrl(providerUrl);\n const cappedTail = tail !== undefined ? Math.min(tail, MAX_TAIL) : undefined;\n const qs = cappedTail !== undefined ? `?tail=${cappedTail}` : '';\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/logs${qs}`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseLogs>(res, url);\n}\n\nexport interface FredLeaseProvision {\n readonly status: string;\n readonly fail_count: number;\n /**\n * Set only when the most recent provisioning attempt failed. The Fred\n * provider omits the field on success, so the optional marker matches\n * the wire shape (and matches the same field on FredLeaseStatus above).\n */\n readonly last_error?: string;\n}\n\nexport async function getLeaseProvision(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseProvision> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/provision`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseProvision>(res, url);\n}\n\nexport interface FredActionResponse {\n readonly status: string;\n}\n\nexport async function restartLease(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredActionResponse> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/restart`;\n const res = await checkedFetch(\n url,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredActionResponse>(res, url);\n}\n\nexport async function updateLease(\n providerUrl: string,\n leaseUuid: string,\n payload: Uint8Array,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredActionResponse> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/update`;\n // The provider expects JSON with a base64-encoded payload (Go []byte field).\n const b64 = toBase64(payload);\n const res = await checkedFetch(\n url,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ payload: b64 }),\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredActionResponse>(res, url);\n}\n\nexport interface FredLeaseRelease {\n readonly version: number;\n readonly image: string;\n readonly status: string;\n readonly created_at: string;\n readonly error?: string;\n readonly manifest?: string;\n}\n\nexport interface FredLeaseReleases {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly releases: readonly FredLeaseRelease[];\n}\n\nexport async function getLeaseReleases(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseReleases> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/releases`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseReleases>(res, url);\n}\n\nexport interface FredLeaseInfo {\n readonly host: string;\n readonly ports?: Record<string, unknown>;\n}\n\nexport async function getLeaseInfo(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseInfo> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/info`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseInfo>(res, url);\n}\n\nexport type TerminalChainLeaseState = 'closed' | 'rejected' | 'expired';\n\nexport interface TerminalChainState {\n readonly state: TerminalChainLeaseState;\n}\n\nexport interface PollOptions {\n readonly intervalMs?: number;\n readonly timeoutMs?: number;\n readonly abortSignal?: AbortSignal;\n readonly onProgress?: (status: FredLeaseStatus) => void;\n /** Runs once per iteration before the provider is queried. Non-null return throws; errors propagate. */\n readonly checkChainState?: () => Promise<TerminalChainState | null>;\n}\n\nconst CHAIN_STATE_TO_LEASE_STATE: Record<TerminalChainLeaseState, LeaseState> =\n {\n closed: LeaseState.LEASE_STATE_CLOSED,\n rejected: LeaseState.LEASE_STATE_REJECTED,\n expired: LeaseState.LEASE_STATE_EXPIRED,\n };\n\nfunction leaseStateName(state: LeaseState): string {\n return LeaseState[state] ?? String(state);\n}\n\n/**\n * Provider `provision_status` values (fred backend `ProvisionStatus`) that mean\n * the lease is not yet confirmed healthy while the chain lease is already\n * ACTIVE — keep polling. `failing` is the pre-terminal window before `failed`\n * (the backend state machine only ever moves `failing → failed`, never back to\n * provisioning, so waiting is bounded). `unknown` is the backend's indeterminate\n * signal — an unrecognized container status or a state-machine read error — and\n * likewise is \"not confirmed ready\", so we wait for it to settle to\n * `ready`/`failed` rather than reporting it as success. A status string this\n * client does not recognize at all (a genuinely future value) is NOT listed\n * here; the ACTIVE branch treats it as settled (see below).\n */\nconst PROVISION_IN_PROGRESS: ReadonlySet<string> = new Set([\n 'provisioning',\n 'restarting',\n 'updating',\n 'failing',\n 'unknown',\n]);\n\n/**\n * Provider `provision_status` values that mean provisioning will not become\n * healthy. The chain lease is ACTIVE, but the deployment has effectively failed\n * (or is being torn down) — surface it as an error instead of a ready lease.\n */\nconst PROVISION_FAILED: ReadonlySet<string> = new Set([\n 'failed',\n 'deprovisioning',\n]);\n\n/**\n * Thrown by pollLeaseUntilReady when the caller's checkChainState callback\n * reports a terminal lease state on-chain. Extends ProviderApiError so\n * existing catchers keep working; use `instanceof TerminalChainStateError`\n * or read `chainState` to distinguish from provider-reported terminal states.\n */\nexport interface TerminalChainStateContext {\n readonly lease_uuid?: string;\n readonly providerUuid?: string;\n readonly providerUrl?: string;\n}\n\nexport class TerminalChainStateError extends ProviderApiError {\n public readonly chainState: TerminalChainLeaseState;\n public readonly leaseUuid: string;\n public readonly providerUuid?: string;\n public readonly providerUrl?: string;\n /**\n * Structured context for downstream classifiers (e.g. agent-core's\n * classify-deploy-error). `lease_uuid` is always present so callers can name\n * the affected lease without re-deriving it from the message; provider keys\n * appear once `withContext` enriches the error.\n */\n public readonly details: {\n readonly lease_uuid: string;\n readonly provider_uuid?: string;\n readonly provider_url?: string;\n };\n\n constructor(\n leaseUuid: string,\n chainState: TerminalChainLeaseState,\n context?: TerminalChainStateContext,\n ) {\n const mapped = CHAIN_STATE_TO_LEASE_STATE[chainState];\n super(\n 0,\n `Lease ${leaseUuid} entered terminal state ${leaseStateName(mapped)} on chain`,\n );\n this.name = 'TerminalChainStateError';\n this.chainState = chainState;\n this.leaseUuid = leaseUuid;\n this.providerUuid = context?.providerUuid;\n this.providerUrl = context?.providerUrl;\n this.details = {\n lease_uuid: context?.lease_uuid ?? leaseUuid,\n provider_uuid: context?.providerUuid,\n provider_url: context?.providerUrl,\n };\n Object.setPrototypeOf(this, TerminalChainStateError.prototype);\n }\n\n /**\n * Returns a new instance with the same lease/state and the supplied context,\n * preserving the original stack trace so debugging points to where the\n * terminal state was first detected.\n */\n withContext(context: TerminalChainStateContext): TerminalChainStateError {\n const enriched = new TerminalChainStateError(\n this.leaseUuid,\n this.chainState,\n context,\n );\n if (this.stack) enriched.stack = this.stack;\n return enriched;\n }\n}\n\nfunction abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));\n signal.throwIfAborted();\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(\n signal.reason ??\n new DOMException('The operation was aborted', 'AbortError'),\n );\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nexport async function pollLeaseUntilReady(\n providerUrl: string,\n leaseUuid: string,\n authToken: string | (() => Promise<string>),\n opts: PollOptions = {},\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseStatus> {\n const {\n intervalMs = 3_000,\n timeoutMs = 120_000,\n abortSignal,\n onProgress,\n checkChainState,\n } = opts;\n const deadline = Date.now() + timeoutMs;\n let lastState: LeaseState | undefined;\n let lastProvisionStatus: string | undefined;\n\n while (Date.now() < deadline) {\n abortSignal?.throwIfAborted();\n if (checkChainState) {\n const chainState = await checkChainState();\n if (chainState) {\n throw new TerminalChainStateError(leaseUuid, chainState.state);\n }\n abortSignal?.throwIfAborted();\n }\n const token =\n typeof authToken === 'function' ? await authToken() : authToken;\n abortSignal?.throwIfAborted();\n const status = await getLeaseStatus(providerUrl, leaseUuid, token, fetchFn);\n lastState = status.state;\n lastProvisionStatus = status.provision_status;\n onProgress?.(status);\n switch (status.state) {\n case LeaseState.LEASE_STATE_ACTIVE: {\n // The chain lease is ACTIVE, but the provider may still be pulling the\n // image / starting the container — or the container may have crashed.\n // Gate readiness on provision_status so callers never observe a lease as\n // ready mid-provision. An absent field, or a status string this client\n // does not recognize (a future value), is treated as settled —\n // forward-compat, and it preserves the original ACTIVE-returns behavior\n // for providers that don't populate the field.\n const ps = status.provision_status;\n if (ps !== undefined) {\n if (PROVISION_FAILED.has(ps)) {\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} is ACTIVE but provisioning ${ps}${\n status.last_error ? `: ${status.last_error}` : ''\n }`,\n );\n }\n if (PROVISION_IN_PROGRESS.has(ps)) {\n break; // still provisioning — keep polling\n }\n }\n return status;\n }\n case LeaseState.LEASE_STATE_PENDING:\n break;\n case LeaseState.LEASE_STATE_CLOSED:\n case LeaseState.LEASE_STATE_REJECTED:\n case LeaseState.LEASE_STATE_EXPIRED:\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} entered terminal state ${leaseStateName(status.state)}`,\n );\n default:\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} returned unexpected state ${leaseStateName(status.state)}`,\n );\n }\n await abortableSleep(intervalMs, abortSignal);\n }\n\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} poll timed out after ${timeoutMs}ms (last state: ${lastState !== undefined ? leaseStateName(lastState) : 'unknown'}, provision_status: ${lastProvisionStatus ?? 'unknown'})`,\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manifest-network/manifest-mcp-fred",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "MCP server for Manifest provider (Fred) operations (deploy, status, logs, restart, update)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,7 +51,7 @@
51
51
  ],
52
52
  "dependencies": {
53
53
  "@cosmjs/encoding": "0.32.4",
54
- "@manifest-network/manifest-mcp-core": "^0.13.0",
54
+ "@manifest-network/manifest-mcp-core": "^0.13.1",
55
55
  "@modelcontextprotocol/sdk": "1.29.0",
56
56
  "zod": "^4.3.6"
57
57
  },