@sandagent/sdk 0.2.0-beta.5
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/LICENSE +201 -0
- package/dist/index.d.ts +158 -0
- package/dist/index.js +631 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +437 -0
- package/dist/react/index.js +421 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider/sandagent-provider.ts","../src/provider/sandagent-language-model.ts","../src/provider/types.ts","../src/index.ts"],"sourcesContent":["import type {\n EmbeddingModelV3,\n ImageModelV3,\n LanguageModelV3,\n ProviderV3,\n} from \"@ai-sdk/provider\";\nimport { NoSuchModelError } from \"@ai-sdk/provider\";\nimport type { RunnerSpec } from \"@sandagent/manager\";\nimport { SandAgentLanguageModel } from \"./sandagent-language-model\";\nimport type { Logger, SandAgentModelId } from \"./types\";\nimport {\n type SandAgentProviderSettings,\n getRunnerKindForModel,\n resolveModelId,\n} from \"./types\";\n\nexport type { SandAgentProviderSettings } from \"./types\";\n\n/**\n * SandAgent provider interface that extends the AI SDK's ProviderV3.\n */\nexport interface SandAgentProvider extends ProviderV3 {\n (\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n languageModel(\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n chat(\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n embeddingModel(modelId: string): EmbeddingModelV3;\n textEmbeddingModel(modelId: string): EmbeddingModelV3;\n imageModel(modelId: string): ImageModelV3;\n}\n\nfunction getLogger(settings: Partial<SandAgentProviderSettings>): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n\n/**\n * Creates a SandAgent provider instance with the specified configuration.\n *\n * @example\n * ```typescript\n * import { createSandAgent } from '@sandagent/sdk';\n * import { E2BSandbox } from '@sandagent/sandbox-e2b';\n * import { generateText } from 'ai';\n *\n * const sandagent = createSandAgent({\n * sandbox: new E2BSandbox({ apiKey: process.env.E2B_API_KEY! }),\n * env: {\n * ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,\n * },\n * });\n *\n * const { text } = await generateText({\n * model: sandagent('sonnet'),\n * prompt: 'Create a hello world program',\n * });\n * ```\n */\nexport function createSandAgent(\n defaultOptions: SandAgentProviderSettings,\n): SandAgentProvider {\n const logger = getLogger(defaultOptions);\n\n if (!defaultOptions.sandbox) {\n throw new Error(\n \"SandAgent provider requires a sandbox adapter. \" +\n \"Please provide one, e.g.: new E2BSandbox({ apiKey: 'xxx' })\",\n );\n }\n\n const createModel = (\n modelId: SandAgentModelId,\n options: Partial<SandAgentProviderSettings> = {},\n ): LanguageModelV3 => {\n const runnerKind = getRunnerKindForModel(modelId);\n const resolvedModelId = resolveModelId(modelId);\n\n const runner: RunnerSpec = {\n kind: runnerKind,\n model: resolvedModelId,\n outputFormat: \"stream\",\n };\n\n const mergedOptions = {\n ...defaultOptions,\n ...options,\n runner,\n env: {\n ...defaultOptions.env,\n ...options.env,\n },\n artifactProcessors: [\n ...(defaultOptions.artifactProcessors ?? []),\n ...(options.artifactProcessors ?? []),\n ],\n } as SandAgentProviderSettings & { runner: RunnerSpec };\n\n logger.debug(\n `[sandagent] Creating model: ${modelId} with runner: ${runner.kind}`,\n );\n\n return new SandAgentLanguageModel({\n id: modelId,\n options: mergedOptions,\n });\n };\n\n const provider = function (\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ) {\n if (new.target) {\n throw new Error(\n \"The SandAgent model function cannot be called with the new keyword.\",\n );\n }\n\n return createModel(modelId, options);\n };\n\n provider.languageModel = createModel;\n provider.chat = createModel;\n provider.specificationVersion = \"v3\" as const;\n\n provider.embeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.textEmbeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.imageModel = (modelId: string): ImageModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"imageModel\",\n });\n };\n\n return provider as SandAgentProvider;\n}\n","import type {\n JSONValue,\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3GenerateResult,\n LanguageModelV3Prompt,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n SharedV3ProviderMetadata,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport { type Message, type RunnerSpec, SandAgent } from \"@sandagent/manager\";\nimport type {\n Logger,\n SandAgentModelId,\n SandAgentProviderSettings,\n} from \"./types\";\nimport { resolveModelId } from \"./types\";\n\n/**\n * Options for creating a SandAgent language model instance.\n */\nexport interface SandAgentLanguageModelOptions {\n id: SandAgentModelId;\n options: SandAgentProviderSettings & { runner: RunnerSpec };\n}\n\nfunction getLogger(settings: SandAgentProviderSettings): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n\nfunction createEmptyUsage(): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: 0,\n noCache: 0,\n cacheRead: 0,\n cacheWrite: 0,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n };\n}\n\n/**\n * SandAgent Language Model implementation for AI SDK.\n */\nexport class SandAgentLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider = \"sandagent\";\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {\n \"image/*\": [/.*/],\n };\n\n private readonly options: SandAgentProviderSettings & { runner: RunnerSpec };\n private readonly logger: Logger;\n private sessionId: string | undefined;\n private toolNameMap: Map<string, string> = new Map();\n\n constructor(modelOptions: SandAgentLanguageModelOptions) {\n this.modelId = resolveModelId(modelOptions.id);\n this.options = modelOptions.options;\n this.logger = getLogger(modelOptions.options);\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n const { stream, request } = await this.doStream(options);\n const reader = stream.getReader();\n\n const content: LanguageModelV3Content[] = [];\n const warnings: SharedV3Warning[] = [];\n let finishReason: LanguageModelV3FinishReason = {\n unified: \"other\",\n raw: undefined,\n };\n let usage: LanguageModelV3Usage = createEmptyUsage();\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n\n const textParts: Map<string, { text: string }> = new Map();\n const toolInputs: Map<string, { toolName: string; input: string }> =\n new Map();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n switch (value.type) {\n case \"text-start\": {\n textParts.set(value.id, { text: \"\" });\n break;\n }\n case \"text-delta\": {\n const part = textParts.get(value.id);\n if (part) {\n part.text += value.delta;\n }\n break;\n }\n case \"text-end\": {\n const part = textParts.get(value.id);\n if (part) {\n content.push({\n type: \"text\",\n text: part.text,\n });\n }\n break;\n }\n case \"tool-input-start\": {\n toolInputs.set(value.id, { toolName: value.toolName, input: \"\" });\n break;\n }\n case \"tool-input-delta\": {\n const tool = toolInputs.get(value.id);\n if (tool) {\n tool.input += value.delta;\n }\n break;\n }\n case \"tool-input-end\": {\n break;\n }\n case \"tool-call\": {\n content.push({\n type: \"tool-call\",\n toolCallId: value.toolCallId,\n toolName: value.toolName,\n input: value.input,\n providerExecuted: value.providerExecuted,\n });\n break;\n }\n case \"stream-start\": {\n warnings.push(...value.warnings);\n break;\n }\n case \"finish\": {\n finishReason = value.finishReason;\n usage = value.usage;\n providerMetadata = value.providerMetadata;\n break;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n return {\n content,\n finishReason,\n usage,\n providerMetadata,\n request,\n warnings,\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n const { prompt, abortSignal } = options;\n const messages = this.convertPromptToMessages(prompt);\n\n this.logger.debug(\n `[sandagent] Starting stream with ${messages.length} messages`,\n );\n\n const sandbox = this.options.sandbox;\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const sandboxWorkdir =\n this.options.cwd ?? sandbox.getWorkdir?.() ?? \"/workspace\";\n\n const agent = new SandAgent({\n sandbox: this.options.sandbox,\n runner: this.options.runner,\n env: { ...sandboxEnv, ...this.options.env },\n });\n\n try {\n const stream = await agent.stream({\n messages,\n workspace: {\n path: sandboxWorkdir,\n },\n resume: this.options.resume,\n signal: abortSignal,\n });\n\n const self = this;\n const reader = stream.getReader();\n\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const outputStream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n try {\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n if (buffer.trim()) {\n const parts = self.parseSSEBuffer(buffer);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n controller.close();\n break;\n }\n\n const text = new TextDecoder().decode(value);\n buffer += text;\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n let foundDone = false;\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n\n if (data === \"[DONE]\") {\n foundDone = true;\n continue;\n }\n try {\n const parts = self.parseSSEData(data);\n for (const part of parts) {\n controller.enqueue(part);\n\n if (\n self.options.artifactProcessors?.length &&\n self.sessionId\n ) {\n const sessionId: string = self.sessionId;\n for (const processor of self.options\n .artifactProcessors) {\n Promise.resolve()\n .then(() => processor.onChange(part, sessionId))\n .catch((e) => {\n self.logger.error(\n `[sandagent] Artifact processor error: ${e}`,\n );\n });\n }\n }\n }\n } catch (e) {\n self.logger.error(\n `[sandagent] Failed to parse SSE data: ${e}`,\n );\n }\n }\n }\n\n if (foundDone) {\n controller.close();\n return;\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n self.logger.info(\"[sandagent] Stream aborted by user\");\n } else {\n self.logger.error(`[sandagent] Stream error: ${error}`);\n }\n controller.error(error);\n }\n },\n\n cancel() {\n reader.cancel();\n },\n });\n\n return {\n stream: outputStream,\n request: {\n body: JSON.stringify({ messages }),\n },\n };\n } catch (error) {\n await agent.destroy().catch(() => {});\n throw error;\n }\n }\n\n private parseSSEBuffer(buffer: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const lines = buffer.split(\"\\n\");\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n\n if (data === \"[DONE]\") {\n continue;\n }\n\n try {\n const parsedParts = this.parseSSEData(data);\n parts.push(...parsedParts);\n } catch (e) {\n this.logger.error(`[sandagent] Failed to parse SSE data: ${e}`);\n }\n }\n }\n\n return parts;\n }\n\n private parseSSEData(data: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const parsed = JSON.parse(data) as Record<string, unknown>;\n\n switch (parsed.type) {\n case \"start\": {\n break;\n }\n\n case \"message-metadata\": {\n const metadata = parsed.messageMetadata as Record<string, unknown>;\n if (metadata?.sessionId && typeof metadata.sessionId === \"string\") {\n this.sessionId = metadata.sessionId;\n this.logger.debug(\n `[sandagent] Session ID extracted: ${this.sessionId}`,\n );\n parts.push({\n type: \"raw\",\n rawValue: this.sessionId,\n });\n }\n break;\n }\n\n case \"text-start\": {\n parts.push({\n type: \"text-start\",\n id: parsed.id as string,\n providerMetadata: {\n \"claude-code\": {\n sessionId: this.sessionId,\n },\n },\n });\n break;\n }\n\n case \"text-delta\": {\n parts.push({\n type: \"text-delta\",\n id: parsed.id as string,\n delta: parsed.delta as string,\n });\n break;\n }\n\n case \"text-end\": {\n parts.push({\n type: \"text-end\",\n id: parsed.id as string,\n });\n break;\n }\n\n case \"tool-input-start\": {\n parts.push({\n type: \"tool-input-start\",\n id: parsed.toolCallId as string,\n toolName: parsed.toolName as string,\n dynamic: parsed.dynamic as boolean,\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-input-delta\": {\n parts.push({\n type: \"tool-input-delta\",\n id: parsed.toolCallId as string,\n delta: parsed.inputTextDelta as string,\n });\n break;\n }\n case \"tool-input-available\": {\n const toolCallId = parsed.toolCallId as string;\n const toolName = parsed.toolName as string;\n const input = parsed.input as Record<string, unknown>;\n this.toolNameMap.set(toolCallId, toolName);\n parts.push({\n type: \"tool-call\",\n toolCallId,\n toolName,\n input: JSON.stringify(input),\n dynamic: parsed.dynamic as boolean,\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-output-available\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: parsed.output as NonNullable<JSONValue>,\n isError: parsed.isError as boolean,\n dynamic: parsed.dynamic as boolean,\n });\n break;\n }\n case \"error\": {\n parts.push({\n type: \"error\",\n error: new Error(parsed.errorText as string),\n });\n break;\n }\n\n case \"finish\": {\n const rawFinishReason = parsed.finishReason;\n let finishReason: LanguageModelV3FinishReason;\n\n if (\n typeof rawFinishReason === \"object\" &&\n rawFinishReason !== null &&\n \"unified\" in rawFinishReason\n ) {\n finishReason = rawFinishReason as LanguageModelV3FinishReason;\n } else {\n finishReason = this.mapFinishReason(rawFinishReason as string);\n }\n\n const rawUsage = parsed.usage ?? parsed.messageMetadata;\n const usage = this.convertUsage(\n rawUsage as Record<string, unknown> | undefined,\n );\n\n parts.push({\n type: \"finish\",\n finishReason,\n usage,\n providerMetadata: {\n sandagent: parsed.messageMetadata,\n } as SharedV3ProviderMetadata,\n });\n break;\n }\n }\n\n return parts;\n }\n\n private convertPromptToMessages(prompt: LanguageModelV3Prompt): Message[] {\n const messages: Message[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case \"system\": {\n messages.push({\n role: \"system\",\n content: message.content,\n });\n break;\n }\n\n case \"user\": {\n const textParts = message.content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part.type === \"text\",\n )\n .map((part) => part.text);\n\n if (textParts.length > 0) {\n messages.push({\n role: \"user\",\n content: textParts.join(\"\\n\"),\n });\n }\n break;\n }\n\n case \"assistant\": {\n const textParts = message.content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part.type === \"text\",\n )\n .map((part) => part.text);\n\n if (textParts.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textParts.join(\"\\n\"),\n });\n }\n break;\n }\n\n case \"tool\": {\n break;\n }\n }\n }\n\n return messages;\n }\n\n private mapFinishReason(\n reason: string | undefined,\n ): LanguageModelV3FinishReason {\n switch (reason) {\n case \"stop\":\n return { unified: \"stop\", raw: reason };\n case \"length\":\n return { unified: \"length\", raw: reason };\n case \"tool_calls\":\n case \"tool-calls\":\n return { unified: \"tool-calls\", raw: reason };\n case \"content_filter\":\n case \"content-filter\":\n return { unified: \"content-filter\", raw: reason };\n case \"error\":\n return { unified: \"error\", raw: reason };\n default:\n return { unified: \"other\", raw: reason ?? \"unknown\" };\n }\n }\n\n private convertUsage(\n data: Record<string, unknown> | undefined,\n ): LanguageModelV3Usage {\n if (!data) {\n return createEmptyUsage();\n }\n\n if (\"inputTokens\" in data && \"outputTokens\" in data) {\n const inputTokens = data.inputTokens as Record<string, number>;\n const outputTokens = data.outputTokens as Record<string, number>;\n\n return {\n inputTokens: {\n total: inputTokens.total ?? 0,\n noCache: inputTokens.noCache ?? 0,\n cacheRead: inputTokens.cacheRead ?? 0,\n cacheWrite: inputTokens.cacheWrite ?? 0,\n },\n outputTokens: {\n total: outputTokens.total ?? 0,\n text: undefined,\n reasoning: undefined,\n },\n };\n }\n\n const usage = (data.usage ?? data) as Record<string, number>;\n\n if (\"input_tokens\" in usage || \"output_tokens\" in usage) {\n const inputTokens = (usage.input_tokens as number) ?? 0;\n const outputTokens = (usage.output_tokens as number) ?? 0;\n const cacheWrite = (usage.cache_creation_input_tokens as number) ?? 0;\n const cacheRead = (usage.cache_read_input_tokens as number) ?? 0;\n\n return {\n inputTokens: {\n total: inputTokens + cacheWrite + cacheRead,\n noCache: inputTokens,\n cacheRead,\n cacheWrite,\n },\n outputTokens: {\n total: outputTokens,\n text: undefined,\n reasoning: undefined,\n },\n };\n }\n\n return createEmptyUsage();\n }\n}\n","import type { LanguageModelV3StreamPart } from \"@ai-sdk/provider\";\nimport type { SandAgentOptions } from \"@sandagent/manager\";\n\n/**\n * Artifact Processor 返回结果\n */\nexport interface ArtifactResult {\n artifactId: string;\n content: string;\n mimeType?: string;\n}\n\n/**\n * Stream writer interface for writing data parts\n */\nexport interface StreamWriter {\n write(chunk: {\n type: string;\n id?: string;\n data?: unknown;\n transient?: boolean;\n }): void;\n}\n\n/**\n * Artifact Processor 接口\n */\nexport interface ArtifactProcessor {\n /**\n * 当收到 stream part 时触发\n * @param event - Stream part 事件\n * @param sessionId - 当前会话 ID(taskId)\n */\n onChange(event: LanguageModelV3StreamPart, sessionId: string): Promise<void>;\n}\n\n/**\n * Logger interface for custom logging.\n */\nexport interface Logger {\n debug: (message: string) => void;\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\n/**\n * AI Provider specific settings that extend SandAgentOptions.\n */\nexport interface SandAgentProviderSettings\n extends Omit<SandAgentOptions, \"runner\" | \"sandboxId\"> {\n /** Working directory for CLI operations inside the sandbox. */\n cwd?: string;\n /** Resume session ID for multi-turn conversation. */\n resume?: string;\n /** Enable verbose logging for debugging. */\n verbose?: boolean;\n /** Custom logger for handling warnings and errors. */\n logger?: Logger | false;\n /** Artifact processors for handling artifact events. */\n artifactProcessors?: ArtifactProcessor[];\n}\n\n/**\n * Supported model identifiers for SandAgent.\n */\nexport type SandAgentModelId =\n | \"claude-sonnet-4-20250514\"\n | \"claude-opus-4-20250514\"\n | \"claude-sonnet-4.5-20250514\"\n | \"claude-opus-4.5-20250514\"\n | \"claude-4-5-sonnet-20250514\"\n | \"claude-4-5-opus-20250514\"\n | \"claude-3-7-sonnet-20250219\"\n | \"claude-3-5-sonnet-20241022\"\n | \"claude-3-5-haiku-20241022\"\n | \"claude-3-opus-20240229\"\n | \"claude-3-sonnet-20240229\"\n | \"claude-3-haiku-20240307\"\n | \"sonnet\"\n | \"opus\"\n | \"haiku\"\n | (string & {});\n\n/**\n * Maps model aliases to full model IDs\n */\nexport function resolveModelId(modelId: SandAgentModelId): string {\n switch (modelId) {\n case \"sonnet\":\n return \"claude-sonnet-4-20250514\";\n case \"opus\":\n return \"claude-opus-4-20250514\";\n case \"haiku\":\n return \"claude-3-5-haiku-20241022\";\n default:\n return modelId;\n }\n}\n\n/**\n * Determine the runner kind based on model ID\n */\nexport function getRunnerKindForModel(\n modelId: SandAgentModelId,\n): \"claude-agent-sdk\" {\n const resolvedId = resolveModelId(modelId);\n\n if (\n resolvedId.startsWith(\"claude\") ||\n resolvedId.includes(\"anthropic\") ||\n resolvedId.startsWith(\"us.anthropic\")\n ) {\n return \"claude-agent-sdk\";\n }\n\n return \"claude-agent-sdk\";\n}\n","/**\n * @sandagent/sdk\n *\n * SandAgent SDK - AI Provider and React hooks for building AI chat interfaces.\n *\n * Main entry point exports the AI provider (backend).\n * React hooks are available via \"@sandagent/sdk/react\".\n *\n * @example\n * ```typescript\n * // Backend - Provider\n * import { createSandAgent } from \"@sandagent/sdk\";\n * const sandagent = createSandAgent({ sandbox, env });\n * const model = sandagent(\"sonnet\");\n *\n * // Frontend - React hooks\n * import { useSandAgentChat } from \"@sandagent/sdk/react\";\n * const { messages, sendMessage } = useSandAgentChat({ apiEndpoint: \"/api/ai\" });\n * ```\n */\n\n// Provider exports\nexport {\n createSandAgent,\n SandAgentLanguageModel,\n resolveModelId,\n} from \"./provider\";\n\nexport type {\n SandAgentProvider,\n SandAgentProviderSettings,\n SandAgentLanguageModelOptions,\n SandAgentModelId,\n Logger,\n ArtifactProcessor,\n ArtifactResult,\n StreamWriter,\n // Re-exports from @sandagent/manager\n SandboxAdapter,\n SandboxHandle,\n TranscriptEntry,\n Message,\n // Re-exports from @ai-sdk/provider\n LanguageModelV3StreamPart,\n} from \"./provider\";\n\n// Re-export LocalSandbox for convenience\nexport { LocalSandbox } from \"@sandagent/manager\";\nexport type { LocalSandboxOptions } from \"@sandagent/manager\";\n\nexport const VERSION = \"0.1.0\";\n"],"mappings":"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","names":["getLogger"]}
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { UIMessage, DynamicToolUIPart } from 'ai';
|
|
2
|
+
export { DynamicToolUIPart, UIMessage } from 'ai';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Artifact data structure
|
|
6
|
+
*/
|
|
7
|
+
interface ArtifactData {
|
|
8
|
+
artifactId: string;
|
|
9
|
+
content: string;
|
|
10
|
+
mimeType: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Options for useSandAgentChat hook
|
|
14
|
+
*/
|
|
15
|
+
interface UseSandAgentChatOptions {
|
|
16
|
+
/** API endpoint for chat (default: /api/ai) */
|
|
17
|
+
apiEndpoint?: string;
|
|
18
|
+
/** Additional body params to pass to API on each request */
|
|
19
|
+
body?: Record<string, unknown>;
|
|
20
|
+
/** Session ID (auto-generated if not provided) */
|
|
21
|
+
sessionId?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Return type for useSandAgentChat hook
|
|
25
|
+
*/
|
|
26
|
+
interface UseSandAgentChatReturn {
|
|
27
|
+
/** Current session ID */
|
|
28
|
+
sessionId: string;
|
|
29
|
+
/** All chat messages */
|
|
30
|
+
messages: UIMessage[];
|
|
31
|
+
/** Current chat status */
|
|
32
|
+
status: "submitted" | "streaming" | "ready" | "error";
|
|
33
|
+
/** Error if any */
|
|
34
|
+
error: Error | undefined;
|
|
35
|
+
/** Whether the chat is loading (streaming or submitted) */
|
|
36
|
+
isLoading: boolean;
|
|
37
|
+
/** Whether there's an error */
|
|
38
|
+
hasError: boolean;
|
|
39
|
+
/** Extracted artifacts from messages */
|
|
40
|
+
artifacts: ArtifactData[];
|
|
41
|
+
/** Currently selected artifact */
|
|
42
|
+
selectedArtifact: ArtifactData | null;
|
|
43
|
+
/** Set the selected artifact */
|
|
44
|
+
setSelectedArtifact: (artifact: ArtifactData | null) => void;
|
|
45
|
+
/** Send a message */
|
|
46
|
+
sendMessage: (text: string) => void;
|
|
47
|
+
/** Stop the current stream */
|
|
48
|
+
stop: () => void;
|
|
49
|
+
/** Handle form submit (for use with PromptInput) */
|
|
50
|
+
handleSubmit: (message: {
|
|
51
|
+
text: string;
|
|
52
|
+
}) => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Question option structure
|
|
56
|
+
*/
|
|
57
|
+
interface QuestionOption {
|
|
58
|
+
label: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Question structure for AskUserQuestion tool
|
|
63
|
+
*/
|
|
64
|
+
interface Question {
|
|
65
|
+
question: string;
|
|
66
|
+
header?: string;
|
|
67
|
+
options?: QuestionOption[];
|
|
68
|
+
multiSelect?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* AskUserQuestion input structure (from tool)
|
|
72
|
+
*/
|
|
73
|
+
interface AskUserQuestionInput {
|
|
74
|
+
questions: Question[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* AskUserQuestion output structure (answers)
|
|
78
|
+
*/
|
|
79
|
+
interface AskUserQuestionOutput {
|
|
80
|
+
questions: Question[];
|
|
81
|
+
answers: Record<string, string>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Options for useAskUserQuestion hook
|
|
85
|
+
*/
|
|
86
|
+
interface UseAskUserQuestionOptions {
|
|
87
|
+
/** The dynamic tool UI part from the message */
|
|
88
|
+
part: DynamicToolUIPart;
|
|
89
|
+
/** Callback when user selects an answer */
|
|
90
|
+
onAnswer?: (data: {
|
|
91
|
+
toolCallId: string;
|
|
92
|
+
questions: Question[];
|
|
93
|
+
answers: Record<string, string>;
|
|
94
|
+
}) => void;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Return type for useAskUserQuestion hook
|
|
98
|
+
*/
|
|
99
|
+
interface UseAskUserQuestionReturn {
|
|
100
|
+
/** Parsed questions from the tool input */
|
|
101
|
+
questions: Question[];
|
|
102
|
+
/** Current selected answers (question -> value or values) */
|
|
103
|
+
answers: Record<string, string | string[]>;
|
|
104
|
+
/** Whether the tool interaction is completed */
|
|
105
|
+
isCompleted: boolean;
|
|
106
|
+
/** Whether waiting for user input (shows animation) */
|
|
107
|
+
isWaitingForInput: boolean;
|
|
108
|
+
/** Select an answer for a question */
|
|
109
|
+
selectAnswer: (question: string, value: string, multiSelect?: boolean) => void;
|
|
110
|
+
/** Get formatted answers map (for submission) */
|
|
111
|
+
getAnswersMap: () => Record<string, string>;
|
|
112
|
+
/** Check if an option is selected */
|
|
113
|
+
isSelected: (question: string, optionLabel: string, multiSelect?: boolean) => boolean;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Write tool input structure
|
|
117
|
+
*/
|
|
118
|
+
interface WriteToolInput {
|
|
119
|
+
file_path: string;
|
|
120
|
+
content: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Write tool output structure
|
|
124
|
+
*/
|
|
125
|
+
interface WriteToolOutput {
|
|
126
|
+
type: "create" | "edit";
|
|
127
|
+
filePath: string;
|
|
128
|
+
content: string;
|
|
129
|
+
structuredPatch?: unknown[];
|
|
130
|
+
originalFile?: string | null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Options for useWriteTool hook
|
|
134
|
+
*/
|
|
135
|
+
interface UseWriteToolOptions$1 {
|
|
136
|
+
/** The dynamic tool UI part from the message */
|
|
137
|
+
part: DynamicToolUIPart;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Return type for useWriteTool hook
|
|
141
|
+
*/
|
|
142
|
+
interface UseWriteToolReturn$1 {
|
|
143
|
+
/** File path being written to */
|
|
144
|
+
filePath: string | null;
|
|
145
|
+
/** File name (extracted from path) */
|
|
146
|
+
fileName: string | null;
|
|
147
|
+
/** File content */
|
|
148
|
+
content: string | null;
|
|
149
|
+
/** Operation type: 'create' or 'edit' */
|
|
150
|
+
operationType: "create" | "edit" | null;
|
|
151
|
+
/** Original file content (for edit operations) */
|
|
152
|
+
originalContent: string | null;
|
|
153
|
+
/** Structured patch data (for edit operations) */
|
|
154
|
+
structuredPatch: unknown[] | null;
|
|
155
|
+
/** Tool state */
|
|
156
|
+
state: "streaming" | "input-available" | "output-available" | "error";
|
|
157
|
+
/** Whether the tool is currently streaming input */
|
|
158
|
+
isStreaming: boolean;
|
|
159
|
+
/** Whether the write operation completed successfully */
|
|
160
|
+
isCompleted: boolean;
|
|
161
|
+
/** Whether there was an error */
|
|
162
|
+
hasError: boolean;
|
|
163
|
+
/** Error message if any */
|
|
164
|
+
errorText: string | null;
|
|
165
|
+
/** Whether this is a markdown file */
|
|
166
|
+
isMarkdown: boolean;
|
|
167
|
+
/** File extension */
|
|
168
|
+
fileExtension: string | null;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Options for useArtifacts hook
|
|
172
|
+
*/
|
|
173
|
+
interface UseArtifactsOptions$1 {
|
|
174
|
+
/** Messages to extract artifacts from */
|
|
175
|
+
messages: UIMessage[];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Return type for useArtifacts hook
|
|
179
|
+
*/
|
|
180
|
+
interface UseArtifactsReturn$1 {
|
|
181
|
+
/** All extracted artifacts */
|
|
182
|
+
artifacts: ArtifactData[];
|
|
183
|
+
/** Currently selected artifact */
|
|
184
|
+
selectedArtifact: ArtifactData | null;
|
|
185
|
+
/** Set the selected artifact */
|
|
186
|
+
setSelectedArtifact: (artifact: ArtifactData | null) => void;
|
|
187
|
+
/** Select artifact by ID */
|
|
188
|
+
selectArtifactById: (artifactId: string) => void;
|
|
189
|
+
/** Whether there are any artifacts */
|
|
190
|
+
hasArtifacts: boolean;
|
|
191
|
+
/** Number of artifacts */
|
|
192
|
+
count: number;
|
|
193
|
+
/** Copy artifact content to clipboard */
|
|
194
|
+
copyContent: (artifact: ArtifactData) => Promise<void>;
|
|
195
|
+
/** Download artifact as file */
|
|
196
|
+
downloadArtifact: (artifact: ArtifactData) => void;
|
|
197
|
+
/** Get file extension from mime type */
|
|
198
|
+
getFileExtension: (mimeType: string) => string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* useSandAgentChat - Core hook for SandAgent chat functionality
|
|
203
|
+
*
|
|
204
|
+
* Provides all the logic needed for a chat interface:
|
|
205
|
+
* - Message management
|
|
206
|
+
* - Artifact extraction
|
|
207
|
+
* - Session management
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```tsx
|
|
211
|
+
* import { useSandAgentChat } from "@sandagent/sdk/react";
|
|
212
|
+
*
|
|
213
|
+
* const {
|
|
214
|
+
* messages,
|
|
215
|
+
* sendMessage,
|
|
216
|
+
* status,
|
|
217
|
+
* artifacts,
|
|
218
|
+
* selectedArtifact,
|
|
219
|
+
* setSelectedArtifact,
|
|
220
|
+
* } = useSandAgentChat({
|
|
221
|
+
* apiEndpoint: "/api/ai",
|
|
222
|
+
* body: { template: "default" },
|
|
223
|
+
* });
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
declare function useSandAgentChat({ apiEndpoint, body, sessionId: providedSessionId, }?: UseSandAgentChatOptions): UseSandAgentChatReturn;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* useAskUserQuestion - Hook for handling AskUserQuestion tool interactions
|
|
230
|
+
*
|
|
231
|
+
* Manages the state for user question/answer interactions in chat.
|
|
232
|
+
* Provides answer selection, completion detection, and formatted output.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```tsx
|
|
236
|
+
* import { useAskUserQuestion } from "@sandagent/sdk/react";
|
|
237
|
+
*
|
|
238
|
+
* function QuestionUI({ part, sessionId }) {
|
|
239
|
+
* const {
|
|
240
|
+
* questions,
|
|
241
|
+
* answers,
|
|
242
|
+
* isCompleted,
|
|
243
|
+
* selectAnswer,
|
|
244
|
+
* isSelected,
|
|
245
|
+
* } = useAskUserQuestion({
|
|
246
|
+
* part,
|
|
247
|
+
* onAnswer: (data) => {
|
|
248
|
+
* fetch("/api/approval/submit", {
|
|
249
|
+
* method: "POST",
|
|
250
|
+
* body: JSON.stringify({ sessionId, ...data }),
|
|
251
|
+
* });
|
|
252
|
+
* },
|
|
253
|
+
* });
|
|
254
|
+
*
|
|
255
|
+
* if (isCompleted) {
|
|
256
|
+
* return <div>Completed</div>;
|
|
257
|
+
* }
|
|
258
|
+
*
|
|
259
|
+
* return (
|
|
260
|
+
* <div>
|
|
261
|
+
* {questions.map((q) => (
|
|
262
|
+
* <div key={q.question}>
|
|
263
|
+
* <p>{q.question}</p>
|
|
264
|
+
* {q.options?.map((opt) => (
|
|
265
|
+
* <button
|
|
266
|
+
* key={opt.label}
|
|
267
|
+
* onClick={() => selectAnswer(q.question, opt.label, q.multiSelect)}
|
|
268
|
+
* style={{ fontWeight: isSelected(q.question, opt.label, q.multiSelect) ? 'bold' : 'normal' }}
|
|
269
|
+
* >
|
|
270
|
+
* {opt.label}
|
|
271
|
+
* </button>
|
|
272
|
+
* ))}
|
|
273
|
+
* </div>
|
|
274
|
+
* ))}
|
|
275
|
+
* </div>
|
|
276
|
+
* );
|
|
277
|
+
* }
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
declare function useAskUserQuestion({ part, onAnswer, }: UseAskUserQuestionOptions): UseAskUserQuestionReturn;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Options for useWriteTool hook
|
|
284
|
+
*/
|
|
285
|
+
interface UseWriteToolOptions {
|
|
286
|
+
/** The dynamic tool UI part from the message */
|
|
287
|
+
part: DynamicToolUIPart;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Return type for useWriteTool hook
|
|
291
|
+
*/
|
|
292
|
+
interface UseWriteToolReturn {
|
|
293
|
+
/** File path being written to */
|
|
294
|
+
filePath: string | null;
|
|
295
|
+
/** File name (extracted from path) */
|
|
296
|
+
fileName: string | null;
|
|
297
|
+
/** File content */
|
|
298
|
+
content: string | null;
|
|
299
|
+
/** Operation type: 'create' or 'edit' */
|
|
300
|
+
operationType: "create" | "edit" | null;
|
|
301
|
+
/** Original file content (for edit operations) */
|
|
302
|
+
originalContent: string | null;
|
|
303
|
+
/** Structured patch data (for edit operations) */
|
|
304
|
+
structuredPatch: unknown[] | null;
|
|
305
|
+
/** Tool state */
|
|
306
|
+
state: "streaming" | "input-available" | "output-available" | "error";
|
|
307
|
+
/** Whether the tool is currently streaming input */
|
|
308
|
+
isStreaming: boolean;
|
|
309
|
+
/** Whether the write operation completed successfully */
|
|
310
|
+
isCompleted: boolean;
|
|
311
|
+
/** Whether there was an error */
|
|
312
|
+
hasError: boolean;
|
|
313
|
+
/** Error message if any */
|
|
314
|
+
errorText: string | null;
|
|
315
|
+
/** Whether this is a markdown file */
|
|
316
|
+
isMarkdown: boolean;
|
|
317
|
+
/** File extension */
|
|
318
|
+
fileExtension: string | null;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* useWriteTool - Hook for handling Write tool interactions
|
|
322
|
+
*
|
|
323
|
+
* Parses the Write tool's input and output data, providing
|
|
324
|
+
* easy access to file information and operation state.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```tsx
|
|
328
|
+
* import { useWriteTool } from "@sandagent/sdk/react";
|
|
329
|
+
*
|
|
330
|
+
* function WriteToolUI({ part }) {
|
|
331
|
+
* const {
|
|
332
|
+
* filePath,
|
|
333
|
+
* fileName,
|
|
334
|
+
* content,
|
|
335
|
+
* operationType,
|
|
336
|
+
* isStreaming,
|
|
337
|
+
* isCompleted,
|
|
338
|
+
* isMarkdown,
|
|
339
|
+
* } = useWriteTool({ part });
|
|
340
|
+
*
|
|
341
|
+
* if (isStreaming) {
|
|
342
|
+
* return <div>Writing {fileName}...</div>;
|
|
343
|
+
* }
|
|
344
|
+
*
|
|
345
|
+
* return (
|
|
346
|
+
* <div>
|
|
347
|
+
* <h3>{fileName} ({operationType})</h3>
|
|
348
|
+
* {isMarkdown ? (
|
|
349
|
+
* <MarkdownRenderer content={content} />
|
|
350
|
+
* ) : (
|
|
351
|
+
* <pre>{content}</pre>
|
|
352
|
+
* )}
|
|
353
|
+
* </div>
|
|
354
|
+
* );
|
|
355
|
+
* }
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
declare function useWriteTool({ part, }: UseWriteToolOptions): UseWriteToolReturn;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Options for useArtifacts hook
|
|
362
|
+
*/
|
|
363
|
+
interface UseArtifactsOptions {
|
|
364
|
+
/** Messages to extract artifacts from */
|
|
365
|
+
messages: UIMessage[];
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Return type for useArtifacts hook
|
|
369
|
+
*/
|
|
370
|
+
interface UseArtifactsReturn {
|
|
371
|
+
/** All extracted artifacts */
|
|
372
|
+
artifacts: ArtifactData[];
|
|
373
|
+
/** Currently selected artifact */
|
|
374
|
+
selectedArtifact: ArtifactData | null;
|
|
375
|
+
/** Set the selected artifact */
|
|
376
|
+
setSelectedArtifact: (artifact: ArtifactData | null) => void;
|
|
377
|
+
/** Select artifact by ID */
|
|
378
|
+
selectArtifactById: (artifactId: string) => void;
|
|
379
|
+
/** Whether there are any artifacts */
|
|
380
|
+
hasArtifacts: boolean;
|
|
381
|
+
/** Number of artifacts */
|
|
382
|
+
count: number;
|
|
383
|
+
/** Copy artifact content to clipboard */
|
|
384
|
+
copyContent: (artifact: ArtifactData) => Promise<void>;
|
|
385
|
+
/** Download artifact as file */
|
|
386
|
+
downloadArtifact: (artifact: ArtifactData) => void;
|
|
387
|
+
/** Get file extension from mime type */
|
|
388
|
+
getFileExtension: (mimeType: string) => string;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* useArtifacts - Hook for managing artifacts from chat messages
|
|
392
|
+
*
|
|
393
|
+
* Extracts artifacts from messages and provides selection,
|
|
394
|
+
* copy, and download functionality.
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```tsx
|
|
398
|
+
* import { useArtifacts } from "@sandagent/sdk/react";
|
|
399
|
+
*
|
|
400
|
+
* function ArtifactPanel({ messages }) {
|
|
401
|
+
* const {
|
|
402
|
+
* artifacts,
|
|
403
|
+
* selectedArtifact,
|
|
404
|
+
* setSelectedArtifact,
|
|
405
|
+
* hasArtifacts,
|
|
406
|
+
* copyContent,
|
|
407
|
+
* downloadArtifact,
|
|
408
|
+
* } = useArtifacts({ messages });
|
|
409
|
+
*
|
|
410
|
+
* if (!hasArtifacts) return null;
|
|
411
|
+
*
|
|
412
|
+
* return (
|
|
413
|
+
* <div>
|
|
414
|
+
* {artifacts.map((artifact) => (
|
|
415
|
+
* <button
|
|
416
|
+
* key={artifact.artifactId}
|
|
417
|
+
* onClick={() => setSelectedArtifact(artifact)}
|
|
418
|
+
* >
|
|
419
|
+
* {artifact.artifactId}
|
|
420
|
+
* </button>
|
|
421
|
+
* ))}
|
|
422
|
+
*
|
|
423
|
+
* {selectedArtifact && (
|
|
424
|
+
* <div>
|
|
425
|
+
* <pre>{selectedArtifact.content}</pre>
|
|
426
|
+
* <button onClick={() => copyContent(selectedArtifact)}>Copy</button>
|
|
427
|
+
* <button onClick={() => downloadArtifact(selectedArtifact)}>Download</button>
|
|
428
|
+
* </div>
|
|
429
|
+
* )}
|
|
430
|
+
* </div>
|
|
431
|
+
* );
|
|
432
|
+
* }
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
declare function useArtifacts({ messages, }: UseArtifactsOptions): UseArtifactsReturn;
|
|
436
|
+
|
|
437
|
+
export { type ArtifactData, type AskUserQuestionInput, type AskUserQuestionOutput, type Question, type QuestionOption, type UseArtifactsOptions$1 as UseArtifactsOptions, type UseArtifactsReturn$1 as UseArtifactsReturn, type UseAskUserQuestionOptions, type UseAskUserQuestionReturn, type UseSandAgentChatOptions, type UseSandAgentChatReturn, type UseWriteToolOptions$1 as UseWriteToolOptions, type UseWriteToolReturn$1 as UseWriteToolReturn, type WriteToolInput, type WriteToolOutput, useArtifacts, useAskUserQuestion, useSandAgentChat, useWriteTool };
|