@vertesia/workflow 0.79.1 → 0.80.0-dev-20251118
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/package.json +7 -7
- package/src/activities/notifyWebhook.test.ts +1 -1
- package/src/dsl/setup/ActivityContext.ts +45 -12
- package/src/dsl/workflow-exec-child.test.ts +3 -3
- package/src/dsl/workflow-fetch.test.ts +1 -1
- package/src/dsl/workflow-import.test.ts +1 -1
- package/src/dsl/workflow.test.ts +1 -1
- package/src/iterative-generation/activities/extractToc.ts +26 -12
- package/src/iterative-generation/activities/finalizeOutput.ts +52 -29
- package/src/iterative-generation/activities/generatePart.ts +64 -23
- package/src/iterative-generation/activities/generateToc.ts +78 -65
- package/src/utils/blobs.ts +3 -1
- package/src/utils/client.ts +22 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.80.0-dev-20251118",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vertesia workflow DSL",
|
|
6
6
|
"main": "./lib/esm/index.js",
|
|
@@ -16,11 +16,6 @@
|
|
|
16
16
|
"build": "pnpm exec tsmod build && node ./bin/bundle-workflows.mjs lib/esm/workflows.js lib/workflows-bundle.js",
|
|
17
17
|
"clean": "rm -rf ./lib tsconfig.tsbuildinfo"
|
|
18
18
|
},
|
|
19
|
-
"repository": {
|
|
20
|
-
"type": "git",
|
|
21
|
-
"url": "https://github.com/vertesia/composableai.git",
|
|
22
|
-
"directory": "zeno/workflow"
|
|
23
|
-
},
|
|
24
19
|
"license": "Apache-2.0",
|
|
25
20
|
"devDependencies": {
|
|
26
21
|
"@smithy/types": "^3.7.2",
|
|
@@ -56,7 +51,7 @@
|
|
|
56
51
|
"seedrandom": "^3.0.5",
|
|
57
52
|
"sharp": "^0.33.4",
|
|
58
53
|
"tiktoken": "^1.0.15",
|
|
59
|
-
"tmp": "^0.2.
|
|
54
|
+
"tmp": "^0.2.4",
|
|
60
55
|
"tmp-promise": "^3.0.3",
|
|
61
56
|
"yaml": "^2.6.0"
|
|
62
57
|
},
|
|
@@ -110,6 +105,11 @@
|
|
|
110
105
|
"require": "./lib/cjs/errors.js"
|
|
111
106
|
}
|
|
112
107
|
},
|
|
108
|
+
"repository": {
|
|
109
|
+
"type": "git",
|
|
110
|
+
"url": "https://github.com/vertesia/composableai.git",
|
|
111
|
+
"directory": "packages/workflow"
|
|
112
|
+
},
|
|
113
113
|
"types": "./lib/types/index.d.ts",
|
|
114
114
|
"typesVersions": {
|
|
115
115
|
"*": {
|
|
@@ -33,7 +33,7 @@ const defaultParams = {
|
|
|
33
33
|
const createTestPayload = (params: Partial<NotifyWebhookParams> = {}): DSLActivityExecutionPayload<NotifyWebhookParams> => {
|
|
34
34
|
const mergedParams = { ...defaultParams, ...params };
|
|
35
35
|
return {
|
|
36
|
-
auth_token: "
|
|
36
|
+
auth_token: process.env.VERTESIA_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature",
|
|
37
37
|
account_id: "unset",
|
|
38
38
|
project_id: "unset",
|
|
39
39
|
params: mergedParams,
|
|
@@ -6,16 +6,32 @@ import {
|
|
|
6
6
|
Project,
|
|
7
7
|
WorkflowExecutionPayload,
|
|
8
8
|
} from "@vertesia/common";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
DocumentNotFoundError,
|
|
11
|
+
WorkflowParamNotFoundError,
|
|
12
|
+
} from "../../errors.js";
|
|
10
13
|
import { getProjectFromToken } from "../../utils/auth.js";
|
|
11
14
|
import { getVertesiaClient } from "../../utils/client.js";
|
|
12
15
|
import { Vars } from "../vars.js";
|
|
13
|
-
import {
|
|
14
|
-
|
|
16
|
+
import {
|
|
17
|
+
getFetchProvider,
|
|
18
|
+
registerFetchProviderFactory,
|
|
19
|
+
} from "./fetch/index.js";
|
|
20
|
+
import {
|
|
21
|
+
DocumentProvider,
|
|
22
|
+
DocumentTypeProvider,
|
|
23
|
+
InteractionRunProvider,
|
|
24
|
+
} from "./fetch/providers.js";
|
|
15
25
|
|
|
16
26
|
registerFetchProviderFactory(DocumentProvider.ID, DocumentProvider.factory);
|
|
17
|
-
registerFetchProviderFactory(
|
|
18
|
-
|
|
27
|
+
registerFetchProviderFactory(
|
|
28
|
+
DocumentTypeProvider.ID,
|
|
29
|
+
DocumentTypeProvider.factory,
|
|
30
|
+
);
|
|
31
|
+
registerFetchProviderFactory(
|
|
32
|
+
InteractionRunProvider.ID,
|
|
33
|
+
InteractionRunProvider.factory,
|
|
34
|
+
);
|
|
19
35
|
|
|
20
36
|
export class ActivityContext<ParamsT extends Record<string, any>> {
|
|
21
37
|
client: VertesiaClient;
|
|
@@ -40,7 +56,10 @@ export class ActivityContext<ParamsT extends Record<string, any>> {
|
|
|
40
56
|
log.error("No objectId found in payload");
|
|
41
57
|
throw new WorkflowParamNotFoundError(
|
|
42
58
|
"objectIds[0]",
|
|
43
|
-
(
|
|
59
|
+
(
|
|
60
|
+
this
|
|
61
|
+
.payload as WorkflowExecutionPayload as DSLWorkflowExecutionPayload
|
|
62
|
+
).workflow,
|
|
44
63
|
);
|
|
45
64
|
}
|
|
46
65
|
return objectId;
|
|
@@ -56,7 +75,10 @@ export class ActivityContext<ParamsT extends Record<string, any>> {
|
|
|
56
75
|
log.error("No runId found in activityInfo");
|
|
57
76
|
throw new WorkflowParamNotFoundError(
|
|
58
77
|
"runId",
|
|
59
|
-
(
|
|
78
|
+
(
|
|
79
|
+
this
|
|
80
|
+
.payload as WorkflowExecutionPayload as DSLWorkflowExecutionPayload
|
|
81
|
+
).workflow,
|
|
60
82
|
);
|
|
61
83
|
}
|
|
62
84
|
return runId;
|
|
@@ -68,7 +90,10 @@ export class ActivityContext<ParamsT extends Record<string, any>> {
|
|
|
68
90
|
log.error("No workflowId found in activityInfo");
|
|
69
91
|
throw new WorkflowParamNotFoundError(
|
|
70
92
|
"workflowId",
|
|
71
|
-
(
|
|
93
|
+
(
|
|
94
|
+
this
|
|
95
|
+
.payload as WorkflowExecutionPayload as DSLWorkflowExecutionPayload
|
|
96
|
+
).workflow,
|
|
72
97
|
);
|
|
73
98
|
}
|
|
74
99
|
return workflowId;
|
|
@@ -102,7 +127,7 @@ export async function setupActivity<ParamsT extends Record<string, any>>(
|
|
|
102
127
|
});
|
|
103
128
|
}
|
|
104
129
|
|
|
105
|
-
const client = getVertesiaClient(payload);
|
|
130
|
+
const client = await getVertesiaClient(payload);
|
|
106
131
|
const fetchSpecs = payload.activity.fetch;
|
|
107
132
|
if (fetchSpecs) {
|
|
108
133
|
const keys = Object.keys(fetchSpecs);
|
|
@@ -118,7 +143,10 @@ export async function setupActivity<ParamsT extends Record<string, any>>(
|
|
|
118
143
|
|
|
119
144
|
const provider = getFetchProvider(client, fetchSpec);
|
|
120
145
|
|
|
121
|
-
log.info(
|
|
146
|
+
log.info(
|
|
147
|
+
`Fetching data for ${key} with provider ${provider.name}`,
|
|
148
|
+
{ fetchSpec },
|
|
149
|
+
);
|
|
122
150
|
const result = await provider.fetch(fetchSpec);
|
|
123
151
|
if (result && result.length > 0) {
|
|
124
152
|
if (fetchSpec.limit === 1) {
|
|
@@ -127,7 +155,9 @@ export async function setupActivity<ParamsT extends Record<string, any>>(
|
|
|
127
155
|
vars.setValue(key, result);
|
|
128
156
|
}
|
|
129
157
|
} else if (fetchSpec.on_not_found === "throw") {
|
|
130
|
-
throw new DocumentNotFoundError(
|
|
158
|
+
throw new DocumentNotFoundError(
|
|
159
|
+
"No documents found for: " + JSON.stringify(fetchSpec),
|
|
160
|
+
);
|
|
131
161
|
} else {
|
|
132
162
|
vars.setValue(key, null);
|
|
133
163
|
}
|
|
@@ -141,7 +171,10 @@ export async function setupActivity<ParamsT extends Record<string, any>>(
|
|
|
141
171
|
return new ActivityContext<ParamsT>(payload, client, params);
|
|
142
172
|
}
|
|
143
173
|
|
|
144
|
-
async function _fetchProject(
|
|
174
|
+
async function _fetchProject(
|
|
175
|
+
client: VertesiaClient,
|
|
176
|
+
payload: WorkflowExecutionPayload,
|
|
177
|
+
) {
|
|
145
178
|
const project = await getProjectFromToken(payload.auth_token);
|
|
146
179
|
return project ? await client.projects.retrieve(project.id) : undefined;
|
|
147
180
|
}
|
|
@@ -159,7 +159,7 @@ describe('DSL Workflow with child workflows', () => {
|
|
|
159
159
|
account_id: '123',
|
|
160
160
|
project_id: '123',
|
|
161
161
|
wf_rule_name: 'test',
|
|
162
|
-
auth_token: '
|
|
162
|
+
auth_token: process.env.VERTESIA_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature',
|
|
163
163
|
config: {
|
|
164
164
|
studio_url: process.env.CP_STUDIO_URL || "http://localhost:8081",
|
|
165
165
|
store_url: process.env.CP_STORE_URL || "http://localhost:8082",
|
|
@@ -203,7 +203,7 @@ describe('DSL Workflow with child workflows', () => {
|
|
|
203
203
|
account_id: '123',
|
|
204
204
|
project_id: '123',
|
|
205
205
|
wf_rule_name: 'test',
|
|
206
|
-
auth_token: '
|
|
206
|
+
auth_token: process.env.VERTESIA_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature',
|
|
207
207
|
config: {
|
|
208
208
|
studio_url: process.env.CP_STUDIO_URL || "http://localhost:8081",
|
|
209
209
|
store_url: process.env.CP_STORE_URL || "http://localhost:8082",
|
|
@@ -247,7 +247,7 @@ describe('DSL Workflow with child workflows', () => {
|
|
|
247
247
|
account_id: '123',
|
|
248
248
|
project_id: '123',
|
|
249
249
|
wf_rule_name: 'test',
|
|
250
|
-
auth_token: '
|
|
250
|
+
auth_token: process.env.VERTESIA_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature',
|
|
251
251
|
config: {
|
|
252
252
|
studio_url: process.env.CP_STUDIO_URL || "http://localhost:8081",
|
|
253
253
|
store_url: process.env.CP_STORE_URL || "http://localhost:8082",
|
|
@@ -107,7 +107,7 @@ describe('DSL Workflow', () => {
|
|
|
107
107
|
project_id: '123',
|
|
108
108
|
timestamp: Date.now(),
|
|
109
109
|
wf_rule_name: 'test',
|
|
110
|
-
auth_token: '
|
|
110
|
+
auth_token: process.env.VERTESIA_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature',
|
|
111
111
|
config: {
|
|
112
112
|
studio_url: process.env.CP_STUDIO_URL || "http://localhost:8081",
|
|
113
113
|
store_url: process.env.CP_STORE_URL || "http://localhost:8082",
|
|
@@ -61,7 +61,7 @@ describe('DSL Workflow import vars', () => {
|
|
|
61
61
|
project_id: '123',
|
|
62
62
|
timestamp: Date.now(),
|
|
63
63
|
wf_rule_name: 'test',
|
|
64
|
-
auth_token: '
|
|
64
|
+
auth_token: process.env.VERTESIA_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature',
|
|
65
65
|
config: {
|
|
66
66
|
studio_url: process.env.CP_STUDIO_URL || "http://localhost:8081",
|
|
67
67
|
store_url: process.env.CP_STORE_URL || "http://localhost:8082",
|
package/src/dsl/workflow.test.ts
CHANGED
|
@@ -91,7 +91,7 @@ describe('DSL Workflow', () => {
|
|
|
91
91
|
project_id: '123',
|
|
92
92
|
timestamp: Date.now(),
|
|
93
93
|
wf_rule_name: 'test',
|
|
94
|
-
auth_token: '
|
|
94
|
+
auth_token: process.env.VERTESIA_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature',
|
|
95
95
|
config: {
|
|
96
96
|
studio_url: process.env.CP_STUDIO_URL || "http://localhost:8081",
|
|
97
97
|
store_url: process.env.CP_STORE_URL || "http://localhost:8082",
|
|
@@ -2,8 +2,16 @@ import { log } from "@temporalio/activity";
|
|
|
2
2
|
import { WorkflowExecutionPayload } from "@vertesia/common";
|
|
3
3
|
import { parse as parseYaml } from "yaml";
|
|
4
4
|
import { getVertesiaClient } from "../../utils/client.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
buildAndPublishMemoryPack,
|
|
7
|
+
loadMemoryPack,
|
|
8
|
+
} from "../../utils/memory.js";
|
|
9
|
+
import {
|
|
10
|
+
IterativeGenerationPayload,
|
|
11
|
+
OutputMemoryMeta,
|
|
12
|
+
Toc,
|
|
13
|
+
TocIndex,
|
|
14
|
+
} from "../types.js";
|
|
7
15
|
import { tocIndex } from "../utils.js";
|
|
8
16
|
|
|
9
17
|
/**
|
|
@@ -12,10 +20,12 @@ import { tocIndex } from "../utils.js";
|
|
|
12
20
|
*
|
|
13
21
|
* @param payload
|
|
14
22
|
*/
|
|
15
|
-
export async function it_gen_extractToc(
|
|
23
|
+
export async function it_gen_extractToc(
|
|
24
|
+
payload: WorkflowExecutionPayload,
|
|
25
|
+
): Promise<TocIndex | null> {
|
|
16
26
|
const vars = payload.vars as IterativeGenerationPayload;
|
|
17
27
|
const memory = vars.memory;
|
|
18
|
-
const client = getVertesiaClient(payload);
|
|
28
|
+
const client = await getVertesiaClient(payload);
|
|
19
29
|
|
|
20
30
|
const inMemory = await loadMemoryPack(client, `${memory}/input`);
|
|
21
31
|
let tocJson: string | null = null;
|
|
@@ -37,13 +47,17 @@ export async function it_gen_extractToc(payload: WorkflowExecutionPayload): Prom
|
|
|
37
47
|
|
|
38
48
|
log.info(`Found a TOC in the input memory pack`);
|
|
39
49
|
|
|
40
|
-
await buildAndPublishMemoryPack(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
await buildAndPublishMemoryPack(
|
|
51
|
+
client,
|
|
52
|
+
`${vars.memory}/output`,
|
|
53
|
+
async () => {
|
|
54
|
+
return {
|
|
55
|
+
toc,
|
|
56
|
+
lastProcessedPart: undefined, // the part index (a number array)
|
|
57
|
+
previouslyGenerated: "",
|
|
58
|
+
} as OutputMemoryMeta;
|
|
59
|
+
},
|
|
60
|
+
);
|
|
47
61
|
|
|
48
62
|
return tocIndex(toc);
|
|
49
|
-
}
|
|
63
|
+
}
|
|
@@ -2,14 +2,24 @@ import { log } from "@temporalio/activity";
|
|
|
2
2
|
import { WorkflowExecutionPayload } from "@vertesia/common";
|
|
3
3
|
import { getVertesiaClient } from "../../utils/client.js";
|
|
4
4
|
import { expandVars } from "../../utils/expand-vars.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
buildAndPublishMemoryPack,
|
|
7
|
+
loadMemoryPack,
|
|
8
|
+
} from "../../utils/memory.js";
|
|
9
|
+
import {
|
|
10
|
+
IterativeGenerationPayload,
|
|
11
|
+
Section,
|
|
12
|
+
SECTION_ID_PLACEHOLDER,
|
|
13
|
+
TocSection,
|
|
14
|
+
} from "../types.js";
|
|
7
15
|
|
|
8
|
-
export async function it_gen_finalizeOutput(
|
|
16
|
+
export async function it_gen_finalizeOutput(
|
|
17
|
+
payload: WorkflowExecutionPayload,
|
|
18
|
+
): Promise<string> {
|
|
9
19
|
const vars = payload.vars as IterativeGenerationPayload;
|
|
10
20
|
|
|
11
21
|
const memory = vars.memory;
|
|
12
|
-
const client = getVertesiaClient(payload);
|
|
22
|
+
const client = await getVertesiaClient(payload);
|
|
13
23
|
const inMemory = await loadMemoryPack(client, `${memory}/input`);
|
|
14
24
|
const outMemory = await loadMemoryPack(client, `${memory}/output`);
|
|
15
25
|
|
|
@@ -35,43 +45,56 @@ export async function it_gen_finalizeOutput(payload: WorkflowExecutionPayload):
|
|
|
35
45
|
}
|
|
36
46
|
const sections = JSON.parse(content) as Section[];
|
|
37
47
|
|
|
38
|
-
await buildAndPublishMemoryPack(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
await buildAndPublishMemoryPack(
|
|
49
|
+
client,
|
|
50
|
+
`${memory}/output`,
|
|
51
|
+
async ({ copyText }) => {
|
|
52
|
+
// copy the input toc file if any
|
|
53
|
+
if (toc) {
|
|
54
|
+
copyText(toc, tocName);
|
|
55
|
+
}
|
|
56
|
+
// copy the raw JSON content
|
|
57
|
+
copyText(content, "content.json");
|
|
58
|
+
if (vars.section_file_pattern) {
|
|
59
|
+
log.info(
|
|
60
|
+
`Saving sections to files using pattern: ${vars.section_file_pattern}`,
|
|
61
|
+
);
|
|
62
|
+
// save sections to files
|
|
63
|
+
for (const section of sections) {
|
|
64
|
+
let content = section.content;
|
|
65
|
+
if (vars.section_file_header) {
|
|
66
|
+
content =
|
|
67
|
+
getSectionFileHeader(
|
|
68
|
+
section,
|
|
69
|
+
vars.section_file_header,
|
|
70
|
+
) +
|
|
71
|
+
"\n\n" +
|
|
72
|
+
content;
|
|
73
|
+
}
|
|
74
|
+
copyText(
|
|
75
|
+
content,
|
|
76
|
+
getSectionFileName(section, vars.section_file_pattern),
|
|
77
|
+
);
|
|
52
78
|
}
|
|
53
|
-
copyText(content, getSectionFileName(section, vars.section_file_pattern));
|
|
54
79
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
80
|
+
return {
|
|
81
|
+
...inMeta,
|
|
82
|
+
vars,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
);
|
|
61
86
|
|
|
62
87
|
return `Processing done. Extracted files to: ${vars.section_file_pattern}`;
|
|
63
88
|
}
|
|
64
89
|
|
|
65
|
-
|
|
66
|
-
|
|
67
90
|
function getSectionFileHeader(section: TocSection, header: string): string {
|
|
68
91
|
const date = new Date().toISOString();
|
|
69
92
|
return expandVars(header, {
|
|
70
93
|
section,
|
|
71
|
-
date
|
|
94
|
+
date,
|
|
72
95
|
});
|
|
73
96
|
}
|
|
74
97
|
|
|
75
98
|
function getSectionFileName(section: TocSection, pattern: string): string {
|
|
76
99
|
return pattern.replace(SECTION_ID_PLACEHOLDER, section.id);
|
|
77
|
-
}
|
|
100
|
+
}
|
|
@@ -2,29 +2,49 @@ import { ApplicationFailure } from "@temporalio/workflow";
|
|
|
2
2
|
import { WorkflowExecutionPayload } from "@vertesia/common";
|
|
3
3
|
import { MemoryPack } from "@vertesia/memory";
|
|
4
4
|
import { getVertesiaClient } from "../../utils/client.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
buildAndPublishMemoryPack,
|
|
7
|
+
loadMemoryPack,
|
|
8
|
+
} from "../../utils/memory.js";
|
|
9
|
+
import {
|
|
10
|
+
IterativeGenerationPayload,
|
|
11
|
+
OutputMemoryMeta,
|
|
12
|
+
Section,
|
|
13
|
+
TocPart,
|
|
14
|
+
TocSection,
|
|
15
|
+
} from "../types.js";
|
|
7
16
|
import { executeWithVars, expectMemoryIsConsistent } from "../utils.js";
|
|
8
17
|
|
|
9
|
-
export async function it_gen_generatePart(
|
|
18
|
+
export async function it_gen_generatePart(
|
|
19
|
+
payload: WorkflowExecutionPayload,
|
|
20
|
+
path: number[],
|
|
21
|
+
) {
|
|
10
22
|
const vars = payload.vars as IterativeGenerationPayload;
|
|
11
|
-
const client = getVertesiaClient(payload);
|
|
23
|
+
const client = await getVertesiaClient(payload);
|
|
12
24
|
const memory = vars.memory;
|
|
13
25
|
|
|
14
26
|
const [sectionIndex, partIndex] = path;
|
|
15
27
|
const outMemory = await loadMemoryPack(client, `${memory}/output`);
|
|
16
|
-
const meta = await outMemory.getMetadata() as OutputMemoryMeta;
|
|
28
|
+
const meta = (await outMemory.getMetadata()) as OutputMemoryMeta;
|
|
17
29
|
|
|
18
30
|
// the section we build is the section at the given index
|
|
19
31
|
const section: TocSection = meta.toc.sections[sectionIndex];
|
|
20
32
|
if (!section) {
|
|
21
|
-
throw ApplicationFailure.nonRetryable(
|
|
33
|
+
throw ApplicationFailure.nonRetryable(
|
|
34
|
+
"Section not found in the TOC",
|
|
35
|
+
"SectionNotFound",
|
|
36
|
+
{ memory, path },
|
|
37
|
+
);
|
|
22
38
|
}
|
|
23
39
|
let part: TocPart | undefined;
|
|
24
40
|
if (partIndex !== undefined) {
|
|
25
41
|
part = section.parts?.[partIndex];
|
|
26
42
|
if (!part) {
|
|
27
|
-
throw ApplicationFailure.nonRetryable(
|
|
43
|
+
throw ApplicationFailure.nonRetryable(
|
|
44
|
+
"Part not found in the TOC section",
|
|
45
|
+
"PartNotFound",
|
|
46
|
+
{ memory, path },
|
|
47
|
+
);
|
|
28
48
|
}
|
|
29
49
|
}
|
|
30
50
|
|
|
@@ -32,17 +52,26 @@ export async function it_gen_generatePart(payload: WorkflowExecutionPayload, pat
|
|
|
32
52
|
|
|
33
53
|
const content = await loadGeneratedContent(outMemory);
|
|
34
54
|
|
|
35
|
-
let previously_generated = getPreviouslyGeneratedContent(
|
|
55
|
+
let previously_generated = getPreviouslyGeneratedContent(
|
|
56
|
+
content,
|
|
57
|
+
!part,
|
|
58
|
+
vars.remembrance_strategy,
|
|
59
|
+
);
|
|
36
60
|
|
|
37
|
-
if (!part) {
|
|
61
|
+
if (!part) {
|
|
62
|
+
// a new section
|
|
38
63
|
content.push({
|
|
39
64
|
id: section.id,
|
|
40
65
|
name: section.name,
|
|
41
66
|
description: section.description,
|
|
42
|
-
content:
|
|
43
|
-
})
|
|
67
|
+
content: "",
|
|
68
|
+
});
|
|
44
69
|
} else if (!content.length) {
|
|
45
|
-
throw ApplicationFailure.nonRetryable(
|
|
70
|
+
throw ApplicationFailure.nonRetryable(
|
|
71
|
+
"content.json is empty while generating a part",
|
|
72
|
+
"InvalidIterationState",
|
|
73
|
+
{ memory, path },
|
|
74
|
+
);
|
|
46
75
|
}
|
|
47
76
|
|
|
48
77
|
const interaction = vars.iterative_interaction || vars.interaction;
|
|
@@ -53,30 +82,42 @@ export async function it_gen_generatePart(payload: WorkflowExecutionPayload, pat
|
|
|
53
82
|
section: section.name,
|
|
54
83
|
part: part?.name,
|
|
55
84
|
path: path,
|
|
56
|
-
}
|
|
85
|
+
},
|
|
57
86
|
});
|
|
58
87
|
|
|
59
88
|
const result = r.result.text();
|
|
60
89
|
content[content.length - 1].content += result;
|
|
61
90
|
meta.lastProcessedPart = path;
|
|
62
|
-
await buildAndPublishMemoryPack(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
91
|
+
await buildAndPublishMemoryPack(
|
|
92
|
+
client,
|
|
93
|
+
`${memory}/output`,
|
|
94
|
+
async ({ copyText }) => {
|
|
95
|
+
copyText(JSON.stringify(content, null, 2), "content.json");
|
|
96
|
+
return meta;
|
|
97
|
+
},
|
|
98
|
+
);
|
|
66
99
|
}
|
|
67
100
|
|
|
68
101
|
async function loadGeneratedContent(memory: MemoryPack): Promise<Section[]> {
|
|
69
|
-
const content = await memory.getEntryText(
|
|
102
|
+
const content = await memory.getEntryText("content.json");
|
|
70
103
|
return content ? JSON.parse(content) : [];
|
|
71
104
|
}
|
|
72
105
|
|
|
73
|
-
function getPreviouslyGeneratedContent(
|
|
106
|
+
function getPreviouslyGeneratedContent(
|
|
107
|
+
sections: Section[],
|
|
108
|
+
isNewSection: boolean,
|
|
109
|
+
strategy?: "document" | "section" | "none",
|
|
110
|
+
): string {
|
|
74
111
|
switch (strategy) {
|
|
75
112
|
case "document":
|
|
76
|
-
return sections
|
|
113
|
+
return sections
|
|
114
|
+
.map((section: Section) => section.content || "")
|
|
115
|
+
.join("\n\n");
|
|
77
116
|
case "none":
|
|
78
|
-
return
|
|
117
|
+
return "";
|
|
79
118
|
default:
|
|
80
|
-
return isNewSection
|
|
119
|
+
return isNewSection
|
|
120
|
+
? ""
|
|
121
|
+
: sections[sections.length - 1]?.content || "";
|
|
81
122
|
}
|
|
82
|
-
}
|
|
123
|
+
}
|
|
@@ -1,88 +1,97 @@
|
|
|
1
1
|
import { WorkflowExecutionPayload } from "@vertesia/common";
|
|
2
2
|
import { getVertesiaClient } from "../../utils/client.js";
|
|
3
3
|
import { buildAndPublishMemoryPack } from "../../utils/memory.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
IterativeGenerationPayload,
|
|
6
|
+
OutputMemoryMeta,
|
|
7
|
+
Toc,
|
|
8
|
+
TocIndex,
|
|
9
|
+
} from "../types.js";
|
|
5
10
|
import { executeWithVars, tocIndex } from "../utils.js";
|
|
6
11
|
|
|
7
12
|
const defaultTocSchema = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
sections: {
|
|
16
|
+
type: "array",
|
|
17
|
+
items: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
id: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description:
|
|
23
|
+
"the id of the section, can be a filename if working on a file, a slug if working on a document or path, or a unique identifier if working on a model.",
|
|
18
24
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
operation: {
|
|
26
|
+
type: "string",
|
|
27
|
+
enum: ["create", "update", "delete"],
|
|
28
|
+
description:
|
|
29
|
+
"The operation to perform on the section, create, update or delete. If update, you will be requested later to provide the list of change operation to perform.",
|
|
23
30
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
name: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description:
|
|
34
|
+
"The name or title of the section, should be the path in the OpenAPI spec, of the title of the section/part.",
|
|
27
35
|
},
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
description: {
|
|
37
|
+
type: "string",
|
|
30
38
|
},
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
instructions: {
|
|
40
|
+
type: "string",
|
|
33
41
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
parts: {
|
|
43
|
+
type: "array",
|
|
44
|
+
description:
|
|
45
|
+
"when the section is too large, you can split it into parts, each part should have a title and description. Use it to split the section into subsection. When doing an API documentation, you can do one part for each path. When generating code, you can do one part for each method. When generating an OpenAPI spec, you can do one part for each operation.",
|
|
46
|
+
items: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
id: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description:
|
|
52
|
+
"the id of the part, can be a filename if working on a file, a slug if working on a document or path, or a unique identifier if working on a model.",
|
|
44
53
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
name: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description:
|
|
57
|
+
"The name or title of the part, should be the path in the OpenAPI spec, of the title of the section/part.",
|
|
48
58
|
},
|
|
49
59
|
/*
|
|
50
60
|
"description": {
|
|
51
61
|
"type": "string"
|
|
52
62
|
},
|
|
53
63
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
64
|
+
instructions: {
|
|
65
|
+
type: "string",
|
|
66
|
+
},
|
|
57
67
|
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
}
|
|
68
|
+
required: ["id", "name"],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
64
71
|
},
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"operation"
|
|
69
|
-
]
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
+
required: ["id", "name", "operation"],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
72
75
|
},
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
]
|
|
76
|
-
}
|
|
76
|
+
required: ["sections"],
|
|
77
|
+
};
|
|
77
78
|
|
|
78
|
-
export async function it_gen_generateToc(
|
|
79
|
+
export async function it_gen_generateToc(
|
|
80
|
+
payload: WorkflowExecutionPayload,
|
|
81
|
+
): Promise<TocIndex> {
|
|
79
82
|
const vars = payload.vars as IterativeGenerationPayload;
|
|
80
83
|
|
|
81
84
|
const schema = vars.toc_schema || defaultTocSchema;
|
|
82
85
|
|
|
83
|
-
const client = getVertesiaClient(payload);
|
|
86
|
+
const client = await getVertesiaClient(payload);
|
|
84
87
|
|
|
85
|
-
const run = await executeWithVars(
|
|
88
|
+
const run = await executeWithVars(
|
|
89
|
+
client,
|
|
90
|
+
vars.interaction,
|
|
91
|
+
vars,
|
|
92
|
+
undefined,
|
|
93
|
+
schema,
|
|
94
|
+
);
|
|
86
95
|
|
|
87
96
|
//Parse the CompletionResult[] to get a Toc object
|
|
88
97
|
const jsonResults = run.result.object();
|
|
@@ -91,13 +100,17 @@ export async function it_gen_generateToc(payload: WorkflowExecutionPayload): Pro
|
|
|
91
100
|
sections: jsonResults.sections
|
|
92
101
|
};
|
|
93
102
|
|
|
94
|
-
await buildAndPublishMemoryPack(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
await buildAndPublishMemoryPack(
|
|
104
|
+
client,
|
|
105
|
+
`${vars.memory}/output`,
|
|
106
|
+
async () => {
|
|
107
|
+
return {
|
|
108
|
+
toc,
|
|
109
|
+
lastProcessedPart: undefined, // the part index (a number array)
|
|
110
|
+
previouslyGenerated: "",
|
|
111
|
+
} satisfies OutputMemoryMeta;
|
|
112
|
+
},
|
|
113
|
+
);
|
|
101
114
|
|
|
102
115
|
return tocIndex(toc);
|
|
103
116
|
}
|
package/src/utils/blobs.ts
CHANGED
|
@@ -14,7 +14,9 @@ export async function fetchBlobAsStream(client: VertesiaClient, blobUri: string)
|
|
|
14
14
|
} catch (err: any) {
|
|
15
15
|
if (err.message.includes("not found")) {
|
|
16
16
|
//TODO improve error handling with a fetch fail error class in the client
|
|
17
|
-
throw new DocumentNotFoundError(`
|
|
17
|
+
throw new DocumentNotFoundError(`Not found at ${blobUri}: ${err.message}`, []);
|
|
18
|
+
} else if (err.message.includes("forbidden")) {
|
|
19
|
+
throw new DocumentNotFoundError(`Forbidden at ${blobUri}: ${err.message}`);
|
|
18
20
|
} else {
|
|
19
21
|
throw new Error(`Failed to download blob ${blobUri}: ${err.message}`);
|
|
20
22
|
}
|
package/src/utils/client.ts
CHANGED
|
@@ -2,31 +2,45 @@
|
|
|
2
2
|
* get a zeno client for a given token
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
decodeJWT,
|
|
7
|
+
VertesiaClient,
|
|
8
|
+
VertesiaClientProps,
|
|
9
|
+
} from "@vertesia/client";
|
|
6
10
|
import { WorkflowExecutionBaseParams } from "@vertesia/common";
|
|
7
11
|
import { WorkflowParamNotFoundError } from "../errors.js";
|
|
8
12
|
|
|
9
|
-
|
|
10
13
|
export function getVertesiaClient(payload: WorkflowExecutionBaseParams) {
|
|
11
14
|
return new VertesiaClient(getVertesiaClientOptions(payload));
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
export function getVertesiaClientOptions(
|
|
17
|
+
export function getVertesiaClientOptions(
|
|
18
|
+
payload: WorkflowExecutionBaseParams,
|
|
19
|
+
): VertesiaClientProps {
|
|
15
20
|
if (!payload.auth_token) {
|
|
16
|
-
throw new WorkflowParamNotFoundError(
|
|
21
|
+
throw new WorkflowParamNotFoundError(
|
|
22
|
+
"Authentication Token is missing from WorkflowExecutionPayload.authToken",
|
|
23
|
+
);
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
if (!payload.config?.studio_url) {
|
|
20
|
-
throw new WorkflowParamNotFoundError(
|
|
27
|
+
throw new WorkflowParamNotFoundError(
|
|
28
|
+
"Content Store URL is missing from WorkflowExecutionPayload.servers.storeUrl",
|
|
29
|
+
);
|
|
21
30
|
}
|
|
22
31
|
|
|
23
32
|
if (!payload.config?.store_url) {
|
|
24
|
-
throw new WorkflowParamNotFoundError(
|
|
33
|
+
throw new WorkflowParamNotFoundError(
|
|
34
|
+
"Content Store URL is missing from WorkflowExecutionPayload.servers.storeUrl",
|
|
35
|
+
);
|
|
25
36
|
}
|
|
26
37
|
|
|
38
|
+
const token = decodeJWT(payload.auth_token);
|
|
39
|
+
|
|
27
40
|
return {
|
|
28
41
|
serverUrl: payload.config.studio_url,
|
|
29
42
|
storeUrl: payload.config.store_url,
|
|
30
|
-
|
|
43
|
+
tokenServerUrl: token.iss,
|
|
44
|
+
apikey: payload.auth_token,
|
|
31
45
|
};
|
|
32
|
-
}
|
|
46
|
+
}
|