@workflow-code/cli 0.2.4-20261012004.codex-studio-integration → 0.2.4-20261012005.codex-studio-integration
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/{chunk-WN7VAGK6.js → chunk-5DWX3LL6.js} +1 -1
- package/dist/{chunk-MNY562W5.js → chunk-5FPIZZE4.js} +12 -7
- package/dist/index.js +3 -3
- package/dist/{local-QLYFH4WT.js → local-XHR2O2FP.js} +2 -2
- package/dist/{mcp-UQTMW3LK.js → mcp-RPT64F7T.js} +1 -1
- package/dist/web/related-projects.mjs +528 -0
- package/dist/web/worker.mjs +7 -0
- package/dist/{web-OMVO2EGT.js → web-6SWHMU2A.js} +36 -7
- package/package.json +4 -4
|
@@ -12,7 +12,7 @@ import os from "os";
|
|
|
12
12
|
import path from "path";
|
|
13
13
|
import { readFileSync, realpathSync, statSync } from "fs";
|
|
14
14
|
import * as workflowCode from "workflow-code";
|
|
15
|
-
var
|
|
15
|
+
var defaultStorageApi = workflowCode;
|
|
16
16
|
function parseCliRelatedProjectSpec(value) {
|
|
17
17
|
const separatorIndex = value.indexOf("=");
|
|
18
18
|
if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
|
|
@@ -30,6 +30,7 @@ function parseCliRelatedProjectSpec(value) {
|
|
|
30
30
|
}
|
|
31
31
|
function createCliRelatedProjectRuntime(options) {
|
|
32
32
|
if (options.relatedProjects.length === 0) return {};
|
|
33
|
+
const targetStorageApi = options.storageApi ?? defaultStorageApi;
|
|
33
34
|
const consumer = readProjectSnapshot(options.consumerProjectDir, "Current project");
|
|
34
35
|
const configuredByAlias = /* @__PURE__ */ new Map();
|
|
35
36
|
const configuredProjectIds = /* @__PURE__ */ new Set();
|
|
@@ -76,7 +77,7 @@ function createCliRelatedProjectRuntime(options) {
|
|
|
76
77
|
configured.projectDir,
|
|
77
78
|
`Related project "${alias}"`
|
|
78
79
|
);
|
|
79
|
-
if (currentTarget.projectId.toLowerCase() !== configured.projectId.toLowerCase()) {
|
|
80
|
+
if (currentConsumer.projectId.toLowerCase() !== consumer.projectId.toLowerCase() || currentTarget.projectId.toLowerCase() !== configured.projectId.toLowerCase()) {
|
|
80
81
|
return void 0;
|
|
81
82
|
}
|
|
82
83
|
const access = resolveWorkflowRelatedProjectAccess({
|
|
@@ -93,7 +94,8 @@ function createCliRelatedProjectRuntime(options) {
|
|
|
93
94
|
if (fixedStore === void 0 && typeof createRemoteStore !== "function") {
|
|
94
95
|
throw new Error("Installed workflow-code does not support related project storage.");
|
|
95
96
|
}
|
|
96
|
-
const
|
|
97
|
+
const roots = options.localStorageForProject?.(currentTarget.projectDir) ?? { kvStoreDir: localKvStoreDir, persistentValueStoreDir: localPersistentValueStoreDir };
|
|
98
|
+
const store = location === "local" && options.localStorageForProject ? targetStorageApi.createLocalWorkflowKVStore({ rootDir: roots.kvStoreDir, storageKind: "kv" }) : fixedStore ?? createRemoteStore({
|
|
97
99
|
consumerProjectId: currentConsumer.projectId,
|
|
98
100
|
targetProjectId: currentTarget.projectId,
|
|
99
101
|
alias,
|
|
@@ -105,8 +107,9 @@ function createCliRelatedProjectRuntime(options) {
|
|
|
105
107
|
runId: options.runId,
|
|
106
108
|
conversationId: options.conversationId
|
|
107
109
|
};
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
+
const persistentStore = location === "server" ? store : options.localStorageForProject && roots.persistentValueStoreDir !== void 0 ? targetStorageApi.createLocalWorkflowKVStore({ rootDir: roots.persistentValueStoreDir, storageKind: "persistent_value" }) : fixedPersistentValueStore;
|
|
111
|
+
const persistentValue = persistentStore === void 0 ? void 0 : targetStorageApi.createWorkflowPersistentValueContext?.({
|
|
112
|
+
store: persistentStore,
|
|
110
113
|
projectId: currentTarget.projectId,
|
|
111
114
|
source
|
|
112
115
|
});
|
|
@@ -119,8 +122,9 @@ function createCliRelatedProjectRuntime(options) {
|
|
|
119
122
|
// The roots settled above, not the raw options: the relation and the
|
|
120
123
|
// target's own run have to land on the same store, defaults
|
|
121
124
|
// included, or one side writes what the other cannot see.
|
|
122
|
-
kvStoreDir:
|
|
123
|
-
persistentValueStoreDir:
|
|
125
|
+
kvStoreDir: roots.kvStoreDir,
|
|
126
|
+
persistentValueStoreDir: roots.persistentValueStoreDir,
|
|
127
|
+
storageApi: targetStorageApi
|
|
124
128
|
});
|
|
125
129
|
return {
|
|
126
130
|
projectId: currentTarget.projectId,
|
|
@@ -139,6 +143,7 @@ function createCliRelatedProjectRuntime(options) {
|
|
|
139
143
|
}
|
|
140
144
|
function createLocalProjectRunner(options) {
|
|
141
145
|
const projectDir = options.projectDir;
|
|
146
|
+
const targetStorageApi = options.storageApi;
|
|
142
147
|
const inspect = targetStorageApi.inspectLocalWorkflowStructure;
|
|
143
148
|
const run = targetStorageApi.runLocalWorkflowWithReport;
|
|
144
149
|
const unwrap = targetStorageApi.readEntrypointOutput;
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
24
24
|
const prepared = prepareCliInvocation(argv);
|
|
25
25
|
argv = prepared.argv;
|
|
26
26
|
if (argv[0] === "web") {
|
|
27
|
-
const webCli = await import("./web-
|
|
27
|
+
const webCli = await import("./web-6SWHMU2A.js");
|
|
28
28
|
return webCli.main(argv.slice(1));
|
|
29
29
|
}
|
|
30
30
|
if (argv[0] === "workspace") {
|
|
@@ -33,7 +33,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
33
33
|
return typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
34
34
|
}
|
|
35
35
|
if (argv[0] === "mcp") {
|
|
36
|
-
const mcpCli = await import("./mcp-
|
|
36
|
+
const mcpCli = await import("./mcp-RPT64F7T.js");
|
|
37
37
|
return mcpCli.main(argv.slice(1));
|
|
38
38
|
}
|
|
39
39
|
if (argv.length === 0 || argv[0] === "help" || argv[0] === "--help" || argv[0] === "-h") {
|
|
@@ -43,7 +43,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
43
43
|
}
|
|
44
44
|
const { register } = await import("tsx/esm/api");
|
|
45
45
|
register();
|
|
46
|
-
const localCli = await import("./local-
|
|
46
|
+
const localCli = await import("./local-XHR2O2FP.js");
|
|
47
47
|
return localCli.main(argv, { localeInitialized: true });
|
|
48
48
|
}
|
|
49
49
|
function formatHelp() {
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
main,
|
|
10
10
|
parseWorkflowArgs,
|
|
11
11
|
readInstalledWorkflowCoreVersion
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5DWX3LL6.js";
|
|
13
13
|
import "./chunk-J2JMC4MZ.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-5FPIZZE4.js";
|
|
15
15
|
import "./chunk-P6K3NB5S.js";
|
|
16
16
|
import "./chunk-7WEXRL5A.js";
|
|
17
17
|
import "./chunk-NSPRIPOP.js";
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
// src/web/related-projects.ts
|
|
2
|
+
import path3 from "node:path";
|
|
3
|
+
|
|
4
|
+
// src/related-projects.ts
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
8
|
+
import * as workflowCode from "workflow-code";
|
|
9
|
+
|
|
10
|
+
// .shared/project-info/index.ts
|
|
11
|
+
var WORKFLOW_PROJECT_DATA_STORAGE_MODES = ["local", "server", "both"];
|
|
12
|
+
var WORKFLOW_RELATED_PROJECT_ALIAS_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
13
|
+
var WORKFLOW_RELATED_PROJECT_LIMIT = 32;
|
|
14
|
+
var WORKFLOW_RELATED_PROJECT_PREFIX_LIMIT = 32;
|
|
15
|
+
var WORKFLOW_RELATED_PROJECT_KEY_LIMIT = 1024;
|
|
16
|
+
var WORKFLOW_PROJECT_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
17
|
+
var PROJECT_INFO_ID_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
18
|
+
function createUndeclaredWorkflowProjectInfo() {
|
|
19
|
+
return {
|
|
20
|
+
localizedNames: {},
|
|
21
|
+
declarations: [],
|
|
22
|
+
platformSupport: { mode: "agnostic" },
|
|
23
|
+
dataStorage: null,
|
|
24
|
+
relatedProjects: []
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function normalizeWorkflowProjectInfo(value) {
|
|
28
|
+
if (!isRecord(value)) {
|
|
29
|
+
throw new Error("workflowCode.projectInfo must be an object.");
|
|
30
|
+
}
|
|
31
|
+
const localizedNames = normalizeLocalizedNames(value["localizedNames"]);
|
|
32
|
+
const declarations = normalizeIds(value["declarations"], "workflowCode.projectInfo.declarations");
|
|
33
|
+
const platformSupport = normalizePlatformSupport(value["platformSupport"]);
|
|
34
|
+
const dataStorage = normalizeDataStorage(value["dataStorage"]);
|
|
35
|
+
const relatedProjects = normalizeRelatedProjects(value["relatedProjects"]);
|
|
36
|
+
return { localizedNames, declarations, platformSupport, dataStorage, relatedProjects };
|
|
37
|
+
}
|
|
38
|
+
function readWorkflowProjectInfo(packageJson) {
|
|
39
|
+
if (!isRecord(packageJson)) return createUndeclaredWorkflowProjectInfo();
|
|
40
|
+
const workflowCode2 = packageJson["workflowCode"];
|
|
41
|
+
if (!isRecord(workflowCode2) || workflowCode2["projectInfo"] === void 0) {
|
|
42
|
+
return createUndeclaredWorkflowProjectInfo();
|
|
43
|
+
}
|
|
44
|
+
const projectInfo = normalizeWorkflowProjectInfo(workflowCode2["projectInfo"]);
|
|
45
|
+
const projectId = typeof packageJson["id"] === "string" ? packageJson["id"].trim() : void 0;
|
|
46
|
+
if (projectId !== void 0 && projectId !== "") {
|
|
47
|
+
assertWorkflowRelatedProjects(projectInfo, projectId);
|
|
48
|
+
}
|
|
49
|
+
return projectInfo;
|
|
50
|
+
}
|
|
51
|
+
function assertWorkflowRelatedProjects(projectInfo, currentProjectId) {
|
|
52
|
+
if (projectInfo.relatedProjects.length === 0) return;
|
|
53
|
+
const normalizedProjectId = currentProjectId.trim();
|
|
54
|
+
if (!WORKFLOW_PROJECT_UUID_PATTERN.test(normalizedProjectId)) {
|
|
55
|
+
throw new Error("package.json.id must be a UUID before related projects can be declared.");
|
|
56
|
+
}
|
|
57
|
+
if (projectInfo.relatedProjects.some(
|
|
58
|
+
(relation) => relation.projectId.toLowerCase() === normalizedProjectId.toLowerCase()
|
|
59
|
+
)) {
|
|
60
|
+
throw new Error("workflowCode.projectInfo.relatedProjects cannot reference the current project.");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function findWorkflowRelatedProject(projectInfo, alias) {
|
|
64
|
+
const normalizedAlias = alias.trim();
|
|
65
|
+
return projectInfo.relatedProjects.find((relation) => relation.alias === normalizedAlias);
|
|
66
|
+
}
|
|
67
|
+
function resolveWorkflowRelatedProjectAccess(input) {
|
|
68
|
+
const consumer = findWorkflowRelatedProject(input.consumerProjectInfo, input.alias);
|
|
69
|
+
if (consumer?.projectId.toLowerCase() !== input.targetProjectId.trim().toLowerCase()) {
|
|
70
|
+
return void 0;
|
|
71
|
+
}
|
|
72
|
+
const target = input.targetProjectInfo.relatedProjects.find(
|
|
73
|
+
(relation) => relation.projectId.toLowerCase() === input.consumerProjectId.trim().toLowerCase()
|
|
74
|
+
);
|
|
75
|
+
if (target === void 0) return void 0;
|
|
76
|
+
return { consumer, target, grant: target.grantToRelatedProject };
|
|
77
|
+
}
|
|
78
|
+
function isWorkflowProjectDataStorageLocationAllowed(projectInfo, location) {
|
|
79
|
+
const mode = projectInfo.dataStorage?.mode;
|
|
80
|
+
return mode === "both" || mode === location;
|
|
81
|
+
}
|
|
82
|
+
function normalizeLocalizedNames(value) {
|
|
83
|
+
if (value === void 0) return {};
|
|
84
|
+
if (!isRecord(value)) {
|
|
85
|
+
throw new Error("workflowCode.projectInfo.localizedNames must be an object.");
|
|
86
|
+
}
|
|
87
|
+
const entries = [];
|
|
88
|
+
for (const [rawLocale, rawName] of Object.entries(value)) {
|
|
89
|
+
const locale = rawLocale.trim();
|
|
90
|
+
if (locale === "") {
|
|
91
|
+
throw new Error("workflowCode.projectInfo.localizedNames contains an empty locale.");
|
|
92
|
+
}
|
|
93
|
+
if (typeof rawName !== "string") {
|
|
94
|
+
throw new Error(`workflowCode.projectInfo.localizedNames.${locale} must be a string.`);
|
|
95
|
+
}
|
|
96
|
+
const name = rawName.trim();
|
|
97
|
+
if (name !== "") entries.push([locale, name]);
|
|
98
|
+
}
|
|
99
|
+
return Object.fromEntries(entries);
|
|
100
|
+
}
|
|
101
|
+
function normalizePlatformSupport(value) {
|
|
102
|
+
if (value === void 0) return { mode: "agnostic" };
|
|
103
|
+
if (!isRecord(value)) {
|
|
104
|
+
throw new Error("workflowCode.projectInfo.platformSupport must be an object.");
|
|
105
|
+
}
|
|
106
|
+
if (value["mode"] === "agnostic") {
|
|
107
|
+
if (value["platforms"] !== void 0) {
|
|
108
|
+
throw new Error("workflowCode.projectInfo.platformSupport.platforms is not allowed in agnostic mode.");
|
|
109
|
+
}
|
|
110
|
+
return { mode: "agnostic" };
|
|
111
|
+
}
|
|
112
|
+
if (value["mode"] !== "specific") {
|
|
113
|
+
throw new Error('workflowCode.projectInfo.platformSupport.mode must be "agnostic" or "specific".');
|
|
114
|
+
}
|
|
115
|
+
const platforms = normalizeIds(
|
|
116
|
+
value["platforms"],
|
|
117
|
+
"workflowCode.projectInfo.platformSupport.platforms"
|
|
118
|
+
);
|
|
119
|
+
if (platforms.length === 0) {
|
|
120
|
+
throw new Error("workflowCode.projectInfo.platformSupport.platforms must contain at least one platform.");
|
|
121
|
+
}
|
|
122
|
+
return { mode: "specific", platforms };
|
|
123
|
+
}
|
|
124
|
+
function normalizeDataStorage(value) {
|
|
125
|
+
if (value === void 0 || value === null) return null;
|
|
126
|
+
if (!isRecord(value)) {
|
|
127
|
+
throw new Error("workflowCode.projectInfo.dataStorage must be an object.");
|
|
128
|
+
}
|
|
129
|
+
const mode = value["mode"];
|
|
130
|
+
if (typeof mode !== "string" || !WORKFLOW_PROJECT_DATA_STORAGE_MODES.includes(
|
|
131
|
+
mode
|
|
132
|
+
)) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
'workflowCode.projectInfo.dataStorage.mode must be "local", "server", or "both".'
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return { mode };
|
|
138
|
+
}
|
|
139
|
+
function normalizeRelatedProjects(value) {
|
|
140
|
+
if (value === void 0) return [];
|
|
141
|
+
if (!Array.isArray(value)) {
|
|
142
|
+
throw new Error("workflowCode.projectInfo.relatedProjects must be an array.");
|
|
143
|
+
}
|
|
144
|
+
if (value.length > WORKFLOW_RELATED_PROJECT_LIMIT) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`workflowCode.projectInfo.relatedProjects supports at most ${WORKFLOW_RELATED_PROJECT_LIMIT} items.`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
150
|
+
const projectIds = /* @__PURE__ */ new Set();
|
|
151
|
+
return value.map((item, index) => {
|
|
152
|
+
const field = `workflowCode.projectInfo.relatedProjects[${index}]`;
|
|
153
|
+
if (!isRecord(item)) throw new Error(`${field} must be an object.`);
|
|
154
|
+
const supportedFields = /* @__PURE__ */ new Set(["alias", "projectId", "grantToRelatedProject"]);
|
|
155
|
+
if (Object.keys(item).some((key) => !supportedFields.has(key))) {
|
|
156
|
+
throw new Error(`${field} contains unsupported fields.`);
|
|
157
|
+
}
|
|
158
|
+
const alias = readRelatedProjectString(item["alias"], `${field}.alias`);
|
|
159
|
+
if (!WORKFLOW_RELATED_PROJECT_ALIAS_PATTERN.test(alias)) {
|
|
160
|
+
throw new Error(`${field}.alias is invalid.`);
|
|
161
|
+
}
|
|
162
|
+
if (aliases.has(alias)) {
|
|
163
|
+
throw new Error(`workflowCode.projectInfo.relatedProjects contains duplicate alias "${alias}".`);
|
|
164
|
+
}
|
|
165
|
+
aliases.add(alias);
|
|
166
|
+
const projectId = readRelatedProjectString(item["projectId"], `${field}.projectId`);
|
|
167
|
+
if (!WORKFLOW_PROJECT_UUID_PATTERN.test(projectId)) {
|
|
168
|
+
throw new Error(`${field}.projectId must be a UUID.`);
|
|
169
|
+
}
|
|
170
|
+
const normalizedProjectId = projectId.toLowerCase();
|
|
171
|
+
if (projectIds.has(normalizedProjectId)) {
|
|
172
|
+
throw new Error(`workflowCode.projectInfo.relatedProjects contains duplicate projectId "${projectId}".`);
|
|
173
|
+
}
|
|
174
|
+
projectIds.add(normalizedProjectId);
|
|
175
|
+
return {
|
|
176
|
+
alias,
|
|
177
|
+
projectId,
|
|
178
|
+
grantToRelatedProject: normalizeRelatedProjectGrant(
|
|
179
|
+
item["grantToRelatedProject"],
|
|
180
|
+
`${field}.grantToRelatedProject`
|
|
181
|
+
)
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function normalizeRelatedProjectGrant(value, field) {
|
|
186
|
+
if (!isRecord(value)) throw new Error(`${field} must be an object.`);
|
|
187
|
+
const supported = /* @__PURE__ */ new Set(["read", "write", "knowledge", "entrypoints"]);
|
|
188
|
+
if (Object.keys(value).some((key) => !supported.has(key))) {
|
|
189
|
+
throw new Error(`${field} contains unsupported fields.`);
|
|
190
|
+
}
|
|
191
|
+
const grant = {
|
|
192
|
+
read: normalizeProjectAccessRule(value["read"], `${field}.read`),
|
|
193
|
+
write: normalizeProjectAccessRule(value["write"], `${field}.write`)
|
|
194
|
+
};
|
|
195
|
+
const knowledge = value["knowledge"];
|
|
196
|
+
if (knowledge !== void 0) {
|
|
197
|
+
if (!isRecord(knowledge)) throw new Error(`${field}.knowledge must be an object.`);
|
|
198
|
+
if (Object.keys(knowledge).some((key) => key !== "read" && key !== "write")) {
|
|
199
|
+
throw new Error(`${field}.knowledge contains unsupported fields.`);
|
|
200
|
+
}
|
|
201
|
+
grant.knowledge = {
|
|
202
|
+
read: normalizeProjectAccessRule(knowledge["read"], `${field}.knowledge.read`),
|
|
203
|
+
write: normalizeProjectAccessRule(knowledge["write"], `${field}.knowledge.write`)
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const entrypoints = value["entrypoints"];
|
|
207
|
+
if (entrypoints !== void 0) {
|
|
208
|
+
grant.entrypoints = normalizeProjectAccessRule(entrypoints, `${field}.entrypoints`);
|
|
209
|
+
}
|
|
210
|
+
return grant;
|
|
211
|
+
}
|
|
212
|
+
function normalizeProjectAccessRule(value, field) {
|
|
213
|
+
if (!isRecord(value)) throw new Error(`${field} must be an object.`);
|
|
214
|
+
const mode = value["mode"];
|
|
215
|
+
if (mode === "none" || mode === "all") {
|
|
216
|
+
if (Object.keys(value).some((key) => key !== "mode")) {
|
|
217
|
+
throw new Error(`${field} contains unsupported fields.`);
|
|
218
|
+
}
|
|
219
|
+
return { mode };
|
|
220
|
+
}
|
|
221
|
+
if (mode !== "prefixes") {
|
|
222
|
+
throw new Error(`${field}.mode must be "none", "all", or "prefixes".`);
|
|
223
|
+
}
|
|
224
|
+
if (Object.keys(value).some((key) => key !== "mode" && key !== "prefixes")) {
|
|
225
|
+
throw new Error(`${field} contains unsupported fields.`);
|
|
226
|
+
}
|
|
227
|
+
const rawPrefixes = value["prefixes"];
|
|
228
|
+
if (!Array.isArray(rawPrefixes) || rawPrefixes.length === 0 || rawPrefixes.length > WORKFLOW_RELATED_PROJECT_PREFIX_LIMIT) {
|
|
229
|
+
throw new Error(
|
|
230
|
+
`${field}.prefixes must contain 1 to ${WORKFLOW_RELATED_PROJECT_PREFIX_LIMIT} items.`
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
const prefixes = rawPrefixes.map((prefix, index) => {
|
|
234
|
+
const normalized = readRelatedProjectString(prefix, `${field}.prefixes[${index}]`);
|
|
235
|
+
if (normalized.length > WORKFLOW_RELATED_PROJECT_KEY_LIMIT || normalized.includes("\0")) {
|
|
236
|
+
throw new Error(`${field}.prefixes[${index}] is invalid.`);
|
|
237
|
+
}
|
|
238
|
+
return normalized;
|
|
239
|
+
});
|
|
240
|
+
if (new Set(prefixes).size !== prefixes.length) {
|
|
241
|
+
throw new Error(`${field}.prefixes contains duplicates.`);
|
|
242
|
+
}
|
|
243
|
+
return { mode: "prefixes", prefixes };
|
|
244
|
+
}
|
|
245
|
+
function readRelatedProjectString(value, field) {
|
|
246
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
247
|
+
throw new Error(`${field} must be a non-empty string.`);
|
|
248
|
+
}
|
|
249
|
+
return value.trim();
|
|
250
|
+
}
|
|
251
|
+
function normalizeIds(value, field) {
|
|
252
|
+
if (value === void 0) return [];
|
|
253
|
+
if (!Array.isArray(value)) throw new Error(`${field} must be an array.`);
|
|
254
|
+
const values = value.map((item, index) => {
|
|
255
|
+
if (typeof item !== "string" || !PROJECT_INFO_ID_PATTERN.test(item.trim())) {
|
|
256
|
+
throw new Error(`${field}[${index}] must be a lowercase identifier.`);
|
|
257
|
+
}
|
|
258
|
+
return item.trim();
|
|
259
|
+
});
|
|
260
|
+
return uniqueStrings(values, true);
|
|
261
|
+
}
|
|
262
|
+
function uniqueStrings(values, caseSensitive) {
|
|
263
|
+
const seen = /* @__PURE__ */ new Set();
|
|
264
|
+
const result = [];
|
|
265
|
+
for (const rawValue of values) {
|
|
266
|
+
const value = rawValue.trim();
|
|
267
|
+
if (value === "") continue;
|
|
268
|
+
const key = caseSensitive ? value : value.toLocaleLowerCase();
|
|
269
|
+
if (seen.has(key)) continue;
|
|
270
|
+
seen.add(key);
|
|
271
|
+
result.push(value);
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
function isRecord(value) {
|
|
276
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// .shared/workflow-ids/index.ts
|
|
280
|
+
var WORKFLOW_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
281
|
+
function isWorkflowUuid(value) {
|
|
282
|
+
return WORKFLOW_UUID_PATTERN.test(value.trim());
|
|
283
|
+
}
|
|
284
|
+
function assertWorkflowUuid(value, label = "workflow id") {
|
|
285
|
+
const normalized = value.trim();
|
|
286
|
+
if (!isWorkflowUuid(normalized)) {
|
|
287
|
+
throw new Error(`Invalid ${label} "${value}".`);
|
|
288
|
+
}
|
|
289
|
+
return normalized;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// src/related-projects.ts
|
|
293
|
+
var defaultStorageApi = workflowCode;
|
|
294
|
+
function createCliRelatedProjectRuntime(options) {
|
|
295
|
+
if (options.relatedProjects.length === 0) return {};
|
|
296
|
+
const targetStorageApi = options.storageApi ?? defaultStorageApi;
|
|
297
|
+
const consumer = readProjectSnapshot(options.consumerProjectDir, "Current project");
|
|
298
|
+
const configuredByAlias = /* @__PURE__ */ new Map();
|
|
299
|
+
const configuredProjectIds = /* @__PURE__ */ new Set();
|
|
300
|
+
const configuredPaths = /* @__PURE__ */ new Set();
|
|
301
|
+
for (const spec of options.relatedProjects) {
|
|
302
|
+
if (configuredByAlias.has(spec.alias)) {
|
|
303
|
+
throw new Error(`Related project alias "${spec.alias}" was specified more than once.`);
|
|
304
|
+
}
|
|
305
|
+
const target = readProjectSnapshot(spec.projectDir, `Related project "${spec.alias}"`);
|
|
306
|
+
const targetProjectId = target.projectId.toLowerCase();
|
|
307
|
+
if (configuredProjectIds.has(targetProjectId)) {
|
|
308
|
+
throw new Error(`Related project UUID "${target.projectId}" was specified more than once.`);
|
|
309
|
+
}
|
|
310
|
+
if (configuredPaths.has(target.projectDir)) {
|
|
311
|
+
throw new Error(`Related project directory "${target.projectDir}" was specified more than once.`);
|
|
312
|
+
}
|
|
313
|
+
assertConfirmedRelationship(consumer, target, spec.alias);
|
|
314
|
+
configuredByAlias.set(spec.alias, target);
|
|
315
|
+
configuredProjectIds.add(targetProjectId);
|
|
316
|
+
configuredPaths.add(target.projectDir);
|
|
317
|
+
}
|
|
318
|
+
const localKvStoreDir = options.localKvStoreDir ?? path.join(os.tmpdir(), "workflow-code-kv");
|
|
319
|
+
const localPersistentValueStoreDir = options.localPersistentValueStoreDir;
|
|
320
|
+
const localKvStore = targetStorageApi.createLocalWorkflowKVStore({
|
|
321
|
+
rootDir: localKvStoreDir,
|
|
322
|
+
storageKind: "kv"
|
|
323
|
+
});
|
|
324
|
+
const localPersistentValueStore = typeof targetStorageApi.createWorkflowPersistentValueContext === "function" && localPersistentValueStoreDir !== void 0 ? targetStorageApi.createLocalWorkflowKVStore({
|
|
325
|
+
rootDir: localPersistentValueStoreDir,
|
|
326
|
+
storageKind: "persistent_value"
|
|
327
|
+
}) : void 0;
|
|
328
|
+
return {
|
|
329
|
+
localKvStore,
|
|
330
|
+
localResolver: createResolver("local", localKvStore, localPersistentValueStore),
|
|
331
|
+
serverResolver: createResolver("server")
|
|
332
|
+
};
|
|
333
|
+
function createResolver(location, fixedStore, fixedPersistentValueStore) {
|
|
334
|
+
return {
|
|
335
|
+
resolve(alias) {
|
|
336
|
+
const configured = configuredByAlias.get(alias);
|
|
337
|
+
if (configured === void 0) return void 0;
|
|
338
|
+
const currentConsumer = readProjectSnapshot(consumer.projectDir, "Current project");
|
|
339
|
+
const currentTarget = readProjectSnapshot(
|
|
340
|
+
configured.projectDir,
|
|
341
|
+
`Related project "${alias}"`
|
|
342
|
+
);
|
|
343
|
+
if (currentConsumer.projectId.toLowerCase() !== consumer.projectId.toLowerCase() || currentTarget.projectId.toLowerCase() !== configured.projectId.toLowerCase()) {
|
|
344
|
+
return void 0;
|
|
345
|
+
}
|
|
346
|
+
const access = resolveWorkflowRelatedProjectAccess({
|
|
347
|
+
consumerProjectId: currentConsumer.projectId,
|
|
348
|
+
consumerProjectInfo: currentConsumer.projectInfo,
|
|
349
|
+
targetProjectId: currentTarget.projectId,
|
|
350
|
+
targetProjectInfo: currentTarget.projectInfo,
|
|
351
|
+
alias
|
|
352
|
+
});
|
|
353
|
+
if (access === void 0 || !isWorkflowProjectDataStorageLocationAllowed(currentTarget.projectInfo, location)) {
|
|
354
|
+
return void 0;
|
|
355
|
+
}
|
|
356
|
+
const createRemoteStore = targetStorageApi.createRemoteWorkflowRelatedProjectKVStoreFromEnv;
|
|
357
|
+
if (fixedStore === void 0 && typeof createRemoteStore !== "function") {
|
|
358
|
+
throw new Error("Installed workflow-code does not support related project storage.");
|
|
359
|
+
}
|
|
360
|
+
const roots = options.localStorageForProject?.(currentTarget.projectDir) ?? { kvStoreDir: localKvStoreDir, persistentValueStoreDir: localPersistentValueStoreDir };
|
|
361
|
+
const store = location === "local" && options.localStorageForProject ? targetStorageApi.createLocalWorkflowKVStore({ rootDir: roots.kvStoreDir, storageKind: "kv" }) : fixedStore ?? createRemoteStore({
|
|
362
|
+
consumerProjectId: currentConsumer.projectId,
|
|
363
|
+
targetProjectId: currentTarget.projectId,
|
|
364
|
+
alias,
|
|
365
|
+
env: options.env
|
|
366
|
+
});
|
|
367
|
+
if (store === void 0) return void 0;
|
|
368
|
+
const source = {
|
|
369
|
+
projectId: currentConsumer.projectId,
|
|
370
|
+
runId: options.runId,
|
|
371
|
+
conversationId: options.conversationId
|
|
372
|
+
};
|
|
373
|
+
const persistentStore = location === "server" ? store : options.localStorageForProject && roots.persistentValueStoreDir !== void 0 ? targetStorageApi.createLocalWorkflowKVStore({ rootDir: roots.persistentValueStoreDir, storageKind: "persistent_value" }) : fixedPersistentValueStore;
|
|
374
|
+
const persistentValue = persistentStore === void 0 ? void 0 : targetStorageApi.createWorkflowPersistentValueContext?.({
|
|
375
|
+
store: persistentStore,
|
|
376
|
+
projectId: currentTarget.projectId,
|
|
377
|
+
source
|
|
378
|
+
});
|
|
379
|
+
const runner = createLocalProjectRunner({
|
|
380
|
+
projectDir: currentTarget.projectDir,
|
|
381
|
+
// Where the target keeps its data decides which store its own run
|
|
382
|
+
// uses: a project that lives on the server runs against the server,
|
|
383
|
+
// exactly as it would if its author started it here.
|
|
384
|
+
location,
|
|
385
|
+
// The roots settled above, not the raw options: the relation and the
|
|
386
|
+
// target's own run have to land on the same store, defaults
|
|
387
|
+
// included, or one side writes what the other cannot see.
|
|
388
|
+
kvStoreDir: roots.kvStoreDir,
|
|
389
|
+
persistentValueStoreDir: roots.persistentValueStoreDir,
|
|
390
|
+
storageApi: targetStorageApi
|
|
391
|
+
});
|
|
392
|
+
return {
|
|
393
|
+
projectId: currentTarget.projectId,
|
|
394
|
+
grant: access.grant,
|
|
395
|
+
kv: targetStorageApi.createWorkflowKVContext({
|
|
396
|
+
store,
|
|
397
|
+
projectId: currentTarget.projectId,
|
|
398
|
+
source
|
|
399
|
+
}),
|
|
400
|
+
...persistentValue === void 0 ? {} : { persistentValue },
|
|
401
|
+
...runner === void 0 ? {} : { runner }
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function createLocalProjectRunner(options) {
|
|
408
|
+
const projectDir = options.projectDir;
|
|
409
|
+
const targetStorageApi = options.storageApi;
|
|
410
|
+
const inspect = targetStorageApi.inspectLocalWorkflowStructure;
|
|
411
|
+
const run = targetStorageApi.runLocalWorkflowWithReport;
|
|
412
|
+
const unwrap = targetStorageApi.readEntrypointOutput;
|
|
413
|
+
if (typeof inspect !== "function" || typeof run !== "function" || typeof unwrap !== "function") {
|
|
414
|
+
return void 0;
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
async listEntrypoints() {
|
|
418
|
+
const structure = inspect({ workflowDir: projectDir });
|
|
419
|
+
return (structure.entrypoints ?? []).map((entrypoint) => ({
|
|
420
|
+
id: entrypoint.id,
|
|
421
|
+
...entrypoint.title === void 0 ? {} : { title: entrypoint.title },
|
|
422
|
+
...entrypoint.description === void 0 ? {} : { description: entrypoint.description }
|
|
423
|
+
}));
|
|
424
|
+
},
|
|
425
|
+
async run(entrypointId, args) {
|
|
426
|
+
const report = await run({
|
|
427
|
+
workflowDir: projectDir,
|
|
428
|
+
entrypointId,
|
|
429
|
+
args: [...args],
|
|
430
|
+
storage: options.location === "server" ? { host: "server" } : {
|
|
431
|
+
host: "local",
|
|
432
|
+
local: {
|
|
433
|
+
kvStoreDir: options.kvStoreDir,
|
|
434
|
+
persistentValueStoreDir: options.persistentValueStoreDir
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
if (report.result === void 0) {
|
|
439
|
+
throw new Error(`Related project entrypoint "${entrypointId}" returned no result.`);
|
|
440
|
+
}
|
|
441
|
+
return unwrap(report.result.data);
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function assertConfirmedRelationship(consumer, target, alias) {
|
|
446
|
+
const consumerRelation = consumer.projectInfo.relatedProjects.find(
|
|
447
|
+
(relation) => relation.alias === alias
|
|
448
|
+
);
|
|
449
|
+
if (consumerRelation?.projectId.toLowerCase() !== target.projectId.toLowerCase()) {
|
|
450
|
+
throw new Error(
|
|
451
|
+
`Current project does not declare related project "${alias}" with UUID "${target.projectId}".`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
if (resolveWorkflowRelatedProjectAccess({
|
|
455
|
+
consumerProjectId: consumer.projectId,
|
|
456
|
+
consumerProjectInfo: consumer.projectInfo,
|
|
457
|
+
targetProjectId: target.projectId,
|
|
458
|
+
targetProjectInfo: target.projectInfo,
|
|
459
|
+
alias
|
|
460
|
+
}) === void 0) {
|
|
461
|
+
throw new Error(`Related project "${alias}" is not confirmed by both project manifests.`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
function readProjectSnapshot(projectDir, label) {
|
|
465
|
+
let canonicalDir;
|
|
466
|
+
try {
|
|
467
|
+
canonicalDir = realpathSync(projectDir);
|
|
468
|
+
if (!statSync(canonicalDir).isDirectory()) {
|
|
469
|
+
throw new Error("not a directory");
|
|
470
|
+
}
|
|
471
|
+
} catch (error) {
|
|
472
|
+
throw new Error(`${label} directory is unavailable: ${projectDir}`, { cause: error });
|
|
473
|
+
}
|
|
474
|
+
const packagePath = path.join(canonicalDir, "package.json");
|
|
475
|
+
let packageJson;
|
|
476
|
+
try {
|
|
477
|
+
packageJson = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
478
|
+
} catch (error) {
|
|
479
|
+
throw new Error(`${label} must contain a readable package.json: ${canonicalDir}`, {
|
|
480
|
+
cause: error
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
if (!isRecord2(packageJson) || typeof packageJson["id"] !== "string") {
|
|
484
|
+
throw new Error(`${label} package.json.id must be a UUID.`);
|
|
485
|
+
}
|
|
486
|
+
const projectId = assertWorkflowUuid(packageJson["id"], `${label} package.json.id`);
|
|
487
|
+
const projectInfo = readWorkflowProjectInfo(packageJson);
|
|
488
|
+
if (projectInfo.dataStorage === null) {
|
|
489
|
+
throw new Error(`${label} must declare workflowCode.projectInfo.dataStorage.mode.`);
|
|
490
|
+
}
|
|
491
|
+
return { projectDir: canonicalDir, projectId, projectInfo };
|
|
492
|
+
}
|
|
493
|
+
function isRecord2(value) {
|
|
494
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// src/web/kanban-data.ts
|
|
498
|
+
import { createHash } from "node:crypto";
|
|
499
|
+
import path2 from "node:path";
|
|
500
|
+
|
|
501
|
+
// .shared/kanban-project/index.ts
|
|
502
|
+
var KANBAN_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
503
|
+
|
|
504
|
+
// src/web/kanban-data.ts
|
|
505
|
+
var webProjectDataDirectory = (storageDir, projectDir) => path2.join(storageDir, createHash("sha256").update(projectDir).digest("hex").slice(0, 24));
|
|
506
|
+
|
|
507
|
+
// src/web/related-projects.ts
|
|
508
|
+
function createWebRelatedProjectRuntime(core, options) {
|
|
509
|
+
const roots = (projectDir) => {
|
|
510
|
+
const directory = webProjectDataDirectory(options.storageDir, projectDir);
|
|
511
|
+
return { kvStoreDir: path3.join(directory, "kv"), persistentValueStoreDir: path3.join(directory, "values") };
|
|
512
|
+
};
|
|
513
|
+
const local = roots(options.projectDir);
|
|
514
|
+
return createCliRelatedProjectRuntime({
|
|
515
|
+
consumerProjectDir: options.projectDir,
|
|
516
|
+
relatedProjects: options.relatedProjects,
|
|
517
|
+
localKvStoreDir: local.kvStoreDir,
|
|
518
|
+
localPersistentValueStoreDir: local.persistentValueStoreDir,
|
|
519
|
+
localStorageForProject: roots,
|
|
520
|
+
storageApi: core,
|
|
521
|
+
runId: options.runId,
|
|
522
|
+
conversationId: options.conversationId,
|
|
523
|
+
env: process.env
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
export {
|
|
527
|
+
createWebRelatedProjectRuntime
|
|
528
|
+
};
|
package/dist/web/worker.mjs
CHANGED
|
@@ -123,6 +123,13 @@ try {
|
|
|
123
123
|
process.env.WORKFLOW_DEVELOPER_ASSISTANT_WORKSPACE_MANIFEST = manifestPath;
|
|
124
124
|
}
|
|
125
125
|
const storage = { host: 'local', local: { kvStoreDir: path.join(dataDir, 'kv'), persistentValueStoreDir: path.join(dataDir, 'values') } };
|
|
126
|
+
if (request.method === 'run' || request.method === 'resolve') {
|
|
127
|
+
const { createWebRelatedProjectRuntime } = await import(new URL(import.meta.url.includes('/src/web/') ? './related-projects.ts' : './related-projects.mjs', import.meta.url));
|
|
128
|
+
const related = createWebRelatedProjectRuntime(core, { projectDir, storageDir: request.storageDir,
|
|
129
|
+
relatedProjects: request.relatedProjects ?? [], runId: request.runId, conversationId: request.conversationId });
|
|
130
|
+
storage.local.relatedProjectResolver = related.localResolver;
|
|
131
|
+
storage.server = { relatedProjectResolver: related.serverResolver };
|
|
132
|
+
}
|
|
126
133
|
const filesDir = path.join(dataDir, 'files');
|
|
127
134
|
const createdFiles = [];
|
|
128
135
|
const managed = createServerWorkflowFileStore({ rootDir: filesDir, workflowName: request.project.id, conversationId: request.conversationId });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
assertLocalCliCoreCompatible
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5DWX3LL6.js";
|
|
5
5
|
import {
|
|
6
6
|
assertKanbanMethodJson,
|
|
7
7
|
consumeKanbanRelatedProjectRevisionStream,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
sanitizeKanbanValues
|
|
22
22
|
} from "./chunk-HLMW6LAQ.js";
|
|
23
23
|
import "./chunk-J2JMC4MZ.js";
|
|
24
|
-
import "./chunk-
|
|
24
|
+
import "./chunk-5FPIZZE4.js";
|
|
25
25
|
import {
|
|
26
26
|
clearCliAuthConfig,
|
|
27
27
|
createEmptyWorkflowAuthConfig,
|
|
@@ -2485,7 +2485,7 @@ function cliRoot() {
|
|
|
2485
2485
|
}
|
|
2486
2486
|
throw new Error("Cannot locate the CLI installation.");
|
|
2487
2487
|
}
|
|
2488
|
-
function createWebRuntime(projectDir, storageDir, connection) {
|
|
2488
|
+
function createWebRuntime(projectDir, storageDir, connection, relatedProjects = () => []) {
|
|
2489
2489
|
const root = cliRoot();
|
|
2490
2490
|
const builtWorker = path5.join(root, "dist/web/worker.mjs");
|
|
2491
2491
|
const worker = existsSync(builtWorker) ? builtWorker : path5.join(root, "src/web/worker.mjs");
|
|
@@ -2597,7 +2597,7 @@ function createWebRuntime(projectDir, storageDir, connection) {
|
|
|
2597
2597
|
}
|
|
2598
2598
|
});
|
|
2599
2599
|
child.stdin.on("error", () => void 0);
|
|
2600
|
-
child.stdin.end(JSON.stringify({ ...request, storageDir, runtimeProjectDir: projectDir }));
|
|
2600
|
+
child.stdin.end(JSON.stringify({ ...request, storageDir, runtimeProjectDir: projectDir, relatedProjects: relatedProjects() }));
|
|
2601
2601
|
});
|
|
2602
2602
|
return {
|
|
2603
2603
|
available: true,
|
|
@@ -2735,7 +2735,8 @@ async function startWebServer(options) {
|
|
|
2735
2735
|
let authenticationInitialized = false;
|
|
2736
2736
|
let authCheck;
|
|
2737
2737
|
const sensitiveTokens = /* @__PURE__ */ new Set();
|
|
2738
|
-
|
|
2738
|
+
let relatedProjects = options.host?.relatedProjects ?? [];
|
|
2739
|
+
const runtime = options.runtime ?? createWebRuntime(projectDir, storageDir, () => connection, () => relatedProjects);
|
|
2739
2740
|
let inspected;
|
|
2740
2741
|
try {
|
|
2741
2742
|
inspected = await inspectWebProject(runtime, projectDir, options.host);
|
|
@@ -3448,6 +3449,9 @@ ${token}`;
|
|
|
3448
3449
|
controller,
|
|
3449
3450
|
workflowController,
|
|
3450
3451
|
kanbanController,
|
|
3452
|
+
setHostRelatedProjects: (value) => {
|
|
3453
|
+
relatedProjects = value;
|
|
3454
|
+
},
|
|
3451
3455
|
setHostConnection: async (value) => {
|
|
3452
3456
|
authEpoch++;
|
|
3453
3457
|
authCheck?.abort();
|
|
@@ -3486,6 +3490,23 @@ import { createInterface } from "readline";
|
|
|
3486
3490
|
|
|
3487
3491
|
// src/web/host-config.ts
|
|
3488
3492
|
import path7 from "path";
|
|
3493
|
+
function parseHostRelatedProjects(value) {
|
|
3494
|
+
if (value === void 0) {
|
|
3495
|
+
return [];
|
|
3496
|
+
}
|
|
3497
|
+
if (!Array.isArray(value) || value.length > 100) {
|
|
3498
|
+
throw new Error("Invalid host related projects.");
|
|
3499
|
+
}
|
|
3500
|
+
const aliases = /* @__PURE__ */ new Set(), directories = /* @__PURE__ */ new Set();
|
|
3501
|
+
return value.map((project) => {
|
|
3502
|
+
if (!project || typeof project.alias !== "string" || !/^[a-z][a-z0-9_-]{0,63}$/.test(project.alias) || typeof project.projectDir !== "string" || !path7.isAbsolute(project.projectDir) || aliases.has(project.alias) || directories.has(project.projectDir)) {
|
|
3503
|
+
throw new Error("Invalid host related projects.");
|
|
3504
|
+
}
|
|
3505
|
+
aliases.add(project.alias);
|
|
3506
|
+
directories.add(project.projectDir);
|
|
3507
|
+
return { alias: project.alias, projectDir: project.projectDir };
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3489
3510
|
function parseHostConnection(value) {
|
|
3490
3511
|
if (value === null || value === void 0) {
|
|
3491
3512
|
return;
|
|
@@ -3519,7 +3540,13 @@ function parseHostConfiguration(value) {
|
|
|
3519
3540
|
if (configuration.surface !== "assistant" && (assistant || assistantProjectDir !== void 0)) {
|
|
3520
3541
|
throw new Error("Assistant configuration requires the assistant surface.");
|
|
3521
3542
|
}
|
|
3522
|
-
return {
|
|
3543
|
+
return {
|
|
3544
|
+
surface: configuration.surface,
|
|
3545
|
+
assistant,
|
|
3546
|
+
assistantProjectDir,
|
|
3547
|
+
connection: parseHostConnection(configuration.connection),
|
|
3548
|
+
relatedProjects: parseHostRelatedProjects(configuration.relatedProjects)
|
|
3549
|
+
};
|
|
3523
3550
|
}
|
|
3524
3551
|
|
|
3525
3552
|
// src/web.ts
|
|
@@ -3613,7 +3640,7 @@ async function main(argv) {
|
|
|
3613
3640
|
};
|
|
3614
3641
|
process.once("SIGINT", close);
|
|
3615
3642
|
process.once("SIGTERM", close);
|
|
3616
|
-
console.log(options.json ? JSON.stringify({ type: "ready", protocolVersion: 1, hostProtocolVersion: 1, accountProtocolVersion: 1, traceProtocolVersion: 1, assistantProtocolVersion: host?.assistant ? ASSISTANT_PROTOCOL_VERSION : void 0, url: app.url, project: { id: app.project.id, name: app.project.name, projectType: app.project.projectType }, runtime: app.project.runtime }) : `Workflow Web: ${app.url}`);
|
|
3643
|
+
console.log(options.json ? JSON.stringify({ type: "ready", protocolVersion: 1, hostProtocolVersion: 1, accountProtocolVersion: 1, relatedProjectsProtocolVersion: 1, traceProtocolVersion: 1, assistantProtocolVersion: host?.assistant ? ASSISTANT_PROTOCOL_VERSION : void 0, url: app.url, project: { id: app.project.id, name: app.project.name, projectType: app.project.projectType }, runtime: app.project.runtime }) : `Workflow Web: ${app.url}`);
|
|
3617
3644
|
if (lines) {
|
|
3618
3645
|
void (async () => {
|
|
3619
3646
|
try {
|
|
@@ -3628,6 +3655,8 @@ async function main(argv) {
|
|
|
3628
3655
|
process.exitCode = 1;
|
|
3629
3656
|
close();
|
|
3630
3657
|
});
|
|
3658
|
+
} else if (message.type === "related-projects") {
|
|
3659
|
+
app.setHostRelatedProjects(parseHostRelatedProjects(message.relatedProjects));
|
|
3631
3660
|
} else if (message.type === "close") {
|
|
3632
3661
|
break;
|
|
3633
3662
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workflow-code/cli",
|
|
3
|
-
"version": "0.2.4-
|
|
3
|
+
"version": "0.2.4-20261012005.codex-studio-integration",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"workflow-code": "./dist/index.js"
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"typescript": "^6.0.3",
|
|
37
37
|
"vitest": "^4.1.7",
|
|
38
38
|
"workflow-code": "0.2.4-20260929001",
|
|
39
|
+
"@workflow-code/auth-config": "0.1.0",
|
|
39
40
|
"@workflow-code/execution-targets": "0.1.0",
|
|
40
41
|
"@workflow-code/i18n": "0.1.0",
|
|
41
42
|
"@workflow-code/kanban-project": "0.1.0",
|
|
42
43
|
"@workflow-code/openai-responses": "0.1.0",
|
|
43
44
|
"@workflow-code/project-dependencies": "0.1.0",
|
|
44
45
|
"@workflow-code/project-info": "0.1.0",
|
|
45
|
-
"@workflow-code/runtime-compatibility": "0.1.0",
|
|
46
46
|
"@workflow-code/project-upload": "0.1.0",
|
|
47
|
-
"@workflow-code/
|
|
47
|
+
"@workflow-code/runtime-compatibility": "0.1.0",
|
|
48
48
|
"@workflow-code/workflow-ids": "0.1.0",
|
|
49
|
-
"@workflow-code/
|
|
49
|
+
"@workflow-code/workflow-mcp": "0.1.0"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"bootstrap": "node scripts/bootstrap.mjs",
|