@nextclaw/nextclaw-ncp-runtime-adapter-hermes-http 0.1.15 → 0.1.17
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.
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -0
- package/dist/hermes-http-adapter-config.utils.d.ts +2 -1
- package/dist/hermes-http-adapter-config.utils.d.ts.map +1 -0
- package/dist/hermes-http-adapter-config.utils.js +2 -0
- package/dist/hermes-http-adapter-config.utils.js.map +1 -0
- package/dist/hermes-http-adapter-message.utils.d.ts +2 -1
- package/dist/hermes-http-adapter-message.utils.d.ts.map +1 -0
- package/dist/hermes-http-adapter-message.utils.js +2 -0
- package/dist/hermes-http-adapter-message.utils.js.map +1 -0
- package/dist/hermes-http-adapter-session-store.service.js +2 -0
- package/dist/hermes-http-adapter-session-store.service.js.map +1 -0
- package/dist/hermes-http-adapter.service.d.ts +2 -1
- package/dist/hermes-http-adapter.service.d.ts.map +1 -0
- package/dist/hermes-http-adapter.service.js +2 -0
- package/dist/hermes-http-adapter.service.js.map +1 -0
- package/dist/hermes-http-adapter.types.d.ts +2 -1
- package/dist/hermes-http-adapter.types.d.ts.map +1 -0
- package/dist/hermes-openai-stream-parser.utils.d.ts +2 -1
- package/dist/hermes-openai-stream-parser.utils.d.ts.map +1 -0
- package/dist/hermes-openai-stream-parser.utils.js +2 -0
- package/dist/hermes-openai-stream-parser.utils.js.map +1 -0
- package/package.json +5 -5
package/dist/cli.js
CHANGED
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { HermesHttpAdapterServer } from \"./hermes-http-adapter.service.js\";\n\nclass HermesHttpAdapterCli {\n run = async (): Promise<void> => {\n const server = new HermesHttpAdapterServer(this.readArgs());\n await server.start();\n process.stdout.write(\n `[hermes-http-adapter] listening on http://${server.config.host}:${server.config.port}${server.config.basePath}\\n`,\n );\n\n const shutdown = async (): Promise<void> => {\n await server.stop();\n process.exit(0);\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown();\n });\n process.once(\"SIGTERM\", () => {\n void shutdown();\n });\n };\n\n private readArgs = (): Record<string, unknown> => {\n const args = process.argv.slice(2);\n const config: Record<string, unknown> = {};\n\n for (let index = 0; index < args.length; index += 1) {\n const current = args[index];\n if (!current?.startsWith(\"--\")) {\n continue;\n }\n const key = current.slice(2);\n const nextValue = args[index + 1];\n if (!nextValue || nextValue.startsWith(\"--\")) {\n config[key] = true;\n continue;\n }\n config[key] = nextValue;\n index += 1;\n }\n\n return {\n host: config.host,\n port: config.port,\n basePath: config[\"base-path\"],\n hermesBaseUrl: config[\"hermes-base-url\"],\n hermesApiKey: config[\"api-key\"],\n model: config.model,\n systemPrompt: config[\"system-prompt\"],\n };\n };\n}\n\nvoid new HermesHttpAdapterCli().run();\n"],"mappings":";;;AAIA,IAAM,uBAAN,MAA2B;CACzB,MAAM,YAA2B;EAC/B,MAAM,SAAS,IAAI,wBAAwB,KAAK,UAAU,CAAC;AAC3D,QAAM,OAAO,OAAO;AACpB,UAAQ,OAAO,MACb,6CAA6C,OAAO,OAAO,KAAK,GAAG,OAAO,OAAO,OAAO,OAAO,OAAO,SAAS,IAChH;EAED,MAAM,WAAW,YAA2B;AAC1C,SAAM,OAAO,MAAM;AACnB,WAAQ,KAAK,EAAE;;AAGjB,UAAQ,KAAK,gBAAgB;AACtB,aAAU;IACf;AACF,UAAQ,KAAK,iBAAiB;AACvB,aAAU;IACf;;CAGJ,iBAAkD;EAChD,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;EAClC,MAAM,SAAkC,EAAE;AAE1C,OAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;GACnD,MAAM,UAAU,KAAK;AACrB,OAAI,CAAC,SAAS,WAAW,KAAK,CAC5B;GAEF,MAAM,MAAM,QAAQ,MAAM,EAAE;GAC5B,MAAM,YAAY,KAAK,QAAQ;AAC/B,OAAI,CAAC,aAAa,UAAU,WAAW,KAAK,EAAE;AAC5C,WAAO,OAAO;AACd;;AAEF,UAAO,OAAO;AACd,YAAS;;AAGX,SAAO;GACL,MAAM,OAAO;GACb,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,eAAe,OAAO;GACtB,cAAc,OAAO;GACrB,OAAO,OAAO;GACd,cAAc,OAAO;GACtB;;;AAIA,IAAI,sBAAsB,CAAC,KAAK"}
|
|
@@ -13,4 +13,5 @@ declare function normalizeBasePath(value: string): string;
|
|
|
13
13
|
declare function resolveHermesApiUrl(baseUrl: string, path: string): string;
|
|
14
14
|
declare function resolveHermesHealthcheckUrl(baseUrl: string): string;
|
|
15
15
|
//#endregion
|
|
16
|
-
export { HermesHttpAdapterConfigInput, HermesHttpAdapterConfigResolver, normalizeBasePath, resolveHermesApiUrl, resolveHermesHealthcheckUrl };
|
|
16
|
+
export { HermesHttpAdapterConfigInput, HermesHttpAdapterConfigResolver, normalizeBasePath, resolveHermesApiUrl, resolveHermesHealthcheckUrl };
|
|
17
|
+
//# sourceMappingURL=hermes-http-adapter-config.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter-config.utils.d.ts","names":[],"sources":["../src/hermes-http-adapter-config.utils.ts"],"mappings":";;;KAcY,4BAAA,GAA+B,OAAA,CACzC,IAAA,CAAK,uBAAA;EAEL,SAAA,GAAY,0BAAA;AAAA;AAAA,cAGD,+BAAA;EAAA,iBACkB,MAAA;cAAA,MAAA,GAAQ,4BAAA;EAErC,OAAA,QAAc,+BAAA;AAAA;AAAA,iBA4CA,iBAAA,CAAkB,KAAA;AAAA,iBAWlB,mBAAA,CAAoB,OAAA,UAAiB,IAAA;AAAA,iBAQrC,2BAAA,CAA4B,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter-config.utils.js","names":[],"sources":["../src/hermes-http-adapter-config.utils.ts"],"sourcesContent":["import type {\n HermesHttpAdapterConfig,\n HermesHttpAdapterFetchLike,\n HermesHttpAdapterResolvedConfig,\n} from \"./hermes-http-adapter.types.js\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 8765;\nconst DEFAULT_BASE_PATH = \"/ncp/agent\";\nconst DEFAULT_HERMES_BASE_URL = \"http://127.0.0.1:8642\";\nconst DEFAULT_MODEL = \"hermes-agent\";\nconst DEFAULT_STREAM_WAIT_TIMEOUT_MS = 15000;\nconst DEFAULT_HEALTHCHECK_TIMEOUT_MS = 3000;\n\nexport type HermesHttpAdapterConfigInput = Partial<\n Omit<HermesHttpAdapterConfig, \"fetchImpl\">\n> & {\n fetchImpl?: HermesHttpAdapterFetchLike;\n};\n\nexport class HermesHttpAdapterConfigResolver {\n constructor(private readonly source: HermesHttpAdapterConfigInput = {}) {}\n\n resolve = (): HermesHttpAdapterResolvedConfig => {\n const basePath = normalizeBasePath(\n this.source.basePath ??\n process.env.NEXTCLAW_HERMES_ADAPTER_BASE_PATH ??\n DEFAULT_BASE_PATH,\n );\n const hermesBaseUrl = readString(\n this.source.hermesBaseUrl ?? process.env.HERMES_API_BASE_URL,\n ) ?? DEFAULT_HERMES_BASE_URL;\n const resolved: HermesHttpAdapterConfig = {\n host:\n readString(this.source.host ?? process.env.NEXTCLAW_HERMES_ADAPTER_HOST) ??\n DEFAULT_HOST,\n port:\n readPositiveInteger(this.source.port) ??\n readPositiveInteger(process.env.NEXTCLAW_HERMES_ADAPTER_PORT) ??\n DEFAULT_PORT,\n basePath,\n hermesBaseUrl,\n hermesApiKey: readString(this.source.hermesApiKey ?? process.env.HERMES_API_KEY),\n model:\n readString(this.source.model ?? process.env.HERMES_MODEL) ?? DEFAULT_MODEL,\n systemPrompt: readString(\n this.source.systemPrompt ?? process.env.HERMES_SYSTEM_PROMPT,\n ),\n streamWaitTimeoutMs:\n readPositiveInteger(this.source.streamWaitTimeoutMs) ??\n readPositiveInteger(process.env.NEXTCLAW_HERMES_ADAPTER_STREAM_WAIT_TIMEOUT_MS) ??\n DEFAULT_STREAM_WAIT_TIMEOUT_MS,\n healthcheckTimeoutMs:\n readPositiveInteger(this.source.healthcheckTimeoutMs) ??\n readPositiveInteger(process.env.NEXTCLAW_HERMES_ADAPTER_HEALTHCHECK_TIMEOUT_MS) ??\n DEFAULT_HEALTHCHECK_TIMEOUT_MS,\n ...(this.source.fetchImpl ? { fetchImpl: this.source.fetchImpl } : {}),\n };\n\n return {\n ...resolved,\n chatCompletionsUrl: resolveHermesApiUrl(hermesBaseUrl, \"chat/completions\"),\n healthcheckUrl: resolveHermesHealthcheckUrl(hermesBaseUrl),\n };\n };\n}\n\nexport function normalizeBasePath(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) {\n return DEFAULT_BASE_PATH;\n }\n const withLeadingSlash = trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n return withLeadingSlash.endsWith(\"/\")\n ? withLeadingSlash.slice(0, -1)\n : withLeadingSlash;\n}\n\nexport function resolveHermesApiUrl(baseUrl: string, path: string): string {\n const normalizedBase = baseUrl.trim().replace(/\\/+$/, \"\");\n const normalizedPath = path.replace(/^\\/+/, \"\");\n const hasVersionPath = /\\/v1$/u.test(normalizedBase);\n const prefix = hasVersionPath ? \"\" : \"/v1\";\n return `${normalizedBase}${prefix}/${normalizedPath}`;\n}\n\nexport function resolveHermesHealthcheckUrl(baseUrl: string): string {\n const normalizedBase = baseUrl.trim().replace(/\\/+$/, \"\");\n const rootBase = normalizedBase.endsWith(\"/v1\")\n ? normalizedBase.slice(0, -\"/v1\".length)\n : normalizedBase;\n return `${rootBase}/health`;\n}\n\nfunction readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readPositiveInteger(value: unknown): number | undefined {\n const parsed =\n typeof value === \"number\"\n ? value\n : typeof value === \"string\"\n ? Number.parseInt(value, 10)\n : Number.NaN;\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n const normalized = Math.trunc(parsed);\n return normalized > 0 ? normalized : undefined;\n}\n"],"mappings":";AAMA,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,oBAAoB;AAC1B,MAAM,0BAA0B;AAChC,MAAM,gBAAgB;AACtB,MAAM,iCAAiC;AACvC,MAAM,iCAAiC;AAQvC,IAAa,kCAAb,MAA6C;CAC3C,YAAY,SAAwD,EAAE,EAAE;AAA3C,OAAA,SAAA;;CAE7B,gBAAiD;EAC/C,MAAM,WAAW,kBACf,KAAK,OAAO,YACV,QAAQ,IAAI,qCACZ,kBACH;EACD,MAAM,gBAAgB,WACpB,KAAK,OAAO,iBAAiB,QAAQ,IAAI,oBAC1C,IAAI;AA4BL,SAAO;GA1BL,MACE,WAAW,KAAK,OAAO,QAAQ,QAAQ,IAAI,6BAA6B,IACxE;GACF,MACE,oBAAoB,KAAK,OAAO,KAAK,IACrC,oBAAoB,QAAQ,IAAI,6BAA6B,IAC7D;GACF;GACA;GACA,cAAc,WAAW,KAAK,OAAO,gBAAgB,QAAQ,IAAI,eAAe;GAChF,OACE,WAAW,KAAK,OAAO,SAAS,QAAQ,IAAI,aAAa,IAAI;GAC/D,cAAc,WACZ,KAAK,OAAO,gBAAgB,QAAQ,IAAI,qBACzC;GACD,qBACE,oBAAoB,KAAK,OAAO,oBAAoB,IACpD,oBAAoB,QAAQ,IAAI,+CAA+C,IAC/E;GACF,sBACE,oBAAoB,KAAK,OAAO,qBAAqB,IACrD,oBAAoB,QAAQ,IAAI,+CAA+C,IAC/E;GACF,GAAI,KAAK,OAAO,YAAY,EAAE,WAAW,KAAK,OAAO,WAAW,GAAG,EAAE;GAKrE,oBAAoB,oBAAoB,eAAe,mBAAmB;GAC1E,gBAAgB,4BAA4B,cAAc;GAC3D;;;AAIL,SAAgB,kBAAkB,OAAuB;CACvD,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,CAAC,QACH,QAAO;CAET,MAAM,mBAAmB,QAAQ,WAAW,IAAI,GAAG,UAAU,IAAI;AACjE,QAAO,iBAAiB,SAAS,IAAI,GACjC,iBAAiB,MAAM,GAAG,GAAG,GAC7B;;AAGN,SAAgB,oBAAoB,SAAiB,MAAsB;CACzE,MAAM,iBAAiB,QAAQ,MAAM,CAAC,QAAQ,QAAQ,GAAG;CACzD,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,GAAG;AAG/C,QAAO,GAAG,iBAFa,SAAS,KAAK,eAAe,GACpB,KAAK,MACH,GAAG;;AAGvC,SAAgB,4BAA4B,SAAyB;CACnE,MAAM,iBAAiB,QAAQ,MAAM,CAAC,QAAQ,QAAQ,GAAG;AAIzD,QAAO,GAHU,eAAe,SAAS,MAAM,GAC3C,eAAe,MAAM,GAAG,GAAc,GACtC,eACe;;AAGrB,SAAS,WAAW,OAAoC;AACtD,KAAI,OAAO,UAAU,SACnB;CAEF,MAAM,UAAU,MAAM,MAAM;AAC5B,QAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;;AAGxC,SAAS,oBAAoB,OAAoC;CAC/D,MAAM,SACJ,OAAO,UAAU,WACb,QACA,OAAO,UAAU,WACf,OAAO,SAAS,OAAO,GAAG,GAC1B;AACR,KAAI,CAAC,OAAO,SAAS,OAAO,CAC1B;CAEF,MAAM,aAAa,KAAK,MAAM,OAAO;AACrC,QAAO,aAAa,IAAI,aAAa,KAAA"}
|
|
@@ -80,4 +80,5 @@ declare function toErrorSseFrame(error: {
|
|
|
80
80
|
message: string;
|
|
81
81
|
}): string;
|
|
82
82
|
//#endregion
|
|
83
|
-
export { HermesAssistantEventCollector, HermesInlineToolTraceTranslator, HermesProviderRoute, HermesReasoningDeltaTranslator, buildHermesMessages, createAssistantMessage, createAssistantMessageFromParts, inferHermesProvider, normalizeHermesRequestedModel, readHermesProviderRoute, resolveHermesModel, toErrorSseFrame, toNcpError, toNcpSseFrame };
|
|
83
|
+
export { HermesAssistantEventCollector, HermesInlineToolTraceTranslator, HermesProviderRoute, HermesReasoningDeltaTranslator, buildHermesMessages, createAssistantMessage, createAssistantMessageFromParts, inferHermesProvider, normalizeHermesRequestedModel, readHermesProviderRoute, resolveHermesModel, toErrorSseFrame, toNcpError, toNcpSseFrame };
|
|
84
|
+
//# sourceMappingURL=hermes-http-adapter-message.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter-message.utils.d.ts","names":[],"sources":["../src/hermes-http-adapter-message.utils.ts"],"mappings":";;;;KAiEY,mBAAA;EACV,KAAA;EACA,MAAA;EACA,OAAA;EACA,OAAA,EAAS,MAAA;EACT,OAAA;AAAA;AAAA,iBAKc,uBAAA,CACd,QAAA,EAAU,kBAAA,GACT,mBAAA;AAAA,iBA0Ba,mBAAA,CAAoB,MAAA;EAClC,QAAA,EAAU,kBAAA;EACV,YAAA;AAAA,IACE,mBAAA;AAAA,iBAiBY,sBAAA,CAAuB,MAAA;EACrC,SAAA;EACA,SAAA;EACA,IAAA;EACA,SAAA;EACA,QAAA,GAAW,MAAA;AAAA,IACT,UAAA;AAAA,iBAkBY,+BAAA,CAAgC,MAAA;EAC9C,SAAA;EACA,SAAA;EACA,KAAA,EAAO,cAAA;EACP,SAAA;EACA,QAAA,GAAW,MAAA;AAAA,IACT,UAAA;AAAA,cAaS,6BAAA;EAAA,iBACM,KAAA;EAAA,iBACA,qBAAA;EAEjB,UAAA,GAAc,KAAA,EAAO,gBAAA;EA8CrB,QAAA;EAEA,UAAA,QAAiB,cAAA;EAAA,QAET,cAAA;EAAA,QAeA,mBAAA;EAAA,QAeA,sBAAA;EAAA,QAWA,wBAAA;EAAA,QAkCA,YAAA;EAAA,QAUA,YAAA;EAAA,QAKA,YAAA;AAAA;AAAA,cAYG,+BAAA;EAAA,QACH,iBAAA;EAAA,QACA,qBAAA;EAAA,QACA,aAAA;EAER,SAAA,GACE,IAAA,EAAM,+BAAA,EACN,MAAA,EAAQ,aAAA,CAAc,gBAAA,MACrB,cAAA,CAAe,gBAAA;EAAA,QAyCV,gBAAA;EAAA,QAuEA,sBAAA;EAAA,QAOA,yBAAA;EAAA,QAOA,kBAAA;EAAA,QASA,kBAAA;AAAA;AAAA,cAUG,8BAAA;EAAA,iBACM,UAAA;EAEjB,SAAA,GACE,IAAA,EAAM,8BAAA,EACN,MAAA,EAAQ,aAAA,CAAc,gBAAA,MACrB,cAAA,CAAe,gBAAA;EAAA,QAiBV,uBAAA;EAAA,QA+BA,gBAAA;EAAA,QAsCA,aAAA;EAAA,QAMA,sBAAA;EAAA,QAOA,kBAAA;EAAA,QASA,kBAAA;AAAA;AAAA,iBAUM,kBAAA,CAAmB,MAAA;EACjC,QAAA,EAAU,kBAAA;EACV,aAAA;AAAA;AAAA,iBAoBc,6BAAA,CAA8B,KAAA;AAAA,iBAuB9B,mBAAA,CAAoB,MAAA;EAClC,KAAA;EACA,OAAA;EACA,OAAA,GAAU,mBAAA;AAAA;AAAA,iBAcI,UAAA,CACd,KAAA,WACA,IAAA,EAAM,QAAA,WACL,QAAA;AAAA,iBAOa,aAAA,CAAc,KAAA,EAAO,gBAAA;AAAA,iBAIrB,eAAA,CAAgB,KAAA;EAAS,IAAA;EAAc,OAAA;AAAA"}
|
|
@@ -456,3 +456,5 @@ function normalizeRole(role) {
|
|
|
456
456
|
}
|
|
457
457
|
//#endregion
|
|
458
458
|
export { HermesAssistantEventCollector, HermesInlineToolTraceTranslator, HermesReasoningDeltaTranslator, buildHermesMessages, createAssistantMessage, createAssistantMessageFromParts, inferHermesProvider, normalizeHermesRequestedModel, readHermesProviderRoute, resolveHermesModel, toErrorSseFrame, toNcpError, toNcpSseFrame };
|
|
459
|
+
|
|
460
|
+
//# sourceMappingURL=hermes-http-adapter-message.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter-message.utils.js","names":[],"sources":["../src/hermes-http-adapter-message.utils.ts"],"sourcesContent":["import {\n NcpAssistantTextStreamNormalizer,\n type NcpEndpointEvent,\n type NcpError,\n type NcpMessage,\n type NcpMessagePart,\n type NcpProviderRuntimeRoute,\n type NcpRequestEnvelope,\n type NcpToolInvocationPart,\n NcpEventType,\n} from \"@nextclaw/ncp\";\nimport type { HermesOpenAIMessage } from \"./hermes-http-adapter.types.js\";\n\ntype HermesInlineToolTrace = {\n toolName: string;\n args: string;\n};\n\nconst HERMES_INLINE_TOOL_TRACE_PATTERNS: Array<{\n icon: string;\n toolName: string;\n buildArgs: (rawArgs: string) => string;\n}> = [\n {\n icon: \"🔎\",\n toolName: \"search_files\",\n buildArgs: (rawArgs) => JSON.stringify({ pattern: rawArgs }),\n },\n {\n icon: \"💻\",\n toolName: \"terminal\",\n buildArgs: (rawArgs) => JSON.stringify({ command: rawArgs }),\n },\n];\n\nfunction readMetadataString(\n metadata: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n const value = metadata?.[key];\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readStringRecord(value: unknown): Record<string, string> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n const out: Record<string, string> = {};\n for (const [entryKey, entryValue] of Object.entries(value)) {\n if (typeof entryValue !== \"string\") {\n continue;\n }\n const normalized = entryValue.trim();\n if (!normalized) {\n continue;\n }\n out[entryKey] = normalized;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nexport type HermesProviderRoute = {\n model: string;\n apiKey?: string;\n apiBase?: string;\n headers: Record<string, string>;\n apiMode?: \"chat_completions\" | \"codex_responses\" | \"anthropic_messages\";\n};\n\nconst NARP_API_MODE_HEADER = \"x-nextclaw-narp-api-mode\";\n\nexport function readHermesProviderRoute(\n envelope: NcpRequestEnvelope,\n): HermesProviderRoute | undefined {\n const route = envelope.providerRoute;\n if (!route || typeof route !== \"object\" || Array.isArray(route)) {\n return undefined;\n }\n const routeRecord = route as Record<string, unknown>;\n\n const model =\n readMetadataString(routeRecord, \"model\") ??\n readMetadataString(routeRecord, \"providerLocalModel\");\n if (!model) {\n return undefined;\n }\n\n return {\n model,\n apiKey: readMetadataString(routeRecord, \"apiKey\"),\n apiBase: readMetadataString(routeRecord, \"apiBase\"),\n ...extractRuntimeHeaders(\n readStringRecord(routeRecord.headers) ??\n readStringRecord(routeRecord.extraHeaders) ??\n {},\n ),\n };\n}\n\nexport function buildHermesMessages(params: {\n envelope: NcpRequestEnvelope;\n systemPrompt?: string;\n}): HermesOpenAIMessage[] {\n const { envelope, systemPrompt } = params;\n const messages: HermesOpenAIMessage[] = [];\n if (systemPrompt) {\n messages.push({\n role: \"system\",\n content: systemPrompt,\n });\n }\n const content = extractMessageText(envelope.message);\n messages.push({\n role: normalizeRole(envelope.message.role),\n content,\n });\n return messages;\n}\n\nexport function createAssistantMessage(params: {\n sessionId: string;\n messageId: string;\n text: string;\n timestamp: string;\n metadata?: Record<string, unknown>;\n}): NcpMessage {\n const { sessionId, messageId, text, timestamp, metadata } = params;\n return {\n id: messageId,\n sessionId,\n role: \"assistant\",\n status: \"final\",\n parts: [\n {\n type: \"text\",\n text,\n },\n ],\n timestamp,\n ...(metadata ? { metadata } : {}),\n };\n}\n\nexport function createAssistantMessageFromParts(params: {\n sessionId: string;\n messageId: string;\n parts: NcpMessagePart[];\n timestamp: string;\n metadata?: Record<string, unknown>;\n}): NcpMessage {\n const { sessionId, messageId, parts, timestamp, metadata } = params;\n return {\n id: messageId,\n sessionId,\n role: \"assistant\",\n status: \"final\",\n parts: structuredClone(parts),\n timestamp,\n ...(metadata ? { metadata } : {}),\n };\n}\n\nexport class HermesAssistantEventCollector {\n private readonly parts: NcpMessagePart[] = [];\n private readonly toolPartIndexByCallId = new Map<string, number>();\n\n applyEvent = (event: NcpEndpointEvent): void => {\n switch (event.type) {\n case NcpEventType.MessageTextDelta:\n this.appendTextPart(event.payload.delta);\n return;\n case NcpEventType.MessageReasoningDelta:\n this.appendReasoningPart(event.payload.delta);\n return;\n case NcpEventType.MessageToolCallStart:\n this.upsertToolInvocationPart({\n type: \"tool-invocation\",\n toolCallId: event.payload.toolCallId,\n toolName: event.payload.toolName,\n state: \"partial-call\",\n args: \"\",\n });\n return;\n case NcpEventType.MessageToolCallArgsDelta:\n this.applyToolCallArgsDelta(\n event.payload.toolCallId,\n event.payload.delta,\n );\n return;\n case NcpEventType.MessageToolCallArgs:\n this.upsertToolInvocationPart({\n type: \"tool-invocation\",\n toolCallId: event.payload.toolCallId,\n toolName: this.readToolName(event.payload.toolCallId),\n state: \"partial-call\",\n args: event.payload.args,\n });\n return;\n case NcpEventType.MessageToolCallEnd:\n this.upsertToolInvocationPart({\n type: \"tool-invocation\",\n toolCallId: event.payload.toolCallId,\n toolName: this.readToolName(event.payload.toolCallId),\n state: \"call\",\n args: this.readToolArgs(event.payload.toolCallId),\n });\n return;\n default:\n return;\n }\n };\n\n hasParts = (): boolean => this.parts.length > 0;\n\n buildParts = (): NcpMessagePart[] => structuredClone(this.parts);\n\n private appendTextPart = (delta: string): void => {\n if (!delta) {\n return;\n }\n const lastPart = this.parts.at(-1);\n if (lastPart?.type === \"text\") {\n lastPart.text = `${lastPart.text}${delta}`;\n return;\n }\n this.parts.push({\n type: \"text\",\n text: delta,\n });\n };\n\n private appendReasoningPart = (delta: string): void => {\n if (!delta) {\n return;\n }\n const lastPart = this.parts.at(-1);\n if (lastPart?.type === \"reasoning\") {\n lastPart.text = `${lastPart.text}${delta}`;\n return;\n }\n this.parts.push({\n type: \"reasoning\",\n text: delta,\n });\n };\n\n private applyToolCallArgsDelta = (toolCallId: string, delta: string): void => {\n const currentArgs = this.readToolArgs(toolCallId);\n this.upsertToolInvocationPart({\n type: \"tool-invocation\",\n toolCallId,\n toolName: this.readToolName(toolCallId),\n state: \"partial-call\",\n args: `${currentArgs}${delta}`,\n });\n };\n\n private upsertToolInvocationPart = (\n nextPart: NcpToolInvocationPart,\n ): void => {\n const normalizedToolCallId = nextPart.toolCallId?.trim();\n if (!normalizedToolCallId) {\n this.parts.push({\n ...nextPart,\n });\n return;\n }\n\n const existingIndex = this.toolPartIndexByCallId.get(normalizedToolCallId);\n if (typeof existingIndex === \"number\") {\n const existingPart = this.parts[existingIndex];\n if (existingPart?.type !== \"tool-invocation\") {\n return;\n }\n this.parts[existingIndex] = {\n ...existingPart,\n ...nextPart,\n toolCallId: normalizedToolCallId,\n toolName: nextPart.toolName || existingPart.toolName,\n args: nextPart.args ?? existingPart.args,\n };\n return;\n }\n\n this.toolPartIndexByCallId.set(normalizedToolCallId, this.parts.length);\n this.parts.push({\n ...nextPart,\n toolCallId: normalizedToolCallId,\n });\n };\n\n private readToolArgs = (toolCallId: string): string => {\n const part = this.findToolPart(toolCallId);\n if (!part) {\n return \"\";\n }\n return typeof part.args === \"string\"\n ? part.args\n : JSON.stringify(part.args ?? \"\");\n };\n\n private readToolName = (toolCallId: string): string => {\n const part = this.findToolPart(toolCallId);\n return part?.toolName ?? \"unknown\";\n };\n\n private findToolPart = (\n toolCallId: string,\n ): NcpToolInvocationPart | null => {\n const existingIndex = this.toolPartIndexByCallId.get(toolCallId);\n if (typeof existingIndex !== \"number\") {\n return null;\n }\n const part = this.parts[existingIndex];\n return part?.type === \"tool-invocation\" ? part : null;\n };\n}\n\nexport class HermesInlineToolTraceTranslator {\n private pendingTextBuffer = \"\";\n private sawStructuredToolCall = false;\n private toolCallCount = 0;\n\n translate = async function* (\n this: HermesInlineToolTraceTranslator,\n events: AsyncIterable<NcpEndpointEvent>,\n ): AsyncGenerator<NcpEndpointEvent> {\n for await (const event of events) {\n if (this.isStructuredToolCallEvent(event)) {\n this.sawStructuredToolCall = true;\n yield* this.flushPendingText({\n sessionId: this.readEventSessionId(event),\n messageId: this.readEventMessageId(event),\n flush: true,\n });\n yield event;\n continue;\n }\n\n if (\n !this.sawStructuredToolCall &&\n event.type === NcpEventType.MessageTextDelta\n ) {\n this.pendingTextBuffer += event.payload.delta;\n yield* this.flushPendingText({\n sessionId: event.payload.sessionId,\n messageId: event.payload.messageId,\n flush: false,\n });\n continue;\n }\n\n if (\n !this.sawStructuredToolCall &&\n this.shouldFlushPendingText(event)\n ) {\n yield* this.flushPendingText({\n sessionId: this.readEventSessionId(event),\n messageId: this.readEventMessageId(event),\n flush: true,\n });\n }\n\n yield event;\n }\n };\n\n private flushPendingText = function* (\n this: HermesInlineToolTraceTranslator,\n params: {\n sessionId?: string;\n messageId?: string;\n flush: boolean;\n },\n ): Generator<NcpEndpointEvent> {\n if (!this.pendingTextBuffer) {\n return;\n }\n\n const lastNewlineIndex = this.pendingTextBuffer.lastIndexOf(\"\\n\");\n const flushableText =\n params.flush\n ? this.pendingTextBuffer\n : lastNewlineIndex >= 0\n ? this.pendingTextBuffer.slice(0, lastNewlineIndex + 1)\n : this.pendingTextBuffer.includes(\"`\")\n ? \"\"\n : this.pendingTextBuffer;\n if (!flushableText) {\n return;\n }\n\n this.pendingTextBuffer = this.pendingTextBuffer.slice(flushableText.length);\n for (const segment of splitIntoLineSegments(flushableText)) {\n const inlineToolTrace = matchHermesInlineToolTrace(segment);\n if (inlineToolTrace && params.sessionId) {\n const toolCallId = `hermes-inline-tool-${++this.toolCallCount}`;\n yield {\n type: NcpEventType.MessageToolCallStart,\n payload: {\n sessionId: params.sessionId,\n ...(params.messageId ? { messageId: params.messageId } : {}),\n toolCallId,\n toolName: inlineToolTrace.toolName,\n },\n };\n yield {\n type: NcpEventType.MessageToolCallArgs,\n payload: {\n sessionId: params.sessionId,\n toolCallId,\n args: inlineToolTrace.args,\n },\n };\n yield {\n type: NcpEventType.MessageToolCallEnd,\n payload: {\n sessionId: params.sessionId,\n toolCallId,\n },\n };\n continue;\n }\n\n if (!segment || !params.sessionId || !params.messageId) {\n continue;\n }\n yield {\n type: NcpEventType.MessageTextDelta,\n payload: {\n sessionId: params.sessionId,\n messageId: params.messageId,\n delta: segment,\n },\n };\n }\n };\n\n private shouldFlushPendingText = (event: NcpEndpointEvent): boolean =>\n event.type === NcpEventType.MessageTextEnd ||\n event.type === NcpEventType.MessageCompleted ||\n event.type === NcpEventType.MessageFailed ||\n event.type === NcpEventType.RunFinished ||\n event.type === NcpEventType.RunError;\n\n private isStructuredToolCallEvent = (event: NcpEndpointEvent): boolean =>\n event.type === NcpEventType.MessageToolCallStart ||\n event.type === NcpEventType.MessageToolCallArgs ||\n event.type === NcpEventType.MessageToolCallArgsDelta ||\n event.type === NcpEventType.MessageToolCallEnd ||\n event.type === NcpEventType.MessageToolCallResult;\n\n private readEventSessionId = (event: NcpEndpointEvent): string | undefined => {\n if (!(\"payload\" in event) || !event.payload || typeof event.payload !== \"object\") {\n return undefined;\n }\n return \"sessionId\" in event.payload && typeof event.payload.sessionId === \"string\"\n ? event.payload.sessionId\n : undefined;\n };\n\n private readEventMessageId = (event: NcpEndpointEvent): string | undefined => {\n if (!(\"payload\" in event) || !event.payload || typeof event.payload !== \"object\") {\n return undefined;\n }\n return \"messageId\" in event.payload && typeof event.payload.messageId === \"string\"\n ? event.payload.messageId\n : undefined;\n };\n}\n\nexport class HermesReasoningDeltaTranslator {\n private readonly normalizer = new NcpAssistantTextStreamNormalizer(\"think-tags\");\n\n translate = async function* (\n this: HermesReasoningDeltaTranslator,\n events: AsyncIterable<NcpEndpointEvent>,\n ): AsyncGenerator<NcpEndpointEvent> {\n for await (const event of events) {\n if (event.type === NcpEventType.MessageTextDelta) {\n yield* this.emitNormalizedTextDelta(event);\n continue;\n }\n\n if (this.shouldFlushPendingText(event)) {\n yield* this.flushPendingText(event);\n }\n\n yield event;\n }\n\n yield* this.flushSegments();\n };\n\n private emitNormalizedTextDelta = function* (\n this: HermesReasoningDeltaTranslator,\n event: Extract<NcpEndpointEvent, { type: NcpEventType.MessageTextDelta }>,\n ): Generator<NcpEndpointEvent> {\n const segments = this.normalizer.push(event.payload.delta);\n for (const segment of segments) {\n if (!segment.text) {\n continue;\n }\n if (segment.type === \"reasoning\") {\n yield {\n type: NcpEventType.MessageReasoningDelta,\n payload: {\n sessionId: event.payload.sessionId,\n messageId: event.payload.messageId,\n delta: segment.text,\n },\n };\n continue;\n }\n yield {\n type: NcpEventType.MessageTextDelta,\n payload: {\n sessionId: event.payload.sessionId,\n messageId: event.payload.messageId,\n delta: segment.text,\n },\n };\n }\n };\n\n private flushPendingText = function* (\n this: HermesReasoningDeltaTranslator,\n event: NcpEndpointEvent,\n ): Generator<NcpEndpointEvent> {\n const sessionId = this.readEventSessionId(event);\n const messageId = this.readEventMessageId(event);\n if (!sessionId || !messageId) {\n yield* this.flushSegments();\n return;\n }\n\n const segments = this.normalizer.finish();\n for (const segment of segments) {\n if (!segment.text) {\n continue;\n }\n if (segment.type === \"reasoning\") {\n yield {\n type: NcpEventType.MessageReasoningDelta,\n payload: {\n sessionId,\n messageId,\n delta: segment.text,\n },\n };\n continue;\n }\n yield {\n type: NcpEventType.MessageTextDelta,\n payload: {\n sessionId,\n messageId,\n delta: segment.text,\n },\n };\n }\n };\n\n private flushSegments = function* (\n this: HermesReasoningDeltaTranslator,\n ): Generator<NcpEndpointEvent> {\n this.normalizer.finish();\n };\n\n private shouldFlushPendingText = (event: NcpEndpointEvent): boolean =>\n event.type === NcpEventType.MessageTextEnd ||\n event.type === NcpEventType.MessageCompleted ||\n event.type === NcpEventType.MessageFailed ||\n event.type === NcpEventType.RunFinished ||\n event.type === NcpEventType.RunError;\n\n private readEventSessionId = (event: NcpEndpointEvent): string | undefined => {\n if (!(\"payload\" in event) || !event.payload || typeof event.payload !== \"object\") {\n return undefined;\n }\n return \"sessionId\" in event.payload && typeof event.payload.sessionId === \"string\"\n ? event.payload.sessionId\n : undefined;\n };\n\n private readEventMessageId = (event: NcpEndpointEvent): string | undefined => {\n if (!(\"payload\" in event) || !event.payload || typeof event.payload !== \"object\") {\n return undefined;\n }\n return \"messageId\" in event.payload && typeof event.payload.messageId === \"string\"\n ? event.payload.messageId\n : undefined;\n };\n}\n\nexport function resolveHermesModel(params: {\n envelope: NcpRequestEnvelope;\n fallbackModel: string;\n}): string {\n const { envelope, fallbackModel } = params;\n const providerRoute = readHermesProviderRoute(envelope);\n const metadata =\n envelope.metadata &&\n typeof envelope.metadata === \"object\" &&\n !Array.isArray(envelope.metadata)\n ? (envelope.metadata as Record<string, unknown>)\n : undefined;\n\n return (\n providerRoute?.model ??\n readMetadataString(metadata, \"preferred_model\") ??\n readMetadataString(metadata, \"preferredModel\") ??\n readMetadataString(metadata, \"model\") ??\n fallbackModel\n );\n}\n\nexport function normalizeHermesRequestedModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) {\n return trimmed;\n }\n\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex <= 0) {\n return trimmed;\n }\n\n const suffix = trimmed.slice(slashIndex + 1).trim();\n if (!suffix) {\n return trimmed;\n }\n\n if (suffix.includes(\":\")) {\n return suffix;\n }\n\n return trimmed;\n}\n\nexport function inferHermesProvider(params: {\n model: string;\n apiBase?: string | null;\n apiMode?: HermesProviderRoute[\"apiMode\"];\n}): string | undefined {\n if (params.apiMode === \"anthropic_messages\") {\n return \"anthropic\";\n }\n const model = params.model.trim().toLowerCase();\n const hostname = readHostname(params.apiBase);\n\n if (hostname.includes(\"anthropic.com\") || model.startsWith(\"claude\")) {\n return \"anthropic\";\n }\n return \"openai\";\n}\n\nexport function toNcpError(\n error: unknown,\n code: NcpError[\"code\"],\n): NcpError {\n return {\n code,\n message: error instanceof Error ? error.message : String(error),\n };\n}\n\nexport function toNcpSseFrame(event: NcpEndpointEvent): string {\n return `event: ncp-event\\ndata: ${JSON.stringify(event)}\\n\\n`;\n}\n\nexport function toErrorSseFrame(error: { code: string; message: string }): string {\n return `event: error\\ndata: ${JSON.stringify(error)}\\n\\n`;\n}\n\nfunction readHostname(value: string | null | undefined): string {\n if (!value) {\n return \"\";\n }\n try {\n return new URL(value).hostname.trim().toLowerCase();\n } catch {\n return \"\";\n }\n}\n\nfunction extractRuntimeHeaders(\n headers: Record<string, string>,\n): Pick<HermesProviderRoute, \"headers\" | \"apiMode\"> {\n const nextHeaders = { ...headers };\n const apiMode = nextHeaders[NARP_API_MODE_HEADER] as HermesProviderRoute[\"apiMode\"] | undefined;\n delete nextHeaders[NARP_API_MODE_HEADER];\n return {\n headers: nextHeaders,\n ...(apiMode ? { apiMode } : {}),\n };\n}\n\nfunction extractMessageText(message: NcpMessage): string {\n const text = message.parts\n .map((part) => {\n if (part.type === \"text\" || part.type === \"reasoning\" || part.type === \"rich-text\") {\n return part.text;\n }\n return \"\";\n })\n .join(\"\\n\")\n .trim();\n return text.length > 0 ? text : \"[empty message]\";\n}\n\nfunction splitIntoLineSegments(text: string): string[] {\n return text.match(/[^\\n]*\\n|[^\\n]+$/gu) ?? [];\n}\n\nfunction matchHermesInlineToolTrace(segment: string): HermesInlineToolTrace | null {\n const trimmed = segment.trim();\n if (!trimmed.startsWith(\"`\") || !trimmed.endsWith(\"`\")) {\n return null;\n }\n\n const body = trimmed.slice(1, -1).trim();\n for (const candidate of HERMES_INLINE_TOOL_TRACE_PATTERNS) {\n if (!body.startsWith(candidate.icon)) {\n continue;\n }\n const rawArgs = body.slice(candidate.icon.length).trim();\n if (!rawArgs) {\n return null;\n }\n return {\n toolName: candidate.toolName,\n args: candidate.buildArgs(rawArgs),\n };\n }\n\n return null;\n}\n\nfunction normalizeRole(role: NcpMessage[\"role\"]): HermesOpenAIMessage[\"role\"] {\n if (role === \"assistant\" || role === \"system\") {\n return role;\n }\n return \"user\";\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter-session-store.service.js","names":[],"sources":["../src/hermes-http-adapter-session-store.service.ts"],"sourcesContent":["import type { HermesHttpAdapterRun } from \"./hermes-http-adapter.types.js\";\n\ntype SessionRunWaiter = {\n resolve: (run: HermesHttpAdapterRun) => void;\n reject: (error: Error) => void;\n};\n\ntype SessionEntry = {\n hermesSessionId?: string;\n selectedModel?: string;\n pendingRun?: HermesHttpAdapterRun;\n activeAbortController?: AbortController;\n waiters: Set<SessionRunWaiter>;\n};\n\nexport class HermesHttpAdapterSessionStore {\n private readonly sessions = new Map<string, SessionEntry>();\n\n setPendingRun = (run: HermesHttpAdapterRun): void => {\n const session = this.getOrCreateEntry(run.envelope.sessionId);\n if (session.pendingRun || session.activeAbortController) {\n throw new Error(\n `[hermes-http-adapter] session ${run.envelope.sessionId} already has an active or pending run.`,\n );\n }\n session.pendingRun = run;\n this.flushWaiters(run.envelope.sessionId, session);\n };\n\n waitForPendingRun = async (\n sessionId: string,\n signal: AbortSignal,\n timeoutMs: number,\n ): Promise<HermesHttpAdapterRun> => {\n const entry = this.getOrCreateEntry(sessionId);\n if (entry.pendingRun) {\n const run = entry.pendingRun;\n entry.pendingRun = undefined;\n return run;\n }\n\n return await new Promise<HermesHttpAdapterRun>((resolve, reject) => {\n const waiter: SessionRunWaiter = {\n resolve: (run) => {\n cleanup();\n resolve(run);\n },\n reject: (error) => {\n cleanup();\n reject(error);\n },\n };\n\n const cleanup = (): void => {\n clearTimeout(timeout);\n signal.removeEventListener(\"abort\", handleAbort);\n entry.waiters.delete(waiter);\n };\n\n const handleAbort = (): void => {\n waiter.reject(createAbortError(\"stream request aborted before send arrived\"));\n };\n\n const timeout = setTimeout(() => {\n waiter.reject(\n new Error(\n `[hermes-http-adapter] timed out waiting for /send for session ${sessionId}.`,\n ),\n );\n }, timeoutMs);\n\n signal.addEventListener(\"abort\", handleAbort, { once: true });\n entry.waiters.add(waiter);\n });\n };\n\n setActiveAbortController = (\n sessionId: string,\n controller: AbortController,\n ): void => {\n const session = this.getOrCreateEntry(sessionId);\n session.activeAbortController = controller;\n };\n\n clearActiveAbortController = (sessionId: string): void => {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return;\n }\n session.activeAbortController = undefined;\n this.cleanupSession(sessionId, session);\n };\n\n abortSession = (sessionId: string): boolean => {\n const session = this.sessions.get(sessionId);\n if (!session?.activeAbortController) {\n return false;\n }\n session.activeAbortController.abort(\"session aborted\");\n return true;\n };\n\n setHermesSessionId = (sessionId: string, hermesSessionId: string): void => {\n const session = this.getOrCreateEntry(sessionId);\n session.hermesSessionId = hermesSessionId;\n };\n\n readHermesSessionId = (sessionId: string): string | undefined =>\n this.sessions.get(sessionId)?.hermesSessionId;\n\n setSelectedModel = (sessionId: string, model: string): void => {\n const session = this.getOrCreateEntry(sessionId);\n session.selectedModel = model;\n };\n\n readSelectedModel = (sessionId: string): string | undefined =>\n this.sessions.get(sessionId)?.selectedModel;\n\n dispose = (): void => {\n for (const [sessionId, session] of this.sessions.entries()) {\n session.activeAbortController?.abort(\"adapter disposed\");\n for (const waiter of session.waiters) {\n waiter.reject(new Error(`[hermes-http-adapter] adapter disposed for ${sessionId}.`));\n }\n session.waiters.clear();\n }\n this.sessions.clear();\n };\n\n private flushWaiters = (sessionId: string, session: SessionEntry): void => {\n if (!session.pendingRun || session.waiters.size === 0) {\n return;\n }\n const run = session.pendingRun;\n session.pendingRun = undefined;\n const waiters = [...session.waiters];\n session.waiters.clear();\n for (const waiter of waiters) {\n waiter.resolve(run);\n }\n this.cleanupSession(sessionId, session);\n };\n\n private cleanupSession = (sessionId: string, session: SessionEntry): void => {\n if (session.pendingRun || session.activeAbortController || session.waiters.size > 0) {\n return;\n }\n if (session.hermesSessionId || session.selectedModel) {\n return;\n }\n this.sessions.delete(sessionId);\n };\n\n private getOrCreateEntry = (sessionId: string): SessionEntry => {\n const existing = this.sessions.get(sessionId);\n if (existing) {\n return existing;\n }\n const created: SessionEntry = {\n waiters: new Set(),\n };\n this.sessions.set(sessionId, created);\n return created;\n };\n}\n\nfunction createAbortError(message: string): Error {\n const error = new Error(message);\n error.name = \"AbortError\";\n return error;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter.service.d.ts","names":[],"sources":["../src/hermes-http-adapter.service.ts"],"mappings":";;;;cAmmBa,uBAAA;EAAA,SACF,MAAA,EAAQ,+BAAA;EAAA,iBAEA,YAAA;EAAA,QACT,MAAA;cAEI,WAAA,GAAa,4BAAA;EAKzB,KAAA,QAAkB,OAAA;EAiBlB,IAAA,QAAiB,OAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter.service.js","names":[],"sources":["../src/hermes-http-adapter.service.ts"],"sourcesContent":["import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport { DefaultNcpStreamEncoder } from \"@nextclaw/ncp-agent-runtime\";\nimport {\n NcpEventType,\n type NcpEndpointEvent,\n type NcpRequestEnvelope,\n type OpenAITool,\n} from \"@nextclaw/ncp\";\nimport { HermesHttpAdapterConfigResolver } from \"./hermes-http-adapter-config.utils.js\";\nimport {\n buildHermesMessages,\n createAssistantMessageFromParts,\n HermesAssistantEventCollector,\n HermesInlineToolTraceTranslator,\n HermesReasoningDeltaTranslator,\n inferHermesProvider,\n normalizeHermesRequestedModel,\n readHermesProviderRoute,\n resolveHermesModel,\n type HermesProviderRoute,\n toErrorSseFrame,\n toNcpError,\n toNcpSseFrame,\n} from \"./hermes-http-adapter-message.utils.js\";\nimport { parseHermesOpenAIChatStream } from \"./hermes-openai-stream-parser.utils.js\";\nimport { HermesHttpAdapterSessionStore } from \"./hermes-http-adapter-session-store.service.js\";\nimport type {\n HermesAdapterAssistantMessageFactory,\n HermesHttpAdapterResolvedConfig,\n HermesHttpAdapterRun,\n HermesHttpAdapterRunResult,\n} from \"./hermes-http-adapter.types.js\";\nimport type { HermesHttpAdapterConfigInput } from \"./hermes-http-adapter-config.utils.js\";\n\nfunction isUserVisibleAssistantEvent(event: NcpEndpointEvent): boolean {\n const eventType = event.type;\n return (\n eventType.startsWith(\"message.text-\") ||\n eventType.startsWith(\"message.reasoning-\") ||\n eventType.startsWith(\"message.tool-call-\")\n );\n}\n\nclass HermesHttpAdapterRouteService {\n private readonly sessions = new HermesHttpAdapterSessionStore();\n private readonly streamEncoder = new DefaultNcpStreamEncoder({\n reasoningNormalizationMode: \"think-tags\",\n });\n private readonly fetchImpl: typeof fetch;\n\n constructor(\n private readonly config: HermesHttpAdapterResolvedConfig,\n private readonly buildAssistantMessage: HermesAdapterAssistantMessageFactory = createAssistantMessageFromParts,\n ) {\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n handle = async (\n request: IncomingMessage,\n response: ServerResponse,\n ): Promise<void> => {\n const requestUrl = new URL(request.url ?? \"/\", this.baseOrigin);\n const normalizedPath = requestUrl.pathname;\n\n if (request.method === \"GET\" && normalizedPath === \"/health\") {\n await this.handleHealth(response);\n return;\n }\n\n if (request.method === \"POST\" && normalizedPath === `${this.config.basePath}/send`) {\n await this.handleSend(request, response);\n return;\n }\n\n if (request.method === \"GET\" && normalizedPath === `${this.config.basePath}/stream`) {\n await this.handleStream(request, response, requestUrl);\n return;\n }\n\n if (request.method === \"POST\" && normalizedPath === `${this.config.basePath}/abort`) {\n await this.handleAbort(request, response);\n return;\n }\n\n this.writeJson(response, 404, {\n ok: false,\n error: {\n code: \"NOT_FOUND\",\n message: `Unknown path: ${normalizedPath}`,\n },\n });\n };\n\n dispose = (): void => {\n this.sessions.dispose();\n };\n\n private get baseOrigin(): string {\n return `http://${this.config.host}:${this.config.port}`;\n }\n\n private handleHealth = async (response: ServerResponse): Promise<void> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.config.healthcheckTimeoutMs);\n\n try {\n const upstream = await this.fetchImpl(this.config.healthcheckUrl, {\n method: \"GET\",\n signal: controller.signal,\n });\n if (!upstream.ok) {\n this.writeJson(response, 503, {\n status: \"degraded\",\n adapter: \"ok\",\n upstream: {\n status: \"error\",\n httpStatus: upstream.status,\n },\n });\n return;\n }\n this.writeJson(response, 200, {\n status: \"ok\",\n adapter: \"ok\",\n upstream: \"ok\",\n });\n } catch (error) {\n this.writeJson(response, 503, {\n status: \"degraded\",\n adapter: \"ok\",\n upstream: {\n status: \"unreachable\",\n message: error instanceof Error ? error.message : String(error),\n },\n });\n } finally {\n clearTimeout(timeout);\n }\n };\n\n private handleSend = async (\n request: IncomingMessage,\n response: ServerResponse,\n ): Promise<void> => {\n try {\n const envelope = await this.readJsonBody<NcpRequestEnvelope>(request);\n if (!envelope?.sessionId || !envelope.message) {\n this.writeJson(response, 400, {\n ok: false,\n error: {\n code: \"INVALID_BODY\",\n message: \"sessionId and message are required.\",\n },\n });\n return;\n }\n\n const run: HermesHttpAdapterRun = {\n envelope,\n messageId: randomUUID(),\n runId: randomUUID(),\n };\n this.sessions.setPendingRun(run);\n this.writeJson(response, 200, { ok: true });\n } catch (error) {\n this.writeJson(response, 409, {\n ok: false,\n error: {\n code: \"RUN_CONFLICT\",\n message: error instanceof Error ? error.message : String(error),\n },\n });\n }\n };\n\n private handleAbort = async (\n request: IncomingMessage,\n response: ServerResponse,\n ): Promise<void> => {\n try {\n const payload = await this.readJsonBody<{ sessionId?: string }>(request);\n const sessionId = typeof payload?.sessionId === \"string\" ? payload.sessionId : \"\";\n if (!sessionId.trim()) {\n this.writeJson(response, 400, {\n ok: false,\n error: {\n code: \"INVALID_BODY\",\n message: \"sessionId is required.\",\n },\n });\n return;\n }\n const aborted = this.sessions.abortSession(sessionId);\n this.writeJson(response, 200, { ok: true, aborted });\n } catch (error) {\n this.writeJson(response, 500, {\n ok: false,\n error: {\n code: \"ABORT_FAILED\",\n message: error instanceof Error ? error.message : String(error),\n },\n });\n }\n };\n\n private handleStream = async (\n request: IncomingMessage,\n response: ServerResponse,\n requestUrl: URL,\n ): Promise<void> => {\n const sessionId = requestUrl.searchParams.get(\"sessionId\")?.trim();\n if (!sessionId) {\n this.writeJson(response, 400, {\n ok: false,\n error: {\n code: \"INVALID_QUERY\",\n message: \"sessionId is required.\",\n },\n });\n return;\n }\n\n const connectionController = new AbortController();\n const runController = new AbortController();\n response.once(\"close\", () => {\n connectionController.abort(\"client disconnected\");\n runController.abort(\"client disconnected\");\n });\n\n response.writeHead(200, {\n \"content-type\": \"text/event-stream; charset=utf-8\",\n \"cache-control\": \"no-cache, no-transform\",\n connection: \"keep-alive\",\n \"x-accel-buffering\": \"no\",\n });\n\n try {\n const run = await this.sessions.waitForPendingRun(\n sessionId,\n connectionController.signal,\n this.config.streamWaitTimeoutMs,\n );\n this.sessions.setActiveAbortController(sessionId, runController);\n\n const streamResult = await this.startRun({\n run,\n signal: runController.signal,\n });\n\n for await (const event of streamResult.events) {\n if (connectionController.signal.aborted) {\n break;\n }\n response.write(toNcpSseFrame(event));\n }\n } catch (error) {\n if (!connectionController.signal.aborted) {\n response.write(\n toErrorSseFrame({\n code: \"STREAM_FAILED\",\n message: error instanceof Error ? error.message : String(error),\n }),\n );\n }\n } finally {\n this.sessions.clearActiveAbortController(sessionId);\n response.end();\n }\n };\n\n private startRun = async (params: {\n run: HermesHttpAdapterRun;\n signal: AbortSignal;\n }): Promise<HermesHttpAdapterRunResult> => {\n const { run, signal } = params;\n const providerRoute = this.readProviderRoute(run.envelope);\n const requestedModel = normalizeHermesRequestedModel(resolveHermesModel({\n envelope: run.envelope,\n fallbackModel: this.config.model,\n }));\n if (!providerRoute) {\n await this.ensureHermesSessionModel({\n sessionId: run.envelope.sessionId,\n requestedModel,\n signal,\n });\n }\n\n const response = await this.fetchHermesChatCompletion({\n sessionId: run.envelope.sessionId,\n signal,\n stream: true,\n model: requestedModel,\n providerRoute,\n messages: buildHermesMessages({\n envelope: run.envelope,\n systemPrompt: this.config.systemPrompt,\n }),\n tools: run.envelope.tools,\n });\n if (!response.body) {\n throw new Error(\"[hermes-http-adapter] Hermes stream response body is missing.\");\n }\n this.sessions.setSelectedModel(run.envelope.sessionId, requestedModel);\n\n return {\n events: this.createRunEvents({\n response,\n run,\n signal,\n }),\n };\n };\n\n private createRunEvents = async function* (\n this: HermesHttpAdapterRouteService,\n params: {\n response: Response;\n run: HermesHttpAdapterRun;\n signal: AbortSignal;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { response, run, signal } = params;\n const sessionId = run.envelope.sessionId;\n const providerRoute = this.readProviderRoute(run.envelope);\n const requestedModel = normalizeHermesRequestedModel(resolveHermesModel({\n envelope: run.envelope,\n fallbackModel: this.config.model,\n }));\n const metadata = {\n hermesModel: requestedModel,\n };\n let emittedUserVisibleAssistantEvent = false;\n const messageCollector = new HermesAssistantEventCollector();\n const inlineToolTraceTranslator = new HermesInlineToolTraceTranslator();\n const reasoningDeltaTranslator = new HermesReasoningDeltaTranslator();\n\n yield {\n type: NcpEventType.MessageAccepted,\n payload: {\n messageId: run.messageId,\n correlationId: run.envelope.correlationId,\n },\n };\n yield {\n type: NcpEventType.RunStarted,\n payload: {\n sessionId,\n messageId: run.messageId,\n runId: run.runId,\n },\n };\n\n try {\n for await (const event of reasoningDeltaTranslator.translate(\n inlineToolTraceTranslator.translate(\n this.streamEncoder.encode(\n parseHermesOpenAIChatStream(response.body as ReadableStream<Uint8Array>),\n {\n sessionId,\n messageId: run.messageId,\n runId: run.runId,\n correlationId: run.envelope.correlationId,\n },\n ),\n ),\n )) {\n messageCollector.applyEvent(event);\n if (isUserVisibleAssistantEvent(event)) {\n emittedUserVisibleAssistantEvent = true;\n }\n yield event;\n }\n\n if (!emittedUserVisibleAssistantEvent || !messageCollector.hasParts()) {\n throw new Error(\n `[hermes-http-adapter] Hermes completed without any assistant content for session ${sessionId}.`,\n );\n }\n\n const message = this.buildAssistantMessage({\n sessionId,\n messageId: run.messageId,\n parts: messageCollector.buildParts(),\n timestamp: new Date().toISOString(),\n metadata,\n });\n yield {\n type: NcpEventType.MessageCompleted,\n payload: {\n sessionId,\n message,\n correlationId: run.envelope.correlationId,\n metadata,\n },\n };\n yield {\n type: NcpEventType.RunFinished,\n payload: {\n sessionId,\n messageId: run.messageId,\n runId: run.runId,\n },\n };\n } catch (error) {\n if (signal.aborted) {\n const abortError = toNcpError(error, \"abort-error\");\n yield {\n type: NcpEventType.MessageFailed,\n payload: {\n sessionId,\n messageId: run.messageId,\n correlationId: run.envelope.correlationId,\n error: abortError,\n },\n };\n yield {\n type: NcpEventType.RunError,\n payload: {\n sessionId,\n messageId: run.messageId,\n runId: run.runId,\n error: abortError.message,\n },\n };\n return;\n }\n\n const runtimeError = toNcpError(error, \"runtime-error\");\n yield {\n type: NcpEventType.MessageFailed,\n payload: {\n sessionId,\n messageId: run.messageId,\n correlationId: run.envelope.correlationId,\n error: runtimeError,\n },\n };\n yield {\n type: NcpEventType.RunError,\n payload: {\n sessionId,\n messageId: run.messageId,\n runId: run.runId,\n error: runtimeError.message,\n },\n };\n }\n };\n\n private ensureHermesSessionModel = async (params: {\n sessionId: string;\n requestedModel: string;\n signal: AbortSignal;\n }): Promise<void> => {\n const { requestedModel, sessionId, signal } = params;\n const selectedModel = this.sessions.readSelectedModel(sessionId) ?? this.config.model;\n if (selectedModel === requestedModel) {\n return;\n }\n\n const response = await this.fetchHermesChatCompletion({\n sessionId,\n signal,\n stream: false,\n model: requestedModel,\n messages: [\n {\n role: \"user\",\n content: `/model ${requestedModel}`,\n },\n ],\n });\n\n const payload = await this.readJsonResponse<{\n choices?: Array<{\n message?: {\n content?: unknown;\n };\n }>;\n }>(response);\n const content = payload.choices?.[0]?.message?.content;\n if (typeof content === \"string\" && content.trim().startsWith(\"Error:\")) {\n throw new Error(\n `[hermes-http-adapter] failed to switch Hermes model to ${requestedModel}: ${content.trim()}`,\n );\n }\n\n this.sessions.setSelectedModel(sessionId, requestedModel);\n };\n\n private fetchHermesChatCompletion = async (params: {\n sessionId: string;\n signal: AbortSignal;\n stream: boolean;\n model: string;\n providerRoute?: HermesProviderRoute;\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>;\n tools?: ReadonlyArray<OpenAITool>;\n }): Promise<Response> => {\n const { messages, model, providerRoute, sessionId, signal, stream, tools } = params;\n const headers = new Headers({\n \"content-type\": \"application/json\",\n accept: stream ? \"text/event-stream\" : \"application/json\",\n });\n if (this.config.hermesApiKey) {\n headers.set(\"authorization\", `Bearer ${this.config.hermesApiKey}`);\n }\n\n const hermesSessionId = this.sessions.readHermesSessionId(sessionId);\n if (hermesSessionId) {\n headers.set(\"x-hermes-session-id\", hermesSessionId);\n }\n\n const response = await this.fetchImpl(this.config.chatCompletionsUrl, {\n method: \"POST\",\n headers,\n signal,\n body: JSON.stringify({\n model,\n stream,\n messages,\n ...(providerRoute\n ? {\n nextclaw_provider_route:\n this.toHermesProviderRoutePayload(providerRoute),\n }\n : {}),\n ...(tools && tools.length > 0 ? { tools } : {}),\n }),\n });\n if (!response.ok) {\n throw new Error(\n `[hermes-http-adapter] Hermes request failed with HTTP ${response.status}.`,\n );\n }\n\n const returnedSessionId = response.headers.get(\"x-hermes-session-id\")?.trim();\n if (returnedSessionId) {\n this.sessions.setHermesSessionId(sessionId, returnedSessionId);\n }\n\n return response;\n };\n\n private readProviderRoute = (\n envelope: NcpRequestEnvelope,\n ): HermesProviderRoute | undefined => {\n const providerRoute = readHermesProviderRoute(envelope);\n if (!providerRoute) {\n return undefined;\n }\n if (!providerRoute.apiBase) {\n throw new Error(\n `[hermes-http-adapter] missing provider apiBase for model \"${providerRoute.model}\". Configure the selected NextClaw provider before using Hermes.`,\n );\n }\n return providerRoute;\n };\n\n private toHermesProviderRoutePayload = (\n providerRoute: HermesProviderRoute,\n ): Record<string, unknown> => {\n const inferredProvider = inferHermesProvider(providerRoute);\n return {\n model: providerRoute.model,\n ...(inferredProvider ? { provider: inferredProvider } : {}),\n ...(providerRoute.apiKey ? { api_key: providerRoute.apiKey } : {}),\n ...(providerRoute.apiBase ? { base_url: providerRoute.apiBase } : {}),\n ...(providerRoute.apiMode ? { api_mode: providerRoute.apiMode } : {}),\n ...(Object.keys(providerRoute.headers).length > 0\n ? { extra_headers: providerRoute.headers }\n : {}),\n };\n };\n\n private readJsonResponse = async <T>(response: Response): Promise<T> => {\n try {\n return (await response.json()) as T;\n } catch (error) {\n throw new Error(\n `[hermes-http-adapter] expected JSON response from Hermes: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n };\n\n private readJsonBody = async <T>(request: IncomingMessage): Promise<T> => {\n const chunks: Buffer[] = [];\n for await (const chunk of request) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const body = Buffer.concat(chunks).toString(\"utf8\");\n if (!body.trim()) {\n throw new Error(\"request body is empty\");\n }\n return JSON.parse(body) as T;\n };\n\n private writeJson = (\n response: ServerResponse,\n statusCode: number,\n payload: unknown,\n ): void => {\n response.writeHead(statusCode, {\n \"content-type\": \"application/json; charset=utf-8\",\n });\n response.end(JSON.stringify(payload));\n };\n}\n\nexport class HermesHttpAdapterServer {\n readonly config: HermesHttpAdapterResolvedConfig;\n\n private readonly routeService: HermesHttpAdapterRouteService;\n private server: Server | null = null;\n\n constructor(configInput: HermesHttpAdapterConfigInput = {}) {\n this.config = new HermesHttpAdapterConfigResolver(configInput).resolve();\n this.routeService = new HermesHttpAdapterRouteService(this.config);\n }\n\n start = async (): Promise<void> => {\n if (this.server) {\n return;\n }\n const nextServer = createServer((request, response) => {\n void this.routeService.handle(request, response);\n });\n await new Promise<void>((resolve, reject) => {\n nextServer.once(\"error\", reject);\n nextServer.listen(this.config.port, this.config.host, () => {\n nextServer.off(\"error\", reject);\n resolve();\n });\n });\n this.server = nextServer;\n };\n\n stop = async (): Promise<void> => {\n this.routeService.dispose();\n const activeServer = this.server;\n if (!activeServer) {\n return;\n }\n await new Promise<void>((resolve, reject) => {\n activeServer.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n this.server = null;\n };\n}\n"],"mappings":"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"}
|
|
@@ -23,4 +23,5 @@ type HermesOpenAIMessage = {
|
|
|
23
23
|
content: string;
|
|
24
24
|
};
|
|
25
25
|
//#endregion
|
|
26
|
-
export { HermesHttpAdapterConfig, HermesHttpAdapterFetchLike, HermesHttpAdapterResolvedConfig, HermesOpenAIMessage };
|
|
26
|
+
export { HermesHttpAdapterConfig, HermesHttpAdapterFetchLike, HermesHttpAdapterResolvedConfig, HermesOpenAIMessage };
|
|
27
|
+
//# sourceMappingURL=hermes-http-adapter.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-http-adapter.types.d.ts","names":[],"sources":["../src/hermes-http-adapter.types.ts"],"mappings":";;;KAOY,0BAAA,IACV,KAAA,EAAO,GAAA,YAAe,OAAA,EACtB,IAAA,GAAO,WAAA,KACJ,OAAA,CAAQ,QAAA;AAAA,KAED,uBAAA;EACV,IAAA;EACA,IAAA;EACA,QAAA;EACA,aAAA;EACA,YAAA;EACA,KAAA;EACA,YAAA;EACA,mBAAA;EACA,oBAAA;EACA,SAAA,GAAY,0BAAA;AAAA;AAAA,KAGF,+BAAA,GAAkC,uBAAA;EAC5C,kBAAA;EACA,cAAA;AAAA;AAAA,KAaU,mBAAA;EACV,IAAA;EACA,OAAA;AAAA"}
|
|
@@ -3,4 +3,5 @@ import { OpenAIChatChunk } from "@nextclaw/ncp";
|
|
|
3
3
|
//#region src/hermes-openai-stream-parser.utils.d.ts
|
|
4
4
|
declare function parseHermesOpenAIChatStream(stream: ReadableStream<Uint8Array>): AsyncGenerator<OpenAIChatChunk>;
|
|
5
5
|
//#endregion
|
|
6
|
-
export { parseHermesOpenAIChatStream };
|
|
6
|
+
export { parseHermesOpenAIChatStream };
|
|
7
|
+
//# sourceMappingURL=hermes-openai-stream-parser.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-openai-stream-parser.utils.d.ts","names":[],"sources":["../src/hermes-openai-stream-parser.utils.ts"],"mappings":";;;iBAMuB,2BAAA,CACrB,MAAA,EAAQ,cAAA,CAAe,UAAA,IACtB,cAAA,CAAe,eAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-openai-stream-parser.utils.js","names":[],"sources":["../src/hermes-openai-stream-parser.utils.ts"],"sourcesContent":["import type { OpenAIChatChunk } from \"@nextclaw/ncp\";\n\ntype SseFrame = {\n data: string;\n};\n\nexport async function* parseHermesOpenAIChatStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<OpenAIChatChunk> {\n for await (const frame of consumeSseFrames(stream)) {\n const payload = frame.data.trim();\n if (!payload || payload === \"[DONE]\") {\n continue;\n }\n const parsed = JSON.parse(payload) as OpenAIChatChunk;\n yield parsed;\n }\n}\n\nasync function* consumeSseFrames(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<SseFrame> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n break;\n }\n buffer += decoder.decode(value, { stream: true });\n const drained = drainSseFrames(buffer);\n buffer = drained.rest;\n for (const frame of drained.frames) {\n yield frame;\n }\n }\n buffer += decoder.decode();\n const drained = drainSseFrames(buffer, true);\n for (const frame of drained.frames) {\n yield frame;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction drainSseFrames(\n rawBuffer: string,\n flush = false,\n): { frames: SseFrame[]; rest: string } {\n const parts = rawBuffer.split(/\\r?\\n\\r?\\n/u);\n const rest = parts.pop() ?? \"\";\n const frames = parts\n .map(parseSseFrame)\n .filter((frame): frame is SseFrame => Boolean(frame));\n\n if (!flush || !rest.trim()) {\n return { frames, rest };\n }\n\n const finalFrame = parseSseFrame(rest);\n return {\n frames: finalFrame ? [...frames, finalFrame] : frames,\n rest: \"\",\n };\n}\n\nfunction parseSseFrame(frameText: string): SseFrame | null {\n const dataLines: string[] = [];\n for (const rawLine of frameText.split(/\\r?\\n/u)) {\n const line = rawLine.trimEnd();\n if (!line || line.startsWith(\":\") || !line.startsWith(\"data:\")) {\n continue;\n }\n dataLines.push(line.slice(5).trimStart());\n }\n\n if (dataLines.length === 0) {\n return null;\n }\n\n return {\n data: dataLines.join(\"\\n\"),\n };\n}\n"],"mappings":";AAMA,gBAAuB,4BACrB,QACiC;AACjC,YAAW,MAAM,SAAS,iBAAiB,OAAO,EAAE;EAClD,MAAM,UAAU,MAAM,KAAK,MAAM;AACjC,MAAI,CAAC,WAAW,YAAY,SAC1B;AAGF,QADe,KAAK,MAAM,QAAQ;;;AAKtC,gBAAgB,iBACd,QAC0B;CAC1B,MAAM,SAAS,OAAO,WAAW;CACjC,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,SAAS;AAEb,KAAI;AACF,SAAO,MAAM;GACX,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,MAAM;AAC3C,OAAI,KACF;AAEF,aAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;GACjD,MAAM,UAAU,eAAe,OAAO;AACtC,YAAS,QAAQ;AACjB,QAAK,MAAM,SAAS,QAAQ,OAC1B,OAAM;;AAGV,YAAU,QAAQ,QAAQ;EAC1B,MAAM,UAAU,eAAe,QAAQ,KAAK;AAC5C,OAAK,MAAM,SAAS,QAAQ,OAC1B,OAAM;WAEA;AACR,SAAO,aAAa;;;AAIxB,SAAS,eACP,WACA,QAAQ,OAC8B;CACtC,MAAM,QAAQ,UAAU,MAAM,cAAc;CAC5C,MAAM,OAAO,MAAM,KAAK,IAAI;CAC5B,MAAM,SAAS,MACZ,IAAI,cAAc,CAClB,QAAQ,UAA6B,QAAQ,MAAM,CAAC;AAEvD,KAAI,CAAC,SAAS,CAAC,KAAK,MAAM,CACxB,QAAO;EAAE;EAAQ;EAAM;CAGzB,MAAM,aAAa,cAAc,KAAK;AACtC,QAAO;EACL,QAAQ,aAAa,CAAC,GAAG,QAAQ,WAAW,GAAG;EAC/C,MAAM;EACP;;AAGH,SAAS,cAAc,WAAoC;CACzD,MAAM,YAAsB,EAAE;AAC9B,MAAK,MAAM,WAAW,UAAU,MAAM,SAAS,EAAE;EAC/C,MAAM,OAAO,QAAQ,SAAS;AAC9B,MAAI,CAAC,QAAQ,KAAK,WAAW,IAAI,IAAI,CAAC,KAAK,WAAW,QAAQ,CAC5D;AAEF,YAAU,KAAK,KAAK,MAAM,EAAE,CAAC,WAAW,CAAC;;AAG3C,KAAI,UAAU,WAAW,EACvB,QAAO;AAGT,QAAO,EACL,MAAM,UAAU,KAAK,KAAK,EAC3B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/nextclaw-ncp-runtime-adapter-hermes-http",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Standalone NCP HTTP adapter server that bridges NextClaw http-runtime sessions to Hermes API Server.",
|
|
6
6
|
"type": "module",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"README.md"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@nextclaw/ncp": "0.5.
|
|
23
|
-
"@nextclaw/ncp-agent-
|
|
24
|
-
"@nextclaw/ncp-
|
|
22
|
+
"@nextclaw/ncp": "0.5.17",
|
|
23
|
+
"@nextclaw/ncp-http-agent-client": "0.3.29",
|
|
24
|
+
"@nextclaw/ncp-agent-runtime": "0.3.28"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^20.17.6",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"vitest": "^4.1.2"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
|
-
"build": "tsdown src/index.ts src/cli.ts --dts --clean --target es2022 --no-fixedExtension --unbundle",
|
|
32
|
+
"build": "tsdown src/index.ts src/cli.ts --dts.sourcemap --clean --target es2022 --no-fixedExtension --unbundle",
|
|
33
33
|
"lint": "eslint .",
|
|
34
34
|
"tsc": "tsc -p tsconfig.json",
|
|
35
35
|
"test": "vitest run"
|