@copilotkitnext/runtime 0.0.17 → 0.0.19-threads-and-attachements.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/dist/index.d.mts +246 -8
- package/dist/index.d.ts +246 -8
- package/dist/index.js +650 -255
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +638 -251
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { MaybePromise, NonEmptyRecord } from '@copilotkitnext/shared';
|
|
1
|
+
import { MaybePromise, ThreadMetadata, NonEmptyRecord } from '@copilotkitnext/shared';
|
|
2
|
+
export { ThreadMetadata, finalizeRunEvents } from '@copilotkitnext/shared';
|
|
2
3
|
import { AbstractAgent, RunAgentInput, BaseEvent } from '@ag-ui/client';
|
|
3
4
|
import { Observable } from 'rxjs';
|
|
4
5
|
import * as hono_hono_base from 'hono/hono-base';
|
|
@@ -47,13 +48,26 @@ declare abstract class TranscriptionService {
|
|
|
47
48
|
abstract transcribeFile(options: TranscribeFileOptions): Promise<string>;
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Resource scope for thread access control.
|
|
53
|
+
*
|
|
54
|
+
* @property resourceId - Primary isolation dimension (indexed, fast queries).
|
|
55
|
+
* Can be a single string or array of strings for multi-resource access.
|
|
56
|
+
* @property properties - Optional metadata (flexible, slower JSON queries).
|
|
57
|
+
*/
|
|
58
|
+
interface ResourceScope {
|
|
59
|
+
resourceId: string | string[];
|
|
60
|
+
properties?: Record<string, any>;
|
|
61
|
+
}
|
|
50
62
|
interface AgentRunnerRunRequest {
|
|
51
63
|
threadId: string;
|
|
52
64
|
agent: AbstractAgent;
|
|
53
65
|
input: RunAgentInput;
|
|
66
|
+
scope?: ResourceScope | null;
|
|
54
67
|
}
|
|
55
68
|
interface AgentRunnerConnectRequest {
|
|
56
69
|
threadId: string;
|
|
70
|
+
scope?: ResourceScope | null;
|
|
57
71
|
}
|
|
58
72
|
interface AgentRunnerIsRunningRequest {
|
|
59
73
|
threadId: string;
|
|
@@ -61,14 +75,27 @@ interface AgentRunnerIsRunningRequest {
|
|
|
61
75
|
interface AgentRunnerStopRequest {
|
|
62
76
|
threadId: string;
|
|
63
77
|
}
|
|
78
|
+
interface AgentRunnerListThreadsRequest {
|
|
79
|
+
scope?: ResourceScope | null;
|
|
80
|
+
limit?: number;
|
|
81
|
+
offset?: number;
|
|
82
|
+
}
|
|
83
|
+
interface AgentRunnerListThreadsResponse {
|
|
84
|
+
threads: ThreadMetadata[];
|
|
85
|
+
total: number;
|
|
86
|
+
}
|
|
64
87
|
declare abstract class AgentRunner {
|
|
65
88
|
abstract run(request: AgentRunnerRunRequest): Observable<BaseEvent>;
|
|
66
89
|
abstract connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>;
|
|
67
90
|
abstract isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>;
|
|
68
91
|
abstract stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>;
|
|
92
|
+
abstract listThreads(request: AgentRunnerListThreadsRequest): Promise<AgentRunnerListThreadsResponse>;
|
|
93
|
+
abstract getThreadMetadata(threadId: string, scope?: ResourceScope | null): Promise<ThreadMetadata | null>;
|
|
94
|
+
abstract deleteThread(threadId: string, scope?: ResourceScope | null): Promise<void>;
|
|
69
95
|
}
|
|
70
96
|
|
|
71
97
|
declare const VERSION: string;
|
|
98
|
+
|
|
72
99
|
/**
|
|
73
100
|
* Options used to construct a `CopilotRuntime` instance.
|
|
74
101
|
*/
|
|
@@ -83,17 +110,115 @@ interface CopilotRuntimeOptions {
|
|
|
83
110
|
beforeRequestMiddleware?: BeforeRequestMiddleware;
|
|
84
111
|
/** Optional *after* middleware – callback function or webhook URL. */
|
|
85
112
|
afterRequestMiddleware?: AfterRequestMiddleware;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve the resource scope for thread access control.
|
|
115
|
+
* This is where you authenticate the request and determine which resource(s)
|
|
116
|
+
* the user has access to.
|
|
117
|
+
*
|
|
118
|
+
* If not provided, defaults to GLOBAL_SCOPE (all threads globally accessible).
|
|
119
|
+
*
|
|
120
|
+
* Return `null` for admin bypass (no filtering).
|
|
121
|
+
*
|
|
122
|
+
* @param context.request - The incoming HTTP request
|
|
123
|
+
* @param context.clientDeclared - Resource ID(s) the client declares it wants to access (must be validated)
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* // Basic usage (determine access from authentication)
|
|
128
|
+
* resolveThreadsScope: async ({ request }) => {
|
|
129
|
+
* const user = await authenticate(request);
|
|
130
|
+
* return { resourceId: user.id };
|
|
131
|
+
* }
|
|
132
|
+
*
|
|
133
|
+
* // Validate client-declared resourceId
|
|
134
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
135
|
+
* const user = await authenticate(request);
|
|
136
|
+
* if (clientDeclared && clientDeclared !== user.id) {
|
|
137
|
+
* throw new Error('Unauthorized');
|
|
138
|
+
* }
|
|
139
|
+
* return { resourceId: user.id };
|
|
140
|
+
* }
|
|
141
|
+
*
|
|
142
|
+
* // Multi-resource: Filter client-declared IDs to only those user has access to
|
|
143
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
144
|
+
* const user = await authenticate(request);
|
|
145
|
+
* const userResourceIds = await getUserResourceIds(user);
|
|
146
|
+
* const requestedIds = Array.isArray(clientDeclared) ? clientDeclared : [clientDeclared];
|
|
147
|
+
* const allowedIds = requestedIds.filter(id => userResourceIds.includes(id));
|
|
148
|
+
* return { resourceId: allowedIds };
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
resolveThreadsScope?: (context: {
|
|
153
|
+
request: Request;
|
|
154
|
+
clientDeclared?: string | string[];
|
|
155
|
+
}) => Promise<ResourceScope | null>;
|
|
156
|
+
/**
|
|
157
|
+
* Suppress warning when using GLOBAL_SCOPE.
|
|
158
|
+
*
|
|
159
|
+
* Set to `true` if you intentionally want all threads to be globally accessible
|
|
160
|
+
* (e.g., single-user apps, demos, prototypes).
|
|
161
|
+
*/
|
|
162
|
+
suppressResourceIdWarning?: boolean;
|
|
86
163
|
}
|
|
87
164
|
/**
|
|
88
165
|
* Central runtime object passed to all request handlers.
|
|
89
166
|
*/
|
|
90
167
|
declare class CopilotRuntime {
|
|
168
|
+
/**
|
|
169
|
+
* Built-in global scope for single-user apps or demos.
|
|
170
|
+
*
|
|
171
|
+
* All threads are globally accessible when using this scope.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* new CopilotRuntime({
|
|
176
|
+
* agents: { myAgent },
|
|
177
|
+
* resolveThreadsScope: CopilotRuntime.GLOBAL_SCOPE,
|
|
178
|
+
* suppressResourceIdWarning: true
|
|
179
|
+
* });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
static readonly GLOBAL_SCOPE: (context: {
|
|
183
|
+
request: Request;
|
|
184
|
+
clientDeclared?: string | string[];
|
|
185
|
+
}) => Promise<ResourceScope>;
|
|
186
|
+
/**
|
|
187
|
+
* Parses the client-declared resource ID(s) from the request header.
|
|
188
|
+
*
|
|
189
|
+
* This is a utility method used internally by handlers to extract the
|
|
190
|
+
* `X-CopilotKit-Resource-ID` header sent by the client via `CopilotKitProvider`.
|
|
191
|
+
*
|
|
192
|
+
* **You typically don't need to call this directly** - it's automatically called
|
|
193
|
+
* by the runtime handlers and passed to your `resolveThreadsScope` function as
|
|
194
|
+
* the `clientDeclared` parameter.
|
|
195
|
+
*
|
|
196
|
+
* @param request - The incoming HTTP request
|
|
197
|
+
* @returns The parsed resource ID(s), or undefined if header is missing
|
|
198
|
+
* - Returns a string if single ID
|
|
199
|
+
* - Returns an array if multiple comma-separated IDs
|
|
200
|
+
* - Returns undefined if header not present
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* // Automatically used internally:
|
|
205
|
+
* const clientDeclared = CopilotRuntime.parseClientDeclaredResourceId(request);
|
|
206
|
+
* const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
static parseClientDeclaredResourceId(request: Request): string | string[] | undefined;
|
|
91
210
|
agents: CopilotRuntimeOptions["agents"];
|
|
92
211
|
transcriptionService: CopilotRuntimeOptions["transcriptionService"];
|
|
93
212
|
beforeRequestMiddleware: CopilotRuntimeOptions["beforeRequestMiddleware"];
|
|
94
213
|
afterRequestMiddleware: CopilotRuntimeOptions["afterRequestMiddleware"];
|
|
95
214
|
runner: AgentRunner;
|
|
96
|
-
|
|
215
|
+
resolveThreadsScope: (context: {
|
|
216
|
+
request: Request;
|
|
217
|
+
clientDeclared?: string | string[];
|
|
218
|
+
}) => Promise<ResourceScope | null>;
|
|
219
|
+
private suppressResourceIdWarning;
|
|
220
|
+
constructor({ agents, transcriptionService, beforeRequestMiddleware, afterRequestMiddleware, runner, resolveThreadsScope, suppressResourceIdWarning, }: CopilotRuntimeOptions);
|
|
221
|
+
private logGlobalScopeWarning;
|
|
97
222
|
}
|
|
98
223
|
|
|
99
224
|
interface CopilotEndpointParams {
|
|
@@ -166,6 +291,41 @@ declare function createCopilotEndpoint({ runtime, basePath }: CopilotEndpointPar
|
|
|
166
291
|
status: hono_utils_http_status.StatusCode;
|
|
167
292
|
};
|
|
168
293
|
};
|
|
294
|
+
} & {
|
|
295
|
+
[x: `${string}/threads`]: {
|
|
296
|
+
$get: {
|
|
297
|
+
input: {};
|
|
298
|
+
output: {};
|
|
299
|
+
outputFormat: string;
|
|
300
|
+
status: hono_utils_http_status.StatusCode;
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
} & {
|
|
304
|
+
[x: `${string}/threads/:threadId`]: {
|
|
305
|
+
$get: {
|
|
306
|
+
input: {
|
|
307
|
+
param: {
|
|
308
|
+
threadId: string;
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
output: {};
|
|
312
|
+
outputFormat: string;
|
|
313
|
+
status: hono_utils_http_status.StatusCode;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
} & {
|
|
317
|
+
[x: `${string}/threads/:threadId`]: {
|
|
318
|
+
$delete: {
|
|
319
|
+
input: {
|
|
320
|
+
param: {
|
|
321
|
+
threadId: string;
|
|
322
|
+
};
|
|
323
|
+
};
|
|
324
|
+
output: {};
|
|
325
|
+
outputFormat: string;
|
|
326
|
+
status: hono_utils_http_status.StatusCode;
|
|
327
|
+
};
|
|
328
|
+
};
|
|
169
329
|
}, string>;
|
|
170
330
|
|
|
171
331
|
declare class InMemoryAgentRunner extends AgentRunner {
|
|
@@ -173,12 +333,90 @@ declare class InMemoryAgentRunner extends AgentRunner {
|
|
|
173
333
|
connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>;
|
|
174
334
|
isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>;
|
|
175
335
|
stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>;
|
|
336
|
+
listThreads(request: AgentRunnerListThreadsRequest): Promise<AgentRunnerListThreadsResponse>;
|
|
337
|
+
getThreadMetadata(threadId: string, scope?: {
|
|
338
|
+
resourceId: string | string[];
|
|
339
|
+
} | null): Promise<ThreadMetadata | null>;
|
|
340
|
+
deleteThread(threadId: string, scope?: {
|
|
341
|
+
resourceId: string | string[];
|
|
342
|
+
} | null): Promise<void>;
|
|
343
|
+
/**
|
|
344
|
+
* Clear all threads from the global store (for testing purposes only)
|
|
345
|
+
* @internal
|
|
346
|
+
*/
|
|
347
|
+
clearAllThreads(): void;
|
|
176
348
|
}
|
|
177
349
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Helper to validate that client-declared resourceId matches the authenticated user's resourceId.
|
|
352
|
+
*
|
|
353
|
+
* Throws an error if validation fails.
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```typescript
|
|
357
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
358
|
+
* const user = await authenticate(request);
|
|
359
|
+
* validateResourceIdMatch(clientDeclared, user.id);
|
|
360
|
+
* return { resourceId: user.id };
|
|
361
|
+
* }
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
declare function validateResourceIdMatch(clientDeclared: string | string[] | undefined, serverAuthorized: string | string[]): void;
|
|
365
|
+
/**
|
|
366
|
+
* Helper to filter client-declared resourceIds to only those the user has access to.
|
|
367
|
+
*
|
|
368
|
+
* Returns the filtered resourceId(s), or throws if no valid IDs remain.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```typescript
|
|
372
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
373
|
+
* const user = await authenticate(request);
|
|
374
|
+
* const userResourceIds = await getUserAccessibleResources(user);
|
|
375
|
+
* const resourceId = filterAuthorizedResourceIds(clientDeclared, userResourceIds);
|
|
376
|
+
* return { resourceId };
|
|
377
|
+
* }
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
declare function filterAuthorizedResourceIds(clientDeclared: string | string[] | undefined, serverAuthorized: string | string[]): string | string[];
|
|
381
|
+
/**
|
|
382
|
+
* Helper to create a strict thread scope resolver that only allows exact matches.
|
|
383
|
+
*
|
|
384
|
+
* Use this when you want to enforce that the client MUST declare the correct resourceId.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```typescript
|
|
388
|
+
* new CopilotRuntime({
|
|
389
|
+
* agents: { myAgent },
|
|
390
|
+
* resolveThreadsScope: createStrictThreadScopeResolver(async (request) => {
|
|
391
|
+
* const user = await authenticate(request);
|
|
392
|
+
* return user.id;
|
|
393
|
+
* })
|
|
394
|
+
* });
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
397
|
+
declare function createStrictThreadScopeResolver(getUserId: (request: Request) => Promise<string | string[]>): (context: {
|
|
398
|
+
request: Request;
|
|
399
|
+
clientDeclared?: string | string[];
|
|
400
|
+
}) => Promise<ResourceScope>;
|
|
401
|
+
/**
|
|
402
|
+
* Helper to create a filtering thread scope resolver for multi-resource scenarios.
|
|
403
|
+
*
|
|
404
|
+
* Use this when users have access to multiple resources (e.g., multiple workspaces).
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* new CopilotRuntime({
|
|
409
|
+
* agents: { myAgent },
|
|
410
|
+
* resolveThreadsScope: createFilteringThreadScopeResolver(async (request) => {
|
|
411
|
+
* const user = await authenticate(request);
|
|
412
|
+
* return await getUserAccessibleWorkspaces(user);
|
|
413
|
+
* })
|
|
414
|
+
* });
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
declare function createFilteringThreadScopeResolver(getUserResourceIds: (request: Request) => Promise<string[]>): (context: {
|
|
418
|
+
request: Request;
|
|
419
|
+
clientDeclared?: string | string[];
|
|
420
|
+
}) => Promise<ResourceScope>;
|
|
183
421
|
|
|
184
|
-
export { AgentRunner, type AgentRunnerConnectRequest, type AgentRunnerIsRunningRequest, type AgentRunnerRunRequest, type AgentRunnerStopRequest, CopilotRuntime, type CopilotRuntimeOptions, InMemoryAgentRunner, VERSION, createCopilotEndpoint,
|
|
422
|
+
export { AgentRunner, type AgentRunnerConnectRequest, type AgentRunnerIsRunningRequest, type AgentRunnerListThreadsRequest, type AgentRunnerListThreadsResponse, type AgentRunnerRunRequest, type AgentRunnerStopRequest, CopilotRuntime, type CopilotRuntimeOptions, InMemoryAgentRunner, type ResourceScope, VERSION, createCopilotEndpoint, createFilteringThreadScopeResolver, createStrictThreadScopeResolver, filterAuthorizedResourceIds, validateResourceIdMatch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { MaybePromise, NonEmptyRecord } from '@copilotkitnext/shared';
|
|
1
|
+
import { MaybePromise, ThreadMetadata, NonEmptyRecord } from '@copilotkitnext/shared';
|
|
2
|
+
export { ThreadMetadata, finalizeRunEvents } from '@copilotkitnext/shared';
|
|
2
3
|
import { AbstractAgent, RunAgentInput, BaseEvent } from '@ag-ui/client';
|
|
3
4
|
import { Observable } from 'rxjs';
|
|
4
5
|
import * as hono_hono_base from 'hono/hono-base';
|
|
@@ -47,13 +48,26 @@ declare abstract class TranscriptionService {
|
|
|
47
48
|
abstract transcribeFile(options: TranscribeFileOptions): Promise<string>;
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Resource scope for thread access control.
|
|
53
|
+
*
|
|
54
|
+
* @property resourceId - Primary isolation dimension (indexed, fast queries).
|
|
55
|
+
* Can be a single string or array of strings for multi-resource access.
|
|
56
|
+
* @property properties - Optional metadata (flexible, slower JSON queries).
|
|
57
|
+
*/
|
|
58
|
+
interface ResourceScope {
|
|
59
|
+
resourceId: string | string[];
|
|
60
|
+
properties?: Record<string, any>;
|
|
61
|
+
}
|
|
50
62
|
interface AgentRunnerRunRequest {
|
|
51
63
|
threadId: string;
|
|
52
64
|
agent: AbstractAgent;
|
|
53
65
|
input: RunAgentInput;
|
|
66
|
+
scope?: ResourceScope | null;
|
|
54
67
|
}
|
|
55
68
|
interface AgentRunnerConnectRequest {
|
|
56
69
|
threadId: string;
|
|
70
|
+
scope?: ResourceScope | null;
|
|
57
71
|
}
|
|
58
72
|
interface AgentRunnerIsRunningRequest {
|
|
59
73
|
threadId: string;
|
|
@@ -61,14 +75,27 @@ interface AgentRunnerIsRunningRequest {
|
|
|
61
75
|
interface AgentRunnerStopRequest {
|
|
62
76
|
threadId: string;
|
|
63
77
|
}
|
|
78
|
+
interface AgentRunnerListThreadsRequest {
|
|
79
|
+
scope?: ResourceScope | null;
|
|
80
|
+
limit?: number;
|
|
81
|
+
offset?: number;
|
|
82
|
+
}
|
|
83
|
+
interface AgentRunnerListThreadsResponse {
|
|
84
|
+
threads: ThreadMetadata[];
|
|
85
|
+
total: number;
|
|
86
|
+
}
|
|
64
87
|
declare abstract class AgentRunner {
|
|
65
88
|
abstract run(request: AgentRunnerRunRequest): Observable<BaseEvent>;
|
|
66
89
|
abstract connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>;
|
|
67
90
|
abstract isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>;
|
|
68
91
|
abstract stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>;
|
|
92
|
+
abstract listThreads(request: AgentRunnerListThreadsRequest): Promise<AgentRunnerListThreadsResponse>;
|
|
93
|
+
abstract getThreadMetadata(threadId: string, scope?: ResourceScope | null): Promise<ThreadMetadata | null>;
|
|
94
|
+
abstract deleteThread(threadId: string, scope?: ResourceScope | null): Promise<void>;
|
|
69
95
|
}
|
|
70
96
|
|
|
71
97
|
declare const VERSION: string;
|
|
98
|
+
|
|
72
99
|
/**
|
|
73
100
|
* Options used to construct a `CopilotRuntime` instance.
|
|
74
101
|
*/
|
|
@@ -83,17 +110,115 @@ interface CopilotRuntimeOptions {
|
|
|
83
110
|
beforeRequestMiddleware?: BeforeRequestMiddleware;
|
|
84
111
|
/** Optional *after* middleware – callback function or webhook URL. */
|
|
85
112
|
afterRequestMiddleware?: AfterRequestMiddleware;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve the resource scope for thread access control.
|
|
115
|
+
* This is where you authenticate the request and determine which resource(s)
|
|
116
|
+
* the user has access to.
|
|
117
|
+
*
|
|
118
|
+
* If not provided, defaults to GLOBAL_SCOPE (all threads globally accessible).
|
|
119
|
+
*
|
|
120
|
+
* Return `null` for admin bypass (no filtering).
|
|
121
|
+
*
|
|
122
|
+
* @param context.request - The incoming HTTP request
|
|
123
|
+
* @param context.clientDeclared - Resource ID(s) the client declares it wants to access (must be validated)
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* // Basic usage (determine access from authentication)
|
|
128
|
+
* resolveThreadsScope: async ({ request }) => {
|
|
129
|
+
* const user = await authenticate(request);
|
|
130
|
+
* return { resourceId: user.id };
|
|
131
|
+
* }
|
|
132
|
+
*
|
|
133
|
+
* // Validate client-declared resourceId
|
|
134
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
135
|
+
* const user = await authenticate(request);
|
|
136
|
+
* if (clientDeclared && clientDeclared !== user.id) {
|
|
137
|
+
* throw new Error('Unauthorized');
|
|
138
|
+
* }
|
|
139
|
+
* return { resourceId: user.id };
|
|
140
|
+
* }
|
|
141
|
+
*
|
|
142
|
+
* // Multi-resource: Filter client-declared IDs to only those user has access to
|
|
143
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
144
|
+
* const user = await authenticate(request);
|
|
145
|
+
* const userResourceIds = await getUserResourceIds(user);
|
|
146
|
+
* const requestedIds = Array.isArray(clientDeclared) ? clientDeclared : [clientDeclared];
|
|
147
|
+
* const allowedIds = requestedIds.filter(id => userResourceIds.includes(id));
|
|
148
|
+
* return { resourceId: allowedIds };
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
resolveThreadsScope?: (context: {
|
|
153
|
+
request: Request;
|
|
154
|
+
clientDeclared?: string | string[];
|
|
155
|
+
}) => Promise<ResourceScope | null>;
|
|
156
|
+
/**
|
|
157
|
+
* Suppress warning when using GLOBAL_SCOPE.
|
|
158
|
+
*
|
|
159
|
+
* Set to `true` if you intentionally want all threads to be globally accessible
|
|
160
|
+
* (e.g., single-user apps, demos, prototypes).
|
|
161
|
+
*/
|
|
162
|
+
suppressResourceIdWarning?: boolean;
|
|
86
163
|
}
|
|
87
164
|
/**
|
|
88
165
|
* Central runtime object passed to all request handlers.
|
|
89
166
|
*/
|
|
90
167
|
declare class CopilotRuntime {
|
|
168
|
+
/**
|
|
169
|
+
* Built-in global scope for single-user apps or demos.
|
|
170
|
+
*
|
|
171
|
+
* All threads are globally accessible when using this scope.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* new CopilotRuntime({
|
|
176
|
+
* agents: { myAgent },
|
|
177
|
+
* resolveThreadsScope: CopilotRuntime.GLOBAL_SCOPE,
|
|
178
|
+
* suppressResourceIdWarning: true
|
|
179
|
+
* });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
static readonly GLOBAL_SCOPE: (context: {
|
|
183
|
+
request: Request;
|
|
184
|
+
clientDeclared?: string | string[];
|
|
185
|
+
}) => Promise<ResourceScope>;
|
|
186
|
+
/**
|
|
187
|
+
* Parses the client-declared resource ID(s) from the request header.
|
|
188
|
+
*
|
|
189
|
+
* This is a utility method used internally by handlers to extract the
|
|
190
|
+
* `X-CopilotKit-Resource-ID` header sent by the client via `CopilotKitProvider`.
|
|
191
|
+
*
|
|
192
|
+
* **You typically don't need to call this directly** - it's automatically called
|
|
193
|
+
* by the runtime handlers and passed to your `resolveThreadsScope` function as
|
|
194
|
+
* the `clientDeclared` parameter.
|
|
195
|
+
*
|
|
196
|
+
* @param request - The incoming HTTP request
|
|
197
|
+
* @returns The parsed resource ID(s), or undefined if header is missing
|
|
198
|
+
* - Returns a string if single ID
|
|
199
|
+
* - Returns an array if multiple comma-separated IDs
|
|
200
|
+
* - Returns undefined if header not present
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* // Automatically used internally:
|
|
205
|
+
* const clientDeclared = CopilotRuntime.parseClientDeclaredResourceId(request);
|
|
206
|
+
* const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
static parseClientDeclaredResourceId(request: Request): string | string[] | undefined;
|
|
91
210
|
agents: CopilotRuntimeOptions["agents"];
|
|
92
211
|
transcriptionService: CopilotRuntimeOptions["transcriptionService"];
|
|
93
212
|
beforeRequestMiddleware: CopilotRuntimeOptions["beforeRequestMiddleware"];
|
|
94
213
|
afterRequestMiddleware: CopilotRuntimeOptions["afterRequestMiddleware"];
|
|
95
214
|
runner: AgentRunner;
|
|
96
|
-
|
|
215
|
+
resolveThreadsScope: (context: {
|
|
216
|
+
request: Request;
|
|
217
|
+
clientDeclared?: string | string[];
|
|
218
|
+
}) => Promise<ResourceScope | null>;
|
|
219
|
+
private suppressResourceIdWarning;
|
|
220
|
+
constructor({ agents, transcriptionService, beforeRequestMiddleware, afterRequestMiddleware, runner, resolveThreadsScope, suppressResourceIdWarning, }: CopilotRuntimeOptions);
|
|
221
|
+
private logGlobalScopeWarning;
|
|
97
222
|
}
|
|
98
223
|
|
|
99
224
|
interface CopilotEndpointParams {
|
|
@@ -166,6 +291,41 @@ declare function createCopilotEndpoint({ runtime, basePath }: CopilotEndpointPar
|
|
|
166
291
|
status: hono_utils_http_status.StatusCode;
|
|
167
292
|
};
|
|
168
293
|
};
|
|
294
|
+
} & {
|
|
295
|
+
[x: `${string}/threads`]: {
|
|
296
|
+
$get: {
|
|
297
|
+
input: {};
|
|
298
|
+
output: {};
|
|
299
|
+
outputFormat: string;
|
|
300
|
+
status: hono_utils_http_status.StatusCode;
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
} & {
|
|
304
|
+
[x: `${string}/threads/:threadId`]: {
|
|
305
|
+
$get: {
|
|
306
|
+
input: {
|
|
307
|
+
param: {
|
|
308
|
+
threadId: string;
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
output: {};
|
|
312
|
+
outputFormat: string;
|
|
313
|
+
status: hono_utils_http_status.StatusCode;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
} & {
|
|
317
|
+
[x: `${string}/threads/:threadId`]: {
|
|
318
|
+
$delete: {
|
|
319
|
+
input: {
|
|
320
|
+
param: {
|
|
321
|
+
threadId: string;
|
|
322
|
+
};
|
|
323
|
+
};
|
|
324
|
+
output: {};
|
|
325
|
+
outputFormat: string;
|
|
326
|
+
status: hono_utils_http_status.StatusCode;
|
|
327
|
+
};
|
|
328
|
+
};
|
|
169
329
|
}, string>;
|
|
170
330
|
|
|
171
331
|
declare class InMemoryAgentRunner extends AgentRunner {
|
|
@@ -173,12 +333,90 @@ declare class InMemoryAgentRunner extends AgentRunner {
|
|
|
173
333
|
connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>;
|
|
174
334
|
isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>;
|
|
175
335
|
stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>;
|
|
336
|
+
listThreads(request: AgentRunnerListThreadsRequest): Promise<AgentRunnerListThreadsResponse>;
|
|
337
|
+
getThreadMetadata(threadId: string, scope?: {
|
|
338
|
+
resourceId: string | string[];
|
|
339
|
+
} | null): Promise<ThreadMetadata | null>;
|
|
340
|
+
deleteThread(threadId: string, scope?: {
|
|
341
|
+
resourceId: string | string[];
|
|
342
|
+
} | null): Promise<void>;
|
|
343
|
+
/**
|
|
344
|
+
* Clear all threads from the global store (for testing purposes only)
|
|
345
|
+
* @internal
|
|
346
|
+
*/
|
|
347
|
+
clearAllThreads(): void;
|
|
176
348
|
}
|
|
177
349
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Helper to validate that client-declared resourceId matches the authenticated user's resourceId.
|
|
352
|
+
*
|
|
353
|
+
* Throws an error if validation fails.
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```typescript
|
|
357
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
358
|
+
* const user = await authenticate(request);
|
|
359
|
+
* validateResourceIdMatch(clientDeclared, user.id);
|
|
360
|
+
* return { resourceId: user.id };
|
|
361
|
+
* }
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
declare function validateResourceIdMatch(clientDeclared: string | string[] | undefined, serverAuthorized: string | string[]): void;
|
|
365
|
+
/**
|
|
366
|
+
* Helper to filter client-declared resourceIds to only those the user has access to.
|
|
367
|
+
*
|
|
368
|
+
* Returns the filtered resourceId(s), or throws if no valid IDs remain.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```typescript
|
|
372
|
+
* resolveThreadsScope: async ({ request, clientDeclared }) => {
|
|
373
|
+
* const user = await authenticate(request);
|
|
374
|
+
* const userResourceIds = await getUserAccessibleResources(user);
|
|
375
|
+
* const resourceId = filterAuthorizedResourceIds(clientDeclared, userResourceIds);
|
|
376
|
+
* return { resourceId };
|
|
377
|
+
* }
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
declare function filterAuthorizedResourceIds(clientDeclared: string | string[] | undefined, serverAuthorized: string | string[]): string | string[];
|
|
381
|
+
/**
|
|
382
|
+
* Helper to create a strict thread scope resolver that only allows exact matches.
|
|
383
|
+
*
|
|
384
|
+
* Use this when you want to enforce that the client MUST declare the correct resourceId.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```typescript
|
|
388
|
+
* new CopilotRuntime({
|
|
389
|
+
* agents: { myAgent },
|
|
390
|
+
* resolveThreadsScope: createStrictThreadScopeResolver(async (request) => {
|
|
391
|
+
* const user = await authenticate(request);
|
|
392
|
+
* return user.id;
|
|
393
|
+
* })
|
|
394
|
+
* });
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
397
|
+
declare function createStrictThreadScopeResolver(getUserId: (request: Request) => Promise<string | string[]>): (context: {
|
|
398
|
+
request: Request;
|
|
399
|
+
clientDeclared?: string | string[];
|
|
400
|
+
}) => Promise<ResourceScope>;
|
|
401
|
+
/**
|
|
402
|
+
* Helper to create a filtering thread scope resolver for multi-resource scenarios.
|
|
403
|
+
*
|
|
404
|
+
* Use this when users have access to multiple resources (e.g., multiple workspaces).
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* new CopilotRuntime({
|
|
409
|
+
* agents: { myAgent },
|
|
410
|
+
* resolveThreadsScope: createFilteringThreadScopeResolver(async (request) => {
|
|
411
|
+
* const user = await authenticate(request);
|
|
412
|
+
* return await getUserAccessibleWorkspaces(user);
|
|
413
|
+
* })
|
|
414
|
+
* });
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
declare function createFilteringThreadScopeResolver(getUserResourceIds: (request: Request) => Promise<string[]>): (context: {
|
|
418
|
+
request: Request;
|
|
419
|
+
clientDeclared?: string | string[];
|
|
420
|
+
}) => Promise<ResourceScope>;
|
|
183
421
|
|
|
184
|
-
export { AgentRunner, type AgentRunnerConnectRequest, type AgentRunnerIsRunningRequest, type AgentRunnerRunRequest, type AgentRunnerStopRequest, CopilotRuntime, type CopilotRuntimeOptions, InMemoryAgentRunner, VERSION, createCopilotEndpoint,
|
|
422
|
+
export { AgentRunner, type AgentRunnerConnectRequest, type AgentRunnerIsRunningRequest, type AgentRunnerListThreadsRequest, type AgentRunnerListThreadsResponse, type AgentRunnerRunRequest, type AgentRunnerStopRequest, CopilotRuntime, type CopilotRuntimeOptions, InMemoryAgentRunner, type ResourceScope, VERSION, createCopilotEndpoint, createFilteringThreadScopeResolver, createStrictThreadScopeResolver, filterAuthorizedResourceIds, validateResourceIdMatch };
|