@modelprofile.com/flexharness 1.0.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.
@@ -0,0 +1,26 @@
1
+ import type { IFlexHarnessSnapshot, IFlexHarnessStore } from './interfaces.js';
2
+ export declare class InMemoryFlexHarnessStore implements IFlexHarnessStore {
3
+ private readonly snapshots;
4
+ load(storageKey: string): Promise<IFlexHarnessSnapshot | undefined>;
5
+ save(storageKey: string, snapshot: IFlexHarnessSnapshot, expectedRevision: number): Promise<void>;
6
+ }
7
+ export interface IJsonFileFlexHarnessStoreOptions {
8
+ directory: string;
9
+ }
10
+ /**
11
+ * Atomic and CAS-safe across instances in this process. It intentionally does not
12
+ * claim cross-process safety because no operating-system lock is held.
13
+ */
14
+ export declare class JsonFileFlexHarnessStore implements IFlexHarnessStore {
15
+ private static readonly fileQueues;
16
+ private readonly directory;
17
+ constructor(options: IJsonFileFlexHarnessStoreOptions);
18
+ load(storageKey: string): Promise<IFlexHarnessSnapshot | undefined>;
19
+ save(storageKey: string, snapshot: IFlexHarnessSnapshot, expectedRevision: number): Promise<void>;
20
+ private static inFileQueue;
21
+ private filePath;
22
+ private preparePath;
23
+ private cleanupTemps;
24
+ private readSnapshot;
25
+ private writeSnapshot;
26
+ }
@@ -0,0 +1,156 @@
1
+ import * as plugins from './plugins.js';
2
+ import { FlexHarnessStoreConflictError, FlexHarnessStoreFormatError, FlexHarnessValidationError, } from './errors.js';
3
+ import { assertFlexHarnessSnapshot, cloneSerializable } from './utils.json.js';
4
+ function validateSave(snapshot, expectedRevision) {
5
+ assertFlexHarnessSnapshot(snapshot);
6
+ if (!Number.isSafeInteger(expectedRevision) || expectedRevision < 0) {
7
+ throw new FlexHarnessValidationError('expectedRevision must be a non-negative integer.');
8
+ }
9
+ if (snapshot.revision !== expectedRevision + 1) {
10
+ throw new FlexHarnessStoreFormatError(`Snapshot revision ${snapshot.revision} must equal expected revision ${expectedRevision} plus one.`);
11
+ }
12
+ return cloneSerializable(snapshot);
13
+ }
14
+ export class InMemoryFlexHarnessStore {
15
+ snapshots = new Map();
16
+ async load(storageKey) {
17
+ const snapshot = this.snapshots.get(storageKey);
18
+ return snapshot ? cloneSerializable(snapshot) : undefined;
19
+ }
20
+ async save(storageKey, snapshot, expectedRevision) {
21
+ const validated = validateSave(snapshot, expectedRevision);
22
+ const actualRevision = this.snapshots.get(storageKey)?.revision ?? 0;
23
+ if (actualRevision !== expectedRevision) {
24
+ throw new FlexHarnessStoreConflictError(storageKey, expectedRevision, actualRevision);
25
+ }
26
+ this.snapshots.set(storageKey, validated);
27
+ }
28
+ }
29
+ /**
30
+ * Atomic and CAS-safe across instances in this process. It intentionally does not
31
+ * claim cross-process safety because no operating-system lock is held.
32
+ */
33
+ export class JsonFileFlexHarnessStore {
34
+ static fileQueues = new Map();
35
+ directory;
36
+ constructor(options) {
37
+ if (!options.directory) {
38
+ throw new FlexHarnessValidationError('JsonFileFlexHarnessStore requires a directory.');
39
+ }
40
+ this.directory = plugins.path.resolve(options.directory);
41
+ }
42
+ async load(storageKey) {
43
+ const filePath = this.filePath(storageKey);
44
+ return JsonFileFlexHarnessStore.inFileQueue(filePath, async () => {
45
+ await this.preparePath(filePath);
46
+ return this.readSnapshot(filePath);
47
+ });
48
+ }
49
+ async save(storageKey, snapshot, expectedRevision) {
50
+ const validated = validateSave(snapshot, expectedRevision);
51
+ const filePath = this.filePath(storageKey);
52
+ await JsonFileFlexHarnessStore.inFileQueue(filePath, async () => {
53
+ await this.preparePath(filePath);
54
+ const current = await this.readSnapshot(filePath);
55
+ const actualRevision = current?.revision ?? 0;
56
+ if (actualRevision !== expectedRevision) {
57
+ throw new FlexHarnessStoreConflictError(storageKey, expectedRevision, actualRevision);
58
+ }
59
+ await this.writeSnapshot(filePath, validated);
60
+ });
61
+ }
62
+ static inFileQueue(filePath, operation) {
63
+ const previous = JsonFileFlexHarnessStore.fileQueues.get(filePath) ?? Promise.resolve();
64
+ const result = previous.catch(() => undefined).then(operation);
65
+ const barrier = result.then(() => undefined, () => undefined);
66
+ JsonFileFlexHarnessStore.fileQueues.set(filePath, barrier);
67
+ void barrier.then(() => {
68
+ if (JsonFileFlexHarnessStore.fileQueues.get(filePath) === barrier) {
69
+ JsonFileFlexHarnessStore.fileQueues.delete(filePath);
70
+ }
71
+ });
72
+ return result;
73
+ }
74
+ filePath(storageKey) {
75
+ const digest = plugins.crypto.createHash('sha256').update(storageKey).digest('hex');
76
+ return plugins.path.join(this.directory, `${digest}.json`);
77
+ }
78
+ async preparePath(filePath) {
79
+ await plugins.fs.mkdir(this.directory, { recursive: true, mode: 0o700 });
80
+ await plugins.fs.chmod(this.directory, 0o700);
81
+ await this.cleanupTemps(filePath);
82
+ }
83
+ async cleanupTemps(filePath) {
84
+ const prefix = `${plugins.path.basename(filePath)}.`;
85
+ const entries = await plugins.fs.readdir(this.directory, { withFileTypes: true });
86
+ await Promise.all(entries
87
+ .filter((entry) => entry.isFile() && entry.name.startsWith(prefix) && entry.name.endsWith('.tmp'))
88
+ .map(async (entry) => {
89
+ try {
90
+ await plugins.fs.unlink(plugins.path.join(this.directory, entry.name));
91
+ }
92
+ catch (error) {
93
+ if (error.code !== 'ENOENT') {
94
+ throw error;
95
+ }
96
+ }
97
+ }));
98
+ }
99
+ async readSnapshot(filePath) {
100
+ let serialized;
101
+ try {
102
+ await plugins.fs.chmod(filePath, 0o600);
103
+ serialized = await plugins.fs.readFile(filePath, 'utf8');
104
+ }
105
+ catch (error) {
106
+ if (error.code === 'ENOENT') {
107
+ return undefined;
108
+ }
109
+ throw error;
110
+ }
111
+ let parsed;
112
+ try {
113
+ parsed = JSON.parse(serialized);
114
+ }
115
+ catch (error) {
116
+ throw new FlexHarnessStoreFormatError(`Malformed JSON snapshot at ${filePath}.`, {
117
+ cause: error,
118
+ });
119
+ }
120
+ try {
121
+ assertFlexHarnessSnapshot(parsed);
122
+ }
123
+ catch (error) {
124
+ if (error instanceof FlexHarnessStoreFormatError) {
125
+ throw new FlexHarnessStoreFormatError(`Invalid snapshot at ${filePath}: ${error.message}`, {
126
+ cause: error,
127
+ });
128
+ }
129
+ throw error;
130
+ }
131
+ return cloneSerializable(parsed);
132
+ }
133
+ async writeSnapshot(filePath, snapshot) {
134
+ const tempPath = `${filePath}.${process.pid}.${plugins.crypto.randomUUID()}.tmp`;
135
+ let fileHandle;
136
+ try {
137
+ fileHandle = await plugins.fs.open(tempPath, 'wx', 0o600);
138
+ await fileHandle.writeFile(`${JSON.stringify(snapshot, null, 2)}\n`, 'utf8');
139
+ await fileHandle.sync();
140
+ await fileHandle.close();
141
+ fileHandle = undefined;
142
+ await plugins.fs.chmod(tempPath, 0o600);
143
+ await plugins.fs.rename(tempPath, filePath);
144
+ await plugins.fs.chmod(filePath, 0o600);
145
+ }
146
+ finally {
147
+ await fileHandle?.close().catch(() => undefined);
148
+ await plugins.fs.unlink(tempPath).catch((error) => {
149
+ if (error.code !== 'ENOENT') {
150
+ throw error;
151
+ }
152
+ });
153
+ }
154
+ }
155
+ }
156
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdG9yZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnN0b3Jlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsNkJBQTZCLEVBQzdCLDJCQUEyQixFQUMzQiwwQkFBMEIsR0FDM0IsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUFFLHlCQUF5QixFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFL0UsU0FBUyxZQUFZLENBQ25CLFFBQThCLEVBQzlCLGdCQUF3QjtJQUV4Qix5QkFBeUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLGdCQUFnQixHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3BFLE1BQU0sSUFBSSwwQkFBMEIsQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFDRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssZ0JBQWdCLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLDJCQUEyQixDQUNuQyxxQkFBcUIsUUFBUSxDQUFDLFFBQVEsaUNBQWlDLGdCQUFnQixZQUFZLENBQ3BHLENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNyQyxDQUFDO0FBRUQsTUFBTSxPQUFPLHdCQUF3QjtJQUNsQixTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7SUFFOUQsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFrQjtRQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNoRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUMs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
@@ -0,0 +1,44 @@
1
+ import type { IFlexErrorInfo } from './interfaces.js';
2
+ export declare class FlexHarnessError extends Error {
3
+ readonly code: string;
4
+ constructor(code: string, message: string, options?: ErrorOptions);
5
+ }
6
+ export declare class FlexHarnessValidationError extends FlexHarnessError {
7
+ constructor(message: string, options?: ErrorOptions);
8
+ }
9
+ export declare class FlexHarnessClosedError extends FlexHarnessError {
10
+ constructor();
11
+ }
12
+ export declare class FlexHarnessNotFoundError extends FlexHarnessError {
13
+ constructor(resource: string, id: string);
14
+ }
15
+ export declare class FlexHarnessSessionBusyError extends FlexHarnessError {
16
+ constructor(sessionId: string, reason?: string);
17
+ }
18
+ export declare class FlexHarnessAbortError extends FlexHarnessError {
19
+ constructor(message?: string, options?: ErrorOptions);
20
+ }
21
+ export declare class FlexHarnessCallbackOverflowError extends FlexHarnessError {
22
+ constructor(message: string);
23
+ }
24
+ export declare class FlexHarnessPermissionRejectedError extends FlexHarnessError {
25
+ constructor(permissionId: string, options?: ErrorOptions);
26
+ }
27
+ export declare class FlexHarnessPermissionStateError extends FlexHarnessError {
28
+ constructor(message: string);
29
+ }
30
+ export declare class FlexHarnessStoreConflictError extends FlexHarnessError {
31
+ readonly storageKey: string;
32
+ readonly expectedRevision: number;
33
+ readonly actualRevision: number;
34
+ constructor(storageKey: string, expectedRevision: number, actualRevision: number);
35
+ }
36
+ export declare class FlexHarnessStoreFormatError extends FlexHarnessError {
37
+ constructor(message: string, options?: ErrorOptions);
38
+ }
39
+ export declare class FlexHarnessRunError extends AggregateError {
40
+ readonly code = "FLEX_RUN_FAILED";
41
+ constructor(errors: unknown[]);
42
+ }
43
+ export declare function errorToInfo(error: unknown): IFlexErrorInfo;
44
+ export declare function errorMessage(error: unknown): string;
@@ -0,0 +1,105 @@
1
+ export class FlexHarnessError extends Error {
2
+ code;
3
+ constructor(code, message, options) {
4
+ super(message, options);
5
+ this.name = 'FlexHarnessError';
6
+ this.code = code;
7
+ }
8
+ }
9
+ export class FlexHarnessValidationError extends FlexHarnessError {
10
+ constructor(message, options) {
11
+ super('FLEX_VALIDATION', message, options);
12
+ this.name = 'FlexHarnessValidationError';
13
+ }
14
+ }
15
+ export class FlexHarnessClosedError extends FlexHarnessError {
16
+ constructor() {
17
+ super('FLEX_CLOSED', 'FlexHarness is disposed.');
18
+ this.name = 'FlexHarnessClosedError';
19
+ }
20
+ }
21
+ export class FlexHarnessNotFoundError extends FlexHarnessError {
22
+ constructor(resource, id) {
23
+ super('FLEX_NOT_FOUND', `${resource} "${id}" was not found.`);
24
+ this.name = 'FlexHarnessNotFoundError';
25
+ }
26
+ }
27
+ export class FlexHarnessSessionBusyError extends FlexHarnessError {
28
+ constructor(sessionId, reason = 'already has an active run') {
29
+ super('FLEX_SESSION_BUSY', `Session "${sessionId}" ${reason}.`);
30
+ this.name = 'FlexHarnessSessionBusyError';
31
+ }
32
+ }
33
+ export class FlexHarnessAbortError extends FlexHarnessError {
34
+ constructor(message = 'The run was aborted.', options) {
35
+ super('FLEX_ABORTED', message, options);
36
+ this.name = 'FlexHarnessAbortError';
37
+ }
38
+ }
39
+ export class FlexHarnessCallbackOverflowError extends FlexHarnessError {
40
+ constructor(message) {
41
+ super('FLEX_CALLBACK_OVERFLOW', message);
42
+ this.name = 'FlexHarnessCallbackOverflowError';
43
+ }
44
+ }
45
+ export class FlexHarnessPermissionRejectedError extends FlexHarnessError {
46
+ constructor(permissionId, options) {
47
+ super('FLEX_PERMISSION_REJECTED', `Permission "${permissionId}" was rejected.`, options);
48
+ this.name = 'FlexHarnessPermissionRejectedError';
49
+ }
50
+ }
51
+ export class FlexHarnessPermissionStateError extends FlexHarnessError {
52
+ constructor(message) {
53
+ super('FLEX_PERMISSION_STATE', message);
54
+ this.name = 'FlexHarnessPermissionStateError';
55
+ }
56
+ }
57
+ export class FlexHarnessStoreConflictError extends FlexHarnessError {
58
+ storageKey;
59
+ expectedRevision;
60
+ actualRevision;
61
+ constructor(storageKey, expectedRevision, actualRevision) {
62
+ super('FLEX_STORE_CONFLICT', `Snapshot conflict for storage key "${storageKey}": expected revision ${expectedRevision}, found ${actualRevision}.`);
63
+ this.name = 'FlexHarnessStoreConflictError';
64
+ this.storageKey = storageKey;
65
+ this.expectedRevision = expectedRevision;
66
+ this.actualRevision = actualRevision;
67
+ }
68
+ }
69
+ export class FlexHarnessStoreFormatError extends FlexHarnessError {
70
+ constructor(message, options) {
71
+ super('FLEX_STORE_FORMAT', message, options);
72
+ this.name = 'FlexHarnessStoreFormatError';
73
+ }
74
+ }
75
+ export class FlexHarnessRunError extends AggregateError {
76
+ code = 'FLEX_RUN_FAILED';
77
+ constructor(errors) {
78
+ super(errors, 'Multiple FlexHarness run or cleanup operations failed.');
79
+ this.name = 'FlexHarnessRunError';
80
+ }
81
+ }
82
+ export function errorToInfo(error) {
83
+ if (error instanceof FlexHarnessError) {
84
+ return {
85
+ name: error.name,
86
+ message: error.message,
87
+ code: error.code,
88
+ };
89
+ }
90
+ if (error instanceof Error) {
91
+ return {
92
+ name: error.name,
93
+ message: error.message,
94
+ ...('code' in error && typeof error.code === 'string' ? { code: error.code } : {}),
95
+ };
96
+ }
97
+ return {
98
+ name: 'Error',
99
+ message: String(error),
100
+ };
101
+ }
102
+ export function errorMessage(error) {
103
+ return error instanceof Error ? error.message : String(error);
104
+ }
105
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZXJyb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxLQUFLO0lBQ3pCLElBQUksQ0FBUztJQUU3QixZQUFZLElBQVksRUFBRSxPQUFlLEVBQUUsT0FBc0I7UUFDL0QsS0FBSyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN4QixJQUFJLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDO1FBQy9CLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ25CLENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTywwQkFBMkIsU0FBUSxnQkFBZ0I7SUFDOUQsWUFBWSxPQUFlLEVBQUUsT0FBc0I7UUFDakQsS0FBSyxDQUFDLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsSUFBSSxHQUFHLDRCQUE0QixDQUFDO0lBQzNDLENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxnQkFBZ0I7SUFDMUQ7UUFDRSxLQUFLLENBQUMsYUFBYSxFQUFFLDBCQUEwQixDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLElBQUksR0FBRyx3QkFBd0IsQ0FBQztJQUN2QyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLE9BQU8sd0JBQXlCLFNBQVEsZ0JBQWdCO0lBQzVELFlBQVksUUFBZ0IsRUFBRSxFQUFVO1FBQ3RDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLFFBQVEsS0FBSyxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLElBQUksR0FBRywwQkFBMEIsQ0FBQztJQUN6QyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLE9BQU8sMkJBQTRCLFNBQVEsZ0JBQWdCO0lBQy9ELFlBQVksU0FBaUIsRUFBRSxNQUFNLEdBQUcsMkJBQTJCO1FBQ2pFLEtBQUssQ0FBQyxtQkFBbUIsRUFB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
@@ -0,0 +1,5 @@
1
+ export * from './classes.flexharness.js';
2
+ export * from './classes.stores.js';
3
+ export * from './errors.js';
4
+ export * from './interfaces.js';
5
+ export { normalizeJsonValue } from './utils.json.js';
@@ -0,0 +1,6 @@
1
+ export * from './classes.flexharness.js';
2
+ export * from './classes.stores.js';
3
+ export * from './errors.js';
4
+ export * from './interfaces.js';
5
+ export { normalizeJsonValue } from './utils.json.js';
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQyJ9
@@ -0,0 +1,288 @@
1
+ import type * as plugins from './plugins.js';
2
+ export type TJsonPrimitive = string | number | boolean | null;
3
+ export interface IJsonObject {
4
+ [key: string]: TJsonValue;
5
+ }
6
+ export type TJsonValue = TJsonPrimitive | IJsonObject | TJsonValue[];
7
+ export type TFlexAgentRunOptions = plugins.IAgentRunOptions;
8
+ export type TFlexAgentRunResult = plugins.IAgentRunResult;
9
+ export type TFlexAgentRunner = (options: TFlexAgentRunOptions) => Promise<TFlexAgentRunResult>;
10
+ export type TFlexAgentModel = TFlexAgentRunOptions['model'];
11
+ export type TFlexAgentPrompt = TFlexAgentRunOptions['prompt'];
12
+ export type TFlexAgentModelMessage = NonNullable<TFlexAgentRunOptions['messages']>[number];
13
+ export type TFlexAgentToolSet = NonNullable<TFlexAgentRunOptions['tools']>;
14
+ export type TFlexAgentProviderOptions = TFlexAgentRunOptions['providerOptions'];
15
+ export type TFlexAgentCacheSetting = TFlexAgentRunOptions['cache'];
16
+ export type TFlexAgentToolCallFinishEvent = Parameters<NonNullable<TFlexAgentRunOptions['onToolCallFinish']>>[0];
17
+ export interface IFlexTextPromptPart {
18
+ type: 'text';
19
+ text: string;
20
+ }
21
+ export interface IFlexImagePromptPart {
22
+ type: 'image';
23
+ data: string;
24
+ mediaType?: string;
25
+ name?: string;
26
+ }
27
+ export interface IFlexFilePromptPart {
28
+ type: 'file';
29
+ data: string;
30
+ mediaType: string;
31
+ name?: string;
32
+ }
33
+ export type TFlexPromptPart = IFlexTextPromptPart | IFlexImagePromptPart | IFlexFilePromptPart;
34
+ export type TFlexPrompt = string | TFlexPromptPart[];
35
+ export interface IFlexUsage {
36
+ inputTokens: number;
37
+ outputTokens: number;
38
+ totalTokens: number;
39
+ cacheReadTokens: number;
40
+ cacheWriteTokens: number;
41
+ }
42
+ export interface IFlexModelIdentity {
43
+ provider: string;
44
+ model: string;
45
+ displayName?: string;
46
+ }
47
+ export type TFlexActivityStatus = 'idle' | 'running' | 'waiting_permission' | 'failed' | 'cancelled';
48
+ export type TFlexMessageStatus = 'streaming' | 'completed' | 'failed' | 'cancelled';
49
+ export type TFlexToolPartStatus = 'running' | 'completed' | 'failed' | 'cancelled';
50
+ export type TFlexAttachmentSource = 'inline-base64' | 'data-url' | 'remote-url';
51
+ export interface IFlexTextMessagePart {
52
+ partId: string;
53
+ type: 'text';
54
+ text: string;
55
+ }
56
+ export interface IFlexReasoningMessagePart {
57
+ partId: string;
58
+ type: 'reasoning';
59
+ text: string;
60
+ status: 'running' | 'completed' | 'cancelled';
61
+ }
62
+ export interface IFlexToolMessagePart {
63
+ partId: string;
64
+ type: 'tool';
65
+ toolCallId: string;
66
+ toolName: string;
67
+ status: TFlexToolPartStatus;
68
+ input: TJsonValue;
69
+ output?: TJsonValue;
70
+ error?: string;
71
+ }
72
+ export interface IFlexAttachmentMessagePart {
73
+ partId: string;
74
+ type: 'attachment';
75
+ attachmentType: 'image' | 'file';
76
+ source: TFlexAttachmentSource;
77
+ sizeBytes?: number;
78
+ mediaType?: string;
79
+ name?: string;
80
+ }
81
+ export type TFlexMessagePart = IFlexTextMessagePart | IFlexReasoningMessagePart | IFlexToolMessagePart | IFlexAttachmentMessagePart;
82
+ export interface IFlexMessage {
83
+ messageId: string;
84
+ sessionId: string;
85
+ runId: string;
86
+ role: 'user' | 'assistant';
87
+ status: TFlexMessageStatus;
88
+ createdAt: string;
89
+ completedAt?: string;
90
+ parts: TFlexMessagePart[];
91
+ model?: IFlexModelIdentity;
92
+ usage?: IFlexUsage;
93
+ error?: string;
94
+ }
95
+ export interface IFlexSessionActivity {
96
+ runId?: string;
97
+ status: TFlexActivityStatus;
98
+ startedAt?: string;
99
+ completedAt?: string;
100
+ error?: string;
101
+ }
102
+ export interface IFlexSession {
103
+ scopeId: string;
104
+ sessionId: string;
105
+ title?: string;
106
+ createdAt: string;
107
+ updatedAt: string;
108
+ archivedAt?: string;
109
+ status: TFlexActivityStatus;
110
+ activity: IFlexSessionActivity;
111
+ }
112
+ export interface IFlexCreateSessionOptions {
113
+ sessionId?: string;
114
+ title?: string;
115
+ }
116
+ export interface IFlexUpdateSessionOptions {
117
+ title?: string | null;
118
+ archived?: boolean;
119
+ }
120
+ export interface IFlexPromptOptions {
121
+ modelHint?: string;
122
+ system?: string;
123
+ maxSteps?: number;
124
+ }
125
+ export interface IFlexPromptResult {
126
+ runId: string;
127
+ sessionId: string;
128
+ userMessage: IFlexMessage;
129
+ assistantMessage: IFlexMessage;
130
+ model: IFlexModelIdentity;
131
+ usage: IFlexUsage;
132
+ finishReason: string;
133
+ steps: number;
134
+ }
135
+ export interface IFlexResolvedScope<TScope> {
136
+ storageKey: string;
137
+ scope: TScope;
138
+ }
139
+ export interface IFlexScopeResolver<TScope> {
140
+ resolveScope(scopeId: string): Promise<IFlexResolvedScope<TScope>> | IFlexResolvedScope<TScope>;
141
+ }
142
+ export interface IFlexModelResolverContext<TScope> {
143
+ scopeId: string;
144
+ scope: TScope;
145
+ sessionId: string;
146
+ runId: string;
147
+ modelHint?: string;
148
+ signal: AbortSignal;
149
+ }
150
+ export interface IFlexResolvedModel {
151
+ model: TFlexAgentModel;
152
+ identity: IFlexModelIdentity;
153
+ system?: string;
154
+ providerOptions?: TFlexAgentProviderOptions;
155
+ cache?: TFlexAgentCacheSetting;
156
+ maxSteps?: number;
157
+ }
158
+ export interface IFlexModelResolver<TScope> {
159
+ resolveModel(context: IFlexModelResolverContext<TScope>): Promise<IFlexResolvedModel> | IFlexResolvedModel;
160
+ }
161
+ export interface IFlexPermissionRequestInput {
162
+ kind: string;
163
+ description: string;
164
+ toolCallId?: string;
165
+ rememberKey?: string;
166
+ metadata?: TJsonValue;
167
+ }
168
+ export interface IFlexPermissionRequest extends IFlexPermissionRequestInput {
169
+ permissionId: string;
170
+ scopeId: string;
171
+ sessionId: string;
172
+ runId: string;
173
+ createdAt: string;
174
+ }
175
+ export type TFlexPermissionDecision = 'once' | 'always' | 'reject';
176
+ export interface IFlexToolProviderContext<TScope> {
177
+ scopeId: string;
178
+ scope: TScope;
179
+ sessionId: string;
180
+ runId: string;
181
+ signal: AbortSignal;
182
+ requestPermission(request: IFlexPermissionRequestInput): Promise<void>;
183
+ }
184
+ export interface IFlexToolHandle {
185
+ tools: TFlexAgentToolSet;
186
+ close?(): Promise<void> | void;
187
+ }
188
+ export interface IFlexToolProvider<TScope> {
189
+ provideTools(context: IFlexToolProviderContext<TScope>): Promise<IFlexToolHandle | undefined> | IFlexToolHandle | undefined;
190
+ }
191
+ export interface IFlexStoredSessionSnapshot {
192
+ session: IFlexSession;
193
+ messages: IFlexMessage[];
194
+ modelHistory: TJsonValue[];
195
+ rememberedPermissionKeys: string[];
196
+ }
197
+ export interface IFlexHarnessSnapshot {
198
+ schemaVersion: 1;
199
+ revision: number;
200
+ sessions: IFlexStoredSessionSnapshot[];
201
+ }
202
+ export interface IFlexHarnessStore {
203
+ load(storageKey: string): Promise<IFlexHarnessSnapshot | undefined>;
204
+ save(storageKey: string, snapshot: IFlexHarnessSnapshot, expectedRevision: number): Promise<void>;
205
+ }
206
+ export interface IFlexJsonLimits {
207
+ maxDepth?: number;
208
+ maxBytes?: number;
209
+ }
210
+ export interface IFlexCallbackLimits {
211
+ maxEvents?: number;
212
+ maxOutputBytes?: number;
213
+ maxParts?: number;
214
+ }
215
+ export interface IFlexHarnessOptions<TScope> {
216
+ scopeResolver: IFlexScopeResolver<TScope>;
217
+ modelResolver: IFlexModelResolver<TScope>;
218
+ toolProvider?: IFlexToolProvider<TScope>;
219
+ store?: IFlexHarnessStore;
220
+ runner?: TFlexAgentRunner;
221
+ toolOutputLimits?: IFlexJsonLimits;
222
+ callbackLimits?: IFlexCallbackLimits;
223
+ }
224
+ export interface IFlexEventBase {
225
+ readonly eventId: string;
226
+ readonly sequence: number;
227
+ readonly timestamp: string;
228
+ readonly scopeId: string;
229
+ readonly sessionId: string;
230
+ }
231
+ export interface IFlexSessionCreatedEvent extends IFlexEventBase {
232
+ readonly type: 'session.created';
233
+ readonly session: IFlexSession;
234
+ }
235
+ export interface IFlexSessionUpdatedEvent extends IFlexEventBase {
236
+ readonly type: 'session.updated';
237
+ readonly session: IFlexSession;
238
+ }
239
+ export interface IFlexSessionDeletedEvent extends IFlexEventBase {
240
+ readonly type: 'session.deleted';
241
+ readonly session: IFlexSession;
242
+ }
243
+ export interface IFlexRunStartedEvent extends IFlexEventBase {
244
+ readonly type: 'run.started';
245
+ readonly runId: string;
246
+ readonly messageId: string;
247
+ readonly session: IFlexSession;
248
+ }
249
+ export interface IFlexMessageChangedEvent extends IFlexEventBase {
250
+ readonly type: 'message.created' | 'message.updated';
251
+ readonly runId: string;
252
+ readonly messageId: string;
253
+ readonly message: IFlexMessage;
254
+ }
255
+ export interface IFlexPartChangedEvent extends IFlexEventBase {
256
+ readonly type: 'part.started' | 'part.delta' | 'part.completed';
257
+ readonly runId: string;
258
+ readonly messageId: string;
259
+ readonly partId: string;
260
+ readonly part: TFlexMessagePart;
261
+ readonly delta?: string;
262
+ }
263
+ export interface IFlexPermissionRequestedEvent extends IFlexEventBase {
264
+ readonly type: 'permission.requested';
265
+ readonly runId: string;
266
+ readonly request: IFlexPermissionRequest;
267
+ }
268
+ export interface IFlexPermissionResolvedEvent extends IFlexEventBase {
269
+ readonly type: 'permission.resolved';
270
+ readonly runId: string;
271
+ readonly request: IFlexPermissionRequest;
272
+ readonly decision: TFlexPermissionDecision;
273
+ }
274
+ export interface IFlexRunFinishedEvent extends IFlexEventBase {
275
+ readonly type: 'run.finished';
276
+ readonly runId: string;
277
+ readonly messageId: string;
278
+ readonly status: 'completed' | 'failed' | 'cancelled';
279
+ readonly message: IFlexMessage;
280
+ readonly error?: IFlexErrorInfo;
281
+ }
282
+ export interface IFlexErrorInfo {
283
+ name: string;
284
+ message: string;
285
+ code?: string;
286
+ }
287
+ export type TFlexHarnessEvent = IFlexSessionCreatedEvent | IFlexSessionUpdatedEvent | IFlexSessionDeletedEvent | IFlexRunStartedEvent | IFlexMessageChangedEvent | IFlexPartChangedEvent | IFlexPermissionRequestedEvent | IFlexPermissionResolvedEvent | IFlexRunFinishedEvent;
288
+ export type TFlexHarnessEventListener = (event: TFlexHarnessEvent) => void;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2ludGVyZmFjZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -0,0 +1,7 @@
1
+ import * as crypto from 'node:crypto';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ export { crypto, fs, path };
5
+ import { runAgent } from '@push.rocks/smartagent';
6
+ export { runAgent };
7
+ export type { IAgentRunOptions, IAgentRunResult, } from '@push.rocks/smartagent';
@@ -0,0 +1,9 @@
1
+ // node native scope
2
+ import * as crypto from 'node:crypto';
3
+ import * as fs from 'node:fs/promises';
4
+ import * as path from 'node:path';
5
+ export { crypto, fs, path };
6
+ // @push.rocks scope
7
+ import { runAgent } from '@push.rocks/smartagent';
8
+ export { runAgent };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFFbEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFFNUIsb0JBQW9CO0FBQ3BCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVsRCxPQUFPLEVBQUUsUUFBUSxFQUFFLENBQUMifQ==