@agentforge-io/sdk-server 4.0.22 → 4.1.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.
@@ -9,6 +9,20 @@ export interface StreamMessageInput {
9
9
  /** Si se omite, el server crea una conversación nueva. */
10
10
  conversationId?: string;
11
11
  }
12
+ export interface StreamMessageForAppUserInput {
13
+ /** Which of the App's tenant agents to run. */
14
+ agentId: string;
15
+ /** The App's own identifier for its end user — NOT signed, rides as a
16
+ * plain param inside the sk_live_-authenticated request (AGF-072 §4.4
17
+ * rationale: the authenticated channel is the proof, not a per-user
18
+ * signature). Threads into the conversation key
19
+ * `app-user:${appId}:${externalUserId}` server-side; `appId` itself is
20
+ * never a param, only ever resolved from the secret. */
21
+ externalUserId: string;
22
+ content: string;
23
+ /** Si se omite, el server crea una conversación nueva. */
24
+ conversationId?: string;
25
+ }
12
26
  export declare class ChatResource {
13
27
  private readonly client;
14
28
  constructor(client: AgentForgeClient);
@@ -52,4 +66,37 @@ export declare class ChatResource {
52
66
  * no pertenece al ChatToken que llama.
53
67
  */
54
68
  getHistory(conversationId: string): Promise<ConversationHistory>;
69
+ /**
70
+ * AGF-073a — chat streaming AGENT-AWARE para el surface App-authenticated
71
+ * (`sk_live_`/`sk_test_`), server-to-server — `POST
72
+ * /api/v1/app-user-chat/conversations/stream` (o `.../conversations/:id/
73
+ * messages/stream` cuando `input.conversationId` viene seteado). Sibling
74
+ * ADITIVO de `streamMessage()`: NO usa ChatToken, requiere que el
75
+ * `AgentForgeClient` se haya construido con `appSecret`. `appId` lo
76
+ * resuelve el server exclusivamente del secret — nunca es un param acá
77
+ * tampoco (ver `APP_USER_CHAT_RUNTIME_SDD.md`).
78
+ *
79
+ * Mismo shape de eventos que `streamMessage()` — `ChatStreamEvent` con
80
+ * los mismos `kind`s (`conversation` | `chunk` | `stream_end` | `error`).
81
+ * Un consumidor no puede distinguir cuál de los dos métodos produjo el
82
+ * stream a partir de los eventos solos.
83
+ *
84
+ * @example
85
+ * const af = new AgentForgeClient({ baseURL, appSecret: 'sk_live_...' });
86
+ * for await (const ev of af.chat.streamMessageForAppUser({
87
+ * agentId: 'agent-uuid',
88
+ * externalUserId: 'scrappydoc-user-42',
89
+ * content: 'hola',
90
+ * })) {
91
+ * if (ev.kind === 'conversation') conversationId = ev.conversationId;
92
+ * }
93
+ */
94
+ streamMessageForAppUser(input: StreamMessageForAppUserInput): AsyncGenerator<ChatStreamEvent>;
95
+ /**
96
+ * AGF-073a companion to `streamMessageForAppUser` — historial completo de
97
+ * una conversación app-user, `GET /api/v1/app-user-chat/conversations/:id/
98
+ * messages?externalUserId=...`. `externalUserId` va como query param
99
+ * porque GET no lleva body; `appId` sigue resolviéndose del secret.
100
+ */
101
+ getHistoryForAppUser(conversationId: string, externalUserId: string): Promise<ConversationHistory>;
55
102
  }
@@ -110,6 +110,86 @@ class ChatResource {
110
110
  async getHistory(conversationId) {
111
111
  return this.client.request('GET', `/api/v1/chat/conversations/${encodeURIComponent(conversationId)}/messages`);
112
112
  }
113
+ /**
114
+ * AGF-073a — chat streaming AGENT-AWARE para el surface App-authenticated
115
+ * (`sk_live_`/`sk_test_`), server-to-server — `POST
116
+ * /api/v1/app-user-chat/conversations/stream` (o `.../conversations/:id/
117
+ * messages/stream` cuando `input.conversationId` viene seteado). Sibling
118
+ * ADITIVO de `streamMessage()`: NO usa ChatToken, requiere que el
119
+ * `AgentForgeClient` se haya construido con `appSecret`. `appId` lo
120
+ * resuelve el server exclusivamente del secret — nunca es un param acá
121
+ * tampoco (ver `APP_USER_CHAT_RUNTIME_SDD.md`).
122
+ *
123
+ * Mismo shape de eventos que `streamMessage()` — `ChatStreamEvent` con
124
+ * los mismos `kind`s (`conversation` | `chunk` | `stream_end` | `error`).
125
+ * Un consumidor no puede distinguir cuál de los dos métodos produjo el
126
+ * stream a partir de los eventos solos.
127
+ *
128
+ * @example
129
+ * const af = new AgentForgeClient({ baseURL, appSecret: 'sk_live_...' });
130
+ * for await (const ev of af.chat.streamMessageForAppUser({
131
+ * agentId: 'agent-uuid',
132
+ * externalUserId: 'scrappydoc-user-42',
133
+ * content: 'hola',
134
+ * })) {
135
+ * if (ev.kind === 'conversation') conversationId = ev.conversationId;
136
+ * }
137
+ */
138
+ async *streamMessageForAppUser(input) {
139
+ if (!this.client.getAppSecret()) {
140
+ throw new Error('chat.streamMessageForAppUser requires appSecret (sk_live_/sk_test_) in ' +
141
+ 'AgentForgeClient. This surface authenticates AS the App, not via chatToken.');
142
+ }
143
+ const path = input.conversationId
144
+ ? `/api/v1/app-user-chat/conversations/${encodeURIComponent(input.conversationId)}/messages/stream`
145
+ : '/api/v1/app-user-chat/conversations/stream';
146
+ const res = await this.client.requestStream('POST', path, {
147
+ agentId: input.agentId,
148
+ externalUserId: input.externalUserId,
149
+ content: input.content,
150
+ });
151
+ if (!res.body) {
152
+ throw new Error('chat.streamMessageForAppUser: response has no readable body');
153
+ }
154
+ const reader = res.body.getReader();
155
+ const decoder = new TextDecoder();
156
+ let buffer = '';
157
+ try {
158
+ for (;;) {
159
+ const { value, done } = await reader.read();
160
+ if (done)
161
+ break;
162
+ buffer += decoder.decode(value, { stream: true });
163
+ let idx;
164
+ while ((idx = buffer.indexOf('\n\n')) !== -1) {
165
+ const frame = buffer.slice(0, idx);
166
+ buffer = buffer.slice(idx + 2);
167
+ const raw = parseRawSseFrame(frame);
168
+ if (!raw)
169
+ continue;
170
+ const event = toChatStreamEvent(raw);
171
+ if (event)
172
+ yield event;
173
+ }
174
+ }
175
+ }
176
+ finally {
177
+ reader.releaseLock();
178
+ }
179
+ }
180
+ /**
181
+ * AGF-073a companion to `streamMessageForAppUser` — historial completo de
182
+ * una conversación app-user, `GET /api/v1/app-user-chat/conversations/:id/
183
+ * messages?externalUserId=...`. `externalUserId` va como query param
184
+ * porque GET no lleva body; `appId` sigue resolviéndose del secret.
185
+ */
186
+ async getHistoryForAppUser(conversationId, externalUserId) {
187
+ if (!this.client.getAppSecret()) {
188
+ throw new Error('chat.getHistoryForAppUser requires appSecret (sk_live_/sk_test_) in AgentForgeClient.');
189
+ }
190
+ return this.client.request('GET', `/api/v1/app-user-chat/conversations/${encodeURIComponent(conversationId)}/messages` +
191
+ `?externalUserId=${encodeURIComponent(externalUserId)}`);
192
+ }
113
193
  }
114
194
  exports.ChatResource = ChatResource;
115
195
  /** Frame SSE genérico: `event: <name>\ndata: <line>\ndata: <line>...`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge-io/sdk-server",
3
- "version": "4.0.22",
3
+ "version": "4.1.0",
4
4
  "description": "Server-side SDK for backend apps integrating with AgentForge platform. Auth via ChatToken or ak_live_ API key.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",