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