@haiai/haiai 0.1.2
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/README.md +127 -0
- package/bin/haiai.cjs +70 -0
- package/dist/cjs/a2a.js +352 -0
- package/dist/cjs/a2a.js.map +1 -0
- package/dist/cjs/agent.js +236 -0
- package/dist/cjs/agent.js.map +1 -0
- package/dist/cjs/client.js +2168 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/config.js +176 -0
- package/dist/cjs/config.js.map +1 -0
- package/dist/cjs/errors.js +102 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/hash.js +52 -0
- package/dist/cjs/hash.js.map +1 -0
- package/dist/cjs/index.js +84 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/integrations.js +193 -0
- package/dist/cjs/integrations.js.map +1 -0
- package/dist/cjs/jacs.js +66 -0
- package/dist/cjs/jacs.js.map +1 -0
- package/dist/cjs/mime.js +100 -0
- package/dist/cjs/mime.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/signing.js +190 -0
- package/dist/cjs/signing.js.map +1 -0
- package/dist/cjs/sse.js +76 -0
- package/dist/cjs/sse.js.map +1 -0
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/verify.js +76 -0
- package/dist/cjs/verify.js.map +1 -0
- package/dist/cjs/ws.js +206 -0
- package/dist/cjs/ws.js.map +1 -0
- package/dist/esm/a2a.js +305 -0
- package/dist/esm/a2a.js.map +1 -0
- package/dist/esm/agent.js +231 -0
- package/dist/esm/agent.js.map +1 -0
- package/dist/esm/client.js +2131 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/config.js +171 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/errors.js +88 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/hash.js +49 -0
- package/dist/esm/hash.js.map +1 -0
- package/dist/esm/index.js +27 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/integrations.js +147 -0
- package/dist/esm/integrations.js.map +1 -0
- package/dist/esm/jacs.js +61 -0
- package/dist/esm/jacs.js.map +1 -0
- package/dist/esm/mime.js +97 -0
- package/dist/esm/mime.js.map +1 -0
- package/dist/esm/signing.js +183 -0
- package/dist/esm/signing.js.map +1 -0
- package/dist/esm/sse.js +73 -0
- package/dist/esm/sse.js.map +1 -0
- package/dist/esm/types.js +5 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/verify.js +72 -0
- package/dist/esm/verify.js.map +1 -0
- package/dist/esm/ws.js +168 -0
- package/dist/esm/ws.js.map +1 -0
- package/dist/types/a2a.d.ts +52 -0
- package/dist/types/a2a.d.ts.map +1 -0
- package/dist/types/agent.d.ts +202 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/client.d.ts +486 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/config.d.ts +31 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/errors.d.ts +50 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/hash.d.ts +32 -0
- package/dist/types/hash.d.ts.map +1 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/integrations.d.ts +25 -0
- package/dist/types/integrations.d.ts.map +1 -0
- package/dist/types/jacs.d.ts +26 -0
- package/dist/types/jacs.d.ts.map +1 -0
- package/dist/types/mime.d.ts +39 -0
- package/dist/types/mime.d.ts.map +1 -0
- package/dist/types/signing.d.ts +58 -0
- package/dist/types/signing.d.ts.map +1 -0
- package/dist/types/sse.d.ts +8 -0
- package/dist/types/sse.d.ts.map +1 -0
- package/dist/types/types.d.ts +652 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/verify.d.ts +20 -0
- package/dist/types/verify.d.ts.map +1 -0
- package/dist/types/ws.d.ts +30 -0
- package/dist/types/ws.d.ts.map +1 -0
- package/examples/a2a_quickstart.ts +138 -0
- package/examples/hai_quickstart.ts +111 -0
- package/examples/mcp_quickstart.ts +53 -0
- package/npm/@haiai/cli-darwin-arm64/package.json +16 -0
- package/npm/@haiai/cli-darwin-x64/package.json +16 -0
- package/npm/@haiai/cli-linux-arm64/package.json +16 -0
- package/npm/@haiai/cli-linux-x64/package.json +16 -0
- package/npm/@haiai/cli-win32-x64/package.json +16 -0
- package/package.json +68 -0
- package/scripts/build-platform-packages.js +132 -0
- package/scripts/smoke-package.cjs +114 -0
- package/scripts/write-cjs-package.cjs +9 -0
- package/src/a2a.ts +463 -0
- package/src/agent.ts +302 -0
- package/src/client.ts +2504 -0
- package/src/config.ts +204 -0
- package/src/errors.ts +99 -0
- package/src/hash.ts +66 -0
- package/src/index.ts +163 -0
- package/src/integrations.ts +210 -0
- package/src/jacs.ts +86 -0
- package/src/mime.ts +131 -0
- package/src/signing.ts +233 -0
- package/src/sse.ts +86 -0
- package/src/types.ts +773 -0
- package/src/verify.ts +89 -0
- package/src/ws.ts +198 -0
- package/tests/_debug_jacs.cjs +29 -0
- package/tests/a2a-contract.test.ts +271 -0
- package/tests/a2a-fixtures.test.ts +73 -0
- package/tests/a2a.test.ts +379 -0
- package/tests/binary.test.ts +90 -0
- package/tests/client-api-methods.test.ts +176 -0
- package/tests/client-path-escaping.test.ts +80 -0
- package/tests/client-register.test.ts +61 -0
- package/tests/config.test.ts +281 -0
- package/tests/contract.test.ts +360 -0
- package/tests/cross-lang-contract.test.ts +67 -0
- package/tests/email-conformance.test.ts +289 -0
- package/tests/email-integration.test.ts +217 -0
- package/tests/email.test.ts +767 -0
- package/tests/errors.test.ts +167 -0
- package/tests/init-contract.test.ts +129 -0
- package/tests/integrations.test.ts +132 -0
- package/tests/jacs-passthrough.test.ts +125 -0
- package/tests/key-cache.test.ts +201 -0
- package/tests/key-integration.test.ts +119 -0
- package/tests/key-lookups.test.ts +187 -0
- package/tests/key-rotation.test.ts +362 -0
- package/tests/mime.test.ts +127 -0
- package/tests/security.test.ts +109 -0
- package/tests/setup.ts +60 -0
- package/tests/signing.test.ts +142 -0
- package/tests/sse.test.ts +125 -0
- package/tests/types.test.ts +294 -0
- package/tests/verify-link.test.ts +81 -0
- package/tests/ws.test.ts +213 -0
- package/tsconfig.cjs.json +11 -0
- package/tsconfig.json +22 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.JacsModuleError = void 0;
|
|
37
|
+
exports.langchainSignedTool = langchainSignedTool;
|
|
38
|
+
exports.langgraphWrapToolCall = langgraphWrapToolCall;
|
|
39
|
+
exports.langgraphToolNode = langgraphToolNode;
|
|
40
|
+
exports.createJacsLangchainTools = createJacsLangchainTools;
|
|
41
|
+
exports.createJacsMcpTransportProxy = createJacsMcpTransportProxy;
|
|
42
|
+
exports.getJacsMcpToolDefinitions = getJacsMcpToolDefinitions;
|
|
43
|
+
exports.registerJacsMcpTools = registerJacsMcpTools;
|
|
44
|
+
exports.createAgentSdkToolWrapper = createAgentSdkToolWrapper;
|
|
45
|
+
exports.verifyAgentSdkPayload = verifyAgentSdkPayload;
|
|
46
|
+
const node_util_1 = require("node:util");
|
|
47
|
+
class JacsModuleError extends Error {
|
|
48
|
+
constructor(message) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = 'JacsModuleError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.JacsModuleError = JacsModuleError;
|
|
54
|
+
function isMissingModuleError(error, moduleName) {
|
|
55
|
+
if (!error || typeof error !== 'object') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const code = error.code;
|
|
59
|
+
if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const message = error.message ?? '';
|
|
63
|
+
if (message.includes(`Cannot find package '${moduleName}'`)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (message.includes(`Cannot find module '${moduleName}'`)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (message.includes(`Failed to load url ${moduleName}`)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
async function loadOptionalModule(moduleName, feature, installHint) {
|
|
75
|
+
try {
|
|
76
|
+
return await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (isMissingModuleError(error, moduleName)) {
|
|
80
|
+
throw new JacsModuleError(`Optional dependency '${moduleName}' is required for ${feature}. ${installHint}`);
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function getRequiredFunction(moduleName, moduleObj, name) {
|
|
86
|
+
const value = moduleObj[name];
|
|
87
|
+
if (typeof value !== 'function') {
|
|
88
|
+
throw new JacsModuleError(`Module '${moduleName}' does not export function '${name}'. ` +
|
|
89
|
+
`Received: ${(0, node_util_1.inspect)(value, { depth: 1 })}`);
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
const LANGCHAIN_HINT = "Install with: npm install @hai.ai/jacs @langchain/core @langchain/langgraph";
|
|
94
|
+
const MCP_HINT = "Install with: npm install @hai.ai/jacs @modelcontextprotocol/sdk";
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// LangChain / LangGraph wrappers (delegates to @hai.ai/jacs/langchain)
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
async function langchainSignedTool(tool, options) {
|
|
99
|
+
const moduleName = '@hai.ai/jacs/langchain';
|
|
100
|
+
const mod = await loadOptionalModule(moduleName, 'LangChain/LangGraph integration', LANGCHAIN_HINT);
|
|
101
|
+
return getRequiredFunction(moduleName, mod, 'signedTool')(tool, options);
|
|
102
|
+
}
|
|
103
|
+
async function langgraphWrapToolCall(options) {
|
|
104
|
+
const moduleName = '@hai.ai/jacs/langchain';
|
|
105
|
+
const mod = await loadOptionalModule(moduleName, 'LangGraph tool wrapping', LANGCHAIN_HINT);
|
|
106
|
+
return getRequiredFunction(moduleName, mod, 'jacsWrapToolCall')(options);
|
|
107
|
+
}
|
|
108
|
+
async function langgraphToolNode(tools, options) {
|
|
109
|
+
const moduleName = '@hai.ai/jacs/langchain';
|
|
110
|
+
const mod = await loadOptionalModule(moduleName, 'LangGraph ToolNode integration', LANGCHAIN_HINT);
|
|
111
|
+
return getRequiredFunction(moduleName, mod, 'jacsToolNode')(tools, options);
|
|
112
|
+
}
|
|
113
|
+
async function createJacsLangchainTools(options) {
|
|
114
|
+
const moduleName = '@hai.ai/jacs/langchain';
|
|
115
|
+
const mod = await loadOptionalModule(moduleName, 'LangChain JACS tools', LANGCHAIN_HINT);
|
|
116
|
+
return getRequiredFunction(moduleName, mod, 'createJacsTools')(options);
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// MCP wrappers (delegates to @hai.ai/jacs/mcp)
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
async function createJacsMcpTransportProxy(transport, clientOrAgent, role = 'server') {
|
|
122
|
+
const moduleName = '@hai.ai/jacs/mcp';
|
|
123
|
+
const mod = await loadOptionalModule(moduleName, 'MCP transport signing', MCP_HINT);
|
|
124
|
+
return getRequiredFunction(moduleName, mod, 'createJACSTransportProxy')(transport, clientOrAgent, role);
|
|
125
|
+
}
|
|
126
|
+
async function getJacsMcpToolDefinitions() {
|
|
127
|
+
const moduleName = '@hai.ai/jacs/mcp';
|
|
128
|
+
const mod = await loadOptionalModule(moduleName, 'MCP tool definitions', MCP_HINT);
|
|
129
|
+
return getRequiredFunction(moduleName, mod, 'getJacsMcpToolDefinitions')();
|
|
130
|
+
}
|
|
131
|
+
async function registerJacsMcpTools(server, client) {
|
|
132
|
+
const moduleName = '@hai.ai/jacs/mcp';
|
|
133
|
+
const mod = await loadOptionalModule(moduleName, 'MCP server tool registration', MCP_HINT);
|
|
134
|
+
getRequiredFunction(moduleName, mod, 'registerJacsTools')(server, client);
|
|
135
|
+
}
|
|
136
|
+
function normalizeSignedPayload(value) {
|
|
137
|
+
if (typeof value === 'string') {
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
if (value && typeof value === 'object') {
|
|
141
|
+
const v = value;
|
|
142
|
+
const direct = v.raw ?? v.raw_json ?? v.rawJson;
|
|
143
|
+
if (typeof direct === 'string') {
|
|
144
|
+
return direct;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return JSON.stringify(value);
|
|
148
|
+
}
|
|
149
|
+
function passthroughPayload(value) {
|
|
150
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
151
|
+
}
|
|
152
|
+
function createAgentSdkToolWrapper(options) {
|
|
153
|
+
const strict = options.strict ?? false;
|
|
154
|
+
return function wrapTool(tool, toolName) {
|
|
155
|
+
const resolvedToolName = toolName ?? options.defaultToolName ?? tool.name ?? 'tool';
|
|
156
|
+
return async (...args) => {
|
|
157
|
+
const result = await tool(...args);
|
|
158
|
+
const payload = {
|
|
159
|
+
tool: resolvedToolName,
|
|
160
|
+
result,
|
|
161
|
+
};
|
|
162
|
+
try {
|
|
163
|
+
const signed = await options.signer.signMessage(payload);
|
|
164
|
+
return normalizeSignedPayload(signed);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (strict) {
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
return passthroughPayload(result);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async function verifyAgentSdkPayload(signer, signedPayload, options = {}) {
|
|
176
|
+
const strict = options.strict ?? false;
|
|
177
|
+
if (typeof signer.verify !== 'function') {
|
|
178
|
+
if (strict) {
|
|
179
|
+
throw new JacsModuleError('Agent SDK verification requires signer.verify(signedPayload).');
|
|
180
|
+
}
|
|
181
|
+
return signedPayload;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
return await signer.verify(signedPayload);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
if (strict) {
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
return signedPayload;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=integrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../src/integrations.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/jacs.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveJacsCliBin = resolveJacsCliBin;
|
|
4
|
+
exports.enforceMcpRunStdioArgs = enforceMcpRunStdioArgs;
|
|
5
|
+
exports.runJacsCli = runJacsCli;
|
|
6
|
+
const node_child_process_1 = require("node:child_process");
|
|
7
|
+
function resolveJacsCliBin(env = process.env) {
|
|
8
|
+
const candidate = (env.JACS_CLI_BIN ?? '').trim();
|
|
9
|
+
return candidate.length > 0 ? candidate : 'jacs';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Enforce local MCP execution policy when invoking `jacs mcp run`.
|
|
13
|
+
*
|
|
14
|
+
* We only allow `--bin` passthrough here and reject all forwarded runtime args
|
|
15
|
+
* so transport cannot be switched away from stdio.
|
|
16
|
+
*/
|
|
17
|
+
function enforceMcpRunStdioArgs(args) {
|
|
18
|
+
if (args.length < 2 || args[0] !== 'mcp' || args[1] !== 'run') {
|
|
19
|
+
return args;
|
|
20
|
+
}
|
|
21
|
+
const normalized = ['mcp', 'run'];
|
|
22
|
+
for (let i = 2; i < args.length; i += 1) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
if (arg === '--bin') {
|
|
25
|
+
const bin = args[i + 1];
|
|
26
|
+
if (!bin) {
|
|
27
|
+
throw new Error('Missing value for --bin');
|
|
28
|
+
}
|
|
29
|
+
normalized.push('--bin', bin);
|
|
30
|
+
i += 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (arg.startsWith('--bin=')) {
|
|
34
|
+
normalized.push(arg);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
throw new Error('`jacs mcp run` is stdio-only in haiai. ' +
|
|
38
|
+
'Only optional `--bin <path>` is allowed; transport/runtime overrides are blocked.');
|
|
39
|
+
}
|
|
40
|
+
return normalized;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Execute a JACS CLI command from library code.
|
|
44
|
+
*
|
|
45
|
+
* Example:
|
|
46
|
+
* runJacsCli(["verify", "./signed.json"])
|
|
47
|
+
*/
|
|
48
|
+
function runJacsCli(args, options = {}) {
|
|
49
|
+
const normalizedArgs = enforceMcpRunStdioArgs(args);
|
|
50
|
+
const binary = options.jacsBin?.trim() || resolveJacsCliBin(options.env ?? process.env);
|
|
51
|
+
const result = (0, node_child_process_1.spawnSync)(binary, normalizedArgs, {
|
|
52
|
+
cwd: options.cwd,
|
|
53
|
+
env: options.env,
|
|
54
|
+
stdio: options.stdio ?? 'pipe',
|
|
55
|
+
encoding: 'buffer',
|
|
56
|
+
});
|
|
57
|
+
if (result.error) {
|
|
58
|
+
const err = result.error;
|
|
59
|
+
if (err.code === 'ENOENT') {
|
|
60
|
+
throw new Error(`JACS CLI binary not found: ${binary}. Install jacs or set JACS_CLI_BIN.`);
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`Failed to execute JACS CLI '${binary}': ${err.message}`);
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=jacs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jacs.js","sourceRoot":"","sources":["../../src/jacs.ts"],"names":[],"mappings":";;AAaA,8CAGC;AAQD,wDA+BC;AAQD,gCAsBC;AArFD,2DAA+G;AAa/G,SAAgB,iBAAiB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACpE,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,IAAc;IACnD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC7C,CAAC;YACD,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC9B,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QAED,MAAM,IAAI,KAAK,CACb,yCAAyC;YACzC,mFAAmF,CACpF,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CACxB,IAAc,EACd,UAA6B,EAAE;IAE/B,MAAM,cAAc,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,iBAAiB,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,IAAA,8BAAS,EAAC,MAAM,EAAE,cAAc,EAAE;QAC/C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM;QAC9B,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,MAAM,CAAC,KAA8B,CAAC;QAClD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,qCAAqC,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/cjs/mime.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RFC 5322 MIME email construction.
|
|
4
|
+
*
|
|
5
|
+
* Builds standards-compliant email messages from structured fields.
|
|
6
|
+
* Zero external dependencies — uses only Node.js built-ins.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.buildRfc5322Email = buildRfc5322Email;
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
11
|
+
/**
|
|
12
|
+
* Strip `\r` and `\n` from a header value to prevent CRLF injection.
|
|
13
|
+
*/
|
|
14
|
+
function sanitizeHeader(value) {
|
|
15
|
+
return value.replace(/[\r\n"]/g, '');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build an RFC 5322 email from structured fields.
|
|
19
|
+
*
|
|
20
|
+
* Produces raw bytes with CRLF line endings suitable for JACS signing
|
|
21
|
+
* and parseable by standard email parsers.
|
|
22
|
+
*
|
|
23
|
+
* @param opts - Email options (to, subject, body, attachments, etc.)
|
|
24
|
+
* @param fromEmail - The sender's email address
|
|
25
|
+
* @returns Buffer containing the raw RFC 5322 email
|
|
26
|
+
*/
|
|
27
|
+
function buildRfc5322Email(opts, fromEmail) {
|
|
28
|
+
const safeTo = sanitizeHeader(opts.to);
|
|
29
|
+
const safeFrom = sanitizeHeader(fromEmail);
|
|
30
|
+
const safeSubject = sanitizeHeader(opts.subject);
|
|
31
|
+
const messageId = `<${(0, node_crypto_1.randomUUID)()}@hai.ai>`;
|
|
32
|
+
const date = new Date().toUTCString();
|
|
33
|
+
const attachments = opts.attachments ?? [];
|
|
34
|
+
if (attachments.length === 0) {
|
|
35
|
+
// Simple text/plain email
|
|
36
|
+
let email = '';
|
|
37
|
+
email += `From: <${safeFrom}>\r\n`;
|
|
38
|
+
email += `To: ${safeTo}\r\n`;
|
|
39
|
+
email += `Subject: ${safeSubject}\r\n`;
|
|
40
|
+
email += `Date: ${date}\r\n`;
|
|
41
|
+
email += `Message-ID: ${messageId}\r\n`;
|
|
42
|
+
if (opts.inReplyTo) {
|
|
43
|
+
const safeReply = sanitizeHeader(opts.inReplyTo);
|
|
44
|
+
email += `In-Reply-To: ${safeReply}\r\n`;
|
|
45
|
+
email += `References: ${safeReply}\r\n`;
|
|
46
|
+
}
|
|
47
|
+
email += 'MIME-Version: 1.0\r\n';
|
|
48
|
+
email += 'Content-Type: text/plain; charset=utf-8\r\n';
|
|
49
|
+
email += 'Content-Transfer-Encoding: 8bit\r\n';
|
|
50
|
+
email += '\r\n'; // end of headers
|
|
51
|
+
email += opts.body;
|
|
52
|
+
email += '\r\n';
|
|
53
|
+
return Buffer.from(email, 'utf-8');
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// multipart/mixed with text body + attachments
|
|
57
|
+
const boundary = `hai-boundary-${(0, node_crypto_1.randomUUID)().replace(/-/g, '')}`;
|
|
58
|
+
let email = '';
|
|
59
|
+
email += `From: <${safeFrom}>\r\n`;
|
|
60
|
+
email += `To: ${safeTo}\r\n`;
|
|
61
|
+
email += `Subject: ${safeSubject}\r\n`;
|
|
62
|
+
email += `Date: ${date}\r\n`;
|
|
63
|
+
email += `Message-ID: ${messageId}\r\n`;
|
|
64
|
+
if (opts.inReplyTo) {
|
|
65
|
+
const safeReply = sanitizeHeader(opts.inReplyTo);
|
|
66
|
+
email += `In-Reply-To: ${safeReply}\r\n`;
|
|
67
|
+
email += `References: ${safeReply}\r\n`;
|
|
68
|
+
}
|
|
69
|
+
email += 'MIME-Version: 1.0\r\n';
|
|
70
|
+
email += `Content-Type: multipart/mixed; boundary="${boundary}"\r\n`;
|
|
71
|
+
email += '\r\n'; // end of headers
|
|
72
|
+
// Body part
|
|
73
|
+
email += `--${boundary}\r\n`;
|
|
74
|
+
email += 'Content-Type: text/plain; charset=utf-8\r\n';
|
|
75
|
+
email += 'Content-Transfer-Encoding: 8bit\r\n';
|
|
76
|
+
email += '\r\n';
|
|
77
|
+
email += opts.body;
|
|
78
|
+
email += '\r\n';
|
|
79
|
+
// Attachment parts
|
|
80
|
+
for (const att of attachments) {
|
|
81
|
+
const safeFilename = sanitizeHeader(att.filename);
|
|
82
|
+
const safeContentType = sanitizeHeader(att.contentType);
|
|
83
|
+
const b64 = att.data.toString('base64');
|
|
84
|
+
email += `--${boundary}\r\n`;
|
|
85
|
+
email += `Content-Type: ${safeContentType}; name="${safeFilename}"\r\n`;
|
|
86
|
+
email += `Content-Disposition: attachment; filename="${safeFilename}"\r\n`;
|
|
87
|
+
email += 'Content-Transfer-Encoding: base64\r\n';
|
|
88
|
+
email += '\r\n';
|
|
89
|
+
// Write base64 in 76-char lines (RFC 2045)
|
|
90
|
+
for (let i = 0; i < b64.length; i += 76) {
|
|
91
|
+
email += b64.slice(i, i + 76);
|
|
92
|
+
email += '\r\n';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Closing boundary
|
|
96
|
+
email += `--${boundary}--\r\n`;
|
|
97
|
+
return Buffer.from(email, 'utf-8');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=mime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../../src/mime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getServerKeys = getServerKeys;
|
|
4
|
+
exports.clearServerKeysCache = clearServerKeysCache;
|
|
5
|
+
exports.canonicalJson = canonicalJson;
|
|
6
|
+
exports.unwrapSignedEvent = unwrapSignedEvent;
|
|
7
|
+
exports.signResponse = signResponse;
|
|
8
|
+
const node_crypto_1 = require("node:crypto");
|
|
9
|
+
const jacs_1 = require("@hai.ai/jacs");
|
|
10
|
+
// Cache for server public keys
|
|
11
|
+
let serverKeysCache = {};
|
|
12
|
+
let cacheExpiry = 0;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch the server's public signing keys from the well-known endpoint.
|
|
15
|
+
* Results are cached for 1 hour.
|
|
16
|
+
*/
|
|
17
|
+
async function getServerKeys(baseUrl) {
|
|
18
|
+
if (Date.now() < cacheExpiry && Object.keys(serverKeysCache).length > 0) {
|
|
19
|
+
return serverKeysCache;
|
|
20
|
+
}
|
|
21
|
+
const resp = await fetch(`${baseUrl.replace(/\/+$/, '')}/.well-known/hai-keys.json`);
|
|
22
|
+
if (!resp.ok) {
|
|
23
|
+
throw new Error(`Failed to fetch server keys (${resp.status})`);
|
|
24
|
+
}
|
|
25
|
+
const data = (await resp.json());
|
|
26
|
+
serverKeysCache = {};
|
|
27
|
+
for (const key of data.keys ?? []) {
|
|
28
|
+
serverKeysCache[key.key_id] = key.public_key;
|
|
29
|
+
}
|
|
30
|
+
cacheExpiry = Date.now() + 3_600_000; // 1 hour
|
|
31
|
+
return serverKeysCache;
|
|
32
|
+
}
|
|
33
|
+
/** Reset the server keys cache (useful for testing). */
|
|
34
|
+
function clearServerKeysCache() {
|
|
35
|
+
serverKeysCache = {};
|
|
36
|
+
cacheExpiry = 0;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Produce canonical JSON per RFC 8785 (JCS).
|
|
40
|
+
*
|
|
41
|
+
* Delegates to JACS binding-core `canonicalizeJsonSync` when an agent is
|
|
42
|
+
* provided. Falls back to local sorted-key JSON.stringify for environments
|
|
43
|
+
* where the JACS native module is not loaded.
|
|
44
|
+
*/
|
|
45
|
+
function canonicalJson(obj, agent) {
|
|
46
|
+
if (agent && 'canonicalizeJsonSync' in agent && typeof agent.canonicalizeJsonSync === 'function') {
|
|
47
|
+
try {
|
|
48
|
+
const jsonStr = canonicalJsonLocal(obj);
|
|
49
|
+
return agent.canonicalizeJsonSync(jsonStr);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Fall through to local implementation
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return canonicalJsonLocal(obj);
|
|
56
|
+
}
|
|
57
|
+
/** Local sorted-key JSON canonicalization (fallback). */
|
|
58
|
+
function canonicalJsonLocal(obj) {
|
|
59
|
+
return JSON.stringify(obj, (_key, value) => {
|
|
60
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
61
|
+
const sorted = {};
|
|
62
|
+
for (const k of Object.keys(value).sort()) {
|
|
63
|
+
sorted[k] = value[k];
|
|
64
|
+
}
|
|
65
|
+
return sorted;
|
|
66
|
+
}
|
|
67
|
+
return value;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Unwrap a JACS-signed event, verifying the signature via JACS if server keys
|
|
72
|
+
* are provided.
|
|
73
|
+
*
|
|
74
|
+
* Delegates to JACS binding-core `unwrapSignedEventSync` when the agent
|
|
75
|
+
* supports it. Falls back to local unwrap + verification otherwise.
|
|
76
|
+
*
|
|
77
|
+
* Supports both the canonical format (version/document_type/data/metadata/jacsSignature)
|
|
78
|
+
* and the legacy format (payload/metadata/signature). If the event is not a
|
|
79
|
+
* JacsDocument, it is returned as-is.
|
|
80
|
+
*
|
|
81
|
+
* Throws if a known key fails verification (signature mismatch).
|
|
82
|
+
*/
|
|
83
|
+
function unwrapSignedEvent(eventData, serverPublicKeys, agent) {
|
|
84
|
+
// Try JACS binding-core delegation first
|
|
85
|
+
if (agent && 'unwrapSignedEventSync' in agent && typeof agent.unwrapSignedEventSync === 'function') {
|
|
86
|
+
try {
|
|
87
|
+
const eventJson = JSON.stringify(eventData);
|
|
88
|
+
const serverKeysJson = JSON.stringify({
|
|
89
|
+
keys: Object.entries(serverPublicKeys).map(([keyId, publicKey]) => ({
|
|
90
|
+
key_id: keyId,
|
|
91
|
+
public_key: publicKey,
|
|
92
|
+
})),
|
|
93
|
+
});
|
|
94
|
+
const resultJson = agent.unwrapSignedEventSync(eventJson, serverKeysJson);
|
|
95
|
+
const result = JSON.parse(resultJson);
|
|
96
|
+
return result.data ?? eventData;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Fall through to local implementation
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Fallback: local unwrap with JACS verify for signature checks
|
|
103
|
+
// Canonical JacsDocument format: {version, document_type, data, metadata, jacsSignature}
|
|
104
|
+
if (eventData.jacsSignature && eventData.metadata && eventData.data !== undefined) {
|
|
105
|
+
const doc = eventData;
|
|
106
|
+
const agentID = doc.jacsSignature.agentID;
|
|
107
|
+
const publicKeyPem = serverPublicKeys[agentID];
|
|
108
|
+
if (publicKeyPem) {
|
|
109
|
+
const signedContent = canonicalJson(doc.data, agent);
|
|
110
|
+
let valid = false;
|
|
111
|
+
if (agent) {
|
|
112
|
+
valid = agent.verifyStringSync(signedContent, doc.jacsSignature.signature, Buffer.from(publicKeyPem, 'utf-8'), 'pem');
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const standaloneResult = (0, jacs_1.verifyDocumentStandalone)(JSON.stringify(eventData));
|
|
116
|
+
valid = standaloneResult.valid;
|
|
117
|
+
}
|
|
118
|
+
if (!valid) {
|
|
119
|
+
throw new Error(`JACS signature verification failed for agentID="${agentID}"`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return doc.data;
|
|
123
|
+
}
|
|
124
|
+
// Legacy format: {payload, metadata, signature}
|
|
125
|
+
if (eventData.metadata && eventData.signature) {
|
|
126
|
+
const payload = eventData.payload;
|
|
127
|
+
const sig = eventData.signature;
|
|
128
|
+
const keyId = sig.key_id || '';
|
|
129
|
+
const publicKeyPem = serverPublicKeys[keyId];
|
|
130
|
+
if (publicKeyPem) {
|
|
131
|
+
const signedContent = canonicalJson({
|
|
132
|
+
metadata: eventData.metadata,
|
|
133
|
+
payload: eventData.payload,
|
|
134
|
+
}, agent);
|
|
135
|
+
let valid = false;
|
|
136
|
+
if (agent) {
|
|
137
|
+
valid = agent.verifyStringSync(signedContent, sig.signature || '', Buffer.from(publicKeyPem, 'utf-8'), 'pem');
|
|
138
|
+
}
|
|
139
|
+
if (!valid) {
|
|
140
|
+
throw new Error(`JACS signature verification failed for key_id="${keyId}"`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return payload;
|
|
144
|
+
}
|
|
145
|
+
// Not a JacsDocument -- return unchanged
|
|
146
|
+
return eventData;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Sign a job response as a JACS document via JACS core.
|
|
150
|
+
*
|
|
151
|
+
* Delegates envelope construction to JACS binding-core when the agent
|
|
152
|
+
* exposes `signResponseSync`. Falls back to local construction for agents
|
|
153
|
+
* that only provide `signStringSync` (e.g. test mocks).
|
|
154
|
+
*/
|
|
155
|
+
function signResponse(jobResponse, agent, jacsId) {
|
|
156
|
+
// Prefer JACS binding delegation (JACS canonicalizes internally via RFC 8785)
|
|
157
|
+
if ('signResponseSync' in agent && typeof agent.signResponseSync === 'function') {
|
|
158
|
+
const rawJson = JSON.stringify(jobResponse);
|
|
159
|
+
const resultJson = agent.signResponseSync(rawJson);
|
|
160
|
+
return { signed_document: resultJson, agent_jacs_id: jacsId };
|
|
161
|
+
}
|
|
162
|
+
// Fallback for agents without signResponseSync
|
|
163
|
+
const canonicalPayload = canonicalJson(jobResponse, agent);
|
|
164
|
+
const now = new Date().toISOString();
|
|
165
|
+
const documentId = (0, node_crypto_1.randomUUID)();
|
|
166
|
+
const hash = (0, jacs_1.hashString)(canonicalPayload);
|
|
167
|
+
const sortedData = JSON.parse(canonicalPayload);
|
|
168
|
+
const signature = agent.signStringSync(canonicalPayload);
|
|
169
|
+
const jacsDoc = {
|
|
170
|
+
version: '1.0.0',
|
|
171
|
+
document_type: 'job_response',
|
|
172
|
+
data: sortedData,
|
|
173
|
+
metadata: {
|
|
174
|
+
issuer: jacsId,
|
|
175
|
+
document_id: documentId,
|
|
176
|
+
created_at: now,
|
|
177
|
+
hash,
|
|
178
|
+
},
|
|
179
|
+
jacsSignature: {
|
|
180
|
+
agentID: jacsId,
|
|
181
|
+
date: now,
|
|
182
|
+
signature,
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
return {
|
|
186
|
+
signed_document: JSON.stringify(jacsDoc),
|
|
187
|
+
agent_jacs_id: jacsId,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=signing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.js","sourceRoot":"","sources":["../../src/signing.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/sse.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSseStream = parseSseStream;
|
|
4
|
+
/**
|
|
5
|
+
* Parse an SSE stream (ReadableStream<Uint8Array>) into an async generator of HaiEvents.
|
|
6
|
+
*
|
|
7
|
+
* Implements the SSE protocol: events are delimited by blank lines,
|
|
8
|
+
* fields are "event:", "data:", and "id:".
|
|
9
|
+
*/
|
|
10
|
+
async function* parseSseStream(body) {
|
|
11
|
+
const reader = body.getReader();
|
|
12
|
+
const decoder = new TextDecoder();
|
|
13
|
+
let buffer = '';
|
|
14
|
+
let fields = { event: '', data: '', id: undefined };
|
|
15
|
+
try {
|
|
16
|
+
while (true) {
|
|
17
|
+
const { done, value } = await reader.read();
|
|
18
|
+
if (done)
|
|
19
|
+
break;
|
|
20
|
+
buffer += decoder.decode(value, { stream: true });
|
|
21
|
+
const lines = buffer.split('\n');
|
|
22
|
+
buffer = lines.pop() ?? '';
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
if (line.startsWith('event:')) {
|
|
25
|
+
fields.event = line.slice(6).trim();
|
|
26
|
+
}
|
|
27
|
+
else if (line.startsWith('data:')) {
|
|
28
|
+
fields.data += (fields.data ? '\n' : '') + line.slice(5).trim();
|
|
29
|
+
}
|
|
30
|
+
else if (line.startsWith('id:')) {
|
|
31
|
+
fields.id = line.slice(3).trim();
|
|
32
|
+
}
|
|
33
|
+
else if (line === '' || line === '\r') {
|
|
34
|
+
// Blank line = end of event
|
|
35
|
+
if (fields.data) {
|
|
36
|
+
const event = buildEvent(fields);
|
|
37
|
+
if (event)
|
|
38
|
+
yield event;
|
|
39
|
+
}
|
|
40
|
+
fields = { event: '', data: '', id: undefined };
|
|
41
|
+
}
|
|
42
|
+
// Lines starting with ':' are comments, ignored
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Flush any remaining event
|
|
46
|
+
if (fields.data) {
|
|
47
|
+
const event = buildEvent(fields);
|
|
48
|
+
if (event)
|
|
49
|
+
yield event;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
reader.releaseLock();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function buildEvent(fields) {
|
|
57
|
+
if (!fields.event && !fields.data)
|
|
58
|
+
return null;
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(fields.data);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
parsed = fields.data;
|
|
65
|
+
}
|
|
66
|
+
const eventType = fields.event || (typeof parsed === 'object' && parsed !== null
|
|
67
|
+
? parsed.type || 'message'
|
|
68
|
+
: 'message');
|
|
69
|
+
return {
|
|
70
|
+
eventType,
|
|
71
|
+
data: parsed,
|
|
72
|
+
id: fields.id,
|
|
73
|
+
raw: fields.data,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=sse.js.map
|