@hai.ai/jacs 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/koa.js ADDED
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * JACS Koa Middleware
4
+ *
5
+ * Factory-based middleware for Koa that verifies incoming JACS-signed
6
+ * request bodies and optionally auto-signs JSON responses.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import Koa from 'koa';
11
+ * import bodyParser from 'koa-bodyparser';
12
+ * import { JacsClient } from './client';
13
+ * import { jacsKoaMiddleware } from './koa';
14
+ *
15
+ * const client = await JacsClient.quickstart();
16
+ * const app = new Koa();
17
+ * app.use(bodyParser({ enableTypes: ['text'] }));
18
+ * app.use(jacsKoaMiddleware({ client, verify: true }));
19
+ *
20
+ * app.use(async (ctx) => {
21
+ * console.log(ctx.state.jacsPayload); // verified payload
22
+ * ctx.body = { status: 'ok' };
23
+ * });
24
+ * ```
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.jacsKoaMiddleware = jacsKoaMiddleware;
28
+ // =============================================================================
29
+ // Internal helpers
30
+ // =============================================================================
31
+ const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
32
+ async function resolveClient(options) {
33
+ if (options.client) {
34
+ return options.client;
35
+ }
36
+ const { JacsClient: ClientCtor } = await import('./client.js');
37
+ if (options.configPath) {
38
+ const client = new ClientCtor();
39
+ await client.load(options.configPath);
40
+ return client;
41
+ }
42
+ return ClientCtor.quickstart();
43
+ }
44
+ // =============================================================================
45
+ // Middleware factory
46
+ // =============================================================================
47
+ /**
48
+ * Create JACS Koa middleware.
49
+ *
50
+ * Attaches `ctx.state.jacsClient` on every request.
51
+ * When `verify` is true (default), POST/PUT/PATCH bodies are verified and
52
+ * extracted payload is set on `ctx.state.jacsPayload`.
53
+ * When `sign` is true, `ctx.body` is auto-signed after downstream middleware runs.
54
+ */
55
+ function jacsKoaMiddleware(options = {}) {
56
+ const shouldVerify = options.verify !== false;
57
+ const shouldSign = options.sign === true;
58
+ const isOptional = options.optional === true;
59
+ let clientPromise = null;
60
+ function getClient() {
61
+ if (!clientPromise) {
62
+ clientPromise = resolveClient(options);
63
+ }
64
+ return clientPromise;
65
+ }
66
+ if (options.client) {
67
+ clientPromise = Promise.resolve(options.client);
68
+ }
69
+ return async function jacsKoaMiddlewareHandler(ctx, next) {
70
+ let client;
71
+ try {
72
+ client = await getClient();
73
+ }
74
+ catch {
75
+ ctx.status = 500;
76
+ ctx.body = { error: 'JACS initialization failed' };
77
+ return;
78
+ }
79
+ // Expose client on context state for manual use in route handlers.
80
+ ctx.state.jacsClient = client;
81
+ // ----- Verify incoming body -----
82
+ if (shouldVerify && BODY_METHODS.has(ctx.method)) {
83
+ // koa-bodyparser puts parsed body on ctx.request.body
84
+ const rawBody = typeof ctx.request.body === 'string'
85
+ ? ctx.request.body
86
+ : typeof ctx.body === 'string' && ctx.method !== 'GET'
87
+ ? ctx.body
88
+ : null;
89
+ if (rawBody) {
90
+ try {
91
+ const result = await client.verify(rawBody);
92
+ if (result.valid) {
93
+ ctx.state.jacsPayload = result.data;
94
+ }
95
+ else if (!isOptional) {
96
+ ctx.status = 401;
97
+ ctx.body = { error: 'JACS verification failed', details: result.errors };
98
+ return;
99
+ }
100
+ }
101
+ catch (err) {
102
+ if (!isOptional) {
103
+ ctx.status = 401;
104
+ ctx.body = { error: 'JACS verification failed', details: [String(err)] };
105
+ return;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ await next();
111
+ // ----- Auto-sign response -----
112
+ if (shouldSign && ctx.body && typeof ctx.body === 'object' && !Buffer.isBuffer(ctx.body)) {
113
+ try {
114
+ const signed = await client.signMessage(ctx.body);
115
+ ctx.body = signed.raw;
116
+ ctx.type = 'application/json';
117
+ }
118
+ catch {
119
+ // Signing failed — leave the original body intact.
120
+ }
121
+ }
122
+ };
123
+ }
124
+ //# sourceMappingURL=koa.js.map
package/koa.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"koa.js","sourceRoot":"","sources":["koa.ts"],"names":[],"mappings":"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"}
package/langchain.d.ts ADDED
@@ -0,0 +1,97 @@
1
+ /**
2
+ * JACS LangChain.js Adapter
3
+ *
4
+ * Provides full JACS capabilities for LangChain.js agents: cryptographic
5
+ * signing, verification, multi-party agreements, trust store, and audit.
6
+ * All `@langchain/core` and `@langchain/langgraph` imports are lazy so this
7
+ * module can be imported without those packages installed.
8
+ *
9
+ * Two integration patterns:
10
+ *
11
+ * **A. Full JACS toolkit** — give your LangChain agent access to all JACS
12
+ * operations (sign, verify, agreements, trust, audit):
13
+ *
14
+ * `createJacsTools(options)` -- Returns an array of LangChain tools that
15
+ * wrap the full JacsClient API. Bind these to your agent/LLM so it can
16
+ * call JACS operations as part of its reasoning.
17
+ *
18
+ * **B. Auto-signing wrappers** — transparently sign tool outputs:
19
+ *
20
+ * `signedTool(tool, options)` -- Wraps a BaseTool to auto-sign output.
21
+ * `jacsToolNode(tools, options)` -- ToolNode with auto-signed tools.
22
+ * `jacsWrapToolCall(options)` -- Manual tool execution with signing.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { JacsClient } from '@hai.ai/jacs/client';
27
+ * import { createJacsTools, signedTool } from '@hai.ai/jacs/langchain';
28
+ *
29
+ * const client = await JacsClient.quickstart();
30
+ *
31
+ * // Full toolkit — agent can sign, verify, create agreements, etc.
32
+ * const jacsTools = createJacsTools({ client });
33
+ * const allTools = [...myTools, ...jacsTools];
34
+ *
35
+ * // Or just wrap existing tools for auto-signing
36
+ * const signed = signedTool(myTool, { client });
37
+ * ```
38
+ */
39
+ import type { JacsClient } from './client.js';
40
+ export interface JacsToolOptions {
41
+ /** An initialized JacsClient instance. */
42
+ client: JacsClient;
43
+ /** Throw on signing failure instead of logging and passing through. Default: false. */
44
+ strict?: boolean;
45
+ }
46
+ /**
47
+ * Wrap a LangChain BaseTool so its output is automatically signed with JACS.
48
+ *
49
+ * Returns a new `DynamicStructuredTool` that delegates to the original tool
50
+ * and signs the result before returning it.
51
+ *
52
+ * @param tool - A LangChain `BaseTool` instance (or any object with
53
+ * `name`, `description`, `schema`, and `invoke`).
54
+ * @param options - JACS signing options.
55
+ * @returns A new `DynamicStructuredTool` with signed output.
56
+ */
57
+ export declare function signedTool(tool: any, options: JacsToolOptions): any;
58
+ /**
59
+ * Create an async function that executes a tool call and signs the result.
60
+ *
61
+ * The returned function has the signature
62
+ * `(toolCall, runnable) => Promise<ToolMessage>` and can be used in custom
63
+ * LangGraph workflows where you control tool execution.
64
+ *
65
+ * @param options - JACS signing options.
66
+ * @returns An async wrapper function.
67
+ */
68
+ export declare function jacsWrapToolCall(options: JacsToolOptions): (toolCall: any, runnable: any) => Promise<any>;
69
+ /**
70
+ * Create a LangGraph `ToolNode` where every tool's output is signed with JACS.
71
+ *
72
+ * Since the JavaScript `ToolNode` does not support a `wrap_tool_call`
73
+ * parameter (unlike the Python version), this function wraps each tool
74
+ * individually with {@link signedTool} before passing them to `ToolNode`.
75
+ *
76
+ * @param tools - Array of LangChain tools.
77
+ * @param options - JACS signing options.
78
+ * @returns A `ToolNode` instance with all tools auto-signing their output.
79
+ */
80
+ export declare function jacsToolNode(tools: any[], options: JacsToolOptions): any;
81
+ /**
82
+ * Create an array of LangChain tools that expose the full JACS API.
83
+ *
84
+ * Returns `DynamicStructuredTool` instances for: signing, verification,
85
+ * multi-party agreements, trust store operations, and audit. Bind these
86
+ * to your LangChain agent so it can call JACS operations directly.
87
+ *
88
+ * @param options - JACS tool options (client required).
89
+ * @returns Array of LangChain `DynamicStructuredTool` instances.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * const tools = createJacsTools({ client });
94
+ * const llm = model.bindTools(tools);
95
+ * ```
96
+ */
97
+ export declare function createJacsTools(options: JacsToolOptions): any[];
package/langchain.js ADDED
@@ -0,0 +1,439 @@
1
+ "use strict";
2
+ /**
3
+ * JACS LangChain.js Adapter
4
+ *
5
+ * Provides full JACS capabilities for LangChain.js agents: cryptographic
6
+ * signing, verification, multi-party agreements, trust store, and audit.
7
+ * All `@langchain/core` and `@langchain/langgraph` imports are lazy so this
8
+ * module can be imported without those packages installed.
9
+ *
10
+ * Two integration patterns:
11
+ *
12
+ * **A. Full JACS toolkit** — give your LangChain agent access to all JACS
13
+ * operations (sign, verify, agreements, trust, audit):
14
+ *
15
+ * `createJacsTools(options)` -- Returns an array of LangChain tools that
16
+ * wrap the full JacsClient API. Bind these to your agent/LLM so it can
17
+ * call JACS operations as part of its reasoning.
18
+ *
19
+ * **B. Auto-signing wrappers** — transparently sign tool outputs:
20
+ *
21
+ * `signedTool(tool, options)` -- Wraps a BaseTool to auto-sign output.
22
+ * `jacsToolNode(tools, options)` -- ToolNode with auto-signed tools.
23
+ * `jacsWrapToolCall(options)` -- Manual tool execution with signing.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import { JacsClient } from '@hai.ai/jacs/client';
28
+ * import { createJacsTools, signedTool } from '@hai.ai/jacs/langchain';
29
+ *
30
+ * const client = await JacsClient.quickstart();
31
+ *
32
+ * // Full toolkit — agent can sign, verify, create agreements, etc.
33
+ * const jacsTools = createJacsTools({ client });
34
+ * const allTools = [...myTools, ...jacsTools];
35
+ *
36
+ * // Or just wrap existing tools for auto-signing
37
+ * const signed = signedTool(myTool, { client });
38
+ * ```
39
+ */
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.signedTool = signedTool;
42
+ exports.jacsWrapToolCall = jacsWrapToolCall;
43
+ exports.jacsToolNode = jacsToolNode;
44
+ exports.createJacsTools = createJacsTools;
45
+ // =============================================================================
46
+ // signedTool -- wrap a BaseTool to auto-sign its output
47
+ // =============================================================================
48
+ /**
49
+ * Wrap a LangChain BaseTool so its output is automatically signed with JACS.
50
+ *
51
+ * Returns a new `DynamicStructuredTool` that delegates to the original tool
52
+ * and signs the result before returning it.
53
+ *
54
+ * @param tool - A LangChain `BaseTool` instance (or any object with
55
+ * `name`, `description`, `schema`, and `invoke`).
56
+ * @param options - JACS signing options.
57
+ * @returns A new `DynamicStructuredTool` with signed output.
58
+ */
59
+ function signedTool(tool, options) {
60
+ let DynamicStructuredTool;
61
+ try {
62
+ DynamicStructuredTool = require('@langchain/core/tools').DynamicStructuredTool;
63
+ }
64
+ catch {
65
+ throw new Error("@langchain/core is required for signedTool. " +
66
+ "Install it with: npm install @langchain/core");
67
+ }
68
+ const originalName = tool.name || 'jacs_tool';
69
+ const originalDescription = tool.description || '';
70
+ const originalSchema = tool.schema;
71
+ const wrapped = new DynamicStructuredTool({
72
+ name: originalName,
73
+ description: originalDescription,
74
+ schema: originalSchema,
75
+ func: async (input) => {
76
+ const result = await tool.invoke(input);
77
+ const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
78
+ try {
79
+ const signed = await options.client.signMessage({
80
+ tool: originalName,
81
+ result: resultStr,
82
+ });
83
+ return signed.raw;
84
+ }
85
+ catch (err) {
86
+ if (options.strict)
87
+ throw err;
88
+ console.error('[jacs/langchain] signing failed:', err);
89
+ return resultStr;
90
+ }
91
+ },
92
+ });
93
+ // Stash a reference to the original tool for introspection.
94
+ wrapped._innerTool = tool;
95
+ return wrapped;
96
+ }
97
+ // =============================================================================
98
+ // jacsWrapToolCall -- returns an async wrapper for manual tool execution
99
+ // =============================================================================
100
+ /**
101
+ * Create an async function that executes a tool call and signs the result.
102
+ *
103
+ * The returned function has the signature
104
+ * `(toolCall, runnable) => Promise<ToolMessage>` and can be used in custom
105
+ * LangGraph workflows where you control tool execution.
106
+ *
107
+ * @param options - JACS signing options.
108
+ * @returns An async wrapper function.
109
+ */
110
+ function jacsWrapToolCall(options) {
111
+ return async (toolCall, runnable) => {
112
+ const result = await runnable.invoke(toolCall);
113
+ // result is expected to be a ToolMessage (has .content, .tool_call_id, .name)
114
+ if (!result || typeof result.content === 'undefined') {
115
+ return result;
116
+ }
117
+ const contentStr = typeof result.content === 'string'
118
+ ? result.content
119
+ : JSON.stringify(result.content);
120
+ try {
121
+ const signed = await options.client.signMessage({
122
+ tool: toolCall.name || result.name || 'unknown',
123
+ content: contentStr,
124
+ });
125
+ let ToolMessage;
126
+ try {
127
+ ToolMessage = require('@langchain/core/messages').ToolMessage;
128
+ }
129
+ catch {
130
+ // If ToolMessage is not available, mutate in place as fallback.
131
+ result.content = signed.raw;
132
+ return result;
133
+ }
134
+ return new ToolMessage({
135
+ content: signed.raw,
136
+ tool_call_id: result.tool_call_id || '',
137
+ name: result.name,
138
+ });
139
+ }
140
+ catch (err) {
141
+ if (options.strict)
142
+ throw err;
143
+ console.error('[jacs/langchain] signing failed:', err);
144
+ return result;
145
+ }
146
+ };
147
+ }
148
+ // =============================================================================
149
+ // jacsToolNode -- convenience ToolNode with signed tools
150
+ // =============================================================================
151
+ /**
152
+ * Create a LangGraph `ToolNode` where every tool's output is signed with JACS.
153
+ *
154
+ * Since the JavaScript `ToolNode` does not support a `wrap_tool_call`
155
+ * parameter (unlike the Python version), this function wraps each tool
156
+ * individually with {@link signedTool} before passing them to `ToolNode`.
157
+ *
158
+ * @param tools - Array of LangChain tools.
159
+ * @param options - JACS signing options.
160
+ * @returns A `ToolNode` instance with all tools auto-signing their output.
161
+ */
162
+ function jacsToolNode(tools, options) {
163
+ let ToolNode;
164
+ try {
165
+ ToolNode = require('@langchain/langgraph/prebuilt').ToolNode;
166
+ }
167
+ catch {
168
+ throw new Error("@langchain/langgraph is required for jacsToolNode. " +
169
+ "Install it with: npm install @langchain/langgraph");
170
+ }
171
+ const wrappedTools = tools.map((t) => signedTool(t, options));
172
+ return new ToolNode({
173
+ tools: wrappedTools,
174
+ handleToolErrors: true,
175
+ });
176
+ }
177
+ // =============================================================================
178
+ // createJacsTools -- full JACS toolkit as LangChain tools
179
+ // =============================================================================
180
+ /**
181
+ * Create an array of LangChain tools that expose the full JACS API.
182
+ *
183
+ * Returns `DynamicStructuredTool` instances for: signing, verification,
184
+ * multi-party agreements, trust store operations, and audit. Bind these
185
+ * to your LangChain agent so it can call JACS operations directly.
186
+ *
187
+ * @param options - JACS tool options (client required).
188
+ * @returns Array of LangChain `DynamicStructuredTool` instances.
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * const tools = createJacsTools({ client });
193
+ * const llm = model.bindTools(tools);
194
+ * ```
195
+ */
196
+ function createJacsTools(options) {
197
+ let DynamicStructuredTool;
198
+ let z;
199
+ try {
200
+ DynamicStructuredTool = require('@langchain/core/tools').DynamicStructuredTool;
201
+ z = require('zod');
202
+ }
203
+ catch {
204
+ throw new Error("@langchain/core is required for createJacsTools. " +
205
+ "Install it with: npm install @langchain/core");
206
+ }
207
+ const { client, strict } = options;
208
+ function handleError(err, fallback) {
209
+ if (strict)
210
+ throw err;
211
+ return JSON.stringify({ error: String(err), fallback });
212
+ }
213
+ return [
214
+ // ----- Sign -----
215
+ new DynamicStructuredTool({
216
+ name: 'jacs_sign',
217
+ description: 'Sign arbitrary JSON data with JACS cryptographic provenance. ' +
218
+ 'Returns a signed document with documentId, agentId, and timestamp.',
219
+ schema: z.object({
220
+ data: z.string().describe('JSON string of the data to sign'),
221
+ }),
222
+ func: async ({ data }) => {
223
+ try {
224
+ const parsed = JSON.parse(data);
225
+ const signed = await client.signMessage(parsed);
226
+ return JSON.stringify({
227
+ documentId: signed.documentId,
228
+ agentId: signed.agentId,
229
+ timestamp: signed.timestamp,
230
+ raw: signed.raw,
231
+ });
232
+ }
233
+ catch (err) {
234
+ return handleError(err, 'signing failed');
235
+ }
236
+ },
237
+ }),
238
+ // ----- Verify -----
239
+ new DynamicStructuredTool({
240
+ name: 'jacs_verify',
241
+ description: 'Verify a JACS-signed document. Returns whether the signature is valid, ' +
242
+ 'the signer ID, timestamp, and any verification errors.',
243
+ schema: z.object({
244
+ document: z.string().describe('The full signed JSON document string to verify'),
245
+ }),
246
+ func: async ({ document }) => {
247
+ try {
248
+ const result = await client.verify(document);
249
+ return JSON.stringify({
250
+ valid: result.valid,
251
+ signerId: result.signerId,
252
+ timestamp: result.timestamp,
253
+ data: result.data,
254
+ errors: result.errors,
255
+ });
256
+ }
257
+ catch (err) {
258
+ return handleError(err, 'verification failed');
259
+ }
260
+ },
261
+ }),
262
+ // ----- Create Agreement -----
263
+ new DynamicStructuredTool({
264
+ name: 'jacs_create_agreement',
265
+ description: 'Create a multi-party agreement that requires signatures from specified agents. ' +
266
+ 'Supports optional timeout (ISO 8601), quorum (M-of-N), and algorithm constraints.',
267
+ schema: z.object({
268
+ document: z.string().describe('JSON string of the document to agree on'),
269
+ agentIds: z.array(z.string()).describe('Array of agent IDs who must sign'),
270
+ question: z.string().optional().describe('Question or prompt for signers'),
271
+ timeout: z.string().optional().describe('ISO 8601 deadline for signatures'),
272
+ quorum: z.number().optional().describe('Minimum number of signatures required (M-of-N)'),
273
+ }),
274
+ func: async (input) => {
275
+ try {
276
+ const parsed = JSON.parse(input.document);
277
+ const agreementOpts = {};
278
+ if (input.question)
279
+ agreementOpts.question = input.question;
280
+ if (input.timeout)
281
+ agreementOpts.timeout = input.timeout;
282
+ if (input.quorum !== undefined)
283
+ agreementOpts.quorum = input.quorum;
284
+ const signed = await client.createAgreement(parsed, input.agentIds, agreementOpts);
285
+ return JSON.stringify({
286
+ documentId: signed.documentId,
287
+ agentId: signed.agentId,
288
+ timestamp: signed.timestamp,
289
+ raw: signed.raw,
290
+ });
291
+ }
292
+ catch (err) {
293
+ return handleError(err, 'create agreement failed');
294
+ }
295
+ },
296
+ }),
297
+ // ----- Sign Agreement -----
298
+ new DynamicStructuredTool({
299
+ name: 'jacs_sign_agreement',
300
+ description: 'Sign an existing multi-party agreement. Pass the full agreement document.',
301
+ schema: z.object({
302
+ document: z.string().describe('The full agreement JSON document to sign'),
303
+ }),
304
+ func: async ({ document }) => {
305
+ try {
306
+ const signed = await client.signAgreement(document);
307
+ return JSON.stringify({
308
+ documentId: signed.documentId,
309
+ agentId: signed.agentId,
310
+ timestamp: signed.timestamp,
311
+ raw: signed.raw,
312
+ });
313
+ }
314
+ catch (err) {
315
+ return handleError(err, 'sign agreement failed');
316
+ }
317
+ },
318
+ }),
319
+ // ----- Check Agreement -----
320
+ new DynamicStructuredTool({
321
+ name: 'jacs_check_agreement',
322
+ description: 'Check the status of a multi-party agreement: how many signatures collected, ' +
323
+ 'whether it is complete, and who has signed.',
324
+ schema: z.object({
325
+ document: z.string().describe('The full agreement JSON document to check'),
326
+ }),
327
+ func: async ({ document }) => {
328
+ try {
329
+ const status = await client.checkAgreement(document);
330
+ return JSON.stringify(status);
331
+ }
332
+ catch (err) {
333
+ return handleError(err, 'check agreement failed');
334
+ }
335
+ },
336
+ }),
337
+ // ----- Verify Self -----
338
+ new DynamicStructuredTool({
339
+ name: 'jacs_verify_self',
340
+ description: "Verify this agent's own cryptographic integrity. Returns valid/invalid status.",
341
+ schema: z.object({}),
342
+ func: async () => {
343
+ try {
344
+ const result = await client.verifySelf();
345
+ return JSON.stringify({
346
+ valid: result.valid,
347
+ signerId: result.signerId,
348
+ errors: result.errors,
349
+ });
350
+ }
351
+ catch (err) {
352
+ return handleError(err, 'self-verification failed');
353
+ }
354
+ },
355
+ }),
356
+ // ----- Trust Agent -----
357
+ new DynamicStructuredTool({
358
+ name: 'jacs_trust_agent',
359
+ description: 'Add an agent to the local trust store. Pass the agent JSON document.',
360
+ schema: z.object({
361
+ agentJson: z.string().describe('The agent JSON document to trust'),
362
+ }),
363
+ func: async ({ agentJson }) => {
364
+ try {
365
+ const result = client.trustAgent(agentJson);
366
+ return JSON.stringify({ success: true, result });
367
+ }
368
+ catch (err) {
369
+ return handleError(err, 'trust agent failed');
370
+ }
371
+ },
372
+ }),
373
+ // ----- List Trusted Agents -----
374
+ new DynamicStructuredTool({
375
+ name: 'jacs_list_trusted',
376
+ description: 'List all agent IDs in the local trust store.',
377
+ schema: z.object({}),
378
+ func: async () => {
379
+ try {
380
+ const agents = client.listTrustedAgents();
381
+ return JSON.stringify({ trustedAgents: agents });
382
+ }
383
+ catch (err) {
384
+ return handleError(err, 'list trusted failed');
385
+ }
386
+ },
387
+ }),
388
+ // ----- Is Trusted -----
389
+ new DynamicStructuredTool({
390
+ name: 'jacs_is_trusted',
391
+ description: 'Check whether a specific agent ID is in the local trust store.',
392
+ schema: z.object({
393
+ agentId: z.string().describe('The agent ID to check'),
394
+ }),
395
+ func: async ({ agentId }) => {
396
+ try {
397
+ const trusted = client.isTrusted(agentId);
398
+ return JSON.stringify({ agentId, trusted });
399
+ }
400
+ catch (err) {
401
+ return handleError(err, 'is trusted check failed');
402
+ }
403
+ },
404
+ }),
405
+ // ----- Audit -----
406
+ new DynamicStructuredTool({
407
+ name: 'jacs_audit',
408
+ description: 'Run a JACS security audit. Returns audit results including document integrity, ' +
409
+ 'key status, and configuration health.',
410
+ schema: z.object({
411
+ recentN: z.number().optional().describe('Number of recent documents to audit'),
412
+ }),
413
+ func: async (input) => {
414
+ try {
415
+ const result = await client.audit(input.recentN !== undefined ? { recentN: input.recentN } : undefined);
416
+ return JSON.stringify(result);
417
+ }
418
+ catch (err) {
419
+ return handleError(err, 'audit failed');
420
+ }
421
+ },
422
+ }),
423
+ // ----- Get Agent Info -----
424
+ new DynamicStructuredTool({
425
+ name: 'jacs_agent_info',
426
+ description: 'Get the current JACS agent ID and name. Useful for knowing your own identity ' +
427
+ 'when creating agreements or sharing with other agents.',
428
+ schema: z.object({}),
429
+ func: async () => {
430
+ return JSON.stringify({
431
+ agentId: client.agentId,
432
+ name: client.name,
433
+ strict: client.strict,
434
+ });
435
+ },
436
+ }),
437
+ ];
438
+ }
439
+ //# sourceMappingURL=langchain.js.map