@workflow-code/cli 0.2.4-20261012006.codex-studio-integration → 0.2.4-20261013001.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/index.js +1 -1
- package/dist/web/kanban-data.mjs +18 -2
- package/dist/web/kanban-workspace.css +76 -10
- package/dist/web/kanban-workspace.js +119 -8
- package/dist/web/resource-preview.css +2172 -0
- package/dist/web/resource-preview.js +16518 -0
- package/dist/web/worker.mjs +7 -6
- package/dist/web/workflow-ui.css +76 -10
- package/dist/web/workflow-ui.js +251 -27
- package/dist/web/workflow-workspace.css +76 -10
- package/dist/web/workflow-workspace.js +247 -27
- package/dist/{web-FDREEISF.js → web-JXC3WIJK.js} +534 -170
- package/package.json +2 -2
package/dist/web/worker.mjs
CHANGED
|
@@ -76,7 +76,7 @@ try {
|
|
|
76
76
|
} = await import(coreUrl);
|
|
77
77
|
const core = await import(coreUrl);
|
|
78
78
|
const language = /^zh/i.test(process.env[core.WORKFLOW_RUNTIME_LOCALE_ENV] ?? process.env.WORKFLOW_CODE_LOCALE ?? 'en') ? 'zh-CN' : 'en';
|
|
79
|
-
const {
|
|
79
|
+
const { readWorkflowProjectInfo, resolveWorkflowProjectName, runKanbanDataCall } = await import(new URL(import.meta.url.includes('/src/web/') ? './kanban-data.ts' : './kanban-data.mjs', import.meta.url));
|
|
80
80
|
if (request.method === 'inspect') {
|
|
81
81
|
const projects = [];
|
|
82
82
|
const errors = [];
|
|
@@ -84,12 +84,13 @@ try {
|
|
|
84
84
|
try {
|
|
85
85
|
const pkg = JSON.parse(readFileSync(path.join(folderPath, 'package.json'), 'utf8'));
|
|
86
86
|
const structure = inspectLocalWorkflowStructure({ workflowDir: folderPath });
|
|
87
|
+
const projectInfo = readWorkflowProjectInfo(pkg);
|
|
87
88
|
const parameters = (entry) => ({ fields: entry.params ?? [], paramLayout: entry.paramLayout, paramResolver: entry.paramResolver, tools: entry.tools, tokenUsage: entry.tokenUsage });
|
|
88
89
|
projects.push({
|
|
89
90
|
id: pkg.id,
|
|
90
91
|
runtime: { coreVersion: coreManifest.version, corePath },
|
|
91
92
|
folderPath,
|
|
92
|
-
name: pkg.
|
|
93
|
+
name: resolveWorkflowProjectName(pkg.name ?? path.basename(folderPath), projectInfo, language),
|
|
93
94
|
projectType: structure.projectType,
|
|
94
95
|
...parameters(structure),
|
|
95
96
|
entrypoints: (structure.entrypoints ?? []).map((entry) => ({ id: entry.id, title: entry.title, group: entry.group, description: entry.description, execution: entry.execution, ...parameters(entry) })),
|
|
@@ -99,7 +100,7 @@ try {
|
|
|
99
100
|
defaultEntrypoint: structure.defaultEntrypoint,
|
|
100
101
|
artifactEntry: structure.kanban ? createKanbanArtifactEntryPath(structure.kanban) : undefined,
|
|
101
102
|
kanban: structure.kanban ? { artifactDir: structure.kanban.artifactDir, entry: structure.kanban.entry } : undefined,
|
|
102
|
-
projectInfo
|
|
103
|
+
projectInfo,
|
|
103
104
|
conversation: structure.conversation,
|
|
104
105
|
requiresLogin: await requiresSystemAi(folderPath),
|
|
105
106
|
});
|
|
@@ -214,14 +215,14 @@ try {
|
|
|
214
215
|
const rootDir = request.kind === 'knowledge' ? path.join(dataDir, 'values') : path.join(dataDir, 'kv');
|
|
215
216
|
const store = createLocalWorkflowKVStore({ rootDir, storageKind: request.kind === 'knowledge' ? 'persistent_value' : 'kv' });
|
|
216
217
|
const context = request.kind === 'knowledge'
|
|
217
|
-
? createWorkflowPersistentValueContext({ store, projectId: request.project.id, conversationId: request.conversationId })
|
|
218
|
-
: createWorkflowKVContext({ store, projectId: request.project.id, conversationId: request.conversationId });
|
|
218
|
+
? createWorkflowPersistentValueContext({ store, projectId: request.project.id, conversationId: target.conversationId ?? request.conversationId })
|
|
219
|
+
: createWorkflowKVContext({ store, projectId: request.project.id, conversationId: target.conversationId ?? request.conversationId });
|
|
219
220
|
if (request.kind === 'knowledge') {
|
|
220
221
|
send('result', target.documentId ? await getKnowledgeDocument({ persistentValue: context }, target.documentId) : await listKnowledgeDocuments({ persistentValue: context }));
|
|
221
222
|
} else if (target.key) {
|
|
222
223
|
send('result', await (target.scope === 'conversation' ? context.conversation : context).getValue(target.key) ?? null);
|
|
223
224
|
} else {
|
|
224
|
-
send('result', await listLocalWorkflowKVEntries({ rootDir, storageKind: 'kv', projectId: request.project.id, scope: target.scope === 'conversation' ? 'conversation' : 'project', conversationId: target.scope === 'conversation' ? request.conversationId : undefined, pageSize: 100 }));
|
|
225
|
+
send('result', await listLocalWorkflowKVEntries({ rootDir, storageKind: 'kv', projectId: request.project.id, scope: target.scope === 'conversation' ? 'conversation' : 'project', conversationId: target.scope === 'conversation' ? target.conversationId ?? request.conversationId : undefined, pageSize: 100 }));
|
|
225
226
|
}
|
|
226
227
|
} else if (request.method === 'delete-conversation') {
|
|
227
228
|
for (const [storageKind, rootDir] of [['kv', path.join(dataDir, 'kv')], ['persistent_value', path.join(dataDir, 'values')]]) {
|
package/dist/web/workflow-ui.css
CHANGED
|
@@ -1072,23 +1072,89 @@ main {
|
|
|
1072
1072
|
margin-top: 12px;
|
|
1073
1073
|
}
|
|
1074
1074
|
.resource-card {
|
|
1075
|
-
display:
|
|
1076
|
-
|
|
1077
|
-
gap: 8px;
|
|
1075
|
+
display: block;
|
|
1076
|
+
width: 100%;
|
|
1078
1077
|
min-width: 0;
|
|
1079
|
-
|
|
1080
|
-
min-height: 36px;
|
|
1081
|
-
padding: 6px 10px;
|
|
1078
|
+
margin: 8px 0;
|
|
1082
1079
|
border: 1px solid var(--border);
|
|
1083
1080
|
border-radius: 6px;
|
|
1084
1081
|
background: var(--vscode-editor-background);
|
|
1082
|
+
overflow: hidden;
|
|
1083
|
+
container-type: inline-size;
|
|
1084
|
+
}
|
|
1085
|
+
.resource-card-row {
|
|
1086
|
+
display: flex;
|
|
1087
|
+
align-items: center;
|
|
1088
|
+
gap: 4px;
|
|
1089
|
+
min-height: 44px;
|
|
1090
|
+
padding: 4px 8px;
|
|
1091
|
+
}
|
|
1092
|
+
.resource-target {
|
|
1093
|
+
display: flex;
|
|
1094
|
+
align-items: center;
|
|
1095
|
+
gap: 10px;
|
|
1096
|
+
flex: 1;
|
|
1097
|
+
min-width: 0;
|
|
1098
|
+
min-height: 36px;
|
|
1099
|
+
padding: 6px 4px;
|
|
1100
|
+
border: 0;
|
|
1101
|
+
background: transparent;
|
|
1085
1102
|
text-align: left;
|
|
1086
1103
|
}
|
|
1087
|
-
.resource-
|
|
1104
|
+
.resource-target > .codicon {
|
|
1105
|
+
flex: none;
|
|
1106
|
+
color: var(--muted);
|
|
1107
|
+
}
|
|
1108
|
+
.resource-title {
|
|
1088
1109
|
min-width: 0;
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1110
|
+
white-space: normal;
|
|
1111
|
+
overflow-wrap: anywhere;
|
|
1112
|
+
line-height: 1.5;
|
|
1113
|
+
}
|
|
1114
|
+
.resource-card-row > .icon-button {
|
|
1115
|
+
flex: none;
|
|
1116
|
+
width: 28px;
|
|
1117
|
+
height: 28px;
|
|
1118
|
+
}
|
|
1119
|
+
@container (max-width: 280px) {
|
|
1120
|
+
.resource-card-row {
|
|
1121
|
+
flex-wrap: wrap;
|
|
1122
|
+
}
|
|
1123
|
+
.resource-target {
|
|
1124
|
+
flex-basis: 100%;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
.resource-inline {
|
|
1128
|
+
height: 360px;
|
|
1129
|
+
max-height: 70vh;
|
|
1130
|
+
min-height: 160px;
|
|
1131
|
+
border-top: 1px solid var(--border);
|
|
1132
|
+
overflow: auto;
|
|
1133
|
+
}
|
|
1134
|
+
.resource-inline[role] {
|
|
1135
|
+
padding: 12px;
|
|
1136
|
+
color: var(--muted);
|
|
1137
|
+
}
|
|
1138
|
+
.resource-inline[role=alert] {
|
|
1139
|
+
color: var(--vscode-errorForeground);
|
|
1140
|
+
}
|
|
1141
|
+
.resource-inline iframe {
|
|
1142
|
+
display: block;
|
|
1143
|
+
width: 100%;
|
|
1144
|
+
height: 100%;
|
|
1145
|
+
border: 0;
|
|
1146
|
+
}
|
|
1147
|
+
.resource-call-details {
|
|
1148
|
+
padding: 8px 12px;
|
|
1149
|
+
border-top: 1px solid var(--border);
|
|
1150
|
+
max-height: 320px;
|
|
1151
|
+
overflow: auto;
|
|
1152
|
+
}
|
|
1153
|
+
.resource-call-details pre {
|
|
1154
|
+
margin: 0;
|
|
1155
|
+
font-size: 11px;
|
|
1156
|
+
white-space: pre-wrap;
|
|
1157
|
+
overflow-wrap: anywhere;
|
|
1092
1158
|
}
|
|
1093
1159
|
.input-prompt {
|
|
1094
1160
|
margin: 16px 0;
|
package/dist/web/workflow-ui.js
CHANGED
|
@@ -12885,7 +12885,33 @@
|
|
|
12885
12885
|
"Write file": "\u5199\u5165\u6587\u4EF6",
|
|
12886
12886
|
Yes: "\u662F",
|
|
12887
12887
|
"Zoom in": "\u653E\u5927",
|
|
12888
|
-
"Zoom out": "\u7F29\u5C0F"
|
|
12888
|
+
"Zoom out": "\u7F29\u5C0F",
|
|
12889
|
+
"Open resource": "\u6253\u5F00\u8D44\u6E90",
|
|
12890
|
+
"Show in conversation": "\u5728\u5BF9\u8BDD\u4E2D\u5C55\u793A",
|
|
12891
|
+
"Hide preview": "\u6536\u8D77\u9884\u89C8",
|
|
12892
|
+
"Open in new window": "\u5728\u65B0\u7A97\u53E3\u4E2D\u6253\u5F00",
|
|
12893
|
+
"Tool call details": "\u5DE5\u5177\u8C03\u7528\u8BE6\u60C5",
|
|
12894
|
+
"Please sign in to preview this server resource.": "\u8BF7\u767B\u5F55\u540E\u9884\u89C8\u670D\u52A1\u5668\u8D44\u6E90\u3002",
|
|
12895
|
+
"You do not have access to this resource.": "\u4F60\u6CA1\u6709\u6B64\u8D44\u6E90\u7684\u8BBF\u95EE\u6743\u9650\u3002",
|
|
12896
|
+
"The resource project is unavailable.": "\u8D44\u6E90\u6240\u5C5E\u9879\u76EE\u4E0D\u53EF\u7528\u3002",
|
|
12897
|
+
"The resource project is unavailable. Import or open the target project first.": "\u8D44\u6E90\u6240\u5C5E\u9879\u76EE\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5148\u5BFC\u5165\u6216\u6253\u5F00\u76EE\u6807\u9879\u76EE\u3002",
|
|
12898
|
+
"The project does not allow this storage location.": "\u9879\u76EE\u4E0D\u5141\u8BB8\u4F7F\u7528\u6B64\u5B58\u50A8\u4F4D\u7F6E\u3002",
|
|
12899
|
+
"This resource no longer exists.": "\u6B64\u8D44\u6E90\u5DF2\u4E0D\u5B58\u5728\u3002",
|
|
12900
|
+
"Server source files cannot be previewed by this card.": "\u6B64\u5361\u7247\u4E0D\u652F\u6301\u9884\u89C8\u670D\u52A1\u5668\u6E90\u7801\u6587\u4EF6\u3002",
|
|
12901
|
+
"File is outside this project.": "\u6587\u4EF6\u4E0D\u5728\u6B64\u9879\u76EE\u4E2D\u3002",
|
|
12902
|
+
"File preview exceeds 2 MiB.": "\u6587\u4EF6\u9884\u89C8\u5927\u5C0F\u8D85\u8FC7 2 MiB\u3002",
|
|
12903
|
+
"This project does not provide a Kanban preview.": "\u6B64\u9879\u76EE\u4E0D\u63D0\u4F9B\u770B\u677F\u9884\u89C8\u3002",
|
|
12904
|
+
"Invalid resource preview URL.": "\u8D44\u6E90\u9884\u89C8\u5730\u5740\u65E0\u6548\u3002",
|
|
12905
|
+
"This preview configuration no longer exists.": "\u6B64\u9884\u89C8\u914D\u7F6E\u5DF2\u4E0D\u5B58\u5728\u3002",
|
|
12906
|
+
"Resource access changed. Open the card again.": "\u8D44\u6E90\u8BBF\u95EE\u72B6\u6001\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5361\u7247\u3002",
|
|
12907
|
+
"This resource preview is read-only.": "\u6B64\u8D44\u6E90\u9884\u89C8\u4E3A\u53EA\u8BFB\u3002",
|
|
12908
|
+
"Invalid resource action.": "\u8D44\u6E90\u64CD\u4F5C\u65E0\u6548\u3002",
|
|
12909
|
+
"Run no longer exists.": "\u6B64\u8FD0\u884C\u5DF2\u4E0D\u5B58\u5728\u3002",
|
|
12910
|
+
"Conversation changed.": "\u4F1A\u8BDD\u5DF2\u53D8\u5316\u3002",
|
|
12911
|
+
"Unable to load this preview. Retry or open it separately.": "\u65E0\u6CD5\u52A0\u8F7D\u6B64\u9884\u89C8\uFF0C\u8BF7\u91CD\u8BD5\u6216\u5355\u72EC\u6253\u5F00\u3002",
|
|
12912
|
+
"Open in browser": "\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00",
|
|
12913
|
+
"No resources": "\u6682\u65E0\u8D44\u6E90",
|
|
12914
|
+
"Allow popups to open this resource in a new window.": "\u8BF7\u5141\u8BB8\u5F39\u51FA\u7A97\u53E3\u4EE5\u5355\u72EC\u6253\u5F00\u6B64\u8D44\u6E90\u3002"
|
|
12889
12915
|
};
|
|
12890
12916
|
|
|
12891
12917
|
// src/web/localization.ts
|
|
@@ -16140,7 +16166,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
16140
16166
|
// src/web/resource-cards.ts
|
|
16141
16167
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
16142
16168
|
var string = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
16143
|
-
function conversationResourceCards(items, projectId, conversationId) {
|
|
16169
|
+
function conversationResourceCards(items, projectId, conversationId, storageSource = "local") {
|
|
16144
16170
|
const cards = /* @__PURE__ */ new Map();
|
|
16145
16171
|
for (const [index, item] of items.entries()) {
|
|
16146
16172
|
if (!["agent-part", "opencode-part"].includes(String(item.metadata?.kind)) || item.metadata?.partType !== "tool") {
|
|
@@ -16203,6 +16229,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
16203
16229
|
if (!kind2) {
|
|
16204
16230
|
continue;
|
|
16205
16231
|
}
|
|
16232
|
+
if (kind2 === "kv" || kind2 === "knowledge") {
|
|
16233
|
+
target2.source = input.source ?? storageSource;
|
|
16234
|
+
}
|
|
16206
16235
|
descriptor = { kind: kind2, target: target2, title: record(output?.document)?.title };
|
|
16207
16236
|
}
|
|
16208
16237
|
const kind = descriptor.kind;
|
|
@@ -16211,7 +16240,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
16211
16240
|
}
|
|
16212
16241
|
const target = Object.fromEntries(Object.entries(record(descriptor.target) ?? {}).filter((entry) => typeof entry[1] === "string" && entry[1].length < 8192));
|
|
16213
16242
|
if (target.source === "current") {
|
|
16214
|
-
target.source = "local";
|
|
16243
|
+
target.source = kind === "kv" || kind === "knowledge" ? storageSource : "local";
|
|
16215
16244
|
target.projectId = projectId;
|
|
16216
16245
|
}
|
|
16217
16246
|
if (target.source && !["local", "server"].includes(target.source)) {
|
|
@@ -16237,8 +16266,18 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
16237
16266
|
}
|
|
16238
16267
|
}
|
|
16239
16268
|
const id = string(descriptor.cardId) ?? `${kind}:${JSON.stringify(target)}`;
|
|
16240
|
-
const title = (string(descriptor.title) ?? target.key ?? target.documentId ?? target.filePath ?? target.url ?? target.projectId ?? kind).slice(0, 200);
|
|
16241
|
-
|
|
16269
|
+
const title = (string(descriptor.title) ?? string(record(output?.document)?.title) ?? target.key ?? target.documentId ?? target.filePath ?? target.url ?? target.projectId ?? kind).slice(0, 200);
|
|
16270
|
+
const kanban = record(descriptor.kanban), values = record(kanban?.values);
|
|
16271
|
+
cards.set(id, {
|
|
16272
|
+
id,
|
|
16273
|
+
kind,
|
|
16274
|
+
title,
|
|
16275
|
+
target,
|
|
16276
|
+
itemId: item.id ?? String(index),
|
|
16277
|
+
...typeof descriptor.preview === "boolean" ? { preview: descriptor.preview } : {},
|
|
16278
|
+
...typeof descriptor.pinned === "boolean" ? { pinned: descriptor.pinned } : {},
|
|
16279
|
+
...kind === "kanban" && ["preview", "save"].includes(String(kanban?.mode)) && values && Object.keys(values).length <= 100 && Object.values(values).every((value) => typeof value === "string") ? { kanban: { mode: kanban.mode, values } } : {}
|
|
16280
|
+
});
|
|
16242
16281
|
}
|
|
16243
16282
|
return [...cards.values()];
|
|
16244
16283
|
}
|
|
@@ -16432,15 +16471,53 @@ ${JSON.stringify(output.details, null, 2)}` : "");
|
|
|
16432
16471
|
this.root = root;
|
|
16433
16472
|
this.options = options;
|
|
16434
16473
|
root.className = "message-output";
|
|
16474
|
+
window.addEventListener("message", this.resourceReply);
|
|
16475
|
+
this.resourceTheme.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
|
|
16435
16476
|
}
|
|
16436
16477
|
root;
|
|
16437
16478
|
options;
|
|
16438
16479
|
views = /* @__PURE__ */ new Map();
|
|
16439
16480
|
groups = /* @__PURE__ */ new Map();
|
|
16440
16481
|
activities = /* @__PURE__ */ new Map();
|
|
16441
|
-
|
|
16482
|
+
resourceTheme = new MutationObserver(() => this.syncResourceTheme());
|
|
16483
|
+
syncResourceTheme() {
|
|
16484
|
+
for (const frame of this.root.querySelectorAll(".resource-inline > iframe")) {
|
|
16485
|
+
frame.contentWindow?.postMessage({ type: "workflow-host", theme: document.documentElement.dataset.theme }, location.origin);
|
|
16486
|
+
}
|
|
16487
|
+
}
|
|
16488
|
+
resourceReply = (event) => {
|
|
16489
|
+
const reply = event.data;
|
|
16490
|
+
if (event.source !== null || !reply?.requestId) {
|
|
16491
|
+
return;
|
|
16492
|
+
}
|
|
16493
|
+
const card = Array.from(this.root.querySelectorAll(".resource-card")).find((card2) => card2.dataset.requestId === reply.requestId);
|
|
16494
|
+
if (!card) {
|
|
16495
|
+
return;
|
|
16496
|
+
}
|
|
16497
|
+
const preview = card.querySelector(".resource-inline");
|
|
16498
|
+
if (reply.type === "error") {
|
|
16499
|
+
preview.textContent = reply.message;
|
|
16500
|
+
preview.setAttribute("role", "alert");
|
|
16501
|
+
}
|
|
16502
|
+
if (reply.type === "resource-preview" && reply.action === "inline") {
|
|
16503
|
+
const frame = document.createElement("iframe");
|
|
16504
|
+
frame.title = card.querySelector(".resource-title").textContent ?? "";
|
|
16505
|
+
const address = new URL(reply.url, location.href);
|
|
16506
|
+
address.searchParams.set("resourcePresentation", "card");
|
|
16507
|
+
frame.src = address.href;
|
|
16508
|
+
frame.sandbox.add("allow-scripts", "allow-same-origin");
|
|
16509
|
+
frame.addEventListener("load", () => this.syncResourceTheme());
|
|
16510
|
+
preview.replaceChildren(frame);
|
|
16511
|
+
preview.removeAttribute("role");
|
|
16512
|
+
}
|
|
16513
|
+
};
|
|
16514
|
+
dispose() {
|
|
16515
|
+
window.removeEventListener("message", this.resourceReply);
|
|
16516
|
+
this.resourceTheme.disconnect();
|
|
16517
|
+
}
|
|
16518
|
+
update(message, projectId, conversationId, files, storageSource = "local") {
|
|
16442
16519
|
const items = message.items ?? [];
|
|
16443
|
-
const cards = conversationResourceCards(items, projectId, conversationId);
|
|
16520
|
+
const cards = conversationResourceCards(items, projectId, conversationId, storageSource);
|
|
16444
16521
|
const cardByItem = new Map(cards.map((card) => [card.itemId, card]));
|
|
16445
16522
|
const answers = [...new Map([...message.resolvedInputs ?? [], ...message.submittingInput ? [message.submittingInput] : []].map((answer) => [answer.requestId, answer])).values()];
|
|
16446
16523
|
const ordered = (message.timers ?? []).map((timer) => ({ key: `timer:${timer.timerId}`, timer }));
|
|
@@ -16460,14 +16537,18 @@ ${JSON.stringify(output.details, null, 2)}` : "");
|
|
|
16460
16537
|
const blocks = [];
|
|
16461
16538
|
for (const entry of ordered) {
|
|
16462
16539
|
const content = entry.item?.content;
|
|
16463
|
-
if (content?.tool === "workflow-ui_present_card" && !entry.card) {
|
|
16540
|
+
if (content?.tool === "workflow-ui_present_card" && content.status === "success" && !entry.card) {
|
|
16464
16541
|
continue;
|
|
16465
16542
|
}
|
|
16466
|
-
if (entry.item && content?.tool !== "workflow-ui_present_card") {
|
|
16543
|
+
if (entry.item && (content?.tool !== "workflow-ui_present_card" || content.status !== "success")) {
|
|
16467
16544
|
entry.activity = agentActivity(entry.item, message);
|
|
16468
16545
|
}
|
|
16469
|
-
if (entry.
|
|
16470
|
-
entry.card = conversationResourceCards([entry.item], projectId, conversationId)[0];
|
|
16546
|
+
if (entry.item && content?.tool !== "workflow-ui_present_card" && !entry.card) {
|
|
16547
|
+
entry.card = conversationResourceCards([entry.item], projectId, conversationId, storageSource)[0];
|
|
16548
|
+
}
|
|
16549
|
+
if (entry.card && entry.card.kind !== "file") {
|
|
16550
|
+
blocks.push({ key: `resource:${entry.key}`, card: entry.card, item: entry.item });
|
|
16551
|
+
continue;
|
|
16471
16552
|
}
|
|
16472
16553
|
if (entry.activity) {
|
|
16473
16554
|
const last = blocks.at(-1);
|
|
@@ -16494,7 +16575,7 @@ ${JSON.stringify(output.details, null, 2)}` : "");
|
|
|
16494
16575
|
view.signature = signature;
|
|
16495
16576
|
}
|
|
16496
16577
|
} else if (!view || view.signature !== signature) {
|
|
16497
|
-
const root = entry.answer ? this.answer(entry.answer, message.submittingInput?.requestId === entry.answer.requestId) : entry.timer ? this.timer(entry.timer) : activity ? this.activity(activity, entry.key, entry.card) : entry.card ? this.card(entry.card) : entry.item ? this.item(entry.item, files) : this.markdown(entry.text ?? "", files);
|
|
16578
|
+
const root = entry.answer ? this.answer(entry.answer, message.submittingInput?.requestId === entry.answer.requestId) : entry.timer ? this.timer(entry.timer) : activity ? this.activity(activity, entry.key, entry.card) : entry.card ? this.card(entry.card, entry.item) : entry.item ? this.item(entry.item, files) : this.markdown(entry.text ?? "", files);
|
|
16498
16579
|
if (view?.root instanceof HTMLDetailsElement && root instanceof HTMLDetailsElement) {
|
|
16499
16580
|
root.open = view.root.open;
|
|
16500
16581
|
}
|
|
@@ -16828,13 +16909,67 @@ ${JSON.stringify(output.details, null, 2)}` : "");
|
|
|
16828
16909
|
root.append(entry);
|
|
16829
16910
|
return root;
|
|
16830
16911
|
}
|
|
16831
|
-
card(card) {
|
|
16912
|
+
card(card, item) {
|
|
16913
|
+
const root = document.createElement("section");
|
|
16914
|
+
root.className = "resource-card";
|
|
16915
|
+
root.dataset.cardId = card.id;
|
|
16916
|
+
const row = document.createElement("div");
|
|
16917
|
+
row.className = "resource-card-row";
|
|
16832
16918
|
const button = document.createElement("button");
|
|
16833
|
-
button.className = "resource-
|
|
16834
|
-
button.title =
|
|
16835
|
-
button.innerHTML = `${iconHtml(card.kind === "browser" ? "globe" : card.kind === "file" ? "file" : card.kind === "kv" ? "database" : card.kind === "knowledge" ? "book" : "folder")}<span>${escapeHtml(card.title)}</span
|
|
16836
|
-
button.addEventListener("click", () => this.options.resource(card));
|
|
16837
|
-
|
|
16919
|
+
button.className = "resource-target";
|
|
16920
|
+
button.title = t2("Open resource");
|
|
16921
|
+
button.innerHTML = `${iconHtml(card.kind === "browser" ? "globe" : card.kind === "file" ? "file" : card.kind === "kv" ? "database" : card.kind === "knowledge" ? "book" : card.kind === "kanban" ? "layout" : "folder")}<span class="resource-title">${escapeHtml(card.title)}</span>`;
|
|
16922
|
+
button.addEventListener("click", () => this.options.resource(card, "open"));
|
|
16923
|
+
const preview = document.createElement("div");
|
|
16924
|
+
preview.className = "resource-inline";
|
|
16925
|
+
preview.hidden = true;
|
|
16926
|
+
const toggle = iconButton("eye", t2("Show in conversation"), () => {
|
|
16927
|
+
preview.hidden = !preview.hidden;
|
|
16928
|
+
toggle.setAttribute("aria-expanded", String(!preview.hidden));
|
|
16929
|
+
toggle.title = preview.hidden ? t2("Show in conversation") : t2("Hide preview");
|
|
16930
|
+
if (preview.hidden) {
|
|
16931
|
+
preview.replaceChildren();
|
|
16932
|
+
delete root.dataset.requestId;
|
|
16933
|
+
return;
|
|
16934
|
+
}
|
|
16935
|
+
const requestId = crypto.randomUUID();
|
|
16936
|
+
root.dataset.requestId = requestId;
|
|
16937
|
+
preview.textContent = t2("Loading...");
|
|
16938
|
+
preview.setAttribute("role", "status");
|
|
16939
|
+
this.options.resource(card, "inline", requestId);
|
|
16940
|
+
});
|
|
16941
|
+
toggle.setAttribute("aria-expanded", "false");
|
|
16942
|
+
toggle.dataset.action = "inline";
|
|
16943
|
+
const separate = iconButton("open-preview", t2("Open in new window"), () => this.options.resource(card, "window"));
|
|
16944
|
+
separate.dataset.action = "window";
|
|
16945
|
+
row.append(button, toggle, separate);
|
|
16946
|
+
root.append(row, preview);
|
|
16947
|
+
if (card.kind === "project" || card.kind === "kanban") {
|
|
16948
|
+
row.append(iconButton("folder-opened", t2("Open project"), () => this.options.resource(card, "project")));
|
|
16949
|
+
}
|
|
16950
|
+
if (item) {
|
|
16951
|
+
const details = document.createElement("div");
|
|
16952
|
+
details.className = "resource-call-details";
|
|
16953
|
+
details.hidden = true;
|
|
16954
|
+
const data = document.createElement("pre");
|
|
16955
|
+
data.textContent = JSON.stringify(item.content, null, 2);
|
|
16956
|
+
details.append(data);
|
|
16957
|
+
const inspect = iconButton("info", t2("Tool call details"), () => {
|
|
16958
|
+
details.hidden = !details.hidden;
|
|
16959
|
+
inspect.setAttribute("aria-expanded", String(!details.hidden));
|
|
16960
|
+
});
|
|
16961
|
+
inspect.setAttribute("aria-expanded", "false");
|
|
16962
|
+
row.append(inspect);
|
|
16963
|
+
root.append(details);
|
|
16964
|
+
}
|
|
16965
|
+
if (card.preview && ["project", "kanban", "browser"].includes(card.kind)) {
|
|
16966
|
+
queueMicrotask(() => {
|
|
16967
|
+
if (root.isConnected) {
|
|
16968
|
+
toggle.click();
|
|
16969
|
+
}
|
|
16970
|
+
});
|
|
16971
|
+
}
|
|
16972
|
+
return root;
|
|
16838
16973
|
}
|
|
16839
16974
|
};
|
|
16840
16975
|
|
|
@@ -17026,11 +17161,14 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17026
17161
|
var ConnectionError = class extends Error {
|
|
17027
17162
|
};
|
|
17028
17163
|
var BrowserConnection = class {
|
|
17029
|
-
constructor(emit) {
|
|
17164
|
+
constructor(emit, live = true) {
|
|
17030
17165
|
this.emit = emit;
|
|
17166
|
+
this.live = live;
|
|
17031
17167
|
if (this.token) {
|
|
17168
|
+
const query = new URLSearchParams(location.search);
|
|
17169
|
+
query.delete("session");
|
|
17032
17170
|
sessionStorage.setItem("workflow-web-session", this.token);
|
|
17033
|
-
history.replaceState(null, "", `${location.pathname}${
|
|
17171
|
+
history.replaceState(null, "", `${location.pathname}${query.size ? `?${query}` : ""}`);
|
|
17034
17172
|
}
|
|
17035
17173
|
queueMicrotask(() => {
|
|
17036
17174
|
this.banner = document.createElement("div");
|
|
@@ -17064,6 +17202,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17064
17202
|
});
|
|
17065
17203
|
}
|
|
17066
17204
|
emit;
|
|
17205
|
+
live;
|
|
17067
17206
|
clientId = crypto.randomUUID();
|
|
17068
17207
|
source;
|
|
17069
17208
|
banner;
|
|
@@ -17071,10 +17210,11 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17071
17210
|
handshake;
|
|
17072
17211
|
epoch = 0;
|
|
17073
17212
|
retry;
|
|
17213
|
+
snapshotTimer;
|
|
17074
17214
|
status = "connecting";
|
|
17075
17215
|
attempts = 0;
|
|
17076
17216
|
closed = false;
|
|
17077
|
-
token = new URLSearchParams(location.hash.slice(1)).get("session") ?? sessionStorage.getItem("workflow-web-session");
|
|
17217
|
+
token = new URLSearchParams(location.hash.slice(1)).get("session") ?? new URLSearchParams(location.search).get("session") ?? sessionStorage.getItem("workflow-web-session");
|
|
17078
17218
|
update(status) {
|
|
17079
17219
|
this.status = status;
|
|
17080
17220
|
this.emit({ type: "connection", status });
|
|
@@ -17097,6 +17237,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17097
17237
|
this.source?.close();
|
|
17098
17238
|
this.source = void 0;
|
|
17099
17239
|
clearTimeout(this.retry);
|
|
17240
|
+
clearTimeout(this.snapshotTimer);
|
|
17100
17241
|
}
|
|
17101
17242
|
interrupted() {
|
|
17102
17243
|
this.disconnect();
|
|
@@ -17150,6 +17291,10 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17150
17291
|
if (!session.ok) {
|
|
17151
17292
|
throw new Error("Cannot connect to the project.");
|
|
17152
17293
|
}
|
|
17294
|
+
if (!this.live) {
|
|
17295
|
+
await this.snapshot(epoch);
|
|
17296
|
+
return;
|
|
17297
|
+
}
|
|
17153
17298
|
const eventsUrl = new URL(this.fileUrl("/api/events"), location.href);
|
|
17154
17299
|
eventsUrl.searchParams.set("clientId", this.clientId);
|
|
17155
17300
|
const source = this.source = new EventSource(eventsUrl.href);
|
|
@@ -17186,6 +17331,39 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17186
17331
|
});
|
|
17187
17332
|
return this.connecting;
|
|
17188
17333
|
}
|
|
17334
|
+
async snapshot(epoch) {
|
|
17335
|
+
if (epoch !== this.epoch || this.closed) {
|
|
17336
|
+
return;
|
|
17337
|
+
}
|
|
17338
|
+
const response = await fetch("/api/resource-state", { headers: this.headers(), signal: AbortSignal.timeout(1e4) });
|
|
17339
|
+
if (epoch !== this.epoch || this.closed) {
|
|
17340
|
+
return;
|
|
17341
|
+
}
|
|
17342
|
+
if (response.status === 401) {
|
|
17343
|
+
this.disconnect();
|
|
17344
|
+
this.update("expired");
|
|
17345
|
+
return;
|
|
17346
|
+
}
|
|
17347
|
+
if (!response.ok) {
|
|
17348
|
+
throw new Error("Cannot connect to the project.");
|
|
17349
|
+
}
|
|
17350
|
+
const state = await response.json();
|
|
17351
|
+
if (epoch !== this.epoch || this.closed) {
|
|
17352
|
+
return;
|
|
17353
|
+
}
|
|
17354
|
+
if (this.status !== "connected") {
|
|
17355
|
+
this.attempts = 0;
|
|
17356
|
+
this.update("connected");
|
|
17357
|
+
}
|
|
17358
|
+
this.emit(state);
|
|
17359
|
+
this.snapshotTimer = setTimeout(() => {
|
|
17360
|
+
void this.snapshot(epoch).catch(() => {
|
|
17361
|
+
if (epoch === this.epoch && !this.closed) {
|
|
17362
|
+
this.interrupted();
|
|
17363
|
+
}
|
|
17364
|
+
});
|
|
17365
|
+
}, 5e3);
|
|
17366
|
+
}
|
|
17189
17367
|
async request(message) {
|
|
17190
17368
|
await this.connecting;
|
|
17191
17369
|
if (this.status !== "connected") {
|
|
@@ -17231,7 +17409,12 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17231
17409
|
return this.token ? { Authorization: `Bearer ${this.token}` } : {};
|
|
17232
17410
|
}
|
|
17233
17411
|
fileUrl(path) {
|
|
17234
|
-
|
|
17412
|
+
if (!this.token) {
|
|
17413
|
+
return path;
|
|
17414
|
+
}
|
|
17415
|
+
const url = new URL(path, location.href);
|
|
17416
|
+
url.searchParams.set("session", this.token);
|
|
17417
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
17235
17418
|
}
|
|
17236
17419
|
publicFiles(value) {
|
|
17237
17420
|
if (Array.isArray(value)) {
|
|
@@ -17452,7 +17635,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17452
17635
|
};
|
|
17453
17636
|
|
|
17454
17637
|
// src/web/ui/host.ts
|
|
17455
|
-
function acquireWorkflowHost() {
|
|
17638
|
+
function acquireWorkflowHost(options = {}) {
|
|
17456
17639
|
const embedded = globalThis.acquireVsCodeApi;
|
|
17457
17640
|
if (embedded) {
|
|
17458
17641
|
return embedded();
|
|
@@ -17472,6 +17655,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17472
17655
|
window.parent.postMessage(message, "*");
|
|
17473
17656
|
}
|
|
17474
17657
|
});
|
|
17658
|
+
let resourceHost = false;
|
|
17475
17659
|
const clipboard = new ClipboardBridge(
|
|
17476
17660
|
(message) => window.parent.postMessage(message, "*"),
|
|
17477
17661
|
(text3) => navigator.clipboard.writeText(text3),
|
|
@@ -17484,7 +17668,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17484
17668
|
}
|
|
17485
17669
|
trace.receive(message);
|
|
17486
17670
|
emit(message);
|
|
17487
|
-
});
|
|
17671
|
+
}, options.live);
|
|
17488
17672
|
const request = async (message) => {
|
|
17489
17673
|
for (const entry of await connection.request(message)) {
|
|
17490
17674
|
handleReply(entry);
|
|
@@ -17503,6 +17687,12 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17503
17687
|
if (event.data.clipboardVersion !== void 0) {
|
|
17504
17688
|
clipboard.enable(event.data.clipboardVersion);
|
|
17505
17689
|
}
|
|
17690
|
+
if (event.data.resourceVersion === 1) {
|
|
17691
|
+
resourceHost = true;
|
|
17692
|
+
}
|
|
17693
|
+
if (event.data.resourceError) {
|
|
17694
|
+
emit(event.data.resourceError);
|
|
17695
|
+
}
|
|
17506
17696
|
clipboard.receive(event.data.clipboard);
|
|
17507
17697
|
const traceCommand = trace.command(event.data.traceCommand);
|
|
17508
17698
|
if (traceCommand) {
|
|
@@ -17520,7 +17710,14 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17520
17710
|
}
|
|
17521
17711
|
return;
|
|
17522
17712
|
}
|
|
17523
|
-
if (reply.type === "
|
|
17713
|
+
if (reply.type === "resource-preview") {
|
|
17714
|
+
reply.url = connection.fileUrl(reply.url);
|
|
17715
|
+
if (reply.action === "inline") {
|
|
17716
|
+
emit(reply);
|
|
17717
|
+
} else {
|
|
17718
|
+
window.open(reply.url, "_blank", "noopener");
|
|
17719
|
+
}
|
|
17720
|
+
} else if (reply.type === "download") {
|
|
17524
17721
|
const url = URL.createObjectURL(new Blob([reply.content], { type: reply.mimeType ?? "application/json" }));
|
|
17525
17722
|
const link = document.createElement("a");
|
|
17526
17723
|
link.href = url;
|
|
@@ -17588,6 +17785,29 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
17588
17785
|
if (message.type === "ready") {
|
|
17589
17786
|
return;
|
|
17590
17787
|
}
|
|
17788
|
+
if (message.type === "resource" && message.action !== "inline" && resourceHost) {
|
|
17789
|
+
window.parent.postMessage({ type: "workflow-resource", version: 1, request: message }, "*");
|
|
17790
|
+
return;
|
|
17791
|
+
}
|
|
17792
|
+
if (message.type === "resource" && message.action !== "inline") {
|
|
17793
|
+
const popup = window.open("", "_blank");
|
|
17794
|
+
try {
|
|
17795
|
+
const reply = (await connection.request(message)).find((reply2) => reply2.type === "resource-preview");
|
|
17796
|
+
if (reply && popup) {
|
|
17797
|
+
popup.opener = null;
|
|
17798
|
+
popup.location.href = connection.fileUrl(reply.url);
|
|
17799
|
+
} else {
|
|
17800
|
+
popup?.close();
|
|
17801
|
+
if (reply) {
|
|
17802
|
+
emit({ type: "error", message: t2("Allow popups to open this resource in a new window.") });
|
|
17803
|
+
}
|
|
17804
|
+
}
|
|
17805
|
+
} catch (error) {
|
|
17806
|
+
popup?.close();
|
|
17807
|
+
emit({ type: "error", requestId: message.requestId, message: error.message });
|
|
17808
|
+
}
|
|
17809
|
+
return;
|
|
17810
|
+
}
|
|
17591
17811
|
if (message.type === "trace") {
|
|
17592
17812
|
if (trace.open(message)) {
|
|
17593
17813
|
return;
|
|
@@ -18367,7 +18587,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
18367
18587
|
plan: (text3) => dialogs.plan(text3),
|
|
18368
18588
|
file: (id) => post({ type: "open-file", id }),
|
|
18369
18589
|
image: (src, title) => dialogs.image(src, title),
|
|
18370
|
-
resource: (card) => post({ type: "resource", messageId: view.message.id, cardId: card.id })
|
|
18590
|
+
resource: (card, action, requestId2) => post({ type: "resource", messageId: view.message.id, cardId: card.id, action, requestId: requestId2 })
|
|
18371
18591
|
});
|
|
18372
18592
|
const actions = root.querySelector(".message-actions");
|
|
18373
18593
|
actions.prepend(iconButton("history", t2("Trace"), () => post({ type: "trace", messageId: view.message.id, runId: view.message.runId })));
|
|
@@ -18398,7 +18618,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
18398
18618
|
if (message.role === "user") {
|
|
18399
18619
|
view.content.textContent = message.content;
|
|
18400
18620
|
} else {
|
|
18401
|
-
view.output.update(message, state.project.id, state.activeId, (currentSession()?.messages ?? []).flatMap((entry) => [...entry.files ?? [], ...entry.attachments ?? []]));
|
|
18621
|
+
view.output.update(message, state.project.id, state.activeId, (currentSession()?.messages ?? []).flatMap((entry) => [...entry.files ?? [], ...entry.attachments ?? []]), state.project.projectInfo?.dataStorage?.mode === "server" ? "server" : "local");
|
|
18402
18622
|
}
|
|
18403
18623
|
view.error.textContent = message.error ?? "";
|
|
18404
18624
|
view.error.hidden = !message.error;
|
|
@@ -18489,6 +18709,9 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
18489
18709
|
draftFiles = session.draft?.attachments ?? [];
|
|
18490
18710
|
editingQueueId = session.draft?.editingQueueId;
|
|
18491
18711
|
renderedSession = next.activeId;
|
|
18712
|
+
for (const view of messages.values()) {
|
|
18713
|
+
view.output?.dispose();
|
|
18714
|
+
}
|
|
18492
18715
|
messages.clear();
|
|
18493
18716
|
transcript.replaceChildren();
|
|
18494
18717
|
document.querySelector("#error").hidden = true;
|
|
@@ -18531,6 +18754,7 @@ ${state.user?.avatarUrl ?? ""}`;
|
|
|
18531
18754
|
});
|
|
18532
18755
|
for (const [id, view] of messages) {
|
|
18533
18756
|
if (!active.has(id)) {
|
|
18757
|
+
view.output?.dispose();
|
|
18534
18758
|
view.root.remove();
|
|
18535
18759
|
messages.delete(id);
|
|
18536
18760
|
}
|