@astralform/js 2.0.0 → 3.0.1
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.cjs +20 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -8
- package/dist/index.d.ts +19 -8
- package/dist/index.js +20 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -138,7 +138,7 @@ interface AstralformUserTokenConfig extends AstralformBaseConfig {
|
|
|
138
138
|
*/
|
|
139
139
|
accessToken: string;
|
|
140
140
|
/**
|
|
141
|
-
* Active agent context. Sent as the `X-
|
|
141
|
+
* Active agent context. Sent as the `X-Agent-ID` header. The backend
|
|
142
142
|
* verifies the token's developer has access to this agent on every
|
|
143
143
|
* request; switching agents is a local `updateAgentId()` call.
|
|
144
144
|
*
|
|
@@ -151,7 +151,7 @@ interface AstralformUserTokenConfig extends AstralformBaseConfig {
|
|
|
151
151
|
/**
|
|
152
152
|
* Optional end-user override — lets a developer acting under a user
|
|
153
153
|
* token impersonate a downstream end-user identity for testing
|
|
154
|
-
* purposes. When set, sent alongside `X-
|
|
154
|
+
* purposes. When set, sent alongside `X-Agent-ID` as `X-End-User-ID`
|
|
155
155
|
* so memory, rate limits, and conversations scope to the specified
|
|
156
156
|
* end-user rather than the developer themselves.
|
|
157
157
|
*
|
|
@@ -988,10 +988,11 @@ declare class ChatSession {
|
|
|
988
988
|
switchConversation(id: string, jobId?: string,
|
|
989
989
|
/**
|
|
990
990
|
* User prompt that triggered this job, if known. Emitted as a
|
|
991
|
-
* synthetic ``user_message`` ChatEvent
|
|
992
|
-
*
|
|
993
|
-
*
|
|
994
|
-
*
|
|
991
|
+
* synthetic ``user_message`` ChatEvent at the START of the replay —
|
|
992
|
+
* a completed job maps to exactly one user turn, so every event in it
|
|
993
|
+
* belongs beneath that prompt. User messages aren't persisted in
|
|
994
|
+
* ``job_events``, so without this the restored conversation would show
|
|
995
|
+
* the agent response with no visible prompt above it.
|
|
995
996
|
*/
|
|
996
997
|
userMessageContent?: string): Promise<void>;
|
|
997
998
|
deleteConversation(id: string): Promise<void>;
|
|
@@ -1145,8 +1146,18 @@ interface RawSseEvent {
|
|
|
1145
1146
|
declare function mapSseToChat(raw: RawSseEvent): ChatEvent[];
|
|
1146
1147
|
/**
|
|
1147
1148
|
* Replay persisted SSE events through the provided handler, interleaving
|
|
1148
|
-
* user messages from session.messages at the
|
|
1149
|
-
*
|
|
1149
|
+
* user messages from session.messages at the START of each turn (user
|
|
1150
|
+
* messages aren't persisted in job_events).
|
|
1151
|
+
*
|
|
1152
|
+
* The turn boundary is a change of ``job_id``, NOT ``message_start`` or
|
|
1153
|
+
* ``message_stop``. A completed job maps to exactly one user turn — but a
|
|
1154
|
+
* single job can contain several ``message_start``/``message_stop`` pairs (a
|
|
1155
|
+
* tool-use loop: LLM call → tool result → LLM call again), so neither event
|
|
1156
|
+
* reliably delimits turns. And within a job some events precede the first
|
|
1157
|
+
* ``message_start`` (e.g. ``memory_recall``, emitted during prompt prep), so
|
|
1158
|
+
* gating the user block on ``message_start`` would replay them above the
|
|
1159
|
+
* user's own message. Keying off ``job_id`` injects the prompt once per job,
|
|
1160
|
+
* before its first event — matching ``session.ts#switchConversation``.
|
|
1150
1161
|
*/
|
|
1151
1162
|
declare function replayEvents(sseEvents: RawSseEvent[], userMessages: {
|
|
1152
1163
|
role: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -138,7 +138,7 @@ interface AstralformUserTokenConfig extends AstralformBaseConfig {
|
|
|
138
138
|
*/
|
|
139
139
|
accessToken: string;
|
|
140
140
|
/**
|
|
141
|
-
* Active agent context. Sent as the `X-
|
|
141
|
+
* Active agent context. Sent as the `X-Agent-ID` header. The backend
|
|
142
142
|
* verifies the token's developer has access to this agent on every
|
|
143
143
|
* request; switching agents is a local `updateAgentId()` call.
|
|
144
144
|
*
|
|
@@ -151,7 +151,7 @@ interface AstralformUserTokenConfig extends AstralformBaseConfig {
|
|
|
151
151
|
/**
|
|
152
152
|
* Optional end-user override — lets a developer acting under a user
|
|
153
153
|
* token impersonate a downstream end-user identity for testing
|
|
154
|
-
* purposes. When set, sent alongside `X-
|
|
154
|
+
* purposes. When set, sent alongside `X-Agent-ID` as `X-End-User-ID`
|
|
155
155
|
* so memory, rate limits, and conversations scope to the specified
|
|
156
156
|
* end-user rather than the developer themselves.
|
|
157
157
|
*
|
|
@@ -988,10 +988,11 @@ declare class ChatSession {
|
|
|
988
988
|
switchConversation(id: string, jobId?: string,
|
|
989
989
|
/**
|
|
990
990
|
* User prompt that triggered this job, if known. Emitted as a
|
|
991
|
-
* synthetic ``user_message`` ChatEvent
|
|
992
|
-
*
|
|
993
|
-
*
|
|
994
|
-
*
|
|
991
|
+
* synthetic ``user_message`` ChatEvent at the START of the replay —
|
|
992
|
+
* a completed job maps to exactly one user turn, so every event in it
|
|
993
|
+
* belongs beneath that prompt. User messages aren't persisted in
|
|
994
|
+
* ``job_events``, so without this the restored conversation would show
|
|
995
|
+
* the agent response with no visible prompt above it.
|
|
995
996
|
*/
|
|
996
997
|
userMessageContent?: string): Promise<void>;
|
|
997
998
|
deleteConversation(id: string): Promise<void>;
|
|
@@ -1145,8 +1146,18 @@ interface RawSseEvent {
|
|
|
1145
1146
|
declare function mapSseToChat(raw: RawSseEvent): ChatEvent[];
|
|
1146
1147
|
/**
|
|
1147
1148
|
* Replay persisted SSE events through the provided handler, interleaving
|
|
1148
|
-
* user messages from session.messages at the
|
|
1149
|
-
*
|
|
1149
|
+
* user messages from session.messages at the START of each turn (user
|
|
1150
|
+
* messages aren't persisted in job_events).
|
|
1151
|
+
*
|
|
1152
|
+
* The turn boundary is a change of ``job_id``, NOT ``message_start`` or
|
|
1153
|
+
* ``message_stop``. A completed job maps to exactly one user turn — but a
|
|
1154
|
+
* single job can contain several ``message_start``/``message_stop`` pairs (a
|
|
1155
|
+
* tool-use loop: LLM call → tool result → LLM call again), so neither event
|
|
1156
|
+
* reliably delimits turns. And within a job some events precede the first
|
|
1157
|
+
* ``message_start`` (e.g. ``memory_recall``, emitted during prompt prep), so
|
|
1158
|
+
* gating the user block on ``message_start`` would replay them above the
|
|
1159
|
+
* user's own message. Keying off ``job_id`` injects the prompt once per job,
|
|
1160
|
+
* before its first event — matching ``session.ts#switchConversation``.
|
|
1150
1161
|
*/
|
|
1151
1162
|
declare function replayEvents(sseEvents: RawSseEvent[], userMessages: {
|
|
1152
1163
|
role: string;
|
package/dist/index.js
CHANGED
|
@@ -379,7 +379,7 @@ var AstralformClient = class {
|
|
|
379
379
|
Authorization: `Bearer ${this.auth.accessToken}`
|
|
380
380
|
};
|
|
381
381
|
if (this.auth.agentId) {
|
|
382
|
-
headers["X-
|
|
382
|
+
headers["X-Agent-ID"] = this.auth.agentId;
|
|
383
383
|
}
|
|
384
384
|
if (this.auth.endUserId) {
|
|
385
385
|
headers["X-End-User-ID"] = this.auth.endUserId;
|
|
@@ -434,10 +434,9 @@ var AstralformClient = class {
|
|
|
434
434
|
async getHealth() {
|
|
435
435
|
return this.get("/v1/health");
|
|
436
436
|
}
|
|
437
|
-
// Agent readiness check
|
|
438
|
-
// iOS SDK) — it scopes to the client's active agent via X-Project-ID.
|
|
437
|
+
// Agent readiness check, scoped to the client's active agent via X-Agent-ID.
|
|
439
438
|
async getAgentStatus() {
|
|
440
|
-
const raw = await this.get("/v1/
|
|
439
|
+
const raw = await this.get("/v1/agent/status");
|
|
441
440
|
const ui = raw.ui_components ?? {};
|
|
442
441
|
return {
|
|
443
442
|
isReady: raw.is_ready,
|
|
@@ -607,7 +606,7 @@ var AstralformClient = class {
|
|
|
607
606
|
// --- Account-scoped discovery (user-token mode) ---
|
|
608
607
|
//
|
|
609
608
|
// Lets a signed-in user pick which team/agent they want to act on.
|
|
610
|
-
// Backend gates these on OIDC user context (no X-
|
|
609
|
+
// Backend gates these on OIDC user context (no X-Agent-ID required) —
|
|
611
610
|
// sending them in API-key mode yields 401.
|
|
612
611
|
async listTeams() {
|
|
613
612
|
const raw = await this.get("/v1/teams");
|
|
@@ -1629,17 +1628,12 @@ var ChatSession = class {
|
|
|
1629
1628
|
]);
|
|
1630
1629
|
this.messages = messagesResult.status === "fulfilled" ? messagesResult.value : [];
|
|
1631
1630
|
if (eventsResult.status === "fulfilled") {
|
|
1632
|
-
|
|
1631
|
+
if (userMessageContent) {
|
|
1632
|
+
this.emit({ type: "user_message", content: userMessageContent });
|
|
1633
|
+
}
|
|
1633
1634
|
for (const ev of eventsResult.value) {
|
|
1634
1635
|
const type = ev.data.type || ev.event;
|
|
1635
1636
|
if (!type || type === "done") continue;
|
|
1636
|
-
if (!userMessageEmitted && type === "message_start") {
|
|
1637
|
-
this.emit({
|
|
1638
|
-
type: "user_message",
|
|
1639
|
-
content: userMessageContent
|
|
1640
|
-
});
|
|
1641
|
-
userMessageEmitted = true;
|
|
1642
|
-
}
|
|
1643
1637
|
const wire = { ...ev.data, type };
|
|
1644
1638
|
try {
|
|
1645
1639
|
await this.dispatchWireEvent(
|
|
@@ -1948,21 +1942,21 @@ function mapSseToChat(raw) {
|
|
|
1948
1942
|
function replayEvents(sseEvents, userMessages, handleEvent, addBlock) {
|
|
1949
1943
|
const userMsgs = userMessages.filter((m) => m.role === "user");
|
|
1950
1944
|
let userIdx = 0;
|
|
1951
|
-
let
|
|
1945
|
+
let currentJobId = null;
|
|
1952
1946
|
for (const raw of sseEvents) {
|
|
1953
1947
|
const type = raw.data.type || raw.event;
|
|
1954
|
-
if (type === "
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1948
|
+
if (!type || type === "done") continue;
|
|
1949
|
+
const jobId = raw.data.job_id ?? null;
|
|
1950
|
+
if (jobId !== null && jobId !== currentJobId) {
|
|
1951
|
+
currentJobId = jobId;
|
|
1952
|
+
if (userIdx < userMsgs.length) {
|
|
1953
|
+
addBlock({
|
|
1954
|
+
type: "user",
|
|
1955
|
+
id: `replay_user_${userIdx}`,
|
|
1956
|
+
content: userMsgs[userIdx].content
|
|
1957
|
+
});
|
|
1958
|
+
userIdx++;
|
|
1959
|
+
}
|
|
1966
1960
|
}
|
|
1967
1961
|
for (const ce of mapSseToChat(raw)) {
|
|
1968
1962
|
handleEvent(ce);
|