@stina/extension-api 0.26.0-alpha.48430e8 → 0.26.0-alpha.ea677a6
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/runtime.cjs +102 -142
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +102 -142
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
- package/src/runtime/executionContext.ts +37 -0
- package/src/runtime/index.ts +8 -0
- package/src/runtime/secretsApi.ts +48 -0
- package/src/runtime/storageApi.ts +67 -0
- package/src/runtime.ts +19 -162
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime module re-exports.
|
|
3
|
+
* These are extracted from the main runtime.ts for modularity.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { buildExtensionStorageAPI, buildUserStorageAPI } from './storageApi.js'
|
|
7
|
+
export { buildExtensionSecretsAPI, buildUserSecretsAPI } from './secretsApi.js'
|
|
8
|
+
export { createExecutionContext } from './executionContext.js'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets API builders for extension and user-scoped secrets.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SecretsAPI } from '../types.js'
|
|
6
|
+
import type { RequestMessage } from '../messages.js'
|
|
7
|
+
|
|
8
|
+
type SendRequest = <T>(method: RequestMessage['method'], payload: unknown) => Promise<T>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build extension-scoped secrets API (shared across all users).
|
|
12
|
+
*/
|
|
13
|
+
export function buildExtensionSecretsAPI(sendRequest: SendRequest): SecretsAPI {
|
|
14
|
+
return {
|
|
15
|
+
async set(key: string, value: string): Promise<void> {
|
|
16
|
+
return sendRequest<void>('secrets.set', { key, value })
|
|
17
|
+
},
|
|
18
|
+
async get(key: string): Promise<string | undefined> {
|
|
19
|
+
return sendRequest<string | undefined>('secrets.get', { key })
|
|
20
|
+
},
|
|
21
|
+
async delete(key: string): Promise<boolean> {
|
|
22
|
+
return sendRequest<boolean>('secrets.delete', { key })
|
|
23
|
+
},
|
|
24
|
+
async list(): Promise<string[]> {
|
|
25
|
+
return sendRequest<string[]>('secrets.list', {})
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build user-scoped secrets API (isolated per user).
|
|
32
|
+
*/
|
|
33
|
+
export function buildUserSecretsAPI(sendRequest: SendRequest, userId: string): SecretsAPI {
|
|
34
|
+
return {
|
|
35
|
+
async set(key: string, value: string): Promise<void> {
|
|
36
|
+
return sendRequest<void>('secrets.setForUser', { userId, key, value })
|
|
37
|
+
},
|
|
38
|
+
async get(key: string): Promise<string | undefined> {
|
|
39
|
+
return sendRequest<string | undefined>('secrets.getForUser', { userId, key })
|
|
40
|
+
},
|
|
41
|
+
async delete(key: string): Promise<boolean> {
|
|
42
|
+
return sendRequest<boolean>('secrets.deleteForUser', { userId, key })
|
|
43
|
+
},
|
|
44
|
+
async list(): Promise<string[]> {
|
|
45
|
+
return sendRequest<string[]>('secrets.listForUser', { userId })
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage API builders for extension and user-scoped storage.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { StorageAPI, Query, QueryOptions } from '../types.js'
|
|
6
|
+
import type { RequestMessage } from '../messages.js'
|
|
7
|
+
|
|
8
|
+
type SendRequest = <T>(method: RequestMessage['method'], payload: unknown) => Promise<T>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a storage API that delegates to the host via request messages.
|
|
12
|
+
* Used for both extension-scoped and user-scoped storage by varying the method prefix.
|
|
13
|
+
*/
|
|
14
|
+
function buildStorageAPI(
|
|
15
|
+
sendRequest: SendRequest,
|
|
16
|
+
methodSuffix: '' | 'ForUser',
|
|
17
|
+
userId?: string
|
|
18
|
+
): StorageAPI {
|
|
19
|
+
const extraPayload = userId ? { userId } : {}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
async put<T extends object>(collection: string, id: string, data: T): Promise<void> {
|
|
23
|
+
return sendRequest<void>(`storage.put${methodSuffix}`, { ...extraPayload, collection, id, data })
|
|
24
|
+
},
|
|
25
|
+
async get<T>(collection: string, id: string): Promise<T | undefined> {
|
|
26
|
+
return sendRequest<T | undefined>(`storage.get${methodSuffix}`, { ...extraPayload, collection, id })
|
|
27
|
+
},
|
|
28
|
+
async delete(collection: string, id: string): Promise<boolean> {
|
|
29
|
+
return sendRequest<boolean>(`storage.delete${methodSuffix}`, { ...extraPayload, collection, id })
|
|
30
|
+
},
|
|
31
|
+
async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {
|
|
32
|
+
return sendRequest<T[]>(`storage.find${methodSuffix}`, { ...extraPayload, collection, query, options })
|
|
33
|
+
},
|
|
34
|
+
async findOne<T>(collection: string, query: Query): Promise<T | undefined> {
|
|
35
|
+
return sendRequest<T | undefined>(`storage.findOne${methodSuffix}`, { ...extraPayload, collection, query })
|
|
36
|
+
},
|
|
37
|
+
async count(collection: string, query?: Query): Promise<number> {
|
|
38
|
+
return sendRequest<number>(`storage.count${methodSuffix}`, { ...extraPayload, collection, query })
|
|
39
|
+
},
|
|
40
|
+
async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {
|
|
41
|
+
return sendRequest<void>(`storage.putMany${methodSuffix}`, { ...extraPayload, collection, docs })
|
|
42
|
+
},
|
|
43
|
+
async deleteMany(collection: string, query: Query): Promise<number> {
|
|
44
|
+
return sendRequest<number>(`storage.deleteMany${methodSuffix}`, { ...extraPayload, collection, query })
|
|
45
|
+
},
|
|
46
|
+
async dropCollection(collection: string): Promise<void> {
|
|
47
|
+
return sendRequest<void>(`storage.dropCollection${methodSuffix}`, { ...extraPayload, collection })
|
|
48
|
+
},
|
|
49
|
+
async listCollections(): Promise<string[]> {
|
|
50
|
+
return sendRequest<string[]>(`storage.listCollections${methodSuffix}`, { ...extraPayload })
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Build extension-scoped storage API (shared across all users).
|
|
57
|
+
*/
|
|
58
|
+
export function buildExtensionStorageAPI(sendRequest: SendRequest): StorageAPI {
|
|
59
|
+
return buildStorageAPI(sendRequest, '')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Build user-scoped storage API (isolated per user).
|
|
64
|
+
*/
|
|
65
|
+
export function buildUserStorageAPI(sendRequest: SendRequest, userId: string): StorageAPI {
|
|
66
|
+
return buildStorageAPI(sendRequest, 'ForUser', userId)
|
|
67
|
+
}
|
package/src/runtime.ts
CHANGED
|
@@ -25,8 +25,6 @@ import type {
|
|
|
25
25
|
ChatInstructionMessage,
|
|
26
26
|
StorageAPI,
|
|
27
27
|
SecretsAPI,
|
|
28
|
-
Query,
|
|
29
|
-
QueryOptions,
|
|
30
28
|
LogAPI,
|
|
31
29
|
AIProvider,
|
|
32
30
|
Tool,
|
|
@@ -51,6 +49,14 @@ import type {
|
|
|
51
49
|
|
|
52
50
|
import { generateMessageId } from './messages.js'
|
|
53
51
|
|
|
52
|
+
import {
|
|
53
|
+
buildExtensionStorageAPI,
|
|
54
|
+
buildUserStorageAPI,
|
|
55
|
+
buildExtensionSecretsAPI,
|
|
56
|
+
buildUserSecretsAPI,
|
|
57
|
+
createExecutionContext,
|
|
58
|
+
} from './runtime/index.js'
|
|
59
|
+
|
|
54
60
|
// ============================================================================
|
|
55
61
|
// Environment Detection and Message Port
|
|
56
62
|
// ============================================================================
|
|
@@ -329,136 +335,11 @@ function handleSettingsChanged(key: string, value: unknown): void {
|
|
|
329
335
|
}
|
|
330
336
|
}
|
|
331
337
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
*/
|
|
335
|
-
function buildExtensionStorageAPI(): StorageAPI {
|
|
336
|
-
return {
|
|
337
|
-
async put<T extends object>(collection: string, id: string, data: T): Promise<void> {
|
|
338
|
-
return sendRequest<void>('storage.put', { collection, id, data })
|
|
339
|
-
},
|
|
340
|
-
async get<T>(collection: string, id: string): Promise<T | undefined> {
|
|
341
|
-
return sendRequest<T | undefined>('storage.get', { collection, id })
|
|
342
|
-
},
|
|
343
|
-
async delete(collection: string, id: string): Promise<boolean> {
|
|
344
|
-
return sendRequest<boolean>('storage.delete', { collection, id })
|
|
345
|
-
},
|
|
346
|
-
async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {
|
|
347
|
-
return sendRequest<T[]>('storage.find', { collection, query, options })
|
|
348
|
-
},
|
|
349
|
-
async findOne<T>(collection: string, query: Query): Promise<T | undefined> {
|
|
350
|
-
return sendRequest<T | undefined>('storage.findOne', { collection, query })
|
|
351
|
-
},
|
|
352
|
-
async count(collection: string, query?: Query): Promise<number> {
|
|
353
|
-
return sendRequest<number>('storage.count', { collection, query })
|
|
354
|
-
},
|
|
355
|
-
async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {
|
|
356
|
-
return sendRequest<void>('storage.putMany', { collection, docs })
|
|
357
|
-
},
|
|
358
|
-
async deleteMany(collection: string, query: Query): Promise<number> {
|
|
359
|
-
return sendRequest<number>('storage.deleteMany', { collection, query })
|
|
360
|
-
},
|
|
361
|
-
async dropCollection(collection: string): Promise<void> {
|
|
362
|
-
return sendRequest<void>('storage.dropCollection', { collection })
|
|
363
|
-
},
|
|
364
|
-
async listCollections(): Promise<string[]> {
|
|
365
|
-
return sendRequest<string[]>('storage.listCollections', {})
|
|
366
|
-
},
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Build user-scoped storage API
|
|
372
|
-
*/
|
|
373
|
-
function buildUserStorageAPI(userId: string): StorageAPI {
|
|
374
|
-
return {
|
|
375
|
-
async put<T extends object>(collection: string, id: string, data: T): Promise<void> {
|
|
376
|
-
return sendRequest<void>('storage.putForUser', { userId, collection, id, data })
|
|
377
|
-
},
|
|
378
|
-
async get<T>(collection: string, id: string): Promise<T | undefined> {
|
|
379
|
-
return sendRequest<T | undefined>('storage.getForUser', { userId, collection, id })
|
|
380
|
-
},
|
|
381
|
-
async delete(collection: string, id: string): Promise<boolean> {
|
|
382
|
-
return sendRequest<boolean>('storage.deleteForUser', { userId, collection, id })
|
|
383
|
-
},
|
|
384
|
-
async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {
|
|
385
|
-
return sendRequest<T[]>('storage.findForUser', { userId, collection, query, options })
|
|
386
|
-
},
|
|
387
|
-
async findOne<T>(collection: string, query: Query): Promise<T | undefined> {
|
|
388
|
-
return sendRequest<T | undefined>('storage.findOneForUser', { userId, collection, query })
|
|
389
|
-
},
|
|
390
|
-
async count(collection: string, query?: Query): Promise<number> {
|
|
391
|
-
return sendRequest<number>('storage.countForUser', { userId, collection, query })
|
|
392
|
-
},
|
|
393
|
-
async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {
|
|
394
|
-
return sendRequest<void>('storage.putManyForUser', { userId, collection, docs })
|
|
395
|
-
},
|
|
396
|
-
async deleteMany(collection: string, query: Query): Promise<number> {
|
|
397
|
-
return sendRequest<number>('storage.deleteManyForUser', { userId, collection, query })
|
|
398
|
-
},
|
|
399
|
-
async dropCollection(collection: string): Promise<void> {
|
|
400
|
-
return sendRequest<void>('storage.dropCollectionForUser', { userId, collection })
|
|
401
|
-
},
|
|
402
|
-
async listCollections(): Promise<string[]> {
|
|
403
|
-
return sendRequest<string[]>('storage.listCollectionsForUser', { userId })
|
|
404
|
-
},
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Build extension-scoped secrets API
|
|
410
|
-
*/
|
|
411
|
-
function buildExtensionSecretsAPI(): SecretsAPI {
|
|
412
|
-
return {
|
|
413
|
-
async set(key: string, value: string): Promise<void> {
|
|
414
|
-
return sendRequest<void>('secrets.set', { key, value })
|
|
415
|
-
},
|
|
416
|
-
async get(key: string): Promise<string | undefined> {
|
|
417
|
-
return sendRequest<string | undefined>('secrets.get', { key })
|
|
418
|
-
},
|
|
419
|
-
async delete(key: string): Promise<boolean> {
|
|
420
|
-
return sendRequest<boolean>('secrets.delete', { key })
|
|
421
|
-
},
|
|
422
|
-
async list(): Promise<string[]> {
|
|
423
|
-
return sendRequest<string[]>('secrets.list', {})
|
|
424
|
-
},
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Build user-scoped secrets API
|
|
430
|
-
*/
|
|
431
|
-
function buildUserSecretsAPI(userId: string): SecretsAPI {
|
|
432
|
-
return {
|
|
433
|
-
async set(key: string, value: string): Promise<void> {
|
|
434
|
-
return sendRequest<void>('secrets.setForUser', { userId, key, value })
|
|
435
|
-
},
|
|
436
|
-
async get(key: string): Promise<string | undefined> {
|
|
437
|
-
return sendRequest<string | undefined>('secrets.getForUser', { userId, key })
|
|
438
|
-
},
|
|
439
|
-
async delete(key: string): Promise<boolean> {
|
|
440
|
-
return sendRequest<boolean>('secrets.deleteForUser', { userId, key })
|
|
441
|
-
},
|
|
442
|
-
async list(): Promise<string[]> {
|
|
443
|
-
return sendRequest<string[]>('secrets.listForUser', { userId })
|
|
444
|
-
},
|
|
445
|
-
}
|
|
446
|
-
}
|
|
338
|
+
// Storage and Secrets APIs are now in runtime/storageApi.ts and runtime/secretsApi.ts
|
|
339
|
+
// ExecutionContext builder is in runtime/executionContext.ts
|
|
447
340
|
|
|
448
341
|
async function handleSchedulerFire(payload: SchedulerFirePayload): Promise<void> {
|
|
449
|
-
|
|
450
|
-
const execContext: ExecutionContext = {
|
|
451
|
-
userId: payload.userId,
|
|
452
|
-
extension: {
|
|
453
|
-
id: extensionContext!.extension.id,
|
|
454
|
-
version: extensionContext!.extension.version,
|
|
455
|
-
storagePath: extensionContext!.extension.storagePath,
|
|
456
|
-
},
|
|
457
|
-
storage: buildExtensionStorageAPI(),
|
|
458
|
-
userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),
|
|
459
|
-
secrets: buildExtensionSecretsAPI(),
|
|
460
|
-
userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),
|
|
461
|
-
}
|
|
342
|
+
const execContext = createExecutionContext(sendRequest, extensionContext!, payload.userId)
|
|
462
343
|
|
|
463
344
|
// Run callbacks concurrently to avoid blocking
|
|
464
345
|
const results = await Promise.allSettled(
|
|
@@ -624,19 +505,7 @@ async function handleToolExecuteRequest(
|
|
|
624
505
|
}
|
|
625
506
|
|
|
626
507
|
try {
|
|
627
|
-
|
|
628
|
-
const execContext: ExecutionContext = {
|
|
629
|
-
userId: payload.userId,
|
|
630
|
-
extension: {
|
|
631
|
-
id: extensionContext!.extension.id,
|
|
632
|
-
version: extensionContext!.extension.version,
|
|
633
|
-
storagePath: extensionContext!.extension.storagePath,
|
|
634
|
-
},
|
|
635
|
-
storage: buildExtensionStorageAPI(),
|
|
636
|
-
userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),
|
|
637
|
-
secrets: buildExtensionSecretsAPI(),
|
|
638
|
-
userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),
|
|
639
|
-
}
|
|
508
|
+
const execContext = createExecutionContext(sendRequest, extensionContext!, payload.userId)
|
|
640
509
|
|
|
641
510
|
const result = await tool.execute(payload.params, execContext)
|
|
642
511
|
|
|
@@ -679,19 +548,7 @@ async function handleActionExecuteRequest(
|
|
|
679
548
|
}
|
|
680
549
|
|
|
681
550
|
try {
|
|
682
|
-
|
|
683
|
-
const execContext: ExecutionContext = {
|
|
684
|
-
userId: payload.userId,
|
|
685
|
-
extension: {
|
|
686
|
-
id: extensionContext!.extension.id,
|
|
687
|
-
version: extensionContext!.extension.version,
|
|
688
|
-
storagePath: extensionContext!.extension.storagePath,
|
|
689
|
-
},
|
|
690
|
-
storage: buildExtensionStorageAPI(),
|
|
691
|
-
userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),
|
|
692
|
-
secrets: buildExtensionSecretsAPI(),
|
|
693
|
-
userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),
|
|
694
|
-
}
|
|
551
|
+
const execContext = createExecutionContext(sendRequest, extensionContext!, payload.userId)
|
|
695
552
|
|
|
696
553
|
const result = await action.execute(payload.params, execContext)
|
|
697
554
|
|
|
@@ -966,12 +823,12 @@ function buildContext(
|
|
|
966
823
|
|
|
967
824
|
// Add storage API if permitted (new collection-based storage)
|
|
968
825
|
if (hasPermission('storage.collections')) {
|
|
969
|
-
;(context as { storage: StorageAPI }).storage = buildExtensionStorageAPI()
|
|
826
|
+
;(context as { storage: StorageAPI }).storage = buildExtensionStorageAPI(sendRequest)
|
|
970
827
|
}
|
|
971
828
|
|
|
972
829
|
// Add secrets API if permitted
|
|
973
830
|
if (hasPermission('secrets.manage')) {
|
|
974
|
-
;(context as { secrets: SecretsAPI }).secrets = buildExtensionSecretsAPI()
|
|
831
|
+
;(context as { secrets: SecretsAPI }).secrets = buildExtensionSecretsAPI(sendRequest)
|
|
975
832
|
}
|
|
976
833
|
|
|
977
834
|
// Add background workers API if permitted
|
|
@@ -1024,10 +881,10 @@ function buildContext(
|
|
|
1024
881
|
error: (message, data) =>
|
|
1025
882
|
postMessage({ type: 'log', payload: { level: 'error', message: `[${taskId}] ${message}`, data } }),
|
|
1026
883
|
}),
|
|
1027
|
-
createStorageAPI: () => buildExtensionStorageAPI(),
|
|
1028
|
-
createUserStorageAPI: (userId) => buildUserStorageAPI(userId),
|
|
1029
|
-
createSecretsAPI: () => buildExtensionSecretsAPI(),
|
|
1030
|
-
createUserSecretsAPI: (userId) => buildUserSecretsAPI(userId),
|
|
884
|
+
createStorageAPI: () => buildExtensionStorageAPI(sendRequest),
|
|
885
|
+
createUserStorageAPI: (userId) => buildUserStorageAPI(sendRequest, userId),
|
|
886
|
+
createSecretsAPI: () => buildExtensionSecretsAPI(sendRequest),
|
|
887
|
+
createUserSecretsAPI: (userId) => buildUserSecretsAPI(sendRequest, userId),
|
|
1031
888
|
})
|
|
1032
889
|
}
|
|
1033
890
|
|