openwork-server 0.18.50 → 0.18.56
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/README.md +1 -1
- package/bin/openwork-server.mjs +28 -22
- package/bin/platform.mjs +28 -0
- package/dist/opencode-plugin-deps-1.18.30.tgz +0 -0
- package/dist/opencode-plugins/openwork-context-v2.js +84 -0
- package/dist/opencode-plugins/openwork-extensions-preview.js +589 -268
- package/dist/opencode-plugins/openwork-gateway-quota-v2.js +12 -1
- package/dist/opencode-plugins/openwork-gateway-quota.js +12 -1
- package/dist/opencode-plugins/openwork-mcp-results-v2.js +154 -0
- package/dist/opencode-plugins/openwork-office-attachments.js +135 -130
- package/dist/opencode-plugins/openwork-provider-adapters.js +2 -2
- package/dist/opencode-plugins/openwork-provider-filters-v2.js +69 -0
- package/dist/opencode-plugins/openwork-read-transport.js +2 -0
- package/dist/opencode-plugins/openwork-spreadsheets.js +136 -2
- package/dist/openwork-server.mjs +114735 -0
- package/dist/pdfium.wasm +0 -0
- package/package.json +7 -1
- package/web/assets/{abnfDiagram-VCTEODGH-BgnyE_Jl.js → abnfDiagram-VCTEODGH-Dr1YMfll.js} +1 -1
- package/web/assets/{app-CyCqD289.js → app-D9Nvta88.js} +474 -424
- package/web/assets/{arc-jSgX49-e.js → arc-7SoIBvT7.js} +1 -1
- package/web/assets/{architectureDiagram-5GKGNRK7-DD_aGn4v.js → architectureDiagram-5GKGNRK7-BZwevfH9.js} +1 -1
- package/web/assets/{artifact-code-view-DFIq0k-c.js → artifact-code-view-WLwX_I1h.js} +1 -1
- package/web/assets/{artifact-spreadsheet-editor-DFVCYrL7.js → artifact-spreadsheet-editor-BvEnxKsm.js} +1 -1
- package/web/assets/{artifact-text-editor-DBngc6bx.js → artifact-text-editor-BHyVrNyR.js} +1 -1
- package/web/assets/{blockDiagram-OSKFZWR5-CBcZLjLp.js → blockDiagram-OSKFZWR5-Cvqr9DPi.js} +1 -1
- package/web/assets/{c4Diagram-7LVT6UL2-DMrhFCLj.js → c4Diagram-7LVT6UL2-CWTWC9C1.js} +1 -1
- package/web/assets/channel-BkgEJbR-.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-Ce1X-FJQ.js → chunk-2Q5K7J3B-DpJkzZ5x.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-BS48ZtVI.js → chunk-5VM5RSS4-BtTBnr9m.js} +1 -1
- package/web/assets/{chunk-F27PBJKO-COdFZJ-M.js → chunk-F27PBJKO-BbAvFJAg.js} +1 -1
- package/web/assets/{chunk-HLEWEB6X-Cdw4ABX3.js → chunk-HLEWEB6X-DX5mKBrj.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-FVVDYZmE.js → chunk-JWPE2WC7-CugB1e5O.js} +1 -1
- package/web/assets/{chunk-POPQ4Y6H-C7acdUF3.js → chunk-POPQ4Y6H-BQ-bWmmo.js} +1 -1
- package/web/assets/{chunk-SVP7TREG-BUun0UWD.js → chunk-SVP7TREG-szCI_Kz9.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-DLgpJmat.js → chunk-XXDRQBXY-C5UTO899.js} +1 -1
- package/web/assets/{chunk-ZLD2IHE6-BdMQ5Cr0.js → chunk-ZLD2IHE6-D5v_jiDg.js} +1 -1
- package/web/assets/classDiagram-CYGNFDIV-BHINh3-f.js +1 -0
- package/web/assets/classDiagram-v2-TLXNO2FR-BHINh3-f.js +1 -0
- package/web/assets/{cose-bilkent-JH36ORCC-CqWy3Swy.js → cose-bilkent-JH36ORCC-BhG_zAfo.js} +1 -1
- package/web/assets/{cynefin-OW5HDTMX-DslesE5Y.js → cynefin-OW5HDTMX-DSTjm6jO.js} +1 -1
- package/web/assets/{cynefinDiagram-5FMLGOSQ-B54uZJn_.js → cynefinDiagram-5FMLGOSQ-Dqkgb6tF.js} +1 -1
- package/web/assets/{dagre-OS7QT2EB-Bkahh4gZ.js → dagre-OS7QT2EB-BZMseQyA.js} +1 -1
- package/web/assets/{diagram-S7CK7UJ4-CXQl7SfF.js → diagram-S7CK7UJ4-Cs2hsmEJ.js} +1 -1
- package/web/assets/{diagram-UQ7AKVKN-BA0V8tjK.js → diagram-UQ7AKVKN-CDnRP_yz.js} +1 -1
- package/web/assets/{diagram-VSXAHHWV-DlcR8qeO.js → diagram-VSXAHHWV-DxKXQXAC.js} +1 -1
- package/web/assets/{diagram-VX7I27RA-ewm16zDI.js → diagram-VX7I27RA-BJKoseDf.js} +1 -1
- package/web/assets/{diagram-Z3DM3KII-Bc2lRc88.js → diagram-Z3DM3KII-DDcMvRxo.js} +1 -1
- package/web/assets/{ebnfDiagram-PWID7BFC-JwCaf6cT.js → ebnfDiagram-PWID7BFC-C2uUm-CC.js} +1 -1
- package/web/assets/{erDiagram-2YWLMYGG-DOqO-9Yf.js → erDiagram-2YWLMYGG-B0Mdv5WO.js} +1 -1
- package/web/assets/{flowDiagram-T62WH6J4-CCZxvIjW.js → flowDiagram-T62WH6J4-CUnt9AMo.js} +1 -1
- package/web/assets/{ganttDiagram-EL5Y4UJY-BczG7RIu.js → ganttDiagram-EL5Y4UJY-CENsUToC.js} +1 -1
- package/web/assets/{gitGraphDiagram-WWUBYQGX-GOecDN3g.js → gitGraphDiagram-WWUBYQGX-CrbKh94B.js} +1 -1
- package/web/assets/index-CyyMNIC_.css +1 -0
- package/web/assets/{infoDiagram-FKFFQAWI-BbgIVsQp.js → infoDiagram-FKFFQAWI-B-U-x_qU.js} +1 -1
- package/web/assets/{ishikawaDiagram-5VMMS53U-xutQo5Ip.js → ishikawaDiagram-5VMMS53U-jNVSJSu1.js} +1 -1
- package/web/assets/{journeyDiagram-EYS64GPL-BIbzPGaa.js → journeyDiagram-EYS64GPL-De3j0gPh.js} +1 -1
- package/web/assets/{kanban-definition-UXKFOSKX-BCTiRzck.js → kanban-definition-UXKFOSKX-Bbc8wjhq.js} +1 -1
- package/web/assets/{layout-Wpfi54TB.js → layout-BIjP2nup.js} +1 -1
- package/web/assets/{linear-DLJHPikh.js → linear-lvQZOiHM.js} +1 -1
- package/web/assets/{mermaid.core-CDRJkis7.js → mermaid.core-LJPf4T7o.js} +5 -5
- package/web/assets/{mindmap-definition-THT77NOG-DtphSFs_.js → mindmap-definition-THT77NOG-DiboHsg8.js} +1 -1
- package/web/assets/{overlay-zA9qjYXH.js → overlay-DA5SOee-.js} +1 -1
- package/web/assets/{pegDiagram-XKGWAZYB-CzbjpqK7.js → pegDiagram-XKGWAZYB-DO_edVtr.js} +1 -1
- package/web/assets/{pieDiagram-E7YTZNPT-tjxtWWT7.js → pieDiagram-E7YTZNPT-bPvBuBuG.js} +1 -1
- package/web/assets/{quadrantDiagram-AXDQQJYC-CFC1qey-.js → quadrantDiagram-AXDQQJYC-BGyrQhlH.js} +1 -1
- package/web/assets/{railroadDiagram-O6MQD6OU-73_BXhNP.js → railroadDiagram-O6MQD6OU-XhPIuoOE.js} +1 -1
- package/web/assets/{requirementDiagram-IS5BZ75X-B8i4BL2A.js → requirementDiagram-IS5BZ75X-atdASt4G.js} +1 -1
- package/web/assets/{sankeyDiagram-P5KCCOFB-Dll4Naj0.js → sankeyDiagram-P5KCCOFB-BV9prEKy.js} +1 -1
- package/web/assets/{sequenceDiagram-WJ2MYXX4-B8Rvjhb5.js → sequenceDiagram-WJ2MYXX4-Csfm-fZ-.js} +1 -1
- package/web/assets/{sizeCapture-INFHLROL-h8YDF-c3.js → sizeCapture-INFHLROL-CLmH-AjF.js} +1 -1
- package/web/assets/{stateDiagram-XQSTLZYL-COorU6Ga.js → stateDiagram-XQSTLZYL-yiSt2fJK.js} +1 -1
- package/web/assets/stateDiagram-v2-IH3M54BS-BEhxOujx.js +1 -0
- package/web/assets/{swimlanes-V6O3JKXN-CAghInFw.js → swimlanes-V6O3JKXN-BpXNggx9.js} +1 -1
- package/web/assets/swimlanesDiagram-JKAHXJPX-DWqwFv9F.js +8 -0
- package/web/assets/{timeline-definition-24CTP7MA-Dum2N-ex.js → timeline-definition-24CTP7MA-C8X71OnL.js} +1 -1
- package/web/assets/{vennDiagram-4TSXK5OY-D-JeJumX.js → vennDiagram-4TSXK5OY-BZo-99ra.js} +1 -1
- package/web/assets/{wardleyDiagram-VM6X3IG4-d99FKQIG.js → wardleyDiagram-VM6X3IG4-BHwH6ZLg.js} +1 -1
- package/web/assets/{workspace-file-tree-CAuhntUr.js → workspace-file-tree-C8iSfvPt.js} +3 -3
- package/web/assets/{xychartDiagram-S5SC5T6Z-DdmevfkD.js → xychartDiagram-S5SC5T6Z-BieEi319.js} +1 -1
- package/web/ext-github.svg +1 -0
- package/web/ext-hubspot.svg +1 -0
- package/web/ext-slack.svg +1 -0
- package/web/index.html +4 -3
- package/web/overlay.html +3 -3
- package/dist/bin/openwork-server +0 -4
- package/web/assets/channel-BE8JEd1U.js +0 -1
- package/web/assets/classDiagram-CYGNFDIV-Cy8V0GW-.js +0 -1
- package/web/assets/classDiagram-v2-TLXNO2FR-Cy8V0GW-.js +0 -1
- package/web/assets/index-BZgplq0g.css +0 -1
- package/web/assets/stateDiagram-v2-IH3M54BS-BAu05WuT.js +0 -1
- package/web/assets/swimlanesDiagram-JKAHXJPX-CpJNl3pn.js +0 -8
- /package/web/assets/{index-_gYIQM_z.js → index-D6FUvVB1.js} +0 -0
|
@@ -45,98 +45,9 @@ var __export = (target, all) => {
|
|
|
45
45
|
};
|
|
46
46
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
47
47
|
|
|
48
|
-
// src/opencode-plugins/openwork-
|
|
49
|
-
import {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// src/errors.ts
|
|
53
|
-
class ApiError extends Error {
|
|
54
|
-
status;
|
|
55
|
-
code;
|
|
56
|
-
details;
|
|
57
|
-
constructor(status, code, message, details) {
|
|
58
|
-
super(message);
|
|
59
|
-
this.status = status;
|
|
60
|
-
this.code = code;
|
|
61
|
-
this.details = details;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// src/opencode-plugins/openwork-ui-bridge.ts
|
|
66
|
-
import { readFile } from "node:fs/promises";
|
|
67
|
-
import { join } from "node:path";
|
|
68
|
-
import { homedir, platform } from "node:os";
|
|
69
|
-
var cachedBridge = null;
|
|
70
|
-
var cachedBridgeAt = 0;
|
|
71
|
-
var cachedBridgeDiscovery;
|
|
72
|
-
var BRIDGE_CACHE_MS = 2000;
|
|
73
|
-
var BRIDGE_TIMEOUT_MS = 5000;
|
|
74
|
-
function userAppDataDir() {
|
|
75
|
-
if (platform() === "darwin")
|
|
76
|
-
return join(homedir(), "Library", "Application Support");
|
|
77
|
-
if (platform() === "win32")
|
|
78
|
-
return process.env.APPDATA || join(homedir(), "AppData", "Roaming");
|
|
79
|
-
return process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
80
|
-
}
|
|
81
|
-
function uiControlDiscoveryPaths() {
|
|
82
|
-
const explicit = process.env.OPENWORK_UI_CONTROL_DISCOVERY?.trim();
|
|
83
|
-
if (explicit)
|
|
84
|
-
return [explicit];
|
|
85
|
-
return [
|
|
86
|
-
join(userAppDataDir(), "com.differentai.openwork", "openwork-ui-control.json"),
|
|
87
|
-
join(userAppDataDir(), "com.differentai.openwork.dev", "openwork-ui-control.json")
|
|
88
|
-
].filter((p) => Boolean(p));
|
|
89
|
-
}
|
|
90
|
-
async function discoverUiBridge() {
|
|
91
|
-
const discovery = process.env.OPENWORK_UI_CONTROL_DISCOVERY?.trim();
|
|
92
|
-
if (cachedBridge && cachedBridgeDiscovery === discovery && Date.now() - cachedBridgeAt < BRIDGE_CACHE_MS)
|
|
93
|
-
return cachedBridge;
|
|
94
|
-
cachedBridge = null;
|
|
95
|
-
for (const candidate of uiControlDiscoveryPaths()) {
|
|
96
|
-
try {
|
|
97
|
-
const raw = await readFile(candidate, "utf8");
|
|
98
|
-
const parsed = JSON.parse(raw);
|
|
99
|
-
if (typeof parsed.baseUrl === "string" && typeof parsed.token === "string") {
|
|
100
|
-
const url = new URL(parsed.baseUrl);
|
|
101
|
-
if (url.protocol !== "http:" || !["127.0.0.1", "localhost", "[::1]"].includes(url.hostname) || url.username || url.password)
|
|
102
|
-
continue;
|
|
103
|
-
cachedBridge = { baseUrl: parsed.baseUrl, token: parsed.token };
|
|
104
|
-
cachedBridgeAt = Date.now();
|
|
105
|
-
cachedBridgeDiscovery = discovery;
|
|
106
|
-
return cachedBridge;
|
|
107
|
-
}
|
|
108
|
-
} catch {}
|
|
109
|
-
}
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
async function uiBridgeRequest(path, options = {}) {
|
|
113
|
-
const bridge = await discoverUiBridge();
|
|
114
|
-
if (!bridge)
|
|
115
|
-
return { ok: false, code: "browser_unavailable", dispatched: false, error: "The built-in browser is unavailable. Open the desktop app on the same machine as this task's server." };
|
|
116
|
-
try {
|
|
117
|
-
const response = await fetch(`${bridge.baseUrl}${path}`, {
|
|
118
|
-
method: options.method || "GET",
|
|
119
|
-
redirect: "error",
|
|
120
|
-
signal: options.signal ? AbortSignal.any([options.signal, AbortSignal.timeout(options.timeoutMs ?? BRIDGE_TIMEOUT_MS)]) : AbortSignal.timeout(options.timeoutMs ?? BRIDGE_TIMEOUT_MS),
|
|
121
|
-
headers: {
|
|
122
|
-
Authorization: `Bearer ${bridge.token}`,
|
|
123
|
-
...options.body ? { "Content-Type": "application/json" } : {}
|
|
124
|
-
},
|
|
125
|
-
...options.body ? { body: JSON.stringify(options.body) } : {}
|
|
126
|
-
});
|
|
127
|
-
const text = await response.text();
|
|
128
|
-
try {
|
|
129
|
-
return JSON.parse(text);
|
|
130
|
-
} catch {
|
|
131
|
-
return { ok: false, code: "browser_disconnected", mayHaveChangedState: true, retrySafe: false, error: "The browser returned no readable receipt. Inspect the page before retrying an action." };
|
|
132
|
-
}
|
|
133
|
-
} catch {
|
|
134
|
-
cachedBridge = null;
|
|
135
|
-
cachedBridgeAt = 0;
|
|
136
|
-
cachedBridgeDiscovery = undefined;
|
|
137
|
-
return { ok: false, code: "browser_disconnected", mayHaveChangedState: true, retrySafe: false, error: "The browser connection was interrupted. An action may already have run. Reconnect, list this conversation's tabs and observe before deciding what remains." };
|
|
138
|
-
}
|
|
139
|
-
}
|
|
48
|
+
// src/opencode-plugins/openwork-read-transport.ts
|
|
49
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
50
|
+
var openworkReadTransport = new AsyncLocalStorage;
|
|
140
51
|
|
|
141
52
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
142
53
|
var exports_external = {};
|
|
@@ -13670,6 +13581,279 @@ function date4(params) {
|
|
|
13670
13581
|
|
|
13671
13582
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
13672
13583
|
config(en_default());
|
|
13584
|
+
// src/opencode-plugins/session-activity.ts
|
|
13585
|
+
var engineSessionStatusesSchema = exports_external.record(exports_external.string(), exports_external.object({ type: exports_external.string() }).passthrough());
|
|
13586
|
+
var enginePendingRequestsSchema = exports_external.array(exports_external.object({ sessionID: exports_external.string() }).passthrough());
|
|
13587
|
+
function sessionActivityFrom(statuses, permissions, questions, sessionId, descendantIds = [], unknownDescendants = 0) {
|
|
13588
|
+
const parsedStatuses = engineSessionStatusesSchema.safeParse(statuses);
|
|
13589
|
+
const parsedPermissions = enginePendingRequestsSchema.safeParse(permissions);
|
|
13590
|
+
const parsedQuestions = enginePendingRequestsSchema.safeParse(questions);
|
|
13591
|
+
const probesComplete = parsedStatuses.success && parsedPermissions.success && parsedQuestions.success;
|
|
13592
|
+
const waiting = new Set([
|
|
13593
|
+
...parsedPermissions.success ? parsedPermissions.data.map((request) => request.sessionID) : [],
|
|
13594
|
+
...parsedQuestions.success ? parsedQuestions.data.map((request) => request.sessionID) : []
|
|
13595
|
+
]);
|
|
13596
|
+
const statusFor = (id) => {
|
|
13597
|
+
const type = parsedStatuses.success ? parsedStatuses.data[id]?.type : undefined;
|
|
13598
|
+
if (type === "error")
|
|
13599
|
+
return "error";
|
|
13600
|
+
if (waiting.has(id) || type === "waiting")
|
|
13601
|
+
return "waiting";
|
|
13602
|
+
if (type === "busy" || type === "running")
|
|
13603
|
+
return "busy";
|
|
13604
|
+
if (type === "retry" || type === "compacting" || type === "thinking" || type === "responding")
|
|
13605
|
+
return type;
|
|
13606
|
+
return probesComplete && (type === undefined || type === "idle") ? "idle" : "unknown";
|
|
13607
|
+
};
|
|
13608
|
+
const descendantActivity = { busy: 0, waiting: 0, unknown: unknownDescendants };
|
|
13609
|
+
for (const id of new Set(descendantIds)) {
|
|
13610
|
+
if (id === sessionId)
|
|
13611
|
+
continue;
|
|
13612
|
+
const status = statusFor(id);
|
|
13613
|
+
if (status === "unknown")
|
|
13614
|
+
descendantActivity.unknown += 1;
|
|
13615
|
+
else if (status === "waiting")
|
|
13616
|
+
descendantActivity.waiting += 1;
|
|
13617
|
+
else if (status !== "idle" && status !== "error")
|
|
13618
|
+
descendantActivity.busy += 1;
|
|
13619
|
+
}
|
|
13620
|
+
const own = statusFor(sessionId);
|
|
13621
|
+
return {
|
|
13622
|
+
status: own !== "error" && descendantActivity.waiting > 0 ? "waiting" : own,
|
|
13623
|
+
working: own !== "idle" && own !== "error" && own !== "unknown" || descendantActivity.busy > 0 || descendantActivity.waiting > 0,
|
|
13624
|
+
descendantActivity,
|
|
13625
|
+
inventoryComplete: probesComplete && own !== "unknown" && descendantActivity.unknown === 0
|
|
13626
|
+
};
|
|
13627
|
+
}
|
|
13628
|
+
|
|
13629
|
+
// src/opencode-v2-read-adapter.ts
|
|
13630
|
+
function isRecord(value) {
|
|
13631
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13632
|
+
}
|
|
13633
|
+
function data(value) {
|
|
13634
|
+
return isRecord(value) && "data" in value ? value.data : value;
|
|
13635
|
+
}
|
|
13636
|
+
function items(value) {
|
|
13637
|
+
const rows = data(value);
|
|
13638
|
+
if (!Array.isArray(rows))
|
|
13639
|
+
throw new Error("Invalid engine list response");
|
|
13640
|
+
return rows.filter(isRecord);
|
|
13641
|
+
}
|
|
13642
|
+
function session(value) {
|
|
13643
|
+
const row = data(value);
|
|
13644
|
+
if (!isRecord(row))
|
|
13645
|
+
throw new Error("Invalid engine session response");
|
|
13646
|
+
const info = isRecord(row.info) ? row.info : row;
|
|
13647
|
+
const home = info.openworkHomeDirectory;
|
|
13648
|
+
return { ...info, directory: home ?? (isRecord(info.location) ? info.location.directory : undefined) };
|
|
13649
|
+
}
|
|
13650
|
+
async function pages(read, path, limit) {
|
|
13651
|
+
const url2 = new URL(path, "http://engine");
|
|
13652
|
+
url2.searchParams.set("limit", String(limit ?? 200));
|
|
13653
|
+
const rows = [];
|
|
13654
|
+
const cursors = new Set;
|
|
13655
|
+
while (true) {
|
|
13656
|
+
const result = await read(url2.pathname + url2.search);
|
|
13657
|
+
rows.push(...items(result));
|
|
13658
|
+
const next = isRecord(result) && isRecord(result.cursor) ? result.cursor.next : undefined;
|
|
13659
|
+
if (limit !== undefined || typeof next !== "string" || !next)
|
|
13660
|
+
return rows;
|
|
13661
|
+
if (cursors.has(next))
|
|
13662
|
+
throw new Error("Invalid engine pagination cursor");
|
|
13663
|
+
cursors.add(next);
|
|
13664
|
+
url2.searchParams.set("cursor", next);
|
|
13665
|
+
}
|
|
13666
|
+
}
|
|
13667
|
+
function createV2ReadAdapter(read) {
|
|
13668
|
+
return async (path) => {
|
|
13669
|
+
const match = /^\/workspace\/([^/]+)\/opencode(\/.*)$/.exec(path);
|
|
13670
|
+
if (!match)
|
|
13671
|
+
return read(path);
|
|
13672
|
+
const base = `/workspace/${match[1]}/opencode2`;
|
|
13673
|
+
const native = (path2) => read(base + path2);
|
|
13674
|
+
const url2 = new URL(match[2], "http://engine");
|
|
13675
|
+
if (url2.pathname === "/session/status") {
|
|
13676
|
+
const active = data(await native("/api/session/active"));
|
|
13677
|
+
if (!isRecord(active))
|
|
13678
|
+
throw new Error("Invalid engine activity response");
|
|
13679
|
+
return Object.fromEntries(Object.entries(active).map(([id, value]) => [
|
|
13680
|
+
id,
|
|
13681
|
+
{ type: isRecord(value) && value.type === "running" ? "busy" : "idle" }
|
|
13682
|
+
]));
|
|
13683
|
+
}
|
|
13684
|
+
if (url2.pathname === "/session") {
|
|
13685
|
+
const rows2 = await pages(native, "/api/session");
|
|
13686
|
+
return rows2.filter((row) => url2.searchParams.get("roots") !== "true" || !row.parentID).map(session);
|
|
13687
|
+
}
|
|
13688
|
+
if (url2.pathname === "/provider") {
|
|
13689
|
+
const [models, providers] = await Promise.all([native("/api/model").then(items), native("/api/provider").then(items)]);
|
|
13690
|
+
const names = new Map(providers.map((provider) => [provider.id, provider.name]));
|
|
13691
|
+
const catalog = new Map;
|
|
13692
|
+
for (const model of models) {
|
|
13693
|
+
if (typeof model.id !== "string" || typeof model.providerID !== "string")
|
|
13694
|
+
continue;
|
|
13695
|
+
const name = names.get(model.providerID);
|
|
13696
|
+
const provider = catalog.get(model.providerID) ?? {
|
|
13697
|
+
id: model.providerID,
|
|
13698
|
+
name: typeof name === "string" ? name : model.providerID,
|
|
13699
|
+
models: {}
|
|
13700
|
+
};
|
|
13701
|
+
provider.models[model.id] = { name: typeof model.name === "string" ? model.name : model.id };
|
|
13702
|
+
catalog.set(model.providerID, provider);
|
|
13703
|
+
}
|
|
13704
|
+
return { all: [...catalog.values()], connected: [...catalog.keys()] };
|
|
13705
|
+
}
|
|
13706
|
+
if (url2.pathname === "/question")
|
|
13707
|
+
return items(await native("/api/form/request"));
|
|
13708
|
+
const target = /^\/session\/([^/]+)(\/message|\/children)?$/.exec(url2.pathname);
|
|
13709
|
+
if (!target)
|
|
13710
|
+
throw new Error("Unsupported native engine read");
|
|
13711
|
+
if (!target[2])
|
|
13712
|
+
return session(await native(`/api/session/${target[1]}`));
|
|
13713
|
+
if (target[2] === "/children") {
|
|
13714
|
+
return (await pages(native, "/api/session")).filter((row) => row.parentID === decodeURIComponent(target[1])).map(session);
|
|
13715
|
+
}
|
|
13716
|
+
const limit = url2.searchParams.get("limit");
|
|
13717
|
+
const rows = await pages(native, `/api/session/${target[1]}/message`, limit === null ? undefined : Number(limit));
|
|
13718
|
+
return rows.filter((row) => row.type === "user" || row.type === "assistant").sort((a, b) => Number(isRecord(a.time) ? a.time.created : 0) - Number(isRecord(b.time) ? b.time.created : 0)).map((row) => ({
|
|
13719
|
+
info: { id: row.id, role: row.type, time: row.time, ...row.error ? { error: row.error } : {} },
|
|
13720
|
+
parts: Array.isArray(row.content) ? row.content.filter((part) => isRecord(part) && part.type === "text") : typeof row.text === "string" ? [{ type: "text", text: row.text }] : []
|
|
13721
|
+
}));
|
|
13722
|
+
};
|
|
13723
|
+
}
|
|
13724
|
+
async function readV2SessionActivity(read, workspaceId, sessionId) {
|
|
13725
|
+
const base = `/workspace/${encodeURIComponent(workspaceId)}/opencode2`;
|
|
13726
|
+
const native = (path) => read(base + path);
|
|
13727
|
+
const [listed, statuses] = await Promise.all([
|
|
13728
|
+
pages(native, "/api/session").catch(() => null),
|
|
13729
|
+
native("/api/session/active").then(data).catch(() => null)
|
|
13730
|
+
]);
|
|
13731
|
+
const ids = new Set([sessionId]);
|
|
13732
|
+
if (listed) {
|
|
13733
|
+
for (let changed = true;changed; ) {
|
|
13734
|
+
changed = false;
|
|
13735
|
+
for (const row of listed) {
|
|
13736
|
+
if (typeof row.id !== "string" || typeof row.parentID !== "string" || !ids.has(row.parentID) || ids.has(row.id))
|
|
13737
|
+
continue;
|
|
13738
|
+
ids.add(row.id);
|
|
13739
|
+
changed = true;
|
|
13740
|
+
}
|
|
13741
|
+
}
|
|
13742
|
+
}
|
|
13743
|
+
const permissions = [];
|
|
13744
|
+
const questions = [];
|
|
13745
|
+
let complete = listed !== null;
|
|
13746
|
+
const pending = [...ids];
|
|
13747
|
+
await Promise.all(Array.from({ length: Math.min(4, pending.length) }, async () => {
|
|
13748
|
+
for (let id = pending.shift();id; id = pending.shift()) {
|
|
13749
|
+
try {
|
|
13750
|
+
const [p, q] = await Promise.all([
|
|
13751
|
+
native(`/api/session/${encodeURIComponent(id)}/permission`),
|
|
13752
|
+
native(`/api/session/${encodeURIComponent(id)}/form`)
|
|
13753
|
+
]);
|
|
13754
|
+
permissions.push(...items(p).map((item) => ({ ...item, sessionID: id })));
|
|
13755
|
+
questions.push(...items(q).map((item) => ({ ...item, sessionID: id })));
|
|
13756
|
+
} catch {
|
|
13757
|
+
complete = false;
|
|
13758
|
+
}
|
|
13759
|
+
}
|
|
13760
|
+
}));
|
|
13761
|
+
return sessionActivityFrom(statuses, complete ? permissions : null, complete ? questions : null, sessionId, [...ids].filter((id) => id !== sessionId), listed ? 0 : 1);
|
|
13762
|
+
}
|
|
13763
|
+
|
|
13764
|
+
// src/opencode-plugins/openwork-extensions-preview.ts
|
|
13765
|
+
import { randomUUID } from "node:crypto";
|
|
13766
|
+
import { realpath } from "node:fs/promises";
|
|
13767
|
+
|
|
13768
|
+
// src/errors.ts
|
|
13769
|
+
class ApiError extends Error {
|
|
13770
|
+
status;
|
|
13771
|
+
code;
|
|
13772
|
+
details;
|
|
13773
|
+
constructor(status, code, message, details) {
|
|
13774
|
+
super(message);
|
|
13775
|
+
this.status = status;
|
|
13776
|
+
this.code = code;
|
|
13777
|
+
this.details = details;
|
|
13778
|
+
}
|
|
13779
|
+
}
|
|
13780
|
+
|
|
13781
|
+
// src/opencode-plugins/openwork-ui-bridge.ts
|
|
13782
|
+
import { readFile } from "node:fs/promises";
|
|
13783
|
+
import { join } from "node:path";
|
|
13784
|
+
import { homedir, platform } from "node:os";
|
|
13785
|
+
var cachedBridge = null;
|
|
13786
|
+
var cachedBridgeAt = 0;
|
|
13787
|
+
var cachedBridgeDiscovery;
|
|
13788
|
+
var BRIDGE_CACHE_MS = 2000;
|
|
13789
|
+
var BRIDGE_TIMEOUT_MS = 5000;
|
|
13790
|
+
function userAppDataDir() {
|
|
13791
|
+
if (platform() === "darwin")
|
|
13792
|
+
return join(homedir(), "Library", "Application Support");
|
|
13793
|
+
if (platform() === "win32")
|
|
13794
|
+
return process.env.APPDATA || join(homedir(), "AppData", "Roaming");
|
|
13795
|
+
return process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
13796
|
+
}
|
|
13797
|
+
function uiControlDiscoveryPaths() {
|
|
13798
|
+
const explicit = process.env.OPENWORK_UI_CONTROL_DISCOVERY?.trim();
|
|
13799
|
+
if (explicit)
|
|
13800
|
+
return [explicit];
|
|
13801
|
+
return [
|
|
13802
|
+
join(userAppDataDir(), "com.differentai.openwork", "openwork-ui-control.json"),
|
|
13803
|
+
join(userAppDataDir(), "com.differentai.openwork.dev", "openwork-ui-control.json")
|
|
13804
|
+
].filter((p) => Boolean(p));
|
|
13805
|
+
}
|
|
13806
|
+
async function discoverUiBridge() {
|
|
13807
|
+
const discovery = process.env.OPENWORK_UI_CONTROL_DISCOVERY?.trim();
|
|
13808
|
+
if (cachedBridge && cachedBridgeDiscovery === discovery && Date.now() - cachedBridgeAt < BRIDGE_CACHE_MS)
|
|
13809
|
+
return cachedBridge;
|
|
13810
|
+
cachedBridge = null;
|
|
13811
|
+
for (const candidate of uiControlDiscoveryPaths()) {
|
|
13812
|
+
try {
|
|
13813
|
+
const raw = await readFile(candidate, "utf8");
|
|
13814
|
+
const parsed = JSON.parse(raw);
|
|
13815
|
+
if (typeof parsed.baseUrl === "string" && typeof parsed.token === "string") {
|
|
13816
|
+
const url2 = new URL(parsed.baseUrl);
|
|
13817
|
+
if (url2.protocol !== "http:" || !["127.0.0.1", "localhost", "[::1]"].includes(url2.hostname) || url2.username || url2.password)
|
|
13818
|
+
continue;
|
|
13819
|
+
cachedBridge = { baseUrl: parsed.baseUrl, token: parsed.token };
|
|
13820
|
+
cachedBridgeAt = Date.now();
|
|
13821
|
+
cachedBridgeDiscovery = discovery;
|
|
13822
|
+
return cachedBridge;
|
|
13823
|
+
}
|
|
13824
|
+
} catch {}
|
|
13825
|
+
}
|
|
13826
|
+
return null;
|
|
13827
|
+
}
|
|
13828
|
+
async function uiBridgeRequest(path, options = {}) {
|
|
13829
|
+
const bridge = await discoverUiBridge();
|
|
13830
|
+
if (!bridge)
|
|
13831
|
+
return { ok: false, code: "browser_unavailable", dispatched: false, error: "The built-in browser is unavailable. Open the desktop app on the same machine as this task's server." };
|
|
13832
|
+
try {
|
|
13833
|
+
const response = await fetch(`${bridge.baseUrl}${path}`, {
|
|
13834
|
+
method: options.method || "GET",
|
|
13835
|
+
redirect: "error",
|
|
13836
|
+
signal: options.signal ? AbortSignal.any([options.signal, AbortSignal.timeout(options.timeoutMs ?? BRIDGE_TIMEOUT_MS)]) : AbortSignal.timeout(options.timeoutMs ?? BRIDGE_TIMEOUT_MS),
|
|
13837
|
+
headers: {
|
|
13838
|
+
Authorization: `Bearer ${bridge.token}`,
|
|
13839
|
+
...options.body ? { "Content-Type": "application/json" } : {}
|
|
13840
|
+
},
|
|
13841
|
+
...options.body ? { body: JSON.stringify(options.body) } : {}
|
|
13842
|
+
});
|
|
13843
|
+
const text = await response.text();
|
|
13844
|
+
try {
|
|
13845
|
+
return JSON.parse(text);
|
|
13846
|
+
} catch {
|
|
13847
|
+
return { ok: false, code: "browser_disconnected", mayHaveChangedState: true, retrySafe: false, error: "The browser returned no readable receipt. Inspect the page before retrying an action." };
|
|
13848
|
+
}
|
|
13849
|
+
} catch {
|
|
13850
|
+
cachedBridge = null;
|
|
13851
|
+
cachedBridgeAt = 0;
|
|
13852
|
+
cachedBridgeDiscovery = undefined;
|
|
13853
|
+
return { ok: false, code: "browser_disconnected", mayHaveChangedState: true, retrySafe: false, error: "The browser connection was interrupted. An action may already have run. Reconnect, list this conversation's tabs and observe before deciding what remains." };
|
|
13854
|
+
}
|
|
13855
|
+
}
|
|
13856
|
+
|
|
13673
13857
|
// src/opencode-plugins/gmail-attachment-fulfillment.ts
|
|
13674
13858
|
var draftSchema = exports_external.object({
|
|
13675
13859
|
to: exports_external.string().trim().min(3).max(320),
|
|
@@ -13702,7 +13886,7 @@ var receiptSchema = exports_external.object({
|
|
|
13702
13886
|
size: exports_external.number().int().nonnegative()
|
|
13703
13887
|
})).optional()
|
|
13704
13888
|
});
|
|
13705
|
-
function
|
|
13889
|
+
function isRecord2(value) {
|
|
13706
13890
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13707
13891
|
}
|
|
13708
13892
|
function normalizeJson(value) {
|
|
@@ -13752,11 +13936,11 @@ var CLOUD_NO_WRITE = new Set([
|
|
|
13752
13936
|
"mcp_membership_revoked:403"
|
|
13753
13937
|
]);
|
|
13754
13938
|
function noWriteMessage(error48) {
|
|
13755
|
-
if (!
|
|
13939
|
+
if (!isRecord2(error48) || typeof error48.message !== "string")
|
|
13756
13940
|
return;
|
|
13757
13941
|
if (LOCAL_NO_WRITE.has(`${error48.code}:${error48.status}`))
|
|
13758
13942
|
return `${error48.message} No draft created.`;
|
|
13759
|
-
if (error48.code === "cloud_upload_failed" &&
|
|
13943
|
+
if (error48.code === "cloud_upload_failed" && isRecord2(error48.details) && CLOUD_NO_WRITE.has(`${error48.details.upstreamCode}:${error48.status}`)) {
|
|
13760
13944
|
return `${error48.message} No draft created.`;
|
|
13761
13945
|
}
|
|
13762
13946
|
}
|
|
@@ -13776,18 +13960,18 @@ function createGmailAttachmentFulfillment(dependencies, factoryContext = {}) {
|
|
|
13776
13960
|
return call;
|
|
13777
13961
|
}
|
|
13778
13962
|
const fulfill = async (input, output) => {
|
|
13779
|
-
if (!
|
|
13963
|
+
if (!isRecord2(input) || input.tool !== "openwork-cloud_execute_capability")
|
|
13780
13964
|
return;
|
|
13781
|
-
if (!
|
|
13965
|
+
if (!isRecord2(input.args) || typeof input.args.name !== "string")
|
|
13782
13966
|
return;
|
|
13783
13967
|
const native = NATIVE_GMAIL.exec(input.args.name);
|
|
13784
13968
|
const connectionId = native?.[1];
|
|
13785
|
-
if (!connectionId || !
|
|
13969
|
+
if (!connectionId || !isRecord2(output) || output.isError === true)
|
|
13786
13970
|
return;
|
|
13787
13971
|
if (!Array.isArray(output.content) || output.content.length !== 1)
|
|
13788
13972
|
return;
|
|
13789
13973
|
const part = output.content[0];
|
|
13790
|
-
if (!
|
|
13974
|
+
if (!isRecord2(part) || part.type !== "text" || typeof part.text !== "string")
|
|
13791
13975
|
return;
|
|
13792
13976
|
if (!markerSchema.safeParse(normalizeJson(part.text)).success)
|
|
13793
13977
|
return;
|
|
@@ -13822,7 +14006,7 @@ function createGmailAttachmentFulfillment(dependencies, factoryContext = {}) {
|
|
|
13822
14006
|
}
|
|
13823
14007
|
if (call.controller.signal.aborted)
|
|
13824
14008
|
throw new Error(UNKNOWN_OUTCOME);
|
|
13825
|
-
if (
|
|
14009
|
+
if (isRecord2(result) && result.ok === false) {
|
|
13826
14010
|
throw new Error(UNKNOWN_OUTCOME);
|
|
13827
14011
|
}
|
|
13828
14012
|
const receipt = receiptSchema.safeParse(result);
|
|
@@ -13838,17 +14022,17 @@ function createGmailAttachmentFulfillment(dependencies, factoryContext = {}) {
|
|
|
13838
14022
|
};
|
|
13839
14023
|
return Object.assign(fulfill, {
|
|
13840
14024
|
before: async (input, output) => {
|
|
13841
|
-
if (!
|
|
14025
|
+
if (!isRecord2(input) || input.tool !== "openwork-cloud_execute_capability" || typeof input.sessionID !== "string" || typeof input.callID !== "string" || !isRecord2(output) || !isRecord2(output.args) || typeof output.args.name !== "string" || !NATIVE_GMAIL.test(output.args.name))
|
|
13842
14026
|
return;
|
|
13843
14027
|
const body = normalizeJson(output.args.body);
|
|
13844
|
-
if (
|
|
14028
|
+
if (isRecord2(body) && Array.isArray(body.attachments))
|
|
13845
14029
|
invocation(input.sessionID, input.callID);
|
|
13846
14030
|
},
|
|
13847
14031
|
event: async (input) => {
|
|
13848
|
-
if (!
|
|
14032
|
+
if (!isRecord2(input) || !isRecord2(input.event) || input.event.type !== "session.status")
|
|
13849
14033
|
return;
|
|
13850
14034
|
const props = input.event.properties;
|
|
13851
|
-
if (!
|
|
14035
|
+
if (!isRecord2(props) || typeof props.sessionID !== "string" || !isRecord2(props.status))
|
|
13852
14036
|
return;
|
|
13853
14037
|
if (props.status.type === "busy")
|
|
13854
14038
|
idleSessions.delete(props.sessionID);
|
|
@@ -13868,51 +14052,6 @@ function createGmailAttachmentFulfillment(dependencies, factoryContext = {}) {
|
|
|
13868
14052
|
});
|
|
13869
14053
|
}
|
|
13870
14054
|
|
|
13871
|
-
// src/opencode-plugins/session-activity.ts
|
|
13872
|
-
var engineSessionStatusesSchema = exports_external.record(exports_external.string(), exports_external.object({ type: exports_external.string() }).passthrough());
|
|
13873
|
-
var enginePendingRequestsSchema = exports_external.array(exports_external.object({ sessionID: exports_external.string() }).passthrough());
|
|
13874
|
-
function sessionActivityFrom(statuses, permissions, questions, sessionId, descendantIds = [], unknownDescendants = 0) {
|
|
13875
|
-
const parsedStatuses = engineSessionStatusesSchema.safeParse(statuses);
|
|
13876
|
-
const parsedPermissions = enginePendingRequestsSchema.safeParse(permissions);
|
|
13877
|
-
const parsedQuestions = enginePendingRequestsSchema.safeParse(questions);
|
|
13878
|
-
const probesComplete = parsedStatuses.success && parsedPermissions.success && parsedQuestions.success;
|
|
13879
|
-
const waiting = new Set([
|
|
13880
|
-
...parsedPermissions.success ? parsedPermissions.data.map((request) => request.sessionID) : [],
|
|
13881
|
-
...parsedQuestions.success ? parsedQuestions.data.map((request) => request.sessionID) : []
|
|
13882
|
-
]);
|
|
13883
|
-
const statusFor = (id) => {
|
|
13884
|
-
const type = parsedStatuses.success ? parsedStatuses.data[id]?.type : undefined;
|
|
13885
|
-
if (type === "error")
|
|
13886
|
-
return "error";
|
|
13887
|
-
if (waiting.has(id) || type === "waiting")
|
|
13888
|
-
return "waiting";
|
|
13889
|
-
if (type === "busy" || type === "running")
|
|
13890
|
-
return "busy";
|
|
13891
|
-
if (type === "retry" || type === "compacting" || type === "thinking" || type === "responding")
|
|
13892
|
-
return type;
|
|
13893
|
-
return probesComplete && (type === undefined || type === "idle") ? "idle" : "unknown";
|
|
13894
|
-
};
|
|
13895
|
-
const descendantActivity = { busy: 0, waiting: 0, unknown: unknownDescendants };
|
|
13896
|
-
for (const id of new Set(descendantIds)) {
|
|
13897
|
-
if (id === sessionId)
|
|
13898
|
-
continue;
|
|
13899
|
-
const status = statusFor(id);
|
|
13900
|
-
if (status === "unknown")
|
|
13901
|
-
descendantActivity.unknown += 1;
|
|
13902
|
-
else if (status === "waiting")
|
|
13903
|
-
descendantActivity.waiting += 1;
|
|
13904
|
-
else if (status !== "idle" && status !== "error")
|
|
13905
|
-
descendantActivity.busy += 1;
|
|
13906
|
-
}
|
|
13907
|
-
const own = statusFor(sessionId);
|
|
13908
|
-
return {
|
|
13909
|
-
status: own !== "error" && descendantActivity.waiting > 0 ? "waiting" : own,
|
|
13910
|
-
working: own !== "idle" && own !== "error" && own !== "unknown" || descendantActivity.busy > 0 || descendantActivity.waiting > 0,
|
|
13911
|
-
descendantActivity,
|
|
13912
|
-
inventoryComplete: probesComplete && own !== "unknown" && descendantActivity.unknown === 0
|
|
13913
|
-
};
|
|
13914
|
-
}
|
|
13915
|
-
|
|
13916
14055
|
// ../../packages/types/src/openwork-affordance.ts
|
|
13917
14056
|
var openworkAffordanceKindSchema = exports_external.enum(["query", "command", "guidance"]);
|
|
13918
14057
|
var openworkProviderKindSchema = exports_external.enum(["builtin", "extension", "mcp", "connect"]);
|
|
@@ -14216,15 +14355,18 @@ var automationExecutionThreadSchema = exports_external.object({
|
|
|
14216
14355
|
var automationExecutionTargetSchema = exports_external.enum(["desktop", "cloud"]);
|
|
14217
14356
|
var AUTOMATION_MODEL_ATTENTION_CAPABILITY = "model_attention_v1";
|
|
14218
14357
|
var REMOTE_SESSION_DESKTOP_RUNNER_CAPABILITY = "remote_session_v1";
|
|
14358
|
+
var REMOTE_SESSION_CONTROL_RUNNER_CAPABILITY = "remote_session_control_v1";
|
|
14219
14359
|
var automationDesktopRunnerCapabilitySchema = exports_external.enum([
|
|
14220
14360
|
AUTOMATION_MODEL_ATTENTION_CAPABILITY,
|
|
14221
|
-
REMOTE_SESSION_DESKTOP_RUNNER_CAPABILITY
|
|
14361
|
+
REMOTE_SESSION_DESKTOP_RUNNER_CAPABILITY,
|
|
14362
|
+
REMOTE_SESSION_CONTROL_RUNNER_CAPABILITY
|
|
14222
14363
|
]);
|
|
14364
|
+
var AUTOMATION_DESKTOP_RUNNER_CAPABILITY_LIMIT = 3;
|
|
14223
14365
|
var automationDesktopRunnerRegistrationSchema = exports_external.object({
|
|
14224
14366
|
runnerId: idSchema.min(8),
|
|
14225
14367
|
protocolVersion: exports_external.literal(1),
|
|
14226
14368
|
supportedExecutionTargets: exports_external.array(exports_external.literal("desktop")).length(1),
|
|
14227
|
-
capabilities: exports_external.array(automationDesktopRunnerCapabilitySchema).max(
|
|
14369
|
+
capabilities: exports_external.array(automationDesktopRunnerCapabilitySchema).max(AUTOMATION_DESKTOP_RUNNER_CAPABILITY_LIMIT).default([]),
|
|
14228
14370
|
appVersion: exports_external.string().trim().min(1).max(80),
|
|
14229
14371
|
platform: exports_external.enum(["darwin", "win32", "linux"]),
|
|
14230
14372
|
concurrency: exports_external.number().int().min(1).max(4)
|
|
@@ -14240,10 +14382,11 @@ var automationRunnerNotificationSchema = exports_external.object({
|
|
|
14240
14382
|
}).strict();
|
|
14241
14383
|
var automationRunnerWorkItemSchema = exports_external.union([
|
|
14242
14384
|
exports_external.object({ runId: idSchema, executionTarget: exports_external.literal("desktop") }),
|
|
14243
|
-
exports_external.object({ kind: exports_external.literal("remote_session_create"), commandId: idSchema })
|
|
14385
|
+
exports_external.object({ kind: exports_external.literal("remote_session_create"), commandId: idSchema }),
|
|
14386
|
+
exports_external.object({ kind: exports_external.literal("remote_session_request"), requestId: idSchema })
|
|
14244
14387
|
]);
|
|
14245
14388
|
var automationRunnerWorkResponseSchema = exports_external.object({
|
|
14246
|
-
items: exports_external.array(automationRunnerWorkItemSchema).max(
|
|
14389
|
+
items: exports_external.array(automationRunnerWorkItemSchema).max(14)
|
|
14247
14390
|
});
|
|
14248
14391
|
var remoteSessionCommandAssignmentSchema = exports_external.object({
|
|
14249
14392
|
commandId: idSchema,
|
|
@@ -14289,6 +14432,127 @@ var remoteSessionCommandCompleteResponseSchema = exports_external.object({
|
|
|
14289
14432
|
workspaceId: exports_external.string().max(240).nullable()
|
|
14290
14433
|
})
|
|
14291
14434
|
});
|
|
14435
|
+
var REMOTE_SESSION_FINAL_TEXT_MAX_LENGTH = 20000;
|
|
14436
|
+
var remoteSessionStatusSchema = exports_external.enum(["running", "waiting", "idle", "error"]);
|
|
14437
|
+
var remoteSessionWaitingForSchema = exports_external.enum(["permission", "question"]);
|
|
14438
|
+
var remoteSessionEngineSchema = exports_external.enum(["v1", "v2"]);
|
|
14439
|
+
var remoteSessionModelSchema = exports_external.object({
|
|
14440
|
+
providerId: idSchema,
|
|
14441
|
+
modelId: idSchema,
|
|
14442
|
+
variant: exports_external.string().trim().min(1).max(60).nullable().optional()
|
|
14443
|
+
});
|
|
14444
|
+
var remoteSessionCommandSessionReportSchema = exports_external.object({
|
|
14445
|
+
status: remoteSessionStatusSchema,
|
|
14446
|
+
waitingFor: remoteSessionWaitingForSchema.nullable().optional(),
|
|
14447
|
+
engine: remoteSessionEngineSchema.optional(),
|
|
14448
|
+
model: remoteSessionModelSchema.nullable().optional(),
|
|
14449
|
+
finalText: exports_external.string().max(REMOTE_SESSION_FINAL_TEXT_MAX_LENGTH).optional(),
|
|
14450
|
+
error: remoteSessionCommandErrorSchema.nullable().optional(),
|
|
14451
|
+
messageCount: exports_external.number().int().min(0).optional(),
|
|
14452
|
+
observedAt: timestampSchema
|
|
14453
|
+
});
|
|
14454
|
+
var remoteSessionCommandSessionReportResponseSchema = exports_external.object({ ok: exports_external.literal(true) });
|
|
14455
|
+
var REMOTE_SESSION_REQUEST_RESULT_MAX_BYTES = 256 * 1024;
|
|
14456
|
+
var REMOTE_SESSION_TRANSCRIPT_TEXT_MAX_LENGTH = 20000;
|
|
14457
|
+
var REMOTE_SESSION_TOOL_SUMMARY_MAX_LENGTH = 2000;
|
|
14458
|
+
var REMOTE_SESSION_TRANSCRIPT_PAGE_MAX = 100;
|
|
14459
|
+
var remoteSessionRequestActionSchema = exports_external.enum(["read", "send", "stop"]);
|
|
14460
|
+
var remoteSessionMessageIdSchema = exports_external.string().regex(/^msg_[a-zA-Z0-9]+$/).max(160);
|
|
14461
|
+
var remoteSessionReadInputSchema = exports_external.object({
|
|
14462
|
+
from: exports_external.enum(["start", "end"]),
|
|
14463
|
+
cursor: exports_external.string().trim().min(1).max(160).nullable(),
|
|
14464
|
+
limit: exports_external.number().int().min(1).max(REMOTE_SESSION_TRANSCRIPT_PAGE_MAX)
|
|
14465
|
+
});
|
|
14466
|
+
var remoteSessionSendInputSchema = exports_external.object({
|
|
14467
|
+
prompt: exports_external.string().min(1).max(1e5),
|
|
14468
|
+
messageId: remoteSessionMessageIdSchema.nullable(),
|
|
14469
|
+
model: remoteSessionModelSchema.nullable()
|
|
14470
|
+
});
|
|
14471
|
+
var remoteSessionStopInputSchema = exports_external.object({
|
|
14472
|
+
messageId: exports_external.string().trim().min(1).max(160).nullable()
|
|
14473
|
+
});
|
|
14474
|
+
var remoteSessionRequestInputSchema = exports_external.discriminatedUnion("action", [
|
|
14475
|
+
exports_external.object({ action: exports_external.literal("read"), input: remoteSessionReadInputSchema }),
|
|
14476
|
+
exports_external.object({ action: exports_external.literal("send"), input: remoteSessionSendInputSchema }),
|
|
14477
|
+
exports_external.object({ action: exports_external.literal("stop"), input: remoteSessionStopInputSchema })
|
|
14478
|
+
]);
|
|
14479
|
+
var remoteSessionRequestAssignmentBase = {
|
|
14480
|
+
requestId: idSchema,
|
|
14481
|
+
kind: exports_external.literal("remote_session_request"),
|
|
14482
|
+
commandId: idSchema,
|
|
14483
|
+
sessionId: exports_external.string().trim().min(1).max(240),
|
|
14484
|
+
workspaceId: exports_external.string().trim().min(1).max(240),
|
|
14485
|
+
engine: remoteSessionEngineSchema.nullable(),
|
|
14486
|
+
expiresAt: timestampSchema
|
|
14487
|
+
};
|
|
14488
|
+
var remoteSessionRequestAssignmentSchema = exports_external.discriminatedUnion("action", [
|
|
14489
|
+
exports_external.object({ ...remoteSessionRequestAssignmentBase, action: exports_external.literal("read"), input: remoteSessionReadInputSchema }),
|
|
14490
|
+
exports_external.object({ ...remoteSessionRequestAssignmentBase, action: exports_external.literal("send"), input: remoteSessionSendInputSchema }),
|
|
14491
|
+
exports_external.object({ ...remoteSessionRequestAssignmentBase, action: exports_external.literal("stop"), input: remoteSessionStopInputSchema })
|
|
14492
|
+
]);
|
|
14493
|
+
var remoteSessionRequestClaimResponseSchema = exports_external.object({
|
|
14494
|
+
assignment: remoteSessionRequestAssignmentSchema
|
|
14495
|
+
});
|
|
14496
|
+
var boundedSummarySchema = exports_external.string().max(REMOTE_SESSION_TOOL_SUMMARY_MAX_LENGTH).nullable();
|
|
14497
|
+
var remoteSessionTranscriptToolCallSchema = exports_external.object({
|
|
14498
|
+
id: exports_external.string().max(240),
|
|
14499
|
+
name: exports_external.string().max(240),
|
|
14500
|
+
status: exports_external.string().max(60).nullable(),
|
|
14501
|
+
input: boundedSummarySchema,
|
|
14502
|
+
output: boundedSummarySchema,
|
|
14503
|
+
error: boundedSummarySchema,
|
|
14504
|
+
truncated: exports_external.boolean()
|
|
14505
|
+
});
|
|
14506
|
+
var remoteSessionTranscriptMessageSchema = exports_external.object({
|
|
14507
|
+
id: exports_external.string().max(240),
|
|
14508
|
+
role: exports_external.enum(["user", "assistant"]),
|
|
14509
|
+
createdAt: timestampSchema.nullable(),
|
|
14510
|
+
text: exports_external.string().max(REMOTE_SESSION_TRANSCRIPT_TEXT_MAX_LENGTH),
|
|
14511
|
+
truncated: exports_external.boolean(),
|
|
14512
|
+
toolCalls: exports_external.array(remoteSessionTranscriptToolCallSchema).max(200),
|
|
14513
|
+
error: remoteSessionCommandErrorSchema.nullable()
|
|
14514
|
+
});
|
|
14515
|
+
var remoteSessionReadResultSchema = exports_external.object({
|
|
14516
|
+
title: exports_external.string().max(240).nullable(),
|
|
14517
|
+
status: remoteSessionStatusSchema,
|
|
14518
|
+
waitingFor: remoteSessionWaitingForSchema.nullable(),
|
|
14519
|
+
lastError: remoteSessionCommandErrorSchema.nullable(),
|
|
14520
|
+
messageCount: exports_external.number().int().min(0),
|
|
14521
|
+
from: exports_external.enum(["start", "end"]),
|
|
14522
|
+
messages: exports_external.array(remoteSessionTranscriptMessageSchema).max(REMOTE_SESSION_TRANSCRIPT_PAGE_MAX),
|
|
14523
|
+
nextCursor: exports_external.string().max(160).nullable()
|
|
14524
|
+
});
|
|
14525
|
+
var remoteSessionSendResultSchema = exports_external.object({
|
|
14526
|
+
messageId: exports_external.string().max(160).nullable(),
|
|
14527
|
+
alreadyPresent: exports_external.boolean()
|
|
14528
|
+
});
|
|
14529
|
+
var remoteSessionStopResultSchema = exports_external.object({
|
|
14530
|
+
stopped: exports_external.boolean(),
|
|
14531
|
+
reason: exports_external.enum(["different_turn"]).nullable()
|
|
14532
|
+
});
|
|
14533
|
+
var remoteSessionRequestResultSchema = exports_external.discriminatedUnion("action", [
|
|
14534
|
+
exports_external.object({ action: exports_external.literal("read"), result: remoteSessionReadResultSchema }),
|
|
14535
|
+
exports_external.object({ action: exports_external.literal("send"), result: remoteSessionSendResultSchema }),
|
|
14536
|
+
exports_external.object({ action: exports_external.literal("stop"), result: remoteSessionStopResultSchema })
|
|
14537
|
+
]);
|
|
14538
|
+
var remoteSessionRequestCompleteRequestSchema = exports_external.discriminatedUnion("status", [
|
|
14539
|
+
exports_external.object({
|
|
14540
|
+
status: exports_external.literal("done"),
|
|
14541
|
+
outcome: remoteSessionRequestResultSchema,
|
|
14542
|
+
error: exports_external.never().optional()
|
|
14543
|
+
}),
|
|
14544
|
+
exports_external.object({
|
|
14545
|
+
status: exports_external.literal("failed"),
|
|
14546
|
+
outcome: exports_external.never().optional(),
|
|
14547
|
+
error: remoteSessionCommandErrorSchema
|
|
14548
|
+
})
|
|
14549
|
+
]).refine((body) => body.status !== "done" || new TextEncoder().encode(JSON.stringify(body.outcome)).byteLength <= REMOTE_SESSION_REQUEST_RESULT_MAX_BYTES, { message: `The result must be at most ${REMOTE_SESSION_REQUEST_RESULT_MAX_BYTES} bytes`, path: ["outcome"] });
|
|
14550
|
+
var remoteSessionRequestCompleteResponseSchema = exports_external.object({
|
|
14551
|
+
request: exports_external.object({ id: idSchema, status: exports_external.enum(["done", "failed"]) })
|
|
14552
|
+
});
|
|
14553
|
+
var remoteSessionRequestPendingResponseSchema = exports_external.object({
|
|
14554
|
+
items: exports_external.array(exports_external.object({ kind: exports_external.literal("remote_session_request"), requestId: idSchema })).max(5)
|
|
14555
|
+
});
|
|
14292
14556
|
var automationDesktopRunnerAssignmentSchema = exports_external.object({
|
|
14293
14557
|
executionTarget: exports_external.literal("desktop"),
|
|
14294
14558
|
runId: idSchema,
|
|
@@ -14544,14 +14808,14 @@ var OPENWORK_CLOUD_CONNECTION_INSTRUCTION = `The OpenWork Cloud connection is ve
|
|
|
14544
14808
|
var OPENWORK_CONNECT_SIGN_IN_INSTRUCTION = `${OPENWORK_EXTENSION_DISCOVERY_INSTRUCTION} OpenWork Cloud is not signed in or no desired agent access configuration exists for this workspace. Direct the user to sign in to OpenWork and connect the service in Settings → Connect.`;
|
|
14545
14809
|
var OPENWORK_CONNECT_DISABLED_INSTRUCTION = `${OPENWORK_EXTENSION_DISCOVERY_INSTRUCTION} OpenWork Cloud agent access is explicitly disabled for this workspace. Explain that the user can enable agent access in Settings → Connect.`;
|
|
14546
14810
|
var OPENWORK_CLOUD_MCP_NAME = "openwork-cloud";
|
|
14547
|
-
function
|
|
14811
|
+
function isRecord3(value) {
|
|
14548
14812
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14549
14813
|
}
|
|
14550
14814
|
function readString(value) {
|
|
14551
14815
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
14552
14816
|
}
|
|
14553
14817
|
function getRecordProperty(value, key) {
|
|
14554
|
-
return
|
|
14818
|
+
return isRecord3(value) ? value[key] : undefined;
|
|
14555
14819
|
}
|
|
14556
14820
|
function readNestedString(value, keys) {
|
|
14557
14821
|
let current = value;
|
|
@@ -14561,9 +14825,9 @@ function readNestedString(value, keys) {
|
|
|
14561
14825
|
}
|
|
14562
14826
|
function readContext(input) {
|
|
14563
14827
|
const context = getRecordProperty(input, "context");
|
|
14564
|
-
const
|
|
14565
|
-
const directory = readNestedString(input, ["directory"]) ?? readNestedString(context, ["directory"]) ?? readNestedString(
|
|
14566
|
-
const worktree = readNestedString(input, ["worktree"]) ?? readNestedString(context, ["worktree"]) ?? readNestedString(
|
|
14828
|
+
const session2 = getRecordProperty(input, "session");
|
|
14829
|
+
const directory = readNestedString(input, ["directory"]) ?? readNestedString(context, ["directory"]) ?? readNestedString(session2, ["directory"]);
|
|
14830
|
+
const worktree = readNestedString(input, ["worktree"]) ?? readNestedString(context, ["worktree"]) ?? readNestedString(session2, ["worktree"]);
|
|
14567
14831
|
const workspaceId = readNestedString(input, ["workspaceId"]) ?? readNestedString(input, ["workspaceID"]) ?? readNestedString(context, ["workspaceId"]) ?? readNestedString(context, ["workspaceID"]);
|
|
14568
14832
|
return {
|
|
14569
14833
|
...directory ? { directory } : {},
|
|
@@ -14611,7 +14875,7 @@ async function parseResponse(response) {
|
|
|
14611
14875
|
}
|
|
14612
14876
|
}
|
|
14613
14877
|
function getStringProperty(value, key) {
|
|
14614
|
-
if (!
|
|
14878
|
+
if (!isRecord3(value))
|
|
14615
14879
|
return null;
|
|
14616
14880
|
const property = value[key];
|
|
14617
14881
|
return typeof property === "string" ? property : null;
|
|
@@ -14624,11 +14888,11 @@ function readEngineDirectory(input, fallback) {
|
|
|
14624
14888
|
return context.directory ?? context.worktree ?? readString(fallback);
|
|
14625
14889
|
}
|
|
14626
14890
|
function engineStatusPayload(result) {
|
|
14627
|
-
if (!
|
|
14891
|
+
if (!isRecord3(result))
|
|
14628
14892
|
return result;
|
|
14629
|
-
const
|
|
14630
|
-
if (
|
|
14631
|
-
return
|
|
14893
|
+
const data2 = result.data;
|
|
14894
|
+
if (data2 !== undefined)
|
|
14895
|
+
return data2;
|
|
14632
14896
|
if (result.error !== undefined)
|
|
14633
14897
|
throw new Error("OpenCode MCP status request failed");
|
|
14634
14898
|
const responseOk = getRecordProperty(result.response, "ok");
|
|
@@ -14845,7 +15109,7 @@ function sessionContribution() {
|
|
|
14845
15109
|
id: "session.search",
|
|
14846
15110
|
kind: "query",
|
|
14847
15111
|
title: "Find sessions",
|
|
14848
|
-
description: "Search session titles and transcripts without changing the visible workbench. Every root session's title is matched; transcripts are scanned for the `scanLimit` newest sessions only, so when the result's `truncated` is true, retry with a larger `scanLimit` (max 500). Title and phrase matches rank first, then newest `updatedAt`. Each result carries `createdAt`, `archived` and `
|
|
15112
|
+
description: "Search session titles and transcripts without changing the visible workbench. Every root session's title is matched; transcripts are scanned for the `scanLimit` newest sessions only, so when the result's `truncated` is true, retry with a larger `scanLimit` (max 500). Title and phrase matches rank first, then newest `updatedAt`. Each result carries `createdAt`, `archived`, `parentId` and `engine` (v1 or v2, the engine that holds the session).",
|
|
14849
15113
|
provider,
|
|
14850
15114
|
arguments: [
|
|
14851
15115
|
argument("query", "string", true, "Text to find in session titles or messages."),
|
|
@@ -14864,7 +15128,7 @@ function sessionContribution() {
|
|
|
14864
15128
|
id: "session.read",
|
|
14865
15129
|
kind: "query",
|
|
14866
15130
|
title: "Read a session transcript",
|
|
14867
|
-
description: "Read messages from a session without opening it. The result also carries `createdAt`, `archived`, `parentId`, `status` (idle, busy, retry, waiting), `working` (check it before session.archive), and `model` ({ providerId, modelId, variant, displayName?, providerName? } the session is bound to, variant being its reasoning effort; null before a model is bound). Pass `summary: true` to get only the first user message and the last assistant message (what was asked, what was concluded) in one call. Both modes include `lastError` ({ code, message } or null) from the latest assistant info.error before text filtering: end reads inspect only the fetched newest `count` messages; start/summary inspect the whole transcript, even outside displayed text. Null means no assistant error observed in that window; a later assistant without an error clears it. Codes are allowlisted error names (otherwise UnknownError); messages are fixed labels under 160 characters, never arbitrary provider details. Snapshot errors only: event-only failures, including pre-assistant model-not-found, are not observable here.",
|
|
15131
|
+
description: "Read messages from a session without opening it. Finds the session on either engine. The result also carries `engine` (v1 or v2), `createdAt`, `archived`, `parentId`, `status` (idle, busy, retry, waiting), `working` (check it before session.archive), and `model` ({ providerId, modelId, variant, displayName?, providerName? } the session is bound to, variant being its reasoning effort; null before a model is bound). Pass `summary: true` to get only the first user message and the last assistant message (what was asked, what was concluded) in one call. Both modes include `lastError` ({ code, message } or null) from the latest assistant info.error before text filtering: end reads inspect only the fetched newest `count` messages; start/summary inspect the whole transcript, even outside displayed text. Null means no assistant error observed in that window; a later assistant without an error clears it. Codes are allowlisted error names (otherwise UnknownError); messages are fixed labels under 160 characters, never arbitrary provider details. Snapshot errors only: event-only failures, including pre-assistant model-not-found, are not observable here.",
|
|
14868
15132
|
provider,
|
|
14869
15133
|
arguments: [
|
|
14870
15134
|
argument("sessionId", "string", true, "Session id returned by session.search."),
|
|
@@ -15123,18 +15387,18 @@ A dispatch receipt or a website callback returning does not prove the requested
|
|
|
15123
15387
|
If sign-in, CAPTCHA or a sensitive input is needed, call browser_handoff. Ask the user to sign in directly in the browser and resume there; never request passwords, cookies, tokens or one-time codes in chat. Do not put page content or authentication data into logs or evidence.
|
|
15124
15388
|
Models without vision should use site tools and text observations. When a task requires visual interpretation they cannot perform, request user help. No model selection changes permission or session boundaries.`;
|
|
15125
15389
|
var WEBMCP_EXECUTION_TIMEOUT_MS = 125000;
|
|
15126
|
-
function
|
|
15390
|
+
function isRecord4(value) {
|
|
15127
15391
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15128
15392
|
}
|
|
15129
15393
|
var MAX_PRESERVED_MCP_APP_RESULT_BYTES = 1024 * 1024;
|
|
15130
15394
|
function preserveMcpResult(output) {
|
|
15131
|
-
if (!
|
|
15395
|
+
if (!isRecord4(output) || !Array.isArray(output.content))
|
|
15132
15396
|
return;
|
|
15133
15397
|
const appResult = {
|
|
15134
15398
|
content: output.content,
|
|
15135
15399
|
...typeof output.isError === "boolean" ? { isError: output.isError } : {},
|
|
15136
15400
|
...output.structuredContent !== undefined ? { structuredContent: output.structuredContent } : {},
|
|
15137
|
-
...
|
|
15401
|
+
...isRecord4(output._meta) ? { _meta: output._meta } : {}
|
|
15138
15402
|
};
|
|
15139
15403
|
try {
|
|
15140
15404
|
if (new TextEncoder().encode(JSON.stringify(appResult)).byteLength > MAX_PRESERVED_MCP_APP_RESULT_BYTES)
|
|
@@ -15142,7 +15406,7 @@ function preserveMcpResult(output) {
|
|
|
15142
15406
|
} catch {
|
|
15143
15407
|
return;
|
|
15144
15408
|
}
|
|
15145
|
-
const existing =
|
|
15409
|
+
const existing = isRecord4(output.metadata) ? output.metadata : {};
|
|
15146
15410
|
output.metadata = {
|
|
15147
15411
|
...existing,
|
|
15148
15412
|
openworkMcpApp: appResult
|
|
@@ -15154,7 +15418,7 @@ var affordanceExternalWriteEffects = { data: "write", ui: "none", external: true
|
|
|
15154
15418
|
var affordanceWriteNavigateEffects = { data: "write", ui: "navigate", external: false };
|
|
15155
15419
|
var affordanceProposalEffects = { data: "none", ui: "none", external: false };
|
|
15156
15420
|
function affordanceResult(id, result, effects) {
|
|
15157
|
-
if (
|
|
15421
|
+
if (isRecord4(result) && result.ok === false) {
|
|
15158
15422
|
return {
|
|
15159
15423
|
ok: false,
|
|
15160
15424
|
id,
|
|
@@ -15169,7 +15433,7 @@ function unavailableAffordance(id, error48) {
|
|
|
15169
15433
|
return { ok: false, id, error: error48, code: "unavailable" };
|
|
15170
15434
|
}
|
|
15171
15435
|
function optionalStringProperty(value, key) {
|
|
15172
|
-
if (!
|
|
15436
|
+
if (!isRecord4(value))
|
|
15173
15437
|
return;
|
|
15174
15438
|
const property = value[key];
|
|
15175
15439
|
return typeof property === "string" && property.trim().length > 0 ? property : undefined;
|
|
@@ -15178,15 +15442,15 @@ function isOpenWorkEngineMcpStatusFunction(value) {
|
|
|
15178
15442
|
return typeof value === "function";
|
|
15179
15443
|
}
|
|
15180
15444
|
function readEngineMcpStatusClient(value) {
|
|
15181
|
-
const client =
|
|
15182
|
-
const mcp =
|
|
15183
|
-
const status =
|
|
15445
|
+
const client = isRecord4(value) ? value.client : undefined;
|
|
15446
|
+
const mcp = isRecord4(client) ? client.mcp : undefined;
|
|
15447
|
+
const status = isRecord4(mcp) ? mcp.status : undefined;
|
|
15184
15448
|
if (!isOpenWorkEngineMcpStatusFunction(status))
|
|
15185
15449
|
return;
|
|
15186
15450
|
return { mcp: { status: (request) => status.call(mcp, request) } };
|
|
15187
15451
|
}
|
|
15188
15452
|
function normalizeOpenCodeContext(value) {
|
|
15189
|
-
const nested =
|
|
15453
|
+
const nested = isRecord4(value) && isRecord4(value.context) ? value.context : value;
|
|
15190
15454
|
const agent = optionalStringProperty(nested, "agent");
|
|
15191
15455
|
const sessionID = optionalStringProperty(nested, "sessionID");
|
|
15192
15456
|
const messageID = optionalStringProperty(nested, "messageID");
|
|
@@ -15219,6 +15483,9 @@ async function uiControlRequest(kind, input) {
|
|
|
15219
15483
|
}
|
|
15220
15484
|
}
|
|
15221
15485
|
async function serverGet(path) {
|
|
15486
|
+
const transport = openworkReadTransport.getStore();
|
|
15487
|
+
if (transport)
|
|
15488
|
+
return transport.get(path);
|
|
15222
15489
|
const { url: url2, token } = requireOpenWorkServer2();
|
|
15223
15490
|
const response = await fetch(`${url2}${path}`, {
|
|
15224
15491
|
headers: { Authorization: `Bearer ${token}` }
|
|
@@ -15241,8 +15508,8 @@ async function readEngineMcpDescriptors(client, directory) {
|
|
|
15241
15508
|
return [];
|
|
15242
15509
|
try {
|
|
15243
15510
|
const result = await client.mcp.status(directory ? { query: { directory } } : undefined);
|
|
15244
|
-
const payload =
|
|
15245
|
-
if (!
|
|
15511
|
+
const payload = isRecord4(result) && result.data !== undefined ? result.data : result;
|
|
15512
|
+
if (!isRecord4(payload))
|
|
15246
15513
|
return [];
|
|
15247
15514
|
return Object.entries(payload).map(([name, entry]) => {
|
|
15248
15515
|
const status = typeof entry === "string" ? entry : optionalStringProperty(entry, "status");
|
|
@@ -15260,7 +15527,7 @@ async function readOpenworkAgentContext(engineMcpStatusClient, engineMcpStatusDi
|
|
|
15260
15527
|
]);
|
|
15261
15528
|
const contributions = buildOpenworkProviderContributions(skills, mcps);
|
|
15262
15529
|
const providerAffordances = contributions.flatMap((contribution) => contribution.affordances);
|
|
15263
|
-
const uiContext =
|
|
15530
|
+
const uiContext = isRecord4(uiResult) && isRecord4(uiResult.context) ? uiResult.context : null;
|
|
15264
15531
|
if (!uiContext) {
|
|
15265
15532
|
return {
|
|
15266
15533
|
ok: true,
|
|
@@ -15297,7 +15564,7 @@ async function queryOpenworkAffordance(rawArgs) {
|
|
|
15297
15564
|
return unavailableAffordance(request.id, "This affordance declares a dedicated Connect executor. Call the tool named in openwork_context.");
|
|
15298
15565
|
}
|
|
15299
15566
|
const result = await uiControlRequest("query", request);
|
|
15300
|
-
return
|
|
15567
|
+
return isRecord4(result) && typeof result.ok === "boolean" ? result : unavailableAffordance(request.id, "OpenWork UI query returned an invalid response.");
|
|
15301
15568
|
}
|
|
15302
15569
|
async function executeOpenworkAffordance(rawArgs, context) {
|
|
15303
15570
|
const request = openworkAffordanceRequestSchema2.parse(rawArgs);
|
|
@@ -15324,7 +15591,7 @@ async function executeOpenworkAffordance(rawArgs, context) {
|
|
|
15324
15591
|
return unavailableAffordance(request.id, "This affordance declares a dedicated Connect executor. Call the tool named in openwork_context.");
|
|
15325
15592
|
}
|
|
15326
15593
|
const result = await uiControlRequest("command", { ...request, ...affordanceOrigin(context) });
|
|
15327
|
-
return
|
|
15594
|
+
return isRecord4(result) && typeof result.ok === "boolean" ? result : unavailableAffordance(request.id, "OpenWork UI command returned an invalid response.");
|
|
15328
15595
|
}
|
|
15329
15596
|
function affordanceOrigin(context) {
|
|
15330
15597
|
const sessionId = context.sessionID?.trim();
|
|
@@ -15346,46 +15613,47 @@ function buildSessionSnippet(text, index, length) {
|
|
|
15346
15613
|
function workspaceLabel(workspace) {
|
|
15347
15614
|
return workspace.displayName?.trim() || workspace.name?.trim() || workspace.path?.trim() || workspace.id;
|
|
15348
15615
|
}
|
|
15349
|
-
function sessionTitle(
|
|
15350
|
-
return
|
|
15616
|
+
function sessionTitle(session2) {
|
|
15617
|
+
return session2.title?.trim() || session2.id;
|
|
15351
15618
|
}
|
|
15352
|
-
function sessionUpdatedAt(
|
|
15353
|
-
return
|
|
15619
|
+
function sessionUpdatedAt(session2) {
|
|
15620
|
+
return session2.time?.updated ?? session2.time?.created ?? 0;
|
|
15354
15621
|
}
|
|
15355
|
-
function sessionCreatedAt(
|
|
15356
|
-
return
|
|
15622
|
+
function sessionCreatedAt(session2) {
|
|
15623
|
+
return session2.time?.created ?? session2.time?.updated ?? 0;
|
|
15357
15624
|
}
|
|
15358
|
-
function sessionArchived(
|
|
15359
|
-
const archived =
|
|
15625
|
+
function sessionArchived(session2) {
|
|
15626
|
+
const archived = session2.time?.archived;
|
|
15360
15627
|
return typeof archived === "number" && archived > 0;
|
|
15361
15628
|
}
|
|
15362
|
-
function sessionMetadata(workspace,
|
|
15629
|
+
function sessionMetadata(workspace, session2, engine) {
|
|
15363
15630
|
return {
|
|
15364
15631
|
workspaceId: workspace.id,
|
|
15632
|
+
engine,
|
|
15365
15633
|
workspace: workspaceLabel(workspace),
|
|
15366
|
-
sessionId:
|
|
15367
|
-
title: sessionTitle(
|
|
15368
|
-
createdAt: sessionCreatedAt(
|
|
15369
|
-
updatedAt: sessionUpdatedAt(
|
|
15370
|
-
archived: sessionArchived(
|
|
15371
|
-
parentId:
|
|
15634
|
+
sessionId: session2.id,
|
|
15635
|
+
title: sessionTitle(session2),
|
|
15636
|
+
createdAt: sessionCreatedAt(session2),
|
|
15637
|
+
updatedAt: sessionUpdatedAt(session2),
|
|
15638
|
+
archived: sessionArchived(session2),
|
|
15639
|
+
parentId: session2.parentID ?? null
|
|
15372
15640
|
};
|
|
15373
15641
|
}
|
|
15374
|
-
function sessionPassesFilters(
|
|
15375
|
-
const createdAt = sessionCreatedAt(
|
|
15642
|
+
function sessionPassesFilters(session2, args) {
|
|
15643
|
+
const createdAt = sessionCreatedAt(session2);
|
|
15376
15644
|
if (args.createdAfter !== undefined && createdAt < sessionTimestampMs(args.createdAfter))
|
|
15377
15645
|
return false;
|
|
15378
15646
|
if (args.createdBefore !== undefined && createdAt > sessionTimestampMs(args.createdBefore))
|
|
15379
15647
|
return false;
|
|
15380
15648
|
const archived = args.archived ?? "include";
|
|
15381
|
-
if (archived === "exclude" && sessionArchived(
|
|
15649
|
+
if (archived === "exclude" && sessionArchived(session2))
|
|
15382
15650
|
return false;
|
|
15383
|
-
if (archived === "only" && !sessionArchived(
|
|
15651
|
+
if (archived === "only" && !sessionArchived(session2))
|
|
15384
15652
|
return false;
|
|
15385
15653
|
return true;
|
|
15386
15654
|
}
|
|
15387
|
-
function sessionModelOf(
|
|
15388
|
-
const model =
|
|
15655
|
+
function sessionModelOf(session2) {
|
|
15656
|
+
const model = session2.model;
|
|
15389
15657
|
if (!model)
|
|
15390
15658
|
return null;
|
|
15391
15659
|
const variant = model.variant?.trim();
|
|
@@ -15432,19 +15700,19 @@ function findTextMatch(text, queryLower, mode) {
|
|
|
15432
15700
|
}
|
|
15433
15701
|
return Number.isFinite(firstIndex) ? { index: firstIndex, length: firstLength, phrase: false } : null;
|
|
15434
15702
|
}
|
|
15435
|
-
function titleSearchResult(workspace,
|
|
15436
|
-
const text = `${sessionTitle(
|
|
15703
|
+
function titleSearchResult(workspace, session2, engine, queryLower, mode) {
|
|
15704
|
+
const text = `${sessionTitle(session2)} ${workspaceLabel(workspace)}`;
|
|
15437
15705
|
const match = findTextMatch(text, queryLower, mode);
|
|
15438
15706
|
if (!match)
|
|
15439
15707
|
return null;
|
|
15440
15708
|
return {
|
|
15441
|
-
...sessionMetadata(workspace,
|
|
15709
|
+
...sessionMetadata(workspace, session2, engine),
|
|
15442
15710
|
kind: "title",
|
|
15443
15711
|
phrase: match.phrase,
|
|
15444
15712
|
snippet: buildSessionSnippet(text, match.index, match.length)
|
|
15445
15713
|
};
|
|
15446
15714
|
}
|
|
15447
|
-
function messageSearchResult(workspace,
|
|
15715
|
+
function messageSearchResult(workspace, session2, engine, messages, queryLower, mode) {
|
|
15448
15716
|
let fallback = null;
|
|
15449
15717
|
for (const [index, message] of messages.entries()) {
|
|
15450
15718
|
const role = message.info.role;
|
|
@@ -15457,7 +15725,7 @@ function messageSearchResult(workspace, session, messages, queryLower, mode) {
|
|
|
15457
15725
|
if (!match)
|
|
15458
15726
|
continue;
|
|
15459
15727
|
const result = {
|
|
15460
|
-
...sessionMetadata(workspace,
|
|
15728
|
+
...sessionMetadata(workspace, session2, engine),
|
|
15461
15729
|
kind: "message",
|
|
15462
15730
|
phrase: match.phrase,
|
|
15463
15731
|
role,
|
|
@@ -15488,13 +15756,35 @@ function filterWorkspaces(workspaces, workspaceId) {
|
|
|
15488
15756
|
return labels.includes(query);
|
|
15489
15757
|
});
|
|
15490
15758
|
}
|
|
15491
|
-
|
|
15759
|
+
function ownEngineReader() {
|
|
15760
|
+
const transport = openworkReadTransport.getStore();
|
|
15761
|
+
if (!transport)
|
|
15762
|
+
return { engine: "v1", get: serverGet };
|
|
15763
|
+
const activity = transport.activity;
|
|
15764
|
+
return {
|
|
15765
|
+
engine: transport.engine ?? "v1",
|
|
15766
|
+
get: (path) => transport.get(path),
|
|
15767
|
+
...activity ? { activity: (workspaceId, sessionId) => activity(workspaceId, sessionId) } : {}
|
|
15768
|
+
};
|
|
15769
|
+
}
|
|
15770
|
+
function engineReaders() {
|
|
15771
|
+
const own = ownEngineReader();
|
|
15772
|
+
const transport = openworkReadTransport.getStore();
|
|
15773
|
+
if (transport)
|
|
15774
|
+
return transport.other ? [own, transport.other] : [own];
|
|
15775
|
+
return [own, {
|
|
15776
|
+
engine: "v2",
|
|
15777
|
+
get: createV2ReadAdapter(serverGet),
|
|
15778
|
+
activity: (workspaceId, sessionId) => readV2SessionActivity(serverGet, workspaceId, sessionId)
|
|
15779
|
+
}];
|
|
15780
|
+
}
|
|
15781
|
+
async function listWorkspaceSessions(reader, workspace, limit) {
|
|
15492
15782
|
const query = new URLSearchParams({ roots: "true", limit: String(limit) });
|
|
15493
|
-
return exports_external.array(sessionInfoSchema).parse(await
|
|
15783
|
+
return exports_external.array(sessionInfoSchema).parse(await reader.get(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session?${query.toString()}`));
|
|
15494
15784
|
}
|
|
15495
|
-
async function assertSessionInWorkspace(workspace,
|
|
15785
|
+
async function assertSessionInWorkspace(workspace, session2) {
|
|
15496
15786
|
const workspacePath = workspace.path?.trim();
|
|
15497
|
-
const sessionDirectory =
|
|
15787
|
+
const sessionDirectory = session2.directory?.trim();
|
|
15498
15788
|
if (!workspacePath || !sessionDirectory)
|
|
15499
15789
|
return;
|
|
15500
15790
|
const [root, dir] = await Promise.all([
|
|
@@ -15505,26 +15795,26 @@ async function assertSessionInWorkspace(workspace, session) {
|
|
|
15505
15795
|
const normalizedDir = normalizeDirPath(dir);
|
|
15506
15796
|
if (normalizedDir === normalizedRoot || normalizedDir.startsWith(`${normalizedRoot}/`))
|
|
15507
15797
|
return;
|
|
15508
|
-
throw new Error(`Session ${
|
|
15798
|
+
throw new Error(`Session ${session2.id} not found in workspace ${workspaceLabel(workspace)}`);
|
|
15509
15799
|
}
|
|
15510
|
-
async function readWorkspaceSession(workspace, sessionId) {
|
|
15511
|
-
const
|
|
15512
|
-
await assertSessionInWorkspace(workspace,
|
|
15513
|
-
return
|
|
15800
|
+
async function readWorkspaceSession(workspace, sessionId, reader = ownEngineReader()) {
|
|
15801
|
+
const session2 = sessionInfoSchema.parse(await reader.get(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session/${encodeURIComponent(sessionId)}`));
|
|
15802
|
+
await assertSessionInWorkspace(workspace, session2);
|
|
15803
|
+
return session2;
|
|
15514
15804
|
}
|
|
15515
15805
|
var MAX_SESSION_DESCENDANTS = 256;
|
|
15516
15806
|
var sessionChildrenSchema = exports_external.array(exports_external.object({
|
|
15517
15807
|
id: exports_external.string().trim().min(1),
|
|
15518
15808
|
time: exports_external.object({ archived: exports_external.number().optional() }).optional()
|
|
15519
15809
|
}).passthrough());
|
|
15520
|
-
async function readSessionDescendantIds(base, sessionId) {
|
|
15810
|
+
async function readSessionDescendantIds(get, base, sessionId) {
|
|
15521
15811
|
const queue = [sessionId];
|
|
15522
15812
|
const seen = new Set(queue);
|
|
15523
15813
|
const ids = [];
|
|
15524
15814
|
let unknown2 = 0;
|
|
15525
15815
|
let index = 0;
|
|
15526
15816
|
for (;index < queue.length && index < MAX_SESSION_DESCENDANTS; index += 1) {
|
|
15527
|
-
const parsed = sessionChildrenSchema.safeParse(await
|
|
15817
|
+
const parsed = sessionChildrenSchema.safeParse(await get(`${base}/session/${encodeURIComponent(queue[index])}/children`).catch(() => null));
|
|
15528
15818
|
if (!parsed.success) {
|
|
15529
15819
|
unknown2 += 1;
|
|
15530
15820
|
continue;
|
|
@@ -15545,32 +15835,34 @@ async function readSessionDescendantIds(base, sessionId) {
|
|
|
15545
15835
|
}
|
|
15546
15836
|
return { ids, unknown: unknown2 };
|
|
15547
15837
|
}
|
|
15548
|
-
async function readSessionActivity(workspace,
|
|
15838
|
+
async function readSessionActivity(reader, workspace, session2) {
|
|
15839
|
+
if (reader.activity)
|
|
15840
|
+
return reader.activity(workspace.id, session2.id);
|
|
15549
15841
|
const base = `/workspace/${encodeURIComponent(workspace.id)}/opencode`;
|
|
15550
|
-
const probe = (path) =>
|
|
15842
|
+
const probe = (path) => reader.get(`${base}${path}`).catch(() => null);
|
|
15551
15843
|
const [statuses, permissions, questions, descendants] = await Promise.all([
|
|
15552
15844
|
probe("/session/status"),
|
|
15553
15845
|
probe("/permission"),
|
|
15554
15846
|
probe("/question"),
|
|
15555
|
-
|
|
15847
|
+
session2.time?.archived ? { ids: [], unknown: 0 } : readSessionDescendantIds((path) => reader.get(path), base, session2.id)
|
|
15556
15848
|
]);
|
|
15557
|
-
return sessionActivityFrom(statuses, permissions, questions,
|
|
15849
|
+
return sessionActivityFrom(statuses, permissions, questions, session2.id, descendants.ids, descendants.unknown);
|
|
15558
15850
|
}
|
|
15559
|
-
async function readSessionMessages(workspace, sessionId, limit) {
|
|
15851
|
+
async function readSessionMessages(reader, workspace, sessionId, limit) {
|
|
15560
15852
|
const query = limit === undefined ? "" : `?${new URLSearchParams({ limit: String(limit) }).toString()}`;
|
|
15561
|
-
return exports_external.array(sessionMessageSchema).parse(await
|
|
15853
|
+
return exports_external.array(sessionMessageSchema).parse(await reader.get(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session/${encodeURIComponent(sessionId)}/message${query}`));
|
|
15562
15854
|
}
|
|
15563
|
-
async function forEachWithConcurrency(
|
|
15855
|
+
async function forEachWithConcurrency(items2, concurrency, run) {
|
|
15564
15856
|
let index = 0;
|
|
15565
15857
|
const worker = async () => {
|
|
15566
|
-
while (index <
|
|
15567
|
-
const item =
|
|
15858
|
+
while (index < items2.length) {
|
|
15859
|
+
const item = items2[index];
|
|
15568
15860
|
index += 1;
|
|
15569
15861
|
if (item !== undefined)
|
|
15570
15862
|
await run(item);
|
|
15571
15863
|
}
|
|
15572
15864
|
};
|
|
15573
|
-
await Promise.all(Array.from({ length: Math.min(Math.max(1, concurrency), Math.max(1,
|
|
15865
|
+
await Promise.all(Array.from({ length: Math.min(Math.max(1, concurrency), Math.max(1, items2.length)) }, () => worker()));
|
|
15574
15866
|
}
|
|
15575
15867
|
async function searchOpenWorkSessions(rawArgs) {
|
|
15576
15868
|
const parsed = sessionSearchArgsSchema.safeParse(rawArgs);
|
|
@@ -15588,34 +15880,45 @@ async function searchOpenWorkSessions(rawArgs) {
|
|
|
15588
15880
|
}
|
|
15589
15881
|
const sessions = [];
|
|
15590
15882
|
const workspaceErrors = [];
|
|
15883
|
+
const readers = engineReaders();
|
|
15591
15884
|
await Promise.all(workspaces.map(async (workspace) => {
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
|
|
15595
|
-
|
|
15596
|
-
|
|
15597
|
-
|
|
15598
|
-
|
|
15599
|
-
|
|
15885
|
+
const listed = await Promise.all(readers.map((reader, index) => listWorkspaceSessions(reader, workspace, SESSION_SEARCH_TITLE_LIST_LIMIT).catch((error48) => {
|
|
15886
|
+
if (index === 0)
|
|
15887
|
+
workspaceErrors.push({ workspaceId: workspace.id, workspace: workspaceLabel(workspace), error: unknownErrorMessage(error48) });
|
|
15888
|
+
return [];
|
|
15889
|
+
})));
|
|
15890
|
+
const seen = new Set;
|
|
15891
|
+
listed.forEach((items2, index) => {
|
|
15892
|
+
const reader = readers[index];
|
|
15893
|
+
if (!reader)
|
|
15894
|
+
return;
|
|
15895
|
+
for (const session2 of items2) {
|
|
15896
|
+
if (seen.has(session2.id))
|
|
15897
|
+
continue;
|
|
15898
|
+
seen.add(session2.id);
|
|
15899
|
+
if (sessionPassesFilters(session2, args))
|
|
15900
|
+
sessions.push({ workspace, session: session2, reader });
|
|
15901
|
+
}
|
|
15902
|
+
});
|
|
15600
15903
|
}));
|
|
15601
15904
|
sessions.sort((left, right) => sessionUpdatedAt(right.session) - sessionUpdatedAt(left.session));
|
|
15602
15905
|
const sessionsToScan = sessions.slice(0, scanLimit);
|
|
15603
15906
|
const matches = [];
|
|
15604
15907
|
const titleMatched = new Set;
|
|
15605
|
-
for (const { workspace, session } of sessions.slice(scanLimit)) {
|
|
15606
|
-
const titleMatch = titleSearchResult(workspace,
|
|
15908
|
+
for (const { workspace, session: session2, reader } of sessions.slice(scanLimit)) {
|
|
15909
|
+
const titleMatch = titleSearchResult(workspace, session2, reader.engine, queryLower, mode);
|
|
15607
15910
|
if (!titleMatch)
|
|
15608
15911
|
continue;
|
|
15609
|
-
titleMatched.add(
|
|
15912
|
+
titleMatched.add(session2.id);
|
|
15610
15913
|
matches.push(titleMatch);
|
|
15611
15914
|
}
|
|
15612
|
-
await forEachWithConcurrency(sessionsToScan, SESSION_SEARCH_CONCURRENCY, async ({ workspace, session }) => {
|
|
15613
|
-
const titleMatch = titleSearchResult(workspace,
|
|
15915
|
+
await forEachWithConcurrency(sessionsToScan, SESSION_SEARCH_CONCURRENCY, async ({ workspace, session: session2, reader }) => {
|
|
15916
|
+
const titleMatch = titleSearchResult(workspace, session2, reader.engine, queryLower, mode);
|
|
15614
15917
|
if (titleMatch)
|
|
15615
|
-
titleMatched.add(
|
|
15918
|
+
titleMatched.add(session2.id);
|
|
15616
15919
|
try {
|
|
15617
|
-
const messages = await readSessionMessages(workspace,
|
|
15618
|
-
const messageMatch = messageSearchResult(workspace,
|
|
15920
|
+
const messages = await readSessionMessages(reader, workspace, session2.id, messageLimit);
|
|
15921
|
+
const messageMatch = messageSearchResult(workspace, session2, reader.engine, messages, queryLower, mode);
|
|
15619
15922
|
if (messageMatch)
|
|
15620
15923
|
matches.push(messageMatch);
|
|
15621
15924
|
else if (titleMatch)
|
|
@@ -15654,7 +15957,7 @@ function lastAssistantError(messages) {
|
|
|
15654
15957
|
const error48 = [...messages].reverse().find((message) => message.info.role === "assistant")?.info.error;
|
|
15655
15958
|
if (error48 === undefined || error48 === null)
|
|
15656
15959
|
return null;
|
|
15657
|
-
if (
|
|
15960
|
+
if (isRecord4(error48) && typeof error48.name === "string") {
|
|
15658
15961
|
const message = assistantErrorMessages.get(error48.name);
|
|
15659
15962
|
if (message !== undefined)
|
|
15660
15963
|
return { code: error48.name, message };
|
|
@@ -15670,8 +15973,16 @@ function readableMessages(messages) {
|
|
|
15670
15973
|
text: messageText(message)
|
|
15671
15974
|
})).filter((message) => message.text.trim().length > 0);
|
|
15672
15975
|
}
|
|
15673
|
-
async function readWorkspaceModels(workspace) {
|
|
15674
|
-
return openworkCatalogModels(openworkEngineProviderCatalogSchema.parse(await
|
|
15976
|
+
async function readWorkspaceModels(reader, workspace) {
|
|
15977
|
+
return openworkCatalogModels(openworkEngineProviderCatalogSchema.parse(await reader.get(`/workspace/${encodeURIComponent(workspace.id)}/opencode/provider`)));
|
|
15978
|
+
}
|
|
15979
|
+
async function readSessionOnEitherEngine(workspace, sessionId, readers) {
|
|
15980
|
+
for (const reader of readers) {
|
|
15981
|
+
try {
|
|
15982
|
+
return { session: await readWorkspaceSession(workspace, sessionId, reader), reader };
|
|
15983
|
+
} catch {}
|
|
15984
|
+
}
|
|
15985
|
+
return null;
|
|
15675
15986
|
}
|
|
15676
15987
|
async function readOpenWorkSession(rawArgs) {
|
|
15677
15988
|
const parsed = sessionReadArgsSchema.safeParse(rawArgs);
|
|
@@ -15685,19 +15996,26 @@ async function readOpenWorkSession(rawArgs) {
|
|
|
15685
15996
|
if (!workspaces.length) {
|
|
15686
15997
|
return { ok: false, error: args.workspaceId ? `No workspace matched ${args.workspaceId}` : "No OpenWork workspaces are available" };
|
|
15687
15998
|
}
|
|
15999
|
+
const readers = engineReaders();
|
|
15688
16000
|
for (const workspace of workspaces) {
|
|
15689
16001
|
try {
|
|
15690
|
-
const
|
|
16002
|
+
const located = await readSessionOnEitherEngine(workspace, args.sessionId, readers);
|
|
16003
|
+
if (!located) {
|
|
16004
|
+
if (args.workspaceId)
|
|
16005
|
+
break;
|
|
16006
|
+
continue;
|
|
16007
|
+
}
|
|
16008
|
+
const { session: session2, reader } = located;
|
|
15691
16009
|
const needsFullTranscript = summary || from === "start";
|
|
15692
16010
|
const [messages, activity, catalog] = await Promise.all([
|
|
15693
|
-
readSessionMessages(workspace, args.sessionId, needsFullTranscript ? undefined : count),
|
|
15694
|
-
readSessionActivity(workspace,
|
|
15695
|
-
readWorkspaceModels(workspace).catch(() => [])
|
|
16011
|
+
readSessionMessages(reader, workspace, args.sessionId, needsFullTranscript ? undefined : count),
|
|
16012
|
+
readSessionActivity(reader, workspace, session2),
|
|
16013
|
+
readWorkspaceModels(reader, workspace).catch(() => [])
|
|
15696
16014
|
]);
|
|
15697
16015
|
const lastError = lastAssistantError(messages);
|
|
15698
16016
|
const readable = readableMessages(messages);
|
|
15699
16017
|
const metadata = {
|
|
15700
|
-
...sessionMetadata(workspace,
|
|
16018
|
+
...sessionMetadata(workspace, session2, reader.engine),
|
|
15701
16019
|
...activity,
|
|
15702
16020
|
lastError
|
|
15703
16021
|
};
|
|
@@ -15705,7 +16023,7 @@ async function readOpenWorkSession(rawArgs) {
|
|
|
15705
16023
|
return {
|
|
15706
16024
|
ok: true,
|
|
15707
16025
|
...metadata,
|
|
15708
|
-
model: labelOpenworkSessionModel(sessionModelOf(
|
|
16026
|
+
model: labelOpenworkSessionModel(sessionModelOf(session2), catalog),
|
|
15709
16027
|
totalMessages: readable.length,
|
|
15710
16028
|
firstUser: readable.find((message) => message.role === "user") ?? null,
|
|
15711
16029
|
lastAssistant: [...readable].reverse().find((message) => message.role === "assistant") ?? null
|
|
@@ -15715,7 +16033,7 @@ async function readOpenWorkSession(rawArgs) {
|
|
|
15715
16033
|
return {
|
|
15716
16034
|
ok: true,
|
|
15717
16035
|
...metadata,
|
|
15718
|
-
model: labelOpenworkSessionModel(sessionModelOf(
|
|
16036
|
+
model: labelOpenworkSessionModel(sessionModelOf(session2), catalog),
|
|
15719
16037
|
from,
|
|
15720
16038
|
returned: window.length,
|
|
15721
16039
|
requested: count,
|
|
@@ -15756,26 +16074,26 @@ async function sendToOpenWorkSession(rawArgs, context) {
|
|
|
15756
16074
|
const located = await locateOpenWorkSession(args.sessionId, args.workspaceId);
|
|
15757
16075
|
if ("error" in located)
|
|
15758
16076
|
return { ok: false, error: located.error };
|
|
15759
|
-
const { workspace, session } = located;
|
|
16077
|
+
const { workspace, session: session2 } = located;
|
|
15760
16078
|
const messageId = createSendMessageId();
|
|
15761
|
-
await postJson(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session/${encodeURIComponent(
|
|
16079
|
+
await postJson(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session/${encodeURIComponent(session2.id)}/prompt_async`, { messageID: messageId, parts: [{ type: "text", text: args.text }] });
|
|
15762
16080
|
const result = {
|
|
15763
16081
|
ok: true,
|
|
15764
16082
|
accepted: true,
|
|
15765
|
-
sessionId:
|
|
16083
|
+
sessionId: session2.id,
|
|
15766
16084
|
workspaceId: workspace.id,
|
|
15767
16085
|
workspace: workspaceLabel(workspace),
|
|
15768
|
-
title: sessionTitle(
|
|
16086
|
+
title: sessionTitle(session2),
|
|
15769
16087
|
messageId
|
|
15770
16088
|
};
|
|
15771
16089
|
if (args.reveal !== true)
|
|
15772
16090
|
return result;
|
|
15773
16091
|
const opened = await uiControlRequest("command", {
|
|
15774
16092
|
id: "session.open",
|
|
15775
|
-
args: { sessionId:
|
|
16093
|
+
args: { sessionId: session2.id },
|
|
15776
16094
|
...affordanceOrigin(context)
|
|
15777
16095
|
});
|
|
15778
|
-
return { ...result, revealed:
|
|
16096
|
+
return { ...result, revealed: isRecord4(opened) && opened.ok === true };
|
|
15779
16097
|
}
|
|
15780
16098
|
function serverUrl2() {
|
|
15781
16099
|
return String(process.env.OPENWORK_SERVER_URL || "").replace(/\/$/, "");
|
|
@@ -15876,7 +16194,7 @@ async function createOpenWorkSessions(rawArgs, context) {
|
|
|
15876
16194
|
let models;
|
|
15877
16195
|
try {
|
|
15878
16196
|
catalog = [];
|
|
15879
|
-
if (args.model || args.sessions.some((
|
|
16197
|
+
if (args.model || args.sessions.some((session2) => session2.model)) {
|
|
15880
16198
|
const envelope = openworkAffordanceResultSchema.safeParse(await uiControlRequest("query", {
|
|
15881
16199
|
id: "models.list",
|
|
15882
16200
|
args: { workspaceId: workspace.id }
|
|
@@ -15890,23 +16208,23 @@ async function createOpenWorkSessions(rawArgs, context) {
|
|
|
15890
16208
|
catalog = result.models;
|
|
15891
16209
|
}
|
|
15892
16210
|
const defaultModel = args.model ? resolveOpenworkModel(args.model, catalog) : undefined;
|
|
15893
|
-
models = args.sessions.map((
|
|
16211
|
+
models = args.sessions.map((session2) => session2.model ? resolveOpenworkModel(session2.model, catalog) : defaultModel);
|
|
15894
16212
|
} catch (error48) {
|
|
15895
16213
|
return { ok: false, error: unknownErrorMessage(error48) };
|
|
15896
16214
|
}
|
|
15897
16215
|
let createdOnEngine = false;
|
|
15898
|
-
const results = await Promise.all(args.sessions.map(async (
|
|
16216
|
+
const results = await Promise.all(args.sessions.map(async (session2, index) => {
|
|
15899
16217
|
const inputTitle = argumentAtPath(rawArgs, ["sessions", index, "title"]);
|
|
15900
16218
|
const titleTruncated = typeof inputTitle === "string" && inputTitle.trim().length > 120;
|
|
15901
16219
|
const model = models[index];
|
|
15902
16220
|
try {
|
|
15903
|
-
const payload = sessionInfoSchema.parse(await postJson(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session`, { title:
|
|
16221
|
+
const payload = sessionInfoSchema.parse(await postJson(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session`, { title: session2.title, ...model ? { model: engineSessionCreateModel(model) } : {} }));
|
|
15904
16222
|
createdOnEngine = true;
|
|
15905
|
-
await postJson(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session/${encodeURIComponent(payload.id)}/prompt_async`, { ...model ? enginePromptModel(model) : {}, parts: [{ type: "text", text:
|
|
16223
|
+
await postJson(`/workspace/${encodeURIComponent(workspace.id)}/opencode/session/${encodeURIComponent(payload.id)}/prompt_async`, { ...model ? enginePromptModel(model) : {}, parts: [{ type: "text", text: session2.prompt }] });
|
|
15906
16224
|
return {
|
|
15907
16225
|
ok: true,
|
|
15908
16226
|
sessionId: payload.id,
|
|
15909
|
-
title:
|
|
16227
|
+
title: session2.title,
|
|
15910
16228
|
titleTruncated,
|
|
15911
16229
|
started: true,
|
|
15912
16230
|
model: labelOpenworkSessionModel(sessionModelOf(payload), catalog),
|
|
@@ -15915,7 +16233,7 @@ async function createOpenWorkSessions(rawArgs, context) {
|
|
|
15915
16233
|
} catch (error48) {
|
|
15916
16234
|
return {
|
|
15917
16235
|
ok: false,
|
|
15918
|
-
title:
|
|
16236
|
+
title: session2.title,
|
|
15919
16237
|
titleTruncated,
|
|
15920
16238
|
error: unknownErrorMessage(error48)
|
|
15921
16239
|
};
|
|
@@ -15950,6 +16268,9 @@ function proposeAutomation(rawArgs, context) {
|
|
|
15950
16268
|
};
|
|
15951
16269
|
}
|
|
15952
16270
|
async function postJson(path, body, signal, gmailAttachment = false) {
|
|
16271
|
+
const transport = openworkReadTransport.getStore();
|
|
16272
|
+
if (transport)
|
|
16273
|
+
return transport.post(path, body, signal);
|
|
15953
16274
|
if (gmailAttachment && (!serverUrl2() || !serverToken2())) {
|
|
15954
16275
|
throw new ApiError(409, "gmail_host_unavailable", "OpenWork host transport is unavailable. Run this tool from OpenWork.");
|
|
15955
16276
|
}
|
|
@@ -15966,7 +16287,7 @@ async function postJson(path, body, signal, gmailAttachment = false) {
|
|
|
15966
16287
|
const payload = await parseResponse2(response);
|
|
15967
16288
|
if (!response.ok) {
|
|
15968
16289
|
if (gmailAttachment) {
|
|
15969
|
-
throw new ApiError(response.status, getStringProperty2(payload, "code") ?? "gmail_attachment_http_error", errorMessage2(payload, "OpenWork extension call failed"),
|
|
16290
|
+
throw new ApiError(response.status, getStringProperty2(payload, "code") ?? "gmail_attachment_http_error", errorMessage2(payload, "OpenWork extension call failed"), isRecord4(payload) ? payload.details : undefined);
|
|
15970
16291
|
}
|
|
15971
16292
|
throw new Error(errorMessage2(payload, "OpenWork extension call failed"));
|
|
15972
16293
|
}
|
|
@@ -15992,7 +16313,7 @@ var OpenWorkExtensionsPreview = async (factoryInput, _options, dependencies) =>
|
|
|
15992
16313
|
event: fulfillGmailAttachments.event,
|
|
15993
16314
|
dispose: fulfillGmailAttachments.dispose,
|
|
15994
16315
|
"chat.headers": async (input, output) => {
|
|
15995
|
-
if (input.model.providerID !== "openwork")
|
|
16316
|
+
if (input.model.providerID !== "openwork" && input.model.providerID !== "openwork-free")
|
|
15996
16317
|
return;
|
|
15997
16318
|
output.headers["x-openwork-session-id"] = input.sessionID;
|
|
15998
16319
|
output.headers["x-openwork-task-id"] = input.message.id;
|