@nextclaw/ncp-react 0.4.56 → 0.5.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.
package/dist/index.js CHANGED
@@ -137,6 +137,7 @@ function useNcpAgentRuntime({ sessionId, client, manager }) {
137
137
  if (!envelope) return null;
138
138
  setIsSending(true);
139
139
  if (sessionId) await manager.dispatch({
140
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
140
141
  type: NcpEventType.MessageSent,
141
142
  payload: {
142
143
  sessionId,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/hooks/use-ncp-agent-runtime.ts","../src/hooks/use-hydrated-ncp-agent.ts","../src/hooks/use-ncp-agent.ts","../src/attachments/ncp-attachments.ts"],"sourcesContent":["import { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { DefaultNcpAgentConversationStateManager } from \"@nextclaw/ncp-toolkit\";\nimport {\n type NcpAgentClientEndpoint,\n type NcpAgentSendEnvelope,\n type NcpAgentConversationSnapshot,\n type NcpEndpointEvent,\n type NcpMessage,\n type NcpOutboundMessageDraft,\n type NcpRunHandle,\n NcpEventType,\n} from \"@nextclaw/ncp\";\n\nexport type NcpAgentSendInput = string | NcpAgentSendEnvelope;\n\nexport type UseNcpAgentResult = {\n snapshot: NcpAgentConversationSnapshot;\n visibleMessages: readonly NcpMessage[];\n activeRunId: string | null;\n isRunning: boolean;\n isSending: boolean;\n send: (input: NcpAgentSendInput) => Promise<NcpRunHandle | null>;\n abort: () => Promise<void>;\n streamRun: () => Promise<void>;\n};\n\ntype UseNcpAgentRuntimeOptions = {\n sessionId?: string;\n client: NcpAgentClientEndpoint;\n manager: DefaultNcpAgentConversationStateManager;\n};\n\ntype ScopedManagerRef = {\n sessionId: string | null;\n manager: DefaultNcpAgentConversationStateManager;\n};\n\nconst EVENT_BATCH_DELAY_MS = 16;\n\nclass NcpEventDispatchBatcher {\n private readonly queue: NcpEndpointEvent[] = [];\n private flushTimerId: number | null = null;\n private isFlushing = false;\n private isDisposed = false;\n\n constructor(\n private readonly dispatchBatch: (\n events: readonly NcpEndpointEvent[],\n ) => Promise<void>,\n ) {}\n\n enqueue = (event: NcpEndpointEvent): void => {\n if (this.isDisposed) {\n return;\n }\n this.queue.push(event);\n this.scheduleFlush();\n };\n\n dispose = (): void => {\n this.isDisposed = true;\n if (this.flushTimerId !== null) {\n window.clearTimeout(this.flushTimerId);\n this.flushTimerId = null;\n }\n this.queue.length = 0;\n };\n\n private scheduleFlush = (): void => {\n if (\n this.flushTimerId !== null ||\n this.isFlushing ||\n this.queue.length === 0\n ) {\n return;\n }\n this.flushTimerId = window.setTimeout(() => {\n this.flushTimerId = null;\n void this.flush();\n }, EVENT_BATCH_DELAY_MS);\n };\n\n private flush = async (): Promise<void> => {\n if (this.isDisposed || this.isFlushing || this.queue.length === 0) {\n return;\n }\n\n this.isFlushing = true;\n try {\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0);\n await this.dispatchBatch(batch);\n }\n } finally {\n this.isFlushing = false;\n this.scheduleFlush();\n }\n };\n}\n\nfunction dispatchEventsToManager(\n manager: DefaultNcpAgentConversationStateManager,\n events: readonly NcpEndpointEvent[],\n): Promise<void> {\n const batchDispatch = (\n manager as DefaultNcpAgentConversationStateManager & {\n dispatchBatch?: (batch: readonly NcpEndpointEvent[]) => Promise<void>;\n }\n ).dispatchBatch;\n if (typeof batchDispatch === \"function\") {\n return batchDispatch.call(manager, events);\n }\n\n return events.reduce<Promise<void>>(\n (chain, event) => chain.then(() => manager.dispatch(event)),\n Promise.resolve(),\n );\n}\n\nfunction shouldDispatchEventToSession(\n event: NcpEndpointEvent,\n sessionId: string | undefined,\n): boolean {\n if (!sessionId) {\n return true;\n }\n const payload = \"payload\" in event ? event.payload : null;\n if (!payload || typeof payload !== \"object\") {\n return true;\n }\n if (!(\"sessionId\" in payload) || typeof payload.sessionId !== \"string\") {\n return true;\n }\n return payload.sessionId === sessionId;\n}\n\nfunction hasMessageContent(message: NcpMessage | NcpOutboundMessageDraft): boolean {\n return message.parts.some((part) => {\n if (\n part.type === \"text\" ||\n part.type === \"rich-text\" ||\n part.type === \"reasoning\"\n ) {\n return part.text.trim().length > 0;\n }\n return true;\n });\n}\n\nfunction normalizeSendEnvelope(\n input: NcpAgentSendInput,\n sessionId: string | undefined,\n): NcpAgentSendEnvelope | null {\n if (typeof input === \"string\") {\n const content = input.trim();\n if (!content) {\n return null;\n }\n return {\n ...(sessionId ? { sessionId } : {}),\n message: {\n id: `user-${Date.now().toString(36)}`,\n ...(sessionId ? { sessionId } : {}),\n role: \"user\",\n status: \"final\",\n parts: [{ type: \"text\", text: content }],\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n if (!hasMessageContent(input.message)) {\n return null;\n }\n\n const targetSessionId = input.sessionId || input.message.sessionId || sessionId;\n return {\n ...input,\n ...(targetSessionId ? { sessionId: targetSessionId } : {}),\n message: {\n ...input.message,\n ...(targetSessionId\n ? { sessionId: targetSessionId }\n : {}),\n },\n };\n}\n\nexport function useScopedAgentManager(\n sessionId: string | undefined,\n): DefaultNcpAgentConversationStateManager {\n const managerRef = useRef<ScopedManagerRef>();\n if (!managerRef.current) {\n managerRef.current = {\n sessionId: sessionId ?? null,\n manager: new DefaultNcpAgentConversationStateManager(),\n };\n } else if (sessionId && managerRef.current.sessionId === null) {\n managerRef.current.sessionId = sessionId;\n } else if (managerRef.current.sessionId !== (sessionId ?? null)) {\n managerRef.current = {\n sessionId: sessionId ?? null,\n manager: new DefaultNcpAgentConversationStateManager(),\n };\n }\n return managerRef.current.manager;\n}\n\nexport function useNcpAgentRuntime({\n sessionId,\n client,\n manager,\n}: UseNcpAgentRuntimeOptions): UseNcpAgentResult {\n const sessionIdRef = useRef<string | undefined>(sessionId);\n const snapshot = useSyncExternalStore(\n (onStoreChange) => manager.subscribe(() => onStoreChange()),\n () => manager.getSnapshot(),\n () => manager.getSnapshot(),\n );\n const [isSending, setIsSending] = useState(false);\n\n useEffect(() => {\n sessionIdRef.current = sessionId;\n }, [sessionId]);\n\n useEffect(() => {\n setIsSending(false);\n }, [sessionId]);\n\n useEffect(() => {\n const eventBatcher = new NcpEventDispatchBatcher((events) =>\n dispatchEventsToManager(manager, events),\n );\n const unsubscribeClient = client.subscribe((event) => {\n if (!shouldDispatchEventToSession(event, sessionIdRef.current)) {\n return;\n }\n eventBatcher.enqueue(event);\n });\n\n return () => {\n unsubscribeClient();\n eventBatcher.dispose();\n void client.stop();\n };\n }, [client, manager]);\n\n const visibleMessages: readonly NcpMessage[] = snapshot.streamingMessage\n ? [...snapshot.messages, snapshot.streamingMessage]\n : snapshot.messages;\n\n const activeRunId = snapshot.activeRun?.runId ?? null;\n const isRunning = !!snapshot.activeRun;\n\n const send = async (input: NcpAgentSendInput) => {\n if (isSending || isRunning) {\n return null;\n }\n const envelope = normalizeSendEnvelope(input, sessionId);\n if (!envelope) {\n return null;\n }\n\n setIsSending(true);\n if (sessionId) {\n await manager.dispatch({\n type: NcpEventType.MessageSent,\n payload: {\n sessionId,\n message: {\n ...envelope.message,\n sessionId,\n },\n metadata: envelope.metadata,\n },\n });\n }\n try {\n return await client.send(envelope);\n } finally {\n setIsSending(false);\n }\n };\n\n const abort = async () => {\n if (!sessionId) {\n return;\n }\n\n await client.abort({ sessionId });\n };\n\n const streamRun = async () => {\n if (!sessionId) {\n return;\n }\n await client.stop();\n await client.stream({ sessionId });\n };\n\n return {\n snapshot,\n visibleMessages,\n activeRunId,\n isRunning,\n isSending,\n send,\n abort,\n streamRun,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { NcpAgentClientEndpoint, NcpMessage, NcpRunContext } from \"@nextclaw/ncp\";\nimport type { DefaultNcpAgentConversationStateManager } from \"@nextclaw/ncp-toolkit\";\nimport {\n useNcpAgentRuntime,\n useScopedAgentManager,\n type UseNcpAgentResult,\n} from \"./use-ncp-agent-runtime.js\";\n\nexport type NcpConversationSeed = {\n messages: readonly NcpMessage[];\n status: \"idle\" | \"running\";\n};\n\nexport type NcpConversationSeedLoader = (\n sessionId: string,\n signal: AbortSignal,\n) => Promise<NcpConversationSeed>;\n\nexport type UseHydratedNcpAgentOptions = {\n sessionId?: string;\n client: NcpAgentClientEndpoint;\n loadSeed: NcpConversationSeedLoader;\n};\n\nexport type UseHydratedNcpAgentResult = UseNcpAgentResult & {\n isHydrating: boolean;\n hydrateError: Error | null;\n};\n\ntype LoadState = {\n requestId: number;\n controller: AbortController | null;\n};\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction resolveSessionHydratingState(params: {\n sessionId?: string;\n hydratedSessionId: string | null;\n isHydrating: boolean;\n}): boolean {\n const { hydratedSessionId, isHydrating, sessionId } = params;\n if (!sessionId) {\n return false;\n }\n return isHydrating || hydratedSessionId !== sessionId;\n}\n\nfunction managerAlreadyHasSessionState(\n manager: DefaultNcpAgentConversationStateManager,\n sessionId: string,\n): boolean {\n const snapshot = manager.getSnapshot();\n return (\n snapshot.activeRun?.sessionId === sessionId ||\n snapshot.streamingMessage?.sessionId === sessionId ||\n snapshot.messages.some((message) => message.sessionId === sessionId)\n );\n}\n\nfunction createHydratedActiveRun(\n seed: NcpConversationSeed,\n sessionId: string,\n): NcpRunContext | null {\n return seed.status === \"running\"\n ? {\n runId: null,\n sessionId,\n abortDisabledReason: null,\n }\n : null;\n}\n\nfunction isStaleHydrationRequest(\n loadState: LoadState,\n requestId: number,\n controller: AbortController,\n): boolean {\n return controller.signal.aborted || loadState.requestId !== requestId;\n}\n\nexport function useHydratedNcpAgent({\n sessionId,\n client,\n loadSeed,\n}: UseHydratedNcpAgentOptions): UseHydratedNcpAgentResult {\n const manager = useScopedAgentManager(sessionId);\n const runtime = useNcpAgentRuntime({ sessionId, client, manager });\n const [isHydrating, setIsHydrating] = useState(true);\n const [hydrateError, setHydrateError] = useState<Error | null>(null);\n const [hydratedSessionId, setHydratedSessionId] = useState<string | null>(\n null,\n );\n const loadStateRef = useRef<LoadState>({ requestId: 0, controller: null });\n\n const resetEmptySession = useCallback(async () => {\n await client.stop();\n manager.reset();\n setHydrateError(null);\n setHydratedSessionId(null);\n setIsHydrating(false);\n loadStateRef.current = {\n requestId: loadStateRef.current.requestId + 1,\n controller: null,\n };\n }, [client, manager]);\n\n const markHydratedFromLiveState = useCallback((targetSessionId: string) => {\n setHydrateError(null);\n setHydratedSessionId(targetSessionId);\n setIsHydrating(false);\n }, []);\n\n const hydrateSeed = useCallback(async () => {\n loadStateRef.current.controller?.abort();\n\n if (!sessionId) {\n await resetEmptySession();\n return;\n }\n\n const controller = new AbortController();\n const requestId = loadStateRef.current.requestId + 1;\n loadStateRef.current = {\n requestId,\n controller,\n };\n\n if (managerAlreadyHasSessionState(manager, sessionId)) {\n markHydratedFromLiveState(sessionId);\n if (loadStateRef.current.controller === controller) {\n loadStateRef.current.controller = null;\n }\n return;\n }\n\n await client.stop();\n manager.reset();\n setHydrateError(null);\n setIsHydrating(true);\n\n try {\n const seed = await loadSeed(sessionId, controller.signal);\n if (isStaleHydrationRequest(loadStateRef.current, requestId, controller)) {\n return;\n }\n\n manager.hydrate({\n sessionId,\n messages: seed.messages,\n activeRun: createHydratedActiveRun(seed, sessionId),\n });\n markHydratedFromLiveState(sessionId);\n void client.stream({ sessionId }).catch((error) => {\n if (loadStateRef.current.requestId !== requestId) {\n return;\n }\n setHydrateError(toError(error));\n });\n } catch (error) {\n if (isStaleHydrationRequest(loadStateRef.current, requestId, controller)) {\n return;\n }\n setHydrateError(toError(error));\n setHydratedSessionId(sessionId);\n setIsHydrating(false);\n } finally {\n if (loadStateRef.current.controller === controller) {\n loadStateRef.current.controller = null;\n }\n }\n }, [\n client,\n loadSeed,\n manager,\n markHydratedFromLiveState,\n resetEmptySession,\n sessionId,\n ]);\n\n useEffect(() => {\n void hydrateSeed();\n\n return () => {\n loadStateRef.current.controller?.abort();\n loadStateRef.current.controller = null;\n };\n }, [hydrateSeed]);\n\n return {\n ...runtime,\n isHydrating: resolveSessionHydratingState({\n sessionId,\n hydratedSessionId,\n isHydrating,\n }),\n hydrateError,\n };\n}\n","import type { NcpAgentClientEndpoint } from \"@nextclaw/ncp\";\nimport { useNcpAgentRuntime, useScopedAgentManager } from \"./use-ncp-agent-runtime.js\";\n\nexport function useNcpAgent(sessionId: string, client: NcpAgentClientEndpoint) {\n const manager = useScopedAgentManager(sessionId);\n return useNcpAgentRuntime({ sessionId, client, manager });\n}\n","import type { NcpAgentSendEnvelope, NcpMessagePart } from \"@nextclaw/ncp\";\n\nexport const DEFAULT_NCP_IMAGE_ATTACHMENT_ACCEPT =\n \"image/png,image/jpeg,image/webp,image/gif\";\n\nexport const DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/webp\",\n \"image/gif\",\n] as const;\n\nexport const DEFAULT_NCP_ATTACHMENT_MAX_BYTES = 200 * 1024 * 1024;\nexport const DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES = DEFAULT_NCP_ATTACHMENT_MAX_BYTES;\nexport const DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE = \"application/octet-stream\";\n\nexport type NcpDraftAttachment = {\n id: string;\n name: string;\n mimeType: string;\n sizeBytes: number;\n assetUri?: string;\n url?: string;\n contentBase64?: string;\n};\n\nexport type NcpRejectedAttachment = {\n fileName: string;\n mimeType: string;\n sizeBytes: number;\n reason: \"unsupported-type\" | \"too-large\" | \"read-failed\";\n};\n\nexport type ReadNcpDraftAttachmentsOptions = {\n acceptedMimeTypes?: readonly string[];\n maxBytes?: number;\n};\n\nexport type UploadNcpDraftAttachmentsOptions = ReadNcpDraftAttachmentsOptions & {\n uploadBatch: (files: File[]) => Promise<NcpDraftAttachment[]>;\n};\n\nexport type ReadNcpDraftAttachmentsResult = {\n attachments: NcpDraftAttachment[];\n rejected: NcpRejectedAttachment[];\n};\n\nfunction createAttachmentId(): string {\n return `ncp-file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction readFileAsDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error ?? new Error(`Failed to read ${file.name}`));\n reader.onload = () => {\n if (typeof reader.result !== \"string\") {\n reject(new Error(`Unexpected FileReader result for ${file.name}`));\n return;\n }\n resolve(reader.result);\n };\n reader.readAsDataURL(file);\n });\n}\n\nfunction toBase64Content(dataUrl: string): string {\n const commaIndex = dataUrl.indexOf(\",\");\n return commaIndex >= 0 ? dataUrl.slice(commaIndex + 1) : dataUrl;\n}\n\nfunction normalizeAttachmentMimeType(file: File): string {\n const mimeType = file.type.trim().toLowerCase();\n return mimeType.length > 0 ? mimeType : DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE;\n}\n\nfunction validateAttachmentFile(\n file: File,\n options: ReadNcpDraftAttachmentsOptions,\n): { ok: true; mimeType: string } | { ok: false; rejected: NcpRejectedAttachment } {\n const acceptedMimeTypes =\n options.acceptedMimeTypes && options.acceptedMimeTypes.length > 0\n ? new Set(options.acceptedMimeTypes.map((mimeType) => mimeType.trim().toLowerCase()))\n : null;\n const maxBytes = options.maxBytes ?? DEFAULT_NCP_ATTACHMENT_MAX_BYTES;\n const mimeType = normalizeAttachmentMimeType(file);\n if (acceptedMimeTypes && !acceptedMimeTypes.has(mimeType)) {\n return {\n ok: false,\n rejected: {\n fileName: file.name,\n mimeType,\n sizeBytes: file.size,\n reason: \"unsupported-type\",\n },\n };\n }\n if (file.size > maxBytes) {\n return {\n ok: false,\n rejected: {\n fileName: file.name,\n mimeType,\n sizeBytes: file.size,\n reason: \"too-large\",\n },\n };\n }\n return { ok: true, mimeType };\n}\n\nexport function buildNcpImageAttachmentDataUrl(attachment: NcpDraftAttachment): string {\n if (attachment.url?.trim()) {\n return attachment.url.trim();\n }\n if (!attachment.contentBase64?.trim()) {\n throw new Error(`Attachment ${attachment.name} does not have image content.`);\n }\n return `data:${attachment.mimeType};base64,${attachment.contentBase64}`;\n}\n\nexport function buildNcpRequestEnvelope(params: {\n sessionId?: string;\n text?: string;\n attachments?: readonly NcpDraftAttachment[];\n parts?: readonly NcpMessagePart[];\n metadata?: Record<string, unknown>;\n messageId?: string;\n timestamp?: string;\n}): NcpAgentSendEnvelope | null {\n const parts =\n params.parts && params.parts.length > 0\n ? params.parts.map((part) => structuredClone(part))\n : [\n ...((params.text?.trim() ?? \"\")\n ? [{ type: \"text\" as const, text: params.text!.trim() }]\n : []),\n ...(params.attachments ?? []).map((attachment) => ({\n type: \"file\" as const,\n name: attachment.name,\n mimeType: attachment.mimeType,\n ...(attachment.assetUri?.trim()\n ? { assetUri: attachment.assetUri.trim() }\n : {}),\n ...(attachment.url?.trim() ? { url: attachment.url.trim() } : {}),\n ...(attachment.contentBase64?.trim()\n ? { contentBase64: attachment.contentBase64.trim() }\n : {}),\n sizeBytes: attachment.sizeBytes,\n })),\n ];\n\n if (parts.length === 0) {\n return null;\n }\n\n const timestamp = params.timestamp ?? new Date().toISOString();\n const messageId = params.messageId ?? `user-${Date.now().toString(36)}`;\n\n return {\n ...(params.sessionId ? { sessionId: params.sessionId } : {}),\n message: {\n id: messageId,\n ...(params.sessionId ? { sessionId: params.sessionId } : {}),\n role: \"user\",\n status: \"final\",\n parts,\n timestamp,\n ...(params.metadata ? { metadata: params.metadata } : {}),\n },\n ...(params.metadata ? { metadata: params.metadata } : {}),\n };\n}\n\nexport async function readFilesAsNcpDraftAttachments(\n files: Iterable<File>,\n options: ReadNcpDraftAttachmentsOptions = {},\n): Promise<ReadNcpDraftAttachmentsResult> {\n const attachments: NcpDraftAttachment[] = [];\n const rejected: NcpRejectedAttachment[] = [];\n\n for (const file of files) {\n const validation = validateAttachmentFile(file, options);\n if (!validation.ok) {\n rejected.push(validation.rejected);\n continue;\n }\n\n try {\n const dataUrl = await readFileAsDataUrl(file);\n attachments.push({\n id: createAttachmentId(),\n name: file.name,\n mimeType: validation.mimeType,\n contentBase64: toBase64Content(dataUrl),\n sizeBytes: file.size,\n });\n } catch {\n rejected.push({\n fileName: file.name,\n mimeType: validation.mimeType,\n sizeBytes: file.size,\n reason: \"read-failed\",\n });\n }\n }\n\n return { attachments, rejected };\n}\n\nexport async function uploadFilesAsNcpDraftAttachments(\n files: Iterable<File>,\n options: UploadNcpDraftAttachmentsOptions,\n): Promise<ReadNcpDraftAttachmentsResult> {\n const validFiles: File[] = [];\n const rejected: NcpRejectedAttachment[] = [];\n\n for (const file of files) {\n const validation = validateAttachmentFile(file, options);\n if (!validation.ok) {\n rejected.push(validation.rejected);\n continue;\n }\n validFiles.push(file);\n }\n\n if (validFiles.length === 0) {\n return { attachments: [], rejected };\n }\n\n try {\n const attachments = await options.uploadBatch(validFiles);\n return {\n attachments,\n rejected,\n };\n } catch {\n rejected.push(\n ...validFiles.map((file) => ({\n fileName: file.name,\n mimeType: normalizeAttachmentMimeType(file),\n sizeBytes: file.size,\n reason: \"read-failed\" as const,\n })),\n );\n return {\n attachments: [],\n rejected,\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/hooks/use-ncp-agent-runtime.ts","../src/hooks/use-hydrated-ncp-agent.ts","../src/hooks/use-ncp-agent.ts","../src/attachments/ncp-attachments.ts"],"sourcesContent":["import { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { DefaultNcpAgentConversationStateManager } from \"@nextclaw/ncp-toolkit\";\nimport {\n type NcpAgentClientEndpoint,\n type NcpAgentSendEnvelope,\n type NcpAgentConversationSnapshot,\n type NcpEndpointEvent,\n type NcpMessage,\n type NcpOutboundMessageDraft,\n type NcpRunHandle,\n NcpEventType,\n} from \"@nextclaw/ncp\";\n\nexport type NcpAgentSendInput = string | NcpAgentSendEnvelope;\n\nexport type UseNcpAgentResult = {\n snapshot: NcpAgentConversationSnapshot;\n visibleMessages: readonly NcpMessage[];\n activeRunId: string | null;\n isRunning: boolean;\n isSending: boolean;\n send: (input: NcpAgentSendInput) => Promise<NcpRunHandle | null>;\n abort: () => Promise<void>;\n streamRun: () => Promise<void>;\n};\n\ntype UseNcpAgentRuntimeOptions = {\n sessionId?: string;\n client: NcpAgentClientEndpoint;\n manager: DefaultNcpAgentConversationStateManager;\n};\n\ntype ScopedManagerRef = {\n sessionId: string | null;\n manager: DefaultNcpAgentConversationStateManager;\n};\n\nconst EVENT_BATCH_DELAY_MS = 16;\n\nclass NcpEventDispatchBatcher {\n private readonly queue: NcpEndpointEvent[] = [];\n private flushTimerId: number | null = null;\n private isFlushing = false;\n private isDisposed = false;\n\n constructor(\n private readonly dispatchBatch: (\n events: readonly NcpEndpointEvent[],\n ) => Promise<void>,\n ) {}\n\n enqueue = (event: NcpEndpointEvent): void => {\n if (this.isDisposed) {\n return;\n }\n this.queue.push(event);\n this.scheduleFlush();\n };\n\n dispose = (): void => {\n this.isDisposed = true;\n if (this.flushTimerId !== null) {\n window.clearTimeout(this.flushTimerId);\n this.flushTimerId = null;\n }\n this.queue.length = 0;\n };\n\n private scheduleFlush = (): void => {\n if (\n this.flushTimerId !== null ||\n this.isFlushing ||\n this.queue.length === 0\n ) {\n return;\n }\n this.flushTimerId = window.setTimeout(() => {\n this.flushTimerId = null;\n void this.flush();\n }, EVENT_BATCH_DELAY_MS);\n };\n\n private flush = async (): Promise<void> => {\n if (this.isDisposed || this.isFlushing || this.queue.length === 0) {\n return;\n }\n\n this.isFlushing = true;\n try {\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0);\n await this.dispatchBatch(batch);\n }\n } finally {\n this.isFlushing = false;\n this.scheduleFlush();\n }\n };\n}\n\nfunction dispatchEventsToManager(\n manager: DefaultNcpAgentConversationStateManager,\n events: readonly NcpEndpointEvent[],\n): Promise<void> {\n const batchDispatch = (\n manager as DefaultNcpAgentConversationStateManager & {\n dispatchBatch?: (batch: readonly NcpEndpointEvent[]) => Promise<void>;\n }\n ).dispatchBatch;\n if (typeof batchDispatch === \"function\") {\n return batchDispatch.call(manager, events);\n }\n\n return events.reduce<Promise<void>>(\n (chain, event) => chain.then(() => manager.dispatch(event)),\n Promise.resolve(),\n );\n}\n\nfunction shouldDispatchEventToSession(\n event: NcpEndpointEvent,\n sessionId: string | undefined,\n): boolean {\n if (!sessionId) {\n return true;\n }\n const payload = \"payload\" in event ? event.payload : null;\n if (!payload || typeof payload !== \"object\") {\n return true;\n }\n if (!(\"sessionId\" in payload) || typeof payload.sessionId !== \"string\") {\n return true;\n }\n return payload.sessionId === sessionId;\n}\n\nfunction hasMessageContent(message: NcpMessage | NcpOutboundMessageDraft): boolean {\n return message.parts.some((part) => {\n if (\n part.type === \"text\" ||\n part.type === \"rich-text\" ||\n part.type === \"reasoning\"\n ) {\n return part.text.trim().length > 0;\n }\n return true;\n });\n}\n\nfunction normalizeSendEnvelope(\n input: NcpAgentSendInput,\n sessionId: string | undefined,\n): NcpAgentSendEnvelope | null {\n if (typeof input === \"string\") {\n const content = input.trim();\n if (!content) {\n return null;\n }\n return {\n ...(sessionId ? { sessionId } : {}),\n message: {\n id: `user-${Date.now().toString(36)}`,\n ...(sessionId ? { sessionId } : {}),\n role: \"user\",\n status: \"final\",\n parts: [{ type: \"text\", text: content }],\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n if (!hasMessageContent(input.message)) {\n return null;\n }\n\n const targetSessionId = input.sessionId || input.message.sessionId || sessionId;\n return {\n ...input,\n ...(targetSessionId ? { sessionId: targetSessionId } : {}),\n message: {\n ...input.message,\n ...(targetSessionId\n ? { sessionId: targetSessionId }\n : {}),\n },\n };\n}\n\nexport function useScopedAgentManager(\n sessionId: string | undefined,\n): DefaultNcpAgentConversationStateManager {\n const managerRef = useRef<ScopedManagerRef>();\n if (!managerRef.current) {\n managerRef.current = {\n sessionId: sessionId ?? null,\n manager: new DefaultNcpAgentConversationStateManager(),\n };\n } else if (sessionId && managerRef.current.sessionId === null) {\n managerRef.current.sessionId = sessionId;\n } else if (managerRef.current.sessionId !== (sessionId ?? null)) {\n managerRef.current = {\n sessionId: sessionId ?? null,\n manager: new DefaultNcpAgentConversationStateManager(),\n };\n }\n return managerRef.current.manager;\n}\n\nexport function useNcpAgentRuntime({\n sessionId,\n client,\n manager,\n}: UseNcpAgentRuntimeOptions): UseNcpAgentResult {\n const sessionIdRef = useRef<string | undefined>(sessionId);\n const snapshot = useSyncExternalStore(\n (onStoreChange) => manager.subscribe(() => onStoreChange()),\n () => manager.getSnapshot(),\n () => manager.getSnapshot(),\n );\n const [isSending, setIsSending] = useState(false);\n\n useEffect(() => {\n sessionIdRef.current = sessionId;\n }, [sessionId]);\n\n useEffect(() => {\n setIsSending(false);\n }, [sessionId]);\n\n useEffect(() => {\n const eventBatcher = new NcpEventDispatchBatcher((events) =>\n dispatchEventsToManager(manager, events),\n );\n const unsubscribeClient = client.subscribe((event) => {\n if (!shouldDispatchEventToSession(event, sessionIdRef.current)) {\n return;\n }\n eventBatcher.enqueue(event);\n });\n\n return () => {\n unsubscribeClient();\n eventBatcher.dispose();\n void client.stop();\n };\n }, [client, manager]);\n\n const visibleMessages: readonly NcpMessage[] = snapshot.streamingMessage\n ? [...snapshot.messages, snapshot.streamingMessage]\n : snapshot.messages;\n\n const activeRunId = snapshot.activeRun?.runId ?? null;\n const isRunning = !!snapshot.activeRun;\n\n const send = async (input: NcpAgentSendInput) => {\n if (isSending || isRunning) {\n return null;\n }\n const envelope = normalizeSendEnvelope(input, sessionId);\n if (!envelope) {\n return null;\n }\n\n setIsSending(true);\n if (sessionId) {\n await manager.dispatch({\n occurredAt: new Date().toISOString(),\n type: NcpEventType.MessageSent,\n payload: {\n sessionId,\n message: {\n ...envelope.message,\n sessionId,\n },\n metadata: envelope.metadata,\n },\n });\n }\n try {\n return await client.send(envelope);\n } finally {\n setIsSending(false);\n }\n };\n\n const abort = async () => {\n if (!sessionId) {\n return;\n }\n\n await client.abort({ sessionId });\n };\n\n const streamRun = async () => {\n if (!sessionId) {\n return;\n }\n await client.stop();\n await client.stream({ sessionId });\n };\n\n return {\n snapshot,\n visibleMessages,\n activeRunId,\n isRunning,\n isSending,\n send,\n abort,\n streamRun,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { NcpAgentClientEndpoint, NcpMessage, NcpRunContext } from \"@nextclaw/ncp\";\nimport type { DefaultNcpAgentConversationStateManager } from \"@nextclaw/ncp-toolkit\";\nimport {\n useNcpAgentRuntime,\n useScopedAgentManager,\n type UseNcpAgentResult,\n} from \"./use-ncp-agent-runtime.js\";\n\nexport type NcpConversationSeed = {\n messages: readonly NcpMessage[];\n status: \"idle\" | \"running\";\n};\n\nexport type NcpConversationSeedLoader = (\n sessionId: string,\n signal: AbortSignal,\n) => Promise<NcpConversationSeed>;\n\nexport type UseHydratedNcpAgentOptions = {\n sessionId?: string;\n client: NcpAgentClientEndpoint;\n loadSeed: NcpConversationSeedLoader;\n};\n\nexport type UseHydratedNcpAgentResult = UseNcpAgentResult & {\n isHydrating: boolean;\n hydrateError: Error | null;\n};\n\ntype LoadState = {\n requestId: number;\n controller: AbortController | null;\n};\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction resolveSessionHydratingState(params: {\n sessionId?: string;\n hydratedSessionId: string | null;\n isHydrating: boolean;\n}): boolean {\n const { hydratedSessionId, isHydrating, sessionId } = params;\n if (!sessionId) {\n return false;\n }\n return isHydrating || hydratedSessionId !== sessionId;\n}\n\nfunction managerAlreadyHasSessionState(\n manager: DefaultNcpAgentConversationStateManager,\n sessionId: string,\n): boolean {\n const snapshot = manager.getSnapshot();\n return (\n snapshot.activeRun?.sessionId === sessionId ||\n snapshot.streamingMessage?.sessionId === sessionId ||\n snapshot.messages.some((message) => message.sessionId === sessionId)\n );\n}\n\nfunction createHydratedActiveRun(\n seed: NcpConversationSeed,\n sessionId: string,\n): NcpRunContext | null {\n return seed.status === \"running\"\n ? {\n runId: null,\n sessionId,\n abortDisabledReason: null,\n }\n : null;\n}\n\nfunction isStaleHydrationRequest(\n loadState: LoadState,\n requestId: number,\n controller: AbortController,\n): boolean {\n return controller.signal.aborted || loadState.requestId !== requestId;\n}\n\nexport function useHydratedNcpAgent({\n sessionId,\n client,\n loadSeed,\n}: UseHydratedNcpAgentOptions): UseHydratedNcpAgentResult {\n const manager = useScopedAgentManager(sessionId);\n const runtime = useNcpAgentRuntime({ sessionId, client, manager });\n const [isHydrating, setIsHydrating] = useState(true);\n const [hydrateError, setHydrateError] = useState<Error | null>(null);\n const [hydratedSessionId, setHydratedSessionId] = useState<string | null>(\n null,\n );\n const loadStateRef = useRef<LoadState>({ requestId: 0, controller: null });\n\n const resetEmptySession = useCallback(async () => {\n await client.stop();\n manager.reset();\n setHydrateError(null);\n setHydratedSessionId(null);\n setIsHydrating(false);\n loadStateRef.current = {\n requestId: loadStateRef.current.requestId + 1,\n controller: null,\n };\n }, [client, manager]);\n\n const markHydratedFromLiveState = useCallback((targetSessionId: string) => {\n setHydrateError(null);\n setHydratedSessionId(targetSessionId);\n setIsHydrating(false);\n }, []);\n\n const hydrateSeed = useCallback(async () => {\n loadStateRef.current.controller?.abort();\n\n if (!sessionId) {\n await resetEmptySession();\n return;\n }\n\n const controller = new AbortController();\n const requestId = loadStateRef.current.requestId + 1;\n loadStateRef.current = {\n requestId,\n controller,\n };\n\n if (managerAlreadyHasSessionState(manager, sessionId)) {\n markHydratedFromLiveState(sessionId);\n if (loadStateRef.current.controller === controller) {\n loadStateRef.current.controller = null;\n }\n return;\n }\n\n await client.stop();\n manager.reset();\n setHydrateError(null);\n setIsHydrating(true);\n\n try {\n const seed = await loadSeed(sessionId, controller.signal);\n if (isStaleHydrationRequest(loadStateRef.current, requestId, controller)) {\n return;\n }\n\n manager.hydrate({\n sessionId,\n messages: seed.messages,\n activeRun: createHydratedActiveRun(seed, sessionId),\n });\n markHydratedFromLiveState(sessionId);\n void client.stream({ sessionId }).catch((error) => {\n if (loadStateRef.current.requestId !== requestId) {\n return;\n }\n setHydrateError(toError(error));\n });\n } catch (error) {\n if (isStaleHydrationRequest(loadStateRef.current, requestId, controller)) {\n return;\n }\n setHydrateError(toError(error));\n setHydratedSessionId(sessionId);\n setIsHydrating(false);\n } finally {\n if (loadStateRef.current.controller === controller) {\n loadStateRef.current.controller = null;\n }\n }\n }, [\n client,\n loadSeed,\n manager,\n markHydratedFromLiveState,\n resetEmptySession,\n sessionId,\n ]);\n\n useEffect(() => {\n void hydrateSeed();\n\n return () => {\n loadStateRef.current.controller?.abort();\n loadStateRef.current.controller = null;\n };\n }, [hydrateSeed]);\n\n return {\n ...runtime,\n isHydrating: resolveSessionHydratingState({\n sessionId,\n hydratedSessionId,\n isHydrating,\n }),\n hydrateError,\n };\n}\n","import type { NcpAgentClientEndpoint } from \"@nextclaw/ncp\";\nimport { useNcpAgentRuntime, useScopedAgentManager } from \"./use-ncp-agent-runtime.js\";\n\nexport function useNcpAgent(sessionId: string, client: NcpAgentClientEndpoint) {\n const manager = useScopedAgentManager(sessionId);\n return useNcpAgentRuntime({ sessionId, client, manager });\n}\n","import type { NcpAgentSendEnvelope, NcpMessagePart } from \"@nextclaw/ncp\";\n\nexport const DEFAULT_NCP_IMAGE_ATTACHMENT_ACCEPT =\n \"image/png,image/jpeg,image/webp,image/gif\";\n\nexport const DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/webp\",\n \"image/gif\",\n] as const;\n\nexport const DEFAULT_NCP_ATTACHMENT_MAX_BYTES = 200 * 1024 * 1024;\nexport const DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES = DEFAULT_NCP_ATTACHMENT_MAX_BYTES;\nexport const DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE = \"application/octet-stream\";\n\nexport type NcpDraftAttachment = {\n id: string;\n name: string;\n mimeType: string;\n sizeBytes: number;\n assetUri?: string;\n url?: string;\n contentBase64?: string;\n};\n\nexport type NcpRejectedAttachment = {\n fileName: string;\n mimeType: string;\n sizeBytes: number;\n reason: \"unsupported-type\" | \"too-large\" | \"read-failed\";\n};\n\nexport type ReadNcpDraftAttachmentsOptions = {\n acceptedMimeTypes?: readonly string[];\n maxBytes?: number;\n};\n\nexport type UploadNcpDraftAttachmentsOptions = ReadNcpDraftAttachmentsOptions & {\n uploadBatch: (files: File[]) => Promise<NcpDraftAttachment[]>;\n};\n\nexport type ReadNcpDraftAttachmentsResult = {\n attachments: NcpDraftAttachment[];\n rejected: NcpRejectedAttachment[];\n};\n\nfunction createAttachmentId(): string {\n return `ncp-file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction readFileAsDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error ?? new Error(`Failed to read ${file.name}`));\n reader.onload = () => {\n if (typeof reader.result !== \"string\") {\n reject(new Error(`Unexpected FileReader result for ${file.name}`));\n return;\n }\n resolve(reader.result);\n };\n reader.readAsDataURL(file);\n });\n}\n\nfunction toBase64Content(dataUrl: string): string {\n const commaIndex = dataUrl.indexOf(\",\");\n return commaIndex >= 0 ? dataUrl.slice(commaIndex + 1) : dataUrl;\n}\n\nfunction normalizeAttachmentMimeType(file: File): string {\n const mimeType = file.type.trim().toLowerCase();\n return mimeType.length > 0 ? mimeType : DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE;\n}\n\nfunction validateAttachmentFile(\n file: File,\n options: ReadNcpDraftAttachmentsOptions,\n): { ok: true; mimeType: string } | { ok: false; rejected: NcpRejectedAttachment } {\n const acceptedMimeTypes =\n options.acceptedMimeTypes && options.acceptedMimeTypes.length > 0\n ? new Set(options.acceptedMimeTypes.map((mimeType) => mimeType.trim().toLowerCase()))\n : null;\n const maxBytes = options.maxBytes ?? DEFAULT_NCP_ATTACHMENT_MAX_BYTES;\n const mimeType = normalizeAttachmentMimeType(file);\n if (acceptedMimeTypes && !acceptedMimeTypes.has(mimeType)) {\n return {\n ok: false,\n rejected: {\n fileName: file.name,\n mimeType,\n sizeBytes: file.size,\n reason: \"unsupported-type\",\n },\n };\n }\n if (file.size > maxBytes) {\n return {\n ok: false,\n rejected: {\n fileName: file.name,\n mimeType,\n sizeBytes: file.size,\n reason: \"too-large\",\n },\n };\n }\n return { ok: true, mimeType };\n}\n\nexport function buildNcpImageAttachmentDataUrl(attachment: NcpDraftAttachment): string {\n if (attachment.url?.trim()) {\n return attachment.url.trim();\n }\n if (!attachment.contentBase64?.trim()) {\n throw new Error(`Attachment ${attachment.name} does not have image content.`);\n }\n return `data:${attachment.mimeType};base64,${attachment.contentBase64}`;\n}\n\nexport function buildNcpRequestEnvelope(params: {\n sessionId?: string;\n text?: string;\n attachments?: readonly NcpDraftAttachment[];\n parts?: readonly NcpMessagePart[];\n metadata?: Record<string, unknown>;\n messageId?: string;\n timestamp?: string;\n}): NcpAgentSendEnvelope | null {\n const parts =\n params.parts && params.parts.length > 0\n ? params.parts.map((part) => structuredClone(part))\n : [\n ...((params.text?.trim() ?? \"\")\n ? [{ type: \"text\" as const, text: params.text!.trim() }]\n : []),\n ...(params.attachments ?? []).map((attachment) => ({\n type: \"file\" as const,\n name: attachment.name,\n mimeType: attachment.mimeType,\n ...(attachment.assetUri?.trim()\n ? { assetUri: attachment.assetUri.trim() }\n : {}),\n ...(attachment.url?.trim() ? { url: attachment.url.trim() } : {}),\n ...(attachment.contentBase64?.trim()\n ? { contentBase64: attachment.contentBase64.trim() }\n : {}),\n sizeBytes: attachment.sizeBytes,\n })),\n ];\n\n if (parts.length === 0) {\n return null;\n }\n\n const timestamp = params.timestamp ?? new Date().toISOString();\n const messageId = params.messageId ?? `user-${Date.now().toString(36)}`;\n\n return {\n ...(params.sessionId ? { sessionId: params.sessionId } : {}),\n message: {\n id: messageId,\n ...(params.sessionId ? { sessionId: params.sessionId } : {}),\n role: \"user\",\n status: \"final\",\n parts,\n timestamp,\n ...(params.metadata ? { metadata: params.metadata } : {}),\n },\n ...(params.metadata ? { metadata: params.metadata } : {}),\n };\n}\n\nexport async function readFilesAsNcpDraftAttachments(\n files: Iterable<File>,\n options: ReadNcpDraftAttachmentsOptions = {},\n): Promise<ReadNcpDraftAttachmentsResult> {\n const attachments: NcpDraftAttachment[] = [];\n const rejected: NcpRejectedAttachment[] = [];\n\n for (const file of files) {\n const validation = validateAttachmentFile(file, options);\n if (!validation.ok) {\n rejected.push(validation.rejected);\n continue;\n }\n\n try {\n const dataUrl = await readFileAsDataUrl(file);\n attachments.push({\n id: createAttachmentId(),\n name: file.name,\n mimeType: validation.mimeType,\n contentBase64: toBase64Content(dataUrl),\n sizeBytes: file.size,\n });\n } catch {\n rejected.push({\n fileName: file.name,\n mimeType: validation.mimeType,\n sizeBytes: file.size,\n reason: \"read-failed\",\n });\n }\n }\n\n return { attachments, rejected };\n}\n\nexport async function uploadFilesAsNcpDraftAttachments(\n files: Iterable<File>,\n options: UploadNcpDraftAttachmentsOptions,\n): Promise<ReadNcpDraftAttachmentsResult> {\n const validFiles: File[] = [];\n const rejected: NcpRejectedAttachment[] = [];\n\n for (const file of files) {\n const validation = validateAttachmentFile(file, options);\n if (!validation.ok) {\n rejected.push(validation.rejected);\n continue;\n }\n validFiles.push(file);\n }\n\n if (validFiles.length === 0) {\n return { attachments: [], rejected };\n }\n\n try {\n const attachments = await options.uploadBatch(validFiles);\n return {\n attachments,\n rejected,\n };\n } catch {\n rejected.push(\n ...validFiles.map((file) => ({\n fileName: file.name,\n mimeType: normalizeAttachmentMimeType(file),\n sizeBytes: file.size,\n reason: \"read-failed\" as const,\n })),\n );\n return {\n attachments: [],\n rejected,\n };\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ncp-react",
3
- "version": "0.4.56",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "description": "React bindings for building NCP-based agent applications.",
6
6
  "type": "module",
@@ -15,8 +15,8 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
- "@nextclaw/ncp": "0.6.6",
19
- "@nextclaw/ncp-toolkit": "0.5.41"
18
+ "@nextclaw/ncp": "0.7.0",
19
+ "@nextclaw/ncp-toolkit": "0.6.0"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "react": "^18.0.0 || ^19.0.0"