@agentica/core 0.12.2-dev.20250314 → 0.12.2
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/LICENSE +21 -21
- package/README.md +461 -461
- package/package.json +1 -1
- package/prompts/cancel.md +4 -4
- package/prompts/common.md +2 -2
- package/prompts/describe.md +6 -6
- package/prompts/execute.md +6 -6
- package/prompts/initialize.md +2 -2
- package/prompts/select.md +6 -6
- package/src/Agentica.ts +359 -359
- package/src/chatgpt/ChatGptAgent.ts +76 -76
- package/src/chatgpt/ChatGptCallFunctionAgent.ts +466 -466
- package/src/chatgpt/ChatGptCancelFunctionAgent.ts +280 -280
- package/src/chatgpt/ChatGptCompletionMessageUtil.ts +166 -166
- package/src/chatgpt/ChatGptDescribeFunctionAgent.ts +122 -122
- package/src/chatgpt/ChatGptHistoryDecoder.ts +88 -88
- package/src/chatgpt/ChatGptInitializeFunctionAgent.ts +96 -96
- package/src/chatgpt/ChatGptSelectFunctionAgent.ts +311 -311
- package/src/chatgpt/ChatGptUsageAggregator.ts +62 -62
- package/src/context/AgenticaCancelPrompt.ts +32 -32
- package/src/context/AgenticaClassOperation.ts +23 -23
- package/src/context/AgenticaContext.ts +130 -130
- package/src/context/AgenticaHttpOperation.ts +27 -27
- package/src/context/AgenticaOperation.ts +66 -66
- package/src/context/AgenticaOperationBase.ts +57 -57
- package/src/context/AgenticaOperationCollection.ts +52 -52
- package/src/context/AgenticaOperationSelection.ts +27 -27
- package/src/context/AgenticaTokenUsage.ts +170 -170
- package/src/context/internal/AgenticaTokenUsageAggregator.ts +66 -66
- package/src/context/internal/__IChatCancelFunctionsApplication.ts +23 -23
- package/src/context/internal/__IChatFunctionReference.ts +21 -21
- package/src/context/internal/__IChatInitialApplication.ts +15 -15
- package/src/context/internal/__IChatSelectFunctionsApplication.ts +24 -24
- package/src/events/AgenticaCallEvent.ts +36 -36
- package/src/events/AgenticaCancelEvent.ts +28 -28
- package/src/events/AgenticaDescribeEvent.ts +66 -66
- package/src/events/AgenticaEvent.ts +36 -36
- package/src/events/AgenticaEventBase.ts +7 -7
- package/src/events/AgenticaEventSource.ts +6 -6
- package/src/events/AgenticaExecuteEvent.ts +50 -50
- package/src/events/AgenticaInitializeEvent.ts +14 -14
- package/src/events/AgenticaRequestEvent.ts +45 -45
- package/src/events/AgenticaResponseEvent.ts +48 -48
- package/src/events/AgenticaSelectEvent.ts +37 -37
- package/src/events/AgenticaTextEvent.ts +62 -62
- package/src/functional/assertHttpLlmApplication.ts +55 -55
- package/src/functional/validateHttpLlmApplication.ts +66 -66
- package/src/index.ts +44 -44
- package/src/internal/AgenticaConstant.ts +4 -4
- package/src/internal/AgenticaDefaultPrompt.ts +43 -43
- package/src/internal/AgenticaOperationComposer.ts +96 -96
- package/src/internal/ByteArrayUtil.ts +5 -5
- package/src/internal/MPSCUtil.ts +111 -111
- package/src/internal/MathUtil.ts +3 -3
- package/src/internal/Singleton.ts +22 -22
- package/src/internal/StreamUtil.ts +64 -64
- package/src/internal/__map_take.ts +15 -15
- package/src/json/IAgenticaEventJson.ts +178 -178
- package/src/json/IAgenticaOperationJson.ts +36 -36
- package/src/json/IAgenticaOperationSelectionJson.ts +19 -19
- package/src/json/IAgenticaPromptJson.ts +130 -130
- package/src/json/IAgenticaTokenUsageJson.ts +107 -107
- package/src/prompts/AgenticaCancelPrompt.ts +32 -32
- package/src/prompts/AgenticaDescribePrompt.ts +41 -41
- package/src/prompts/AgenticaExecutePrompt.ts +52 -52
- package/src/prompts/AgenticaPrompt.ts +14 -14
- package/src/prompts/AgenticaPromptBase.ts +27 -27
- package/src/prompts/AgenticaSelectPrompt.ts +32 -32
- package/src/prompts/AgenticaTextPrompt.ts +31 -31
- package/src/structures/IAgenticaConfig.ts +123 -123
- package/src/structures/IAgenticaController.ts +133 -133
- package/src/structures/IAgenticaExecutor.ts +157 -157
- package/src/structures/IAgenticaProps.ts +69 -69
- package/src/structures/IAgenticaSystemPrompt.ts +125 -125
- package/src/structures/IAgenticaVendor.ts +39 -39
- package/src/transformers/AgenticaEventTransformer.ts +165 -165
- package/src/transformers/AgenticaPromptTransformer.ts +134 -134
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { ILlmSchema } from "@samchon/openapi";
|
|
2
|
-
|
|
3
|
-
import { IAgenticaConfig } from "../structures/IAgenticaConfig";
|
|
4
|
-
import { AgenticaSystemPrompt } from "./AgenticaSystemPrompt";
|
|
5
|
-
import { Singleton } from "./Singleton";
|
|
6
|
-
|
|
7
|
-
export namespace AgenticaDefaultPrompt {
|
|
8
|
-
export const write = <Model extends ILlmSchema.Model>(
|
|
9
|
-
config?: IAgenticaConfig<Model>,
|
|
10
|
-
): string => {
|
|
11
|
-
if (config?.systemPrompt?.common)
|
|
12
|
-
return config?.systemPrompt?.common(config);
|
|
13
|
-
|
|
14
|
-
const locale: string = config?.locale ?? getLocale.get();
|
|
15
|
-
const timezone: string = config?.timezone ?? getTimezone.get();
|
|
16
|
-
|
|
17
|
-
return AgenticaSystemPrompt.COMMON.replace("${locale}", locale).replace(
|
|
18
|
-
"${timezone}",
|
|
19
|
-
timezone,
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const getLocale = new Singleton(() =>
|
|
25
|
-
isNode.get()
|
|
26
|
-
? (process.env.LANG?.split(".")[0] ?? "en-US")
|
|
27
|
-
: navigator.language,
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
const getTimezone = new Singleton(
|
|
31
|
-
() => Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const isNode = new Singleton(() => {
|
|
35
|
-
const isObject = (obj: any) => typeof obj === "object" && obj !== null;
|
|
36
|
-
return (
|
|
37
|
-
typeof global === "object" &&
|
|
38
|
-
isObject(global) &&
|
|
39
|
-
isObject(global.process) &&
|
|
40
|
-
isObject(global.process.versions) &&
|
|
41
|
-
typeof global.process.versions.node !== "undefined"
|
|
42
|
-
);
|
|
43
|
-
});
|
|
1
|
+
import { ILlmSchema } from "@samchon/openapi";
|
|
2
|
+
|
|
3
|
+
import { IAgenticaConfig } from "../structures/IAgenticaConfig";
|
|
4
|
+
import { AgenticaSystemPrompt } from "./AgenticaSystemPrompt";
|
|
5
|
+
import { Singleton } from "./Singleton";
|
|
6
|
+
|
|
7
|
+
export namespace AgenticaDefaultPrompt {
|
|
8
|
+
export const write = <Model extends ILlmSchema.Model>(
|
|
9
|
+
config?: IAgenticaConfig<Model>,
|
|
10
|
+
): string => {
|
|
11
|
+
if (config?.systemPrompt?.common)
|
|
12
|
+
return config?.systemPrompt?.common(config);
|
|
13
|
+
|
|
14
|
+
const locale: string = config?.locale ?? getLocale.get();
|
|
15
|
+
const timezone: string = config?.timezone ?? getTimezone.get();
|
|
16
|
+
|
|
17
|
+
return AgenticaSystemPrompt.COMMON.replace("${locale}", locale).replace(
|
|
18
|
+
"${timezone}",
|
|
19
|
+
timezone,
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const getLocale = new Singleton(() =>
|
|
25
|
+
isNode.get()
|
|
26
|
+
? (process.env.LANG?.split(".")[0] ?? "en-US")
|
|
27
|
+
: navigator.language,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const getTimezone = new Singleton(
|
|
31
|
+
() => Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const isNode = new Singleton(() => {
|
|
35
|
+
const isObject = (obj: any) => typeof obj === "object" && obj !== null;
|
|
36
|
+
return (
|
|
37
|
+
typeof global === "object" &&
|
|
38
|
+
isObject(global) &&
|
|
39
|
+
isObject(global.process) &&
|
|
40
|
+
isObject(global.process.versions) &&
|
|
41
|
+
typeof global.process.versions.node !== "undefined"
|
|
42
|
+
);
|
|
43
|
+
});
|
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
import { ILlmSchema } from "@samchon/openapi";
|
|
2
|
-
|
|
3
|
-
import { AgenticaOperation } from "../context/AgenticaOperation";
|
|
4
|
-
import { AgenticaOperationCollection } from "../context/AgenticaOperationCollection";
|
|
5
|
-
import { IAgenticaConfig } from "../structures/IAgenticaConfig";
|
|
6
|
-
import { IAgenticaController } from "../structures/IAgenticaController";
|
|
7
|
-
import { __map_take } from "./__map_take";
|
|
8
|
-
|
|
9
|
-
export namespace AgenticaOperationComposer {
|
|
10
|
-
export const compose = <Model extends ILlmSchema.Model>(props: {
|
|
11
|
-
controllers: IAgenticaController<Model>[];
|
|
12
|
-
config?: IAgenticaConfig<Model> | undefined;
|
|
13
|
-
}): AgenticaOperationCollection<Model> => {
|
|
14
|
-
const unique: boolean =
|
|
15
|
-
props.controllers.length === 1 ||
|
|
16
|
-
(() => {
|
|
17
|
-
const names: string[] = props.controllers
|
|
18
|
-
.map((controller) =>
|
|
19
|
-
controller.application.functions.map((func) => func.name),
|
|
20
|
-
)
|
|
21
|
-
.flat();
|
|
22
|
-
return new Set(names).size === names.length;
|
|
23
|
-
})();
|
|
24
|
-
const naming = (func: string, ci: number) =>
|
|
25
|
-
unique ? func : `_${ci}_${func}`;
|
|
26
|
-
|
|
27
|
-
const array: AgenticaOperation<Model>[] = props.controllers
|
|
28
|
-
.map((controller, ci) =>
|
|
29
|
-
controller.protocol === "http"
|
|
30
|
-
? controller.application.functions.map(
|
|
31
|
-
(func) =>
|
|
32
|
-
({
|
|
33
|
-
protocol: "http",
|
|
34
|
-
controller: controller,
|
|
35
|
-
function: func,
|
|
36
|
-
name: naming(func.name, ci),
|
|
37
|
-
toJSON: () => ({
|
|
38
|
-
protocol: "http",
|
|
39
|
-
controller: controller.name,
|
|
40
|
-
function: func.name,
|
|
41
|
-
name: naming(func.name, ci),
|
|
42
|
-
}),
|
|
43
|
-
}) satisfies AgenticaOperation.Http<Model>,
|
|
44
|
-
)
|
|
45
|
-
: controller.application.functions.map(
|
|
46
|
-
(func) =>
|
|
47
|
-
({
|
|
48
|
-
protocol: "class",
|
|
49
|
-
controller,
|
|
50
|
-
function: func,
|
|
51
|
-
name: naming(func.name, ci),
|
|
52
|
-
toJSON: () => ({
|
|
53
|
-
protocol: "class",
|
|
54
|
-
controller: controller.name,
|
|
55
|
-
function: func.name,
|
|
56
|
-
name: naming(func.name, ci),
|
|
57
|
-
}),
|
|
58
|
-
}) satisfies AgenticaOperation.Class<Model>,
|
|
59
|
-
),
|
|
60
|
-
)
|
|
61
|
-
.flat();
|
|
62
|
-
const divided: AgenticaOperation<Model>[][] | undefined =
|
|
63
|
-
!!props.config?.capacity && array.length > props.config.capacity
|
|
64
|
-
? divideOperations({
|
|
65
|
-
array,
|
|
66
|
-
capacity: props.config.capacity,
|
|
67
|
-
})
|
|
68
|
-
: undefined;
|
|
69
|
-
|
|
70
|
-
const flat: Map<string, AgenticaOperation<Model>> = new Map();
|
|
71
|
-
const group: Map<string, Map<string, AgenticaOperation<Model>>> = new Map();
|
|
72
|
-
for (const item of array) {
|
|
73
|
-
flat.set(item.name, item);
|
|
74
|
-
__map_take(group, item.controller.name, () => new Map()).set(
|
|
75
|
-
item.name,
|
|
76
|
-
item,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
array,
|
|
81
|
-
divided,
|
|
82
|
-
flat,
|
|
83
|
-
group,
|
|
84
|
-
};
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const divideOperations = <Model extends ILlmSchema.Model>(props: {
|
|
88
|
-
array: AgenticaOperation<Model>[];
|
|
89
|
-
capacity: number;
|
|
90
|
-
}): AgenticaOperation<Model>[][] => {
|
|
91
|
-
const size: number = Math.ceil(props.array.length / props.capacity);
|
|
92
|
-
const capacity: number = Math.ceil(props.array.length / size);
|
|
93
|
-
const replica: AgenticaOperation<Model>[] = props.array.slice();
|
|
94
|
-
return new Array(size).fill(0).map(() => replica.splice(0, capacity));
|
|
95
|
-
};
|
|
96
|
-
}
|
|
1
|
+
import { ILlmSchema } from "@samchon/openapi";
|
|
2
|
+
|
|
3
|
+
import { AgenticaOperation } from "../context/AgenticaOperation";
|
|
4
|
+
import { AgenticaOperationCollection } from "../context/AgenticaOperationCollection";
|
|
5
|
+
import { IAgenticaConfig } from "../structures/IAgenticaConfig";
|
|
6
|
+
import { IAgenticaController } from "../structures/IAgenticaController";
|
|
7
|
+
import { __map_take } from "./__map_take";
|
|
8
|
+
|
|
9
|
+
export namespace AgenticaOperationComposer {
|
|
10
|
+
export const compose = <Model extends ILlmSchema.Model>(props: {
|
|
11
|
+
controllers: IAgenticaController<Model>[];
|
|
12
|
+
config?: IAgenticaConfig<Model> | undefined;
|
|
13
|
+
}): AgenticaOperationCollection<Model> => {
|
|
14
|
+
const unique: boolean =
|
|
15
|
+
props.controllers.length === 1 ||
|
|
16
|
+
(() => {
|
|
17
|
+
const names: string[] = props.controllers
|
|
18
|
+
.map((controller) =>
|
|
19
|
+
controller.application.functions.map((func) => func.name),
|
|
20
|
+
)
|
|
21
|
+
.flat();
|
|
22
|
+
return new Set(names).size === names.length;
|
|
23
|
+
})();
|
|
24
|
+
const naming = (func: string, ci: number) =>
|
|
25
|
+
unique ? func : `_${ci}_${func}`;
|
|
26
|
+
|
|
27
|
+
const array: AgenticaOperation<Model>[] = props.controllers
|
|
28
|
+
.map((controller, ci) =>
|
|
29
|
+
controller.protocol === "http"
|
|
30
|
+
? controller.application.functions.map(
|
|
31
|
+
(func) =>
|
|
32
|
+
({
|
|
33
|
+
protocol: "http",
|
|
34
|
+
controller: controller,
|
|
35
|
+
function: func,
|
|
36
|
+
name: naming(func.name, ci),
|
|
37
|
+
toJSON: () => ({
|
|
38
|
+
protocol: "http",
|
|
39
|
+
controller: controller.name,
|
|
40
|
+
function: func.name,
|
|
41
|
+
name: naming(func.name, ci),
|
|
42
|
+
}),
|
|
43
|
+
}) satisfies AgenticaOperation.Http<Model>,
|
|
44
|
+
)
|
|
45
|
+
: controller.application.functions.map(
|
|
46
|
+
(func) =>
|
|
47
|
+
({
|
|
48
|
+
protocol: "class",
|
|
49
|
+
controller,
|
|
50
|
+
function: func,
|
|
51
|
+
name: naming(func.name, ci),
|
|
52
|
+
toJSON: () => ({
|
|
53
|
+
protocol: "class",
|
|
54
|
+
controller: controller.name,
|
|
55
|
+
function: func.name,
|
|
56
|
+
name: naming(func.name, ci),
|
|
57
|
+
}),
|
|
58
|
+
}) satisfies AgenticaOperation.Class<Model>,
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
.flat();
|
|
62
|
+
const divided: AgenticaOperation<Model>[][] | undefined =
|
|
63
|
+
!!props.config?.capacity && array.length > props.config.capacity
|
|
64
|
+
? divideOperations({
|
|
65
|
+
array,
|
|
66
|
+
capacity: props.config.capacity,
|
|
67
|
+
})
|
|
68
|
+
: undefined;
|
|
69
|
+
|
|
70
|
+
const flat: Map<string, AgenticaOperation<Model>> = new Map();
|
|
71
|
+
const group: Map<string, Map<string, AgenticaOperation<Model>>> = new Map();
|
|
72
|
+
for (const item of array) {
|
|
73
|
+
flat.set(item.name, item);
|
|
74
|
+
__map_take(group, item.controller.name, () => new Map()).set(
|
|
75
|
+
item.name,
|
|
76
|
+
item,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
array,
|
|
81
|
+
divided,
|
|
82
|
+
flat,
|
|
83
|
+
group,
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const divideOperations = <Model extends ILlmSchema.Model>(props: {
|
|
88
|
+
array: AgenticaOperation<Model>[];
|
|
89
|
+
capacity: number;
|
|
90
|
+
}): AgenticaOperation<Model>[][] => {
|
|
91
|
+
const size: number = Math.ceil(props.array.length / props.capacity);
|
|
92
|
+
const capacity: number = Math.ceil(props.array.length / size);
|
|
93
|
+
const replica: AgenticaOperation<Model>[] = props.array.slice();
|
|
94
|
+
return new Array(size).fill(0).map(() => replica.splice(0, capacity));
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export namespace ByteArrayUtil {
|
|
2
|
-
export const toUtf8 = (byteArray: Uint8Array): string => {
|
|
3
|
-
return new TextDecoder().decode(byteArray);
|
|
4
|
-
};
|
|
5
|
-
}
|
|
1
|
+
export namespace ByteArrayUtil {
|
|
2
|
+
export const toUtf8 = (byteArray: Uint8Array): string => {
|
|
3
|
+
return new TextDecoder().decode(byteArray);
|
|
4
|
+
};
|
|
5
|
+
}
|
package/src/internal/MPSCUtil.ts
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
export namespace MPSCUtil {
|
|
2
|
-
export interface Output<T> {
|
|
3
|
-
consumer: ReadableStream<T>;
|
|
4
|
-
produce: (chunk: T) => void;
|
|
5
|
-
close: () => void;
|
|
6
|
-
/**
|
|
7
|
-
* Wait until the producing is finished.
|
|
8
|
-
*/
|
|
9
|
-
waitClosed: () => Promise<void>;
|
|
10
|
-
/**
|
|
11
|
-
* Wait until the consuming is finished.(finished producing and consuming)
|
|
12
|
-
*/
|
|
13
|
-
waitUntilEmpty: () => Promise<void>;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Check if producing is done and consuming is finished.
|
|
17
|
-
*/
|
|
18
|
-
done: () => boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const create = <T>(): Output<T> => {
|
|
22
|
-
const queue = new AsyncQueue<T>();
|
|
23
|
-
const consumer = new ReadableStream<T>({
|
|
24
|
-
async pull(controller) {
|
|
25
|
-
const { value, done } = await queue.dequeue();
|
|
26
|
-
if (done) {
|
|
27
|
-
controller.close();
|
|
28
|
-
} else {
|
|
29
|
-
controller.enqueue(value);
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
consumer,
|
|
36
|
-
produce: (chunk: T) => queue.enqueue(chunk),
|
|
37
|
-
close: () => queue.close(),
|
|
38
|
-
done: () => queue.done(),
|
|
39
|
-
waitClosed: () => queue.waitClosed(),
|
|
40
|
-
waitUntilEmpty: () => queue.waitUntilEmpty(),
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export class AsyncQueue<T> {
|
|
45
|
-
private queue: T[] = [];
|
|
46
|
-
private resolvers: ((value: IteratorResult<T, undefined>) => void)[] = [];
|
|
47
|
-
private closeResolvers: (() => void)[] = [];
|
|
48
|
-
private emptyResolvers: (() => void)[] = [];
|
|
49
|
-
private closed = false;
|
|
50
|
-
|
|
51
|
-
enqueue(item: T) {
|
|
52
|
-
this.queue.push(item);
|
|
53
|
-
if (this.resolvers.length > 0) {
|
|
54
|
-
this.resolvers.shift()?.({ value: this.queue.shift()!, done: false });
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async dequeue(): Promise<IteratorResult<T, undefined>> {
|
|
59
|
-
if (this.queue.length > 0) {
|
|
60
|
-
return { value: this.queue.shift()!, done: false };
|
|
61
|
-
}
|
|
62
|
-
if (this.closed) {
|
|
63
|
-
if (this.emptyResolvers.length > 0) {
|
|
64
|
-
this.emptyResolvers.forEach((resolve) => resolve());
|
|
65
|
-
this.emptyResolvers = [];
|
|
66
|
-
}
|
|
67
|
-
return { value: undefined, done: true };
|
|
68
|
-
}
|
|
69
|
-
return new Promise((resolve) => this.resolvers.push(resolve));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
isEmpty() {
|
|
73
|
-
return this.queue.length === 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
isClosed() {
|
|
77
|
-
return this.closed;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
done() {
|
|
81
|
-
return this.isClosed() && this.isEmpty();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
close() {
|
|
85
|
-
this.closed = true;
|
|
86
|
-
while (this.resolvers.length > 0) {
|
|
87
|
-
this.resolvers.shift()?.({ value: undefined, done: true });
|
|
88
|
-
}
|
|
89
|
-
this.closeResolvers.forEach((resolve) => resolve());
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
waitUntilEmpty() {
|
|
93
|
-
if (this.isEmpty()) {
|
|
94
|
-
return Promise.resolve();
|
|
95
|
-
}
|
|
96
|
-
return new Promise<void>((resolve) => {
|
|
97
|
-
this.emptyResolvers.push(resolve);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
waitClosed() {
|
|
102
|
-
if (this.isClosed()) {
|
|
103
|
-
return Promise.resolve();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return new Promise<void>((resolve) => {
|
|
107
|
-
this.closeResolvers.push(resolve);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
1
|
+
export namespace MPSCUtil {
|
|
2
|
+
export interface Output<T> {
|
|
3
|
+
consumer: ReadableStream<T>;
|
|
4
|
+
produce: (chunk: T) => void;
|
|
5
|
+
close: () => void;
|
|
6
|
+
/**
|
|
7
|
+
* Wait until the producing is finished.
|
|
8
|
+
*/
|
|
9
|
+
waitClosed: () => Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Wait until the consuming is finished.(finished producing and consuming)
|
|
12
|
+
*/
|
|
13
|
+
waitUntilEmpty: () => Promise<void>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if producing is done and consuming is finished.
|
|
17
|
+
*/
|
|
18
|
+
done: () => boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const create = <T>(): Output<T> => {
|
|
22
|
+
const queue = new AsyncQueue<T>();
|
|
23
|
+
const consumer = new ReadableStream<T>({
|
|
24
|
+
async pull(controller) {
|
|
25
|
+
const { value, done } = await queue.dequeue();
|
|
26
|
+
if (done) {
|
|
27
|
+
controller.close();
|
|
28
|
+
} else {
|
|
29
|
+
controller.enqueue(value);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
consumer,
|
|
36
|
+
produce: (chunk: T) => queue.enqueue(chunk),
|
|
37
|
+
close: () => queue.close(),
|
|
38
|
+
done: () => queue.done(),
|
|
39
|
+
waitClosed: () => queue.waitClosed(),
|
|
40
|
+
waitUntilEmpty: () => queue.waitUntilEmpty(),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export class AsyncQueue<T> {
|
|
45
|
+
private queue: T[] = [];
|
|
46
|
+
private resolvers: ((value: IteratorResult<T, undefined>) => void)[] = [];
|
|
47
|
+
private closeResolvers: (() => void)[] = [];
|
|
48
|
+
private emptyResolvers: (() => void)[] = [];
|
|
49
|
+
private closed = false;
|
|
50
|
+
|
|
51
|
+
enqueue(item: T) {
|
|
52
|
+
this.queue.push(item);
|
|
53
|
+
if (this.resolvers.length > 0) {
|
|
54
|
+
this.resolvers.shift()?.({ value: this.queue.shift()!, done: false });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async dequeue(): Promise<IteratorResult<T, undefined>> {
|
|
59
|
+
if (this.queue.length > 0) {
|
|
60
|
+
return { value: this.queue.shift()!, done: false };
|
|
61
|
+
}
|
|
62
|
+
if (this.closed) {
|
|
63
|
+
if (this.emptyResolvers.length > 0) {
|
|
64
|
+
this.emptyResolvers.forEach((resolve) => resolve());
|
|
65
|
+
this.emptyResolvers = [];
|
|
66
|
+
}
|
|
67
|
+
return { value: undefined, done: true };
|
|
68
|
+
}
|
|
69
|
+
return new Promise((resolve) => this.resolvers.push(resolve));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
isEmpty() {
|
|
73
|
+
return this.queue.length === 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
isClosed() {
|
|
77
|
+
return this.closed;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
done() {
|
|
81
|
+
return this.isClosed() && this.isEmpty();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
close() {
|
|
85
|
+
this.closed = true;
|
|
86
|
+
while (this.resolvers.length > 0) {
|
|
87
|
+
this.resolvers.shift()?.({ value: undefined, done: true });
|
|
88
|
+
}
|
|
89
|
+
this.closeResolvers.forEach((resolve) => resolve());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
waitUntilEmpty() {
|
|
93
|
+
if (this.isEmpty()) {
|
|
94
|
+
return Promise.resolve();
|
|
95
|
+
}
|
|
96
|
+
return new Promise<void>((resolve) => {
|
|
97
|
+
this.emptyResolvers.push(resolve);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
waitClosed() {
|
|
102
|
+
if (this.isClosed()) {
|
|
103
|
+
return Promise.resolve();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return new Promise<void>((resolve) => {
|
|
107
|
+
this.closeResolvers.push(resolve);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
package/src/internal/MathUtil.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export namespace MathUtil {
|
|
2
|
-
export const round = (value: number): number => Math.floor(value * 100) / 100;
|
|
3
|
-
}
|
|
1
|
+
export namespace MathUtil {
|
|
2
|
+
export const round = (value: number): number => Math.floor(value * 100) / 100;
|
|
3
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @internal
|
|
3
|
-
*/
|
|
4
|
-
export class Singleton<T, Args extends any[] = []> {
|
|
5
|
-
private readonly closure_: (...args: Args) => T;
|
|
6
|
-
private value_: T | object;
|
|
7
|
-
|
|
8
|
-
public constructor(closure: (...args: Args) => T) {
|
|
9
|
-
this.closure_ = closure;
|
|
10
|
-
this.value_ = NOT_MOUNTED_YET;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public get(...args: Args): T {
|
|
14
|
-
if (this.value_ === NOT_MOUNTED_YET) this.value_ = this.closure_(...args);
|
|
15
|
-
return this.value_ as T;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @internal
|
|
21
|
-
*/
|
|
22
|
-
const NOT_MOUNTED_YET = {};
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*/
|
|
4
|
+
export class Singleton<T, Args extends any[] = []> {
|
|
5
|
+
private readonly closure_: (...args: Args) => T;
|
|
6
|
+
private value_: T | object;
|
|
7
|
+
|
|
8
|
+
public constructor(closure: (...args: Args) => T) {
|
|
9
|
+
this.closure_ = closure;
|
|
10
|
+
this.value_ = NOT_MOUNTED_YET;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public get(...args: Args): T {
|
|
14
|
+
if (this.value_ === NOT_MOUNTED_YET) this.value_ = this.closure_(...args);
|
|
15
|
+
return this.value_ as T;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
const NOT_MOUNTED_YET = {};
|