@forgeax/engine-dsh 0.1.4 → 0.1.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocol.ts","../src/index.ts","../src/embedded.ts"],"names":[],"mappings":"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","file":"embedded.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport function isFederationCommunityCapability(\n value: unknown,\n): value is FederationCommunityCapability {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return typeof record.id === 'string' && typeof record.value === 'string';\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { randomUUID } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { createWorldContext, Update, World } from '@forgeax/engine-ecs';\nimport type { Context } from '@forgeax/engine-plugin';\n\nimport {\n FEDERATION_PROTOCOL_VERSION,\n FEDERATION_ROUTE_PREFIX,\n type FederationActivityResult,\n type FederationCommunityCapability,\n type FederationStatus,\n} from './protocol';\n\ninterface WebRoute {\n readonly kind: 'exact' | 'prefix';\n readonly path: string;\n readonly handler: (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;\n}\n\ninterface WebServerService {\n register(route: WebRoute): () => void;\n}\n\ninterface DshHostContext {\n readonly webServer: WebServerService;\n readonly logger: { warn(error: unknown): void };\n effect(callback: () => void | (() => void | Promise<void>), label?: string): void;\n get(name: string): unknown;\n}\n\ninterface CommunityProbeService {\n inspect(): FederationCommunityCapability | Promise<FederationCommunityCapability>;\n}\n\ninterface IntelligenceCapabilityService {\n run(\n input: string,\n sessionId: string,\n ): FederationActivityResult | Promise<FederationActivityResult>;\n}\n\nconst MAX_ACTIVITY_BODY_BYTES = 65_536 as const;\n\ntype ActivityBodyResult =\n | { readonly ok: true; readonly value: unknown }\n | {\n readonly ok: false;\n readonly status: 400;\n readonly body: { readonly code: 'federation-activity-invalid' };\n }\n | {\n readonly ok: false;\n readonly status: 413;\n readonly body: {\n readonly code: 'federation-activity-body-too-large';\n readonly limit: typeof MAX_ACTIVITY_BODY_BYTES;\n };\n };\n\nexport interface Config {\n readonly engineEndpoint?: string;\n readonly identity?: string;\n}\n\nexport const inject = ['webServer'];\n\n/** DSH-native Host half. DSH's Loader mounts this ordinary plugin from the package patch. */\nexport async function apply(ctx: DshHostContext, config: Config = {}): Promise<void> {\n const identity = config.identity ?? `dsh-${randomUUID()}`;\n const leases = new Set<string>();\n let tick = 0;\n let state = 0;\n let embeddedContext: Context | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n ctx.effect(\n () => async () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers.reverse()) dispose();\n leases.clear();\n if (timer !== undefined) clearInterval(timer);\n await embeddedContext?.fiber.dispose();\n },\n 'forgeax-federation: routes and embedded engine',\n );\n\n if (config.engineEndpoint === undefined) {\n const world = new World();\n embeddedContext = await createWorldContext(world);\n world\n .addSystem(Update, {\n name: 'forgeax-federation-headless-tick',\n queries: [],\n fn: () => {\n tick += 1;\n },\n })\n .unwrap();\n timer = setInterval(() => {\n const result = world.update(1 / 30);\n if (!result.ok) ctx.logger.warn(result.error);\n }, 1000 / 30);\n }\n\n const status = (): FederationStatus => ({\n protocol: FEDERATION_PROTOCOL_VERSION,\n identity,\n ready: true,\n realm: 'dsh',\n capabilities: ['lease', 'community-probe', 'engine-projection'],\n leases: leases.size,\n engine:\n config.engineEndpoint === undefined\n ? { binding: 'embedded', ready: true, frameId: tick, tick, state }\n : { binding: 'external', endpoint: config.engineEndpoint, ready: true },\n });\n\n disposers.push(\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/status`,\n handler(_request, response) {\n writeJson(response, 200, status());\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/activity`,\n async handler(request, response) {\n if (request.method !== 'POST') {\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n return;\n }\n const candidate = ctx.get('forgeaxIntelligenceCapability') as\n | IntelligenceCapabilityService\n | undefined;\n if (candidate === undefined || typeof candidate.run !== 'function') {\n writeJson(response, 404, { code: 'federation-intelligence-capability-missing' });\n return;\n }\n const parsed = await readJsonBody(request);\n if (!parsed.ok) {\n writeJson(response, parsed.status, parsed.body);\n return;\n }\n const body = parsed.value;\n if (\n typeof body !== 'object' ||\n body === null ||\n typeof Reflect.get(body, 'input') !== 'string' ||\n typeof Reflect.get(body, 'sessionId') !== 'string'\n ) {\n writeJson(response, 400, { code: 'federation-activity-invalid' });\n return;\n }\n writeJson(\n response,\n 200,\n await candidate.run(Reflect.get(body, 'input'), Reflect.get(body, 'sessionId')),\n );\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/lease`,\n handler(request, response) {\n if (request.method === 'POST') {\n const leaseId = randomUUID();\n leases.add(leaseId);\n writeJson(response, 201, { leaseId });\n return;\n }\n if (request.method === 'DELETE') {\n const leaseId = new URL(request.url ?? '/', 'http://localhost').searchParams.get(\n 'leaseId',\n );\n if (leaseId !== null) leases.delete(leaseId);\n writeJson(response, 200, { released: leaseId !== null });\n return;\n }\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/community`,\n async handler(_request, response) {\n const candidate = ctx.get('forgeaxFederationCapability') as\n | CommunityProbeService\n | undefined;\n if (candidate === undefined || typeof candidate.inspect !== 'function') {\n writeJson(response, 404, { code: 'federation-community-capability-missing' });\n return;\n }\n let community: FederationCommunityCapability;\n try {\n community = await candidate.inspect();\n } catch {\n writeJson(response, 503, { code: 'federation-community-capability-failed' });\n return;\n }\n writeJson(response, 200, community);\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/engine/control`,\n handler(request, response) {\n if (request.method !== 'POST' || config.engineEndpoint !== undefined) {\n writeJson(response, 409, { code: 'federation-engine-control-unavailable' });\n return;\n }\n state = state === 0 ? 1 : 0;\n writeJson(response, 200, status().engine);\n },\n }),\n );\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<ActivityBodyResult> {\n const chunks: Buffer[] = [];\n let size = 0;\n let tooLarge = false;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n if (tooLarge) continue;\n size += buffer.byteLength;\n if (size > MAX_ACTIVITY_BODY_BYTES) {\n tooLarge = true;\n chunks.length = 0;\n continue;\n }\n chunks.push(buffer);\n }\n if (tooLarge) {\n return {\n ok: false,\n status: 413,\n body: { code: 'federation-activity-body-too-large', limit: MAX_ACTIVITY_BODY_BYTES },\n };\n }\n try {\n return { ok: true, value: JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown };\n } catch {\n return { ok: false, status: 400, body: { code: 'federation-activity-invalid' } };\n }\n}\n\nfunction writeJson(response: ServerResponse, status: number, value: unknown): void {\n response.writeHead(status, {\n 'cache-control': 'no-store',\n 'content-type': 'application/json; charset=utf-8',\n });\n response.end(JSON.stringify(value));\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\n\nimport { Context, type Plugin } from '@forgeax/engine-plugin';\n\nimport { apply as federationApply, inject as federationInject } from './index';\n\ninterface Route {\n readonly kind: 'exact' | 'prefix';\n readonly path: string;\n readonly handler: (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;\n}\n\nclass EmbeddedWebServer {\n private readonly routes = new Set<Route>();\n\n register(route: Route): () => void {\n this.routes.add(route);\n return () => this.routes.delete(route);\n }\n\n match(pathname: string): Route | undefined {\n return [...this.routes].find((route) =>\n route.kind === 'exact'\n ? pathname === route.path\n : pathname === route.path || pathname.startsWith(`${route.path}/`),\n );\n }\n}\n\nconst routes = new EmbeddedWebServer();\nconst server = createServer((request, response) => {\n const pathname = new URL(request.url ?? '/', 'http://localhost').pathname;\n const route = routes.match(pathname);\n if (route === undefined) {\n response.writeHead(404);\n response.end();\n return;\n }\n Promise.resolve(route.handler(request, response)).catch(() => {\n if (!response.headersSent) response.writeHead(500);\n response.end();\n });\n});\n\nawait new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(0, '127.0.0.1', () => resolve());\n});\n\nconst context = new Context();\nconst carrier: Plugin = {\n name: 'embedded-webserver',\n provide: 'webServer',\n apply(ctx) {\n const provide = ctx.provide as unknown as (name: string, value: unknown) => void;\n provide.call(ctx, 'webServer', routes);\n },\n};\nawait context.plugin(carrier);\nawait context.plugin({\n name: 'forgeax-federation',\n inject: federationInject,\n apply: federationApply as unknown as Plugin['apply'],\n});\n\nconst address = server.address() as AddressInfo;\nprocess.stdout.write(`forgeax embedded: http://127.0.0.1:${address.port}\\n`);\n\nlet closing = false;\nconst close = async (): Promise<void> => {\n if (closing) return;\n closing = true;\n await context.fiber.dispose();\n await new Promise<void>((resolve) => server.close(() => resolve()));\n};\n\nprocess.once('SIGTERM', () => {\n void close().then(() => process.exit(0));\n});\nprocess.once('SIGINT', () => {\n void close().then(() => process.exit(0));\n});\n"]}
1
+ {"version":3,"sources":["../src/protocol.ts","../src/index.ts","../src/embedded.ts"],"names":[],"mappings":"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","file":"embedded.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { randomUUID } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { createWorldContext, Update, World } from '@forgeax/engine-ecs';\nimport type { Context } from '@forgeax/engine-plugin';\n\nimport {\n FEDERATION_PROTOCOL_VERSION,\n FEDERATION_ROUTE_PREFIX,\n type FederationActivityResult,\n type FederationCommunityCapability,\n type FederationStatus,\n} from './protocol';\n\ninterface WebRoute {\n readonly kind: 'exact' | 'prefix';\n readonly path: string;\n readonly handler: (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;\n}\n\ninterface WebServerService {\n register(route: WebRoute): () => void;\n}\n\ninterface DshHostContext {\n readonly webServer: WebServerService;\n readonly logger: { warn(error: unknown): void };\n effect(callback: () => void | (() => void | Promise<void>), label?: string): void;\n get(name: string): unknown;\n}\n\ninterface CommunityProbeService {\n inspect(): FederationCommunityCapability | Promise<FederationCommunityCapability>;\n}\n\ninterface IntelligenceCapabilityService {\n run(\n input: string,\n sessionId: string,\n ): FederationActivityResult | Promise<FederationActivityResult>;\n}\n\nexport interface Config {\n readonly engineEndpoint?: string;\n readonly identity?: string;\n}\n\nexport const inject = ['webServer'];\n\n/** DSH-native Host half. DSH's Loader mounts this ordinary plugin from the package patch. */\nexport async function apply(ctx: DshHostContext, config: Config = {}): Promise<void> {\n const identity = config.identity ?? `dsh-${randomUUID()}`;\n const leases = new Set<string>();\n let tick = 0;\n let state = 0;\n let embeddedContext: Context | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n ctx.effect(\n () => async () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers.reverse()) dispose();\n leases.clear();\n if (timer !== undefined) clearInterval(timer);\n await embeddedContext?.fiber.dispose();\n },\n 'forgeax-federation: routes and embedded engine',\n );\n\n if (config.engineEndpoint === undefined) {\n const world = new World();\n embeddedContext = await createWorldContext(world);\n world\n .addSystem(Update, {\n name: 'forgeax-federation-headless-tick',\n queries: [],\n fn: () => {\n tick += 1;\n },\n })\n .unwrap();\n timer = setInterval(() => {\n const result = world.update(1 / 30);\n if (!result.ok) ctx.logger.warn(result.error);\n }, 1000 / 30);\n }\n\n const status = (): FederationStatus => ({\n protocol: FEDERATION_PROTOCOL_VERSION,\n identity,\n ready: true,\n realm: 'dsh',\n capabilities: ['lease', 'community-probe', 'engine-projection'],\n leases: leases.size,\n engine:\n config.engineEndpoint === undefined\n ? { binding: 'embedded', ready: true, frameId: tick, tick, state }\n : { binding: 'external', endpoint: config.engineEndpoint, ready: true },\n });\n\n disposers.push(\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/status`,\n handler(_request, response) {\n writeJson(response, 200, status());\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/activity`,\n async handler(request, response) {\n if (request.method !== 'POST') {\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n return;\n }\n const candidate = ctx.get('forgeaxIntelligenceCapability') as\n | IntelligenceCapabilityService\n | undefined;\n if (candidate === undefined || typeof candidate.run !== 'function') {\n writeJson(response, 404, { code: 'federation-intelligence-capability-missing' });\n return;\n }\n const body = await readJsonBody(request);\n if (\n typeof body !== 'object' ||\n body === null ||\n typeof Reflect.get(body, 'input') !== 'string' ||\n typeof Reflect.get(body, 'sessionId') !== 'string'\n ) {\n writeJson(response, 400, { code: 'federation-activity-invalid' });\n return;\n }\n writeJson(\n response,\n 200,\n await candidate.run(Reflect.get(body, 'input'), Reflect.get(body, 'sessionId')),\n );\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/lease`,\n handler(request, response) {\n if (request.method === 'POST') {\n const leaseId = randomUUID();\n leases.add(leaseId);\n writeJson(response, 201, { leaseId });\n return;\n }\n if (request.method === 'DELETE') {\n const leaseId = new URL(request.url ?? '/', 'http://localhost').searchParams.get(\n 'leaseId',\n );\n if (leaseId !== null) leases.delete(leaseId);\n writeJson(response, 200, { released: leaseId !== null });\n return;\n }\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/community`,\n async handler(_request, response) {\n const candidate = ctx.get('forgeaxFederationCapability') as\n | CommunityProbeService\n | undefined;\n if (candidate === undefined || typeof candidate.inspect !== 'function') {\n writeJson(response, 404, { code: 'federation-community-capability-missing' });\n return;\n }\n writeJson(response, 200, await candidate.inspect());\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/engine/control`,\n handler(request, response) {\n if (request.method !== 'POST' || config.engineEndpoint !== undefined) {\n writeJson(response, 409, { code: 'federation-engine-control-unavailable' });\n return;\n }\n state = state === 0 ? 1 : 0;\n writeJson(response, 200, status().engine);\n },\n }),\n );\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.byteLength;\n if (size > 65_536) throw new Error('federation request exceeds 65536 bytes');\n chunks.push(buffer);\n }\n return JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown;\n}\n\nfunction writeJson(response: ServerResponse, status: number, value: unknown): void {\n response.writeHead(status, {\n 'cache-control': 'no-store',\n 'content-type': 'application/json; charset=utf-8',\n });\n response.end(JSON.stringify(value));\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\n\nimport { Context, type Plugin } from '@forgeax/engine-plugin';\n\nimport { apply as federationApply, inject as federationInject } from './index';\n\ninterface Route {\n readonly kind: 'exact' | 'prefix';\n readonly path: string;\n readonly handler: (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;\n}\n\nclass EmbeddedWebServer {\n private readonly routes = new Set<Route>();\n\n register(route: Route): () => void {\n this.routes.add(route);\n return () => this.routes.delete(route);\n }\n\n match(pathname: string): Route | undefined {\n return [...this.routes].find((route) =>\n route.kind === 'exact'\n ? pathname === route.path\n : pathname === route.path || pathname.startsWith(`${route.path}/`),\n );\n }\n}\n\nconst routes = new EmbeddedWebServer();\nconst server = createServer((request, response) => {\n const pathname = new URL(request.url ?? '/', 'http://localhost').pathname;\n const route = routes.match(pathname);\n if (route === undefined) {\n response.writeHead(404);\n response.end();\n return;\n }\n Promise.resolve(route.handler(request, response)).catch(() => {\n if (!response.headersSent) response.writeHead(500);\n response.end();\n });\n});\n\nawait new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(0, '127.0.0.1', () => resolve());\n});\n\nconst context = new Context();\nconst carrier: Plugin = {\n name: 'embedded-webserver',\n provide: 'webServer',\n apply(ctx) {\n const provide = ctx.provide as unknown as (name: string, value: unknown) => void;\n provide.call(ctx, 'webServer', routes);\n },\n};\nawait context.plugin(carrier);\nawait context.plugin({\n name: 'forgeax-federation',\n inject: federationInject,\n apply: federationApply as unknown as Plugin['apply'],\n});\n\nconst address = server.address() as AddressInfo;\nprocess.stdout.write(`forgeax embedded: http://127.0.0.1:${address.port}\\n`);\n\nlet closing = false;\nconst close = async (): Promise<void> => {\n if (closing) return;\n closing = true;\n await context.fiber.dispose();\n await new Promise<void>((resolve) => server.close(() => resolve()));\n};\n\nprocess.once('SIGTERM', () => {\n void close().then(() => process.exit(0));\n});\nprocess.once('SIGINT', () => {\n void close().then(() => process.exit(0));\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"engine-host.d.ts","sourceRoot":"","sources":["../src/engine-host.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,6BAA6B,EAElC,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAGtB,MAAM,YAAY,CAAC;AAEpB,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAU,qBAAqB;QAC7B,QAAQ,EAAE,kBAAkB,CAAC;KAC9B;CACF;AAED,MAAM,MAAM,iBAAiB,GACzB,wBAAwB,GACxB,yBAAyB,GACzB,mBAAmB,GACnB,uBAAuB,GACvB,kBAAkB,GAClB,sBAAsB,CAAC;AAE3B,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;gBAGjD,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,KAAK,CAAC,EAAE,OAAO;CASlB;AAED,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,SAAS,IAAI,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACpD,QAAQ,CACN,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,4GAA4G;AAC5G,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAY1E;AAED,wBAAsB,eAAe,CACnC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,CAehD"}
1
+ {"version":3,"file":"engine-host.d.ts","sourceRoot":"","sources":["../src/engine-host.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,6BAA6B,EAElC,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAEtB,MAAM,YAAY,CAAC;AAEpB,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAU,qBAAqB;QAC7B,QAAQ,EAAE,kBAAkB,CAAC;KAC9B;CACF;AAED,MAAM,MAAM,iBAAiB,GACzB,wBAAwB,GACxB,yBAAyB,GACzB,mBAAmB,GACnB,uBAAuB,GACvB,kBAAkB,GAClB,sBAAsB,CAAC;AAE3B,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;gBAGjD,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,KAAK,CAAC,EAAE,OAAO;CASlB;AAED,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,SAAS,IAAI,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACpD,QAAQ,CACN,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,4GAA4G;AAC5G,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAY1E;AAED,wBAAsB,eAAe,CACnC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,CAehD"}
@@ -9,11 +9,6 @@ import { ok, err } from '@forgeax/engine-types';
9
9
  // src/protocol.ts
10
10
  var FEDERATION_PROTOCOL_VERSION = 1;
11
11
  var FEDERATION_ROUTE_PREFIX = "/forgeax-federation/v1";
12
- function isFederationCommunityCapability(value) {
13
- if (typeof value !== "object" || value === null) return false;
14
- const record = value;
15
- return typeof record.id === "string" && typeof record.value === "string";
16
- }
17
12
  function isFederationStatus(value) {
18
13
  if (typeof value !== "object" || value === null) return false;
19
14
  const record = value;
@@ -95,23 +90,12 @@ async function attach(endpoint, timeoutMs) {
95
90
  const status = await waitForStatus(normalized, timeoutMs, "attach");
96
91
  const leaseId = await acquireLease(normalized);
97
92
  let disposed = false;
98
- let releaseAttempt;
99
93
  return {
100
94
  connection: connection(normalized, "attach", "lease", status),
101
95
  async dispose() {
102
96
  if (disposed) return;
103
- if (releaseAttempt !== void 0) return releaseAttempt;
104
- const attempt = releaseLease(normalized, leaseId).then(
105
- () => {
106
- disposed = true;
107
- },
108
- (cause) => {
109
- releaseAttempt = void 0;
110
- throw cause;
111
- }
112
- );
113
- releaseAttempt = attempt;
114
- return attempt;
97
+ disposed = true;
98
+ await releaseLease(normalized, leaseId);
115
99
  }
116
100
  };
117
101
  }
@@ -167,27 +151,7 @@ function connection(endpoint, binding, ownership, status) {
167
151
  { endpoint, status: response.status }
168
152
  );
169
153
  }
170
- let value;
171
- try {
172
- value = await response.json();
173
- } catch (cause) {
174
- throw new DshRealmError(
175
- "dsh-community-failed",
176
- "the DSH-native community capability to answer through the bridge",
177
- "Install and enable a DSH plugin that provides forgeaxFederationCapability.",
178
- { endpoint, reason: "invalid-json" },
179
- cause
180
- );
181
- }
182
- if (!isFederationCommunityCapability(value)) {
183
- throw new DshRealmError(
184
- "dsh-community-failed",
185
- "the DSH-native community capability to answer through the bridge",
186
- "Install and enable a DSH plugin that provides forgeaxFederationCapability.",
187
- { endpoint, received: value }
188
- );
189
- }
190
- return value;
154
+ return await response.json();
191
155
  },
192
156
  async activity(input, sessionId, signal) {
193
157
  const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/activity`, {
@@ -271,26 +235,9 @@ async function acquireLease(endpoint) {
271
235
  return lease.leaseId;
272
236
  }
273
237
  async function releaseLease(endpoint, leaseId) {
274
- try {
275
- const response = await fetch(
276
- `${endpoint}${FEDERATION_ROUTE_PREFIX}/lease?leaseId=${encodeURIComponent(leaseId)}`,
277
- { method: "DELETE" }
278
- );
279
- if (!response.ok) {
280
- throw leaseReleaseError(endpoint, { status: response.status });
281
- }
282
- } catch (cause) {
283
- if (cause instanceof DshRealmError) throw cause;
284
- throw leaseReleaseError(endpoint, { reason: "transport" }, cause);
285
- }
286
- }
287
- function leaseReleaseError(endpoint, detail, cause) {
288
- return new DshRealmError(
289
- "dsh-lease-failed",
290
- "the attached bridge lease to release",
291
- "Keep the ConnectedRealm and retry disposal after the target can accept the release.",
292
- { endpoint, ...detail },
293
- cause
238
+ await fetch(
239
+ `${endpoint}${FEDERATION_ROUTE_PREFIX}/lease?leaseId=${encodeURIComponent(leaseId)}`,
240
+ { method: "DELETE" }
294
241
  );
295
242
  }
296
243
  function readLaunchEndpoint(child, timeoutMs, target) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocol.ts","../src/engine-host.ts"],"names":[],"mappings":"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","file":"engine-host.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport function isFederationCommunityCapability(\n value: unknown,\n): value is FederationCommunityCapability {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return typeof record.id === 'string' && typeof record.value === 'string';\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport { access } from 'node:fs/promises';\nimport { delimiter, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { Plugin } from '@forgeax/engine-plugin';\nimport { err, ok, type Result } from '@forgeax/engine-types';\n\nimport {\n FEDERATION_PROTOCOL_VERSION,\n FEDERATION_ROUTE_PREFIX,\n type FederationActivityResult,\n type FederationBinding,\n type FederationCommunityCapability,\n type FederationLease,\n type FederationOwnership,\n type FederationStatus,\n isFederationCommunityCapability,\n isFederationStatus,\n} from './protocol';\n\ndeclare module '@forgeax/engine-plugin' {\n interface EngineContextServices {\n dshRealm: DshRealmConnection;\n }\n}\n\nexport type DshRealmErrorCode =\n | 'dsh-target-unavailable'\n | 'dsh-target-incompatible'\n | 'dsh-launch-failed'\n | 'dsh-handshake-timeout'\n | 'dsh-lease-failed'\n | 'dsh-community-failed';\n\nexport class DshRealmError extends Error {\n readonly code: DshRealmErrorCode;\n readonly expected: string;\n readonly hint: string;\n readonly detail: Readonly<Record<string, unknown>>;\n\n constructor(\n code: DshRealmErrorCode,\n expected: string,\n hint: string,\n detail: Readonly<Record<string, unknown>>,\n cause?: unknown,\n ) {\n super(`${code}: ${expected}`, cause === undefined ? undefined : { cause });\n this.name = 'DshRealmError';\n this.code = code;\n this.expected = expected;\n this.hint = hint;\n this.detail = detail;\n }\n}\n\nexport interface DshRealmPluginOptions {\n /** Attach to an already-running compatible DSH realm. Never closes that realm. */\n readonly endpoint?: string;\n /** Explicit DSH executable. Omit to discover `dsh` on PATH. */\n readonly executable?: string;\n readonly profile?: string;\n readonly home?: string;\n readonly cwd?: string;\n readonly handshakeTimeoutMs?: number;\n readonly allowEmbedded?: boolean;\n}\n\nexport interface DshRealmConnection {\n readonly endpoint: string;\n readonly binding: FederationBinding;\n readonly ownership: FederationOwnership;\n readonly status: FederationStatus;\n community(): Promise<FederationCommunityCapability>;\n activity(\n input: string,\n sessionId: string,\n signal?: AbortSignal,\n ): Promise<FederationActivityResult>;\n}\n\nexport interface ConnectedRealm {\n readonly connection: DshRealmConnection;\n dispose(): Promise<void>;\n}\n\n/** Engine-side Realm Host Plugin. It publishes no service until handshake and lease acquisition succeed. */\nexport function dshRealmPlugin(options: DshRealmPluginOptions = {}): Plugin {\n return {\n name: 'dsh-realm',\n provide: 'dshRealm',\n async apply(ctx) {\n const result = await connectDshRealm(options);\n if (!result.ok) throw result.error;\n const connected = result.value;\n ctx.effect(() => () => connected.dispose(), 'dsh-realm: binding ownership');\n ctx.provide('dshRealm', connected.connection);\n },\n };\n}\n\nexport async function connectDshRealm(\n options: DshRealmPluginOptions = {},\n): Promise<Result<ConnectedRealm, DshRealmError>> {\n try {\n return ok(await resolveDshRealm(options));\n } catch (cause) {\n if (cause instanceof DshRealmError) return err(cause);\n return err(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the DSH realm binding to initialize',\n 'Inspect the selected endpoint, executable, profile, and process diagnostics.',\n { binding: options.endpoint === undefined ? 'launch' : 'attach' },\n cause,\n ),\n );\n }\n}\n\nasync function resolveDshRealm(options: DshRealmPluginOptions): Promise<ConnectedRealm> {\n const timeoutMs = options.handshakeTimeoutMs ?? 10_000;\n if (options.endpoint !== undefined) {\n return attach(options.endpoint, timeoutMs);\n }\n\n const executable =\n options.executable === undefined ? await discoverOnPath('dsh') : options.executable;\n if (executable !== undefined) {\n return launchExternal(executable, options, timeoutMs);\n }\n if (options.allowEmbedded === false) {\n throw new DshRealmError(\n 'dsh-target-unavailable',\n 'a compatible explicit endpoint or local dsh executable',\n 'Install DeepSeek Harness, pass executable/endpoint, or allow the packaged minimum fallback.',\n { binding: 'external' },\n );\n }\n return launchEmbedded(timeoutMs);\n}\n\nasync function attach(endpoint: string, timeoutMs: number): Promise<ConnectedRealm> {\n const normalized = normalizeEndpoint(endpoint);\n const status = await waitForStatus(normalized, timeoutMs, 'attach');\n const leaseId = await acquireLease(normalized);\n let disposed = false;\n let releaseAttempt: Promise<void> | undefined;\n return {\n connection: connection(normalized, 'attach', 'lease', status),\n async dispose() {\n if (disposed) return;\n if (releaseAttempt !== undefined) return releaseAttempt;\n const attempt = releaseLease(normalized, leaseId).then(\n () => {\n disposed = true;\n },\n (cause) => {\n releaseAttempt = undefined;\n throw cause;\n },\n );\n releaseAttempt = attempt;\n return attempt;\n },\n };\n}\n\nasync function launchExternal(\n executable: string,\n options: DshRealmPluginOptions,\n timeoutMs: number,\n): Promise<ConnectedRealm> {\n const args = ['--profile', options.profile ?? 'web', '--host', '127.0.0.1', '--port', '0'];\n const child = spawn(executable, args, {\n cwd: options.cwd,\n env: {\n ...process.env,\n ...(options.home === undefined ? {} : { DSH_HOME: options.home }),\n },\n });\n return finishLaunch(child, 'external', timeoutMs, executable);\n}\n\nasync function launchEmbedded(timeoutMs: number): Promise<ConnectedRealm> {\n const entry = fileURLToPath(new URL('./embedded.mjs', import.meta.url));\n const child = spawn(process.execPath, [entry], { env: process.env });\n return finishLaunch(child, 'embedded', timeoutMs, entry);\n}\n\nasync function finishLaunch(\n child: ChildProcessWithoutNullStreams,\n binding: Exclude<FederationBinding, 'attach'>,\n timeoutMs: number,\n target: string,\n): Promise<ConnectedRealm> {\n try {\n const endpoint = await readLaunchEndpoint(child, timeoutMs, target);\n const status = await waitForStatus(endpoint, timeoutMs, binding);\n const leaseId = await acquireLease(endpoint);\n let disposed = false;\n return {\n connection: connection(endpoint, binding, 'instance', status),\n async dispose() {\n if (disposed) return;\n disposed = true;\n await releaseLease(endpoint, leaseId).catch(() => undefined);\n await stopChild(child);\n },\n };\n } catch (error) {\n await stopChild(child);\n throw error;\n }\n}\n\nfunction connection(\n endpoint: string,\n binding: FederationBinding,\n ownership: FederationOwnership,\n status: FederationStatus,\n): DshRealmConnection {\n return {\n endpoint,\n binding,\n ownership,\n status,\n async community() {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/community`);\n if (!response.ok) {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'the DSH-native community capability to answer through the bridge',\n 'Install and enable a DSH plugin that provides forgeaxFederationCapability.',\n { endpoint, status: response.status },\n );\n }\n let value: unknown;\n try {\n value = await response.json();\n } catch (cause) {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'the DSH-native community capability to answer through the bridge',\n 'Install and enable a DSH plugin that provides forgeaxFederationCapability.',\n { endpoint, reason: 'invalid-json' },\n cause,\n );\n }\n if (!isFederationCommunityCapability(value)) {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'the DSH-native community capability to answer through the bridge',\n 'Install and enable a DSH plugin that provides forgeaxFederationCapability.',\n { endpoint, received: value },\n );\n }\n return value;\n },\n async activity(input, sessionId, signal) {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/activity`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ input, sessionId }),\n ...(signal === undefined ? {} : { signal }),\n });\n if (!response.ok) {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'a DSH-native intelligence capability to answer through the bridge',\n 'Install and enable a DSH plugin that provides forgeaxIntelligenceCapability.',\n { endpoint, status: response.status },\n );\n }\n const value = (await response.json()) as Partial<FederationActivityResult>;\n if (typeof value.output !== 'string') {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'the DSH intelligence bridge to return text output',\n 'Use a capability plugin compatible with federation protocol 1.',\n { endpoint, received: value },\n );\n }\n return { output: value.output };\n },\n };\n}\n\nasync function waitForStatus(\n endpoint: string,\n timeoutMs: number,\n binding: FederationBinding,\n): Promise<FederationStatus> {\n const deadline = Date.now() + timeoutMs;\n let last: unknown;\n while (Date.now() < deadline) {\n try {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/status`);\n if (response.ok) {\n const value: unknown = await response.json();\n if (!isFederationStatus(value) || value.protocol !== FEDERATION_PROTOCOL_VERSION) {\n throw new DshRealmError(\n 'dsh-target-incompatible',\n `DSH federation protocol ${FEDERATION_PROTOCOL_VERSION}`,\n 'Use a connector version that matches this Engine package.',\n { binding, endpoint, received: value },\n );\n }\n return value;\n }\n last = response.status;\n } catch (error) {\n if (error instanceof DshRealmError) throw error;\n last = error;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n throw new DshRealmError(\n 'dsh-handshake-timeout',\n `a ready federation endpoint within ${timeoutMs}ms`,\n 'Install @forgeax/engine-dsh into the selected DSH profile and inspect its native Loader diagnostics.',\n { binding, endpoint, last },\n );\n}\n\nasync function acquireLease(endpoint: string): Promise<string> {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/lease`, { method: 'POST' });\n if (!response.ok) {\n throw new DshRealmError(\n 'dsh-lease-failed',\n 'a lease-scoped bridge activation',\n 'The target must support lease acquisition and release before attach is safe.',\n { endpoint, status: response.status },\n );\n }\n const lease = (await response.json()) as Partial<FederationLease>;\n if (typeof lease.leaseId !== 'string') {\n throw new DshRealmError(\n 'dsh-lease-failed',\n 'a string leaseId',\n 'Update the target connector to the matching protocol version.',\n { endpoint, received: lease },\n );\n }\n return lease.leaseId;\n}\n\nasync function releaseLease(endpoint: string, leaseId: string): Promise<void> {\n try {\n const response = await fetch(\n `${endpoint}${FEDERATION_ROUTE_PREFIX}/lease?leaseId=${encodeURIComponent(leaseId)}`,\n { method: 'DELETE' },\n );\n if (!response.ok) {\n throw leaseReleaseError(endpoint, { status: response.status });\n }\n } catch (cause) {\n if (cause instanceof DshRealmError) throw cause;\n throw leaseReleaseError(endpoint, { reason: 'transport' }, cause);\n }\n}\n\nfunction leaseReleaseError(\n endpoint: string,\n detail: Readonly<Record<string, unknown>>,\n cause?: unknown,\n): DshRealmError {\n return new DshRealmError(\n 'dsh-lease-failed',\n 'the attached bridge lease to release',\n 'Keep the ConnectedRealm and retry disposal after the target can accept the release.',\n { endpoint, ...detail },\n cause,\n );\n}\n\nfunction readLaunchEndpoint(\n child: ChildProcessWithoutNullStreams,\n timeoutMs: number,\n target: string,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n let output = '';\n const timer = setTimeout(() => {\n cleanup();\n reject(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the launched realm to print its loopback URL',\n 'Inspect the native DSH startup and Loader diagnostics.',\n { target, output },\n ),\n );\n }, timeoutMs);\n const onData = (chunk: Buffer): void => {\n output += chunk.toString('utf8');\n const matched = output.match(/(?:dsh web|forgeax embedded):\\s+(http:\\/\\/127\\.0\\.0\\.1:\\d+)/);\n if (matched?.[1] === undefined) return;\n cleanup();\n resolve(matched[1]);\n };\n const onExit = (code: number | null): void => {\n cleanup();\n reject(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the launched realm to remain alive through readiness',\n 'Inspect the native process output and profile composition.',\n { target, code, output },\n ),\n );\n };\n const onError = (cause: Error): void => {\n cleanup();\n reject(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the selected DSH executable to start',\n 'Pass an executable file that can launch the selected native DSH profile.',\n { target, output },\n cause,\n ),\n );\n };\n const cleanup = (): void => {\n clearTimeout(timer);\n child.stdout.off('data', onData);\n child.stderr.off('data', onData);\n child.off('exit', onExit);\n child.off('error', onError);\n };\n child.stdout.on('data', onData);\n child.stderr.on('data', onData);\n child.once('exit', onExit);\n child.once('error', onError);\n });\n}\n\nasync function stopChild(child: ChildProcessWithoutNullStreams): Promise<void> {\n if (child.exitCode !== null || child.signalCode !== null) return;\n const exited = new Promise<void>((resolve) => child.once('exit', () => resolve()));\n child.kill('SIGTERM');\n const graceful = await Promise.race([\n exited.then(() => true),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), 2_000)),\n ]);\n if (!graceful && child.exitCode === null) {\n child.kill('SIGKILL');\n await exited;\n }\n}\n\nasync function discoverOnPath(name: string): Promise<string | undefined> {\n const paths = process.env.PATH?.split(delimiter) ?? [];\n for (const directory of paths) {\n const candidate = join(directory, name);\n try {\n await access(candidate);\n return candidate;\n } catch {\n // Keep scanning deterministic PATH order.\n }\n }\n return undefined;\n}\n\nfunction normalizeEndpoint(endpoint: string): string {\n return endpoint.endsWith('/') ? endpoint.slice(0, -1) : endpoint;\n}\n"]}
1
+ {"version":3,"sources":["../src/protocol.ts","../src/engine-host.ts"],"names":[],"mappings":"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","file":"engine-host.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport { access } from 'node:fs/promises';\nimport { delimiter, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { Plugin } from '@forgeax/engine-plugin';\nimport { err, ok, type Result } from '@forgeax/engine-types';\n\nimport {\n FEDERATION_PROTOCOL_VERSION,\n FEDERATION_ROUTE_PREFIX,\n type FederationActivityResult,\n type FederationBinding,\n type FederationCommunityCapability,\n type FederationLease,\n type FederationOwnership,\n type FederationStatus,\n isFederationStatus,\n} from './protocol';\n\ndeclare module '@forgeax/engine-plugin' {\n interface EngineContextServices {\n dshRealm: DshRealmConnection;\n }\n}\n\nexport type DshRealmErrorCode =\n | 'dsh-target-unavailable'\n | 'dsh-target-incompatible'\n | 'dsh-launch-failed'\n | 'dsh-handshake-timeout'\n | 'dsh-lease-failed'\n | 'dsh-community-failed';\n\nexport class DshRealmError extends Error {\n readonly code: DshRealmErrorCode;\n readonly expected: string;\n readonly hint: string;\n readonly detail: Readonly<Record<string, unknown>>;\n\n constructor(\n code: DshRealmErrorCode,\n expected: string,\n hint: string,\n detail: Readonly<Record<string, unknown>>,\n cause?: unknown,\n ) {\n super(`${code}: ${expected}`, cause === undefined ? undefined : { cause });\n this.name = 'DshRealmError';\n this.code = code;\n this.expected = expected;\n this.hint = hint;\n this.detail = detail;\n }\n}\n\nexport interface DshRealmPluginOptions {\n /** Attach to an already-running compatible DSH realm. Never closes that realm. */\n readonly endpoint?: string;\n /** Explicit DSH executable. Omit to discover `dsh` on PATH. */\n readonly executable?: string;\n readonly profile?: string;\n readonly home?: string;\n readonly cwd?: string;\n readonly handshakeTimeoutMs?: number;\n readonly allowEmbedded?: boolean;\n}\n\nexport interface DshRealmConnection {\n readonly endpoint: string;\n readonly binding: FederationBinding;\n readonly ownership: FederationOwnership;\n readonly status: FederationStatus;\n community(): Promise<FederationCommunityCapability>;\n activity(\n input: string,\n sessionId: string,\n signal?: AbortSignal,\n ): Promise<FederationActivityResult>;\n}\n\nexport interface ConnectedRealm {\n readonly connection: DshRealmConnection;\n dispose(): Promise<void>;\n}\n\n/** Engine-side Realm Host Plugin. It publishes no service until handshake and lease acquisition succeed. */\nexport function dshRealmPlugin(options: DshRealmPluginOptions = {}): Plugin {\n return {\n name: 'dsh-realm',\n provide: 'dshRealm',\n async apply(ctx) {\n const result = await connectDshRealm(options);\n if (!result.ok) throw result.error;\n const connected = result.value;\n ctx.effect(() => () => connected.dispose(), 'dsh-realm: binding ownership');\n ctx.provide('dshRealm', connected.connection);\n },\n };\n}\n\nexport async function connectDshRealm(\n options: DshRealmPluginOptions = {},\n): Promise<Result<ConnectedRealm, DshRealmError>> {\n try {\n return ok(await resolveDshRealm(options));\n } catch (cause) {\n if (cause instanceof DshRealmError) return err(cause);\n return err(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the DSH realm binding to initialize',\n 'Inspect the selected endpoint, executable, profile, and process diagnostics.',\n { binding: options.endpoint === undefined ? 'launch' : 'attach' },\n cause,\n ),\n );\n }\n}\n\nasync function resolveDshRealm(options: DshRealmPluginOptions): Promise<ConnectedRealm> {\n const timeoutMs = options.handshakeTimeoutMs ?? 10_000;\n if (options.endpoint !== undefined) {\n return attach(options.endpoint, timeoutMs);\n }\n\n const executable =\n options.executable === undefined ? await discoverOnPath('dsh') : options.executable;\n if (executable !== undefined) {\n return launchExternal(executable, options, timeoutMs);\n }\n if (options.allowEmbedded === false) {\n throw new DshRealmError(\n 'dsh-target-unavailable',\n 'a compatible explicit endpoint or local dsh executable',\n 'Install DeepSeek Harness, pass executable/endpoint, or allow the packaged minimum fallback.',\n { binding: 'external' },\n );\n }\n return launchEmbedded(timeoutMs);\n}\n\nasync function attach(endpoint: string, timeoutMs: number): Promise<ConnectedRealm> {\n const normalized = normalizeEndpoint(endpoint);\n const status = await waitForStatus(normalized, timeoutMs, 'attach');\n const leaseId = await acquireLease(normalized);\n let disposed = false;\n return {\n connection: connection(normalized, 'attach', 'lease', status),\n async dispose() {\n if (disposed) return;\n disposed = true;\n await releaseLease(normalized, leaseId);\n },\n };\n}\n\nasync function launchExternal(\n executable: string,\n options: DshRealmPluginOptions,\n timeoutMs: number,\n): Promise<ConnectedRealm> {\n const args = ['--profile', options.profile ?? 'web', '--host', '127.0.0.1', '--port', '0'];\n const child = spawn(executable, args, {\n cwd: options.cwd,\n env: {\n ...process.env,\n ...(options.home === undefined ? {} : { DSH_HOME: options.home }),\n },\n });\n return finishLaunch(child, 'external', timeoutMs, executable);\n}\n\nasync function launchEmbedded(timeoutMs: number): Promise<ConnectedRealm> {\n const entry = fileURLToPath(new URL('./embedded.mjs', import.meta.url));\n const child = spawn(process.execPath, [entry], { env: process.env });\n return finishLaunch(child, 'embedded', timeoutMs, entry);\n}\n\nasync function finishLaunch(\n child: ChildProcessWithoutNullStreams,\n binding: Exclude<FederationBinding, 'attach'>,\n timeoutMs: number,\n target: string,\n): Promise<ConnectedRealm> {\n try {\n const endpoint = await readLaunchEndpoint(child, timeoutMs, target);\n const status = await waitForStatus(endpoint, timeoutMs, binding);\n const leaseId = await acquireLease(endpoint);\n let disposed = false;\n return {\n connection: connection(endpoint, binding, 'instance', status),\n async dispose() {\n if (disposed) return;\n disposed = true;\n await releaseLease(endpoint, leaseId).catch(() => undefined);\n await stopChild(child);\n },\n };\n } catch (error) {\n await stopChild(child);\n throw error;\n }\n}\n\nfunction connection(\n endpoint: string,\n binding: FederationBinding,\n ownership: FederationOwnership,\n status: FederationStatus,\n): DshRealmConnection {\n return {\n endpoint,\n binding,\n ownership,\n status,\n async community() {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/community`);\n if (!response.ok) {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'the DSH-native community capability to answer through the bridge',\n 'Install and enable a DSH plugin that provides forgeaxFederationCapability.',\n { endpoint, status: response.status },\n );\n }\n return (await response.json()) as FederationCommunityCapability;\n },\n async activity(input, sessionId, signal) {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/activity`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ input, sessionId }),\n ...(signal === undefined ? {} : { signal }),\n });\n if (!response.ok) {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'a DSH-native intelligence capability to answer through the bridge',\n 'Install and enable a DSH plugin that provides forgeaxIntelligenceCapability.',\n { endpoint, status: response.status },\n );\n }\n const value = (await response.json()) as Partial<FederationActivityResult>;\n if (typeof value.output !== 'string') {\n throw new DshRealmError(\n 'dsh-community-failed',\n 'the DSH intelligence bridge to return text output',\n 'Use a capability plugin compatible with federation protocol 1.',\n { endpoint, received: value },\n );\n }\n return { output: value.output };\n },\n };\n}\n\nasync function waitForStatus(\n endpoint: string,\n timeoutMs: number,\n binding: FederationBinding,\n): Promise<FederationStatus> {\n const deadline = Date.now() + timeoutMs;\n let last: unknown;\n while (Date.now() < deadline) {\n try {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/status`);\n if (response.ok) {\n const value: unknown = await response.json();\n if (!isFederationStatus(value) || value.protocol !== FEDERATION_PROTOCOL_VERSION) {\n throw new DshRealmError(\n 'dsh-target-incompatible',\n `DSH federation protocol ${FEDERATION_PROTOCOL_VERSION}`,\n 'Use a connector version that matches this Engine package.',\n { binding, endpoint, received: value },\n );\n }\n return value;\n }\n last = response.status;\n } catch (error) {\n if (error instanceof DshRealmError) throw error;\n last = error;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n throw new DshRealmError(\n 'dsh-handshake-timeout',\n `a ready federation endpoint within ${timeoutMs}ms`,\n 'Install @forgeax/engine-dsh into the selected DSH profile and inspect its native Loader diagnostics.',\n { binding, endpoint, last },\n );\n}\n\nasync function acquireLease(endpoint: string): Promise<string> {\n const response = await fetch(`${endpoint}${FEDERATION_ROUTE_PREFIX}/lease`, { method: 'POST' });\n if (!response.ok) {\n throw new DshRealmError(\n 'dsh-lease-failed',\n 'a lease-scoped bridge activation',\n 'The target must support lease acquisition and release before attach is safe.',\n { endpoint, status: response.status },\n );\n }\n const lease = (await response.json()) as Partial<FederationLease>;\n if (typeof lease.leaseId !== 'string') {\n throw new DshRealmError(\n 'dsh-lease-failed',\n 'a string leaseId',\n 'Update the target connector to the matching protocol version.',\n { endpoint, received: lease },\n );\n }\n return lease.leaseId;\n}\n\nasync function releaseLease(endpoint: string, leaseId: string): Promise<void> {\n await fetch(\n `${endpoint}${FEDERATION_ROUTE_PREFIX}/lease?leaseId=${encodeURIComponent(leaseId)}`,\n { method: 'DELETE' },\n );\n}\n\nfunction readLaunchEndpoint(\n child: ChildProcessWithoutNullStreams,\n timeoutMs: number,\n target: string,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n let output = '';\n const timer = setTimeout(() => {\n cleanup();\n reject(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the launched realm to print its loopback URL',\n 'Inspect the native DSH startup and Loader diagnostics.',\n { target, output },\n ),\n );\n }, timeoutMs);\n const onData = (chunk: Buffer): void => {\n output += chunk.toString('utf8');\n const matched = output.match(/(?:dsh web|forgeax embedded):\\s+(http:\\/\\/127\\.0\\.0\\.1:\\d+)/);\n if (matched?.[1] === undefined) return;\n cleanup();\n resolve(matched[1]);\n };\n const onExit = (code: number | null): void => {\n cleanup();\n reject(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the launched realm to remain alive through readiness',\n 'Inspect the native process output and profile composition.',\n { target, code, output },\n ),\n );\n };\n const onError = (cause: Error): void => {\n cleanup();\n reject(\n new DshRealmError(\n 'dsh-launch-failed',\n 'the selected DSH executable to start',\n 'Pass an executable file that can launch the selected native DSH profile.',\n { target, output },\n cause,\n ),\n );\n };\n const cleanup = (): void => {\n clearTimeout(timer);\n child.stdout.off('data', onData);\n child.stderr.off('data', onData);\n child.off('exit', onExit);\n child.off('error', onError);\n };\n child.stdout.on('data', onData);\n child.stderr.on('data', onData);\n child.once('exit', onExit);\n child.once('error', onError);\n });\n}\n\nasync function stopChild(child: ChildProcessWithoutNullStreams): Promise<void> {\n if (child.exitCode !== null || child.signalCode !== null) return;\n const exited = new Promise<void>((resolve) => child.once('exit', () => resolve()));\n child.kill('SIGTERM');\n const graceful = await Promise.race([\n exited.then(() => true),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), 2_000)),\n ]);\n if (!graceful && child.exitCode === null) {\n child.kill('SIGKILL');\n await exited;\n }\n}\n\nasync function discoverOnPath(name: string): Promise<string | undefined> {\n const paths = process.env.PATH?.split(delimiter) ?? [];\n for (const directory of paths) {\n const candidate = join(directory, name);\n try {\n await access(candidate);\n return candidate;\n } catch {\n // Keep scanning deterministic PATH order.\n }\n }\n return undefined;\n}\n\nfunction normalizeEndpoint(endpoint: string): string {\n return endpoint.endsWith('/') ? endpoint.slice(0, -1) : endpoint;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocol.ts","../src/engine-preview.ts"],"names":[],"mappings":"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","file":"engine-preview.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport function isFederationCommunityCapability(\n value: unknown,\n): value is FederationCommunityCapability {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return typeof record.id === 'string' && typeof record.value === 'string';\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { Update } from '@forgeax/engine-ecs';\nimport type { Plugin } from '@forgeax/engine-plugin';\n\nimport {\n type EnginePreviewStatus,\n FEDERATION_PROTOCOL_VERSION,\n isEnginePreviewRequest,\n} from './protocol';\n\nexport interface EnginePreviewPluginOptions {\n readonly window?: Window;\n readonly initialState?: number;\n readonly control?: (state: number) => number | Promise<number>;\n}\n\n/**\n * Engine-native half of the DSH Web preview bridge. The effect owns one ECS\n * counter system and one postMessage listener; neither exists while disabled.\n */\nexport function enginePreviewPlugin(options: EnginePreviewPluginOptions = {}): Plugin {\n return {\n name: 'dsh-engine-preview',\n inject: ['world'],\n apply(ctx) {\n const targetWindow = options.window ?? globalThis.window;\n let tick = 0;\n let state = options.initialState ?? 0;\n const systemName = 'dsh-engine-preview-tick';\n\n ctx.effect(() => {\n ctx.world\n .addSystem(Update, {\n name: systemName,\n queries: [],\n fn: () => {\n tick += 1;\n },\n })\n .unwrap();\n\n const respond = (event: MessageEvent, value: EnginePreviewStatus): void => {\n if (event.source === null) return;\n const origin = event.origin === 'null' ? '*' : event.origin;\n (event.source as WindowProxy).postMessage(value, { targetOrigin: origin });\n };\n const snapshot = (): EnginePreviewStatus => ({\n protocol: FEDERATION_PROTOCOL_VERSION,\n kind: 'forgeax-engine-status',\n binding: 'external',\n ready: true,\n frameId: tick,\n tick,\n state,\n });\n const onMessage = (event: MessageEvent): void => {\n if (!isEnginePreviewRequest(event.data)) return;\n if (event.data.kind === 'forgeax-engine-poll') {\n respond(event, snapshot());\n return;\n }\n Promise.resolve(options.control?.(state) ?? (state === 0 ? 1 : 0))\n .then((next) => {\n state = next;\n respond(event, snapshot());\n })\n .catch(() => undefined);\n };\n targetWindow.addEventListener('message', onMessage);\n\n return () => {\n targetWindow.removeEventListener('message', onMessage);\n ctx.world.removeSystem(Update, systemName).unwrap();\n };\n }, 'dsh-engine-preview: tick and message bridge');\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/protocol.ts","../src/engine-preview.ts"],"names":[],"mappings":";;;;;AAAO,IAAM,2BAAA,GAA8B,CAAA;AAoEpC,SAAS,uBAAuB,KAAA,EAA+C;AACpF,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,MAAM,OAAO,KAAA;AACxD,EAAA,MAAM,MAAA,GAAS,KAAA;AACf,EAAA,IAAI,MAAA,CAAO,QAAA,KAAa,2BAAA,EAA6B,OAAO,KAAA;AAC5D,EAAA,IAAI,MAAA,CAAO,IAAA,KAAS,qBAAA,EAAuB,OAAO,IAAA;AAClD,EAAA,OAAO,MAAA,CAAO,IAAA,KAAS,wBAAA,IAA4B,MAAA,CAAO,MAAA,KAAW,QAAA;AACvE;;;ACvDO,SAAS,mBAAA,CAAoB,OAAA,GAAsC,EAAC,EAAW;AACpF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,oBAAA;AAAA,IACN,MAAA,EAAQ,CAAC,OAAO,CAAA;AAAA,IAChB,MAAM,GAAA,EAAK;AACT,MAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,MAAA,IAAU,UAAA,CAAW,MAAA;AAClD,MAAA,IAAI,IAAA,GAAO,CAAA;AACX,MAAA,IAAI,KAAA,GAAQ,QAAQ,YAAA,IAAgB,CAAA;AACpC,MAAA,MAAM,UAAA,GAAa,yBAAA;AAEnB,MAAA,GAAA,CAAI,OAAO,MAAM;AACf,QAAA,GAAA,CAAI,KAAA,CACD,UAAU,MAAA,EAAQ;AAAA,UACjB,IAAA,EAAM,UAAA;AAAA,UACN,SAAS,EAAC;AAAA,UACV,IAAI,MAAM;AACR,YAAA,IAAA,IAAQ,CAAA;AAAA,UACV;AAAA,SACD,EACA,MAAA,EAAO;AAEV,QAAA,MAAM,OAAA,GAAU,CAAC,KAAA,EAAqB,KAAA,KAAqC;AACzE,UAAA,IAAI,KAAA,CAAM,WAAW,IAAA,EAAM;AAC3B,UAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,KAAW,MAAA,GAAS,MAAM,KAAA,CAAM,MAAA;AACrD,UAAC,MAAM,MAAA,CAAuB,WAAA,CAAY,OAAO,EAAE,YAAA,EAAc,QAAQ,CAAA;AAAA,QAC3E,CAAA;AACA,QAAA,MAAM,WAAW,OAA4B;AAAA,UAC3C,QAAA,EAAU,2BAAA;AAAA,UACV,IAAA,EAAM,uBAAA;AAAA,UACN,OAAA,EAAS,UAAA;AAAA,UACT,KAAA,EAAO,IAAA;AAAA,UACP,OAAA,EAAS,IAAA;AAAA,UACT,IAAA;AAAA,UACA;AAAA,SACF,CAAA;AACA,QAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAA8B;AAC/C,UAAA,IAAI,CAAC,sBAAA,CAAuB,KAAA,CAAM,IAAI,CAAA,EAAG;AACzC,UAAA,IAAI,KAAA,CAAM,IAAA,CAAK,IAAA,KAAS,qBAAA,EAAuB;AAC7C,YAAA,OAAA,CAAQ,KAAA,EAAO,UAAU,CAAA;AACzB,YAAA;AAAA,UACF;AACA,UAAA,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,OAAA,GAAU,KAAK,CAAA,KAAM,KAAA,KAAU,CAAA,GAAI,CAAA,GAAI,CAAA,CAAE,CAAA,CAC9D,IAAA,CAAK,CAAC,IAAA,KAAS;AACd,YAAA,KAAA,GAAQ,IAAA;AACR,YAAA,OAAA,CAAQ,KAAA,EAAO,UAAU,CAAA;AAAA,UAC3B,CAAC,CAAA,CACA,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,QAC1B,CAAA;AACA,QAAA,YAAA,CAAa,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAElD,QAAA,OAAO,MAAM;AACX,UAAA,YAAA,CAAa,mBAAA,CAAoB,WAAW,SAAS,CAAA;AACrD,UAAA,GAAA,CAAI,KAAA,CAAM,YAAA,CAAa,MAAA,EAAQ,UAAU,EAAE,MAAA,EAAO;AAAA,QACpD,CAAA;AAAA,MACF,GAAG,6CAA6C,CAAA;AAAA,IAClD;AAAA,GACF;AACF","file":"engine-preview.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { Update } from '@forgeax/engine-ecs';\nimport type { Plugin } from '@forgeax/engine-plugin';\n\nimport {\n type EnginePreviewStatus,\n FEDERATION_PROTOCOL_VERSION,\n isEnginePreviewRequest,\n} from './protocol';\n\nexport interface EnginePreviewPluginOptions {\n readonly window?: Window;\n readonly initialState?: number;\n readonly control?: (state: number) => number | Promise<number>;\n}\n\n/**\n * Engine-native half of the DSH Web preview bridge. The effect owns one ECS\n * counter system and one postMessage listener; neither exists while disabled.\n */\nexport function enginePreviewPlugin(options: EnginePreviewPluginOptions = {}): Plugin {\n return {\n name: 'dsh-engine-preview',\n inject: ['world'],\n apply(ctx) {\n const targetWindow = options.window ?? globalThis.window;\n let tick = 0;\n let state = options.initialState ?? 0;\n const systemName = 'dsh-engine-preview-tick';\n\n ctx.effect(() => {\n ctx.world\n .addSystem(Update, {\n name: systemName,\n queries: [],\n fn: () => {\n tick += 1;\n },\n })\n .unwrap();\n\n const respond = (event: MessageEvent, value: EnginePreviewStatus): void => {\n if (event.source === null) return;\n const origin = event.origin === 'null' ? '*' : event.origin;\n (event.source as WindowProxy).postMessage(value, { targetOrigin: origin });\n };\n const snapshot = (): EnginePreviewStatus => ({\n protocol: FEDERATION_PROTOCOL_VERSION,\n kind: 'forgeax-engine-status',\n binding: 'external',\n ready: true,\n frameId: tick,\n tick,\n state,\n });\n const onMessage = (event: MessageEvent): void => {\n if (!isEnginePreviewRequest(event.data)) return;\n if (event.data.kind === 'forgeax-engine-poll') {\n respond(event, snapshot());\n return;\n }\n Promise.resolve(options.control?.(state) ?? (state === 0 ? 1 : 0))\n .then((next) => {\n state = next;\n respond(event, snapshot());\n })\n .catch(() => undefined);\n };\n targetWindow.addEventListener('message', onMessage);\n\n return () => {\n targetWindow.removeEventListener('message', onMessage);\n ctx.world.removeSystem(Update, systemName).unwrap();\n };\n }, 'dsh-engine-preview: tick and message bridge');\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAajE,UAAU,QAAQ;IAChB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChG;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,IAAI,CAAC;CACvC;AAED,UAAU,cAAc;IACtB,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AA+BD,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,MAAM,UAAgB,CAAC;AAEpC,6FAA6F;AAC7F,wBAAsB,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyJnF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAajE,UAAU,QAAQ;IAChB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChG;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,IAAI,CAAC;CACvC;AAED,UAAU,cAAc;IACtB,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAaD,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,MAAM,UAAgB,CAAC;AAEpC,6FAA6F;AAC7F,wBAAsB,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA6InF"}
package/dist/index.mjs CHANGED
@@ -8,7 +8,6 @@ var FEDERATION_PROTOCOL_VERSION = 1;
8
8
  var FEDERATION_ROUTE_PREFIX = "/forgeax-federation/v1";
9
9
 
10
10
  // src/index.ts
11
- var MAX_ACTIVITY_BODY_BYTES = 65536;
12
11
  var inject = ["webServer"];
13
12
  async function apply(ctx, config = {}) {
14
13
  const identity = config.identity ?? `dsh-${randomUUID()}`;
@@ -75,12 +74,7 @@ async function apply(ctx, config = {}) {
75
74
  writeJson(response, 404, { code: "federation-intelligence-capability-missing" });
76
75
  return;
77
76
  }
78
- const parsed = await readJsonBody(request);
79
- if (!parsed.ok) {
80
- writeJson(response, parsed.status, parsed.body);
81
- return;
82
- }
83
- const body = parsed.value;
77
+ const body = await readJsonBody(request);
84
78
  if (typeof body !== "object" || body === null || typeof Reflect.get(body, "input") !== "string" || typeof Reflect.get(body, "sessionId") !== "string") {
85
79
  writeJson(response, 400, { code: "federation-activity-invalid" });
86
80
  return;
@@ -122,14 +116,7 @@ async function apply(ctx, config = {}) {
122
116
  writeJson(response, 404, { code: "federation-community-capability-missing" });
123
117
  return;
124
118
  }
125
- let community;
126
- try {
127
- community = await candidate.inspect();
128
- } catch {
129
- writeJson(response, 503, { code: "federation-community-capability-failed" });
130
- return;
131
- }
132
- writeJson(response, 200, community);
119
+ writeJson(response, 200, await candidate.inspect());
133
120
  }
134
121
  }),
135
122
  ctx.webServer.register({
@@ -149,30 +136,13 @@ async function apply(ctx, config = {}) {
149
136
  async function readJsonBody(request) {
150
137
  const chunks = [];
151
138
  let size = 0;
152
- let tooLarge = false;
153
139
  for await (const chunk of request) {
154
140
  const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
155
- if (tooLarge) continue;
156
141
  size += buffer.byteLength;
157
- if (size > MAX_ACTIVITY_BODY_BYTES) {
158
- tooLarge = true;
159
- chunks.length = 0;
160
- continue;
161
- }
142
+ if (size > 65536) throw new Error("federation request exceeds 65536 bytes");
162
143
  chunks.push(buffer);
163
144
  }
164
- if (tooLarge) {
165
- return {
166
- ok: false,
167
- status: 413,
168
- body: { code: "federation-activity-body-too-large", limit: MAX_ACTIVITY_BODY_BYTES }
169
- };
170
- }
171
- try {
172
- return { ok: true, value: JSON.parse(Buffer.concat(chunks).toString("utf8")) };
173
- } catch {
174
- return { ok: false, status: 400, body: { code: "federation-activity-invalid" } };
175
- }
145
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
176
146
  }
177
147
  function writeJson(response, status, value) {
178
148
  response.writeHead(status, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocol.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport function isFederationCommunityCapability(\n value: unknown,\n): value is FederationCommunityCapability {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return typeof record.id === 'string' && typeof record.value === 'string';\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { randomUUID } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { createWorldContext, Update, World } from '@forgeax/engine-ecs';\nimport type { Context } from '@forgeax/engine-plugin';\n\nimport {\n FEDERATION_PROTOCOL_VERSION,\n FEDERATION_ROUTE_PREFIX,\n type FederationActivityResult,\n type FederationCommunityCapability,\n type FederationStatus,\n} from './protocol';\n\ninterface WebRoute {\n readonly kind: 'exact' | 'prefix';\n readonly path: string;\n readonly handler: (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;\n}\n\ninterface WebServerService {\n register(route: WebRoute): () => void;\n}\n\ninterface DshHostContext {\n readonly webServer: WebServerService;\n readonly logger: { warn(error: unknown): void };\n effect(callback: () => void | (() => void | Promise<void>), label?: string): void;\n get(name: string): unknown;\n}\n\ninterface CommunityProbeService {\n inspect(): FederationCommunityCapability | Promise<FederationCommunityCapability>;\n}\n\ninterface IntelligenceCapabilityService {\n run(\n input: string,\n sessionId: string,\n ): FederationActivityResult | Promise<FederationActivityResult>;\n}\n\nconst MAX_ACTIVITY_BODY_BYTES = 65_536 as const;\n\ntype ActivityBodyResult =\n | { readonly ok: true; readonly value: unknown }\n | {\n readonly ok: false;\n readonly status: 400;\n readonly body: { readonly code: 'federation-activity-invalid' };\n }\n | {\n readonly ok: false;\n readonly status: 413;\n readonly body: {\n readonly code: 'federation-activity-body-too-large';\n readonly limit: typeof MAX_ACTIVITY_BODY_BYTES;\n };\n };\n\nexport interface Config {\n readonly engineEndpoint?: string;\n readonly identity?: string;\n}\n\nexport const inject = ['webServer'];\n\n/** DSH-native Host half. DSH's Loader mounts this ordinary plugin from the package patch. */\nexport async function apply(ctx: DshHostContext, config: Config = {}): Promise<void> {\n const identity = config.identity ?? `dsh-${randomUUID()}`;\n const leases = new Set<string>();\n let tick = 0;\n let state = 0;\n let embeddedContext: Context | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n ctx.effect(\n () => async () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers.reverse()) dispose();\n leases.clear();\n if (timer !== undefined) clearInterval(timer);\n await embeddedContext?.fiber.dispose();\n },\n 'forgeax-federation: routes and embedded engine',\n );\n\n if (config.engineEndpoint === undefined) {\n const world = new World();\n embeddedContext = await createWorldContext(world);\n world\n .addSystem(Update, {\n name: 'forgeax-federation-headless-tick',\n queries: [],\n fn: () => {\n tick += 1;\n },\n })\n .unwrap();\n timer = setInterval(() => {\n const result = world.update(1 / 30);\n if (!result.ok) ctx.logger.warn(result.error);\n }, 1000 / 30);\n }\n\n const status = (): FederationStatus => ({\n protocol: FEDERATION_PROTOCOL_VERSION,\n identity,\n ready: true,\n realm: 'dsh',\n capabilities: ['lease', 'community-probe', 'engine-projection'],\n leases: leases.size,\n engine:\n config.engineEndpoint === undefined\n ? { binding: 'embedded', ready: true, frameId: tick, tick, state }\n : { binding: 'external', endpoint: config.engineEndpoint, ready: true },\n });\n\n disposers.push(\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/status`,\n handler(_request, response) {\n writeJson(response, 200, status());\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/activity`,\n async handler(request, response) {\n if (request.method !== 'POST') {\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n return;\n }\n const candidate = ctx.get('forgeaxIntelligenceCapability') as\n | IntelligenceCapabilityService\n | undefined;\n if (candidate === undefined || typeof candidate.run !== 'function') {\n writeJson(response, 404, { code: 'federation-intelligence-capability-missing' });\n return;\n }\n const parsed = await readJsonBody(request);\n if (!parsed.ok) {\n writeJson(response, parsed.status, parsed.body);\n return;\n }\n const body = parsed.value;\n if (\n typeof body !== 'object' ||\n body === null ||\n typeof Reflect.get(body, 'input') !== 'string' ||\n typeof Reflect.get(body, 'sessionId') !== 'string'\n ) {\n writeJson(response, 400, { code: 'federation-activity-invalid' });\n return;\n }\n writeJson(\n response,\n 200,\n await candidate.run(Reflect.get(body, 'input'), Reflect.get(body, 'sessionId')),\n );\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/lease`,\n handler(request, response) {\n if (request.method === 'POST') {\n const leaseId = randomUUID();\n leases.add(leaseId);\n writeJson(response, 201, { leaseId });\n return;\n }\n if (request.method === 'DELETE') {\n const leaseId = new URL(request.url ?? '/', 'http://localhost').searchParams.get(\n 'leaseId',\n );\n if (leaseId !== null) leases.delete(leaseId);\n writeJson(response, 200, { released: leaseId !== null });\n return;\n }\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/community`,\n async handler(_request, response) {\n const candidate = ctx.get('forgeaxFederationCapability') as\n | CommunityProbeService\n | undefined;\n if (candidate === undefined || typeof candidate.inspect !== 'function') {\n writeJson(response, 404, { code: 'federation-community-capability-missing' });\n return;\n }\n let community: FederationCommunityCapability;\n try {\n community = await candidate.inspect();\n } catch {\n writeJson(response, 503, { code: 'federation-community-capability-failed' });\n return;\n }\n writeJson(response, 200, community);\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/engine/control`,\n handler(request, response) {\n if (request.method !== 'POST' || config.engineEndpoint !== undefined) {\n writeJson(response, 409, { code: 'federation-engine-control-unavailable' });\n return;\n }\n state = state === 0 ? 1 : 0;\n writeJson(response, 200, status().engine);\n },\n }),\n );\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<ActivityBodyResult> {\n const chunks: Buffer[] = [];\n let size = 0;\n let tooLarge = false;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n if (tooLarge) continue;\n size += buffer.byteLength;\n if (size > MAX_ACTIVITY_BODY_BYTES) {\n tooLarge = true;\n chunks.length = 0;\n continue;\n }\n chunks.push(buffer);\n }\n if (tooLarge) {\n return {\n ok: false,\n status: 413,\n body: { code: 'federation-activity-body-too-large', limit: MAX_ACTIVITY_BODY_BYTES },\n };\n }\n try {\n return { ok: true, value: JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown };\n } catch {\n return { ok: false, status: 400, body: { code: 'federation-activity-invalid' } };\n }\n}\n\nfunction writeJson(response: ServerResponse, status: number, value: unknown): void {\n response.writeHead(status, {\n 'cache-control': 'no-store',\n 'content-type': 'application/json; charset=utf-8',\n });\n response.end(JSON.stringify(value));\n}\n"]}
1
+ {"version":3,"sources":["../src/protocol.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const FEDERATION_PROTOCOL_VERSION = 1 as const;\nexport const FEDERATION_ROUTE_PREFIX = '/forgeax-federation/v1' as const;\n\nexport type FederationBinding = 'attach' | 'external' | 'embedded';\nexport type FederationOwnership = 'lease' | 'instance';\n\nexport interface FederationStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly identity: string;\n readonly ready: true;\n readonly realm: 'dsh';\n readonly capabilities: readonly string[];\n readonly leases: number;\n readonly engine: EngineProjection;\n}\n\nexport type EngineProjection = EngineEndpointProjection | EmbeddedEngineProjection;\n\nexport interface EngineEndpointProjection {\n readonly binding: 'external';\n readonly endpoint: string;\n readonly ready: true;\n}\n\nexport interface EmbeddedEngineProjection {\n readonly binding: 'embedded';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface FederationLease {\n readonly leaseId: string;\n}\n\nexport interface FederationCommunityCapability {\n readonly id: string;\n readonly value: string;\n}\n\nexport interface FederationActivityResult {\n readonly output: string;\n}\n\nexport interface EnginePreviewStatus {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-status';\n readonly binding: 'external';\n readonly ready: true;\n readonly frameId: number;\n readonly tick: number;\n readonly state: number;\n}\n\nexport interface EnginePreviewPoll {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-poll';\n}\n\nexport interface EnginePreviewControl {\n readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;\n readonly kind: 'forgeax-engine-control';\n readonly action: 'toggle';\n}\n\nexport type EnginePreviewRequest = EnginePreviewPoll | EnginePreviewControl;\n\nexport function isEnginePreviewRequest(value: unknown): value is EnginePreviewRequest {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.protocol !== FEDERATION_PROTOCOL_VERSION) return false;\n if (record.kind === 'forgeax-engine-poll') return true;\n return record.kind === 'forgeax-engine-control' && record.action === 'toggle';\n}\n\nexport function isEnginePreviewStatus(value: unknown): value is EnginePreviewStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.kind === 'forgeax-engine-status' &&\n record.binding === 'external' &&\n record.ready === true &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n\nexport function isFederationStatus(value: unknown): value is FederationStatus {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n record.protocol === FEDERATION_PROTOCOL_VERSION &&\n record.realm === 'dsh' &&\n record.ready === true &&\n typeof record.identity === 'string' &&\n Array.isArray(record.capabilities) &&\n record.capabilities.every((capability) => typeof capability === 'string') &&\n Number.isInteger(record.leases) &&\n (record.leases as number) >= 0 &&\n isEngineProjection(record.engine)\n );\n}\n\nfunction isEngineProjection(value: unknown): value is EngineProjection {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (record.ready !== true) return false;\n if (record.binding === 'external') return typeof record.endpoint === 'string';\n return (\n record.binding === 'embedded' &&\n typeof record.frameId === 'number' &&\n typeof record.tick === 'number' &&\n typeof record.state === 'number'\n );\n}\n","import { randomUUID } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { createWorldContext, Update, World } from '@forgeax/engine-ecs';\nimport type { Context } from '@forgeax/engine-plugin';\n\nimport {\n FEDERATION_PROTOCOL_VERSION,\n FEDERATION_ROUTE_PREFIX,\n type FederationActivityResult,\n type FederationCommunityCapability,\n type FederationStatus,\n} from './protocol';\n\ninterface WebRoute {\n readonly kind: 'exact' | 'prefix';\n readonly path: string;\n readonly handler: (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;\n}\n\ninterface WebServerService {\n register(route: WebRoute): () => void;\n}\n\ninterface DshHostContext {\n readonly webServer: WebServerService;\n readonly logger: { warn(error: unknown): void };\n effect(callback: () => void | (() => void | Promise<void>), label?: string): void;\n get(name: string): unknown;\n}\n\ninterface CommunityProbeService {\n inspect(): FederationCommunityCapability | Promise<FederationCommunityCapability>;\n}\n\ninterface IntelligenceCapabilityService {\n run(\n input: string,\n sessionId: string,\n ): FederationActivityResult | Promise<FederationActivityResult>;\n}\n\nexport interface Config {\n readonly engineEndpoint?: string;\n readonly identity?: string;\n}\n\nexport const inject = ['webServer'];\n\n/** DSH-native Host half. DSH's Loader mounts this ordinary plugin from the package patch. */\nexport async function apply(ctx: DshHostContext, config: Config = {}): Promise<void> {\n const identity = config.identity ?? `dsh-${randomUUID()}`;\n const leases = new Set<string>();\n let tick = 0;\n let state = 0;\n let embeddedContext: Context | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n ctx.effect(\n () => async () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers.reverse()) dispose();\n leases.clear();\n if (timer !== undefined) clearInterval(timer);\n await embeddedContext?.fiber.dispose();\n },\n 'forgeax-federation: routes and embedded engine',\n );\n\n if (config.engineEndpoint === undefined) {\n const world = new World();\n embeddedContext = await createWorldContext(world);\n world\n .addSystem(Update, {\n name: 'forgeax-federation-headless-tick',\n queries: [],\n fn: () => {\n tick += 1;\n },\n })\n .unwrap();\n timer = setInterval(() => {\n const result = world.update(1 / 30);\n if (!result.ok) ctx.logger.warn(result.error);\n }, 1000 / 30);\n }\n\n const status = (): FederationStatus => ({\n protocol: FEDERATION_PROTOCOL_VERSION,\n identity,\n ready: true,\n realm: 'dsh',\n capabilities: ['lease', 'community-probe', 'engine-projection'],\n leases: leases.size,\n engine:\n config.engineEndpoint === undefined\n ? { binding: 'embedded', ready: true, frameId: tick, tick, state }\n : { binding: 'external', endpoint: config.engineEndpoint, ready: true },\n });\n\n disposers.push(\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/status`,\n handler(_request, response) {\n writeJson(response, 200, status());\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/activity`,\n async handler(request, response) {\n if (request.method !== 'POST') {\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n return;\n }\n const candidate = ctx.get('forgeaxIntelligenceCapability') as\n | IntelligenceCapabilityService\n | undefined;\n if (candidate === undefined || typeof candidate.run !== 'function') {\n writeJson(response, 404, { code: 'federation-intelligence-capability-missing' });\n return;\n }\n const body = await readJsonBody(request);\n if (\n typeof body !== 'object' ||\n body === null ||\n typeof Reflect.get(body, 'input') !== 'string' ||\n typeof Reflect.get(body, 'sessionId') !== 'string'\n ) {\n writeJson(response, 400, { code: 'federation-activity-invalid' });\n return;\n }\n writeJson(\n response,\n 200,\n await candidate.run(Reflect.get(body, 'input'), Reflect.get(body, 'sessionId')),\n );\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/lease`,\n handler(request, response) {\n if (request.method === 'POST') {\n const leaseId = randomUUID();\n leases.add(leaseId);\n writeJson(response, 201, { leaseId });\n return;\n }\n if (request.method === 'DELETE') {\n const leaseId = new URL(request.url ?? '/', 'http://localhost').searchParams.get(\n 'leaseId',\n );\n if (leaseId !== null) leases.delete(leaseId);\n writeJson(response, 200, { released: leaseId !== null });\n return;\n }\n writeJson(response, 405, { code: 'federation-method-not-allowed' });\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/community`,\n async handler(_request, response) {\n const candidate = ctx.get('forgeaxFederationCapability') as\n | CommunityProbeService\n | undefined;\n if (candidate === undefined || typeof candidate.inspect !== 'function') {\n writeJson(response, 404, { code: 'federation-community-capability-missing' });\n return;\n }\n writeJson(response, 200, await candidate.inspect());\n },\n }),\n ctx.webServer.register({\n kind: 'exact',\n path: `${FEDERATION_ROUTE_PREFIX}/engine/control`,\n handler(request, response) {\n if (request.method !== 'POST' || config.engineEndpoint !== undefined) {\n writeJson(response, 409, { code: 'federation-engine-control-unavailable' });\n return;\n }\n state = state === 0 ? 1 : 0;\n writeJson(response, 200, status().engine);\n },\n }),\n );\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.byteLength;\n if (size > 65_536) throw new Error('federation request exceeds 65536 bytes');\n chunks.push(buffer);\n }\n return JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown;\n}\n\nfunction writeJson(response: ServerResponse, status: number, value: unknown): void {\n response.writeHead(status, {\n 'cache-control': 'no-store',\n 'content-type': 'application/json; charset=utf-8',\n });\n response.end(JSON.stringify(value));\n}\n"]}
@@ -34,7 +34,6 @@ export interface FederationCommunityCapability {
34
34
  export interface FederationActivityResult {
35
35
  readonly output: string;
36
36
  }
37
- export declare function isFederationCommunityCapability(value: unknown): value is FederationCommunityCapability;
38
37
  export interface EnginePreviewStatus {
39
38
  readonly protocol: typeof FEDERATION_PROTOCOL_VERSION;
40
39
  readonly kind: 'forgeax-engine-status';
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,EAAG,CAAU,CAAC;AACtD,eAAO,MAAM,uBAAuB,EAAG,wBAAiC,CAAC;AAEzE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,UAAU,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED,MAAM,MAAM,gBAAgB,GAAG,wBAAwB,GAAG,wBAAwB,CAAC;AAEnF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,6BAA6B,CAIxC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;CACtC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC3B;AAED,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;AAE5E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAMpF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAYlF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAc5E"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,EAAG,CAAU,CAAC;AACtD,eAAO,MAAM,uBAAuB,EAAG,wBAAiC,CAAC;AAEzE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,UAAU,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED,MAAM,MAAM,gBAAgB,GAAG,wBAAwB,GAAG,wBAAwB,CAAC;AAEnF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;CACtC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,2BAA2B,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC3B;AAED,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;AAE5E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAMpF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAYlF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAc5E"}