@contractspec/module.ai-chat 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +130 -10
  2. package/dist/adapters/ai-sdk-bundle-adapter.d.ts +18 -0
  3. package/dist/adapters/index.d.ts +4 -0
  4. package/dist/browser/core/index.js +1138 -21
  5. package/dist/browser/index.js +2816 -651
  6. package/dist/browser/presentation/components/index.js +3143 -358
  7. package/dist/browser/presentation/hooks/index.js +961 -43
  8. package/dist/browser/presentation/index.js +2784 -666
  9. package/dist/core/agent-adapter.d.ts +53 -0
  10. package/dist/core/agent-tools-adapter.d.ts +12 -0
  11. package/dist/core/chat-service.d.ts +49 -1
  12. package/dist/core/contracts-context.d.ts +46 -0
  13. package/dist/core/contracts-context.test.d.ts +1 -0
  14. package/dist/core/conversation-store.d.ts +16 -2
  15. package/dist/core/create-chat-route.d.ts +3 -0
  16. package/dist/core/export-formatters.d.ts +29 -0
  17. package/dist/core/export-formatters.test.d.ts +1 -0
  18. package/dist/core/index.d.ts +8 -0
  19. package/dist/core/index.js +1138 -21
  20. package/dist/core/local-storage-conversation-store.d.ts +33 -0
  21. package/dist/core/message-types.d.ts +6 -0
  22. package/dist/core/surface-planner-tools.d.ts +23 -0
  23. package/dist/core/surface-planner-tools.test.d.ts +1 -0
  24. package/dist/core/thinking-levels.d.ts +38 -0
  25. package/dist/core/thinking-levels.test.d.ts +1 -0
  26. package/dist/core/workflow-tools.d.ts +18 -0
  27. package/dist/core/workflow-tools.test.d.ts +1 -0
  28. package/dist/index.d.ts +4 -2
  29. package/dist/index.js +2816 -651
  30. package/dist/node/core/index.js +1138 -21
  31. package/dist/node/index.js +2816 -651
  32. package/dist/node/presentation/components/index.js +3143 -358
  33. package/dist/node/presentation/hooks/index.js +961 -43
  34. package/dist/node/presentation/index.js +2787 -669
  35. package/dist/presentation/components/ChatContainer.d.ts +3 -1
  36. package/dist/presentation/components/ChatExportToolbar.d.ts +25 -0
  37. package/dist/presentation/components/ChatMessage.d.ts +16 -1
  38. package/dist/presentation/components/ChatSidebar.d.ts +26 -0
  39. package/dist/presentation/components/ChatWithExport.d.ts +34 -0
  40. package/dist/presentation/components/ChatWithSidebar.d.ts +19 -0
  41. package/dist/presentation/components/ThinkingLevelPicker.d.ts +16 -0
  42. package/dist/presentation/components/ToolResultRenderer.d.ts +33 -0
  43. package/dist/presentation/components/index.d.ts +6 -0
  44. package/dist/presentation/components/index.js +3143 -358
  45. package/dist/presentation/hooks/index.d.ts +2 -0
  46. package/dist/presentation/hooks/index.js +961 -43
  47. package/dist/presentation/hooks/useChat.d.ts +44 -2
  48. package/dist/presentation/hooks/useConversations.d.ts +18 -0
  49. package/dist/presentation/hooks/useMessageSelection.d.ts +13 -0
  50. package/dist/presentation/index.js +2787 -669
  51. package/package.json +14 -18
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Adapter interface for agent mode in ai-chat.
3
+ * Allows ContractSpecAgent or UnifiedAgent to be used as the chat backend.
4
+ */
5
+ export interface ChatAgentAdapter {
6
+ generate(params: {
7
+ prompt: string;
8
+ signal?: AbortSignal;
9
+ }): Promise<{
10
+ text: string;
11
+ toolCalls?: Array<{
12
+ toolCallId: string;
13
+ toolName: string;
14
+ args: unknown;
15
+ }>;
16
+ toolResults?: Array<{
17
+ toolCallId: string;
18
+ toolName: string;
19
+ output: unknown;
20
+ }>;
21
+ usage?: {
22
+ inputTokens: number;
23
+ outputTokens: number;
24
+ };
25
+ }>;
26
+ }
27
+ /**
28
+ * Wraps a ContractSpecAgent or similar agent for use with useChat agent mode.
29
+ * Maps AgentGenerateResult to ChatAgentAdapter format.
30
+ */
31
+ export declare function createChatAgentAdapter(agent: {
32
+ generate(params: {
33
+ prompt: string;
34
+ systemOverride?: string;
35
+ signal?: AbortSignal;
36
+ }): Promise<{
37
+ text: string;
38
+ toolCalls?: Array<{
39
+ toolCallId: string;
40
+ toolName: string;
41
+ args: unknown;
42
+ }>;
43
+ toolResults?: Array<{
44
+ toolCallId: string;
45
+ toolName: string;
46
+ output: unknown;
47
+ }>;
48
+ usage?: {
49
+ inputTokens: number;
50
+ outputTokens: number;
51
+ };
52
+ }>;
53
+ }): ChatAgentAdapter;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Converts AgentToolConfig from ai-agent to AI SDK ToolSet.
3
+ * Handlers are optional; when missing, execute returns unimplemented stub.
4
+ */
5
+ import { type ToolSet } from 'ai';
6
+ import type { AgentToolConfig } from '@contractspec/lib.ai-agent';
7
+ export type ToolHandler = (input: Record<string, unknown>) => Promise<unknown> | unknown;
8
+ /**
9
+ * Convert AgentToolConfig array to AI SDK ToolSet.
10
+ * When handler is missing, execute returns { status: 'unimplemented', message: 'Wire handler in host' }.
11
+ */
12
+ export declare function agentToolConfigsToToolSet(configs: AgentToolConfig[], handlers?: Record<string, ToolHandler>): ToolSet;
@@ -3,9 +3,15 @@
3
3
  */
4
4
  import { type ToolSet } from 'ai';
5
5
  import type { Provider as ChatProvider } from '@contractspec/lib.ai-providers';
6
+ import type { ModelSelector } from '@contractspec/lib.ai-providers/selector-types';
7
+ import type { WorkflowComposer } from '@contractspec/lib.workflow-composer';
8
+ import type { WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow';
6
9
  import type { WorkspaceContext } from '../context/workspace-context';
7
10
  import type { ConversationStore } from './conversation-store';
8
- import type { ChatConversation, SendMessageOptions, SendMessageResult, StreamMessageResult } from './message-types';
11
+ import { type ThinkingLevel } from './thinking-levels';
12
+ import { type ContractsContextConfig } from './contracts-context';
13
+ import type { ResolvedSurfacePlan } from '@contractspec/lib.surface-runtime/runtime/resolve-bundle';
14
+ import type { ChatConversation, ChatMessage, SendMessageOptions, SendMessageResult, StreamMessageResult } from './message-types';
9
15
  /**
10
16
  * Configuration for ChatService
11
17
  */
@@ -33,10 +39,28 @@ export interface ChatServiceConfig {
33
39
  authHeaders?: Record<string, string>;
34
40
  /** Tools for the model to call (AI SDK ToolSet) */
35
41
  tools?: ToolSet;
42
+ /** Thinking level: instant, thinking, extra_thinking, max. Maps to provider reasoning options. */
43
+ thinkingLevel?: ThinkingLevel;
36
44
  /** Enable reasoning parts in stream (Deepseek R1, Claude extended thinking) */
37
45
  sendReasoning?: boolean;
38
46
  /** Enable source citations in stream (e.g. Perplexity Sonar) */
39
47
  sendSources?: boolean;
48
+ /** Workflow creation tools: base workflows and optional composer */
49
+ workflowToolsConfig?: {
50
+ baseWorkflows: WorkflowSpec[];
51
+ composer?: WorkflowComposer;
52
+ };
53
+ /** Optional model selector for dynamic model selection by task dimension */
54
+ modelSelector?: ModelSelector;
55
+ /** Contracts-spec context: agent, data-views, operations, forms, presentations */
56
+ contractsContext?: ContractsContextConfig;
57
+ /** Surface plan config: enables propose-patch tool when used in surface-runtime */
58
+ surfacePlanConfig?: {
59
+ plan: ResolvedSurfacePlan;
60
+ onPatchProposal?: (proposal: import('@contractspec/lib.surface-runtime/spec/types').SurfacePatchProposal) => void;
61
+ };
62
+ /** MCP tools (from createMcpToolsets); merged when provided */
63
+ mcpTools?: ToolSet;
40
64
  }
41
65
  /**
42
66
  * Main chat service for AI-powered conversations
@@ -49,9 +73,15 @@ export declare class ChatService {
49
73
  private readonly maxHistoryMessages;
50
74
  private readonly onUsage?;
51
75
  private readonly tools?;
76
+ private readonly thinkingLevel?;
52
77
  private readonly sendReasoning;
53
78
  private readonly sendSources;
79
+ private readonly modelSelector?;
54
80
  constructor(config: ChatServiceConfig);
81
+ private buildSystemPrompt;
82
+ private mergeTools;
83
+ private resolveModel;
84
+ private thinkingLevelToDimension;
55
85
  /**
56
86
  * Send a message and get a complete response
57
87
  */
@@ -68,9 +98,27 @@ export declare class ChatService {
68
98
  * List conversations
69
99
  */
70
100
  listConversations(options?: {
101
+ projectId?: string;
102
+ tags?: string[];
71
103
  limit?: number;
72
104
  offset?: number;
73
105
  }): Promise<ChatConversation[]>;
106
+ /**
107
+ * Update conversation properties (title, project, tags, etc.)
108
+ */
109
+ updateConversation(conversationId: string, updates: Parameters<ConversationStore['update']>[1]): Promise<ChatConversation | null>;
110
+ /**
111
+ * Fork a conversation, optionally up to a specific message
112
+ */
113
+ forkConversation(conversationId: string, upToMessageId?: string): Promise<ChatConversation>;
114
+ /**
115
+ * Update a message in a conversation
116
+ */
117
+ updateMessage(conversationId: string, messageId: string, updates: Partial<ChatMessage>): Promise<ChatMessage | null>;
118
+ /**
119
+ * Truncate messages after the given message (for edit/regenerate)
120
+ */
121
+ truncateAfter(conversationId: string, messageId: string): Promise<ChatConversation | null>;
74
122
  /**
75
123
  * Delete a conversation
76
124
  */
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Contracts-spec context for ai-chat.
3
+ * Exposes agent, data-views, operations, forms, and presentations to the model.
4
+ */
5
+ import type { AgentToolConfig } from '@contractspec/lib.ai-agent';
6
+ export interface ContractsContextConfig {
7
+ /** Agent specs (for tool schemas, instructions) */
8
+ agentSpecs?: Array<{
9
+ key: string;
10
+ tools?: AgentToolConfig[];
11
+ }>;
12
+ /** Data view specs (for query suggestions, filters) */
13
+ dataViewSpecs?: Array<{
14
+ key: string;
15
+ meta: {
16
+ title?: string;
17
+ };
18
+ source?: unknown;
19
+ }>;
20
+ /** Form specs (for rendering or generating form configs) */
21
+ formSpecs?: Array<{
22
+ key: string;
23
+ meta: {
24
+ title?: string;
25
+ };
26
+ fields?: unknown[];
27
+ }>;
28
+ /** Presentation specs (for rendering tool outputs) */
29
+ presentationSpecs?: Array<{
30
+ key: string;
31
+ meta: {
32
+ title?: string;
33
+ };
34
+ targets?: string[];
35
+ }>;
36
+ /** Operation refs the chat can invoke via tools */
37
+ operationRefs?: Array<{
38
+ key: string;
39
+ version: string;
40
+ }>;
41
+ }
42
+ /**
43
+ * Builds a prompt section describing available contracts-spec resources.
44
+ * Append to system prompt when contractsContext is set.
45
+ */
46
+ export declare function buildContractsContextPrompt(config: ContractsContextConfig): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -17,7 +17,7 @@ export interface ConversationStore {
17
17
  /**
18
18
  * Update conversation properties
19
19
  */
20
- update(conversationId: string, updates: Partial<Pick<ChatConversation, 'title' | 'status' | 'summary' | 'metadata'>>): Promise<ChatConversation | null>;
20
+ update(conversationId: string, updates: Partial<Pick<ChatConversation, 'title' | 'status' | 'summary' | 'metadata' | 'projectId' | 'projectName' | 'tags'>>): Promise<ChatConversation | null>;
21
21
  /**
22
22
  * Append a message to a conversation
23
23
  */
@@ -35,9 +35,19 @@ export interface ConversationStore {
35
35
  */
36
36
  list(options?: {
37
37
  status?: ConversationStatus;
38
+ projectId?: string;
39
+ tags?: string[];
38
40
  limit?: number;
39
41
  offset?: number;
40
42
  }): Promise<ChatConversation[]>;
43
+ /**
44
+ * Fork a conversation, optionally up to a specific message
45
+ */
46
+ fork(conversationId: string, upToMessageId?: string): Promise<ChatConversation>;
47
+ /**
48
+ * Remove all messages after the given message (for edit/regenerate flow)
49
+ */
50
+ truncateAfter(conversationId: string, messageId: string): Promise<ChatConversation | null>;
41
51
  /**
42
52
  * Search conversations by content
43
53
  */
@@ -50,15 +60,19 @@ export declare class InMemoryConversationStore implements ConversationStore {
50
60
  private readonly conversations;
51
61
  get(conversationId: string): Promise<ChatConversation | null>;
52
62
  create(conversation: Omit<ChatConversation, 'id' | 'createdAt' | 'updatedAt'>): Promise<ChatConversation>;
53
- update(conversationId: string, updates: Partial<Pick<ChatConversation, 'title' | 'status' | 'summary' | 'metadata'>>): Promise<ChatConversation | null>;
63
+ update(conversationId: string, updates: Partial<Pick<ChatConversation, 'title' | 'status' | 'summary' | 'metadata' | 'projectId' | 'projectName' | 'tags'>>): Promise<ChatConversation | null>;
54
64
  appendMessage(conversationId: string, message: Omit<ChatMessage, 'id' | 'conversationId' | 'createdAt' | 'updatedAt'>): Promise<ChatMessage>;
55
65
  updateMessage(conversationId: string, messageId: string, updates: Partial<ChatMessage>): Promise<ChatMessage | null>;
56
66
  delete(conversationId: string): Promise<boolean>;
57
67
  list(options?: {
58
68
  status?: ConversationStatus;
69
+ projectId?: string;
70
+ tags?: string[];
59
71
  limit?: number;
60
72
  offset?: number;
61
73
  }): Promise<ChatConversation[]>;
74
+ fork(conversationId: string, upToMessageId?: string): Promise<ChatConversation>;
75
+ truncateAfter(conversationId: string, messageId: string): Promise<ChatConversation | null>;
62
76
  search(query: string, limit?: number): Promise<ChatConversation[]>;
63
77
  /**
64
78
  * Clear all conversations (for testing)
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { type ToolSet } from 'ai';
17
17
  import type { Provider as ChatProvider } from '@contractspec/lib.ai-providers';
18
+ import type { ThinkingLevel } from './thinking-levels';
18
19
  export interface CreateChatRouteOptions {
19
20
  /** LLM provider (from createProvider) */
20
21
  provider: ChatProvider;
@@ -22,6 +23,8 @@ export interface CreateChatRouteOptions {
22
23
  systemPrompt?: string;
23
24
  /** Tools for the model */
24
25
  tools?: ToolSet;
26
+ /** Default thinking level (can be overridden by request body) */
27
+ thinkingLevel?: ThinkingLevel;
25
28
  }
26
29
  /**
27
30
  * Create a route handler that streams chat using streamText + toUIMessageStreamResponse.
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Export formatters for chat conversations
3
+ * Pure functions to convert ChatMessage[] to Markdown, TXT, or JSON.
4
+ */
5
+ import type { ChatMessage, ChatConversation } from './message-types';
6
+ /**
7
+ * Format messages as Markdown
8
+ */
9
+ export declare function formatMessagesAsMarkdown(messages: ChatMessage[]): string;
10
+ /**
11
+ * Format messages as plain text
12
+ */
13
+ export declare function formatMessagesAsTxt(messages: ChatMessage[]): string;
14
+ /**
15
+ * Format messages as JSON with optional conversation metadata
16
+ */
17
+ export declare function formatMessagesAsJson(messages: ChatMessage[], conversation?: ChatConversation | null): string;
18
+ /**
19
+ * Generate export filename
20
+ */
21
+ export declare function getExportFilename(format: 'markdown' | 'txt' | 'json', conversation?: ChatConversation | null): string;
22
+ /**
23
+ * Download content as a file
24
+ */
25
+ export declare function downloadAsFile(content: string, filename: string, mimeType: string): void;
26
+ /**
27
+ * Export messages to a file (convenience helper)
28
+ */
29
+ export declare function exportToFile(messages: ChatMessage[], format: 'markdown' | 'txt' | 'json', conversation?: ChatConversation | null): void;
@@ -0,0 +1 @@
1
+ export {};
@@ -6,3 +6,11 @@ export * from './conversation-store';
6
6
  export * from './chat-service';
7
7
  export * from './create-chat-route';
8
8
  export * from './create-completion-route';
9
+ export * from './export-formatters';
10
+ export * from './local-storage-conversation-store';
11
+ export * from './thinking-levels';
12
+ export * from './workflow-tools';
13
+ export * from './contracts-context';
14
+ export * from './agent-tools-adapter';
15
+ export * from './surface-planner-tools';
16
+ export * from './agent-adapter';