@hunsu/protocol 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +157 -0
- package/dist/command-decoder.d.ts +5 -0
- package/dist/command-decoder.js +329 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.js +15 -0
- package/dist/decoder-helpers.d.ts +58 -0
- package/dist/decoder-helpers.js +1757 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +28 -0
- package/dist/event-decoder.d.ts +5 -0
- package/dist/event-decoder.js +232 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/lifecycle.d.ts +67 -0
- package/dist/lifecycle.js +271 -0
- package/dist/model.d.ts +1058 -0
- package/dist/model.js +1 -0
- package/dist/primitives.d.ts +59 -0
- package/dist/primitives.js +135 -0
- package/dist/projection.d.ts +8 -0
- package/dist/projection.js +875 -0
- package/dist/prompt-template.d.ts +12 -0
- package/dist/prompt-template.js +83 -0
- package/dist/protocol-validation.d.ts +36 -0
- package/dist/protocol-validation.js +1139 -0
- package/dist/result.d.ts +20 -0
- package/dist/result.js +21 -0
- package/dist/workflow-helpers.d.ts +31 -0
- package/dist/workflow-helpers.js +193 -0
- package/dist/workflow.d.ts +10 -0
- package/dist/workflow.js +594 -0
- package/package.json +30 -0
- package/src/command-decoder.ts +292 -0
- package/src/constants.ts +27 -0
- package/src/decoder-helpers.ts +1672 -0
- package/src/errors.ts +38 -0
- package/src/event-decoder.ts +225 -0
- package/src/index.ts +43 -0
- package/src/lifecycle.ts +403 -0
- package/src/model.ts +1233 -0
- package/src/primitives.ts +196 -0
- package/src/projection.ts +1081 -0
- package/src/prompt-template.ts +97 -0
- package/src/protocol-validation.ts +1252 -0
- package/src/result.ts +35 -0
- package/src/workflow-helpers.ts +239 -0
- package/src/workflow.ts +753 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { DomainInvariantError, workflowError, type DomainWorkflowError } from "./errors.ts";
|
|
2
|
+
import { ok, type Result } from "./result.ts";
|
|
3
|
+
|
|
4
|
+
export const PROMPT_TEMPLATE_ENGINE_V1 = "hunsu-template-v1" as const;
|
|
5
|
+
|
|
6
|
+
export type PromptTemplate = {
|
|
7
|
+
engine: typeof PROMPT_TEMPLATE_ENGINE_V1;
|
|
8
|
+
template: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type PromptTemplateContext = Record<string, unknown>;
|
|
12
|
+
|
|
13
|
+
export function promptTemplateFromText(template: string): PromptTemplate {
|
|
14
|
+
return { engine: PROMPT_TEMPLATE_ENGINE_V1, template };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function decodePromptTemplate(value: unknown, path: string): Result<PromptTemplate, DomainWorkflowError> {
|
|
18
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
19
|
+
return workflowError(`${path} must be an object`);
|
|
20
|
+
}
|
|
21
|
+
const record = value as Record<string, unknown>;
|
|
22
|
+
const allowed = new Set(["engine", "template"]);
|
|
23
|
+
const unexpected = Object.keys(record).filter(key => !allowed.has(key));
|
|
24
|
+
if (unexpected.length > 0) {
|
|
25
|
+
return workflowError(`${path} has unsupported field: ${unexpected[0]}`);
|
|
26
|
+
}
|
|
27
|
+
if (!("engine" in record)) {
|
|
28
|
+
return workflowError(`${path}.engine is required`);
|
|
29
|
+
}
|
|
30
|
+
if (!("template" in record)) {
|
|
31
|
+
return workflowError(`${path}.template is required`);
|
|
32
|
+
}
|
|
33
|
+
if (record.engine !== PROMPT_TEMPLATE_ENGINE_V1) {
|
|
34
|
+
return workflowError(`${path}.engine must be ${PROMPT_TEMPLATE_ENGINE_V1}`);
|
|
35
|
+
}
|
|
36
|
+
if (typeof record.template !== "string") {
|
|
37
|
+
return workflowError(`${path}.template must be a string`);
|
|
38
|
+
}
|
|
39
|
+
return ok({ engine: PROMPT_TEMPLATE_ENGINE_V1, template: record.template });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function assertValidPromptTemplate(value: unknown, path: string): asserts value is PromptTemplate {
|
|
43
|
+
const result = decodePromptTemplate(value, path);
|
|
44
|
+
if (!result.ok) {
|
|
45
|
+
throw new DomainInvariantError(result.error.message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function renderPromptTemplate(template: PromptTemplate, context: PromptTemplateContext): string {
|
|
50
|
+
assertValidPromptTemplate(template, "promptTemplate");
|
|
51
|
+
return template.template.replace(/\{\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[0-9]+\])*)\s*\}\}/g, (_match, expression: string) => {
|
|
52
|
+
const value = resolveTemplateExpression(context, expression);
|
|
53
|
+
if (value === undefined || value === null) {
|
|
54
|
+
throw new DomainInvariantError(`Prompt template value is unavailable: ${expression}`);
|
|
55
|
+
}
|
|
56
|
+
return formatTemplateValue(value);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function resolveTemplateExpression(context: PromptTemplateContext, expression: string): unknown {
|
|
61
|
+
const tokens = expression.match(/[A-Za-z_$][\w$]*|\[[0-9]+\]/g);
|
|
62
|
+
if (!tokens || tokens.join("").replace(/\]\[/g, "][") === "") {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
let current: unknown = context;
|
|
66
|
+
for (const token of tokens) {
|
|
67
|
+
if (token.startsWith("[")) {
|
|
68
|
+
const index = Number(token.slice(1, -1));
|
|
69
|
+
if (!Array.isArray(current)) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
current = current[index];
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (typeof current !== "object" || current === null) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
current = (current as Record<string, unknown>)[token];
|
|
79
|
+
}
|
|
80
|
+
return current;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function formatTemplateValue(value: unknown): string {
|
|
84
|
+
if (typeof value === "string") {
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
88
|
+
return String(value);
|
|
89
|
+
}
|
|
90
|
+
if (Array.isArray(value)) {
|
|
91
|
+
return value.map(formatTemplateValue).join("\n");
|
|
92
|
+
}
|
|
93
|
+
if (typeof value === "object" && value !== null) {
|
|
94
|
+
return JSON.stringify(value);
|
|
95
|
+
}
|
|
96
|
+
return "";
|
|
97
|
+
}
|