@alia.onl/sdk 22.3.0 → 22.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @alia.onl/sdk
|
|
2
2
|
|
|
3
|
+
## 22.5.0
|
|
4
|
+
|
|
5
|
+
- **`AliaApi.put`.** The REST API (`useAliaApi`, `createAliaApi`) sends PUT like PATCH: the
|
|
6
|
+
linked Oxy client's authentication and 401 replay, the app assertion and a JSON body. Alia's
|
|
7
|
+
memory profile takes its sections by PUT (`/memory/context`, `/memory/preferences`,
|
|
8
|
+
`/memory/settings`), so a host's personalization settings can save them without its own client.
|
|
9
|
+
|
|
10
|
+
## 22.4.0
|
|
11
|
+
|
|
12
|
+
- **A shared conversation shows its artifacts.** `readSharedConversation` keeps an assistant
|
|
13
|
+
message's `artifacts` (`AliaSharedArtifact`: `{ id, type, title, data }`, the canvas tool's
|
|
14
|
+
result) and `sharedMessages` hands each to the thread as the canvas call that drew it.
|
|
15
|
+
`AliaSharedConversation` draws them inline under their reply on the canvas renderers (reports,
|
|
16
|
+
decks, dashboards, charts, tables). An `AliaThread` that is not `readOnly` is unchanged: in the
|
|
17
|
+
app an artifact still opens in the canvas panel, not in the reply.
|
|
18
|
+
- The server sends `artifacts` only from the API that ships with this release
|
|
19
|
+
(`docs/agent-embedding.md` §6); against an older API the shared page shows words and images,
|
|
20
|
+
as before.
|
|
21
|
+
|
|
3
22
|
## 22.3.0
|
|
4
23
|
|
|
5
24
|
- **Decks and dashboards on the canvas.** `CanvasComponent` draws the canvas tool's two new
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A conversation somebody shared (`GET /v1/shared/:token`, `docs/agent-embedding.md` §6), read
|
|
3
3
|
* by anybody with the link, signed in or not. It is the SDK's own thread (`AliaThread`), read-only:
|
|
4
|
-
* words, pictures
|
|
5
|
-
*
|
|
4
|
+
* words, pictures, who wrote them and the canvas artifacts Alia drew (a report, deck or dashboard,
|
|
5
|
+
* drawn inline because there is no canvas panel here). The server sends no other tool's output,
|
|
6
|
+
* which can hold the person's own data, and there is nothing to vote on, play, edit or regenerate.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { AgentAvatarProvider } from '@oxy.so/bloom/agent-avatar';
|
|
@@ -24,6 +24,7 @@ import { readAgentCharacter } from '../../lib/agent-character';
|
|
|
24
24
|
import { getImagesFromContent, messageText } from '../../lib/content-utils';
|
|
25
25
|
import { ANCHORS, useAliaFlights } from '../../lib/flights';
|
|
26
26
|
import { useLabels } from '../../lib/labels';
|
|
27
|
+
import { canvasResultOf } from '../../lib/canvas-result';
|
|
27
28
|
import { askedQuestions, isQuestionInvocation } from '../../lib/questions';
|
|
28
29
|
import { parseCatalogueTool, useToolRenderers } from '../../lib/tool-renderers';
|
|
29
30
|
import { isWebInvocation, taskListLog, webSearchLog } from '../../lib/work-log';
|
|
@@ -33,6 +34,7 @@ import type { OpenThought } from '../../hooks/useOpenThought';
|
|
|
33
34
|
import { Image } from '../Image';
|
|
34
35
|
import { PlanPreviewCard } from '../PlanPreviewCard';
|
|
35
36
|
import { AskedQuestions } from '../QuestionCard';
|
|
37
|
+
import { CanvasComponent } from '../canvas/CanvasComponent';
|
|
36
38
|
import { ReplyMarkdown } from '../ReplyMarkdown';
|
|
37
39
|
import { MessageBlockBoundary } from './MessageBlockBoundary';
|
|
38
40
|
import { ToolResultCard } from './ToolResultCard';
|
|
@@ -240,7 +242,20 @@ function ReplyTurn({
|
|
|
240
242
|
},
|
|
241
243
|
];
|
|
242
244
|
});
|
|
243
|
-
|
|
245
|
+
|
|
246
|
+
// A shared conversation has no canvas panel to open an artifact in, so it draws each one inline.
|
|
247
|
+
const inlineCanvases = readOnly
|
|
248
|
+
? toolInvocations.flatMap((call, index) => {
|
|
249
|
+
const canvas = canvasResultOf(call);
|
|
250
|
+
return canvas === null
|
|
251
|
+
? []
|
|
252
|
+
: [{ key: call.toolCallId || `canvas-${message.id}-${index}`, call, canvas }];
|
|
253
|
+
})
|
|
254
|
+
: [];
|
|
255
|
+
const renderedCalls = new Set([
|
|
256
|
+
...rendered.map(({ call }) => call),
|
|
257
|
+
...inlineCanvases.map(({ call }) => call),
|
|
258
|
+
]);
|
|
244
259
|
|
|
245
260
|
// The calls the work summary lists: every one that did not draw its own card. Read on each
|
|
246
261
|
// render — the list changes per streamed tool event and the row is memoised on `message`.
|
|
@@ -320,6 +335,7 @@ function ReplyTurn({
|
|
|
320
335
|
hasWorkLog ||
|
|
321
336
|
toolCards.length > 0 ||
|
|
322
337
|
rendered.length > 0 ||
|
|
338
|
+
inlineCanvases.length > 0 ||
|
|
323
339
|
(message.isStreaming === true && message.source === 'voice');
|
|
324
340
|
/** Its avatar is the source of the flight into the header while it is answering. */
|
|
325
341
|
const agentLive = agent !== undefined && message.isStreaming === true;
|
|
@@ -420,6 +436,13 @@ function ReplyTurn({
|
|
|
420
436
|
{rendered.map(({ key, node }) => (
|
|
421
437
|
<MessageBlockBoundary key={key}>{node}</MessageBlockBoundary>
|
|
422
438
|
))}
|
|
439
|
+
{inlineCanvases.map(({ key, canvas }) => (
|
|
440
|
+
<MessageBlockBoundary key={key}>
|
|
441
|
+
<View className="rounded-2xl border border-border p-4" testID="shared-canvas">
|
|
442
|
+
<CanvasComponent component={{ id: key, ...canvas }} />
|
|
443
|
+
</View>
|
|
444
|
+
</MessageBlockBoundary>
|
|
445
|
+
))}
|
|
423
446
|
{/* Each card in its own boundary: `cardOf` checks the card's NAME, and its data is
|
|
424
447
|
cast unchecked. */}
|
|
425
448
|
{toolCards.map(({ key, card }) => (
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ToolInvocation } from '../runtime/types';
|
|
2
|
+
|
|
3
|
+
/** A canvas artifact as `CanvasComponent` draws it. */
|
|
4
|
+
export interface CanvasResult {
|
|
5
|
+
type: string;
|
|
6
|
+
title: string;
|
|
7
|
+
data: unknown;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A finished canvas call's artifact; `null` for any other call, one still running, or one the tool
|
|
12
|
+
* refused (`{ error }`). An artifact without a title is titled by its type.
|
|
13
|
+
*/
|
|
14
|
+
export function canvasResultOf(call: ToolInvocation): CanvasResult | null {
|
|
15
|
+
if (call.toolName !== 'canvas' || call.state !== 'result') return null;
|
|
16
|
+
const result: unknown = call.result;
|
|
17
|
+
if (result === null || typeof result !== 'object') return null;
|
|
18
|
+
const { type, title, data } = result as Record<string, unknown>;
|
|
19
|
+
if (typeof type !== 'string' || type === '' || data === undefined || data === null) return null;
|
|
20
|
+
return { type, title: typeof title === 'string' && title !== '' ? title : type, data };
|
|
21
|
+
}
|
package/src/runtime/api.ts
CHANGED
|
@@ -44,6 +44,8 @@ export interface AliaApi {
|
|
|
44
44
|
get<T>(path: string, request?: AliaApiRequest): Promise<AliaApiResult<T>>;
|
|
45
45
|
post<T>(path: string, body?: unknown, request?: AliaApiRequest): Promise<AliaApiResult<T>>;
|
|
46
46
|
patch<T>(path: string, body?: unknown, request?: AliaApiRequest): Promise<AliaApiResult<T>>;
|
|
47
|
+
/** Replaces a resource whole, for the routes that take PUT (the memory profile's sections). */
|
|
48
|
+
put<T>(path: string, body?: unknown, request?: AliaApiRequest): Promise<AliaApiResult<T>>;
|
|
47
49
|
delete<T>(path: string, request?: AliaApiRequest): Promise<AliaApiResult<T>>;
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -95,7 +97,7 @@ export function createAliaApi(
|
|
|
95
97
|
appAssertionHeaders: AppAssertionHeaders = NO_APP_ASSERTION,
|
|
96
98
|
): AliaApi {
|
|
97
99
|
async function send<T>(
|
|
98
|
-
method: 'GET' | 'POST' | 'PATCH' | 'DELETE',
|
|
100
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
99
101
|
path: string,
|
|
100
102
|
request: AliaApiRequest = {},
|
|
101
103
|
): Promise<AliaApiResult<T>> {
|
|
@@ -125,6 +127,7 @@ export function createAliaApi(
|
|
|
125
127
|
get: (path, request) => send('GET', path, request),
|
|
126
128
|
post: (path, body, request) => send('POST', path, { ...request, body: body ?? {} }),
|
|
127
129
|
patch: (path, body, request) => send('PATCH', path, { ...request, body: body ?? {} }),
|
|
130
|
+
put: (path, body, request) => send('PUT', path, { ...request, body: body ?? {} }),
|
|
128
131
|
delete: (path, request) => send('DELETE', path, request),
|
|
129
132
|
};
|
|
130
133
|
}
|
package/src/runtime/sharing.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { useAliaApi } from './api';
|
|
|
5
5
|
import { useAliaRuntime } from './config';
|
|
6
6
|
import { aliaQueryKeys } from './query-keys';
|
|
7
7
|
import { API_ROUTES } from './routes';
|
|
8
|
-
import type { Message } from './types';
|
|
8
|
+
import type { Message, ToolInvocation } from './types';
|
|
9
9
|
|
|
10
10
|
/** A conversation's read-only link (`POST /v1/conversations/:id/share`, `docs/agent-embedding.md` §6). */
|
|
11
11
|
export interface AliaConversationShare {
|
|
@@ -65,11 +65,26 @@ export function useShareConversation() {
|
|
|
65
65
|
);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* A canvas artifact of a shared conversation: the report, deck, dashboard, chart or table Alia drew,
|
|
70
|
+
* as the canvas tool returned it. `id` is the tool call that drew it.
|
|
71
|
+
*/
|
|
72
|
+
export interface AliaSharedArtifact {
|
|
73
|
+
id: string;
|
|
74
|
+
type: string;
|
|
75
|
+
title: string;
|
|
76
|
+
data: unknown;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* A message of a shared conversation: words and pictures, who wrote them, and the canvas artifacts
|
|
81
|
+
* it drew. Never any other tool's output.
|
|
82
|
+
*/
|
|
69
83
|
export interface AliaSharedMessage {
|
|
70
84
|
role: 'user' | 'assistant';
|
|
71
85
|
content: string | Array<{ type: string; [key: string]: unknown }>;
|
|
72
86
|
agent?: AliaSharedAgent;
|
|
87
|
+
artifacts?: AliaSharedArtifact[];
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
export interface AliaSharedAgent {
|
|
@@ -100,6 +115,18 @@ function readSharedAgent(value: unknown): AliaSharedAgent | undefined {
|
|
|
100
115
|
};
|
|
101
116
|
}
|
|
102
117
|
|
|
118
|
+
/** The artifacts the server sent, each kept only with an id, a type, a title and its data. */
|
|
119
|
+
function readSharedArtifacts(value: unknown): AliaSharedArtifact[] {
|
|
120
|
+
if (!Array.isArray(value)) return [];
|
|
121
|
+
return value.flatMap((artifact): AliaSharedArtifact[] => {
|
|
122
|
+
if (artifact === null || typeof artifact !== 'object') return [];
|
|
123
|
+
const { id, type, title, data } = artifact as Record<string, unknown>;
|
|
124
|
+
if (typeof id !== 'string' || typeof type !== 'string' || type === '') return [];
|
|
125
|
+
if (data === undefined || data === null) return [];
|
|
126
|
+
return [{ id, type, title: typeof title === 'string' ? title : '', data }];
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
103
130
|
/** The shared conversation as the contract names it; any message of another shape is left out. */
|
|
104
131
|
export function readSharedConversation(value: unknown): AliaSharedConversationData | null {
|
|
105
132
|
if (value === null || typeof value !== 'object') return null;
|
|
@@ -107,15 +134,17 @@ export function readSharedConversation(value: unknown): AliaSharedConversationDa
|
|
|
107
134
|
if (!Array.isArray(raw.messages) || typeof raw.expiresAt !== 'string') return null;
|
|
108
135
|
const messages = raw.messages.flatMap((message): AliaSharedMessage[] => {
|
|
109
136
|
if (message === null || typeof message !== 'object') return [];
|
|
110
|
-
const { role, content, agent } = message as Record<string, unknown>;
|
|
137
|
+
const { role, content, agent, artifacts } = message as Record<string, unknown>;
|
|
111
138
|
if (role !== 'user' && role !== 'assistant') return [];
|
|
112
139
|
if (typeof content !== 'string' && !Array.isArray(content)) return [];
|
|
113
140
|
const author = readSharedAgent(agent);
|
|
141
|
+
const drawn = role === 'assistant' ? readSharedArtifacts(artifacts) : [];
|
|
114
142
|
return [
|
|
115
143
|
{
|
|
116
144
|
role,
|
|
117
145
|
content: content as AliaSharedMessage['content'],
|
|
118
146
|
...(author ? { agent: author } : {}),
|
|
147
|
+
...(drawn.length > 0 ? { artifacts: drawn } : {}),
|
|
119
148
|
},
|
|
120
149
|
];
|
|
121
150
|
});
|
|
@@ -128,13 +157,28 @@ export function readSharedConversation(value: unknown): AliaSharedConversationDa
|
|
|
128
157
|
};
|
|
129
158
|
}
|
|
130
159
|
|
|
131
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* The shared messages as the thread draws them: an agent's under its own identity, and each artifact
|
|
162
|
+
* as the canvas call that drew it, which the read-only thread draws inline.
|
|
163
|
+
*/
|
|
132
164
|
export function sharedMessages(shared: AliaSharedConversationData): Message[] {
|
|
133
165
|
return shared.messages.map((message, index) => ({
|
|
134
166
|
id: `shared-${index}`,
|
|
135
167
|
role: message.role,
|
|
136
168
|
content: message.content,
|
|
137
169
|
...(message.agent ? { agentInfo: { ...message.agent } } : {}),
|
|
170
|
+
...(message.artifacts
|
|
171
|
+
? {
|
|
172
|
+
toolInvocations: message.artifacts.map(
|
|
173
|
+
(artifact): ToolInvocation => ({
|
|
174
|
+
toolCallId: artifact.id,
|
|
175
|
+
toolName: 'canvas',
|
|
176
|
+
state: 'result',
|
|
177
|
+
result: { type: artifact.type, title: artifact.title, data: artifact.data },
|
|
178
|
+
}),
|
|
179
|
+
),
|
|
180
|
+
}
|
|
181
|
+
: {}),
|
|
138
182
|
}));
|
|
139
183
|
}
|
|
140
184
|
|