@asgard-js/core 0.3.4 → 0.3.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/README.md +40 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,7 +114,7 @@ const client = new AsgardServiceClient({
|
|
|
114
114
|
|
|
115
115
|
## API Reference
|
|
116
116
|
|
|
117
|
-
The core package exports three main classes for different levels of abstraction (`AsgardServiceClient`, `Channel`, `Conversation`), an `HttpError` class with an `isHttpError` type guard for HTTP failure handling,
|
|
117
|
+
The core package exports three main classes for different levels of abstraction (`AsgardServiceClient`, `Channel`, `Conversation`), an `HttpError` class with an `isHttpError` type guard for HTTP failure handling, authentication types for dynamic API key management, and a set of framework-agnostic **derived-state** helpers (Task Check List / Subagent List) for headless / non-React consumers — see [Derived State](#derived-state):
|
|
118
118
|
|
|
119
119
|
<a id="asgardserviceclient"></a>
|
|
120
120
|
<br/>
|
|
@@ -144,6 +144,8 @@ The main client class for interacting with the Asgard AI platform.
|
|
|
144
144
|
- **fetchSse(payload, options?)**: Send a message via Server-Sent Events. `payload.action` is a `FetchSseAction` value — `NONE` for a normal message, `RESET_CHANNEL` to (re)initialize the channel, `RESPONSE_TOOL_CALL_CONSENT` to answer a consent prompt
|
|
145
145
|
- **uploadFile(file, customChannelId)**: Upload file to Blob API and return BlobUploadResponse
|
|
146
146
|
- **downloadChannelHomeFile(relativePath, customChannelId)**: `Promise<ChannelHomeDownloadResult>` - Download a file from the channel's Channel Home file-exchange plane (backs `channel-home://` URI actions); resolves to `{ blob, filename }`
|
|
147
|
+
- **rejoinSse(customChannelId, options?)**: Cold-start transcript rejoin — a `GET /message/sse` with an empty `Last-Event-ID` that replays the channel's collapsed history through the same reducer, so a returning user sees their prior conversation without re-POSTing. Optional on `IAsgardServiceClient` for backward compatibility
|
|
148
|
+
- **channelMetadata(customChannelId)**: `Promise<ChannelMetadata | null>` - Join-init existence + restore gate — `GET /channel/metadata`; resolves to the metadata on `200`, `null` on `404` (channel does not exist), and rejects on any other error. `ChannelMetadata` is `{ title: string | null; runState: 'RUNNING' | 'IDLE'; lastActivityAt?: string }`. Optional on `IAsgardServiceClient` for backward compatibility
|
|
147
149
|
- **on(event, handler)**: Listen to a specific SSE event. `event` must be an `EventType` value (e.g. `EventType.MESSAGE`), not a plain string; registering a listener for an event replaces any previous one
|
|
148
150
|
- **detach({ timeoutMs })**: Detach from the owning component without aborting in-flight runs — the connection stays open so the backend can finish the current run, then auto-closes once all runs settle (or after `timeoutMs` as a safety net). Backs the React `keepConnectionOnUnmount` prop
|
|
149
151
|
- **close()**: Close the SSE connection and clean up resources (idempotent)
|
|
@@ -169,12 +171,16 @@ Higher-level abstraction for managing a conversation channel with reactive state
|
|
|
169
171
|
|
|
170
172
|
#### Static Methods
|
|
171
173
|
|
|
172
|
-
- **Channel.reset(config, payload?, options?)**: `Promise<Channel>` - Create and
|
|
174
|
+
- **Channel.reset(config, payload?, options?)**: `Promise<Channel>` - Create a channel and send `RESET_CHANNEL`, starting a fresh conversation (the server replies with a welcome message)
|
|
175
|
+
- **Channel.restore(config, options?)**: `Promise<Channel>` - Join an **existing** channel without resetting it — seeds the title from `config.channelTitle` and replays the server transcript via `rejoinSse`, preserving history / session / title. This is the join-without-wiping path behind the metadata-gated mount (F-015)
|
|
176
|
+
- **Channel.create(config)**: `Channel` - Create a channel and subscribe to its state without any SSE request (no reset, no rejoin); the first connection happens when you call `sendMessage`
|
|
173
177
|
|
|
174
178
|
#### Instance Methods
|
|
175
179
|
|
|
176
180
|
- **sendMessage(payload, options?)**: `Promise<void>` - Send a message through the channel
|
|
177
181
|
- **replyToolCallConsents(answers, options?, payload?)**: `Promise<void>` - Reply to a pending tool-call consent prompt. `answers` is an array of `ToolCallConsentAnswer` (each `{ toolCallId, result, denyReason }`, where `result` is a `ToolCallConsentResult` value)
|
|
182
|
+
- **getTasks() / getSubagents() / getChannelTitle()**: `Task[]` / `Subagent[]` / `string | null` - Current immutable snapshots of the derived state (for `getSnapshot()`-style bridging; see [Derived State](#derived-state))
|
|
183
|
+
- **setChannelTitle(title)**: `void` - Seed or override the reactive channel title (F-016)
|
|
178
184
|
- **close()**: `void` - Close the channel and cleanup subscriptions
|
|
179
185
|
|
|
180
186
|
#### Configuration (ChannelConfig)
|
|
@@ -183,12 +189,16 @@ Higher-level abstraction for managing a conversation channel with reactive state
|
|
|
183
189
|
- **customChannelId**: `string` - Unique channel identifier
|
|
184
190
|
- **customMessageId?**: `string` - Optional message ID
|
|
185
191
|
- **conversation**: `Conversation` - Initial conversation state
|
|
186
|
-
- **
|
|
192
|
+
- **channelTitle?**: `string | null` - Seed for the reactive channel-title store (F-016), typically the `title` from `channelMetadata()`. `null` = unnamed
|
|
193
|
+
- **statesObserver?**: `ObserverOrNext<ChannelStates>` - Observer for channel state changes. `ChannelStates` carries `isConnecting`, `conversation`, and (since 0.3.x) the derived `tasks: Task[]`, `subagents: Subagent[]`, and `channelTitle: string | null`
|
|
187
194
|
|
|
188
195
|
#### Properties
|
|
189
196
|
|
|
190
197
|
- **customChannelId**: `string` - The channel identifier
|
|
191
198
|
- **customMessageId?**: `string` - Optional message identifier
|
|
199
|
+
- **tasks$**: `Observable<Task[]>` - Reactive Task Check List store; replays the current snapshot and emits only when the list changes (F-010 / F-013)
|
|
200
|
+
- **subagents$**: `Observable<Subagent[]>` - Reactive Subagent List store; replays the current snapshot and emits only when the list changes (F-012 / F-013)
|
|
201
|
+
- **channelTitle$**: `Observable<string | null>` - Reactive channel-title store; seeded from metadata, updated by `title.update` (F-016)
|
|
192
202
|
|
|
193
203
|
#### Example Usage
|
|
194
204
|
|
|
@@ -242,7 +252,9 @@ Immutable conversation state manager that handles message updates and SSE event
|
|
|
242
252
|
|
|
243
253
|
- **ConversationUserMessage**: User-sent messages with `text` and `time`
|
|
244
254
|
- **ConversationBotMessage**: Bot responses with `message`, `isTyping`, `typingText`, `eventType`
|
|
245
|
-
- **ConversationToolCallMessage**: Tool-call entries with `toolName`, `reason`, `parameter`, `result`, `isComplete`
|
|
255
|
+
- **ConversationToolCallMessage**: Tool-call entries with `toolName`, `reason`, `parameter`, `result`, `isComplete`, and (since 0.3.x) `isError` (backend failure flag, F-009), `toolUseId` / `parentToolUseId` (subagent correlation, F-012)
|
|
256
|
+
- **ConversationThinkingMessage**: Extended-thinking (reasoning) block with `text` and `isThinking`, rendered as a collapsible block separate from the answer (F-001)
|
|
257
|
+
- **ConversationSubagentMessage**: Subagent lifecycle entry with `kind` (`start` / `complete`), `parentToolUseId`, `status`, `summary` (F-012)
|
|
246
258
|
- **ConversationErrorMessage**: Error messages with `error` details
|
|
247
259
|
|
|
248
260
|
#### Example Usage
|
|
@@ -397,6 +409,30 @@ interface ChannelHomeDownloadResult {
|
|
|
397
409
|
}
|
|
398
410
|
```
|
|
399
411
|
|
|
412
|
+
<a id="derived-state"></a>
|
|
413
|
+
<br/>
|
|
414
|
+
|
|
415
|
+
### Derived State (Task Check List / Subagent List)
|
|
416
|
+
|
|
417
|
+
The Task Check List (F-010) and Subagent List (F-012) are pure folds over the conversation, exposed as **framework-agnostic** reactive slices so you can render them outside React — in Vue, Svelte, or vanilla JS. Each slice replays its current immutable snapshot and only emits when that slice actually changes (unrelated high-frequency message deltas are suppressed).
|
|
418
|
+
|
|
419
|
+
The simplest path is the reactive stores already on `Channel` (`channel.tasks$`, `channel.subagents$`, `channel.channelTitle$`) plus the snapshot getters (`getTasks()`, `getSubagents()`, `getChannelTitle()`). To build the slices from a bare `conversation$` yourself, use `createDerivedStores(conversation$)`:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
import { createDerivedStores } from '@asgard-js/core';
|
|
423
|
+
|
|
424
|
+
const stores = createDerivedStores(conversation$);
|
|
425
|
+
// stores: { tasks$, subagents$, getTasks(), getSubagents(), teardown() }
|
|
426
|
+
const sub = stores.tasks$.subscribe(tasks => renderTaskList(tasks));
|
|
427
|
+
// ... later
|
|
428
|
+
sub.unsubscribe();
|
|
429
|
+
stores.teardown();
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
For one-shot derivation without subscriptions, `deriveTasks(conversation)` and `deriveSubagents(conversation)` return the current lists directly. Lower-level building blocks are also exported: the reducers `reduceTaskEvents` / `reduceSubagents`, the type guards `isTaskTool` / `isAgentTool` / `isSubagentChildTool`, the adapter `conversationToSubagentEvents`, the structural-equality helpers `tasksEqual` / `subagentsEqual`, and the types `Task`, `Subagent`, `DerivedStores`, `TaskToolEvent`, `SubagentEvent`.
|
|
433
|
+
|
|
434
|
+
> In React, prefer the `useTaskList(channel)`, `useSubagents(channel)`, and `useChannelTitle(channel)` hooks from `@asgard-js/react`, which bridge these stores into `useSyncExternalStore` for you.
|
|
435
|
+
|
|
400
436
|
<a id="development"></a>
|
|
401
437
|
<br/>
|
|
402
438
|
|