@contractspec/module.ai-chat 4.3.6 → 4.3.10
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
package/dist/node/core/index.js
CHANGED
|
@@ -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
|
-
|
|
164
|
-
|
|
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
|
-
|
|
222
|
-
|
|
481
|
+
validateExtension,
|
|
482
|
+
WorkflowComposer
|
|
223
483
|
} from "@contractspec/lib.workflow-composer";
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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:
|
|
231
|
-
key:
|
|
232
|
-
version:
|
|
492
|
+
form: z3.object({
|
|
493
|
+
key: z3.string(),
|
|
494
|
+
version: z3.number()
|
|
233
495
|
}).optional()
|
|
234
496
|
}).optional();
|
|
235
|
-
var StepSchema =
|
|
236
|
-
id:
|
|
497
|
+
var StepSchema = z3.object({
|
|
498
|
+
id: z3.string(),
|
|
237
499
|
type: StepTypeSchema,
|
|
238
|
-
label:
|
|
239
|
-
description:
|
|
500
|
+
label: z3.string(),
|
|
501
|
+
description: z3.string().optional(),
|
|
240
502
|
action: StepActionSchema
|
|
241
503
|
});
|
|
242
|
-
var StepInjectionSchema =
|
|
243
|
-
after:
|
|
244
|
-
before:
|
|
504
|
+
var StepInjectionSchema = z3.object({
|
|
505
|
+
after: z3.string().optional(),
|
|
506
|
+
before: z3.string().optional(),
|
|
245
507
|
inject: StepSchema,
|
|
246
|
-
transitionTo:
|
|
247
|
-
transitionFrom:
|
|
248
|
-
when:
|
|
508
|
+
transitionTo: z3.string().optional(),
|
|
509
|
+
transitionFrom: z3.string().optional(),
|
|
510
|
+
when: z3.string().optional()
|
|
249
511
|
});
|
|
250
|
-
var WorkflowExtensionInputSchema =
|
|
251
|
-
workflow:
|
|
252
|
-
tenantId:
|
|
253
|
-
role:
|
|
254
|
-
priority:
|
|
255
|
-
customSteps:
|
|
256
|
-
hiddenSteps:
|
|
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 =
|
|
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 =
|
|
298
|
-
workflowKey:
|
|
299
|
-
tenantId:
|
|
300
|
-
role:
|
|
301
|
-
extensions:
|
|
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 =
|
|
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 =
|
|
348
|
-
workflowKey:
|
|
349
|
-
composedSteps:
|
|
350
|
-
id:
|
|
351
|
-
type:
|
|
352
|
-
label:
|
|
353
|
-
description:
|
|
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 =
|
|
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,
|