feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing - Add AUTO-TRIGGER-SUMMARY.md documentation - Add FINAL-INTEGRATION-SUMMARY.md documentation - Complete Prometheus integration (6 commands + 4 tools) - Complete Dexto integration (12 commands + 5 tools) - Enhanced Ralph with access to all agents - Fix /clawd command (removed disable-model-invocation) - Update hooks.json to v5 with intelligent routing - 291 total skills now available - All 21 commands with automatic routing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
186
dexto/packages/client-sdk/CHANGELOG.md
Normal file
186
dexto/packages/client-sdk/CHANGELOG.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# @dexto/client-sdk
|
||||
|
||||
## 1.5.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 042f4f0: ### CLI Improvements
|
||||
- Add `/export` command to export conversations as Markdown or JSON
|
||||
- Add `Ctrl+T` toggle for task list visibility during processing
|
||||
- Improve task list UI with collapsible view near the processing message
|
||||
- Fix race condition causing duplicate rendering (mainly visible with explore tool)
|
||||
- Don't truncate `pattern` and `question` args in tool output display
|
||||
|
||||
### Bug Fixes
|
||||
- Fix build script to preserve `.dexto` storage (conversations, logs) during clean builds
|
||||
- Fix `@dexto/tools-todo` versioning - add to fixed version group in changeset config
|
||||
|
||||
### Configuration Changes
|
||||
- Remove approval timeout defaults - now waits indefinitely (better UX for CLI)
|
||||
- Add package versioning guidelines to AGENTS.md
|
||||
|
||||
## 1.5.5
|
||||
|
||||
## 1.5.4
|
||||
|
||||
## 1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- e7722e5: Minor version bump for new release with bundler, custom tool pkgs, etc.
|
||||
|
||||
## 1.4.0
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- eb266af: Migrate WebUI from next-js to vite. Fix any typing in web UI. Improve types in core. minor renames in event schemas
|
||||
|
||||
## 1.2.6
|
||||
|
||||
## 1.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8f373cc: Migrate server API to Hono framework with feature flag
|
||||
- Migrated Express server to Hono with OpenAPI schema generation
|
||||
- Added DEXTO_USE_HONO environment variable flag (default: false for backward compatibility)
|
||||
- Fixed WebSocket test isolation by adding sessionId filtering
|
||||
- Fixed logger context to pass structured objects instead of stringified JSON
|
||||
- Fixed CI workflow for OpenAPI docs synchronization
|
||||
- Updated documentation links and fixed broken API references
|
||||
|
||||
- f28ad7e: Migrate webUI to use client-sdk, add agents.md file to webui,improve types in apis for consumption
|
||||
- a35a256: Migrate from WebSocket to Server-Sent Events (SSE) for real-time streaming
|
||||
- Replace WebSocket with SSE for message streaming via new `/api/message-stream` endpoint
|
||||
- Refactor approval system from event-based providers to simpler handler pattern
|
||||
- Add new APIs for session approval
|
||||
- Move session title generation to a separate API
|
||||
- Add `ApprovalCoordinator` for multi-client SSE routing with sessionId mapping
|
||||
- Add stream and generate methods to DextoAgent and integ tests for itq=
|
||||
|
||||
- 5a26bdf: Update hono server to chain apis to keep type info, update client sdk to be fully typed
|
||||
- ac649fd: Fix error handling and UI bugs, add gpt-5.1, gemini-3
|
||||
|
||||
## 1.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- cd706e7: bump up version after fixing node-machine-id
|
||||
- Updated dependencies [cd706e7]
|
||||
- @dexto/core@1.2.4
|
||||
|
||||
## 1.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5d6ae73: Bump up version to fix bugs
|
||||
- Updated dependencies [5d6ae73]
|
||||
- @dexto/core@1.2.3
|
||||
|
||||
## 1.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @dexto/core@1.2.2
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @dexto/core@1.2.1
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b51e4d9]
|
||||
- Updated dependencies [a27ddf0]
|
||||
- Updated dependencies [155813c]
|
||||
- Updated dependencies [1e25f91]
|
||||
- Updated dependencies [3a65cde]
|
||||
- Updated dependencies [5ba5d38]
|
||||
- Updated dependencies [930a4ca]
|
||||
- Updated dependencies [ecad345]
|
||||
- Updated dependencies [930d75a]
|
||||
- @dexto/core@1.2.0
|
||||
|
||||
## 1.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 01167a2: Refactors
|
||||
- Updated dependencies [c40b675]
|
||||
- Updated dependencies [015100c]
|
||||
- Updated dependencies [0760f8a]
|
||||
- Updated dependencies [5cc6933]
|
||||
- Updated dependencies [40f89f5]
|
||||
- Updated dependencies [3a24d08]
|
||||
- Updated dependencies [01167a2]
|
||||
- Updated dependencies [a53b87a]
|
||||
- Updated dependencies [24e5093]
|
||||
- Updated dependencies [c695e57]
|
||||
- Updated dependencies [0700f6f]
|
||||
- Updated dependencies [0a5636c]
|
||||
- Updated dependencies [35d48c5]
|
||||
- @dexto/core@1.1.11
|
||||
|
||||
## 1.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @dexto/core@1.1.10
|
||||
|
||||
## 1.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [27778ba]
|
||||
- @dexto/core@1.1.9
|
||||
|
||||
## 1.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [d79d358]
|
||||
- @dexto/core@1.1.8
|
||||
|
||||
## 1.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @dexto/core@1.1.7
|
||||
|
||||
## 1.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @dexto/core@1.1.6
|
||||
|
||||
## 1.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 795c7f1: feat: Add @dexto/client-sdk package
|
||||
- New lightweight cross-environment client SDK
|
||||
- HTTP + optional WebSocket support for messaging
|
||||
- Streaming and non-streaming message support
|
||||
- Session management, LLM config/catalog access
|
||||
- MCP tools integration and search functionality
|
||||
- Real-time events support
|
||||
- Comprehensive TypeScript types and validation
|
||||
- Unit tests and documentation included
|
||||
|
||||
- 09b8e33: Fix minor comments
|
||||
- Updated dependencies [e2bd0ce]
|
||||
- Updated dependencies [11cbec0]
|
||||
- Updated dependencies [795c7f1]
|
||||
- Updated dependencies [9d7541c]
|
||||
- @dexto/core@1.1.5
|
||||
107
dexto/packages/client-sdk/README.md
Normal file
107
dexto/packages/client-sdk/README.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Dexto Client SDK
|
||||
|
||||
An ultra-lightweight, zero-dependency HTTP client SDK for the Dexto API.
|
||||
|
||||
## Features
|
||||
|
||||
- 🚀 **Ultra-lightweight**: Only 80KB bundle size
|
||||
- 🔌 **Zero dependencies**: No external libraries
|
||||
- 🌐 **Universal**: Works in Node.js, browsers, and React Native
|
||||
- 📡 **HTTP + SSE**: Full REST API and real-time SSE streaming support
|
||||
- 🛡️ **TypeScript**: Full type safety
|
||||
- 🔄 **Auto-retry**: Built-in retry logic with exponential backoff
|
||||
- ⚡ **Fast**: Server-side validation, client-side pass-through
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @dexto/client-sdk
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { DextoClient } from '@dexto/client-sdk';
|
||||
|
||||
const client = new DextoClient({
|
||||
baseUrl: 'https://your-dexto-server.com',
|
||||
apiKey: 'optional-api-key'
|
||||
});
|
||||
|
||||
// Connect to Dexto server
|
||||
await client.connect();
|
||||
|
||||
// Send a message
|
||||
const response = await client.sendMessage({
|
||||
content: 'Hello, how can you help me?'
|
||||
});
|
||||
|
||||
console.log(response.response);
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```typescript
|
||||
const client = new DextoClient({
|
||||
baseUrl: 'https://your-dexto-server.com', // Required: Dexto API base URL
|
||||
apiKey: 'your-api-key', // Optional: API key for auth
|
||||
timeout: 30000, // Optional: Request timeout (ms)
|
||||
retries: 3, // Optional: Retry attempts
|
||||
}, {
|
||||
reconnect: true, // Optional: Auto-reconnect
|
||||
reconnectInterval: 5000, // Optional: Reconnect delay (ms)
|
||||
debug: false // Optional: Debug logging
|
||||
});
|
||||
```
|
||||
|
||||
## API Methods
|
||||
|
||||
### Connection Management
|
||||
- `connect()` - Establish connection to Dexto server
|
||||
- `disconnect()` - Close connection
|
||||
- `isConnected` - Check connection status
|
||||
|
||||
### Messaging
|
||||
- `sendMessage(input)` - Send message (HTTP)
|
||||
- SSE streaming available via `/api/message-stream` endpoint
|
||||
|
||||
### Session Management
|
||||
- `listSessions()` - List all sessions
|
||||
- `createSession(id?)` - Create new session
|
||||
- `getSession(id)` - Get session details
|
||||
- `deleteSession(id)` - Delete session
|
||||
|
||||
### Real-time Events
|
||||
- `on(eventType, handler)` - Subscribe to Dexto events
|
||||
- `onConnectionState(handler)` - Connection state changes
|
||||
|
||||
## Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await client.sendMessage({ content: 'Hello' });
|
||||
} catch (error) {
|
||||
if (error.name === 'ConnectionError') {
|
||||
console.log('Failed to connect to Dexto server');
|
||||
} else if (error.name === 'HttpError') {
|
||||
console.log(`HTTP ${error.status}: ${error.statusText}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Philosophy
|
||||
|
||||
This SDK follows the **thin client** philosophy:
|
||||
|
||||
- ✅ **Pass-through**: Data goes directly to Dexto server
|
||||
- ✅ **Server validation**: Let the Dexto server handle all validation
|
||||
- ✅ **Simple errors**: Return server errors as-is
|
||||
- ✅ **Type safety**: Full TypeScript support
|
||||
- ✅ **Fast**: Minimal client-side processing
|
||||
|
||||
## Bundle Size
|
||||
|
||||
- **Total**: ~80KB
|
||||
- **Main bundle**: ~25KB
|
||||
- **Type definitions**: ~10KB
|
||||
- **Zero external dependencies**
|
||||
44
dexto/packages/client-sdk/package.json
Normal file
44
dexto/packages/client-sdk/package.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@dexto/client-sdk",
|
||||
"version": "1.5.6",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"hono": "^4.6.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dexto/core": "workspace:*",
|
||||
"@dexto/server": "workspace:*",
|
||||
"tsup": "^8.0.2",
|
||||
"typescript": "^5.4.2",
|
||||
"vitest": "^1.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsup && tsc -p tsconfig.json --emitDeclarationOnly",
|
||||
"dev": "tsup --watch",
|
||||
"typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
99
dexto/packages/client-sdk/src/client.ts
Normal file
99
dexto/packages/client-sdk/src/client.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { hc } from 'hono/client';
|
||||
import type { AppType } from '@dexto/server';
|
||||
import type { ClientConfig } from './types.js';
|
||||
|
||||
/**
|
||||
* Create a type-safe Dexto client using Hono's typed client
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { createDextoClient } from '@dexto/client-sdk';
|
||||
*
|
||||
* const client = createDextoClient({
|
||||
* baseUrl: 'http://localhost:3001',
|
||||
* apiKey: 'optional-api-key'
|
||||
* });
|
||||
*
|
||||
* // Create a session
|
||||
* const session = await client.api.sessions.$post({
|
||||
* json: { sessionId: 'my-session' }
|
||||
* });
|
||||
*
|
||||
* // Send a synchronous message
|
||||
* const response = await client.api['message-sync'].$post({
|
||||
* json: { message: 'Hello!', sessionId: 'my-session' }
|
||||
* });
|
||||
* const { response: text } = await response.json();
|
||||
*
|
||||
* // Search messages
|
||||
* const searchResults = await client.api.search.messages.$get({
|
||||
* query: { q: 'hello', limit: 10 }
|
||||
* });
|
||||
*
|
||||
* // Streaming responses with SSE
|
||||
* import { createMessageStream } from '@dexto/client-sdk';
|
||||
*
|
||||
* const streamPromise = client.api['message-stream'].$post({
|
||||
* json: { message: 'Tell me a story', sessionId: 'my-session' }
|
||||
* });
|
||||
*
|
||||
* // Parse SSE events using createMessageStream
|
||||
* const stream = createMessageStream(streamPromise);
|
||||
* for await (const event of stream) {
|
||||
* if (event.name === 'llm:chunk') {
|
||||
* process.stdout.write(event.content);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function createDextoClient(config: ClientConfig) {
|
||||
const options: { headers?: Record<string, string> } = {};
|
||||
|
||||
if (config.apiKey) {
|
||||
options.headers = {
|
||||
Authorization: `Bearer ${config.apiKey}`,
|
||||
};
|
||||
}
|
||||
|
||||
return hc<AppType>(config.baseUrl, options);
|
||||
}
|
||||
|
||||
export * from './streaming.js';
|
||||
|
||||
// AGENTS DO NOT DELETE THE BELOW COMMENTS
|
||||
// Uncomment for testing autofill in IDE
|
||||
// const client1 = hc<AppType>('http://localhost:3001');
|
||||
// let response1 = await client1.api.search.sessions.$get({
|
||||
// query: {
|
||||
// q: "poop"
|
||||
// }
|
||||
// })
|
||||
// const client2 = createDextoClient({
|
||||
// baseUrl: 'http://localhost:3001',
|
||||
// apiKey: 'optional-api-key'
|
||||
// })
|
||||
// let response2 = await client2.api.sessions.$post({
|
||||
// json: {
|
||||
// sessionId: 'session-123'
|
||||
// }
|
||||
// })
|
||||
// const body2 = await response2.json();
|
||||
// console.log(body2.session.id);
|
||||
|
||||
// let response3 = await client2.health.$get();
|
||||
// console.log(response3.ok);
|
||||
|
||||
// import { createMessageStream } from './streaming.js';
|
||||
// let response4 = client2.api['message-stream'].$post({
|
||||
// json: {
|
||||
// message: 'Tell me a story',
|
||||
// sessionId: 'my-session'
|
||||
// }
|
||||
// });
|
||||
|
||||
// const stream = createMessageStream(response4);
|
||||
// for await (const event of stream) {
|
||||
// if (event.type === 'llm:chunk') {
|
||||
// process.stdout.write(event.content);
|
||||
// }
|
||||
// }
|
||||
17
dexto/packages/client-sdk/src/index.ts
Normal file
17
dexto/packages/client-sdk/src/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Dexto Client SDK
|
||||
* Lightweight type-safe client for Dexto API built on Hono's typed client
|
||||
*/
|
||||
|
||||
// Core client
|
||||
export { createDextoClient } from './client.js';
|
||||
|
||||
// SSE streaming
|
||||
export { stream, createStream, createMessageStream, SSEError } from './streaming.js';
|
||||
export type { SSEEvent, MessageStreamEvent } from './streaming.js';
|
||||
|
||||
// Client configuration
|
||||
export type { ClientConfig } from './types.js';
|
||||
|
||||
// Server types for advanced usage
|
||||
export type { AppType } from '@dexto/server';
|
||||
197
dexto/packages/client-sdk/src/streaming.ts
Normal file
197
dexto/packages/client-sdk/src/streaming.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
import type { StreamingEvent } from '@dexto/core';
|
||||
|
||||
/**
|
||||
* SSE (Server-Sent Events) streaming utilities for client SDK
|
||||
* Adapted from @dexto/webui EventStreamClient
|
||||
*/
|
||||
|
||||
export type MessageStreamEvent = StreamingEvent;
|
||||
|
||||
export interface SSEEvent<T = string> {
|
||||
event?: string;
|
||||
data?: T;
|
||||
id?: string;
|
||||
retry?: number;
|
||||
}
|
||||
|
||||
export class SSEError extends Error {
|
||||
constructor(
|
||||
public status: number,
|
||||
public body: any
|
||||
) {
|
||||
super(`SSE Error: ${status}`);
|
||||
this.name = 'SSEError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an async generator that yields SSE events from a Response object.
|
||||
*
|
||||
* @param response The fetch Response object containing the SSE stream
|
||||
* @param options Optional configuration including AbortSignal
|
||||
*/
|
||||
export async function* stream<T = string>(
|
||||
response: Response,
|
||||
options?: { signal?: AbortSignal }
|
||||
): AsyncGenerator<SSEEvent<T>> {
|
||||
if (!response.ok) {
|
||||
const contentType = response.headers.get('content-type');
|
||||
let errorBody;
|
||||
try {
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
errorBody = await response.json();
|
||||
} else {
|
||||
errorBody = await response.text();
|
||||
}
|
||||
} catch {
|
||||
errorBody = 'Unknown error';
|
||||
}
|
||||
throw new SSEError(response.status, errorBody);
|
||||
}
|
||||
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) {
|
||||
throw new Error('Response body is null');
|
||||
}
|
||||
|
||||
const decoder = new globalThis.TextDecoder();
|
||||
let buffer = '';
|
||||
const signal = options?.signal;
|
||||
|
||||
// Handle abort signal
|
||||
let aborted = false;
|
||||
const abortHandler = () => {
|
||||
aborted = true;
|
||||
reader.cancel().catch(() => {
|
||||
// Ignore errors during cancel
|
||||
});
|
||||
};
|
||||
|
||||
if (signal) {
|
||||
if (signal.aborted) {
|
||||
reader.cancel().catch(() => {});
|
||||
return;
|
||||
}
|
||||
signal.addEventListener('abort', abortHandler);
|
||||
}
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
if (aborted || signal?.aborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we have a double newline in buffer
|
||||
const parts = buffer.split('\n\n');
|
||||
if (parts.length > 1) {
|
||||
const eventString = parts.shift()!;
|
||||
buffer = parts.join('\n\n');
|
||||
|
||||
const event = parseSSE(eventString);
|
||||
if (event) {
|
||||
yield event as SSEEvent<T>;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Need more data
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
if (buffer.trim()) {
|
||||
const event = parseSSE(buffer);
|
||||
if (event) {
|
||||
yield event as SSEEvent<T>;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize CRLF to LF for spec-compliance
|
||||
buffer += decoder.decode(value, { stream: true }).replace(/\r\n/g, '\n');
|
||||
}
|
||||
} finally {
|
||||
if (signal) {
|
||||
signal.removeEventListener('abort', abortHandler);
|
||||
}
|
||||
reader.cancel().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to create a stream from a promise that resolves to a Response.
|
||||
* Useful for chaining with Hono client requests.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const stream = createStream(client.api.chat.$post({ json: { message: 'hi' } }));
|
||||
* for await (const event of stream) { ... }
|
||||
* ```
|
||||
*/
|
||||
export async function* createStream<T = string>(
|
||||
responsePromise: Promise<Response>,
|
||||
options?: { signal?: AbortSignal }
|
||||
): AsyncGenerator<SSEEvent<T>> {
|
||||
const response = await responsePromise;
|
||||
yield* stream<T>(response, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to create a typed message stream from a promise that resolves to a Response.
|
||||
* Automatically parses JSON data and yields typed MessageStreamEvent objects.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const stream = createMessageStream(client.api['message-stream'].$post({ ... }));
|
||||
* for await (const event of stream) {
|
||||
* if (event.name === 'llm:chunk') {
|
||||
* console.log(event.content);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export async function* createMessageStream(
|
||||
responsePromise: Promise<Response>,
|
||||
options?: { signal?: AbortSignal }
|
||||
): AsyncGenerator<MessageStreamEvent> {
|
||||
const sseStream = createStream(responsePromise, options);
|
||||
for await (const event of sseStream) {
|
||||
if (event.data) {
|
||||
try {
|
||||
const parsed = JSON.parse(event.data);
|
||||
// SSE event name becomes the 'name' discriminant for StreamingEvent
|
||||
// Using 'name' (not 'type') to avoid collision with payload fields
|
||||
if (event.event) {
|
||||
parsed.name = event.event;
|
||||
}
|
||||
yield parsed as MessageStreamEvent;
|
||||
} catch {
|
||||
// Ignore parse errors for non-JSON data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseSSE(raw: string): SSEEvent<string> | null {
|
||||
const lines = raw.split('\n').map((line) => line.replace(/\r$/, ''));
|
||||
const event: SSEEvent<string> = {};
|
||||
let hasData = false;
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith(':')) continue; // Comment
|
||||
|
||||
if (line.startsWith('data: ')) {
|
||||
const data = line.slice(6);
|
||||
event.data = event.data ? event.data + '\n' + data : data;
|
||||
hasData = true;
|
||||
} else if (line.startsWith('event: ')) {
|
||||
event.event = line.slice(7);
|
||||
} else if (line.startsWith('id: ')) {
|
||||
event.id = line.slice(4);
|
||||
} else if (line.startsWith('retry: ')) {
|
||||
event.retry = parseInt(line.slice(7), 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasData && !event.event && !event.id) return null;
|
||||
return event;
|
||||
}
|
||||
9
dexto/packages/client-sdk/src/types.ts
Normal file
9
dexto/packages/client-sdk/src/types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Client configuration for Dexto SDK
|
||||
*/
|
||||
export interface ClientConfig {
|
||||
/** Base URL of the Dexto server */
|
||||
baseUrl: string;
|
||||
/** Optional API key for authentication */
|
||||
apiKey?: string;
|
||||
}
|
||||
22
dexto/packages/client-sdk/tsconfig.json
Normal file
22
dexto/packages/client-sdk/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"noEmit": false,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"emitDeclarationOnly": false
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.integration.test.ts",
|
||||
"dist",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
4
dexto/packages/client-sdk/tsconfig.typecheck.json
Normal file
4
dexto/packages/client-sdk/tsconfig.typecheck.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["dist", "node_modules"]
|
||||
}
|
||||
17
dexto/packages/client-sdk/tsup.config.ts
Normal file
17
dexto/packages/client-sdk/tsup.config.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['cjs', 'esm'],
|
||||
outDir: 'dist',
|
||||
dts: false, // Disable DTS generation in tsup to avoid worker memory issues
|
||||
shims: true,
|
||||
bundle: true,
|
||||
platform: 'neutral',
|
||||
target: 'es2018',
|
||||
minify: false,
|
||||
splitting: false,
|
||||
treeshake: false,
|
||||
clean: true,
|
||||
sourcemap: false,
|
||||
});
|
||||
7
dexto/packages/client-sdk/vitest.config.ts
Normal file
7
dexto/packages/client-sdk/vitest.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
environment: 'node',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user