@maintainer-pro/ai-cli 0.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.
@@ -0,0 +1,239 @@
1
+ import { z } from 'zod';
2
+
3
+ type AiCliProviderId = "claude" | "cursor" | "antigravity" | (string & {});
4
+ interface ToolCall {
5
+ tool: string;
6
+ args: Record<string, unknown>;
7
+ }
8
+ interface AiResponse {
9
+ text: string;
10
+ toolCalls: ToolCall[];
11
+ provider: string;
12
+ }
13
+ interface ChatAttachment {
14
+ /** Original filename, e.g. screenshot.png */
15
+ name: string;
16
+ mimeType: string;
17
+ /** Raw base64 (no data: URL prefix). */
18
+ data: string;
19
+ }
20
+ interface ChatMessage {
21
+ role: "user" | "assistant";
22
+ content: string;
23
+ }
24
+ /** Sender roles for the shared client / developer / AI chat panel. */
25
+ type ChatSenderType = "client" | "developer" | "ai";
26
+ interface ChatUser {
27
+ name: string;
28
+ type: ChatSenderType;
29
+ /** When true, this user is selected by default in the composer (client/developer only). */
30
+ default?: boolean;
31
+ /** Login email when users come from Maintainer Pro. */
32
+ email?: string;
33
+ /** Org role from Maintainer Pro (owner, admin, staff, member, …). */
34
+ role?: string;
35
+ }
36
+ /** Live UI / app snapshot sent with each chat request (host-defined). */
37
+ interface ClientContext {
38
+ route: string;
39
+ pageTitle: string;
40
+ visiblePanels?: string[];
41
+ focusedElement?: string | null;
42
+ relevantFiles?: string[];
43
+ /** Arbitrary host app state (tasks, stats, form values, etc.). */
44
+ data?: Record<string, unknown>;
45
+ }
46
+ interface CallAiOptions {
47
+ systemPrompt: string;
48
+ workspaceDir?: string;
49
+ providerPreference?: "auto" | "claude" | "cursor" | "antigravity";
50
+ /** Absolute paths to screenshot/image files the agent should inspect. */
51
+ attachmentPaths?: string[];
52
+ /**
53
+ * Compact excerpts from other `.maintainer-pro/chat` conversations.
54
+ * Injected into the prompt for the model to use when relevant.
55
+ */
56
+ priorConversationsContext?: string;
57
+ /** Extra / override providers (e.g. future HTTP model backends). */
58
+ providers?: AiProvider[];
59
+ }
60
+ interface AiProvider {
61
+ id: string;
62
+ label: string;
63
+ /** Return true if this provider can run in the current environment. */
64
+ isAvailable(): Promise<boolean>;
65
+ call(messages: ChatMessage[], context: ClientContext | undefined, options: CallAiOptions): Promise<AiResponse>;
66
+ }
67
+
68
+ declare function callAi(messages: ChatMessage[], context: ClientContext | undefined, options: CallAiOptions): Promise<AiResponse>;
69
+
70
+ type ProviderPreference = "auto" | "claude" | "cursor" | "antigravity";
71
+ type BuiltinProviderId = "claude" | "cursor" | "antigravity";
72
+ declare function commandExists(command: string): Promise<boolean>;
73
+ declare function getProviderPreference(override?: ProviderPreference): ProviderPreference;
74
+ declare function resolveCliBinary(provider: BuiltinProviderId): Promise<string | null>;
75
+ declare function createBuiltinProviders(): AiProvider[];
76
+ declare function resolveProvider(options?: {
77
+ preference?: ProviderPreference;
78
+ providers?: AiProvider[];
79
+ }): Promise<AiProvider>;
80
+ declare function providerLabel(providerId: string): string;
81
+
82
+ /** Extract ```json ... ``` tool blocks and strip them from assistant text. */
83
+ declare function parseAiResponse(raw: string, provider: AiCliProviderId): AiResponse;
84
+
85
+ declare function buildConversationPrompt(messages: ChatMessage[]): string;
86
+ declare function formatClientContext(context?: ClientContext): string;
87
+ /** Full prompt for providers without a native --system-prompt flag (Cursor). */
88
+ declare function buildCursorPrompt(systemPrompt: string, messages: ChatMessage[], context?: ClientContext, attachmentPaths?: string[], priorConversationsContext?: string): string;
89
+ /** Conversation + context for Claude (system prompt passed separately). */
90
+ declare function buildClaudeUserPrompt(messages: ChatMessage[], context?: ClientContext, attachmentPaths?: string[], priorConversationsContext?: string): string;
91
+
92
+ declare function createDefaultSystemPrompt(input: {
93
+ productDescription: string;
94
+ relevantFilesHint?: string;
95
+ runtimeToolsHint?: string;
96
+ }): string;
97
+
98
+ declare function createClaudeProvider(): AiProvider;
99
+
100
+ declare function createCursorProvider(): AiProvider;
101
+
102
+ declare function createAntigravityProvider(): AiProvider;
103
+
104
+ type ToolSchemaMap = Record<string, z.ZodTypeAny>;
105
+ declare function createToolValidator(schemas: ToolSchemaMap): (toolCall: ToolCall) => {
106
+ valid: true;
107
+ name: string;
108
+ args: Record<string, unknown>;
109
+ } | {
110
+ valid: false;
111
+ error: string;
112
+ };
113
+
114
+ /** Minimal persistence contract (file store, SQL, or Maintainer Pro). */
115
+ interface ChatStoreLike {
116
+ ensureConversation(id: string): Promise<void>;
117
+ saveMessage(input: {
118
+ conversationId: string;
119
+ role: "user" | "assistant" | "system";
120
+ content: string;
121
+ provider?: string;
122
+ attachmentPaths?: string[];
123
+ senderType?: "client" | "developer" | "ai";
124
+ senderName?: string;
125
+ }): Promise<unknown>;
126
+ listMessages?(conversationId: string): Promise<Array<{
127
+ id: string;
128
+ role: string;
129
+ content: string;
130
+ provider?: string | null;
131
+ createdAt?: string | Date;
132
+ attachmentPaths?: string[];
133
+ senderType?: "client" | "developer" | "ai" | null;
134
+ senderName?: string | null;
135
+ }>>;
136
+ /** All conversations under the store (for prior-chat context). */
137
+ listConversations?(): Promise<Array<{
138
+ id: string;
139
+ updatedAt: string;
140
+ messages: Array<{
141
+ role: string;
142
+ content: string;
143
+ createdAt?: string | Date;
144
+ }>;
145
+ }>>;
146
+ saveToolEvents?(conversationId: string, events: Array<{
147
+ tool: string;
148
+ args: Record<string, unknown>;
149
+ }>): Promise<void>;
150
+ /**
151
+ * Optional remote/local upload hook. When present, chat images are persisted
152
+ * through the store instead of `.maintainer-pro/uploads`.
153
+ * `localPaths` are absolute paths for CLI inspection; `refs` are stored on messages.
154
+ */
155
+ uploadAttachments?(conversationId: string, attachments: ChatAttachment[] | undefined): Promise<{
156
+ refs: string[];
157
+ localPaths: string[];
158
+ }>;
159
+ }
160
+ interface ChatHandlerOptions {
161
+ systemPrompt: string;
162
+ workspaceDir?: string;
163
+ providerPreference?: CallAiOptions["providerPreference"];
164
+ providers?: AiProvider[];
165
+ tools?: ToolSchemaMap;
166
+ db?: ChatStoreLike;
167
+ conversationId?: string | ((request: Request) => string | undefined);
168
+ onToolCalls?: (toolCalls: ToolCall[], context?: ClientContext) => void | Promise<void>;
169
+ }
170
+ interface ChatHandlers {
171
+ GET: (request: Request) => Promise<Response>;
172
+ POST: (request: Request) => Promise<Response>;
173
+ }
174
+ declare function createChatHandler(options: ChatHandlerOptions): ChatHandlers;
175
+ declare function toNextRoute(handlers: ChatHandlers): {
176
+ GET: (request: Request) => Promise<Response>;
177
+ POST: (request: Request) => Promise<Response>;
178
+ };
179
+
180
+ /** Persist chat image attachments under the workspace and return absolute paths. */
181
+ declare function saveChatAttachments(attachments: ChatAttachment[] | undefined, workspaceDir: string): Promise<string[]>;
182
+
183
+ interface LocalStoredMessage {
184
+ id: string;
185
+ conversationId: string;
186
+ role: "user" | "assistant" | "system";
187
+ content: string;
188
+ provider: string | null;
189
+ createdAt: string;
190
+ attachmentPaths?: string[];
191
+ senderType?: "client" | "developer" | "ai" | null;
192
+ senderName?: string | null;
193
+ }
194
+ /**
195
+ * Persist conversations as JSON files under a local directory.
196
+ * Layout: `{baseDir}/{conversationId}.json`
197
+ */
198
+ declare function createLocalDirectoryStore(baseDir: string): ChatStoreLike & {
199
+ listMessages: (conversationId: string) => Promise<LocalStoredMessage[]>;
200
+ listConversations: NonNullable<ChatStoreLike["listConversations"]>;
201
+ };
202
+
203
+ interface MaintainerProStoreOptions {
204
+ baseUrl: string;
205
+ apiKey: string;
206
+ /** Directory for temporary local copies of images for CLI providers. */
207
+ tempDir?: string;
208
+ fetchImpl?: typeof fetch;
209
+ }
210
+ type UploadResult = {
211
+ /** Refs persisted on messages (maintainer-pro://uuid). */
212
+ refs: string[];
213
+ /** Absolute local temp paths for CLI image inspection. */
214
+ localPaths: string[];
215
+ attachmentIds: string[];
216
+ };
217
+ /**
218
+ * Persist chat data via Maintainer Pro HTTP API (no local .maintainer-pro writes).
219
+ */
220
+ declare function createMaintainerProStore(options: MaintainerProStoreOptions): ChatStoreLike & {
221
+ uploadAttachments: (conversationId: string, attachments: ChatAttachment[] | undefined) => Promise<UploadResult>;
222
+ };
223
+ /** Build a Maintainer Pro store from env when configured. */
224
+ declare function createMaintainerProStoreFromEnv(): ReturnType<typeof createMaintainerProStore> | null;
225
+
226
+ interface PriorConversationOptions {
227
+ excludeConversationId?: string;
228
+ currentRequest: string;
229
+ maxConversations?: number;
230
+ maxMessagesPerConversation?: number;
231
+ }
232
+ /**
233
+ * Load other conversations from the store and format a compact prompt block.
234
+ * Prefers chats that share keywords with the current request; falls back to
235
+ * most recently updated. Empty string when nothing useful is available.
236
+ */
237
+ declare function buildPriorConversationsContext(db: ChatStoreLike, options: PriorConversationOptions): Promise<string>;
238
+
239
+ export { type AiCliProviderId, type AiProvider, type AiResponse, type CallAiOptions, type ChatAttachment, type ChatHandlerOptions, type ChatHandlers, type ChatMessage, type ChatSenderType, type ChatStoreLike, type ChatUser, type ClientContext, type LocalStoredMessage, type MaintainerProStoreOptions, type PriorConversationOptions, type ProviderPreference, type ToolCall, type ToolSchemaMap, buildClaudeUserPrompt, buildConversationPrompt, buildCursorPrompt, buildPriorConversationsContext, callAi, commandExists, createAntigravityProvider, createBuiltinProviders, createChatHandler, createClaudeProvider, createCursorProvider, createDefaultSystemPrompt, createLocalDirectoryStore, createMaintainerProStore, createMaintainerProStoreFromEnv, createToolValidator, formatClientContext, getProviderPreference, parseAiResponse, providerLabel, resolveCliBinary, resolveProvider, saveChatAttachments, toNextRoute };
@@ -0,0 +1,239 @@
1
+ import { z } from 'zod';
2
+
3
+ type AiCliProviderId = "claude" | "cursor" | "antigravity" | (string & {});
4
+ interface ToolCall {
5
+ tool: string;
6
+ args: Record<string, unknown>;
7
+ }
8
+ interface AiResponse {
9
+ text: string;
10
+ toolCalls: ToolCall[];
11
+ provider: string;
12
+ }
13
+ interface ChatAttachment {
14
+ /** Original filename, e.g. screenshot.png */
15
+ name: string;
16
+ mimeType: string;
17
+ /** Raw base64 (no data: URL prefix). */
18
+ data: string;
19
+ }
20
+ interface ChatMessage {
21
+ role: "user" | "assistant";
22
+ content: string;
23
+ }
24
+ /** Sender roles for the shared client / developer / AI chat panel. */
25
+ type ChatSenderType = "client" | "developer" | "ai";
26
+ interface ChatUser {
27
+ name: string;
28
+ type: ChatSenderType;
29
+ /** When true, this user is selected by default in the composer (client/developer only). */
30
+ default?: boolean;
31
+ /** Login email when users come from Maintainer Pro. */
32
+ email?: string;
33
+ /** Org role from Maintainer Pro (owner, admin, staff, member, …). */
34
+ role?: string;
35
+ }
36
+ /** Live UI / app snapshot sent with each chat request (host-defined). */
37
+ interface ClientContext {
38
+ route: string;
39
+ pageTitle: string;
40
+ visiblePanels?: string[];
41
+ focusedElement?: string | null;
42
+ relevantFiles?: string[];
43
+ /** Arbitrary host app state (tasks, stats, form values, etc.). */
44
+ data?: Record<string, unknown>;
45
+ }
46
+ interface CallAiOptions {
47
+ systemPrompt: string;
48
+ workspaceDir?: string;
49
+ providerPreference?: "auto" | "claude" | "cursor" | "antigravity";
50
+ /** Absolute paths to screenshot/image files the agent should inspect. */
51
+ attachmentPaths?: string[];
52
+ /**
53
+ * Compact excerpts from other `.maintainer-pro/chat` conversations.
54
+ * Injected into the prompt for the model to use when relevant.
55
+ */
56
+ priorConversationsContext?: string;
57
+ /** Extra / override providers (e.g. future HTTP model backends). */
58
+ providers?: AiProvider[];
59
+ }
60
+ interface AiProvider {
61
+ id: string;
62
+ label: string;
63
+ /** Return true if this provider can run in the current environment. */
64
+ isAvailable(): Promise<boolean>;
65
+ call(messages: ChatMessage[], context: ClientContext | undefined, options: CallAiOptions): Promise<AiResponse>;
66
+ }
67
+
68
+ declare function callAi(messages: ChatMessage[], context: ClientContext | undefined, options: CallAiOptions): Promise<AiResponse>;
69
+
70
+ type ProviderPreference = "auto" | "claude" | "cursor" | "antigravity";
71
+ type BuiltinProviderId = "claude" | "cursor" | "antigravity";
72
+ declare function commandExists(command: string): Promise<boolean>;
73
+ declare function getProviderPreference(override?: ProviderPreference): ProviderPreference;
74
+ declare function resolveCliBinary(provider: BuiltinProviderId): Promise<string | null>;
75
+ declare function createBuiltinProviders(): AiProvider[];
76
+ declare function resolveProvider(options?: {
77
+ preference?: ProviderPreference;
78
+ providers?: AiProvider[];
79
+ }): Promise<AiProvider>;
80
+ declare function providerLabel(providerId: string): string;
81
+
82
+ /** Extract ```json ... ``` tool blocks and strip them from assistant text. */
83
+ declare function parseAiResponse(raw: string, provider: AiCliProviderId): AiResponse;
84
+
85
+ declare function buildConversationPrompt(messages: ChatMessage[]): string;
86
+ declare function formatClientContext(context?: ClientContext): string;
87
+ /** Full prompt for providers without a native --system-prompt flag (Cursor). */
88
+ declare function buildCursorPrompt(systemPrompt: string, messages: ChatMessage[], context?: ClientContext, attachmentPaths?: string[], priorConversationsContext?: string): string;
89
+ /** Conversation + context for Claude (system prompt passed separately). */
90
+ declare function buildClaudeUserPrompt(messages: ChatMessage[], context?: ClientContext, attachmentPaths?: string[], priorConversationsContext?: string): string;
91
+
92
+ declare function createDefaultSystemPrompt(input: {
93
+ productDescription: string;
94
+ relevantFilesHint?: string;
95
+ runtimeToolsHint?: string;
96
+ }): string;
97
+
98
+ declare function createClaudeProvider(): AiProvider;
99
+
100
+ declare function createCursorProvider(): AiProvider;
101
+
102
+ declare function createAntigravityProvider(): AiProvider;
103
+
104
+ type ToolSchemaMap = Record<string, z.ZodTypeAny>;
105
+ declare function createToolValidator(schemas: ToolSchemaMap): (toolCall: ToolCall) => {
106
+ valid: true;
107
+ name: string;
108
+ args: Record<string, unknown>;
109
+ } | {
110
+ valid: false;
111
+ error: string;
112
+ };
113
+
114
+ /** Minimal persistence contract (file store, SQL, or Maintainer Pro). */
115
+ interface ChatStoreLike {
116
+ ensureConversation(id: string): Promise<void>;
117
+ saveMessage(input: {
118
+ conversationId: string;
119
+ role: "user" | "assistant" | "system";
120
+ content: string;
121
+ provider?: string;
122
+ attachmentPaths?: string[];
123
+ senderType?: "client" | "developer" | "ai";
124
+ senderName?: string;
125
+ }): Promise<unknown>;
126
+ listMessages?(conversationId: string): Promise<Array<{
127
+ id: string;
128
+ role: string;
129
+ content: string;
130
+ provider?: string | null;
131
+ createdAt?: string | Date;
132
+ attachmentPaths?: string[];
133
+ senderType?: "client" | "developer" | "ai" | null;
134
+ senderName?: string | null;
135
+ }>>;
136
+ /** All conversations under the store (for prior-chat context). */
137
+ listConversations?(): Promise<Array<{
138
+ id: string;
139
+ updatedAt: string;
140
+ messages: Array<{
141
+ role: string;
142
+ content: string;
143
+ createdAt?: string | Date;
144
+ }>;
145
+ }>>;
146
+ saveToolEvents?(conversationId: string, events: Array<{
147
+ tool: string;
148
+ args: Record<string, unknown>;
149
+ }>): Promise<void>;
150
+ /**
151
+ * Optional remote/local upload hook. When present, chat images are persisted
152
+ * through the store instead of `.maintainer-pro/uploads`.
153
+ * `localPaths` are absolute paths for CLI inspection; `refs` are stored on messages.
154
+ */
155
+ uploadAttachments?(conversationId: string, attachments: ChatAttachment[] | undefined): Promise<{
156
+ refs: string[];
157
+ localPaths: string[];
158
+ }>;
159
+ }
160
+ interface ChatHandlerOptions {
161
+ systemPrompt: string;
162
+ workspaceDir?: string;
163
+ providerPreference?: CallAiOptions["providerPreference"];
164
+ providers?: AiProvider[];
165
+ tools?: ToolSchemaMap;
166
+ db?: ChatStoreLike;
167
+ conversationId?: string | ((request: Request) => string | undefined);
168
+ onToolCalls?: (toolCalls: ToolCall[], context?: ClientContext) => void | Promise<void>;
169
+ }
170
+ interface ChatHandlers {
171
+ GET: (request: Request) => Promise<Response>;
172
+ POST: (request: Request) => Promise<Response>;
173
+ }
174
+ declare function createChatHandler(options: ChatHandlerOptions): ChatHandlers;
175
+ declare function toNextRoute(handlers: ChatHandlers): {
176
+ GET: (request: Request) => Promise<Response>;
177
+ POST: (request: Request) => Promise<Response>;
178
+ };
179
+
180
+ /** Persist chat image attachments under the workspace and return absolute paths. */
181
+ declare function saveChatAttachments(attachments: ChatAttachment[] | undefined, workspaceDir: string): Promise<string[]>;
182
+
183
+ interface LocalStoredMessage {
184
+ id: string;
185
+ conversationId: string;
186
+ role: "user" | "assistant" | "system";
187
+ content: string;
188
+ provider: string | null;
189
+ createdAt: string;
190
+ attachmentPaths?: string[];
191
+ senderType?: "client" | "developer" | "ai" | null;
192
+ senderName?: string | null;
193
+ }
194
+ /**
195
+ * Persist conversations as JSON files under a local directory.
196
+ * Layout: `{baseDir}/{conversationId}.json`
197
+ */
198
+ declare function createLocalDirectoryStore(baseDir: string): ChatStoreLike & {
199
+ listMessages: (conversationId: string) => Promise<LocalStoredMessage[]>;
200
+ listConversations: NonNullable<ChatStoreLike["listConversations"]>;
201
+ };
202
+
203
+ interface MaintainerProStoreOptions {
204
+ baseUrl: string;
205
+ apiKey: string;
206
+ /** Directory for temporary local copies of images for CLI providers. */
207
+ tempDir?: string;
208
+ fetchImpl?: typeof fetch;
209
+ }
210
+ type UploadResult = {
211
+ /** Refs persisted on messages (maintainer-pro://uuid). */
212
+ refs: string[];
213
+ /** Absolute local temp paths for CLI image inspection. */
214
+ localPaths: string[];
215
+ attachmentIds: string[];
216
+ };
217
+ /**
218
+ * Persist chat data via Maintainer Pro HTTP API (no local .maintainer-pro writes).
219
+ */
220
+ declare function createMaintainerProStore(options: MaintainerProStoreOptions): ChatStoreLike & {
221
+ uploadAttachments: (conversationId: string, attachments: ChatAttachment[] | undefined) => Promise<UploadResult>;
222
+ };
223
+ /** Build a Maintainer Pro store from env when configured. */
224
+ declare function createMaintainerProStoreFromEnv(): ReturnType<typeof createMaintainerProStore> | null;
225
+
226
+ interface PriorConversationOptions {
227
+ excludeConversationId?: string;
228
+ currentRequest: string;
229
+ maxConversations?: number;
230
+ maxMessagesPerConversation?: number;
231
+ }
232
+ /**
233
+ * Load other conversations from the store and format a compact prompt block.
234
+ * Prefers chats that share keywords with the current request; falls back to
235
+ * most recently updated. Empty string when nothing useful is available.
236
+ */
237
+ declare function buildPriorConversationsContext(db: ChatStoreLike, options: PriorConversationOptions): Promise<string>;
238
+
239
+ export { type AiCliProviderId, type AiProvider, type AiResponse, type CallAiOptions, type ChatAttachment, type ChatHandlerOptions, type ChatHandlers, type ChatMessage, type ChatSenderType, type ChatStoreLike, type ChatUser, type ClientContext, type LocalStoredMessage, type MaintainerProStoreOptions, type PriorConversationOptions, type ProviderPreference, type ToolCall, type ToolSchemaMap, buildClaudeUserPrompt, buildConversationPrompt, buildCursorPrompt, buildPriorConversationsContext, callAi, commandExists, createAntigravityProvider, createBuiltinProviders, createChatHandler, createClaudeProvider, createCursorProvider, createDefaultSystemPrompt, createLocalDirectoryStore, createMaintainerProStore, createMaintainerProStoreFromEnv, createToolValidator, formatClientContext, getProviderPreference, parseAiResponse, providerLabel, resolveCliBinary, resolveProvider, saveChatAttachments, toNextRoute };