@contractspec/module.ai-chat 4.3.6 → 4.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +62 -370
  2. package/dist/adapters/ai-sdk-bundle-adapter.d.ts +1 -1
  3. package/dist/adapters/index.d.ts +1 -1
  4. package/dist/browser/context/index.js +93 -93
  5. package/dist/browser/core/index.js +308 -307
  6. package/dist/browser/index.js +3803 -3801
  7. package/dist/browser/presentation/components/index.js +2617 -2618
  8. package/dist/browser/presentation/hooks/index.js +476 -476
  9. package/dist/browser/presentation/index.js +2474 -2475
  10. package/dist/browser/providers/index.js +7 -7
  11. package/dist/context/index.d.ts +1 -1
  12. package/dist/context/index.js +93 -93
  13. package/dist/core/agent-tools-adapter.d.ts +1 -1
  14. package/dist/core/chat-service.d.ts +4 -4
  15. package/dist/core/create-chat-route.d.ts +1 -1
  16. package/dist/core/create-completion-route.d.ts +15 -0
  17. package/dist/core/export-formatters.d.ts +1 -1
  18. package/dist/core/index.d.ts +6 -6
  19. package/dist/core/index.js +308 -307
  20. package/dist/core/local-storage-conversation-store.d.ts +1 -1
  21. package/dist/core/surface-planner-tools.d.ts +2 -2
  22. package/dist/core/workflow-tools.d.ts +1 -1
  23. package/dist/index.d.ts +8 -8
  24. package/dist/index.js +3803 -3801
  25. package/dist/node/context/index.js +93 -93
  26. package/dist/node/core/index.js +308 -307
  27. package/dist/node/index.js +3803 -3801
  28. package/dist/node/presentation/components/index.js +2617 -2618
  29. package/dist/node/presentation/hooks/index.js +476 -476
  30. package/dist/node/presentation/index.js +2474 -2475
  31. package/dist/node/providers/index.js +7 -7
  32. package/dist/presentation/components/ChainOfThought.d.ts +1 -1
  33. package/dist/presentation/components/ChatExportToolbar.d.ts +1 -1
  34. package/dist/presentation/components/ChatSidebar.d.ts +1 -1
  35. package/dist/presentation/components/ChatWithExport.d.ts +1 -1
  36. package/dist/presentation/components/index.d.ts +11 -11
  37. package/dist/presentation/components/index.js +2617 -2618
  38. package/dist/presentation/hooks/index.d.ts +4 -4
  39. package/dist/presentation/hooks/index.js +476 -476
  40. package/dist/presentation/hooks/useChat.d.ts +6 -6
  41. package/dist/presentation/hooks/useConversations.d.ts +1 -1
  42. package/dist/presentation/hooks/useProviders.d.ts +1 -1
  43. package/dist/presentation/index.js +2474 -2475
  44. package/dist/providers/index.d.ts +2 -2
  45. package/dist/providers/index.js +7 -7
  46. package/package.json +10 -10
@@ -1,5 +1,112 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
4
+ // src/core/agent-adapter.ts
5
+ function createChatAgentAdapter(agent) {
6
+ return {
7
+ async generate({ prompt, signal }) {
8
+ const result = await agent.generate({ prompt, signal });
9
+ return {
10
+ text: result.text,
11
+ toolCalls: result.toolCalls,
12
+ toolResults: result.toolResults,
13
+ usage: result.usage
14
+ };
15
+ }
16
+ };
17
+ }
18
+ // src/core/agent-tools-adapter.ts
19
+ import { tool } from "ai";
20
+ import { z } from "zod";
21
+ function getInputSchema(_schema) {
22
+ return z.object({}).passthrough();
23
+ }
24
+ function agentToolConfigsToToolSet(configs, handlers) {
25
+ const result = {};
26
+ for (const config of configs) {
27
+ const handler = handlers?.[config.name];
28
+ const inputSchema = getInputSchema(config.schema);
29
+ result[config.name] = tool({
30
+ description: config.description ?? config.name,
31
+ inputSchema,
32
+ execute: async (input) => {
33
+ if (!handler) {
34
+ return {
35
+ status: "unimplemented",
36
+ message: "Wire handler in host",
37
+ toolName: config.name
38
+ };
39
+ }
40
+ try {
41
+ const output = await Promise.resolve(handler(input));
42
+ return typeof output === "string" ? output : output;
43
+ } catch (err) {
44
+ return {
45
+ status: "error",
46
+ error: err instanceof Error ? err.message : String(err),
47
+ toolName: config.name
48
+ };
49
+ }
50
+ }
51
+ });
52
+ }
53
+ return result;
54
+ }
55
+ // src/core/chat-service.ts
56
+ import { generateText, streamText } from "ai";
57
+ import { compilePlannerPrompt } from "@contractspec/lib.surface-runtime/runtime/planner-prompt";
58
+
59
+ // src/core/contracts-context.ts
60
+ function buildContractsContextPrompt(config) {
61
+ const parts = [];
62
+ if (!config.agentSpecs?.length && !config.dataViewSpecs?.length && !config.formSpecs?.length && !config.presentationSpecs?.length && !config.operationRefs?.length) {
63
+ return "";
64
+ }
65
+ parts.push(`
66
+
67
+ ## Available resources`);
68
+ if (config.agentSpecs?.length) {
69
+ parts.push(`
70
+ ### Agent tools`);
71
+ for (const agent of config.agentSpecs) {
72
+ const toolNames = agent.tools?.map((t) => t.name).join(", ") ?? "none";
73
+ parts.push(`- **${agent.key}**: tools: ${toolNames}`);
74
+ }
75
+ }
76
+ if (config.dataViewSpecs?.length) {
77
+ parts.push(`
78
+ ### Data views`);
79
+ for (const dv of config.dataViewSpecs) {
80
+ parts.push(`- **${dv.key}**: ${dv.meta.title ?? dv.key}`);
81
+ }
82
+ }
83
+ if (config.formSpecs?.length) {
84
+ parts.push(`
85
+ ### Forms`);
86
+ for (const form of config.formSpecs) {
87
+ parts.push(`- **${form.key}**: ${form.meta.title ?? form.key}`);
88
+ }
89
+ }
90
+ if (config.presentationSpecs?.length) {
91
+ parts.push(`
92
+ ### Presentations`);
93
+ for (const pres of config.presentationSpecs) {
94
+ parts.push(`- **${pres.key}**: ${pres.meta.title ?? pres.key} (targets: ${pres.targets?.join(", ") ?? "react"})`);
95
+ }
96
+ }
97
+ if (config.operationRefs?.length) {
98
+ parts.push(`
99
+ ### Operations`);
100
+ for (const op of config.operationRefs) {
101
+ parts.push(`- **${op.key}@${op.version}**`);
102
+ }
103
+ }
104
+ parts.push(`
105
+ Use the available tools to invoke operations, query data views, or propose surface changes when appropriate.`);
106
+ return parts.join(`
107
+ `);
108
+ }
109
+
3
110
  // src/core/conversation-store.ts
4
111
  function generateId(prefix) {
5
112
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
@@ -160,8 +267,163 @@ class InMemoryConversationStore {
160
267
  function createInMemoryConversationStore() {
161
268
  return new InMemoryConversationStore;
162
269
  }
163
- // src/core/chat-service.ts
164
- import { generateText, streamText } from "ai";
270
+
271
+ // src/core/surface-planner-tools.ts
272
+ import { buildSurfacePatchProposal } from "@contractspec/lib.surface-runtime/runtime/planner-tools";
273
+ import {
274
+ validatePatchProposal
275
+ } from "@contractspec/lib.surface-runtime/spec/validate-surface-patch";
276
+ import { tool as tool2 } from "ai";
277
+ import { z as z2 } from "zod";
278
+ var VALID_OPS = [
279
+ "insert-node",
280
+ "replace-node",
281
+ "remove-node",
282
+ "move-node",
283
+ "resize-panel",
284
+ "set-layout",
285
+ "reveal-field",
286
+ "hide-field",
287
+ "promote-action",
288
+ "set-focus"
289
+ ];
290
+ var DEFAULT_NODE_KINDS = [
291
+ "entity-section",
292
+ "entity-card",
293
+ "data-view",
294
+ "assistant-panel",
295
+ "chat-thread",
296
+ "action-bar",
297
+ "timeline",
298
+ "table",
299
+ "rich-doc",
300
+ "form",
301
+ "chart",
302
+ "custom-widget"
303
+ ];
304
+ function collectSlotIdsFromRegion(node) {
305
+ const ids = [];
306
+ if (node.type === "slot") {
307
+ ids.push(node.slotId);
308
+ }
309
+ if (node.type === "panel-group" || node.type === "stack") {
310
+ for (const child of node.children) {
311
+ ids.push(...collectSlotIdsFromRegion(child));
312
+ }
313
+ }
314
+ if (node.type === "tabs") {
315
+ for (const tab of node.tabs) {
316
+ ids.push(...collectSlotIdsFromRegion(tab.child));
317
+ }
318
+ }
319
+ if (node.type === "floating") {
320
+ ids.push(node.anchorSlotId);
321
+ ids.push(...collectSlotIdsFromRegion(node.child));
322
+ }
323
+ return ids;
324
+ }
325
+ function deriveConstraints(plan) {
326
+ const slotIds = collectSlotIdsFromRegion(plan.layoutRoot);
327
+ const uniqueSlots = [...new Set(slotIds)];
328
+ return {
329
+ allowedOps: VALID_OPS,
330
+ allowedSlots: uniqueSlots.length > 0 ? uniqueSlots : ["assistant", "primary"],
331
+ allowedNodeKinds: DEFAULT_NODE_KINDS
332
+ };
333
+ }
334
+ var ProposePatchInputSchema = z2.object({
335
+ proposalId: z2.string().describe("Unique proposal identifier"),
336
+ ops: z2.array(z2.object({
337
+ op: z2.enum([
338
+ "insert-node",
339
+ "replace-node",
340
+ "remove-node",
341
+ "move-node",
342
+ "resize-panel",
343
+ "set-layout",
344
+ "reveal-field",
345
+ "hide-field",
346
+ "promote-action",
347
+ "set-focus"
348
+ ]),
349
+ slotId: z2.string().optional(),
350
+ nodeId: z2.string().optional(),
351
+ toSlotId: z2.string().optional(),
352
+ index: z2.number().optional(),
353
+ node: z2.object({
354
+ nodeId: z2.string(),
355
+ kind: z2.string(),
356
+ title: z2.string().optional(),
357
+ props: z2.record(z2.string(), z2.unknown()).optional(),
358
+ children: z2.array(z2.unknown()).optional()
359
+ }).optional(),
360
+ persistKey: z2.string().optional(),
361
+ sizes: z2.array(z2.number()).optional(),
362
+ layoutId: z2.string().optional(),
363
+ fieldId: z2.string().optional(),
364
+ actionId: z2.string().optional(),
365
+ placement: z2.enum(["header", "inline", "context", "assistant"]).optional(),
366
+ targetId: z2.string().optional()
367
+ }))
368
+ });
369
+ function createSurfacePlannerTools(config) {
370
+ const { plan, constraints, onPatchProposal } = config;
371
+ const resolvedConstraints = constraints ?? deriveConstraints(plan);
372
+ const proposePatchTool = tool2({
373
+ description: "Propose surface patches (layout changes, node insertions, etc.) for user approval. " + "Only use allowed ops, slots, and node kinds from the planner context.",
374
+ inputSchema: ProposePatchInputSchema,
375
+ execute: async (input) => {
376
+ const ops = input.ops;
377
+ try {
378
+ validatePatchProposal(ops, resolvedConstraints);
379
+ const proposal = buildSurfacePatchProposal(input.proposalId, ops);
380
+ onPatchProposal?.(proposal);
381
+ return {
382
+ success: true,
383
+ proposalId: proposal.proposalId,
384
+ opsCount: proposal.ops.length,
385
+ message: "Patch proposal validated; awaiting user approval"
386
+ };
387
+ } catch (err) {
388
+ return {
389
+ success: false,
390
+ error: err instanceof Error ? err.message : String(err),
391
+ proposalId: input.proposalId
392
+ };
393
+ }
394
+ }
395
+ });
396
+ return {
397
+ "propose-patch": proposePatchTool
398
+ };
399
+ }
400
+ function buildPlannerPromptInput(plan) {
401
+ const constraints = deriveConstraints(plan);
402
+ return {
403
+ bundleMeta: {
404
+ key: plan.bundleKey,
405
+ version: "0.0.0",
406
+ title: plan.bundleKey
407
+ },
408
+ surfaceId: plan.surfaceId,
409
+ allowedPatchOps: constraints.allowedOps,
410
+ allowedSlots: [...constraints.allowedSlots],
411
+ allowedNodeKinds: [...constraints.allowedNodeKinds],
412
+ actions: plan.actions.map((a) => ({
413
+ actionId: a.actionId,
414
+ title: a.title
415
+ })),
416
+ preferences: {
417
+ guidance: "hints",
418
+ density: "standard",
419
+ dataDepth: "detailed",
420
+ control: "standard",
421
+ media: "text",
422
+ pace: "balanced",
423
+ narrative: "top-down"
424
+ }
425
+ };
426
+ }
165
427
 
166
428
  // src/core/thinking-levels.ts
167
429
  var THINKING_LEVEL_LABELS = {
@@ -215,50 +477,50 @@ function getProviderOptions(level, providerName) {
215
477
  }
216
478
 
217
479
  // src/core/workflow-tools.ts
218
- import { tool } from "ai";
219
- import { z } from "zod";
220
480
  import {
221
- WorkflowComposer,
222
- validateExtension
481
+ validateExtension,
482
+ WorkflowComposer
223
483
  } from "@contractspec/lib.workflow-composer";
224
- var StepTypeSchema = z.enum(["human", "automation", "decision"]);
225
- var StepActionSchema = z.object({
226
- operation: z.object({
227
- name: z.string(),
228
- version: z.number()
484
+ import { tool as tool3 } from "ai";
485
+ import { z as z3 } from "zod";
486
+ var StepTypeSchema = z3.enum(["human", "automation", "decision"]);
487
+ var StepActionSchema = z3.object({
488
+ operation: z3.object({
489
+ name: z3.string(),
490
+ version: z3.number()
229
491
  }).optional(),
230
- form: z.object({
231
- key: z.string(),
232
- version: z.number()
492
+ form: z3.object({
493
+ key: z3.string(),
494
+ version: z3.number()
233
495
  }).optional()
234
496
  }).optional();
235
- var StepSchema = z.object({
236
- id: z.string(),
497
+ var StepSchema = z3.object({
498
+ id: z3.string(),
237
499
  type: StepTypeSchema,
238
- label: z.string(),
239
- description: z.string().optional(),
500
+ label: z3.string(),
501
+ description: z3.string().optional(),
240
502
  action: StepActionSchema
241
503
  });
242
- var StepInjectionSchema = z.object({
243
- after: z.string().optional(),
244
- before: z.string().optional(),
504
+ var StepInjectionSchema = z3.object({
505
+ after: z3.string().optional(),
506
+ before: z3.string().optional(),
245
507
  inject: StepSchema,
246
- transitionTo: z.string().optional(),
247
- transitionFrom: z.string().optional(),
248
- when: z.string().optional()
508
+ transitionTo: z3.string().optional(),
509
+ transitionFrom: z3.string().optional(),
510
+ when: z3.string().optional()
249
511
  });
250
- var WorkflowExtensionInputSchema = z.object({
251
- workflow: z.string(),
252
- tenantId: z.string().optional(),
253
- role: z.string().optional(),
254
- priority: z.number().optional(),
255
- customSteps: z.array(StepInjectionSchema).optional(),
256
- hiddenSteps: z.array(z.string()).optional()
512
+ var WorkflowExtensionInputSchema = z3.object({
513
+ workflow: z3.string(),
514
+ tenantId: z3.string().optional(),
515
+ role: z3.string().optional(),
516
+ priority: z3.number().optional(),
517
+ customSteps: z3.array(StepInjectionSchema).optional(),
518
+ hiddenSteps: z3.array(z3.string()).optional()
257
519
  });
258
520
  function createWorkflowTools(config) {
259
521
  const { baseWorkflows, composer } = config;
260
522
  const baseByKey = new Map(baseWorkflows.map((b) => [b.meta.key, b]));
261
- const createWorkflowExtensionTool = tool({
523
+ const createWorkflowExtensionTool = tool3({
262
524
  description: "Create or validate a workflow extension. Use when the user asks to add steps, modify a workflow, or create a tenant-specific extension. The extension targets an existing base workflow.",
263
525
  inputSchema: WorkflowExtensionInputSchema,
264
526
  execute: async (input) => {
@@ -294,13 +556,13 @@ function createWorkflowTools(config) {
294
556
  }
295
557
  }
296
558
  });
297
- const composeWorkflowInputSchema = z.object({
298
- workflowKey: z.string().describe("Base workflow meta.key"),
299
- tenantId: z.string().optional(),
300
- role: z.string().optional(),
301
- extensions: z.array(WorkflowExtensionInputSchema).optional().describe("Extensions to register before composing")
559
+ const composeWorkflowInputSchema = z3.object({
560
+ workflowKey: z3.string().describe("Base workflow meta.key"),
561
+ tenantId: z3.string().optional(),
562
+ role: z3.string().optional(),
563
+ extensions: z3.array(WorkflowExtensionInputSchema).optional().describe("Extensions to register before composing")
302
564
  });
303
- const composeWorkflowTool = tool({
565
+ const composeWorkflowTool = tool3({
304
566
  description: "Compose a workflow by applying registered extensions to a base workflow. Returns the composed WorkflowSpec.",
305
567
  inputSchema: composeWorkflowInputSchema,
306
568
  execute: async (input) => {
@@ -344,16 +606,16 @@ function createWorkflowTools(config) {
344
606
  }
345
607
  }
346
608
  });
347
- const generateWorkflowSpecCodeInputSchema = z.object({
348
- workflowKey: z.string().describe("Workflow meta.key"),
349
- composedSteps: z.array(z.object({
350
- id: z.string(),
351
- type: z.enum(["human", "automation", "decision"]),
352
- label: z.string(),
353
- description: z.string().optional()
609
+ const generateWorkflowSpecCodeInputSchema = z3.object({
610
+ workflowKey: z3.string().describe("Workflow meta.key"),
611
+ composedSteps: z3.array(z3.object({
612
+ id: z3.string(),
613
+ type: z3.enum(["human", "automation", "decision"]),
614
+ label: z3.string(),
615
+ description: z3.string().optional()
354
616
  })).optional().describe("Steps to include; if omitted, uses the base workflow")
355
617
  });
356
- const generateWorkflowSpecCodeTool = tool({
618
+ const generateWorkflowSpecCodeTool = tool3({
357
619
  description: "Generate TypeScript code for a workflow spec. Use after composing a workflow to output the spec as code the user can save.",
358
620
  inputSchema: generateWorkflowSpecCodeInputSchema,
359
621
  execute: async (input) => {
@@ -418,254 +680,7 @@ function escapeString(value) {
418
680
  return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
419
681
  }
420
682
 
421
- // src/core/contracts-context.ts
422
- function buildContractsContextPrompt(config) {
423
- const parts = [];
424
- if (!config.agentSpecs?.length && !config.dataViewSpecs?.length && !config.formSpecs?.length && !config.presentationSpecs?.length && !config.operationRefs?.length) {
425
- return "";
426
- }
427
- parts.push(`
428
-
429
- ## Available resources`);
430
- if (config.agentSpecs?.length) {
431
- parts.push(`
432
- ### Agent tools`);
433
- for (const agent of config.agentSpecs) {
434
- const toolNames = agent.tools?.map((t) => t.name).join(", ") ?? "none";
435
- parts.push(`- **${agent.key}**: tools: ${toolNames}`);
436
- }
437
- }
438
- if (config.dataViewSpecs?.length) {
439
- parts.push(`
440
- ### Data views`);
441
- for (const dv of config.dataViewSpecs) {
442
- parts.push(`- **${dv.key}**: ${dv.meta.title ?? dv.key}`);
443
- }
444
- }
445
- if (config.formSpecs?.length) {
446
- parts.push(`
447
- ### Forms`);
448
- for (const form of config.formSpecs) {
449
- parts.push(`- **${form.key}**: ${form.meta.title ?? form.key}`);
450
- }
451
- }
452
- if (config.presentationSpecs?.length) {
453
- parts.push(`
454
- ### Presentations`);
455
- for (const pres of config.presentationSpecs) {
456
- parts.push(`- **${pres.key}**: ${pres.meta.title ?? pres.key} (targets: ${pres.targets?.join(", ") ?? "react"})`);
457
- }
458
- }
459
- if (config.operationRefs?.length) {
460
- parts.push(`
461
- ### Operations`);
462
- for (const op of config.operationRefs) {
463
- parts.push(`- **${op.key}@${op.version}**`);
464
- }
465
- }
466
- parts.push(`
467
- Use the available tools to invoke operations, query data views, or propose surface changes when appropriate.`);
468
- return parts.join(`
469
- `);
470
- }
471
-
472
- // src/core/agent-tools-adapter.ts
473
- import { tool as tool2 } from "ai";
474
- import { z as z2 } from "zod";
475
- function getInputSchema(_schema) {
476
- return z2.object({}).passthrough();
477
- }
478
- function agentToolConfigsToToolSet(configs, handlers) {
479
- const result = {};
480
- for (const config of configs) {
481
- const handler = handlers?.[config.name];
482
- const inputSchema = getInputSchema(config.schema);
483
- result[config.name] = tool2({
484
- description: config.description ?? config.name,
485
- inputSchema,
486
- execute: async (input) => {
487
- if (!handler) {
488
- return {
489
- status: "unimplemented",
490
- message: "Wire handler in host",
491
- toolName: config.name
492
- };
493
- }
494
- try {
495
- const output = await Promise.resolve(handler(input));
496
- return typeof output === "string" ? output : output;
497
- } catch (err) {
498
- return {
499
- status: "error",
500
- error: err instanceof Error ? err.message : String(err),
501
- toolName: config.name
502
- };
503
- }
504
- }
505
- });
506
- }
507
- return result;
508
- }
509
-
510
- // src/core/surface-planner-tools.ts
511
- import { tool as tool3 } from "ai";
512
- import { z as z3 } from "zod";
513
- import {
514
- validatePatchProposal
515
- } from "@contractspec/lib.surface-runtime/spec/validate-surface-patch";
516
- import { buildSurfacePatchProposal } from "@contractspec/lib.surface-runtime/runtime/planner-tools";
517
- var VALID_OPS = [
518
- "insert-node",
519
- "replace-node",
520
- "remove-node",
521
- "move-node",
522
- "resize-panel",
523
- "set-layout",
524
- "reveal-field",
525
- "hide-field",
526
- "promote-action",
527
- "set-focus"
528
- ];
529
- var DEFAULT_NODE_KINDS = [
530
- "entity-section",
531
- "entity-card",
532
- "data-view",
533
- "assistant-panel",
534
- "chat-thread",
535
- "action-bar",
536
- "timeline",
537
- "table",
538
- "rich-doc",
539
- "form",
540
- "chart",
541
- "custom-widget"
542
- ];
543
- function collectSlotIdsFromRegion(node) {
544
- const ids = [];
545
- if (node.type === "slot") {
546
- ids.push(node.slotId);
547
- }
548
- if (node.type === "panel-group" || node.type === "stack") {
549
- for (const child of node.children) {
550
- ids.push(...collectSlotIdsFromRegion(child));
551
- }
552
- }
553
- if (node.type === "tabs") {
554
- for (const tab of node.tabs) {
555
- ids.push(...collectSlotIdsFromRegion(tab.child));
556
- }
557
- }
558
- if (node.type === "floating") {
559
- ids.push(node.anchorSlotId);
560
- ids.push(...collectSlotIdsFromRegion(node.child));
561
- }
562
- return ids;
563
- }
564
- function deriveConstraints(plan) {
565
- const slotIds = collectSlotIdsFromRegion(plan.layoutRoot);
566
- const uniqueSlots = [...new Set(slotIds)];
567
- return {
568
- allowedOps: VALID_OPS,
569
- allowedSlots: uniqueSlots.length > 0 ? uniqueSlots : ["assistant", "primary"],
570
- allowedNodeKinds: DEFAULT_NODE_KINDS
571
- };
572
- }
573
- var ProposePatchInputSchema = z3.object({
574
- proposalId: z3.string().describe("Unique proposal identifier"),
575
- ops: z3.array(z3.object({
576
- op: z3.enum([
577
- "insert-node",
578
- "replace-node",
579
- "remove-node",
580
- "move-node",
581
- "resize-panel",
582
- "set-layout",
583
- "reveal-field",
584
- "hide-field",
585
- "promote-action",
586
- "set-focus"
587
- ]),
588
- slotId: z3.string().optional(),
589
- nodeId: z3.string().optional(),
590
- toSlotId: z3.string().optional(),
591
- index: z3.number().optional(),
592
- node: z3.object({
593
- nodeId: z3.string(),
594
- kind: z3.string(),
595
- title: z3.string().optional(),
596
- props: z3.record(z3.string(), z3.unknown()).optional(),
597
- children: z3.array(z3.unknown()).optional()
598
- }).optional(),
599
- persistKey: z3.string().optional(),
600
- sizes: z3.array(z3.number()).optional(),
601
- layoutId: z3.string().optional(),
602
- fieldId: z3.string().optional(),
603
- actionId: z3.string().optional(),
604
- placement: z3.enum(["header", "inline", "context", "assistant"]).optional(),
605
- targetId: z3.string().optional()
606
- }))
607
- });
608
- function createSurfacePlannerTools(config) {
609
- const { plan, constraints, onPatchProposal } = config;
610
- const resolvedConstraints = constraints ?? deriveConstraints(plan);
611
- const proposePatchTool = tool3({
612
- description: "Propose surface patches (layout changes, node insertions, etc.) for user approval. " + "Only use allowed ops, slots, and node kinds from the planner context.",
613
- inputSchema: ProposePatchInputSchema,
614
- execute: async (input) => {
615
- const ops = input.ops;
616
- try {
617
- validatePatchProposal(ops, resolvedConstraints);
618
- const proposal = buildSurfacePatchProposal(input.proposalId, ops);
619
- onPatchProposal?.(proposal);
620
- return {
621
- success: true,
622
- proposalId: proposal.proposalId,
623
- opsCount: proposal.ops.length,
624
- message: "Patch proposal validated; awaiting user approval"
625
- };
626
- } catch (err) {
627
- return {
628
- success: false,
629
- error: err instanceof Error ? err.message : String(err),
630
- proposalId: input.proposalId
631
- };
632
- }
633
- }
634
- });
635
- return {
636
- "propose-patch": proposePatchTool
637
- };
638
- }
639
- function buildPlannerPromptInput(plan) {
640
- const constraints = deriveConstraints(plan);
641
- return {
642
- bundleMeta: {
643
- key: plan.bundleKey,
644
- version: "0.0.0",
645
- title: plan.bundleKey
646
- },
647
- surfaceId: plan.surfaceId,
648
- allowedPatchOps: constraints.allowedOps,
649
- allowedSlots: [...constraints.allowedSlots],
650
- allowedNodeKinds: [...constraints.allowedNodeKinds],
651
- actions: plan.actions.map((a) => ({
652
- actionId: a.actionId,
653
- title: a.title
654
- })),
655
- preferences: {
656
- guidance: "hints",
657
- density: "standard",
658
- dataDepth: "detailed",
659
- control: "standard",
660
- media: "text",
661
- pace: "balanced",
662
- narrative: "top-down"
663
- }
664
- };
665
- }
666
-
667
683
  // src/core/chat-service.ts
668
- import { compilePlannerPrompt } from "@contractspec/lib.surface-runtime/runtime/planner-prompt";
669
684
  var DEFAULT_SYSTEM_PROMPT = `You are ContractSpec AI, an expert coding assistant specialized in ContractSpec development.
670
685
 
671
686
  Your capabilities:
@@ -1607,20 +1622,6 @@ class LocalStorageConversationStore {
1607
1622
  function createLocalStorageConversationStore(storageKey) {
1608
1623
  return new LocalStorageConversationStore(storageKey);
1609
1624
  }
1610
- // src/core/agent-adapter.ts
1611
- function createChatAgentAdapter(agent) {
1612
- return {
1613
- async generate({ prompt, signal }) {
1614
- const result = await agent.generate({ prompt, signal });
1615
- return {
1616
- text: result.text,
1617
- toolCalls: result.toolCalls,
1618
- toolResults: result.toolResults,
1619
- usage: result.usage
1620
- };
1621
- }
1622
- };
1623
- }
1624
1625
  export {
1625
1626
  getProviderOptions,
1626
1627
  getExportFilename,