@thisispandora/agent-sdk 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js ADDED
@@ -0,0 +1,757 @@
1
+ 'use strict';
2
+
3
+ const { Client } = require('@modelcontextprotocol/sdk/client/index.js');
4
+ const { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio.js');
5
+ const { StreamableHTTPClientTransport } = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
6
+ const generated = require('./generated/index.js');
7
+
8
+ class PandoraSdkError extends Error {
9
+ constructor(code, message, details = undefined) {
10
+ super(message);
11
+ this.name = 'PandoraSdkError';
12
+ this.code = code;
13
+ if (details !== undefined) {
14
+ this.details = details;
15
+ if (!Object.prototype.hasOwnProperty.call(this, 'cause') && details && details.cause !== undefined) {
16
+ this.cause = details.cause;
17
+ }
18
+ }
19
+ }
20
+ }
21
+
22
+ class PandoraToolCallError extends PandoraSdkError {
23
+ constructor(message, details = undefined) {
24
+ const detailObject = asObject(details) || {};
25
+ const envelope = asObject(detailObject.envelope);
26
+ const envelopeError = asObject(envelope && envelope.error);
27
+ const code = typeof (envelopeError && envelopeError.code) === 'string' && envelopeError.code.trim()
28
+ ? envelopeError.code.trim()
29
+ : 'PANDORA_SDK_TOOL_ERROR';
30
+ super(code, message, detailObject);
31
+ this.name = 'PandoraToolCallError';
32
+ this.sdkCode = 'PANDORA_SDK_TOOL_ERROR';
33
+ this.envelope = envelope;
34
+ this.rawResult = detailObject.result || null;
35
+ this.toolName = typeof detailObject.toolName === 'string' && detailObject.toolName.trim()
36
+ ? detailObject.toolName.trim()
37
+ : null;
38
+ this.toolError = envelopeError || null;
39
+ }
40
+ }
41
+
42
+ function createSdkError(code, message, details = undefined) {
43
+ return new PandoraSdkError(code, message, details);
44
+ }
45
+
46
+ function wrapSdkOperationError(code, message, error, details = undefined) {
47
+ if (error instanceof PandoraSdkError) {
48
+ throw error;
49
+ }
50
+ throw createSdkError(code, message, {
51
+ ...asObject(details),
52
+ cause: error,
53
+ message: error && error.message ? error.message : String(error),
54
+ });
55
+ }
56
+
57
+ function normalizeToolName(name) {
58
+ const normalizedName = String(name || '').trim();
59
+ if (!normalizedName) {
60
+ throw createSdkError('PANDORA_SDK_INVALID_TOOL_NAME', 'Tool name is required.');
61
+ }
62
+ return normalizedName;
63
+ }
64
+
65
+ function parseStructuredEnvelope(result) {
66
+ if (result && result.structuredContent && typeof result.structuredContent === 'object') {
67
+ return result.structuredContent;
68
+ }
69
+ const textContent = Array.isArray(result && result.content)
70
+ ? result.content.find((entry) => entry && entry.type === 'text' && typeof entry.text === 'string')
71
+ : null;
72
+ if (!textContent) {
73
+ throw createSdkError('PANDORA_SDK_INVALID_TOOL_RESULT', 'Tool result did not include structuredContent or parseable text.', {
74
+ result,
75
+ });
76
+ }
77
+ try {
78
+ const parsed = JSON.parse(textContent.text);
79
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
80
+ throw createSdkError('PANDORA_SDK_INVALID_TOOL_RESULT', 'Tool text payload must decode to an object envelope.', {
81
+ parsedType: Array.isArray(parsed) ? 'array' : typeof parsed,
82
+ });
83
+ }
84
+ return parsed;
85
+ } catch (error) {
86
+ if (error instanceof PandoraSdkError) {
87
+ throw error;
88
+ }
89
+ throw createSdkError('PANDORA_SDK_INVALID_TOOL_RESULT', 'Tool text payload was not valid JSON.', {
90
+ cause: error && error.message ? error.message : String(error),
91
+ });
92
+ }
93
+ }
94
+
95
+ function isFailureEnvelope(envelope) {
96
+ const normalizedEnvelope = asObject(envelope);
97
+ if (!normalizedEnvelope) return false;
98
+ if (normalizedEnvelope.ok === false) return true;
99
+ return Boolean(asObject(normalizedEnvelope.error));
100
+ }
101
+
102
+ function normalizeStructuredEnvelope(result, options = {}) {
103
+ const envelope = parseStructuredEnvelope(result);
104
+ if (!options || options.throwOnError !== false) {
105
+ if (result && result.isError || isFailureEnvelope(envelope)) {
106
+ const errorPayload = asObject(envelope && envelope.error);
107
+ const message = errorPayload && typeof errorPayload.message === 'string' && errorPayload.message.trim()
108
+ ? errorPayload.message.trim()
109
+ : 'Pandora tool returned an MCP error result.';
110
+ throw new PandoraToolCallError(message, {
111
+ ...asObject(options),
112
+ result,
113
+ envelope,
114
+ });
115
+ }
116
+ }
117
+ return envelope;
118
+ }
119
+
120
+ function buildCatalogIndex(catalog) {
121
+ const tools = catalog && catalog.tools && typeof catalog.tools === 'object' ? catalog.tools : {};
122
+ return new Map(Object.entries(tools));
123
+ }
124
+
125
+ function asObject(value) {
126
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
127
+ }
128
+
129
+ function toSortedUniqueStrings(values) {
130
+ if (!Array.isArray(values)) return [];
131
+ return Array.from(new Set(
132
+ values
133
+ .map((value) => String(value || '').trim())
134
+ .filter(Boolean),
135
+ )).sort((left, right) => left.localeCompare(right));
136
+ }
137
+
138
+ function loadGeneratedValue(loaderName, propertyName) {
139
+ if (generated && typeof generated[loaderName] === 'function') {
140
+ return generated[loaderName]();
141
+ }
142
+ if (generated && Object.prototype.hasOwnProperty.call(generated, propertyName)) {
143
+ return generated[propertyName];
144
+ }
145
+ throw createSdkError(
146
+ 'PANDORA_SDK_MISSING_GENERATED_ARTIFACT',
147
+ `Generated SDK artifact is missing ${propertyName}.`,
148
+ );
149
+ }
150
+
151
+ function buildCommandDescriptorIndex(catalog) {
152
+ const index = new Map();
153
+ const commandDescriptors = asObject(catalog && catalog.commandDescriptors);
154
+ if (commandDescriptors) {
155
+ for (const [name, descriptor] of Object.entries(commandDescriptors)) {
156
+ if (asObject(descriptor)) {
157
+ index.set(name, descriptor);
158
+ }
159
+ }
160
+ }
161
+
162
+ const tools = asObject(catalog && catalog.tools);
163
+ if (tools) {
164
+ for (const [name, tool] of Object.entries(tools)) {
165
+ const descriptor = asObject(tool && tool.commandDescriptor);
166
+ if (descriptor && !index.has(name)) {
167
+ index.set(name, descriptor);
168
+ }
169
+ }
170
+ }
171
+
172
+ const commandDigests = asObject(getCatalogCapabilities(catalog).commandDigests);
173
+ if (commandDigests) {
174
+ for (const [name, descriptor] of Object.entries(commandDigests)) {
175
+ if (asObject(descriptor) && !index.has(name)) {
176
+ index.set(name, descriptor);
177
+ }
178
+ }
179
+ }
180
+
181
+ return index;
182
+ }
183
+
184
+ function getCatalogCapabilities(catalog) {
185
+ return asObject(catalog && catalog.capabilities) || {};
186
+ }
187
+
188
+ function getRawPolicyProfiles(catalog) {
189
+ return asObject(getCatalogCapabilities(catalog).policyProfiles) || {};
190
+ }
191
+
192
+ function getCommandDescriptor(catalog, name) {
193
+ const normalizedName = String(name || '').trim();
194
+ if (!normalizedName) return null;
195
+ const commandDescriptors = buildCommandDescriptorIndex(catalog);
196
+ return commandDescriptors.get(normalizedName) || null;
197
+ }
198
+
199
+ function getPolicyScopeListFromDescriptor(descriptor) {
200
+ return toSortedUniqueStrings(descriptor && descriptor.policyScopes);
201
+ }
202
+
203
+ function derivePolicyScopedCommands(catalog) {
204
+ const rawPolicyProfiles = getRawPolicyProfiles(catalog);
205
+ const explicit = toSortedUniqueStrings(rawPolicyProfiles.policyPacks && rawPolicyProfiles.policyPacks.commandsWithPolicyScopes);
206
+ if (explicit.length) return explicit;
207
+
208
+ const commandDescriptors = buildCommandDescriptorIndex(catalog);
209
+ return Array.from(commandDescriptors.entries())
210
+ .filter(([, descriptor]) => getPolicyScopeListFromDescriptor(descriptor).length > 0)
211
+ .map(([name]) => name)
212
+ .sort((left, right) => left.localeCompare(right));
213
+ }
214
+
215
+ function deriveSignerProfileCommands(catalog) {
216
+ const rawPolicyProfiles = getRawPolicyProfiles(catalog);
217
+ const explicit = toSortedUniqueStrings(rawPolicyProfiles.signerProfiles && rawPolicyProfiles.signerProfiles.commandsRequiringSecrets);
218
+ if (explicit.length) return explicit;
219
+
220
+ const commandDescriptors = buildCommandDescriptorIndex(catalog);
221
+ return Array.from(commandDescriptors.entries())
222
+ .filter(([, descriptor]) => descriptor && descriptor.requiresSecrets === true)
223
+ .map(([name]) => name)
224
+ .sort((left, right) => left.localeCompare(right));
225
+ }
226
+
227
+ function normalizeCapabilityFeature(feature, defaults = {}) {
228
+ const raw = asObject(feature) || {};
229
+ const fallbackStatus = typeof defaults.status === 'string' && defaults.status.trim()
230
+ ? defaults.status.trim()
231
+ : raw.supported === true
232
+ ? 'active'
233
+ : 'unknown';
234
+ const fallbackNotes = toSortedUniqueStrings(defaults.notes);
235
+ const notes = toSortedUniqueStrings(raw.notes);
236
+ const normalized = {
237
+ ...raw,
238
+ supported: typeof raw.supported === 'boolean' ? raw.supported : Boolean(defaults.supported),
239
+ status: typeof raw.status === 'string' && raw.status.trim() ? raw.status.trim() : fallbackStatus,
240
+ notes: notes.length ? notes : fallbackNotes,
241
+ };
242
+ if (Object.prototype.hasOwnProperty.call(defaults, 'commandsWithPolicyScopes') || Object.prototype.hasOwnProperty.call(raw, 'commandsWithPolicyScopes')) {
243
+ const commands = toSortedUniqueStrings(raw.commandsWithPolicyScopes);
244
+ normalized.commandsWithPolicyScopes = commands.length
245
+ ? commands
246
+ : toSortedUniqueStrings(defaults.commandsWithPolicyScopes);
247
+ }
248
+ if (Object.prototype.hasOwnProperty.call(defaults, 'commandsRequiringSecrets') || Object.prototype.hasOwnProperty.call(raw, 'commandsRequiringSecrets')) {
249
+ const commands = toSortedUniqueStrings(raw.commandsRequiringSecrets);
250
+ normalized.commandsRequiringSecrets = commands.length
251
+ ? commands
252
+ : toSortedUniqueStrings(defaults.commandsRequiringSecrets);
253
+ }
254
+ return normalized;
255
+ }
256
+
257
+ function getPolicyProfileCapabilities(catalog = loadGeneratedContractRegistry()) {
258
+ const rawPolicyProfiles = getRawPolicyProfiles(catalog);
259
+ return {
260
+ policyPacks: normalizeCapabilityFeature(rawPolicyProfiles.policyPacks, {
261
+ commandsWithPolicyScopes: derivePolicyScopedCommands(catalog),
262
+ }),
263
+ signerProfiles: normalizeCapabilityFeature(rawPolicyProfiles.signerProfiles, {
264
+ commandsRequiringSecrets: deriveSignerProfileCommands(catalog),
265
+ }),
266
+ };
267
+ }
268
+
269
+ function getPolicyPackCapability(catalog = loadGeneratedContractRegistry()) {
270
+ return getPolicyProfileCapabilities(catalog).policyPacks;
271
+ }
272
+
273
+ function getSignerProfileCapability(catalog = loadGeneratedContractRegistry()) {
274
+ return getPolicyProfileCapabilities(catalog).signerProfiles;
275
+ }
276
+
277
+ function listPolicyScopes(catalog = loadGeneratedContractRegistry()) {
278
+ const commandDescriptors = buildCommandDescriptorIndex(catalog);
279
+ const scopes = new Set();
280
+ for (const descriptor of commandDescriptors.values()) {
281
+ for (const scope of getPolicyScopeListFromDescriptor(descriptor)) {
282
+ scopes.add(scope);
283
+ }
284
+ }
285
+ return Array.from(scopes).sort((left, right) => left.localeCompare(right));
286
+ }
287
+
288
+ function listPolicyScopedCommands(catalog = loadGeneratedContractRegistry()) {
289
+ return getPolicyPackCapability(catalog).commandsWithPolicyScopes.slice();
290
+ }
291
+
292
+ function listSignerProfileCommands(catalog = loadGeneratedContractRegistry()) {
293
+ return getSignerProfileCapability(catalog).commandsRequiringSecrets.slice();
294
+ }
295
+
296
+ function inspectToolPolicySurface(name, catalog = loadGeneratedContractRegistry()) {
297
+ const normalizedName = String(name || '').trim();
298
+ if (!normalizedName) {
299
+ throw createSdkError('PANDORA_SDK_INVALID_TOOL_NAME', 'Tool name is required for policy/profile inspection.');
300
+ }
301
+
302
+ const tools = buildCatalogIndex(catalog);
303
+ const tool = tools.get(normalizedName) || null;
304
+ const descriptor = asObject(tool && tool.commandDescriptor) || getCommandDescriptor(catalog, normalizedName) || {};
305
+ if (!tool && !Object.keys(descriptor).length) {
306
+ throw createSdkError('PANDORA_SDK_UNKNOWN_TOOL', `Unknown Pandora tool or command: ${normalizedName}`);
307
+ }
308
+ const policyProfiles = getPolicyProfileCapabilities(catalog);
309
+ const policyScopes = getPolicyScopeListFromDescriptor(descriptor);
310
+ const requiresSecrets = descriptor.requiresSecrets === true;
311
+
312
+ return {
313
+ name: normalizedName,
314
+ canonicalTool: descriptor.canonicalTool || normalizedName,
315
+ aliasOf: descriptor.aliasOf || null,
316
+ preferred: descriptor.preferred === true,
317
+ policyScopes,
318
+ requiresSecrets,
319
+ policyPackEligible: policyScopes.length > 0,
320
+ signerProfileEligible: requiresSecrets,
321
+ supportsRemote: descriptor.supportsRemote === true,
322
+ remoteEligible: descriptor.remoteEligible === true,
323
+ policyPackStatus: policyProfiles.policyPacks.status,
324
+ signerProfileStatus: policyProfiles.signerProfiles.status,
325
+ };
326
+ }
327
+
328
+ function inspectPolicyScope(scope, catalog = loadGeneratedContractRegistry()) {
329
+ const normalizedScope = String(scope || '').trim();
330
+ if (!normalizedScope) {
331
+ throw createSdkError('PANDORA_SDK_INVALID_POLICY_SCOPE', 'Policy scope is required.');
332
+ }
333
+
334
+ const commandDescriptors = buildCommandDescriptorIndex(catalog);
335
+ const commands = Array.from(commandDescriptors.entries())
336
+ .filter(([, descriptor]) => getPolicyScopeListFromDescriptor(descriptor).includes(normalizedScope))
337
+ .map(([name]) => name)
338
+ .sort((left, right) => left.localeCompare(right));
339
+
340
+ return {
341
+ scope: normalizedScope,
342
+ commands,
343
+ tools: commands.map((name) => inspectToolPolicySurface(name, catalog)),
344
+ };
345
+ }
346
+
347
+ function loadGeneratedContractRegistry() {
348
+ return loadGeneratedValue('loadGeneratedContractRegistry', 'contractRegistry');
349
+ }
350
+
351
+ function loadGeneratedManifest() {
352
+ return loadGeneratedValue('loadGeneratedManifest', 'manifest');
353
+ }
354
+
355
+ function loadGeneratedCommandDescriptors() {
356
+ return loadGeneratedValue('loadGeneratedCommandDescriptors', 'commandDescriptors');
357
+ }
358
+
359
+ function loadGeneratedMcpToolDefinitions() {
360
+ return loadGeneratedValue('loadGeneratedMcpToolDefinitions', 'mcpToolDefinitions');
361
+ }
362
+
363
+ function loadGeneratedCapabilities() {
364
+ const registry = loadGeneratedContractRegistry();
365
+ return asObject(registry && registry.capabilities) || {};
366
+ }
367
+
368
+ function loadGeneratedToolCatalog() {
369
+ const registry = loadGeneratedContractRegistry();
370
+ return asObject(registry && registry.tools) || {};
371
+ }
372
+
373
+ function normalizeRuntimeToolDefinition(tool, catalog = loadGeneratedContractRegistry()) {
374
+ const rawTool = asObject(tool) || {};
375
+ const name = typeof rawTool.name === 'string' && rawTool.name.trim()
376
+ ? rawTool.name.trim()
377
+ : '';
378
+ const inputSchema = asObject(rawTool.inputSchema) || {};
379
+ const runtimeMetadata = asObject(inputSchema.xPandora) || asObject(rawTool.xPandora);
380
+ const descriptor = asObject(rawTool.commandDescriptor) || getCommandDescriptor(catalog, name) || null;
381
+ const xPandora = runtimeMetadata || descriptor;
382
+
383
+ return {
384
+ ...rawTool,
385
+ name,
386
+ description: typeof rawTool.description === 'string' ? rawTool.description : null,
387
+ inputSchema,
388
+ xPandora: xPandora || null,
389
+ commandDescriptor: descriptor,
390
+ policyScopes: xPandora ? getPolicyScopeListFromDescriptor(xPandora) : [],
391
+ requiresSecrets: Boolean(xPandora && xPandora.requiresSecrets === true),
392
+ supportsRemote: Boolean(xPandora && xPandora.supportsRemote === true),
393
+ remoteEligible: Boolean(xPandora && xPandora.remoteEligible === true),
394
+ canonicalTool: xPandora && typeof xPandora.canonicalTool === 'string' ? xPandora.canonicalTool : null,
395
+ aliasOf: xPandora && typeof xPandora.aliasOf === 'string' ? xPandora.aliasOf : null,
396
+ preferred: Boolean(xPandora && xPandora.preferred === true),
397
+ };
398
+ }
399
+
400
+ function normalizeAuthorizationHeaders(headers = {}, authToken = null) {
401
+ const entries = Object.entries(headers || {}).filter(([key]) => typeof key === 'string' && key.trim());
402
+ const authorizationEntries = entries.filter(([key]) => key.toLowerCase() === 'authorization');
403
+ if (authorizationEntries.length > 1) {
404
+ throw createSdkError(
405
+ 'PANDORA_SDK_INVALID_REMOTE_CONFIG',
406
+ 'Remote backend received multiple Authorization header variants. Provide only one authorization header.',
407
+ {
408
+ headerKeys: authorizationEntries.map(([key]) => key),
409
+ },
410
+ );
411
+ }
412
+ if (authToken && authorizationEntries.length) {
413
+ throw createSdkError(
414
+ 'PANDORA_SDK_INVALID_REMOTE_CONFIG',
415
+ 'Remote backend cannot accept authToken together with an explicit Authorization header.',
416
+ {
417
+ headerKey: authorizationEntries[0][0],
418
+ },
419
+ );
420
+ }
421
+ const normalized = {};
422
+ for (const [key, value] of entries) {
423
+ normalized[key] = value;
424
+ }
425
+ if (authorizationEntries.length === 1) {
426
+ const [[originalKey, authorizationValue]] = authorizationEntries;
427
+ if (originalKey !== 'Authorization') {
428
+ delete normalized[originalKey];
429
+ normalized.Authorization = authorizationValue;
430
+ }
431
+ }
432
+ return normalized;
433
+ }
434
+
435
+ class PandoraMcpBackend {
436
+ constructor(options = {}) {
437
+ const manifestVersion = loadGeneratedManifest().packageVersion || '0.0.0';
438
+ this.clientInfo = {
439
+ name: options.clientName || 'thisispandora-agent-sdk',
440
+ version: options.clientVersion || manifestVersion,
441
+ };
442
+ this.client = null;
443
+ this.transport = null;
444
+ }
445
+
446
+ async connect() {
447
+ if (this.client) return;
448
+ const transport = this.createTransport();
449
+ const client = new Client(this.clientInfo, {
450
+ capabilities: {},
451
+ });
452
+ try {
453
+ await client.connect(transport);
454
+ } catch (error) {
455
+ if (transport && typeof transport.close === 'function') {
456
+ await transport.close().catch(() => {});
457
+ }
458
+ wrapSdkOperationError(
459
+ 'PANDORA_SDK_CONNECT_FAILED',
460
+ 'Failed to connect Pandora MCP backend.',
461
+ error,
462
+ {
463
+ backend: this.constructor && this.constructor.name ? this.constructor.name : 'PandoraMcpBackend',
464
+ },
465
+ );
466
+ }
467
+ this.transport = transport;
468
+ this.client = client;
469
+ }
470
+
471
+ async close() {
472
+ if (this.transport && typeof this.transport.close === 'function') {
473
+ await this.transport.close();
474
+ }
475
+ this.transport = null;
476
+ this.client = null;
477
+ }
478
+
479
+ async listTools() {
480
+ if (!this.client) {
481
+ throw createSdkError('PANDORA_SDK_NOT_CONNECTED', 'Call connect() before listTools().');
482
+ }
483
+ try {
484
+ const result = await this.client.listTools();
485
+ return Array.isArray(result && result.tools) ? result.tools : [];
486
+ } catch (error) {
487
+ wrapSdkOperationError(
488
+ 'PANDORA_SDK_LIST_TOOLS_FAILED',
489
+ 'Failed to list Pandora MCP tools.',
490
+ error,
491
+ {
492
+ backend: this.constructor && this.constructor.name ? this.constructor.name : 'PandoraMcpBackend',
493
+ },
494
+ );
495
+ }
496
+ }
497
+
498
+ async callTool(name, args = {}) {
499
+ if (!this.client) {
500
+ throw createSdkError('PANDORA_SDK_NOT_CONNECTED', 'Call connect() before callTool().');
501
+ }
502
+ const normalizedName = normalizeToolName(name);
503
+ try {
504
+ return await this.client.callTool({ name: normalizedName, arguments: args });
505
+ } catch (error) {
506
+ wrapSdkOperationError(
507
+ 'PANDORA_SDK_CALL_FAILED',
508
+ `Failed to call Pandora tool: ${normalizedName}`,
509
+ error,
510
+ {
511
+ backend: this.constructor && this.constructor.name ? this.constructor.name : 'PandoraMcpBackend',
512
+ toolName: normalizedName,
513
+ },
514
+ );
515
+ }
516
+ }
517
+ }
518
+
519
+ class PandoraStdioBackend extends PandoraMcpBackend {
520
+ constructor(options = {}) {
521
+ super(options);
522
+ this.command = options.command || 'pandora';
523
+ this.args = Array.isArray(options.args) && options.args.length ? options.args.slice() : ['mcp'];
524
+ this.cwd = options.cwd || process.cwd();
525
+ this.env = options.env && typeof options.env === 'object' ? { ...options.env } : undefined;
526
+ this.stderr = options.stderr || 'inherit';
527
+ }
528
+
529
+ createTransport() {
530
+ return new StdioClientTransport({
531
+ command: this.command,
532
+ args: this.args,
533
+ cwd: this.cwd,
534
+ env: this.env,
535
+ stderr: this.stderr,
536
+ });
537
+ }
538
+ }
539
+
540
+ class PandoraRemoteBackend extends PandoraMcpBackend {
541
+ constructor(options = {}) {
542
+ super(options);
543
+ if (!options.url) {
544
+ throw createSdkError('PANDORA_SDK_INVALID_REMOTE_CONFIG', 'Remote backend requires url.');
545
+ }
546
+ this.url = options.url instanceof URL ? options.url : new URL(String(options.url));
547
+ this.authToken = options.authToken || null;
548
+ this.headers = normalizeAuthorizationHeaders(
549
+ options.headers && typeof options.headers === 'object' ? { ...options.headers } : {},
550
+ this.authToken,
551
+ );
552
+ this.fetch = typeof options.fetch === 'function' ? options.fetch : undefined;
553
+ }
554
+
555
+ createTransport() {
556
+ const headers = { ...this.headers };
557
+ if (this.authToken) {
558
+ headers.Authorization = `Bearer ${this.authToken}`;
559
+ }
560
+ return new StreamableHTTPClientTransport(this.url, {
561
+ fetch: this.fetch,
562
+ requestInit: {
563
+ headers,
564
+ },
565
+ });
566
+ }
567
+ }
568
+
569
+ class PandoraAgentClient {
570
+ constructor(options = {}) {
571
+ if (!options.backend) {
572
+ throw createSdkError('PANDORA_SDK_INVALID_CLIENT_CONFIG', 'PandoraAgentClient requires a backend instance.');
573
+ }
574
+ this.backend = options.backend;
575
+ this.catalog = options.catalog || loadGeneratedContractRegistry();
576
+ this.toolIndex = buildCatalogIndex(this.catalog);
577
+ this.commandDescriptorIndex = buildCommandDescriptorIndex(this.catalog);
578
+ }
579
+
580
+ async connect() {
581
+ await this.backend.connect();
582
+ return this;
583
+ }
584
+
585
+ async close() {
586
+ await this.backend.close();
587
+ }
588
+
589
+ getManifest() {
590
+ return loadGeneratedManifest();
591
+ }
592
+
593
+ getCatalog() {
594
+ return this.catalog;
595
+ }
596
+
597
+ getPolicyProfileCapabilities() {
598
+ return getPolicyProfileCapabilities(this.catalog);
599
+ }
600
+
601
+ getPolicyPackCapability() {
602
+ return getPolicyPackCapability(this.catalog);
603
+ }
604
+
605
+ getSignerProfileCapability() {
606
+ return getSignerProfileCapability(this.catalog);
607
+ }
608
+
609
+ listPolicyScopes() {
610
+ return listPolicyScopes(this.catalog);
611
+ }
612
+
613
+ listPolicyScopedCommands() {
614
+ return listPolicyScopedCommands(this.catalog);
615
+ }
616
+
617
+ listSignerProfileCommands() {
618
+ return listSignerProfileCommands(this.catalog);
619
+ }
620
+
621
+ inspectPolicyScope(scope) {
622
+ return inspectPolicyScope(scope, this.catalog);
623
+ }
624
+
625
+ inspectToolPolicySurface(name) {
626
+ return inspectToolPolicySurface(name, this.catalog);
627
+ }
628
+
629
+ listGeneratedTools() {
630
+ return Array.from(this.toolIndex.keys()).sort((left, right) => left.localeCompare(right));
631
+ }
632
+
633
+ getTool(name) {
634
+ return this.toolIndex.get(String(name || '').trim()) || null;
635
+ }
636
+
637
+ requireTool(name) {
638
+ const tool = this.getTool(name);
639
+ if (!tool) {
640
+ throw createSdkError('PANDORA_SDK_UNKNOWN_TOOL', `Unknown Pandora tool: ${name}`);
641
+ }
642
+ return tool;
643
+ }
644
+
645
+ async listTools() {
646
+ const tools = await this.backend.listTools();
647
+ return tools.map((tool) => normalizeRuntimeToolDefinition(tool, this.catalog));
648
+ }
649
+
650
+ async callToolRaw(name, args = {}) {
651
+ const normalizedName = normalizeToolName(name);
652
+ return this.backend.callTool(normalizedName, args);
653
+ }
654
+
655
+ async callToolEnvelope(name, args = {}) {
656
+ const result = await this.callToolRaw(name, args);
657
+ return normalizeStructuredEnvelope(result, { toolName: name });
658
+ }
659
+
660
+ async callToolData(name, args = {}) {
661
+ const envelope = await this.callToolEnvelope(name, args);
662
+ if (envelope && Object.prototype.hasOwnProperty.call(envelope, 'data')) {
663
+ return envelope.data;
664
+ }
665
+ return envelope;
666
+ }
667
+
668
+ async getBootstrapEnvelope(args = {}) {
669
+ return this.callToolEnvelope('bootstrap', args);
670
+ }
671
+
672
+ async getBootstrap(args = {}) {
673
+ return this.callToolData('bootstrap', args);
674
+ }
675
+
676
+ async callTool(name, args = {}) {
677
+ return this.callToolEnvelope(name, args);
678
+ }
679
+ }
680
+
681
+ function createLocalPandoraAgentClient(options = {}) {
682
+ return new PandoraAgentClient({
683
+ backend: new PandoraStdioBackend(options),
684
+ catalog: options.catalog,
685
+ });
686
+ }
687
+
688
+ function createRemotePandoraAgentClient(options = {}) {
689
+ return new PandoraAgentClient({
690
+ backend: new PandoraRemoteBackend(options),
691
+ catalog: options.catalog,
692
+ });
693
+ }
694
+
695
+ function createPandoraStdioBackend(options = {}) {
696
+ return new PandoraStdioBackend(options);
697
+ }
698
+
699
+ function createPandoraRemoteBackend(options = {}) {
700
+ return new PandoraRemoteBackend(options);
701
+ }
702
+
703
+ function createPandoraAgentClient(options = {}) {
704
+ const normalizedOptions = asObject(options) || {};
705
+ if (normalizedOptions.backend) {
706
+ return new PandoraAgentClient({
707
+ backend: normalizedOptions.backend,
708
+ catalog: normalizedOptions.catalog,
709
+ });
710
+ }
711
+ if (normalizedOptions.mode === 'remote' || normalizedOptions.url) {
712
+ return createRemotePandoraAgentClient(normalizedOptions);
713
+ }
714
+ return createLocalPandoraAgentClient(normalizedOptions);
715
+ }
716
+
717
+ async function connectPandoraAgentClient(options = {}) {
718
+ const client = createPandoraAgentClient(options);
719
+ await client.connect();
720
+ return client;
721
+ }
722
+
723
+ const api = {
724
+ PandoraSdkError,
725
+ PandoraToolCallError,
726
+ loadGeneratedContractRegistry,
727
+ loadGeneratedManifest,
728
+ loadGeneratedCommandDescriptors,
729
+ loadGeneratedMcpToolDefinitions,
730
+ loadGeneratedCapabilities,
731
+ loadGeneratedToolCatalog,
732
+ normalizeStructuredEnvelope,
733
+ normalizeRuntimeToolDefinition,
734
+ getPolicyProfileCapabilities,
735
+ getPolicyPackCapability,
736
+ getSignerProfileCapability,
737
+ listPolicyScopes,
738
+ listPolicyScopedCommands,
739
+ listSignerProfileCommands,
740
+ inspectPolicyScope,
741
+ inspectToolPolicySurface,
742
+ PandoraAgentClient,
743
+ PandoraMcpBackend,
744
+ PandoraStdioBackend,
745
+ PandoraRemoteBackend,
746
+ createPandoraStdioBackend,
747
+ createPandoraRemoteBackend,
748
+ createLocalPandoraAgentClient,
749
+ createRemotePandoraAgentClient,
750
+ createPandoraAgentClient,
751
+ connectPandoraAgentClient,
752
+ generated,
753
+ };
754
+
755
+ api.default = api;
756
+
757
+ module.exports = Object.freeze(api);