@runfusion/fusion 0.13.0 → 0.14.1
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 +13 -0
- package/dist/bin.js +1332 -528
- package/dist/client/assets/AgentDetailView-B3KAsP2O.js +18 -0
- package/dist/client/assets/{AgentsView-Dvf_xUkx.js → AgentsView-DoXb_amw.js} +4 -4
- package/dist/client/assets/ChatView-BJ2c7wvd.js +1 -0
- package/dist/client/assets/{DevServerView-C2qTJch7.js → DevServerView-DbgM4tlT.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DRfhg9zz.js → DirectoryPicker-DfmtfMiu.js} +1 -1
- package/dist/client/assets/{DocumentsView-j8ic1xUw.js → DocumentsView-_-Efkx_W.js} +1 -1
- package/dist/client/assets/{InsightsView-CpAz3o0i.js → InsightsView-DUjcfW53.js} +1 -1
- package/dist/client/assets/{MemoryView-BcQsi_JK.js → MemoryView-DxMPBb0q.js} +1 -1
- package/dist/client/assets/{NodesView-Bo_Yhr4N.js → NodesView-BEBTI15s.js} +1 -1
- package/dist/client/assets/PiExtensionsManager-BpMYhHH_.js +11 -0
- package/dist/client/assets/PluginManager-CPv7yQd3.js +1 -0
- package/dist/client/assets/PluginManager-DA_T0GHn.css +1 -0
- package/dist/client/assets/{ResearchView-CLyyqAWE.js → ResearchView-BrFvdyXT.js} +1 -1
- package/dist/client/assets/{RoadmapsView-tG7IdOoc.js → RoadmapsView-BDjLrtcj.js} +1 -1
- package/dist/client/assets/SettingsModal-Cd-QGB0C.js +31 -0
- package/dist/client/assets/{SettingsModal-CXUGeZ0_.js → SettingsModal-CxDxiTRy.js} +1 -1
- package/dist/client/assets/SettingsModal-D_AFkDJa.css +1 -0
- package/dist/client/assets/{SetupWizardModal-BMJL6eNR.js → SetupWizardModal-DFUA4X3z.js} +1 -1
- package/dist/client/assets/{SkillMultiselect-ILMft-Kz.js → SkillMultiselect-BUWe5ujb.js} +1 -1
- package/dist/client/assets/{SkillsView-x4_YwBz6.js → SkillsView-RAkqGX3y.js} +1 -1
- package/dist/client/assets/TodoView-Ceb0wrg1.js +6 -0
- package/dist/client/assets/TodoView-SeO9o7km.css +1 -0
- package/dist/client/assets/{folder-open-DDdJt8aE.js → folder-open-DcM-Vd6r.js} +1 -1
- package/dist/client/assets/index-C1prPuSl.css +1 -0
- package/dist/client/assets/index-DH3aprf6.js +661 -0
- package/dist/client/assets/{list-checks-DFxQ9biT.js → list-checks-ByGHVQpZ.js} +1 -1
- package/dist/client/assets/{star-BKs1bgJN.js → star-DlEYI8GL.js} +1 -1
- package/dist/client/assets/{upload-Bb5Pidne.js → upload-DKshabz-.js} +1 -1
- package/dist/client/assets/{users-BImNn91Q.js → users-X6tYPPBV.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/sw.js +6 -0
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/index.ts +127 -0
- package/dist/droid-cli/package.json +37 -0
- package/dist/droid-cli/src/__tests__/control-handler.test.ts +164 -0
- package/dist/droid-cli/src/__tests__/event-bridge.test.ts +1318 -0
- package/dist/droid-cli/src/__tests__/mcp-config.test.ts +310 -0
- package/dist/droid-cli/src/__tests__/process-manager.test.ts +818 -0
- package/dist/droid-cli/src/__tests__/prompt-builder.test.ts +1206 -0
- package/dist/droid-cli/src/__tests__/provider.test.ts +1894 -0
- package/dist/droid-cli/src/__tests__/setup-test-isolation.test.ts +32 -0
- package/dist/droid-cli/src/__tests__/setup-test-isolation.ts +14 -0
- package/dist/droid-cli/src/__tests__/stream-parser.test.ts +188 -0
- package/dist/droid-cli/src/__tests__/thinking-config.test.ts +141 -0
- package/dist/droid-cli/src/__tests__/tool-mapping.test.ts +253 -0
- package/dist/droid-cli/src/control-handler.ts +82 -0
- package/dist/droid-cli/src/event-bridge.ts +397 -0
- package/dist/droid-cli/src/mcp-config.ts +144 -0
- package/dist/droid-cli/src/mcp-schema-server.cjs +49 -0
- package/dist/droid-cli/src/process-manager.ts +358 -0
- package/dist/droid-cli/src/prompt-builder.ts +629 -0
- package/dist/droid-cli/src/provider.ts +447 -0
- package/dist/droid-cli/src/stream-parser.ts +37 -0
- package/dist/droid-cli/src/thinking-config.ts +83 -0
- package/dist/droid-cli/src/tool-mapping.ts +147 -0
- package/dist/droid-cli/src/types.ts +87 -0
- package/dist/extension.js +555 -125
- package/dist/pi-claude-cli/package.json +1 -1
- package/package.json +2 -1
- package/dist/client/assets/AgentDetailView-B7j297GT.js +0 -18
- package/dist/client/assets/ChatView-BgUt38ty.js +0 -1
- package/dist/client/assets/PiExtensionsManager-DHt2zFg8.js +0 -11
- package/dist/client/assets/PluginManager-BQhBHWrB.js +0 -1
- package/dist/client/assets/PluginManager-jyNkJZSz.css +0 -1
- package/dist/client/assets/SettingsModal-9HS8MnmW.css +0 -1
- package/dist/client/assets/SettingsModal-UziTDnLh.js +0 -31
- package/dist/client/assets/TodoView-BBYcMbXE.js +0 -6
- package/dist/client/assets/TodoView-C1g65hJo.css +0 -1
- package/dist/client/assets/index-B15xwijw.css +0 -1
- package/dist/client/assets/index-DmSs2FGE.js +0 -661
package/dist/bin.js
CHANGED
|
@@ -1009,11 +1009,40 @@ function hasAgentIdentity(agent) {
|
|
|
1009
1009
|
if (!agent) return false;
|
|
1010
1010
|
return !!(agent.soul?.trim() || agent.instructionsText?.trim() || agent.instructionsPath?.trim() || agent.memory?.trim());
|
|
1011
1011
|
}
|
|
1012
|
-
function
|
|
1012
|
+
function slugifyAgentAssetSegment(value) {
|
|
1013
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1014
|
+
}
|
|
1015
|
+
function getSafeAgentAssetIdSegment(agentId) {
|
|
1016
|
+
const slug = slugifyAgentAssetSegment(agentId);
|
|
1017
|
+
return slug || "agent";
|
|
1018
|
+
}
|
|
1019
|
+
function getCanonicalAgentAssetDirectoryName(agentName, agentId) {
|
|
1020
|
+
if (!agentId || typeof agentId !== "string") {
|
|
1021
|
+
throw new Error("getCanonicalAgentAssetDirectoryName requires a non-empty agentId");
|
|
1022
|
+
}
|
|
1023
|
+
const safeId = getSafeAgentAssetIdSegment(agentId);
|
|
1024
|
+
const nameSlug = slugifyAgentAssetSegment(agentName ?? "");
|
|
1025
|
+
const prefix = nameSlug || safeId;
|
|
1026
|
+
return `${prefix}-${safeId}`;
|
|
1027
|
+
}
|
|
1028
|
+
function getLegacyAgentAssetDirectoryName(agentId) {
|
|
1029
|
+
if (!agentId || typeof agentId !== "string") {
|
|
1030
|
+
throw new Error("getLegacyAgentAssetDirectoryName requires a non-empty agentId");
|
|
1031
|
+
}
|
|
1032
|
+
return agentId;
|
|
1033
|
+
}
|
|
1034
|
+
function getCanonicalAgentInstructionsBundleDirName(agentName, agentId) {
|
|
1035
|
+
return `${getCanonicalAgentAssetDirectoryName(agentName, agentId)}-instructions`;
|
|
1036
|
+
}
|
|
1037
|
+
function getLegacyAgentInstructionsBundleDirName(agentId) {
|
|
1038
|
+
return `${getLegacyAgentAssetDirectoryName(agentId)}-instructions`;
|
|
1039
|
+
}
|
|
1040
|
+
function getDefaultHeartbeatProcedurePath(agentId, agentName) {
|
|
1013
1041
|
if (!agentId || typeof agentId !== "string") {
|
|
1014
1042
|
throw new Error("getDefaultHeartbeatProcedurePath requires a non-empty agentId");
|
|
1015
1043
|
}
|
|
1016
|
-
|
|
1044
|
+
const directory = agentName ? getCanonicalAgentAssetDirectoryName(agentName, agentId) : getLegacyAgentAssetDirectoryName(agentId);
|
|
1045
|
+
return `.fusion/agents/${directory}/HEARTBEAT.md`;
|
|
1017
1046
|
}
|
|
1018
1047
|
function agentToConfigSnapshot(agent) {
|
|
1019
1048
|
return {
|
|
@@ -2707,7 +2736,7 @@ var init_db = __esm({
|
|
|
2707
2736
|
"use strict";
|
|
2708
2737
|
init_sqlite_adapter();
|
|
2709
2738
|
init_types();
|
|
2710
|
-
SCHEMA_VERSION =
|
|
2739
|
+
SCHEMA_VERSION = 58;
|
|
2711
2740
|
SCHEMA_SQL = `
|
|
2712
2741
|
-- Tasks table with JSON columns for nested data
|
|
2713
2742
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
@@ -4408,6 +4437,27 @@ CREATE INDEX IF NOT EXISTS idxTodoItemsSortOrder ON todo_items(listId, sortOrder
|
|
|
4408
4437
|
}
|
|
4409
4438
|
});
|
|
4410
4439
|
}
|
|
4440
|
+
if (version < 58) {
|
|
4441
|
+
this.applyMigration(58, () => {
|
|
4442
|
+
const newCommand = "npx runfusion.ai backup --create";
|
|
4443
|
+
if (this.hasTable("automations") && this.hasColumn("automations", "command")) {
|
|
4444
|
+
this.db.prepare(
|
|
4445
|
+
`UPDATE automations
|
|
4446
|
+
SET command = ?, updatedAt = ?
|
|
4447
|
+
WHERE name = 'Database Backup'
|
|
4448
|
+
AND (command LIKE 'fn backup%' OR command LIKE 'kb backup%' OR command LIKE 'fusion backup%')`
|
|
4449
|
+
).run(newCommand, (/* @__PURE__ */ new Date()).toISOString());
|
|
4450
|
+
}
|
|
4451
|
+
if (this.hasTable("routines") && this.hasColumn("routines", "command")) {
|
|
4452
|
+
this.db.prepare(
|
|
4453
|
+
`UPDATE routines
|
|
4454
|
+
SET command = ?, updatedAt = ?
|
|
4455
|
+
WHERE name = 'Database Backup'
|
|
4456
|
+
AND (command LIKE 'fn backup%' OR command LIKE 'kb backup%' OR command LIKE 'fusion backup%')`
|
|
4457
|
+
).run(newCommand, (/* @__PURE__ */ new Date()).toISOString());
|
|
4458
|
+
}
|
|
4459
|
+
});
|
|
4460
|
+
}
|
|
4411
4461
|
}
|
|
4412
4462
|
/**
|
|
4413
4463
|
* Run a single migration step inside a transaction and bump the version.
|
|
@@ -4671,7 +4721,7 @@ var init_agent_store = __esm({
|
|
|
4671
4721
|
if (agent.heartbeatProcedurePath !== DEFAULT_HEARTBEAT_PROCEDURE_PATH) {
|
|
4672
4722
|
continue;
|
|
4673
4723
|
}
|
|
4674
|
-
const newRelPath =
|
|
4724
|
+
const newRelPath = await this.resolveCompatibleHeartbeatProcedurePath(agent);
|
|
4675
4725
|
const newAbsPath = join3(this.rootDir, "..", newRelPath);
|
|
4676
4726
|
if (legacyContent !== null) {
|
|
4677
4727
|
try {
|
|
@@ -4832,7 +4882,7 @@ var init_agent_store = __esm({
|
|
|
4832
4882
|
const metadata = input.metadata ?? {};
|
|
4833
4883
|
const runtimeConfig = resolveCreationRuntimeConfig(input.runtimeConfig, metadata);
|
|
4834
4884
|
const ephemeral = isEphemeralAgent({ metadata, name: input.name, role: input.role, reportsTo: input.reportsTo });
|
|
4835
|
-
const resolvedHeartbeatProcedurePath = input.heartbeatProcedurePath ?? (ephemeral ? void 0 : getDefaultHeartbeatProcedurePath(agentId));
|
|
4885
|
+
const resolvedHeartbeatProcedurePath = input.heartbeatProcedurePath ?? (ephemeral ? void 0 : getDefaultHeartbeatProcedurePath(agentId, input.name));
|
|
4836
4886
|
const agent = {
|
|
4837
4887
|
id: agentId,
|
|
4838
4888
|
name: input.name.trim(),
|
|
@@ -5069,14 +5119,16 @@ var init_agent_store = __esm({
|
|
|
5069
5119
|
* Does not create the directory.
|
|
5070
5120
|
*/
|
|
5071
5121
|
getInstructionsDir(agentId) {
|
|
5072
|
-
|
|
5122
|
+
const agent = this.readAgent(agentId);
|
|
5123
|
+
const agentName = agent?.name ?? "";
|
|
5124
|
+
return join3(this.agentsDir, getCanonicalAgentInstructionsBundleDirName(agentName, agentId));
|
|
5073
5125
|
}
|
|
5074
5126
|
/**
|
|
5075
5127
|
* List markdown files in an agent's managed instructions bundle.
|
|
5076
5128
|
* Returns [] when the bundle directory does not exist.
|
|
5077
5129
|
*/
|
|
5078
5130
|
async listBundleFiles(agentId) {
|
|
5079
|
-
const bundleDir = this.
|
|
5131
|
+
const bundleDir = await this.resolveCompatibleBundleDir(agentId, false);
|
|
5080
5132
|
try {
|
|
5081
5133
|
const entries = await readdir(bundleDir, { withFileTypes: true });
|
|
5082
5134
|
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
@@ -5092,7 +5144,8 @@ var init_agent_store = __esm({
|
|
|
5092
5144
|
*/
|
|
5093
5145
|
async readBundleFile(agentId, filePath) {
|
|
5094
5146
|
this.validateBundleFilePath(filePath);
|
|
5095
|
-
const
|
|
5147
|
+
const bundleDir = await this.resolveCompatibleBundleDir(agentId, false);
|
|
5148
|
+
const resolvedPath = join3(bundleDir, filePath);
|
|
5096
5149
|
return readFile(resolvedPath, "utf-8");
|
|
5097
5150
|
}
|
|
5098
5151
|
/**
|
|
@@ -5101,7 +5154,7 @@ var init_agent_store = __esm({
|
|
|
5101
5154
|
async writeBundleFile(agentId, filePath, content) {
|
|
5102
5155
|
return this.withLock(agentId, async () => {
|
|
5103
5156
|
this.validateBundleFilePath(filePath);
|
|
5104
|
-
const bundleDir = this.
|
|
5157
|
+
const bundleDir = await this.resolveCompatibleBundleDir(agentId, true);
|
|
5105
5158
|
await mkdir(bundleDir, { recursive: true });
|
|
5106
5159
|
const existingFiles = await this.listBundleFiles(agentId);
|
|
5107
5160
|
const isOverwrite = existingFiles.includes(filePath);
|
|
@@ -5120,7 +5173,8 @@ var init_agent_store = __esm({
|
|
|
5120
5173
|
async deleteBundleFile(agentId, filePath) {
|
|
5121
5174
|
return this.withLock(agentId, async () => {
|
|
5122
5175
|
this.validateBundleFilePath(filePath);
|
|
5123
|
-
await
|
|
5176
|
+
const bundleDir = await this.resolveCompatibleBundleDir(agentId, false);
|
|
5177
|
+
await unlink(join3(bundleDir, filePath));
|
|
5124
5178
|
});
|
|
5125
5179
|
}
|
|
5126
5180
|
/**
|
|
@@ -5142,7 +5196,7 @@ var init_agent_store = __esm({
|
|
|
5142
5196
|
};
|
|
5143
5197
|
const updated = await this.updateAgent(agentId, { bundleConfig: normalizedConfig });
|
|
5144
5198
|
if (normalizedConfig.mode === "managed") {
|
|
5145
|
-
await mkdir(this.
|
|
5199
|
+
await mkdir(await this.resolveCompatibleBundleDir(agentId, true), { recursive: true });
|
|
5146
5200
|
}
|
|
5147
5201
|
return updated;
|
|
5148
5202
|
}
|
|
@@ -5165,7 +5219,7 @@ var init_agent_store = __esm({
|
|
|
5165
5219
|
bundleConfig: { mode: "managed", entryFile, files: [] }
|
|
5166
5220
|
});
|
|
5167
5221
|
}
|
|
5168
|
-
await mkdir(this.
|
|
5222
|
+
await mkdir(await this.resolveCompatibleBundleDir(agentId, true), { recursive: true });
|
|
5169
5223
|
const files = [];
|
|
5170
5224
|
if (hasInstructionsText) {
|
|
5171
5225
|
await this.writeBundleFile(agentId, entryFile, agent.instructionsText ?? "");
|
|
@@ -6126,8 +6180,87 @@ var init_agent_store = __esm({
|
|
|
6126
6180
|
}
|
|
6127
6181
|
return null;
|
|
6128
6182
|
}
|
|
6129
|
-
|
|
6130
|
-
return join3(this.agentsDir,
|
|
6183
|
+
getCanonicalBundleDir(agent) {
|
|
6184
|
+
return join3(this.agentsDir, getCanonicalAgentInstructionsBundleDirName(agent.name, agent.id));
|
|
6185
|
+
}
|
|
6186
|
+
getLegacyBundleDir(agentId) {
|
|
6187
|
+
return join3(this.agentsDir, getLegacyAgentInstructionsBundleDirName(agentId));
|
|
6188
|
+
}
|
|
6189
|
+
async resolveCompatibleBundleDir(agentId, createIfMissing) {
|
|
6190
|
+
const agent = this.readAgent(agentId);
|
|
6191
|
+
if (!agent) {
|
|
6192
|
+
throw new Error(`Agent ${agentId} not found`);
|
|
6193
|
+
}
|
|
6194
|
+
const canonicalDir = this.getCanonicalBundleDir(agent);
|
|
6195
|
+
if (await this.pathExists(canonicalDir)) {
|
|
6196
|
+
return canonicalDir;
|
|
6197
|
+
}
|
|
6198
|
+
const compatibleDir = await this.findExistingDisplayNameBundleDir(agent);
|
|
6199
|
+
if (compatibleDir) {
|
|
6200
|
+
return compatibleDir;
|
|
6201
|
+
}
|
|
6202
|
+
const legacyDir = this.getLegacyBundleDir(agent.id);
|
|
6203
|
+
if (await this.pathExists(legacyDir)) {
|
|
6204
|
+
return legacyDir;
|
|
6205
|
+
}
|
|
6206
|
+
return createIfMissing ? canonicalDir : canonicalDir;
|
|
6207
|
+
}
|
|
6208
|
+
async findExistingDisplayNameBundleDir(agent) {
|
|
6209
|
+
const safeId = getSafeAgentAssetIdSegment(agent.id);
|
|
6210
|
+
try {
|
|
6211
|
+
const entries = await readdir(this.agentsDir, { withFileTypes: true });
|
|
6212
|
+
const candidates = entries.filter((entry) => entry.isDirectory() && entry.name.endsWith("-instructions")).map((entry) => entry.name).filter((name) => {
|
|
6213
|
+
const base = name.slice(0, -"-instructions".length);
|
|
6214
|
+
return base.endsWith(`-${safeId}`);
|
|
6215
|
+
}).sort((a, b) => a.localeCompare(b));
|
|
6216
|
+
if (candidates.length === 0) {
|
|
6217
|
+
return null;
|
|
6218
|
+
}
|
|
6219
|
+
const canonicalName = getCanonicalAgentInstructionsBundleDirName(agent.name, agent.id);
|
|
6220
|
+
const selected = candidates.find((candidate) => candidate === canonicalName) ?? candidates[0];
|
|
6221
|
+
return join3(this.agentsDir, selected);
|
|
6222
|
+
} catch (err) {
|
|
6223
|
+
if (err.code === "ENOENT") {
|
|
6224
|
+
return null;
|
|
6225
|
+
}
|
|
6226
|
+
throw err;
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
6229
|
+
async resolveCompatibleHeartbeatProcedurePath(agent) {
|
|
6230
|
+
const canonicalPath = getDefaultHeartbeatProcedurePath(agent.id, agent.name);
|
|
6231
|
+
const canonicalAbs = join3(this.rootDir, "..", canonicalPath);
|
|
6232
|
+
if (await this.pathExists(canonicalAbs)) {
|
|
6233
|
+
return canonicalPath;
|
|
6234
|
+
}
|
|
6235
|
+
const safeId = getSafeAgentAssetIdSegment(agent.id);
|
|
6236
|
+
try {
|
|
6237
|
+
const entries = await readdir(this.agentsDir, { withFileTypes: true });
|
|
6238
|
+
const compatibleDir = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).find((name) => name.endsWith(`-${safeId}`));
|
|
6239
|
+
if (compatibleDir) {
|
|
6240
|
+
const candidatePath = `.fusion/agents/${compatibleDir}/HEARTBEAT.md`;
|
|
6241
|
+
if (await this.pathExists(join3(this.rootDir, "..", candidatePath))) {
|
|
6242
|
+
return candidatePath;
|
|
6243
|
+
}
|
|
6244
|
+
}
|
|
6245
|
+
} catch (err) {
|
|
6246
|
+
if (err.code !== "ENOENT") {
|
|
6247
|
+
throw err;
|
|
6248
|
+
}
|
|
6249
|
+
}
|
|
6250
|
+
const legacyPath = `.fusion/agents/${getLegacyAgentAssetDirectoryName(agent.id)}/HEARTBEAT.md`;
|
|
6251
|
+
const legacyAbs = join3(this.rootDir, "..", legacyPath);
|
|
6252
|
+
if (await this.pathExists(legacyAbs)) {
|
|
6253
|
+
return legacyPath;
|
|
6254
|
+
}
|
|
6255
|
+
return canonicalPath;
|
|
6256
|
+
}
|
|
6257
|
+
async pathExists(path5) {
|
|
6258
|
+
try {
|
|
6259
|
+
await access(path5, fsConstants.F_OK);
|
|
6260
|
+
return true;
|
|
6261
|
+
} catch {
|
|
6262
|
+
return false;
|
|
6263
|
+
}
|
|
6131
6264
|
}
|
|
6132
6265
|
validateBundleFilePath(filePath) {
|
|
6133
6266
|
if (typeof filePath !== "string") {
|
|
@@ -7013,9 +7146,9 @@ var init_global_settings = __esm({
|
|
|
7013
7146
|
* Serialize operations via promise chain to prevent lost-update races.
|
|
7014
7147
|
*/
|
|
7015
7148
|
withLock(fn) {
|
|
7016
|
-
let
|
|
7149
|
+
let resolve42;
|
|
7017
7150
|
const next = new Promise((r) => {
|
|
7018
|
-
|
|
7151
|
+
resolve42 = r;
|
|
7019
7152
|
});
|
|
7020
7153
|
const prev = this.lock;
|
|
7021
7154
|
this.lock = next;
|
|
@@ -7023,7 +7156,7 @@ var init_global_settings = __esm({
|
|
|
7023
7156
|
try {
|
|
7024
7157
|
return await fn();
|
|
7025
7158
|
} finally {
|
|
7026
|
-
|
|
7159
|
+
resolve42();
|
|
7027
7160
|
}
|
|
7028
7161
|
});
|
|
7029
7162
|
}
|
|
@@ -10240,7 +10373,7 @@ function validatePluginManifest(manifest) {
|
|
|
10240
10373
|
const m = manifest;
|
|
10241
10374
|
if (!m.id || typeof m.id !== "string" || m.id.trim() === "") {
|
|
10242
10375
|
errors.push("id is required and must be a non-empty string");
|
|
10243
|
-
} else if (
|
|
10376
|
+
} else if (!SLUG_PATTERN.test(m.id)) {
|
|
10244
10377
|
errors.push("id must be a valid slug (lowercase, alphanumeric, hyphens only, cannot start or end with hyphen)");
|
|
10245
10378
|
}
|
|
10246
10379
|
if (!m.name || typeof m.name !== "string" || m.name.trim() === "") {
|
|
@@ -10293,7 +10426,7 @@ function validatePluginManifest(manifest) {
|
|
|
10293
10426
|
const runtime = m.runtime;
|
|
10294
10427
|
if (!runtime.runtimeId || typeof runtime.runtimeId !== "string" || runtime.runtimeId.trim() === "") {
|
|
10295
10428
|
errors.push("runtime.runtimeId is required and must be a non-empty string");
|
|
10296
|
-
} else if (
|
|
10429
|
+
} else if (!SLUG_PATTERN.test(runtime.runtimeId)) {
|
|
10297
10430
|
errors.push("runtime.runtimeId must be a valid slug (lowercase, alphanumeric, hyphens only, cannot start or end with hyphen)");
|
|
10298
10431
|
}
|
|
10299
10432
|
if (!runtime.name || typeof runtime.name !== "string" || runtime.name.trim() === "") {
|
|
@@ -10308,14 +10441,93 @@ function validatePluginManifest(manifest) {
|
|
|
10308
10441
|
}
|
|
10309
10442
|
}
|
|
10310
10443
|
}
|
|
10444
|
+
if (m.skills !== void 0) {
|
|
10445
|
+
if (!Array.isArray(m.skills)) {
|
|
10446
|
+
errors.push("skills must be an array");
|
|
10447
|
+
} else {
|
|
10448
|
+
for (const [index2, skill] of m.skills.entries()) {
|
|
10449
|
+
if (!skill || typeof skill !== "object") {
|
|
10450
|
+
errors.push(`skills[${index2}] must be an object`);
|
|
10451
|
+
continue;
|
|
10452
|
+
}
|
|
10453
|
+
const skillMeta = skill;
|
|
10454
|
+
if (!skillMeta.skillId || typeof skillMeta.skillId !== "string" || skillMeta.skillId.trim() === "") {
|
|
10455
|
+
errors.push(`skills[${index2}].skillId is required and must be a non-empty string`);
|
|
10456
|
+
} else if (!SLUG_PATTERN.test(skillMeta.skillId)) {
|
|
10457
|
+
errors.push(`skills[${index2}].skillId must be a valid slug (lowercase, alphanumeric, hyphens only, cannot start or end with hyphen)`);
|
|
10458
|
+
}
|
|
10459
|
+
if (!skillMeta.name || typeof skillMeta.name !== "string" || skillMeta.name.trim() === "") {
|
|
10460
|
+
errors.push(`skills[${index2}].name is required and must be a non-empty string`);
|
|
10461
|
+
}
|
|
10462
|
+
}
|
|
10463
|
+
}
|
|
10464
|
+
}
|
|
10465
|
+
if (m.workflowSteps !== void 0) {
|
|
10466
|
+
if (!Array.isArray(m.workflowSteps)) {
|
|
10467
|
+
errors.push("workflowSteps must be an array");
|
|
10468
|
+
} else {
|
|
10469
|
+
for (const [index2, step] of m.workflowSteps.entries()) {
|
|
10470
|
+
if (!step || typeof step !== "object") {
|
|
10471
|
+
errors.push(`workflowSteps[${index2}] must be an object`);
|
|
10472
|
+
continue;
|
|
10473
|
+
}
|
|
10474
|
+
const stepMeta = step;
|
|
10475
|
+
if (!stepMeta.stepId || typeof stepMeta.stepId !== "string" || stepMeta.stepId.trim() === "") {
|
|
10476
|
+
errors.push(`workflowSteps[${index2}].stepId is required and must be a non-empty string`);
|
|
10477
|
+
} else if (!SLUG_PATTERN.test(stepMeta.stepId)) {
|
|
10478
|
+
errors.push(`workflowSteps[${index2}].stepId must be a valid slug (lowercase, alphanumeric, hyphens only, cannot start or end with hyphen)`);
|
|
10479
|
+
}
|
|
10480
|
+
if (!stepMeta.name || typeof stepMeta.name !== "string" || stepMeta.name.trim() === "") {
|
|
10481
|
+
errors.push(`workflowSteps[${index2}].name is required and must be a non-empty string`);
|
|
10482
|
+
}
|
|
10483
|
+
if (stepMeta.mode !== void 0 && (typeof stepMeta.mode !== "string" || !["prompt", "script"].includes(stepMeta.mode))) {
|
|
10484
|
+
errors.push(`workflowSteps[${index2}].mode must be one of: prompt, script`);
|
|
10485
|
+
}
|
|
10486
|
+
}
|
|
10487
|
+
}
|
|
10488
|
+
}
|
|
10489
|
+
if (m.promptSurfaces !== void 0) {
|
|
10490
|
+
if (!Array.isArray(m.promptSurfaces)) {
|
|
10491
|
+
errors.push("promptSurfaces must be an array");
|
|
10492
|
+
} else {
|
|
10493
|
+
for (const [index2, surface] of m.promptSurfaces.entries()) {
|
|
10494
|
+
if (typeof surface !== "string" || !PROMPT_CONTRIBUTION_SURFACES.includes(surface)) {
|
|
10495
|
+
errors.push(`promptSurfaces[${index2}] must be one of: ${PROMPT_CONTRIBUTION_SURFACES.join(", ")}`);
|
|
10496
|
+
}
|
|
10497
|
+
}
|
|
10498
|
+
}
|
|
10499
|
+
}
|
|
10500
|
+
if (m.setup !== void 0) {
|
|
10501
|
+
if (typeof m.setup !== "object" || m.setup === null) {
|
|
10502
|
+
errors.push("setup must be an object");
|
|
10503
|
+
} else {
|
|
10504
|
+
const setup = m.setup;
|
|
10505
|
+
if (!setup.binaryName || typeof setup.binaryName !== "string" || setup.binaryName.trim() === "") {
|
|
10506
|
+
errors.push("setup.binaryName is required and must be a non-empty string");
|
|
10507
|
+
}
|
|
10508
|
+
if (!setup.description || typeof setup.description !== "string" || setup.description.trim() === "") {
|
|
10509
|
+
errors.push("setup.description is required and must be a non-empty string");
|
|
10510
|
+
}
|
|
10511
|
+
if (setup.channel !== void 0 && (typeof setup.channel !== "string" || !SETUP_CHANNELS.includes(setup.channel))) {
|
|
10512
|
+
errors.push(`setup.channel must be one of: ${SETUP_CHANNELS.join(", ")}`);
|
|
10513
|
+
}
|
|
10514
|
+
if (setup.defaultTimeoutMs !== void 0 && (typeof setup.defaultTimeoutMs !== "number" || !Number.isFinite(setup.defaultTimeoutMs) || setup.defaultTimeoutMs <= 0)) {
|
|
10515
|
+
errors.push("setup.defaultTimeoutMs must be a positive finite number");
|
|
10516
|
+
}
|
|
10517
|
+
}
|
|
10518
|
+
}
|
|
10311
10519
|
return {
|
|
10312
10520
|
valid: errors.length === 0,
|
|
10313
10521
|
errors
|
|
10314
10522
|
};
|
|
10315
10523
|
}
|
|
10524
|
+
var SLUG_PATTERN, PROMPT_CONTRIBUTION_SURFACES, SETUP_CHANNELS;
|
|
10316
10525
|
var init_plugin_types = __esm({
|
|
10317
10526
|
"../core/src/plugin-types.ts"() {
|
|
10318
10527
|
"use strict";
|
|
10528
|
+
SLUG_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
10529
|
+
PROMPT_CONTRIBUTION_SURFACES = ["executor-system", "executor-task", "triage", "reviewer", "heartbeat"];
|
|
10530
|
+
SETUP_CHANNELS = ["stable", "beta", "nightly"];
|
|
10319
10531
|
}
|
|
10320
10532
|
});
|
|
10321
10533
|
|
|
@@ -28483,8 +28695,8 @@ var require_CronFileParser = __commonJS({
|
|
|
28483
28695
|
* @throws If file cannot be read
|
|
28484
28696
|
*/
|
|
28485
28697
|
static parseFileSync(filePath) {
|
|
28486
|
-
const { readFileSync:
|
|
28487
|
-
const data =
|
|
28698
|
+
const { readFileSync: readFileSync25 } = __require("fs");
|
|
28699
|
+
const data = readFileSync25(filePath, "utf8");
|
|
28488
28700
|
return _CronFileParser.#parseContent(data);
|
|
28489
28701
|
}
|
|
28490
28702
|
/**
|
|
@@ -28701,9 +28913,9 @@ var init_automation_store = __esm({
|
|
|
28701
28913
|
*/
|
|
28702
28914
|
withScheduleLock(id, fn) {
|
|
28703
28915
|
const prev = this.scheduleLocks.get(id) ?? Promise.resolve();
|
|
28704
|
-
let
|
|
28916
|
+
let resolve42;
|
|
28705
28917
|
const next = new Promise((r) => {
|
|
28706
|
-
|
|
28918
|
+
resolve42 = r;
|
|
28707
28919
|
});
|
|
28708
28920
|
this.scheduleLocks.set(id, next);
|
|
28709
28921
|
return prev.then(async () => {
|
|
@@ -28713,7 +28925,7 @@ var init_automation_store = __esm({
|
|
|
28713
28925
|
if (this.scheduleLocks.get(id) === next) {
|
|
28714
28926
|
this.scheduleLocks.delete(id);
|
|
28715
28927
|
}
|
|
28716
|
-
|
|
28928
|
+
resolve42();
|
|
28717
28929
|
}
|
|
28718
28930
|
});
|
|
28719
28931
|
}
|
|
@@ -30502,7 +30714,7 @@ var init_project_memory = __esm({
|
|
|
30502
30714
|
// ../core/src/run-command.ts
|
|
30503
30715
|
import { spawn } from "node:child_process";
|
|
30504
30716
|
function runCommandAsync(command, options = {}) {
|
|
30505
|
-
return new Promise((
|
|
30717
|
+
return new Promise((resolve42) => {
|
|
30506
30718
|
const maxBuffer = options.maxBuffer ?? DEFAULT_MAX_BUFFER;
|
|
30507
30719
|
let stdout = "";
|
|
30508
30720
|
let stderr = "";
|
|
@@ -30561,7 +30773,7 @@ function runCommandAsync(command, options = {}) {
|
|
|
30561
30773
|
clearTimeout(forceKillTimer);
|
|
30562
30774
|
forceKillTimer = null;
|
|
30563
30775
|
}
|
|
30564
|
-
|
|
30776
|
+
resolve42({
|
|
30565
30777
|
stdout,
|
|
30566
30778
|
stderr,
|
|
30567
30779
|
exitCode: null,
|
|
@@ -30579,7 +30791,7 @@ function runCommandAsync(command, options = {}) {
|
|
|
30579
30791
|
}
|
|
30580
30792
|
signalProcessGroup("SIGTERM");
|
|
30581
30793
|
scheduleForceKill(NORMAL_CLEANUP_FORCE_KILL_DELAY_MS);
|
|
30582
|
-
|
|
30794
|
+
resolve42({
|
|
30583
30795
|
stdout,
|
|
30584
30796
|
stderr,
|
|
30585
30797
|
exitCode: code,
|
|
@@ -31794,9 +32006,9 @@ ${outcome}`;
|
|
|
31794
32006
|
* lost-update races on the nextId counter.
|
|
31795
32007
|
*/
|
|
31796
32008
|
withConfigLock(fn) {
|
|
31797
|
-
let
|
|
32009
|
+
let resolve42;
|
|
31798
32010
|
const next = new Promise((r) => {
|
|
31799
|
-
|
|
32011
|
+
resolve42 = r;
|
|
31800
32012
|
});
|
|
31801
32013
|
const prev = this.configLock;
|
|
31802
32014
|
this.configLock = next;
|
|
@@ -31804,7 +32016,7 @@ ${outcome}`;
|
|
|
31804
32016
|
try {
|
|
31805
32017
|
return await fn();
|
|
31806
32018
|
} finally {
|
|
31807
|
-
|
|
32019
|
+
resolve42();
|
|
31808
32020
|
}
|
|
31809
32021
|
});
|
|
31810
32022
|
}
|
|
@@ -31814,9 +32026,9 @@ ${outcome}`;
|
|
|
31814
32026
|
*/
|
|
31815
32027
|
withTaskLock(id, fn) {
|
|
31816
32028
|
const prev = this.taskLocks.get(id) ?? Promise.resolve();
|
|
31817
|
-
let
|
|
32029
|
+
let resolve42;
|
|
31818
32030
|
const next = new Promise((r) => {
|
|
31819
|
-
|
|
32031
|
+
resolve42 = r;
|
|
31820
32032
|
});
|
|
31821
32033
|
this.taskLocks.set(id, next);
|
|
31822
32034
|
return prev.then(async () => {
|
|
@@ -31826,7 +32038,7 @@ ${outcome}`;
|
|
|
31826
32038
|
if (this.taskLocks.get(id) === next) {
|
|
31827
32039
|
this.taskLocks.delete(id);
|
|
31828
32040
|
}
|
|
31829
|
-
|
|
32041
|
+
resolve42();
|
|
31830
32042
|
}
|
|
31831
32043
|
});
|
|
31832
32044
|
}
|
|
@@ -34094,7 +34306,7 @@ ${task.description}
|
|
|
34094
34306
|
}
|
|
34095
34307
|
}
|
|
34096
34308
|
}
|
|
34097
|
-
await new Promise((
|
|
34309
|
+
await new Promise((resolve42) => setImmediate(resolve42));
|
|
34098
34310
|
const selectClause = this.getTaskSelectClause(true);
|
|
34099
34311
|
const changedRows = this.lastPollTime ? this.db.prepare(`SELECT ${selectClause} FROM tasks WHERE updatedAt > ? OR columnMovedAt > ?`).all(this.lastPollTime, this.lastPollTime) : this.db.prepare(`SELECT ${selectClause} FROM tasks`).all();
|
|
34100
34312
|
this.lastPollTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -34114,7 +34326,7 @@ ${task.description}
|
|
|
34114
34326
|
this.emit("task:updated", task);
|
|
34115
34327
|
}
|
|
34116
34328
|
if (i > 0 && i % 50 === 0) {
|
|
34117
|
-
await new Promise((
|
|
34329
|
+
await new Promise((resolve42) => setImmediate(resolve42));
|
|
34118
34330
|
}
|
|
34119
34331
|
}
|
|
34120
34332
|
const elapsed = Date.now() - startTime;
|
|
@@ -35859,6 +36071,20 @@ function reconcileClaudeCliPaths(paths, vendoredPath) {
|
|
|
35859
36071
|
}
|
|
35860
36072
|
return filtered;
|
|
35861
36073
|
}
|
|
36074
|
+
function isExternalDroidCliPath(p, vendoredPath) {
|
|
36075
|
+
if (vendoredPath && p === vendoredPath) return false;
|
|
36076
|
+
return /(^|[/\\])droid-cli([/\\]|$)/i.test(p);
|
|
36077
|
+
}
|
|
36078
|
+
function reconcileDroidCliPaths(paths, vendoredPath) {
|
|
36079
|
+
if (!vendoredPath) {
|
|
36080
|
+
return [...paths];
|
|
36081
|
+
}
|
|
36082
|
+
const filtered = paths.filter((p) => !isExternalDroidCliPath(p, vendoredPath));
|
|
36083
|
+
if (!filtered.includes(vendoredPath)) {
|
|
36084
|
+
return [vendoredPath, ...filtered];
|
|
36085
|
+
}
|
|
36086
|
+
return filtered;
|
|
36087
|
+
}
|
|
35862
36088
|
function getDisplayPathWithinRoot(root, targetPath) {
|
|
35863
36089
|
const usesWindowsPaths = /^[A-Za-z]:[\\/]/.test(root) || /^[A-Za-z]:[\\/]/.test(targetPath) || root.includes("\\") || targetPath.includes("\\");
|
|
35864
36090
|
const pathApi = usesWindowsPaths ? win32 : { relative: relative2, isAbsolute: isAbsolute5, sep: sep4 };
|
|
@@ -35970,7 +36196,7 @@ function runGh(args, cwd) {
|
|
|
35970
36196
|
}
|
|
35971
36197
|
function runGhAsync(args, cwdOrOptions) {
|
|
35972
36198
|
const { cwd, signal: externalSignal, timeoutMs = DEFAULT_GH_TIMEOUT_MS } = normalizeRunGhOptions(cwdOrOptions);
|
|
35973
|
-
return new Promise((
|
|
36199
|
+
return new Promise((resolve42, reject2) => {
|
|
35974
36200
|
if (externalSignal?.aborted) {
|
|
35975
36201
|
reject2(makeGhError(`gh command aborted: ${describeAbortReason(externalSignal.reason)}`, "ABORT_ERR"));
|
|
35976
36202
|
return;
|
|
@@ -36021,7 +36247,7 @@ function runGhAsync(args, cwdOrOptions) {
|
|
|
36021
36247
|
ghError.stderr = stderr ?? "";
|
|
36022
36248
|
reject2(ghError);
|
|
36023
36249
|
} else {
|
|
36024
|
-
|
|
36250
|
+
resolve42(stdout ?? "");
|
|
36025
36251
|
}
|
|
36026
36252
|
}
|
|
36027
36253
|
);
|
|
@@ -36116,6 +36342,85 @@ var init_gh_cli = __esm({
|
|
|
36116
36342
|
}
|
|
36117
36343
|
});
|
|
36118
36344
|
|
|
36345
|
+
// ../core/src/fn-binary.ts
|
|
36346
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
36347
|
+
import { platform as platform2 } from "node:os";
|
|
36348
|
+
function runProbe(command, args, timeoutMs) {
|
|
36349
|
+
return new Promise((resolve42) => {
|
|
36350
|
+
let stdout = "";
|
|
36351
|
+
let stderr = "";
|
|
36352
|
+
const child = spawn2(command, args, { stdio: ["ignore", "pipe", "pipe"], shell: false });
|
|
36353
|
+
const timer = setTimeout(() => {
|
|
36354
|
+
try {
|
|
36355
|
+
child.kill("SIGKILL");
|
|
36356
|
+
} catch {
|
|
36357
|
+
}
|
|
36358
|
+
}, timeoutMs);
|
|
36359
|
+
child.stdout?.on("data", (chunk) => {
|
|
36360
|
+
stdout += chunk.toString("utf8");
|
|
36361
|
+
});
|
|
36362
|
+
child.stderr?.on("data", (chunk) => {
|
|
36363
|
+
stderr += chunk.toString("utf8");
|
|
36364
|
+
});
|
|
36365
|
+
child.on("error", (err) => {
|
|
36366
|
+
clearTimeout(timer);
|
|
36367
|
+
resolve42({ exitCode: null, stdout, stderr: stderr || err.message });
|
|
36368
|
+
});
|
|
36369
|
+
child.on("close", (exitCode) => {
|
|
36370
|
+
clearTimeout(timer);
|
|
36371
|
+
resolve42({ exitCode, stdout, stderr });
|
|
36372
|
+
});
|
|
36373
|
+
});
|
|
36374
|
+
}
|
|
36375
|
+
async function whichBinary(name) {
|
|
36376
|
+
const isWindows = platform2() === "win32";
|
|
36377
|
+
const lookup = isWindows ? "where" : "which";
|
|
36378
|
+
const result = await runProbe(lookup, [name], 5e3);
|
|
36379
|
+
if (result.exitCode !== 0) return void 0;
|
|
36380
|
+
const firstLine = result.stdout.split(/\r?\n/).map((s) => s.trim()).find(Boolean);
|
|
36381
|
+
return firstLine || void 0;
|
|
36382
|
+
}
|
|
36383
|
+
async function probeVersion(binary) {
|
|
36384
|
+
const result = await runProbe(binary, ["--version"], 1e4);
|
|
36385
|
+
if (result.exitCode !== 0) return void 0;
|
|
36386
|
+
const text = (result.stdout || result.stderr).trim();
|
|
36387
|
+
if (!text) return void 0;
|
|
36388
|
+
const match = text.match(/\d+\.\d+\.\d+(?:-[\w.]+)?/);
|
|
36389
|
+
return match ? match[0] : text.split(/\s+/)[0];
|
|
36390
|
+
}
|
|
36391
|
+
async function detectFnBinary() {
|
|
36392
|
+
for (const candidate of CANDIDATES) {
|
|
36393
|
+
try {
|
|
36394
|
+
const resolvedPath = await whichBinary(candidate);
|
|
36395
|
+
if (!resolvedPath) continue;
|
|
36396
|
+
const version = await probeVersion(candidate);
|
|
36397
|
+
return {
|
|
36398
|
+
installed: true,
|
|
36399
|
+
binary: candidate,
|
|
36400
|
+
path: resolvedPath,
|
|
36401
|
+
version,
|
|
36402
|
+
invocation: candidate
|
|
36403
|
+
};
|
|
36404
|
+
} catch {
|
|
36405
|
+
}
|
|
36406
|
+
}
|
|
36407
|
+
return {
|
|
36408
|
+
installed: false,
|
|
36409
|
+
invocation: FN_NPX_INVOCATION
|
|
36410
|
+
};
|
|
36411
|
+
}
|
|
36412
|
+
var FN_NPM_PACKAGE, FN_INSTALL_CURL, FN_INSTALL_NPM, FN_NPX_INVOCATION, CANDIDATES;
|
|
36413
|
+
var init_fn_binary = __esm({
|
|
36414
|
+
"../core/src/fn-binary.ts"() {
|
|
36415
|
+
"use strict";
|
|
36416
|
+
FN_NPM_PACKAGE = "runfusion.ai";
|
|
36417
|
+
FN_INSTALL_CURL = "curl -fsSL https://runfusion.ai/install.sh | sh";
|
|
36418
|
+
FN_INSTALL_NPM = `npm install -g ${FN_NPM_PACKAGE}`;
|
|
36419
|
+
FN_NPX_INVOCATION = `npx -y ${FN_NPM_PACKAGE}`;
|
|
36420
|
+
CANDIDATES = ["fn", "fusion"];
|
|
36421
|
+
}
|
|
36422
|
+
});
|
|
36423
|
+
|
|
36119
36424
|
// ../core/src/settings-validation.ts
|
|
36120
36425
|
function validateUnavailableNodePolicy(value) {
|
|
36121
36426
|
if (value === void 0) {
|
|
@@ -36309,9 +36614,9 @@ var init_routine_store = __esm({
|
|
|
36309
36614
|
*/
|
|
36310
36615
|
withRoutineLock(id, fn) {
|
|
36311
36616
|
const prev = this.routineLocks.get(id) ?? Promise.resolve();
|
|
36312
|
-
let
|
|
36617
|
+
let resolve42;
|
|
36313
36618
|
const next = new Promise((r) => {
|
|
36314
|
-
|
|
36619
|
+
resolve42 = r;
|
|
36315
36620
|
});
|
|
36316
36621
|
this.routineLocks.set(id, next);
|
|
36317
36622
|
return prev.then(async () => {
|
|
@@ -36321,7 +36626,7 @@ var init_routine_store = __esm({
|
|
|
36321
36626
|
if (this.routineLocks.get(id) === next) {
|
|
36322
36627
|
this.routineLocks.delete(id);
|
|
36323
36628
|
}
|
|
36324
|
-
|
|
36629
|
+
resolve42();
|
|
36325
36630
|
}
|
|
36326
36631
|
});
|
|
36327
36632
|
}
|
|
@@ -36920,13 +37225,13 @@ var init_plugin_loader = __esm({
|
|
|
36920
37225
|
* Execute a promise with a timeout.
|
|
36921
37226
|
*/
|
|
36922
37227
|
withTimeout(promise, ms, timeoutMessage) {
|
|
36923
|
-
return new Promise((
|
|
37228
|
+
return new Promise((resolve42, reject2) => {
|
|
36924
37229
|
const timer = setTimeout(() => {
|
|
36925
37230
|
reject2(new Error(timeoutMessage));
|
|
36926
37231
|
}, ms);
|
|
36927
37232
|
promise.then((result) => {
|
|
36928
37233
|
clearTimeout(timer);
|
|
36929
|
-
|
|
37234
|
+
resolve42(result);
|
|
36930
37235
|
}).catch((err) => {
|
|
36931
37236
|
clearTimeout(timer);
|
|
36932
37237
|
reject2(err);
|
|
@@ -40491,7 +40796,7 @@ var require_get_stream = __commonJS({
|
|
|
40491
40796
|
};
|
|
40492
40797
|
const { maxBuffer } = options;
|
|
40493
40798
|
let stream;
|
|
40494
|
-
await new Promise((
|
|
40799
|
+
await new Promise((resolve42, reject2) => {
|
|
40495
40800
|
const rejectPromise = (error) => {
|
|
40496
40801
|
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
|
|
40497
40802
|
error.bufferedData = stream.getBufferedValue();
|
|
@@ -40503,7 +40808,7 @@ var require_get_stream = __commonJS({
|
|
|
40503
40808
|
rejectPromise(error);
|
|
40504
40809
|
return;
|
|
40505
40810
|
}
|
|
40506
|
-
|
|
40811
|
+
resolve42();
|
|
40507
40812
|
});
|
|
40508
40813
|
stream.on("data", () => {
|
|
40509
40814
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
@@ -41797,7 +42102,7 @@ var require_extract_zip = __commonJS({
|
|
|
41797
42102
|
debug("opening", this.zipPath, "with opts", this.opts);
|
|
41798
42103
|
this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
|
|
41799
42104
|
this.canceled = false;
|
|
41800
|
-
return new Promise((
|
|
42105
|
+
return new Promise((resolve42, reject2) => {
|
|
41801
42106
|
this.zipfile.on("error", (err) => {
|
|
41802
42107
|
this.canceled = true;
|
|
41803
42108
|
reject2(err);
|
|
@@ -41806,7 +42111,7 @@ var require_extract_zip = __commonJS({
|
|
|
41806
42111
|
this.zipfile.on("close", () => {
|
|
41807
42112
|
if (!this.canceled) {
|
|
41808
42113
|
debug("zip extraction complete");
|
|
41809
|
-
|
|
42114
|
+
resolve42();
|
|
41810
42115
|
}
|
|
41811
42116
|
});
|
|
41812
42117
|
this.zipfile.on("entry", async (entry) => {
|
|
@@ -50403,6 +50708,10 @@ __export(src_exports, {
|
|
|
50403
50708
|
EXECUTION_MODES: () => EXECUTION_MODES,
|
|
50404
50709
|
FEATURE_LOOP_STATES: () => FEATURE_LOOP_STATES,
|
|
50405
50710
|
FEATURE_STATUSES: () => FEATURE_STATUSES,
|
|
50711
|
+
FN_INSTALL_CURL: () => FN_INSTALL_CURL,
|
|
50712
|
+
FN_INSTALL_NPM: () => FN_INSTALL_NPM,
|
|
50713
|
+
FN_NPM_PACKAGE: () => FN_NPM_PACKAGE,
|
|
50714
|
+
FN_NPX_INVOCATION: () => FN_NPX_INVOCATION,
|
|
50406
50715
|
FileMemoryBackend: () => FileMemoryBackend,
|
|
50407
50716
|
FirstRunDetector: () => FirstRunDetector,
|
|
50408
50717
|
GLOBAL_SETTINGS_KEYS: () => GLOBAL_SETTINGS_KEYS,
|
|
@@ -50514,6 +50823,7 @@ __export(src_exports, {
|
|
|
50514
50823
|
createInsightExtractionAutomation: () => createInsightExtractionAutomation,
|
|
50515
50824
|
createMemoryDreamsAutomation: () => createMemoryDreamsAutomation,
|
|
50516
50825
|
dailyMemoryPath: () => dailyMemoryPath,
|
|
50826
|
+
detectFnBinary: () => detectFnBinary,
|
|
50517
50827
|
detectLegacyData: () => detectLegacyData,
|
|
50518
50828
|
diffConfigSnapshots: () => diffConfigSnapshots,
|
|
50519
50829
|
discoverPiExtensions: () => discoverPiExtensions,
|
|
@@ -50635,6 +50945,7 @@ __export(src_exports, {
|
|
|
50635
50945
|
readProjectMemoryWithBackend: () => readProjectMemoryWithBackend,
|
|
50636
50946
|
readWorkingMemory: () => readWorkingMemory,
|
|
50637
50947
|
reconcileClaudeCliPaths: () => reconcileClaudeCliPaths,
|
|
50948
|
+
reconcileDroidCliPaths: () => reconcileDroidCliPaths,
|
|
50638
50949
|
refreshQmdProjectMemoryIndex: () => refreshQmdProjectMemoryIndex,
|
|
50639
50950
|
registerMemoryBackend: () => registerMemoryBackend,
|
|
50640
50951
|
renderMemoryAuditMarkdown: () => renderMemoryAuditMarkdown,
|
|
@@ -50724,6 +51035,7 @@ var init_src = __esm({
|
|
|
50724
51035
|
init_automation();
|
|
50725
51036
|
init_automation_store();
|
|
50726
51037
|
init_run_command();
|
|
51038
|
+
init_fn_binary();
|
|
50727
51039
|
init_node_override_guard();
|
|
50728
51040
|
init_settings_validation();
|
|
50729
51041
|
init_routine();
|
|
@@ -51885,12 +52197,12 @@ var init_concurrency = __esm({
|
|
|
51885
52197
|
this._active++;
|
|
51886
52198
|
return Promise.resolve();
|
|
51887
52199
|
}
|
|
51888
|
-
return new Promise((
|
|
52200
|
+
return new Promise((resolve42) => {
|
|
51889
52201
|
this._waiters.push({
|
|
51890
52202
|
priority,
|
|
51891
52203
|
resolve: () => {
|
|
51892
52204
|
this._active++;
|
|
51893
|
-
|
|
52205
|
+
resolve42();
|
|
51894
52206
|
}
|
|
51895
52207
|
});
|
|
51896
52208
|
});
|
|
@@ -53454,8 +53766,23 @@ function getPackageManagerAgentDir() {
|
|
|
53454
53766
|
}
|
|
53455
53767
|
function resolveVendoredClaudeCliEntry() {
|
|
53456
53768
|
try {
|
|
53457
|
-
const
|
|
53458
|
-
const pkgJsonPath =
|
|
53769
|
+
const require_3 = createRequire2(import.meta.url);
|
|
53770
|
+
const pkgJsonPath = require_3.resolve("@fusion/pi-claude-cli/package.json");
|
|
53771
|
+
const pkgJson = JSON.parse(readFileSync9(pkgJsonPath, "utf-8"));
|
|
53772
|
+
const extensions = pkgJson.pi?.extensions;
|
|
53773
|
+
if (!Array.isArray(extensions) || extensions.length === 0) return null;
|
|
53774
|
+
const entry = extensions[0];
|
|
53775
|
+
if (typeof entry !== "string" || entry.length === 0) return null;
|
|
53776
|
+
const path5 = resolve11(dirname8(pkgJsonPath), entry);
|
|
53777
|
+
return existsSync20(path5) ? path5 : null;
|
|
53778
|
+
} catch {
|
|
53779
|
+
return null;
|
|
53780
|
+
}
|
|
53781
|
+
}
|
|
53782
|
+
function resolveVendoredDroidCliEntry() {
|
|
53783
|
+
try {
|
|
53784
|
+
const require_3 = createRequire2(import.meta.url);
|
|
53785
|
+
const pkgJsonPath = require_3.resolve("@fusion/droid-cli/package.json");
|
|
53459
53786
|
const pkgJson = JSON.parse(readFileSync9(pkgJsonPath, "utf-8"));
|
|
53460
53787
|
const extensions = pkgJson.pi?.extensions;
|
|
53461
53788
|
if (!Array.isArray(extensions) || extensions.length === 0) return null;
|
|
@@ -53482,8 +53809,13 @@ async function registerExtensionProviders(cwd, modelRegistry) {
|
|
|
53482
53809
|
[...getEnabledPiExtensionPaths(cwd), ...packageExtensionPaths],
|
|
53483
53810
|
vendoredClaudeCli
|
|
53484
53811
|
);
|
|
53485
|
-
const
|
|
53812
|
+
const vendoredDroidCli = resolveVendoredDroidCliEntry();
|
|
53813
|
+
const doubleReconciledPaths = reconcileDroidCliPaths(
|
|
53486
53814
|
reconciledPaths,
|
|
53815
|
+
vendoredDroidCli
|
|
53816
|
+
);
|
|
53817
|
+
const extensionsResult = await discoverAndLoadExtensions(
|
|
53818
|
+
doubleReconciledPaths,
|
|
53487
53819
|
cwd,
|
|
53488
53820
|
join25(resolvePiExtensionProjectRoot(cwd), ".fusion", "disabled-auto-extension-discovery")
|
|
53489
53821
|
);
|
|
@@ -53727,11 +54059,8 @@ async function createFnAgent2(options) {
|
|
|
53727
54059
|
const createSessionWithModel = async (modelOverride) => {
|
|
53728
54060
|
const customToolList = [
|
|
53729
54061
|
...wrappedTools,
|
|
53730
|
-
...
|
|
54062
|
+
...options.customTools ?? []
|
|
53731
54063
|
];
|
|
53732
|
-
if (isReadonly && (options.customTools?.length ?? 0) > 0) {
|
|
53733
|
-
piLog.log(`readonly session \u2014 customTools (${options.customTools.length}) skipped`);
|
|
53734
|
-
}
|
|
53735
54064
|
if (options.beforeSpawnSession) {
|
|
53736
54065
|
await options.beforeSpawnSession();
|
|
53737
54066
|
}
|
|
@@ -54422,8 +54751,8 @@ var init_page_fetch_provider = __esm({
|
|
|
54422
54751
|
|
|
54423
54752
|
// ../engine/src/research/providers/web-search-provider.ts
|
|
54424
54753
|
async function sleep(ms, signal) {
|
|
54425
|
-
await new Promise((
|
|
54426
|
-
const timer = setTimeout(
|
|
54754
|
+
await new Promise((resolve42, reject2) => {
|
|
54755
|
+
const timer = setTimeout(resolve42, ms);
|
|
54427
54756
|
const onAbort = () => {
|
|
54428
54757
|
clearTimeout(timer);
|
|
54429
54758
|
reject2(new ResearchProviderError({ providerType: "web-search", code: "abort", message: "Search aborted" }));
|
|
@@ -55140,14 +55469,25 @@ async function getAgentMemoryWindow(rootDir, agentMemory, path5, startLine = 1,
|
|
|
55140
55469
|
backend: "agent-memory"
|
|
55141
55470
|
};
|
|
55142
55471
|
}
|
|
55143
|
-
function
|
|
55472
|
+
async function createAgentTask(store, input, options) {
|
|
55473
|
+
const settings = typeof store.getSettings === "function" ? await store.getSettings() : {};
|
|
55474
|
+
const rootDir = options?.rootDir;
|
|
55475
|
+
return store.createTask(input, {
|
|
55476
|
+
settings: { autoSummarizeTitles: settings.autoSummarizeTitles === true },
|
|
55477
|
+
onSummarize: rootDir ? async (description) => {
|
|
55478
|
+
const resolved = resolveTitleSummarizerSettingsModel(settings);
|
|
55479
|
+
return summarizeTitle(description, rootDir, resolved.provider, resolved.modelId);
|
|
55480
|
+
} : void 0
|
|
55481
|
+
});
|
|
55482
|
+
}
|
|
55483
|
+
function createTaskCreateTool(store, provenance, options) {
|
|
55144
55484
|
return {
|
|
55145
55485
|
name: "fn_task_create",
|
|
55146
55486
|
label: "Create Task",
|
|
55147
55487
|
description: "Create a new task for out-of-scope work discovered during execution. The task goes into triage where it will be specified by the AI. Optionally set dependencies (e.g., the new task depends on the current one, or the current task should wait for the new one).",
|
|
55148
55488
|
parameters: taskCreateParams,
|
|
55149
55489
|
execute: async (_id, params) => {
|
|
55150
|
-
const task = await store
|
|
55490
|
+
const task = await createAgentTask(store, {
|
|
55151
55491
|
description: params.description,
|
|
55152
55492
|
dependencies: params.dependencies,
|
|
55153
55493
|
column: "triage",
|
|
@@ -55156,7 +55496,7 @@ function createTaskCreateTool(store, provenance) {
|
|
|
55156
55496
|
sourceAgentId: provenance.sourceAgentId,
|
|
55157
55497
|
sourceRunId: provenance.sourceRunId
|
|
55158
55498
|
} : void 0
|
|
55159
|
-
});
|
|
55499
|
+
}, options);
|
|
55160
55500
|
const deps = task.dependencies.length ? ` (depends on: ${task.dependencies.join(", ")})` : "";
|
|
55161
55501
|
return {
|
|
55162
55502
|
content: [{
|
|
@@ -55509,7 +55849,7 @@ ${lines.join("\n\n")}` }],
|
|
|
55509
55849
|
}
|
|
55510
55850
|
};
|
|
55511
55851
|
}
|
|
55512
|
-
function createDelegateTaskTool(agentStore, taskStore) {
|
|
55852
|
+
function createDelegateTaskTool(agentStore, taskStore, options) {
|
|
55513
55853
|
return {
|
|
55514
55854
|
name: "fn_delegate_task",
|
|
55515
55855
|
label: "Delegate Task",
|
|
@@ -55529,13 +55869,13 @@ function createDelegateTaskTool(agentStore, taskStore) {
|
|
|
55529
55869
|
details: {}
|
|
55530
55870
|
};
|
|
55531
55871
|
}
|
|
55532
|
-
const task = await taskStore
|
|
55872
|
+
const task = await createAgentTask(taskStore, {
|
|
55533
55873
|
description: params.description,
|
|
55534
55874
|
dependencies: params.dependencies,
|
|
55535
55875
|
column: "todo",
|
|
55536
55876
|
assignedAgentId: params.agent_id,
|
|
55537
55877
|
source: { sourceType: "api" }
|
|
55538
|
-
});
|
|
55878
|
+
}, options);
|
|
55539
55879
|
const deps = task.dependencies.length ? ` (depends on: ${task.dependencies.join(", ")})` : "";
|
|
55540
55880
|
return {
|
|
55541
55881
|
content: [{
|
|
@@ -55710,9 +56050,9 @@ function createResearchTools(options) {
|
|
|
55710
56050
|
const maxWaitMs = Math.max(1e3, Math.min(params.max_wait_ms ?? 9e4, resolved.limits.maxDurationMs));
|
|
55711
56051
|
const completed = await Promise.race([
|
|
55712
56052
|
runPromise,
|
|
55713
|
-
new Promise((
|
|
56053
|
+
new Promise((resolve42) => setTimeout(() => {
|
|
55714
56054
|
const latest = options.store.getResearchStore().getRun(runId);
|
|
55715
|
-
|
|
56055
|
+
resolve42(latest ?? {
|
|
55716
56056
|
id: runId,
|
|
55717
56057
|
query: params.query,
|
|
55718
56058
|
status: "running",
|
|
@@ -57286,20 +57626,20 @@ async function withRateLimitRetry(fn, options = {}) {
|
|
|
57286
57626
|
throw lastError ?? new Error("withRateLimitRetry: unexpected state");
|
|
57287
57627
|
}
|
|
57288
57628
|
function sleep2(ms, signal) {
|
|
57289
|
-
return new Promise((
|
|
57629
|
+
return new Promise((resolve42, reject2) => {
|
|
57290
57630
|
if (signal?.aborted) {
|
|
57291
57631
|
reject2(signal.reason ?? new Error("Aborted"));
|
|
57292
57632
|
return;
|
|
57293
57633
|
}
|
|
57294
|
-
const timer = setTimeout(
|
|
57634
|
+
const timer = setTimeout(resolve42, ms);
|
|
57295
57635
|
if (signal) {
|
|
57296
57636
|
const onAbort = () => {
|
|
57297
57637
|
clearTimeout(timer);
|
|
57298
57638
|
reject2(signal.reason ?? new Error("Aborted"));
|
|
57299
57639
|
};
|
|
57300
57640
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
57301
|
-
const origResolve =
|
|
57302
|
-
|
|
57641
|
+
const origResolve = resolve42;
|
|
57642
|
+
resolve42 = () => {
|
|
57303
57643
|
signal.removeEventListener("abort", onAbort);
|
|
57304
57644
|
origResolve();
|
|
57305
57645
|
};
|
|
@@ -58362,7 +58702,7 @@ Write the PROMPT.md directly using the write tool, then call \`fn_review_spec()\
|
|
|
58362
58702
|
// Agent delegation tools — discover and delegate work to other agents.
|
|
58363
58703
|
...this.options.agentStore ? [
|
|
58364
58704
|
createListAgentsTool(this.options.agentStore),
|
|
58365
|
-
createDelegateTaskTool(this.options.agentStore, this.store)
|
|
58705
|
+
createDelegateTaskTool(this.options.agentStore, this.store, { rootDir: this.rootDir })
|
|
58366
58706
|
] : [],
|
|
58367
58707
|
this.createReviewSpecTool(
|
|
58368
58708
|
task.id,
|
|
@@ -58901,7 +59241,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
58901
59241
|
planLog.warn(`${options.parentTaskId}: failed to load parent task for fn_task_create inheritance: ${msg}`);
|
|
58902
59242
|
parentTask = void 0;
|
|
58903
59243
|
}
|
|
58904
|
-
const newTask = await store
|
|
59244
|
+
const newTask = await createAgentTask(store, {
|
|
58905
59245
|
title: params.title,
|
|
58906
59246
|
description: params.description,
|
|
58907
59247
|
dependencies: validDeps,
|
|
@@ -58915,7 +59255,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
58915
59255
|
sourceType: "agent_heartbeat",
|
|
58916
59256
|
sourceParentTaskId: options.parentTaskId
|
|
58917
59257
|
}
|
|
58918
|
-
});
|
|
59258
|
+
}, { rootDir: this.rootDir });
|
|
58919
59259
|
options.createdSubtasksRef.current.push(newTask.id);
|
|
58920
59260
|
return {
|
|
58921
59261
|
content: [
|
|
@@ -59343,13 +59683,13 @@ var init_run_audit = __esm({
|
|
|
59343
59683
|
});
|
|
59344
59684
|
|
|
59345
59685
|
// ../engine/src/merger.ts
|
|
59346
|
-
import { execSync, exec as exec2, spawn as
|
|
59686
|
+
import { execSync, exec as exec2, spawn as spawn3 } from "node:child_process";
|
|
59347
59687
|
import { promisify as promisify3 } from "node:util";
|
|
59348
59688
|
import { existsSync as existsSync22 } from "node:fs";
|
|
59349
59689
|
import { join as join29 } from "node:path";
|
|
59350
59690
|
import { Type as Type3 } from "typebox";
|
|
59351
59691
|
async function execWithProcessGroup(command, options) {
|
|
59352
|
-
return new Promise((
|
|
59692
|
+
return new Promise((resolve42, reject2) => {
|
|
59353
59693
|
if (options.signal?.aborted) {
|
|
59354
59694
|
reject2(Object.assign(
|
|
59355
59695
|
new Error(`Command aborted before start: ${command}`),
|
|
@@ -59358,7 +59698,7 @@ async function execWithProcessGroup(command, options) {
|
|
|
59358
59698
|
return;
|
|
59359
59699
|
}
|
|
59360
59700
|
const useProcessGroup = process.platform !== "win32";
|
|
59361
|
-
const child =
|
|
59701
|
+
const child = spawn3(command, {
|
|
59362
59702
|
cwd: options.cwd,
|
|
59363
59703
|
shell: true,
|
|
59364
59704
|
detached: useProcessGroup,
|
|
@@ -59442,7 +59782,7 @@ async function execWithProcessGroup(command, options) {
|
|
|
59442
59782
|
return;
|
|
59443
59783
|
}
|
|
59444
59784
|
if (code === 0) {
|
|
59445
|
-
|
|
59785
|
+
resolve42({ stdout, stderr, bufferOverflow: stdoutOverflow || stderrOverflow });
|
|
59446
59786
|
return;
|
|
59447
59787
|
}
|
|
59448
59788
|
reject2(Object.assign(
|
|
@@ -63866,7 +64206,7 @@ function resolveExecutorModelPair(taskModelProvider, taskModelId, settings) {
|
|
|
63866
64206
|
return { provider: void 0, modelId: void 0 };
|
|
63867
64207
|
}
|
|
63868
64208
|
function sleep3(ms) {
|
|
63869
|
-
return new Promise((
|
|
64209
|
+
return new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
63870
64210
|
}
|
|
63871
64211
|
var execAsync4, stepExecLog, MAX_STEP_RETRIES, RETRY_DELAYS_MS, NOOP_TASK_STORE, StepSessionExecutor;
|
|
63872
64212
|
var init_step_session_executor = __esm({
|
|
@@ -64094,10 +64434,10 @@ var init_step_session_executor = __esm({
|
|
|
64094
64434
|
] : [];
|
|
64095
64435
|
const memoryTools = createMemoryTools(this.options.rootDir, settings);
|
|
64096
64436
|
const taskLogTool = this.options.store ? [createTaskLogTool(this.options.store, taskDetail.id)] : [];
|
|
64097
|
-
const taskCreateTool = this.options.store ? [createTaskCreateTool(this.options.store)] : [];
|
|
64437
|
+
const taskCreateTool = this.options.store ? [createTaskCreateTool(this.options.store, void 0, { rootDir: this.options.rootDir })] : [];
|
|
64098
64438
|
const delegationTools = this.options.agentStore ? [
|
|
64099
64439
|
createListAgentsTool(this.options.agentStore),
|
|
64100
|
-
createDelegateTaskTool(this.options.agentStore, this.options.store)
|
|
64440
|
+
createDelegateTaskTool(this.options.agentStore, this.options.store, { rootDir: this.options.rootDir })
|
|
64101
64441
|
] : [];
|
|
64102
64442
|
const messagingTools = this.options.messageStore && taskDetail.assignedAgentId ? [
|
|
64103
64443
|
createSendMessageTool(this.options.messageStore, taskDetail.assignedAgentId),
|
|
@@ -64508,7 +64848,7 @@ var init_task_completion = __esm({
|
|
|
64508
64848
|
});
|
|
64509
64849
|
|
|
64510
64850
|
// ../engine/src/run-verification-tool.ts
|
|
64511
|
-
import { spawn as
|
|
64851
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
64512
64852
|
import { existsSync as existsSync26 } from "node:fs";
|
|
64513
64853
|
import { isAbsolute as isAbsolute10, join as join34 } from "node:path";
|
|
64514
64854
|
import { Type as Type4 } from "@mariozechner/pi-ai";
|
|
@@ -64540,8 +64880,8 @@ async function runVerificationCommand2(opts) {
|
|
|
64540
64880
|
const warnings = [];
|
|
64541
64881
|
const stdoutBuf = { head: "", tail: "", totalBytes: 0 };
|
|
64542
64882
|
const stderrBuf = { head: "", tail: "", totalBytes: 0 };
|
|
64543
|
-
return new Promise((
|
|
64544
|
-
const child =
|
|
64883
|
+
return new Promise((resolve42) => {
|
|
64884
|
+
const child = spawn4(command, {
|
|
64545
64885
|
cwd,
|
|
64546
64886
|
stdio: ["ignore", "pipe", "pipe"],
|
|
64547
64887
|
env: { ...process.env },
|
|
@@ -64619,7 +64959,7 @@ async function runVerificationCommand2(opts) {
|
|
|
64619
64959
|
`[fn_run_verification] command failed (exit=${exitCode}, signal=${signal ?? "none"}): ${command}`
|
|
64620
64960
|
);
|
|
64621
64961
|
}
|
|
64622
|
-
|
|
64962
|
+
resolve42({
|
|
64623
64963
|
success,
|
|
64624
64964
|
exitCode,
|
|
64625
64965
|
durationMs,
|
|
@@ -64639,7 +64979,7 @@ async function runVerificationCommand2(opts) {
|
|
|
64639
64979
|
clearTimeout(hardTimer);
|
|
64640
64980
|
const durationMs = Date.now() - startMs;
|
|
64641
64981
|
warnings.push(`Spawn error: ${err.message}`);
|
|
64642
|
-
|
|
64982
|
+
resolve42({
|
|
64643
64983
|
success: false,
|
|
64644
64984
|
exitCode: null,
|
|
64645
64985
|
durationMs,
|
|
@@ -66829,7 +67169,7 @@ The tool prevents your session from being killed by the inactivity watchdog duri
|
|
|
66829
67169
|
// Agent delegation tools — discover and delegate work to other agents.
|
|
66830
67170
|
...this.options.agentStore ? [
|
|
66831
67171
|
createListAgentsTool(this.options.agentStore),
|
|
66832
|
-
createDelegateTaskTool(this.options.agentStore, this.store)
|
|
67172
|
+
createDelegateTaskTool(this.options.agentStore, this.store, { rootDir: this.rootDir })
|
|
66833
67173
|
] : [],
|
|
66834
67174
|
// Messaging tools — allows executor agents to send and receive messages.
|
|
66835
67175
|
...this.options.messageStore && assignedAgentId ? [
|
|
@@ -67523,7 +67863,7 @@ The tool prevents your session from being killed by the inactivity watchdog duri
|
|
|
67523
67863
|
return createTaskLogTool(this.store, taskId);
|
|
67524
67864
|
}
|
|
67525
67865
|
createTaskCreateTool() {
|
|
67526
|
-
return createTaskCreateTool(this.store, { sourceType: "api" });
|
|
67866
|
+
return createTaskCreateTool(this.store, { sourceType: "api" }, { rootDir: this.rootDir });
|
|
67527
67867
|
}
|
|
67528
67868
|
createTaskDocumentWriteTool(taskId) {
|
|
67529
67869
|
return createTaskDocumentWriteTool(this.store, taskId);
|
|
@@ -68617,7 +68957,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
|
|
|
68617
68957
|
);
|
|
68618
68958
|
}
|
|
68619
68959
|
const delay2 = this.WORKTREE_RETRY_DELAYS[attempt] || 1e3;
|
|
68620
|
-
await new Promise((
|
|
68960
|
+
await new Promise((resolve42) => setTimeout(resolve42, delay2));
|
|
68621
68961
|
}
|
|
68622
68962
|
}
|
|
68623
68963
|
throw new Error("Unexpected exit from worktree creation retry loop");
|
|
@@ -72458,7 +72798,7 @@ function isTickableState(state) {
|
|
|
72458
72798
|
function isHeartbeatManaged(agent) {
|
|
72459
72799
|
return !isEphemeralAgent(agent);
|
|
72460
72800
|
}
|
|
72461
|
-
var HEARTBEAT_SYSTEM_PROMPT, HEARTBEAT_NO_TASK_SYSTEM_PROMPT, HEARTBEAT_PROCEDURE, heartbeatDoneParams, HeartbeatMonitor, OVERDUE_FIRE_JITTER_MS, HeartbeatTriggerScheduler;
|
|
72801
|
+
var HEARTBEAT_SYSTEM_PROMPT, HEARTBEAT_NO_TASK_SYSTEM_PROMPT, HEARTBEAT_PROCEDURE, HEARTBEAT_NO_TASK_PROCEDURE, heartbeatDoneParams, HeartbeatMonitor, OVERDUE_FIRE_JITTER_MS, HeartbeatTriggerScheduler;
|
|
72462
72802
|
var init_agent_heartbeat = __esm({
|
|
72463
72803
|
"../engine/src/agent-heartbeat.ts"() {
|
|
72464
72804
|
"use strict";
|
|
@@ -72648,6 +72988,32 @@ When sending messages:
|
|
|
72648
72988
|
Critical: a heartbeat without observable progress (a log, a document write, a
|
|
72649
72989
|
status change, a comment, a delegation, or an explicit "no-op with reason") is
|
|
72650
72990
|
a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
72991
|
+
HEARTBEAT_NO_TASK_PROCEDURE = `## Heartbeat Procedure (run every tick, in order)
|
|
72992
|
+
|
|
72993
|
+
1. **Identity & context** \u2014 review the **Identity Snapshot** at the top of
|
|
72994
|
+
this prompt. Confirm your role, soul, instructions, and memory match what
|
|
72995
|
+
you expect, and surface any anomalies in your first text output before
|
|
72996
|
+
doing anything else. (If fn_identity is available in your runtime you may
|
|
72997
|
+
also call it for full structured detail; the snapshot above is the
|
|
72998
|
+
authoritative source.)
|
|
72999
|
+
2. **Inbox** \u2014 when fn_read_messages is available, call it. Process any pending
|
|
73000
|
+
messages first; reply with reply_to_message_id when answering.
|
|
73001
|
+
3. **Wake delta** \u2014 read the Wake Delta block above. The wake reason is the
|
|
73002
|
+
highest-priority change for this heartbeat. If you were woken by a comment
|
|
73003
|
+
or a message, acknowledge it before doing anything else.
|
|
73004
|
+
4. **Ambient review** \u2014 since you have no assigned task, review board/project
|
|
73005
|
+
signals and recent memory context before acting.
|
|
73006
|
+
5. **Pick the next concrete action** \u2014 exactly ONE useful action this heartbeat:
|
|
73007
|
+
create a focused task, delegate work, send/reply to a message, or append
|
|
73008
|
+
durable memory.
|
|
73009
|
+
6. **Persist progress** \u2014 use available ambient tools only:
|
|
73010
|
+
fn_task_create, fn_delegate_task, fn_send_message, fn_memory_append.
|
|
73011
|
+
7. **Exit** \u2014 call fn_heartbeat_done with a one-line summary of what changed
|
|
73012
|
+
this tick. If you took no action, say so and explain why.
|
|
73013
|
+
|
|
73014
|
+
Critical: a heartbeat without observable progress (a created task, delegation,
|
|
73015
|
+
message reply, memory append, or explicit "no-op with reason") is a bug. Do
|
|
73016
|
+
not loop on the same plan across heartbeats without recording why.`;
|
|
72651
73017
|
heartbeatDoneParams = Type6.Object({
|
|
72652
73018
|
summary: Type6.Optional(Type6.String({ description: "Summary of what was accomplished this heartbeat" }))
|
|
72653
73019
|
});
|
|
@@ -72687,13 +73053,6 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
|
72687
73053
|
this.rootDir = options.rootDir;
|
|
72688
73054
|
this.messageStore = options.messageStore;
|
|
72689
73055
|
this.pluginRunner = options.pluginRunner;
|
|
72690
|
-
this.onRecovered = options.onRecovered;
|
|
72691
|
-
this.onTerminated = options.onTerminated;
|
|
72692
|
-
this.onRunStarted = options.onRunStarted;
|
|
72693
|
-
this.onRunCompleted = options.onRunCompleted;
|
|
72694
|
-
this.taskStore = options.taskStore;
|
|
72695
|
-
this.rootDir = options.rootDir;
|
|
72696
|
-
this.messageStore = options.messageStore;
|
|
72697
73056
|
}
|
|
72698
73057
|
/**
|
|
72699
73058
|
* Start the heartbeat monitoring loop.
|
|
@@ -73392,9 +73751,9 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
|
73392
73751
|
sourceType: "agent_heartbeat",
|
|
73393
73752
|
sourceAgentId: agentId,
|
|
73394
73753
|
sourceRunId: runContext?.runId
|
|
73395
|
-
}));
|
|
73754
|
+
}, { rootDir: this.rootDir }));
|
|
73396
73755
|
heartbeatTools.push(createListAgentsTool(this.store));
|
|
73397
|
-
heartbeatTools.push(createDelegateTaskTool(this.store, taskStore));
|
|
73756
|
+
heartbeatTools.push(createDelegateTaskTool(this.store, taskStore, { rootDir: this.rootDir }));
|
|
73398
73757
|
if (this.messageStore) {
|
|
73399
73758
|
heartbeatTools.push(createSendMessageTool(this.messageStore, agentId));
|
|
73400
73759
|
heartbeatTools.push(createReadMessagesTool(this.messageStore, agentId));
|
|
@@ -73417,22 +73776,27 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
|
73417
73776
|
heartbeatLog.warn(`Failed to configure heartbeat memory tools for ${agentId}: ${message}`);
|
|
73418
73777
|
}
|
|
73419
73778
|
const skillContext = buildSessionSkillContextSync2(agent, "heartbeat", rootDir);
|
|
73420
|
-
|
|
73421
|
-
const baseHeartbeatSystemPrompt = systemPrompt;
|
|
73779
|
+
const baseHeartbeatSystemPrompt = isNoTaskRun ? HEARTBEAT_NO_TASK_SYSTEM_PROMPT : HEARTBEAT_SYSTEM_PROMPT;
|
|
73422
73780
|
let resolvedInstructionsForIdentity = "";
|
|
73423
73781
|
try {
|
|
73424
|
-
|
|
73425
|
-
resolvedInstructionsForIdentity = agentInstructions;
|
|
73426
|
-
const memoryInstructions = memorySettings?.memoryEnabled === false ? "" : buildExecutionMemoryInstructions(rootDir, memorySettings);
|
|
73427
|
-
systemPrompt = buildSystemPromptWithInstructions(
|
|
73428
|
-
baseHeartbeatSystemPrompt,
|
|
73429
|
-
[agentInstructions, memoryInstructions].filter((part) => part.trim()).join("\n\n")
|
|
73430
|
-
);
|
|
73782
|
+
resolvedInstructionsForIdentity = await resolveAgentInstructionsWithRatings(agent, rootDir, this.store);
|
|
73431
73783
|
} catch (instructionError) {
|
|
73432
|
-
systemPrompt = baseHeartbeatSystemPrompt;
|
|
73433
73784
|
const message = instructionError instanceof Error ? instructionError.message : String(instructionError);
|
|
73434
|
-
heartbeatLog.warn(`Failed to
|
|
73785
|
+
heartbeatLog.warn(`Failed to resolve agent instructions for heartbeat ${agentId}: ${message}`);
|
|
73786
|
+
}
|
|
73787
|
+
let memoryInstructions = "";
|
|
73788
|
+
if (memorySettings?.memoryEnabled !== false) {
|
|
73789
|
+
try {
|
|
73790
|
+
memoryInstructions = buildExecutionMemoryInstructions(rootDir, memorySettings);
|
|
73791
|
+
} catch (memoryInstructionErr) {
|
|
73792
|
+
const message = memoryInstructionErr instanceof Error ? memoryInstructionErr.message : String(memoryInstructionErr);
|
|
73793
|
+
heartbeatLog.warn(`Failed to resolve project memory instructions for heartbeat ${agentId}: ${message}`);
|
|
73794
|
+
}
|
|
73435
73795
|
}
|
|
73796
|
+
const systemPrompt = buildSystemPromptWithInstructions(
|
|
73797
|
+
baseHeartbeatSystemPrompt,
|
|
73798
|
+
[resolvedInstructionsForIdentity, memoryInstructions].filter((part) => part.trim()).join("\n\n")
|
|
73799
|
+
);
|
|
73436
73800
|
heartbeatTools.push(createIdentityTool({ agent, resolvedInstructions: resolvedInstructionsForIdentity }));
|
|
73437
73801
|
heartbeatTools.push(heartbeatDoneTool);
|
|
73438
73802
|
if (isNoTaskRun) {
|
|
@@ -73493,7 +73857,7 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
|
73493
73857
|
};
|
|
73494
73858
|
const wakeReason = deriveWakeReason();
|
|
73495
73859
|
const customProcedure = await resolveAgentHeartbeatProcedure(agent, rootDir);
|
|
73496
|
-
const heartbeatProcedureText = customProcedure ?? HEARTBEAT_PROCEDURE;
|
|
73860
|
+
const heartbeatProcedureText = customProcedure ?? (isNoTaskRun ? HEARTBEAT_NO_TASK_PROCEDURE : HEARTBEAT_PROCEDURE);
|
|
73497
73861
|
if (isNoTaskRun) {
|
|
73498
73862
|
if (this.messageStore) {
|
|
73499
73863
|
try {
|
|
@@ -73526,6 +73890,8 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
|
73526
73890
|
`- pending messages: ${pendingMessages.length}`,
|
|
73527
73891
|
"",
|
|
73528
73892
|
"Treat this wake delta as the highest-priority change for this heartbeat.",
|
|
73893
|
+
"This is an autonomous heartbeat run (manual or automatic): re-anchor on",
|
|
73894
|
+
"identity, process wake context, then complete ONE concrete action.",
|
|
73529
73895
|
"Run the Heartbeat Procedure (below) before doing anything else \u2014 even a",
|
|
73530
73896
|
"timer-only wake should re-check messages, memory, and project state.",
|
|
73531
73897
|
"",
|
|
@@ -73617,6 +73983,8 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
|
|
|
73617
73983
|
`- triggering comments: ${effectiveTriggeringCommentIds?.length ?? 0}`,
|
|
73618
73984
|
"",
|
|
73619
73985
|
"Treat this wake delta as the highest-priority change for this heartbeat.",
|
|
73986
|
+
"This is an autonomous heartbeat run (manual or automatic): re-anchor on",
|
|
73987
|
+
"identity, process wake context, then complete ONE concrete action.",
|
|
73620
73988
|
"Before resuming prior task work, run the Heartbeat Procedure (below) and",
|
|
73621
73989
|
"decide what action this delta requires. Your assigned task is one input",
|
|
73622
73990
|
"to the procedure \u2014 not the only thing to consider.",
|
|
@@ -73776,7 +74144,7 @@ ${taskDetail.prompt}` : "No PROMPT.md available.",
|
|
|
73776
74144
|
const baseCreateTool = createTaskCreateTool(taskStore, {
|
|
73777
74145
|
sourceType: "agent_heartbeat",
|
|
73778
74146
|
sourceAgentId: agentId
|
|
73779
|
-
});
|
|
74147
|
+
}, { rootDir: this.rootDir });
|
|
73780
74148
|
const trackedCreateTool = {
|
|
73781
74149
|
...baseCreateTool,
|
|
73782
74150
|
execute: async (id, params, signal, onUpdate, ctx) => {
|
|
@@ -73803,7 +74171,7 @@ ${taskDetail.prompt}` : "No PROMPT.md available.",
|
|
|
73803
74171
|
tools.push(createTaskDocumentWriteTool(taskStore, taskId));
|
|
73804
74172
|
tools.push(createTaskDocumentReadTool(taskStore, taskId));
|
|
73805
74173
|
tools.push(createListAgentsTool(this.store));
|
|
73806
|
-
tools.push(createDelegateTaskTool(this.store, taskStore));
|
|
74174
|
+
tools.push(createDelegateTaskTool(this.store, taskStore, { rootDir: this.rootDir }));
|
|
73807
74175
|
if (messageStore) {
|
|
73808
74176
|
tools.push(createSendMessageTool(messageStore, agentId));
|
|
73809
74177
|
tools.push(createReadMessagesTool(messageStore, agentId));
|
|
@@ -75387,7 +75755,7 @@ var init_shell_utils = __esm({
|
|
|
75387
75755
|
// ../engine/src/cron-runner.ts
|
|
75388
75756
|
import { exec as exec6 } from "node:child_process";
|
|
75389
75757
|
function execCommand(command, options) {
|
|
75390
|
-
return new Promise((
|
|
75758
|
+
return new Promise((resolve42, reject2) => {
|
|
75391
75759
|
exec6(command, options, (error, stdout, stderr) => {
|
|
75392
75760
|
const stdoutText = typeof stdout === "string" ? stdout : String(stdout ?? "");
|
|
75393
75761
|
const stderrText = typeof stderr === "string" ? stderr : String(stderr ?? "");
|
|
@@ -75398,7 +75766,7 @@ function execCommand(command, options) {
|
|
|
75398
75766
|
reject2(errWithOutput);
|
|
75399
75767
|
return;
|
|
75400
75768
|
}
|
|
75401
|
-
|
|
75769
|
+
resolve42({ stdout: stdoutText, stderr: stderrText });
|
|
75402
75770
|
});
|
|
75403
75771
|
});
|
|
75404
75772
|
}
|
|
@@ -78749,13 +79117,13 @@ var init_plugin_runner = __esm({
|
|
|
78749
79117
|
* Returns the result on success, throws on timeout.
|
|
78750
79118
|
*/
|
|
78751
79119
|
withTimeout(promise, ms, timeoutMessage) {
|
|
78752
|
-
return new Promise((
|
|
79120
|
+
return new Promise((resolve42, reject2) => {
|
|
78753
79121
|
const timer = setTimeout(() => {
|
|
78754
79122
|
reject2(new Error(timeoutMessage));
|
|
78755
79123
|
}, ms);
|
|
78756
79124
|
promise.then((result) => {
|
|
78757
79125
|
clearTimeout(timer);
|
|
78758
|
-
|
|
79126
|
+
resolve42(result);
|
|
78759
79127
|
}).catch((err) => {
|
|
78760
79128
|
clearTimeout(timer);
|
|
78761
79129
|
reject2(err);
|
|
@@ -79391,7 +79759,7 @@ var init_in_process_runtime = __esm({
|
|
|
79391
79759
|
runtimeLog.log(
|
|
79392
79760
|
`Waiting for ${metrics.inFlightTasks} in-flight tasks to complete...`
|
|
79393
79761
|
);
|
|
79394
|
-
await new Promise((
|
|
79762
|
+
await new Promise((resolve42) => setTimeout(resolve42, 1e3));
|
|
79395
79763
|
}
|
|
79396
79764
|
const finalMetrics = this.getMetrics();
|
|
79397
79765
|
if (finalMetrics.inFlightTasks > 0) {
|
|
@@ -79788,13 +80156,13 @@ var init_ipc_host = __esm({
|
|
|
79788
80156
|
}
|
|
79789
80157
|
const id = generateCorrelationId();
|
|
79790
80158
|
const message = { type, id, payload };
|
|
79791
|
-
return new Promise((
|
|
80159
|
+
return new Promise((resolve42, reject2) => {
|
|
79792
80160
|
const timeout2 = setTimeout(() => {
|
|
79793
80161
|
this.pendingCommands.delete(id);
|
|
79794
80162
|
reject2(new Error(`Command ${type} timed out after ${timeoutMs ?? this.commandTimeoutMs}ms`));
|
|
79795
80163
|
}, timeoutMs ?? this.commandTimeoutMs);
|
|
79796
80164
|
this.pendingCommands.set(id, {
|
|
79797
|
-
resolve:
|
|
80165
|
+
resolve: resolve42,
|
|
79798
80166
|
reject: reject2,
|
|
79799
80167
|
timeout: timeout2,
|
|
79800
80168
|
type
|
|
@@ -80603,8 +80971,8 @@ var init_remote_node_client = __esm({
|
|
|
80603
80971
|
return error instanceof TypeError;
|
|
80604
80972
|
}
|
|
80605
80973
|
async sleep(ms) {
|
|
80606
|
-
await new Promise((
|
|
80607
|
-
setTimeout(
|
|
80974
|
+
await new Promise((resolve42) => {
|
|
80975
|
+
setTimeout(resolve42, ms);
|
|
80608
80976
|
});
|
|
80609
80977
|
}
|
|
80610
80978
|
};
|
|
@@ -80868,14 +81236,14 @@ var init_remote_node_runtime = __esm({
|
|
|
80868
81236
|
return error instanceof Error ? error : new Error(String(error));
|
|
80869
81237
|
}
|
|
80870
81238
|
async sleep(ms, signal) {
|
|
80871
|
-
await new Promise((
|
|
81239
|
+
await new Promise((resolve42) => {
|
|
80872
81240
|
const timeout2 = setTimeout(() => {
|
|
80873
81241
|
cleanup();
|
|
80874
|
-
|
|
81242
|
+
resolve42();
|
|
80875
81243
|
}, ms);
|
|
80876
81244
|
const onAbort = () => {
|
|
80877
81245
|
cleanup();
|
|
80878
|
-
|
|
81246
|
+
resolve42();
|
|
80879
81247
|
};
|
|
80880
81248
|
const cleanup = () => {
|
|
80881
81249
|
clearTimeout(timeout2);
|
|
@@ -81505,7 +81873,7 @@ var init_provider_adapters = __esm({
|
|
|
81505
81873
|
|
|
81506
81874
|
// ../engine/src/remote-access/tunnel-process-manager.ts
|
|
81507
81875
|
import { EventEmitter as EventEmitter24 } from "node:events";
|
|
81508
|
-
import { exec as exec9, execFile as execFile3, spawn as
|
|
81876
|
+
import { exec as exec9, execFile as execFile3, spawn as spawn5 } from "node:child_process";
|
|
81509
81877
|
import { promisify as promisify9 } from "node:util";
|
|
81510
81878
|
function nowIso() {
|
|
81511
81879
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -81596,7 +81964,7 @@ var init_tunnel_process_manager = __esm({
|
|
|
81596
81964
|
super();
|
|
81597
81965
|
this.maxLogEntries = options.maxLogEntries ?? DEFAULT_MAX_LOG_ENTRIES;
|
|
81598
81966
|
this.defaultStopTimeoutMs = options.stopTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS2;
|
|
81599
|
-
this.spawnImpl = options.spawnImpl ??
|
|
81967
|
+
this.spawnImpl = options.spawnImpl ?? spawn5;
|
|
81600
81968
|
}
|
|
81601
81969
|
getStatus() {
|
|
81602
81970
|
return { ...this.status, lastError: this.status.lastError ? { ...this.status.lastError } : null };
|
|
@@ -81826,10 +82194,10 @@ var init_tunnel_process_manager = __esm({
|
|
|
81826
82194
|
lastError: null
|
|
81827
82195
|
});
|
|
81828
82196
|
this.emitLog("info", "manager", `Stopping ${currentHandle.provider} tunnel (pid=${currentHandle.child.pid ?? "n/a"})`);
|
|
81829
|
-
this.activeStopPromise = new Promise((
|
|
82197
|
+
this.activeStopPromise = new Promise((resolve42) => {
|
|
81830
82198
|
const onClose = () => {
|
|
81831
82199
|
currentHandle.child.removeListener("close", onClose);
|
|
81832
|
-
|
|
82200
|
+
resolve42();
|
|
81833
82201
|
};
|
|
81834
82202
|
currentHandle.child.once("close", onClose);
|
|
81835
82203
|
killManagedProcess(currentHandle.child, "SIGTERM");
|
|
@@ -81970,6 +82338,7 @@ var execFileAsync2, MERGE_HANDOFF_GRACE_MS, isRemoteActive, ProjectEngine;
|
|
|
81970
82338
|
var init_project_engine = __esm({
|
|
81971
82339
|
"../engine/src/project-engine.ts"() {
|
|
81972
82340
|
"use strict";
|
|
82341
|
+
init_src();
|
|
81973
82342
|
init_in_process_runtime();
|
|
81974
82343
|
init_pr_monitor();
|
|
81975
82344
|
init_pr_comment_handler();
|
|
@@ -82436,12 +82805,12 @@ ${detail}`
|
|
|
82436
82805
|
*/
|
|
82437
82806
|
async onMerge(taskId) {
|
|
82438
82807
|
if (this.mergeActive.has(taskId)) {
|
|
82439
|
-
return new Promise((
|
|
82440
|
-
this.manualMergeResolvers.set(taskId, { resolve:
|
|
82808
|
+
return new Promise((resolve42, reject2) => {
|
|
82809
|
+
this.manualMergeResolvers.set(taskId, { resolve: resolve42, reject: reject2 });
|
|
82441
82810
|
});
|
|
82442
82811
|
}
|
|
82443
|
-
return new Promise((
|
|
82444
|
-
this.manualMergeResolvers.set(taskId, { resolve:
|
|
82812
|
+
return new Promise((resolve42, reject2) => {
|
|
82813
|
+
this.manualMergeResolvers.set(taskId, { resolve: resolve42, reject: reject2 });
|
|
82445
82814
|
this.internalEnqueueMerge(taskId);
|
|
82446
82815
|
});
|
|
82447
82816
|
}
|
|
@@ -82664,6 +83033,48 @@ ${detail}`
|
|
|
82664
83033
|
if (task.status === "failed") return false;
|
|
82665
83034
|
return (task.mergeRetries ?? 0) < _ProjectEngine.MAX_AUTO_MERGE_RETRIES || this.hasAutoHealableVerificationBufferFailure(task) || this.isRetryCooldownElapsed(task);
|
|
82666
83035
|
}
|
|
83036
|
+
/**
|
|
83037
|
+
* Remove and return the highest-priority taskId from the merge queue.
|
|
83038
|
+
* Ordering: priority (urgent→low), then createdAt ASC, then id ASC — matching
|
|
83039
|
+
* the triage and scheduler comparators. Manual merges (onMerge resolvers) are
|
|
83040
|
+
* preferred over auto-merges so awaited callers aren't starved by a flood of
|
|
83041
|
+
* higher-priority auto-enqueues. IDs whose tasks can't be loaded fall back to
|
|
83042
|
+
* FIFO order so they still drain.
|
|
83043
|
+
*/
|
|
83044
|
+
async pickNextMergeTaskId(store) {
|
|
83045
|
+
if (this.mergeQueue.length === 0) return void 0;
|
|
83046
|
+
if (this.mergeQueue.length === 1) {
|
|
83047
|
+
return this.mergeQueue.shift();
|
|
83048
|
+
}
|
|
83049
|
+
const queueSnapshot = [...this.mergeQueue];
|
|
83050
|
+
const entries = [];
|
|
83051
|
+
for (let i = 0; i < queueSnapshot.length; i++) {
|
|
83052
|
+
const taskId = queueSnapshot[i];
|
|
83053
|
+
const task = await store.getTask(taskId).catch(() => void 0);
|
|
83054
|
+
entries.push({
|
|
83055
|
+
taskId,
|
|
83056
|
+
task,
|
|
83057
|
+
manual: this.manualMergeResolvers.has(taskId),
|
|
83058
|
+
order: i
|
|
83059
|
+
});
|
|
83060
|
+
}
|
|
83061
|
+
if (this.shuttingDown) return void 0;
|
|
83062
|
+
entries.sort((a, b) => {
|
|
83063
|
+
if (a.manual !== b.manual) return a.manual ? -1 : 1;
|
|
83064
|
+
if (a.task && b.task) return compareTasksByPriorityThenAgeAndId(a.task, b.task);
|
|
83065
|
+
if (a.task) return -1;
|
|
83066
|
+
if (b.task) return 1;
|
|
83067
|
+
return a.order - b.order;
|
|
83068
|
+
});
|
|
83069
|
+
for (const entry of entries) {
|
|
83070
|
+
const liveIndex = this.mergeQueue.indexOf(entry.taskId);
|
|
83071
|
+
if (liveIndex !== -1) {
|
|
83072
|
+
this.mergeQueue.splice(liveIndex, 1);
|
|
83073
|
+
return entry.taskId;
|
|
83074
|
+
}
|
|
83075
|
+
}
|
|
83076
|
+
return void 0;
|
|
83077
|
+
}
|
|
82667
83078
|
internalEnqueueMerge(taskId) {
|
|
82668
83079
|
if (this.shuttingDown) return;
|
|
82669
83080
|
if (this.mergeActive.has(taskId)) return;
|
|
@@ -82671,6 +83082,23 @@ ${detail}`
|
|
|
82671
83082
|
this.mergeQueue.push(taskId);
|
|
82672
83083
|
void this.drainMergeQueue();
|
|
82673
83084
|
}
|
|
83085
|
+
/**
|
|
83086
|
+
* Filter a sweep's listTasks() result to merge-eligible tasks, sort by
|
|
83087
|
+
* priority (urgent → low, then createdAt ASC, then id ASC), and enqueue.
|
|
83088
|
+
* Sorting before enqueue matters because each enqueue may immediately
|
|
83089
|
+
* trigger drainMergeQueue's single-item fast path, so the first task
|
|
83090
|
+
* pushed wins. listTasks returns createdAt ASC — without this sort an
|
|
83091
|
+
* older low-priority task would start before a later urgent one.
|
|
83092
|
+
*/
|
|
83093
|
+
enqueueEligibleInReviewTasks(tasks) {
|
|
83094
|
+
const eligible = sortTasksByPriorityThenAgeAndId(
|
|
83095
|
+
tasks.filter((t) => !t.paused && this.canMergeTask(t))
|
|
83096
|
+
);
|
|
83097
|
+
for (const t of eligible) {
|
|
83098
|
+
this.internalEnqueueMerge(t.id);
|
|
83099
|
+
}
|
|
83100
|
+
return eligible.length;
|
|
83101
|
+
}
|
|
82674
83102
|
async drainMergeQueue() {
|
|
82675
83103
|
if (this.mergeRunning) return;
|
|
82676
83104
|
this.mergeRunning = true;
|
|
@@ -82678,7 +83106,9 @@ ${detail}`
|
|
|
82678
83106
|
const store = this.runtime.getTaskStore();
|
|
82679
83107
|
const cwd = this.config.workingDirectory;
|
|
82680
83108
|
while (this.mergeQueue.length > 0 && !this.shuttingDown) {
|
|
82681
|
-
const taskId = this.
|
|
83109
|
+
const taskId = await this.pickNextMergeTaskId(store);
|
|
83110
|
+
if (!taskId) break;
|
|
83111
|
+
if (this.shuttingDown) break;
|
|
82682
83112
|
const manualResolver = this.manualMergeResolvers.get(taskId);
|
|
82683
83113
|
try {
|
|
82684
83114
|
if (!manualResolver) {
|
|
@@ -83148,12 +83578,9 @@ ${detail}`
|
|
|
83148
83578
|
}
|
|
83149
83579
|
const settings = await store.getSettings();
|
|
83150
83580
|
if (!settings.autoMerge) return;
|
|
83151
|
-
const
|
|
83152
|
-
if (
|
|
83153
|
-
runtimeLog.log(`Auto-merge startup sweep: enqueueing ${
|
|
83154
|
-
for (const t of eligible) {
|
|
83155
|
-
this.internalEnqueueMerge(t.id);
|
|
83156
|
-
}
|
|
83581
|
+
const enqueued = this.enqueueEligibleInReviewTasks(tasks);
|
|
83582
|
+
if (enqueued > 0) {
|
|
83583
|
+
runtimeLog.log(`Auto-merge startup sweep: enqueueing ${enqueued} task(s)`);
|
|
83157
83584
|
}
|
|
83158
83585
|
} catch (err) {
|
|
83159
83586
|
runtimeLog.warn(
|
|
@@ -83169,14 +83596,7 @@ ${detail}`
|
|
|
83169
83596
|
const settings = await store.getSettings();
|
|
83170
83597
|
if (!settings.globalPause && !settings.enginePaused && settings.autoMerge) {
|
|
83171
83598
|
const tasks = await store.listTasks({ column: "in-review" });
|
|
83172
|
-
|
|
83173
|
-
if (t.paused) {
|
|
83174
|
-
continue;
|
|
83175
|
-
}
|
|
83176
|
-
if (this.canMergeTask(t)) {
|
|
83177
|
-
this.internalEnqueueMerge(t.id);
|
|
83178
|
-
}
|
|
83179
|
-
}
|
|
83599
|
+
this.enqueueEligibleInReviewTasks(tasks);
|
|
83180
83600
|
}
|
|
83181
83601
|
} catch (err) {
|
|
83182
83602
|
runtimeLog.warn(
|
|
@@ -83232,14 +83652,7 @@ ${detail}`
|
|
|
83232
83652
|
if (s.autoMerge) {
|
|
83233
83653
|
try {
|
|
83234
83654
|
const tasks = await store.listTasks({ column: "in-review" });
|
|
83235
|
-
|
|
83236
|
-
if (t.paused) {
|
|
83237
|
-
continue;
|
|
83238
|
-
}
|
|
83239
|
-
if (this.canMergeTask(t)) {
|
|
83240
|
-
this.internalEnqueueMerge(t.id);
|
|
83241
|
-
}
|
|
83242
|
-
}
|
|
83655
|
+
this.enqueueEligibleInReviewTasks(tasks);
|
|
83243
83656
|
} catch (err) {
|
|
83244
83657
|
runtimeLog.warn(
|
|
83245
83658
|
`Global unpause: failed to scan in-review tasks for auto-merge: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -83269,14 +83682,7 @@ ${detail}`
|
|
|
83269
83682
|
if (s.autoMerge) {
|
|
83270
83683
|
try {
|
|
83271
83684
|
const tasks = await store.listTasks({ column: "in-review" });
|
|
83272
|
-
|
|
83273
|
-
if (t.paused) {
|
|
83274
|
-
continue;
|
|
83275
|
-
}
|
|
83276
|
-
if (this.canMergeTask(t)) {
|
|
83277
|
-
this.internalEnqueueMerge(t.id);
|
|
83278
|
-
}
|
|
83279
|
-
}
|
|
83685
|
+
this.enqueueEligibleInReviewTasks(tasks);
|
|
83280
83686
|
} catch (err) {
|
|
83281
83687
|
runtimeLog.warn(
|
|
83282
83688
|
`Engine unpause: failed to scan in-review tasks for auto-merge: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -83869,7 +84275,7 @@ var init_peer_exchange_service = __esm({
|
|
|
83869
84275
|
syncIntervalMs;
|
|
83870
84276
|
interval = null;
|
|
83871
84277
|
activeSync = null;
|
|
83872
|
-
|
|
84278
|
+
running = false;
|
|
83873
84279
|
/** Whether settings sync is enabled. Default: false. */
|
|
83874
84280
|
settingsSyncEnabled;
|
|
83875
84281
|
/** Minimum interval between settings syncs with the same node in ms. Default: 5 minutes. */
|
|
@@ -83911,10 +84317,11 @@ var init_peer_exchange_service = __esm({
|
|
|
83911
84317
|
* Begins periodic gossip with all online remote nodes.
|
|
83912
84318
|
*/
|
|
83913
84319
|
start() {
|
|
83914
|
-
if (this.
|
|
83915
|
-
peerExchangeLog.
|
|
84320
|
+
if (this.running) {
|
|
84321
|
+
peerExchangeLog.log("Peer exchange service already running");
|
|
83916
84322
|
return;
|
|
83917
84323
|
}
|
|
84324
|
+
this.running = true;
|
|
83918
84325
|
this.centralCore.listNodes().then((nodes) => {
|
|
83919
84326
|
const onlineRemoteCount = nodes.filter(
|
|
83920
84327
|
(n) => n.type === "remote" && n.status === "online" && n.url
|
|
@@ -83924,6 +84331,7 @@ var init_peer_exchange_service = __esm({
|
|
|
83924
84331
|
peerExchangeLog.warn(`Failed to get initial peer count: ${err}`);
|
|
83925
84332
|
});
|
|
83926
84333
|
this.interval = setInterval(() => {
|
|
84334
|
+
if (!this.running) return;
|
|
83927
84335
|
void this.syncWithAllPeers();
|
|
83928
84336
|
}, this.syncIntervalMs);
|
|
83929
84337
|
}
|
|
@@ -83931,12 +84339,21 @@ var init_peer_exchange_service = __esm({
|
|
|
83931
84339
|
* Stop the peer exchange service.
|
|
83932
84340
|
* Clears the sync interval and prevents further syncs.
|
|
83933
84341
|
*/
|
|
83934
|
-
stop() {
|
|
84342
|
+
async stop() {
|
|
84343
|
+
if (!this.running) {
|
|
84344
|
+
return;
|
|
84345
|
+
}
|
|
84346
|
+
this.running = false;
|
|
83935
84347
|
if (this.interval) {
|
|
83936
84348
|
clearInterval(this.interval);
|
|
83937
84349
|
this.interval = null;
|
|
83938
84350
|
}
|
|
83939
|
-
this.
|
|
84351
|
+
if (this.activeSync) {
|
|
84352
|
+
try {
|
|
84353
|
+
await this.activeSync;
|
|
84354
|
+
} catch {
|
|
84355
|
+
}
|
|
84356
|
+
}
|
|
83940
84357
|
peerExchangeLog.log("Stopped peer exchange service");
|
|
83941
84358
|
}
|
|
83942
84359
|
/**
|
|
@@ -85495,7 +85912,7 @@ For completion:
|
|
|
85495
85912
|
}`;
|
|
85496
85913
|
SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
85497
85914
|
CLEANUP_INTERVAL_MS2 = 5 * 60 * 1e3;
|
|
85498
|
-
MAX_SESSIONS_PER_IP_PER_HOUR =
|
|
85915
|
+
MAX_SESSIONS_PER_IP_PER_HOUR = 1e3;
|
|
85499
85916
|
RATE_LIMIT_WINDOW_MS2 = 60 * 60 * 1e3;
|
|
85500
85917
|
GENERATION_TIMEOUT_MS = 12e4;
|
|
85501
85918
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -88381,7 +88798,7 @@ var init_src3 = __esm({
|
|
|
88381
88798
|
});
|
|
88382
88799
|
|
|
88383
88800
|
// ../../plugins/fusion-plugin-hermes-runtime/dist/cli-spawn.js
|
|
88384
|
-
import { spawn as
|
|
88801
|
+
import { spawn as spawn6, spawnSync } from "node:child_process";
|
|
88385
88802
|
import os2 from "node:os";
|
|
88386
88803
|
import path, { sep as PATH_SEP } from "node:path";
|
|
88387
88804
|
function resolveBinaryForSpawn(binary) {
|
|
@@ -88443,9 +88860,9 @@ function hermesProfileHome(profileName) {
|
|
|
88443
88860
|
async function listHermesProfiles(opts) {
|
|
88444
88861
|
const binary = resolveBinaryForSpawn(opts?.binaryPath ?? "hermes");
|
|
88445
88862
|
const timeoutMs = opts?.timeoutMs ?? 5e3;
|
|
88446
|
-
return new Promise((
|
|
88863
|
+
return new Promise((resolve42, reject2) => {
|
|
88447
88864
|
let settled = false;
|
|
88448
|
-
const child =
|
|
88865
|
+
const child = spawn6(binary, ["profile", "list"], {
|
|
88449
88866
|
stdio: ["ignore", "pipe", "pipe"],
|
|
88450
88867
|
env: { ...process.env }
|
|
88451
88868
|
});
|
|
@@ -88486,7 +88903,7 @@ async function listHermesProfiles(opts) {
|
|
|
88486
88903
|
${combined}`));
|
|
88487
88904
|
return;
|
|
88488
88905
|
}
|
|
88489
|
-
|
|
88906
|
+
resolve42(parseProfileListOutput(stdout));
|
|
88490
88907
|
});
|
|
88491
88908
|
});
|
|
88492
88909
|
}
|
|
@@ -88563,13 +88980,13 @@ function buildHermesArgs(prompt, settings, resumeSessionId) {
|
|
|
88563
88980
|
async function invokeHermesCli(prompt, settings, resumeSessionId, signal) {
|
|
88564
88981
|
const args = buildHermesArgs(prompt, settings, resumeSessionId);
|
|
88565
88982
|
const binary = resolveBinaryForSpawn(settings.binaryPath);
|
|
88566
|
-
return new Promise((
|
|
88983
|
+
return new Promise((resolve42, reject2) => {
|
|
88567
88984
|
let settled = false;
|
|
88568
88985
|
const spawnEnv = { ...process.env, PYTHONUNBUFFERED: "1" };
|
|
88569
88986
|
if (settings.profile) {
|
|
88570
88987
|
spawnEnv.HERMES_HOME = hermesProfileHome(settings.profile);
|
|
88571
88988
|
}
|
|
88572
|
-
const child =
|
|
88989
|
+
const child = spawn6(binary, args, {
|
|
88573
88990
|
stdio: ["ignore", "pipe", "pipe"],
|
|
88574
88991
|
env: spawnEnv
|
|
88575
88992
|
});
|
|
@@ -88631,7 +89048,7 @@ ${combined}`));
|
|
|
88631
89048
|
return;
|
|
88632
89049
|
}
|
|
88633
89050
|
try {
|
|
88634
|
-
|
|
89051
|
+
resolve42(parseHermesOutput(stdout, stderr));
|
|
88635
89052
|
} catch (parseErr) {
|
|
88636
89053
|
reject2(parseErr);
|
|
88637
89054
|
}
|
|
@@ -88724,7 +89141,7 @@ var init_runtime_adapter = __esm({
|
|
|
88724
89141
|
});
|
|
88725
89142
|
|
|
88726
89143
|
// ../../plugins/fusion-plugin-hermes-runtime/dist/probe.js
|
|
88727
|
-
import { spawn as
|
|
89144
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
88728
89145
|
async function probeHermesBinary(opts) {
|
|
88729
89146
|
const startedAt = Date.now();
|
|
88730
89147
|
const binary = typeof opts?.binaryPath === "string" && opts.binaryPath.trim().length > 0 ? opts.binaryPath.trim() : "hermes";
|
|
@@ -88735,7 +89152,7 @@ async function probeHermesBinary(opts) {
|
|
|
88735
89152
|
resolvePromise({ ...result, probeDurationMs: Date.now() - startedAt });
|
|
88736
89153
|
};
|
|
88737
89154
|
let settled = false;
|
|
88738
|
-
const child =
|
|
89155
|
+
const child = spawn7(resolvedPath ?? binary, ["--version"], {
|
|
88739
89156
|
stdio: ["ignore", "pipe", "pipe"]
|
|
88740
89157
|
});
|
|
88741
89158
|
const timer = setTimeout(() => {
|
|
@@ -88796,7 +89213,7 @@ async function probeHermesBinary(opts) {
|
|
|
88796
89213
|
async function tryResolveBinaryPath(binary) {
|
|
88797
89214
|
return new Promise((resolvePromise) => {
|
|
88798
89215
|
const which = process.platform === "win32" ? "where" : "which";
|
|
88799
|
-
const child =
|
|
89216
|
+
const child = spawn7(which, [binary], { stdio: ["ignore", "pipe", "ignore"] });
|
|
88800
89217
|
let out = "";
|
|
88801
89218
|
child.stdout?.on("data", (chunk) => {
|
|
88802
89219
|
out += chunk.toString("utf-8");
|
|
@@ -88874,7 +89291,7 @@ var init_dist = __esm({
|
|
|
88874
89291
|
});
|
|
88875
89292
|
|
|
88876
89293
|
// ../../plugins/fusion-plugin-openclaw-runtime/dist/pi-module.js
|
|
88877
|
-
import { spawn as
|
|
89294
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
88878
89295
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
88879
89296
|
function asString(v) {
|
|
88880
89297
|
return typeof v === "string" && v.trim() !== "" ? v.trim() : void 0;
|
|
@@ -88949,9 +89366,9 @@ async function promptCli(session, message, config, callbacks, signal) {
|
|
|
88949
89366
|
const args = buildOpenClawArgs(config, session.sessionId, message);
|
|
88950
89367
|
const cb = { ...session.callbacks, ...callbacks };
|
|
88951
89368
|
cb.onToolStart?.("openclaw.agent", { sessionId: session.sessionId });
|
|
88952
|
-
return new Promise((
|
|
89369
|
+
return new Promise((resolve42, reject2) => {
|
|
88953
89370
|
let settled = false;
|
|
88954
|
-
const child =
|
|
89371
|
+
const child = spawn8(config.binaryPath, args, {
|
|
88955
89372
|
stdio: ["ignore", "pipe", "pipe"]
|
|
88956
89373
|
});
|
|
88957
89374
|
const hardKill = setTimeout(() => {
|
|
@@ -89042,7 +89459,7 @@ async function promptCli(session, message, config, callbacks, signal) {
|
|
|
89042
89459
|
...metaError ? { error: metaError } : {},
|
|
89043
89460
|
...errorText.length > 0 ? { toolErrors: errorText } : {}
|
|
89044
89461
|
});
|
|
89045
|
-
|
|
89462
|
+
resolve42();
|
|
89046
89463
|
});
|
|
89047
89464
|
});
|
|
89048
89465
|
}
|
|
@@ -89102,7 +89519,7 @@ var init_runtime_adapter2 = __esm({
|
|
|
89102
89519
|
});
|
|
89103
89520
|
|
|
89104
89521
|
// ../../plugins/fusion-plugin-openclaw-runtime/dist/probe.js
|
|
89105
|
-
import { spawn as
|
|
89522
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
89106
89523
|
async function probeOpenClawBinary(opts = {}) {
|
|
89107
89524
|
const startedAt = Date.now();
|
|
89108
89525
|
const binary = opts.binaryPath ?? "openclaw";
|
|
@@ -89113,7 +89530,7 @@ async function probeOpenClawBinary(opts = {}) {
|
|
|
89113
89530
|
resolvePromise({ ...partial, probeDurationMs: Date.now() - startedAt });
|
|
89114
89531
|
};
|
|
89115
89532
|
let settled = false;
|
|
89116
|
-
const child =
|
|
89533
|
+
const child = spawn9(resolvedPath ?? binary, ["--version"], {
|
|
89117
89534
|
stdio: ["ignore", "pipe", "pipe"]
|
|
89118
89535
|
});
|
|
89119
89536
|
const timer = setTimeout(() => {
|
|
@@ -89174,7 +89591,7 @@ async function probeOpenClawBinary(opts = {}) {
|
|
|
89174
89591
|
async function tryResolveBinaryPath2(binary) {
|
|
89175
89592
|
return new Promise((resolvePromise) => {
|
|
89176
89593
|
const which = process.platform === "win32" ? "where" : "which";
|
|
89177
|
-
const child =
|
|
89594
|
+
const child = spawn9(which, [binary], { stdio: ["ignore", "pipe", "ignore"] });
|
|
89178
89595
|
let out = "";
|
|
89179
89596
|
child.stdout?.on("data", (chunk) => {
|
|
89180
89597
|
out += chunk.toString("utf-8");
|
|
@@ -90595,7 +91012,7 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
90595
91012
|
router.patch("/tasks/:id", async (req, res) => {
|
|
90596
91013
|
try {
|
|
90597
91014
|
const { store: scopedStore } = await getProjectContext3(req);
|
|
90598
|
-
const { title, description, prompt, dependencies, enabledWorkflowSteps, modelProvider, modelId, validatorModelProvider, validatorModelId, planningModelProvider, planningModelId, thinkingLevel, assigneeUserId, reviewLevel, executionMode, sourceIssue, nodeId } = req.body;
|
|
91015
|
+
const { title, description, prompt, priority, dependencies, enabledWorkflowSteps, modelProvider, modelId, validatorModelProvider, validatorModelId, planningModelProvider, planningModelId, thinkingLevel, assigneeUserId, reviewLevel, executionMode, sourceIssue, nodeId } = req.body;
|
|
90599
91016
|
const hasBodyField = (field) => Object.prototype.hasOwnProperty.call(req.body, field);
|
|
90600
91017
|
const validateModelField = (value, name) => {
|
|
90601
91018
|
if (value === void 0) return void 0;
|
|
@@ -90625,6 +91042,9 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
90625
91042
|
if (executionMode !== void 0 && executionMode !== null && !validExecutionModes.includes(executionMode)) {
|
|
90626
91043
|
throw new Error(`executionMode must be one of: ${validExecutionModes.join(", ")}`);
|
|
90627
91044
|
}
|
|
91045
|
+
if (priority !== void 0 && priority !== null && !isTaskPriority(priority)) {
|
|
91046
|
+
throw new Error(`priority must be one of: ${TASK_PRIORITIES.join(", ")}`);
|
|
91047
|
+
}
|
|
90628
91048
|
if (enabledWorkflowSteps !== void 0) {
|
|
90629
91049
|
if (!Array.isArray(enabledWorkflowSteps) || !enabledWorkflowSteps.every((id) => typeof id === "string")) {
|
|
90630
91050
|
throw new Error("enabledWorkflowSteps must be an array of strings");
|
|
@@ -90684,6 +91104,7 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
90684
91104
|
if (title !== void 0) updates.title = title;
|
|
90685
91105
|
if (description !== void 0) updates.description = description;
|
|
90686
91106
|
if (prompt !== void 0) updates.prompt = prompt;
|
|
91107
|
+
if (hasBodyField("priority")) updates.priority = priority;
|
|
90687
91108
|
if (dependencies !== void 0) updates.dependencies = dependencies;
|
|
90688
91109
|
if (enabledWorkflowSteps !== void 0) updates.enabledWorkflowSteps = enabledWorkflowSteps;
|
|
90689
91110
|
if (hasBodyField("modelProvider")) updates.modelProvider = validatedModelProvider;
|
|
@@ -90714,7 +91135,7 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
90714
91135
|
if (err instanceof ApiError) {
|
|
90715
91136
|
throw err;
|
|
90716
91137
|
}
|
|
90717
|
-
const status = (err instanceof Error ? err.message : String(err)).includes("must be a string") || (err instanceof Error ? err.message : String(err)).includes("must be a non-empty string") || (err instanceof Error ? err.message : String(err)).includes("must be a string or null") || (err instanceof Error ? err.message : String(err)).includes("must be an array of strings") || (err instanceof Error ? err.message : String(err)).includes("thinkingLevel must be one of") || (err instanceof Error ? err.message : String(err)).includes("reviewLevel must be an integer") || (err instanceof Error ? err.message : String(err)).includes("executionMode must be one of") || (err instanceof Error ? err.message : String(err)).includes("sourceIssue") ? 400 : 500;
|
|
91138
|
+
const status = (err instanceof Error ? err.message : String(err)).includes("must be a string") || (err instanceof Error ? err.message : String(err)).includes("must be a non-empty string") || (err instanceof Error ? err.message : String(err)).includes("must be a string or null") || (err instanceof Error ? err.message : String(err)).includes("must be an array of strings") || (err instanceof Error ? err.message : String(err)).includes("thinkingLevel must be one of") || (err instanceof Error ? err.message : String(err)).includes("reviewLevel must be an integer") || (err instanceof Error ? err.message : String(err)).includes("executionMode must be one of") || (err instanceof Error ? err.message : String(err)).includes("priority must be one of") || (err instanceof Error ? err.message : String(err)).includes("sourceIssue") ? 400 : 500;
|
|
90718
91139
|
throw new ApiError(status, err instanceof Error ? err.message : String(err));
|
|
90719
91140
|
}
|
|
90720
91141
|
});
|
|
@@ -97386,10 +97807,10 @@ var require_browser3 = __commonJS({
|
|
|
97386
97807
|
text = canvas;
|
|
97387
97808
|
canvas = void 0;
|
|
97388
97809
|
}
|
|
97389
|
-
return new Promise(function(
|
|
97810
|
+
return new Promise(function(resolve42, reject2) {
|
|
97390
97811
|
try {
|
|
97391
97812
|
const data = QRCode2.create(text, opts);
|
|
97392
|
-
|
|
97813
|
+
resolve42(renderFunc(data, canvas, opts));
|
|
97393
97814
|
} catch (e) {
|
|
97394
97815
|
reject2(e);
|
|
97395
97816
|
}
|
|
@@ -97471,11 +97892,11 @@ var require_server = __commonJS({
|
|
|
97471
97892
|
}
|
|
97472
97893
|
function render(renderFunc, text, params) {
|
|
97473
97894
|
if (!params.cb) {
|
|
97474
|
-
return new Promise(function(
|
|
97895
|
+
return new Promise(function(resolve42, reject2) {
|
|
97475
97896
|
try {
|
|
97476
97897
|
const data = QRCode2.create(text, params.opts);
|
|
97477
97898
|
return renderFunc(data, params.opts, function(err, data2) {
|
|
97478
|
-
return err ? reject2(err) :
|
|
97899
|
+
return err ? reject2(err) : resolve42(data2);
|
|
97479
97900
|
});
|
|
97480
97901
|
} catch (e) {
|
|
97481
97902
|
reject2(e);
|
|
@@ -99123,9 +99544,9 @@ import * as fs2 from "node:fs";
|
|
|
99123
99544
|
import { createRequire as createRequire3 } from "node:module";
|
|
99124
99545
|
import { join as join42, dirname as dirname12 } from "node:path";
|
|
99125
99546
|
function getNativePrebuildName() {
|
|
99126
|
-
const
|
|
99547
|
+
const platform4 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
|
|
99127
99548
|
const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
|
|
99128
|
-
return `${
|
|
99549
|
+
return `${platform4}-${arch}`;
|
|
99129
99550
|
}
|
|
99130
99551
|
function findInstalledNodePtyNativeDir() {
|
|
99131
99552
|
try {
|
|
@@ -99307,8 +99728,8 @@ var init_terminal_service = __esm({
|
|
|
99307
99728
|
* Get the default allowed shells for the current platform
|
|
99308
99729
|
*/
|
|
99309
99730
|
getAllowedShells() {
|
|
99310
|
-
const
|
|
99311
|
-
return ALLOWED_SHELL_PATHS[
|
|
99731
|
+
const platform4 = os3.platform();
|
|
99732
|
+
return ALLOWED_SHELL_PATHS[platform4] || ALLOWED_SHELL_PATHS.linux;
|
|
99312
99733
|
}
|
|
99313
99734
|
/**
|
|
99314
99735
|
* Validate that a shell path is allowed
|
|
@@ -99322,7 +99743,7 @@ var init_terminal_service = __esm({
|
|
|
99322
99743
|
* Detect the best shell for the current platform
|
|
99323
99744
|
*/
|
|
99324
99745
|
detectShell() {
|
|
99325
|
-
const
|
|
99746
|
+
const platform4 = os3.platform();
|
|
99326
99747
|
const allowedShells = this.getAllowedShells();
|
|
99327
99748
|
const getBasename = (shellPath) => {
|
|
99328
99749
|
const lastSep = Math.max(shellPath.lastIndexOf("/"), shellPath.lastIndexOf("\\"));
|
|
@@ -99339,7 +99760,7 @@ var init_terminal_service = __esm({
|
|
|
99339
99760
|
return ["--login"];
|
|
99340
99761
|
};
|
|
99341
99762
|
const userShell = process.env.SHELL;
|
|
99342
|
-
if (userShell &&
|
|
99763
|
+
if (userShell && platform4 !== "win32") {
|
|
99343
99764
|
const normalizedUserShell = this.isWindows ? userShell.toLowerCase() : userShell;
|
|
99344
99765
|
for (const allowed of allowedShells) {
|
|
99345
99766
|
const normalizedAllowed = this.isWindows ? allowed.toLowerCase() : allowed;
|
|
@@ -99353,7 +99774,7 @@ var init_terminal_service = __esm({
|
|
|
99353
99774
|
return { shell, args: getShellArgs(shell) };
|
|
99354
99775
|
}
|
|
99355
99776
|
}
|
|
99356
|
-
if (
|
|
99777
|
+
if (platform4 === "win32") {
|
|
99357
99778
|
return { shell: "cmd.exe", args: [] };
|
|
99358
99779
|
}
|
|
99359
99780
|
return { shell: "/bin/sh", args: [] };
|
|
@@ -100186,7 +100607,7 @@ var init_register_messaging_scripts = __esm({
|
|
|
100186
100607
|
|
|
100187
100608
|
// ../dashboard/src/github.ts
|
|
100188
100609
|
function delay(ms) {
|
|
100189
|
-
return new Promise((
|
|
100610
|
+
return new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
100190
100611
|
}
|
|
100191
100612
|
function normalizeCheckState(state) {
|
|
100192
100613
|
switch ((state ?? "").toLowerCase()) {
|
|
@@ -104580,7 +105001,7 @@ var init_register_git_github = __esm({
|
|
|
104580
105001
|
});
|
|
104581
105002
|
|
|
104582
105003
|
// ../dashboard/src/terminal.ts
|
|
104583
|
-
import { spawn as
|
|
105004
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
104584
105005
|
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
104585
105006
|
import { EventEmitter as EventEmitter32 } from "node:events";
|
|
104586
105007
|
function extractBaseCommand(command) {
|
|
@@ -104742,7 +105163,7 @@ var init_terminal = __esm({
|
|
|
104742
105163
|
return { sessionId: "", error: validation.error };
|
|
104743
105164
|
}
|
|
104744
105165
|
const sessionId = randomUUID17();
|
|
104745
|
-
const childProcess =
|
|
105166
|
+
const childProcess = spawn10(command, [], {
|
|
104746
105167
|
cwd,
|
|
104747
105168
|
shell: true,
|
|
104748
105169
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -106460,9 +106881,9 @@ var require_readdir_glob = __commonJS({
|
|
|
106460
106881
|
var fs3 = __require("fs");
|
|
106461
106882
|
var { EventEmitter: EventEmitter37 } = __require("events");
|
|
106462
106883
|
var { Minimatch } = require_minimatch();
|
|
106463
|
-
var { resolve:
|
|
106884
|
+
var { resolve: resolve42 } = __require("path");
|
|
106464
106885
|
function readdir12(dir2, strict) {
|
|
106465
|
-
return new Promise((
|
|
106886
|
+
return new Promise((resolve43, reject2) => {
|
|
106466
106887
|
fs3.readdir(dir2, { withFileTypes: true }, (err, files) => {
|
|
106467
106888
|
if (err) {
|
|
106468
106889
|
switch (err.code) {
|
|
@@ -106470,7 +106891,7 @@ var require_readdir_glob = __commonJS({
|
|
|
106470
106891
|
if (strict) {
|
|
106471
106892
|
reject2(err);
|
|
106472
106893
|
} else {
|
|
106473
|
-
|
|
106894
|
+
resolve43([]);
|
|
106474
106895
|
}
|
|
106475
106896
|
break;
|
|
106476
106897
|
case "ENOTSUP":
|
|
@@ -106480,7 +106901,7 @@ var require_readdir_glob = __commonJS({
|
|
|
106480
106901
|
case "ENAMETOOLONG":
|
|
106481
106902
|
// Filename too long
|
|
106482
106903
|
case "UNKNOWN":
|
|
106483
|
-
|
|
106904
|
+
resolve43([]);
|
|
106484
106905
|
break;
|
|
106485
106906
|
case "ELOOP":
|
|
106486
106907
|
// Too many levels of symbolic links
|
|
@@ -106489,30 +106910,30 @@ var require_readdir_glob = __commonJS({
|
|
|
106489
106910
|
break;
|
|
106490
106911
|
}
|
|
106491
106912
|
} else {
|
|
106492
|
-
|
|
106913
|
+
resolve43(files);
|
|
106493
106914
|
}
|
|
106494
106915
|
});
|
|
106495
106916
|
});
|
|
106496
106917
|
}
|
|
106497
106918
|
function stat12(file, followSymlinks) {
|
|
106498
|
-
return new Promise((
|
|
106919
|
+
return new Promise((resolve43, reject2) => {
|
|
106499
106920
|
const statFunc = followSymlinks ? fs3.stat : fs3.lstat;
|
|
106500
106921
|
statFunc(file, (err, stats) => {
|
|
106501
106922
|
if (err) {
|
|
106502
106923
|
switch (err.code) {
|
|
106503
106924
|
case "ENOENT":
|
|
106504
106925
|
if (followSymlinks) {
|
|
106505
|
-
|
|
106926
|
+
resolve43(stat12(file, false));
|
|
106506
106927
|
} else {
|
|
106507
|
-
|
|
106928
|
+
resolve43(null);
|
|
106508
106929
|
}
|
|
106509
106930
|
break;
|
|
106510
106931
|
default:
|
|
106511
|
-
|
|
106932
|
+
resolve43(null);
|
|
106512
106933
|
break;
|
|
106513
106934
|
}
|
|
106514
106935
|
} else {
|
|
106515
|
-
|
|
106936
|
+
resolve43(stats);
|
|
106516
106937
|
}
|
|
106517
106938
|
});
|
|
106518
106939
|
});
|
|
@@ -106602,7 +107023,7 @@ var require_readdir_glob = __commonJS({
|
|
|
106602
107023
|
(skip) => new Minimatch(skip, { dot: true })
|
|
106603
107024
|
);
|
|
106604
107025
|
}
|
|
106605
|
-
this.iterator = explore(
|
|
107026
|
+
this.iterator = explore(resolve42(cwd || "."), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this));
|
|
106606
107027
|
this.paused = false;
|
|
106607
107028
|
this.inactive = false;
|
|
106608
107029
|
this.aborted = false;
|
|
@@ -106856,10 +107277,10 @@ function awaitify(asyncFn, arity) {
|
|
|
106856
107277
|
if (typeof args[arity - 1] === "function") {
|
|
106857
107278
|
return asyncFn.apply(this, args);
|
|
106858
107279
|
}
|
|
106859
|
-
return new Promise((
|
|
107280
|
+
return new Promise((resolve42, reject2) => {
|
|
106860
107281
|
args[arity - 1] = (err, ...cbArgs) => {
|
|
106861
107282
|
if (err) return reject2(err);
|
|
106862
|
-
|
|
107283
|
+
resolve42(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
|
|
106863
107284
|
};
|
|
106864
107285
|
asyncFn.apply(this, args);
|
|
106865
107286
|
});
|
|
@@ -107041,13 +107462,13 @@ function mapSeries(coll, iteratee, callback) {
|
|
|
107041
107462
|
return _asyncMap(eachOfSeries$1, coll, iteratee, callback);
|
|
107042
107463
|
}
|
|
107043
107464
|
function promiseCallback() {
|
|
107044
|
-
let
|
|
107465
|
+
let resolve42, reject2;
|
|
107045
107466
|
function callback(err, ...args) {
|
|
107046
107467
|
if (err) return reject2(err);
|
|
107047
|
-
|
|
107468
|
+
resolve42(args.length > 1 ? args : args[0]);
|
|
107048
107469
|
}
|
|
107049
107470
|
callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
|
|
107050
|
-
|
|
107471
|
+
resolve42 = res, reject2 = rej;
|
|
107051
107472
|
});
|
|
107052
107473
|
return callback;
|
|
107053
107474
|
}
|
|
@@ -107320,8 +107741,8 @@ function queue$1(worker, concurrency, payload) {
|
|
|
107320
107741
|
});
|
|
107321
107742
|
}
|
|
107322
107743
|
if (rejectOnError || !callback) {
|
|
107323
|
-
return new Promise((
|
|
107324
|
-
res =
|
|
107744
|
+
return new Promise((resolve42, reject2) => {
|
|
107745
|
+
res = resolve42;
|
|
107325
107746
|
rej = reject2;
|
|
107326
107747
|
});
|
|
107327
107748
|
}
|
|
@@ -107360,10 +107781,10 @@ function queue$1(worker, concurrency, payload) {
|
|
|
107360
107781
|
}
|
|
107361
107782
|
const eventMethod = (name) => (handler) => {
|
|
107362
107783
|
if (!handler) {
|
|
107363
|
-
return new Promise((
|
|
107784
|
+
return new Promise((resolve42, reject2) => {
|
|
107364
107785
|
once3(name, (err, data) => {
|
|
107365
107786
|
if (err) return reject2(err);
|
|
107366
|
-
|
|
107787
|
+
resolve42(data);
|
|
107367
107788
|
});
|
|
107368
107789
|
});
|
|
107369
107790
|
}
|
|
@@ -108539,7 +108960,7 @@ var require_polyfills = __commonJS({
|
|
|
108539
108960
|
var constants2 = __require("constants");
|
|
108540
108961
|
var origCwd = process.cwd;
|
|
108541
108962
|
var cwd = null;
|
|
108542
|
-
var
|
|
108963
|
+
var platform4 = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
|
108543
108964
|
process.cwd = function() {
|
|
108544
108965
|
if (!cwd)
|
|
108545
108966
|
cwd = origCwd.call(process);
|
|
@@ -108598,7 +109019,7 @@ var require_polyfills = __commonJS({
|
|
|
108598
109019
|
fs3.lchownSync = function() {
|
|
108599
109020
|
};
|
|
108600
109021
|
}
|
|
108601
|
-
if (
|
|
109022
|
+
if (platform4 === "win32") {
|
|
108602
109023
|
fs3.rename = typeof fs3.rename !== "function" ? fs3.rename : (function(fs$rename) {
|
|
108603
109024
|
function rename6(from, to, cb) {
|
|
108604
109025
|
var start = Date.now();
|
|
@@ -113369,25 +113790,25 @@ var require_util2 = __commonJS({
|
|
|
113369
113790
|
};
|
|
113370
113791
|
},
|
|
113371
113792
|
createDeferredPromise: function() {
|
|
113372
|
-
let
|
|
113793
|
+
let resolve42;
|
|
113373
113794
|
let reject2;
|
|
113374
113795
|
const promise = new Promise((res, rej) => {
|
|
113375
|
-
|
|
113796
|
+
resolve42 = res;
|
|
113376
113797
|
reject2 = rej;
|
|
113377
113798
|
});
|
|
113378
113799
|
return {
|
|
113379
113800
|
promise,
|
|
113380
|
-
resolve:
|
|
113801
|
+
resolve: resolve42,
|
|
113381
113802
|
reject: reject2
|
|
113382
113803
|
};
|
|
113383
113804
|
},
|
|
113384
113805
|
promisify(fn) {
|
|
113385
|
-
return new Promise((
|
|
113806
|
+
return new Promise((resolve42, reject2) => {
|
|
113386
113807
|
fn((err, ...args) => {
|
|
113387
113808
|
if (err) {
|
|
113388
113809
|
return reject2(err);
|
|
113389
113810
|
}
|
|
113390
|
-
return
|
|
113811
|
+
return resolve42(...args);
|
|
113391
113812
|
});
|
|
113392
113813
|
});
|
|
113393
113814
|
},
|
|
@@ -114179,7 +114600,7 @@ var require_end_of_stream2 = __commonJS({
|
|
|
114179
114600
|
validateBoolean3(opts.cleanup, "cleanup");
|
|
114180
114601
|
autoCleanup = opts.cleanup;
|
|
114181
114602
|
}
|
|
114182
|
-
return new Promise2((
|
|
114603
|
+
return new Promise2((resolve42, reject2) => {
|
|
114183
114604
|
const cleanup = eos(stream, opts, (err) => {
|
|
114184
114605
|
if (autoCleanup) {
|
|
114185
114606
|
cleanup();
|
|
@@ -114187,7 +114608,7 @@ var require_end_of_stream2 = __commonJS({
|
|
|
114187
114608
|
if (err) {
|
|
114188
114609
|
reject2(err);
|
|
114189
114610
|
} else {
|
|
114190
|
-
|
|
114611
|
+
resolve42();
|
|
114191
114612
|
}
|
|
114192
114613
|
});
|
|
114193
114614
|
});
|
|
@@ -115354,7 +115775,7 @@ var require_readable2 = __commonJS({
|
|
|
115354
115775
|
error = this.readableEnded ? null : new AbortError();
|
|
115355
115776
|
this.destroy(error);
|
|
115356
115777
|
}
|
|
115357
|
-
return new Promise2((
|
|
115778
|
+
return new Promise2((resolve42, reject2) => eos(this, (err) => err && err !== error ? reject2(err) : resolve42(null)));
|
|
115358
115779
|
};
|
|
115359
115780
|
Readable2.prototype.push = function(chunk, encoding) {
|
|
115360
115781
|
return readableAddChunk(this, chunk, encoding, false);
|
|
@@ -115898,12 +116319,12 @@ var require_readable2 = __commonJS({
|
|
|
115898
116319
|
}
|
|
115899
116320
|
async function* createAsyncIterator(stream, options) {
|
|
115900
116321
|
let callback = nop;
|
|
115901
|
-
function next(
|
|
116322
|
+
function next(resolve42) {
|
|
115902
116323
|
if (this === stream) {
|
|
115903
116324
|
callback();
|
|
115904
116325
|
callback = nop;
|
|
115905
116326
|
} else {
|
|
115906
|
-
callback =
|
|
116327
|
+
callback = resolve42;
|
|
115907
116328
|
}
|
|
115908
116329
|
}
|
|
115909
116330
|
stream.on("readable", next);
|
|
@@ -116956,7 +117377,7 @@ var require_duplexify = __commonJS({
|
|
|
116956
117377
|
);
|
|
116957
117378
|
};
|
|
116958
117379
|
function fromAsyncGen(fn) {
|
|
116959
|
-
let { promise, resolve:
|
|
117380
|
+
let { promise, resolve: resolve42 } = createDeferredPromise();
|
|
116960
117381
|
const ac = new AbortController2();
|
|
116961
117382
|
const signal = ac.signal;
|
|
116962
117383
|
const value = fn(
|
|
@@ -116971,7 +117392,7 @@ var require_duplexify = __commonJS({
|
|
|
116971
117392
|
throw new AbortError(void 0, {
|
|
116972
117393
|
cause: signal.reason
|
|
116973
117394
|
});
|
|
116974
|
-
({ promise, resolve:
|
|
117395
|
+
({ promise, resolve: resolve42 } = createDeferredPromise());
|
|
116975
117396
|
yield chunk;
|
|
116976
117397
|
}
|
|
116977
117398
|
})(),
|
|
@@ -116982,8 +117403,8 @@ var require_duplexify = __commonJS({
|
|
|
116982
117403
|
return {
|
|
116983
117404
|
value,
|
|
116984
117405
|
write(chunk, encoding, cb) {
|
|
116985
|
-
const _resolve =
|
|
116986
|
-
|
|
117406
|
+
const _resolve = resolve42;
|
|
117407
|
+
resolve42 = null;
|
|
116987
117408
|
_resolve({
|
|
116988
117409
|
chunk,
|
|
116989
117410
|
done: false,
|
|
@@ -116991,8 +117412,8 @@ var require_duplexify = __commonJS({
|
|
|
116991
117412
|
});
|
|
116992
117413
|
},
|
|
116993
117414
|
final(cb) {
|
|
116994
|
-
const _resolve =
|
|
116995
|
-
|
|
117415
|
+
const _resolve = resolve42;
|
|
117416
|
+
resolve42 = null;
|
|
116996
117417
|
_resolve({
|
|
116997
117418
|
done: true,
|
|
116998
117419
|
cb
|
|
@@ -117444,7 +117865,7 @@ var require_pipeline = __commonJS({
|
|
|
117444
117865
|
callback();
|
|
117445
117866
|
}
|
|
117446
117867
|
};
|
|
117447
|
-
const wait = () => new Promise2((
|
|
117868
|
+
const wait = () => new Promise2((resolve42, reject2) => {
|
|
117448
117869
|
if (error) {
|
|
117449
117870
|
reject2(error);
|
|
117450
117871
|
} else {
|
|
@@ -117452,7 +117873,7 @@ var require_pipeline = __commonJS({
|
|
|
117452
117873
|
if (error) {
|
|
117453
117874
|
reject2(error);
|
|
117454
117875
|
} else {
|
|
117455
|
-
|
|
117876
|
+
resolve42();
|
|
117456
117877
|
}
|
|
117457
117878
|
};
|
|
117458
117879
|
}
|
|
@@ -118096,8 +118517,8 @@ var require_operators = __commonJS({
|
|
|
118096
118517
|
next = null;
|
|
118097
118518
|
}
|
|
118098
118519
|
if (!done && (queue2.length >= highWaterMark2 || cnt >= concurrency)) {
|
|
118099
|
-
await new Promise2((
|
|
118100
|
-
resume =
|
|
118520
|
+
await new Promise2((resolve42) => {
|
|
118521
|
+
resume = resolve42;
|
|
118101
118522
|
});
|
|
118102
118523
|
}
|
|
118103
118524
|
}
|
|
@@ -118131,8 +118552,8 @@ var require_operators = __commonJS({
|
|
|
118131
118552
|
queue2.shift();
|
|
118132
118553
|
maybeResume();
|
|
118133
118554
|
}
|
|
118134
|
-
await new Promise2((
|
|
118135
|
-
next =
|
|
118555
|
+
await new Promise2((resolve42) => {
|
|
118556
|
+
next = resolve42;
|
|
118136
118557
|
});
|
|
118137
118558
|
}
|
|
118138
118559
|
} finally {
|
|
@@ -118390,7 +118811,7 @@ var require_promises = __commonJS({
|
|
|
118390
118811
|
var { finished } = require_end_of_stream2();
|
|
118391
118812
|
require_stream2();
|
|
118392
118813
|
function pipeline(...streams) {
|
|
118393
|
-
return new Promise2((
|
|
118814
|
+
return new Promise2((resolve42, reject2) => {
|
|
118394
118815
|
let signal;
|
|
118395
118816
|
let end;
|
|
118396
118817
|
const lastArg = streams[streams.length - 1];
|
|
@@ -118405,7 +118826,7 @@ var require_promises = __commonJS({
|
|
|
118405
118826
|
if (err) {
|
|
118406
118827
|
reject2(err);
|
|
118407
118828
|
} else {
|
|
118408
|
-
|
|
118829
|
+
resolve42(value);
|
|
118409
118830
|
}
|
|
118410
118831
|
},
|
|
118411
118832
|
{
|
|
@@ -123178,10 +123599,10 @@ var require_commonjs3 = __commonJS({
|
|
|
123178
123599
|
* Return a void Promise that resolves once the stream ends.
|
|
123179
123600
|
*/
|
|
123180
123601
|
async promise() {
|
|
123181
|
-
return new Promise((
|
|
123602
|
+
return new Promise((resolve42, reject2) => {
|
|
123182
123603
|
this.on(DESTROYED, () => reject2(new Error("stream destroyed")));
|
|
123183
123604
|
this.on("error", (er) => reject2(er));
|
|
123184
|
-
this.on("end", () =>
|
|
123605
|
+
this.on("end", () => resolve42());
|
|
123185
123606
|
});
|
|
123186
123607
|
}
|
|
123187
123608
|
/**
|
|
@@ -123205,7 +123626,7 @@ var require_commonjs3 = __commonJS({
|
|
|
123205
123626
|
return Promise.resolve({ done: false, value: res });
|
|
123206
123627
|
if (this[EOF])
|
|
123207
123628
|
return stop();
|
|
123208
|
-
let
|
|
123629
|
+
let resolve42;
|
|
123209
123630
|
let reject2;
|
|
123210
123631
|
const onerr = (er) => {
|
|
123211
123632
|
this.off("data", ondata);
|
|
@@ -123219,19 +123640,19 @@ var require_commonjs3 = __commonJS({
|
|
|
123219
123640
|
this.off("end", onend);
|
|
123220
123641
|
this.off(DESTROYED, ondestroy);
|
|
123221
123642
|
this.pause();
|
|
123222
|
-
|
|
123643
|
+
resolve42({ value, done: !!this[EOF] });
|
|
123223
123644
|
};
|
|
123224
123645
|
const onend = () => {
|
|
123225
123646
|
this.off("error", onerr);
|
|
123226
123647
|
this.off("data", ondata);
|
|
123227
123648
|
this.off(DESTROYED, ondestroy);
|
|
123228
123649
|
stop();
|
|
123229
|
-
|
|
123650
|
+
resolve42({ done: true, value: void 0 });
|
|
123230
123651
|
};
|
|
123231
123652
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
123232
123653
|
return new Promise((res2, rej) => {
|
|
123233
123654
|
reject2 = rej;
|
|
123234
|
-
|
|
123655
|
+
resolve42 = res2;
|
|
123235
123656
|
this.once(DESTROYED, ondestroy);
|
|
123236
123657
|
this.once("error", onerr);
|
|
123237
123658
|
this.once("end", onend);
|
|
@@ -124247,9 +124668,9 @@ var require_commonjs4 = __commonJS({
|
|
|
124247
124668
|
if (this.#asyncReaddirInFlight) {
|
|
124248
124669
|
await this.#asyncReaddirInFlight;
|
|
124249
124670
|
} else {
|
|
124250
|
-
let
|
|
124671
|
+
let resolve42 = () => {
|
|
124251
124672
|
};
|
|
124252
|
-
this.#asyncReaddirInFlight = new Promise((res) =>
|
|
124673
|
+
this.#asyncReaddirInFlight = new Promise((res) => resolve42 = res);
|
|
124253
124674
|
try {
|
|
124254
124675
|
for (const e of await this.#fs.promises.readdir(fullpath, {
|
|
124255
124676
|
withFileTypes: true
|
|
@@ -124262,7 +124683,7 @@ var require_commonjs4 = __commonJS({
|
|
|
124262
124683
|
children.provisional = 0;
|
|
124263
124684
|
}
|
|
124264
124685
|
this.#asyncReaddirInFlight = void 0;
|
|
124265
|
-
|
|
124686
|
+
resolve42();
|
|
124266
124687
|
}
|
|
124267
124688
|
return children.slice(0, children.provisional);
|
|
124268
124689
|
}
|
|
@@ -125129,7 +125550,7 @@ var require_pattern = __commonJS({
|
|
|
125129
125550
|
#isUNC;
|
|
125130
125551
|
#isAbsolute;
|
|
125131
125552
|
#followGlobstar = true;
|
|
125132
|
-
constructor(patternList, globList, index2,
|
|
125553
|
+
constructor(patternList, globList, index2, platform4) {
|
|
125133
125554
|
if (!isPatternList(patternList)) {
|
|
125134
125555
|
throw new TypeError("empty pattern list");
|
|
125135
125556
|
}
|
|
@@ -125146,7 +125567,7 @@ var require_pattern = __commonJS({
|
|
|
125146
125567
|
this.#patternList = patternList;
|
|
125147
125568
|
this.#globList = globList;
|
|
125148
125569
|
this.#index = index2;
|
|
125149
|
-
this.#platform =
|
|
125570
|
+
this.#platform = platform4;
|
|
125150
125571
|
if (this.#index === 0) {
|
|
125151
125572
|
if (this.isUNC()) {
|
|
125152
125573
|
const [p0, p1, p2, p3, ...prest] = this.#patternList;
|
|
@@ -125298,12 +125719,12 @@ var require_ignore = __commonJS({
|
|
|
125298
125719
|
absoluteChildren;
|
|
125299
125720
|
platform;
|
|
125300
125721
|
mmopts;
|
|
125301
|
-
constructor(ignored, { nobrace, nocase, noext, noglobstar, platform:
|
|
125722
|
+
constructor(ignored, { nobrace, nocase, noext, noglobstar, platform: platform4 = defaultPlatform }) {
|
|
125302
125723
|
this.relative = [];
|
|
125303
125724
|
this.absolute = [];
|
|
125304
125725
|
this.relativeChildren = [];
|
|
125305
125726
|
this.absoluteChildren = [];
|
|
125306
|
-
this.platform =
|
|
125727
|
+
this.platform = platform4;
|
|
125307
125728
|
this.mmopts = {
|
|
125308
125729
|
dot: true,
|
|
125309
125730
|
nobrace,
|
|
@@ -125311,7 +125732,7 @@ var require_ignore = __commonJS({
|
|
|
125311
125732
|
noext,
|
|
125312
125733
|
noglobstar,
|
|
125313
125734
|
optimizationLevel: 2,
|
|
125314
|
-
platform:
|
|
125735
|
+
platform: platform4,
|
|
125315
125736
|
nocomment: true,
|
|
125316
125737
|
nonegate: true
|
|
125317
125738
|
};
|
|
@@ -127035,11 +127456,11 @@ var require_core = __commonJS({
|
|
|
127035
127456
|
this._finalize();
|
|
127036
127457
|
}
|
|
127037
127458
|
var self2 = this;
|
|
127038
|
-
return new Promise(function(
|
|
127459
|
+
return new Promise(function(resolve42, reject2) {
|
|
127039
127460
|
var errored;
|
|
127040
127461
|
self2._module.on("end", function() {
|
|
127041
127462
|
if (!errored) {
|
|
127042
|
-
|
|
127463
|
+
resolve42();
|
|
127043
127464
|
}
|
|
127044
127465
|
});
|
|
127045
127466
|
self2._module.on("error", function(err) {
|
|
@@ -127533,8 +127954,8 @@ var require_zip_archive_entry = __commonJS({
|
|
|
127533
127954
|
}
|
|
127534
127955
|
this.name = name;
|
|
127535
127956
|
};
|
|
127536
|
-
ZipArchiveEntry.prototype.setPlatform = function(
|
|
127537
|
-
this.platform =
|
|
127957
|
+
ZipArchiveEntry.prototype.setPlatform = function(platform4) {
|
|
127958
|
+
this.platform = platform4;
|
|
127538
127959
|
};
|
|
127539
127960
|
ZipArchiveEntry.prototype.setSize = function(size) {
|
|
127540
127961
|
if (size < 0) {
|
|
@@ -129479,8 +129900,8 @@ var require_streamx = __commonJS({
|
|
|
129479
129900
|
return this;
|
|
129480
129901
|
},
|
|
129481
129902
|
next() {
|
|
129482
|
-
return new Promise(function(
|
|
129483
|
-
promiseResolve =
|
|
129903
|
+
return new Promise(function(resolve42, reject2) {
|
|
129904
|
+
promiseResolve = resolve42;
|
|
129484
129905
|
promiseReject = reject2;
|
|
129485
129906
|
const data = stream.read();
|
|
129486
129907
|
if (data !== null) ondata(data);
|
|
@@ -129510,11 +129931,11 @@ var require_streamx = __commonJS({
|
|
|
129510
129931
|
}
|
|
129511
129932
|
function destroy(err) {
|
|
129512
129933
|
stream.destroy(err);
|
|
129513
|
-
return new Promise((
|
|
129514
|
-
if (stream._duplexState & DESTROYED) return
|
|
129934
|
+
return new Promise((resolve42, reject2) => {
|
|
129935
|
+
if (stream._duplexState & DESTROYED) return resolve42({ value: void 0, done: true });
|
|
129515
129936
|
stream.once("close", function() {
|
|
129516
129937
|
if (err) reject2(err);
|
|
129517
|
-
else
|
|
129938
|
+
else resolve42({ value: void 0, done: true });
|
|
129518
129939
|
});
|
|
129519
129940
|
});
|
|
129520
129941
|
}
|
|
@@ -129558,8 +129979,8 @@ var require_streamx = __commonJS({
|
|
|
129558
129979
|
const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
|
|
129559
129980
|
if (writes === 0) return Promise.resolve(true);
|
|
129560
129981
|
if (state.drains === null) state.drains = [];
|
|
129561
|
-
return new Promise((
|
|
129562
|
-
state.drains.push({ writes, resolve:
|
|
129982
|
+
return new Promise((resolve42) => {
|
|
129983
|
+
state.drains.push({ writes, resolve: resolve42 });
|
|
129563
129984
|
});
|
|
129564
129985
|
}
|
|
129565
129986
|
write(data) {
|
|
@@ -129664,10 +130085,10 @@ var require_streamx = __commonJS({
|
|
|
129664
130085
|
cb(null);
|
|
129665
130086
|
}
|
|
129666
130087
|
function pipelinePromise(...streams) {
|
|
129667
|
-
return new Promise((
|
|
130088
|
+
return new Promise((resolve42, reject2) => {
|
|
129668
130089
|
return pipeline(...streams, (err) => {
|
|
129669
130090
|
if (err) return reject2(err);
|
|
129670
|
-
|
|
130091
|
+
resolve42();
|
|
129671
130092
|
});
|
|
129672
130093
|
});
|
|
129673
130094
|
}
|
|
@@ -130324,16 +130745,16 @@ var require_extract = __commonJS({
|
|
|
130324
130745
|
entryCallback = null;
|
|
130325
130746
|
cb(err);
|
|
130326
130747
|
}
|
|
130327
|
-
function onnext(
|
|
130748
|
+
function onnext(resolve42, reject2) {
|
|
130328
130749
|
if (error) {
|
|
130329
130750
|
return reject2(error);
|
|
130330
130751
|
}
|
|
130331
130752
|
if (entryStream) {
|
|
130332
|
-
|
|
130753
|
+
resolve42({ value: entryStream, done: false });
|
|
130333
130754
|
entryStream = null;
|
|
130334
130755
|
return;
|
|
130335
130756
|
}
|
|
130336
|
-
promiseResolve =
|
|
130757
|
+
promiseResolve = resolve42;
|
|
130337
130758
|
promiseReject = reject2;
|
|
130338
130759
|
consumeCallback(null);
|
|
130339
130760
|
if (extract._finished && promiseResolve) {
|
|
@@ -130361,11 +130782,11 @@ var require_extract = __commonJS({
|
|
|
130361
130782
|
function destroy(err) {
|
|
130362
130783
|
extract.destroy(err);
|
|
130363
130784
|
consumeCallback(err);
|
|
130364
|
-
return new Promise((
|
|
130365
|
-
if (extract.destroyed) return
|
|
130785
|
+
return new Promise((resolve42, reject2) => {
|
|
130786
|
+
if (extract.destroyed) return resolve42({ value: void 0, done: true });
|
|
130366
130787
|
extract.once("close", function() {
|
|
130367
130788
|
if (err) reject2(err);
|
|
130368
|
-
else
|
|
130789
|
+
else resolve42({ value: void 0, done: true });
|
|
130369
130790
|
});
|
|
130370
130791
|
});
|
|
130371
130792
|
}
|
|
@@ -133702,6 +134123,20 @@ var init_register_settings_sync_inbound_routes = __esm({
|
|
|
133702
134123
|
});
|
|
133703
134124
|
|
|
133704
134125
|
// ../dashboard/src/routes/register-agent-core-routes.ts
|
|
134126
|
+
function isCompatibleDefaultHeartbeatPath(path5, agent) {
|
|
134127
|
+
const trimmed = path5?.trim();
|
|
134128
|
+
if (!trimmed) {
|
|
134129
|
+
return false;
|
|
134130
|
+
}
|
|
134131
|
+
if (trimmed === getDefaultHeartbeatProcedurePath(agent.id, agent.name)) {
|
|
134132
|
+
return true;
|
|
134133
|
+
}
|
|
134134
|
+
if (trimmed === getDefaultHeartbeatProcedurePath(agent.id)) {
|
|
134135
|
+
return true;
|
|
134136
|
+
}
|
|
134137
|
+
const safeId = agent.id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
|
|
134138
|
+
return new RegExp(`^\\.fusion/agents/[^/]+-${safeId}/HEARTBEAT\\.md$`).test(trimmed);
|
|
134139
|
+
}
|
|
133705
134140
|
function registerAgentCoreListCreateRoutes(ctx, deps) {
|
|
133706
134141
|
const { router, getProjectContext: getProjectContext3, rethrowAsApiError: rethrowAsApiError8 } = ctx;
|
|
133707
134142
|
const { sanitizeAgentTaskLinks, validateAgentInstructionsPayload } = deps;
|
|
@@ -133831,7 +134266,7 @@ function registerAgentCoreListCreateRoutes(ctx, deps) {
|
|
|
133831
134266
|
bundleConfig: bundleConfig ?? void 0,
|
|
133832
134267
|
heartbeatProcedurePath: heartbeatProcedurePath ?? void 0
|
|
133833
134268
|
});
|
|
133834
|
-
const expectedDefaultPath = getDefaultHeartbeatProcedurePath(agent.id);
|
|
134269
|
+
const expectedDefaultPath = getDefaultHeartbeatProcedurePath(agent.id, agent.name);
|
|
133835
134270
|
if (agent.heartbeatProcedurePath === expectedDefaultPath) {
|
|
133836
134271
|
try {
|
|
133837
134272
|
await ensureDefaultHeartbeatProcedureFile(scopedStore.getRootDir(), expectedDefaultPath, HEARTBEAT_PROCEDURE);
|
|
@@ -134089,7 +134524,7 @@ function registerAgentCoreRoutes(ctx, deps) {
|
|
|
134089
134524
|
if (!existing) {
|
|
134090
134525
|
throw notFound(`agent ${req.params.id} not found`);
|
|
134091
134526
|
}
|
|
134092
|
-
const targetPath = getDefaultHeartbeatProcedurePath(
|
|
134527
|
+
const targetPath = isCompatibleDefaultHeartbeatPath(existing.heartbeatProcedurePath, existing) ? existing.heartbeatProcedurePath : getDefaultHeartbeatProcedurePath(existing.id, existing.name);
|
|
134093
134528
|
const filePath = await ensureDefaultHeartbeatProcedureFile(
|
|
134094
134529
|
scopedStore.getRootDir(),
|
|
134095
134530
|
targetPath,
|
|
@@ -137349,9 +137784,9 @@ function registerProxyRoutes(router, deps) {
|
|
|
137349
137784
|
if (req.rawBody && req.rawBody.length > 0) {
|
|
137350
137785
|
body = req.rawBody;
|
|
137351
137786
|
} else {
|
|
137352
|
-
await new Promise((
|
|
137787
|
+
await new Promise((resolve42, reject2) => {
|
|
137353
137788
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
137354
|
-
req.on("end",
|
|
137789
|
+
req.on("end", resolve42);
|
|
137355
137790
|
req.on("error", reject2);
|
|
137356
137791
|
});
|
|
137357
137792
|
if (chunks.length > 0) {
|
|
@@ -137482,6 +137917,7 @@ var init_register_model_routes = __esm({
|
|
|
137482
137917
|
let defaultProvider;
|
|
137483
137918
|
let defaultModelId;
|
|
137484
137919
|
let useClaudeCli = false;
|
|
137920
|
+
let useDroidCli = false;
|
|
137485
137921
|
if (store) {
|
|
137486
137922
|
try {
|
|
137487
137923
|
const globalStore = store.getGlobalSettingsStore();
|
|
@@ -137491,6 +137927,7 @@ var init_register_model_routes = __esm({
|
|
|
137491
137927
|
defaultProvider = globalSettings.defaultProvider;
|
|
137492
137928
|
defaultModelId = globalSettings.defaultModelId;
|
|
137493
137929
|
useClaudeCli = globalSettings.useClaudeCli === true;
|
|
137930
|
+
useDroidCli = globalSettings.useDroidCli === true;
|
|
137494
137931
|
} catch {
|
|
137495
137932
|
}
|
|
137496
137933
|
}
|
|
@@ -137516,6 +137953,9 @@ var init_register_model_routes = __esm({
|
|
|
137516
137953
|
if (!useClaudeCli) {
|
|
137517
137954
|
models = models.filter((m) => m.provider !== "pi-claude-cli");
|
|
137518
137955
|
}
|
|
137956
|
+
if (!useDroidCli) {
|
|
137957
|
+
models = models.filter((m) => m.provider !== "droid-cli");
|
|
137958
|
+
}
|
|
137519
137959
|
res.json({
|
|
137520
137960
|
models,
|
|
137521
137961
|
favoriteProviders,
|
|
@@ -137763,13 +138203,13 @@ function getHomeDir5() {
|
|
|
137763
138203
|
return process.env.HOME || process.env.USERPROFILE || os4.homedir();
|
|
137764
138204
|
}
|
|
137765
138205
|
function execFileAsync5(file, args, options) {
|
|
137766
|
-
return new Promise((
|
|
138206
|
+
return new Promise((resolve42, reject2) => {
|
|
137767
138207
|
child_process.execFile(file, args, options, (error, stdout, stderr) => {
|
|
137768
138208
|
if (error) {
|
|
137769
138209
|
reject2(error);
|
|
137770
138210
|
return;
|
|
137771
138211
|
}
|
|
137772
|
-
|
|
138212
|
+
resolve42({ stdout: String(stdout), stderr: String(stderr) });
|
|
137773
138213
|
});
|
|
137774
138214
|
});
|
|
137775
138215
|
}
|
|
@@ -137828,7 +138268,7 @@ function formatDuration(ms) {
|
|
|
137828
138268
|
return remHours > 0 ? `${days}d ${remHours}h` : `${days}d`;
|
|
137829
138269
|
}
|
|
137830
138270
|
function httpsRequest(url, options) {
|
|
137831
|
-
return new Promise((
|
|
138271
|
+
return new Promise((resolve42, reject2) => {
|
|
137832
138272
|
const parsed = new URL(url);
|
|
137833
138273
|
const req = https.request(
|
|
137834
138274
|
{
|
|
@@ -137848,7 +138288,7 @@ function httpsRequest(url, options) {
|
|
|
137848
138288
|
if (typeof v === "string") hdrs[k.toLowerCase()] = v;
|
|
137849
138289
|
else if (Array.isArray(v)) hdrs[k.toLowerCase()] = v.join(", ");
|
|
137850
138290
|
}
|
|
137851
|
-
|
|
138291
|
+
resolve42({
|
|
137852
138292
|
status: res.statusCode || 0,
|
|
137853
138293
|
headers: hdrs,
|
|
137854
138294
|
body: Buffer.concat(chunks).toString("utf-8")
|
|
@@ -138095,7 +138535,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
138095
138535
|
env: { ...process.env, TERM: "xterm-256color" }
|
|
138096
138536
|
};
|
|
138097
138537
|
if (isWindows) ptyOptions.useConpty = false;
|
|
138098
|
-
const output = await new Promise((
|
|
138538
|
+
const output = await new Promise((resolve42, reject2) => {
|
|
138099
138539
|
let buf = "";
|
|
138100
138540
|
let settled = false;
|
|
138101
138541
|
let sentCommand = false;
|
|
@@ -138111,7 +138551,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
138111
138551
|
}
|
|
138112
138552
|
const clean = _stripClaudeAnsi(buf);
|
|
138113
138553
|
if (clean.includes("Current session") || clean.includes("% left") || clean.includes("% used")) {
|
|
138114
|
-
|
|
138554
|
+
resolve42(buf);
|
|
138115
138555
|
} else {
|
|
138116
138556
|
reject2(new Error("Claude CLI timed out after 60s \u2014 got output but no usage data. Try running `claude /usage` manually."));
|
|
138117
138557
|
}
|
|
@@ -138162,7 +138602,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
138162
138602
|
ptyProcess.kill();
|
|
138163
138603
|
} catch {
|
|
138164
138604
|
}
|
|
138165
|
-
|
|
138605
|
+
resolve42(buf);
|
|
138166
138606
|
}
|
|
138167
138607
|
}, 2e3);
|
|
138168
138608
|
}
|
|
@@ -138173,7 +138613,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
138173
138613
|
if (settled) return;
|
|
138174
138614
|
settled = true;
|
|
138175
138615
|
clearTimeout(timeout2);
|
|
138176
|
-
|
|
138616
|
+
resolve42(buf);
|
|
138177
138617
|
});
|
|
138178
138618
|
});
|
|
138179
138619
|
const cleanOutput = _stripClaudeAnsi(output);
|
|
@@ -138841,9 +139281,9 @@ async function fetchGitHubCopilotUsage() {
|
|
|
138841
139281
|
return usage;
|
|
138842
139282
|
}
|
|
138843
139283
|
function withTimeout(providerPromise, providerName, timeoutMs = PROVIDER_FETCH_TIMEOUT_MS) {
|
|
138844
|
-
return new Promise((
|
|
139284
|
+
return new Promise((resolve42) => {
|
|
138845
139285
|
const timer = setTimeout(() => {
|
|
138846
|
-
|
|
139286
|
+
resolve42({
|
|
138847
139287
|
name: providerName,
|
|
138848
139288
|
icon: "\u23F1\uFE0F",
|
|
138849
139289
|
status: "error",
|
|
@@ -138853,10 +139293,10 @@ function withTimeout(providerPromise, providerName, timeoutMs = PROVIDER_FETCH_T
|
|
|
138853
139293
|
}, timeoutMs);
|
|
138854
139294
|
providerPromise.then((result) => {
|
|
138855
139295
|
clearTimeout(timer);
|
|
138856
|
-
|
|
139296
|
+
resolve42(result);
|
|
138857
139297
|
}).catch((err) => {
|
|
138858
139298
|
clearTimeout(timer);
|
|
138859
|
-
|
|
139299
|
+
resolve42({
|
|
138860
139300
|
name: providerName,
|
|
138861
139301
|
icon: "\u23F1\uFE0F",
|
|
138862
139302
|
status: "error",
|
|
@@ -138911,7 +139351,7 @@ var init_usage = __esm({
|
|
|
138911
139351
|
ANTHROPIC_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
138912
139352
|
ANTHROPIC_OAUTH_BETA = "oauth-2025-04-20";
|
|
138913
139353
|
CLAUDE_USAGE_USER_AGENT = "claude-code-fusion-dashboard";
|
|
138914
|
-
_sleep = (ms) => new Promise((
|
|
139354
|
+
_sleep = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
138915
139355
|
sleepFn = _sleep;
|
|
138916
139356
|
PROVIDER_FETCH_TIMEOUT_MS = 1e4;
|
|
138917
139357
|
CLAUDE_FETCH_TIMEOUT_MS = 75e3;
|
|
@@ -138943,7 +139383,7 @@ var init_register_usage_routes = __esm({
|
|
|
138943
139383
|
});
|
|
138944
139384
|
|
|
138945
139385
|
// ../dashboard/src/claude-cli-probe.ts
|
|
138946
|
-
import { spawn as
|
|
139386
|
+
import { spawn as spawn11 } from "node:child_process";
|
|
138947
139387
|
async function probeClaudeCli(options = {}) {
|
|
138948
139388
|
const startedAt = Date.now();
|
|
138949
139389
|
const timeoutMs = options.timeoutMs ?? PROBE_TIMEOUT_MS;
|
|
@@ -138953,7 +139393,7 @@ async function probeClaudeCli(options = {}) {
|
|
|
138953
139393
|
resolvePromise({ ...result, probeDurationMs: Date.now() - startedAt });
|
|
138954
139394
|
};
|
|
138955
139395
|
let settled = false;
|
|
138956
|
-
const child =
|
|
139396
|
+
const child = spawn11(binaryPath ?? "claude", ["--version"], {
|
|
138957
139397
|
stdio: ["ignore", "pipe", "pipe"]
|
|
138958
139398
|
});
|
|
138959
139399
|
const timer = setTimeout(() => {
|
|
@@ -139011,7 +139451,7 @@ async function probeClaudeCli(options = {}) {
|
|
|
139011
139451
|
async function tryResolveBinaryPath3(binary) {
|
|
139012
139452
|
return new Promise((resolvePromise) => {
|
|
139013
139453
|
const which = process.platform === "win32" ? "where" : "which";
|
|
139014
|
-
const child =
|
|
139454
|
+
const child = spawn11(which, [binary], { stdio: ["ignore", "pipe", "ignore"] });
|
|
139015
139455
|
let out = "";
|
|
139016
139456
|
child.stdout?.on("data", (chunk) => {
|
|
139017
139457
|
out += chunk.toString("utf-8");
|
|
@@ -139036,7 +139476,7 @@ var init_claude_cli_probe = __esm({
|
|
|
139036
139476
|
});
|
|
139037
139477
|
|
|
139038
139478
|
// ../dashboard/src/droid-cli-probe.ts
|
|
139039
|
-
import { spawn as
|
|
139479
|
+
import { spawn as spawn12 } from "node:child_process";
|
|
139040
139480
|
async function probeDroidCli(options = {}) {
|
|
139041
139481
|
const startedAt = Date.now();
|
|
139042
139482
|
const timeoutMs = options.timeoutMs ?? PROBE_TIMEOUT_MS2;
|
|
@@ -139046,7 +139486,7 @@ async function probeDroidCli(options = {}) {
|
|
|
139046
139486
|
resolvePromise({ ...result, probeDurationMs: Date.now() - startedAt });
|
|
139047
139487
|
};
|
|
139048
139488
|
let settled = false;
|
|
139049
|
-
const child =
|
|
139489
|
+
const child = spawn12(binaryPath ?? "droid", ["--version"], {
|
|
139050
139490
|
stdio: ["ignore", "pipe", "pipe"]
|
|
139051
139491
|
});
|
|
139052
139492
|
const timer = setTimeout(() => {
|
|
@@ -139104,7 +139544,7 @@ async function probeDroidCli(options = {}) {
|
|
|
139104
139544
|
async function tryResolveBinaryPath4(binary) {
|
|
139105
139545
|
return new Promise((resolvePromise) => {
|
|
139106
139546
|
const which = process.platform === "win32" ? "where" : "which";
|
|
139107
|
-
const child =
|
|
139547
|
+
const child = spawn12(which, [binary], { stdio: ["ignore", "pipe", "ignore"] });
|
|
139108
139548
|
let out = "";
|
|
139109
139549
|
child.stdout?.on("data", (chunk) => {
|
|
139110
139550
|
out += chunk.toString("utf-8");
|
|
@@ -139479,8 +139919,8 @@ var init_register_auth_routes = __esm({
|
|
|
139479
139919
|
loginInProgress.set(provider, abortController);
|
|
139480
139920
|
let authResolve;
|
|
139481
139921
|
let authReject;
|
|
139482
|
-
const authUrlPromise = new Promise((
|
|
139483
|
-
authResolve =
|
|
139922
|
+
const authUrlPromise = new Promise((resolve42, reject2) => {
|
|
139923
|
+
authResolve = resolve42;
|
|
139484
139924
|
authReject = reject2;
|
|
139485
139925
|
});
|
|
139486
139926
|
const loginPromise = storage.login(provider, {
|
|
@@ -139948,7 +140388,7 @@ function stripAnsi2(str) {
|
|
|
139948
140388
|
return str.replace(/\x1B\[[0-9;]*[mGKJHFABCDSTsu]/g, "");
|
|
139949
140389
|
}
|
|
139950
140390
|
async function mintAgentApiKeyViaCli(opts) {
|
|
139951
|
-
const { spawn:
|
|
140391
|
+
const { spawn: spawn19 } = await import("node:child_process");
|
|
139952
140392
|
const bin = opts.cliBinaryPath ?? "paperclipai";
|
|
139953
140393
|
const args = [
|
|
139954
140394
|
"agent",
|
|
@@ -139969,10 +140409,10 @@ async function mintAgentApiKeyViaCli(opts) {
|
|
|
139969
140409
|
args.push("--data-dir", opts.dataDir);
|
|
139970
140410
|
}
|
|
139971
140411
|
const timeoutMs = opts.cliTimeoutMs ?? 3e4;
|
|
139972
|
-
return new Promise((
|
|
140412
|
+
return new Promise((resolve42, reject2) => {
|
|
139973
140413
|
let child;
|
|
139974
140414
|
try {
|
|
139975
|
-
child =
|
|
140415
|
+
child = spawn19(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
139976
140416
|
} catch (err) {
|
|
139977
140417
|
const code = err.code;
|
|
139978
140418
|
if (code === "ENOENT") {
|
|
@@ -140043,7 +140483,7 @@ async function mintAgentApiKeyViaCli(opts) {
|
|
|
140043
140483
|
const apiBase = (typeof r.apiBase === "string" ? r.apiBase : void 0) ?? (typeof r.api_base === "string" ? r.api_base : void 0);
|
|
140044
140484
|
const agentId = (typeof r.agentId === "string" ? r.agentId : void 0) ?? (typeof r.id === "string" ? r.id : void 0);
|
|
140045
140485
|
const companyId = typeof r.companyId === "string" ? r.companyId : void 0;
|
|
140046
|
-
|
|
140486
|
+
resolve42({ apiKey, apiBase, agentId, companyId, raw: parsed });
|
|
140047
140487
|
});
|
|
140048
140488
|
});
|
|
140049
140489
|
}
|
|
@@ -140055,7 +140495,7 @@ function remapSpawnError(err, bin) {
|
|
|
140055
140495
|
return err instanceof Error ? err : new Error(String(err));
|
|
140056
140496
|
}
|
|
140057
140497
|
async function spawnPaperclipCliJson(args, opts) {
|
|
140058
|
-
const { spawn:
|
|
140498
|
+
const { spawn: spawn19 } = await import("node:child_process");
|
|
140059
140499
|
const bin = opts.cliBinaryPath ?? "paperclipai";
|
|
140060
140500
|
const fullArgs = [...args, "--json"];
|
|
140061
140501
|
if (opts.cliConfigPath) {
|
|
@@ -140063,10 +140503,10 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
140063
140503
|
}
|
|
140064
140504
|
const timeoutMs = opts.cliTimeoutMs ?? 15e3;
|
|
140065
140505
|
const label = ["paperclipai", ...args].join(" ");
|
|
140066
|
-
return new Promise((
|
|
140506
|
+
return new Promise((resolve42, reject2) => {
|
|
140067
140507
|
let child;
|
|
140068
140508
|
try {
|
|
140069
|
-
child =
|
|
140509
|
+
child = spawn19(bin, fullArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
140070
140510
|
} catch (err) {
|
|
140071
140511
|
reject2(remapSpawnError(err, bin));
|
|
140072
140512
|
return;
|
|
@@ -140109,7 +140549,7 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
140109
140549
|
return;
|
|
140110
140550
|
}
|
|
140111
140551
|
try {
|
|
140112
|
-
|
|
140552
|
+
resolve42(JSON.parse(cleaned));
|
|
140113
140553
|
} catch {
|
|
140114
140554
|
reject2(new Error(`${label} returned non-JSON output: ${cleaned.slice(0, 200)}`));
|
|
140115
140555
|
}
|
|
@@ -140238,7 +140678,7 @@ var init_paperclip_client = __esm({
|
|
|
140238
140678
|
// ../../plugins/fusion-plugin-paperclip-runtime/dist/runtime-adapter.js
|
|
140239
140679
|
import { randomUUID as randomUUID20 } from "node:crypto";
|
|
140240
140680
|
function sleep4(ms) {
|
|
140241
|
-
return new Promise((
|
|
140681
|
+
return new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
140242
140682
|
}
|
|
140243
140683
|
function asString2(value) {
|
|
140244
140684
|
return typeof value === "string" ? value : void 0;
|
|
@@ -140879,8 +141319,184 @@ var init_register_runtime_provider_routes = __esm({
|
|
|
140879
141319
|
}
|
|
140880
141320
|
});
|
|
140881
141321
|
|
|
141322
|
+
// ../dashboard/src/cli-package-version.ts
|
|
141323
|
+
import { existsSync as existsSync32, readFileSync as readFileSync10 } from "node:fs";
|
|
141324
|
+
import { dirname as dirname15, resolve as resolve23 } from "node:path";
|
|
141325
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
141326
|
+
function readCliPackageVersion(pkgPath) {
|
|
141327
|
+
if (!existsSync32(pkgPath)) {
|
|
141328
|
+
return null;
|
|
141329
|
+
}
|
|
141330
|
+
try {
|
|
141331
|
+
const parsed = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
141332
|
+
if (parsed.name === CLI_PACKAGE_NAME && typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
141333
|
+
return {
|
|
141334
|
+
packageJsonPath: pkgPath,
|
|
141335
|
+
version: parsed.version
|
|
141336
|
+
};
|
|
141337
|
+
}
|
|
141338
|
+
} catch {
|
|
141339
|
+
}
|
|
141340
|
+
return null;
|
|
141341
|
+
}
|
|
141342
|
+
function resolveCliPackageVersionInfo(startDir) {
|
|
141343
|
+
let currentDir = startDir;
|
|
141344
|
+
for (let i = 0; i < 8; i += 1) {
|
|
141345
|
+
const versionInfo = readCliPackageVersion(resolve23(currentDir, "package.json"));
|
|
141346
|
+
if (versionInfo) {
|
|
141347
|
+
return versionInfo;
|
|
141348
|
+
}
|
|
141349
|
+
const parentDir = resolve23(currentDir, "..");
|
|
141350
|
+
if (parentDir === currentDir) {
|
|
141351
|
+
break;
|
|
141352
|
+
}
|
|
141353
|
+
currentDir = parentDir;
|
|
141354
|
+
}
|
|
141355
|
+
currentDir = startDir;
|
|
141356
|
+
for (let i = 0; i < 8; i += 1) {
|
|
141357
|
+
const versionInfo = readCliPackageVersion(resolve23(currentDir, "..", "cli", "package.json"));
|
|
141358
|
+
if (versionInfo) {
|
|
141359
|
+
return versionInfo;
|
|
141360
|
+
}
|
|
141361
|
+
const parentDir = resolve23(currentDir, "..");
|
|
141362
|
+
if (parentDir === currentDir) {
|
|
141363
|
+
break;
|
|
141364
|
+
}
|
|
141365
|
+
currentDir = parentDir;
|
|
141366
|
+
}
|
|
141367
|
+
return null;
|
|
141368
|
+
}
|
|
141369
|
+
function getCliPackageVersion(importMetaUrl = import.meta.url) {
|
|
141370
|
+
const startDir = dirname15(fileURLToPath4(importMetaUrl));
|
|
141371
|
+
return resolveCliPackageVersionInfo(startDir)?.version ?? process.env.npm_package_version ?? "0.0.0";
|
|
141372
|
+
}
|
|
141373
|
+
var CLI_PACKAGE_NAME;
|
|
141374
|
+
var init_cli_package_version = __esm({
|
|
141375
|
+
"../dashboard/src/cli-package-version.ts"() {
|
|
141376
|
+
"use strict";
|
|
141377
|
+
CLI_PACKAGE_NAME = "@runfusion/fusion";
|
|
141378
|
+
}
|
|
141379
|
+
});
|
|
141380
|
+
|
|
141381
|
+
// ../dashboard/src/routes/register-fn-binary-routes.ts
|
|
141382
|
+
import { spawn as spawn13 } from "node:child_process";
|
|
141383
|
+
function buildStatusPayload(binary, expectedVersion) {
|
|
141384
|
+
let state = "missing";
|
|
141385
|
+
if (binary.installed) {
|
|
141386
|
+
state = binary.version && binary.version !== expectedVersion ? "version-mismatch" : "installed";
|
|
141387
|
+
}
|
|
141388
|
+
return {
|
|
141389
|
+
binary,
|
|
141390
|
+
expectedVersion,
|
|
141391
|
+
state,
|
|
141392
|
+
install: {
|
|
141393
|
+
npm: FN_INSTALL_NPM,
|
|
141394
|
+
curl: FN_INSTALL_CURL,
|
|
141395
|
+
package: FN_NPM_PACKAGE
|
|
141396
|
+
}
|
|
141397
|
+
};
|
|
141398
|
+
}
|
|
141399
|
+
function runNpmInstall() {
|
|
141400
|
+
const startedAt = Date.now();
|
|
141401
|
+
const command = FN_INSTALL_NPM;
|
|
141402
|
+
return new Promise((resolve42) => {
|
|
141403
|
+
let stdout = "";
|
|
141404
|
+
let stderr = "";
|
|
141405
|
+
let timedOut = false;
|
|
141406
|
+
const child = spawn13("npm", ["install", "-g", FN_NPM_PACKAGE], {
|
|
141407
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
141408
|
+
shell: false
|
|
141409
|
+
});
|
|
141410
|
+
const timer = setTimeout(() => {
|
|
141411
|
+
timedOut = true;
|
|
141412
|
+
try {
|
|
141413
|
+
child.kill("SIGKILL");
|
|
141414
|
+
} catch {
|
|
141415
|
+
}
|
|
141416
|
+
}, INSTALL_TIMEOUT_MS);
|
|
141417
|
+
const append = (target, chunk) => {
|
|
141418
|
+
const text = chunk.toString("utf8");
|
|
141419
|
+
if (target === "stdout") {
|
|
141420
|
+
if (stdout.length < MAX_OUTPUT_BYTES2) {
|
|
141421
|
+
stdout += text.slice(0, MAX_OUTPUT_BYTES2 - stdout.length);
|
|
141422
|
+
}
|
|
141423
|
+
} else {
|
|
141424
|
+
if (stderr.length < MAX_OUTPUT_BYTES2) {
|
|
141425
|
+
stderr += text.slice(0, MAX_OUTPUT_BYTES2 - stderr.length);
|
|
141426
|
+
}
|
|
141427
|
+
}
|
|
141428
|
+
};
|
|
141429
|
+
child.stdout?.on("data", (c) => append("stdout", c));
|
|
141430
|
+
child.stderr?.on("data", (c) => append("stderr", c));
|
|
141431
|
+
child.on("error", (err) => {
|
|
141432
|
+
clearTimeout(timer);
|
|
141433
|
+
resolve42({
|
|
141434
|
+
success: false,
|
|
141435
|
+
exitCode: null,
|
|
141436
|
+
stdout,
|
|
141437
|
+
stderr: stderr || err.message,
|
|
141438
|
+
command,
|
|
141439
|
+
durationMs: Date.now() - startedAt
|
|
141440
|
+
});
|
|
141441
|
+
});
|
|
141442
|
+
child.on("close", (exitCode) => {
|
|
141443
|
+
clearTimeout(timer);
|
|
141444
|
+
const combined = `${stdout}
|
|
141445
|
+
${stderr}`;
|
|
141446
|
+
const eaccesHit = /EACCES|permission denied|Operation not permitted/i.test(combined);
|
|
141447
|
+
const success = exitCode === 0 && !timedOut;
|
|
141448
|
+
resolve42({
|
|
141449
|
+
success,
|
|
141450
|
+
exitCode,
|
|
141451
|
+
stdout,
|
|
141452
|
+
stderr: timedOut ? `${stderr}
|
|
141453
|
+
[install timed out after ${INSTALL_TIMEOUT_MS / 1e3}s]` : stderr,
|
|
141454
|
+
command,
|
|
141455
|
+
durationMs: Date.now() - startedAt,
|
|
141456
|
+
permissionsHint: !success && eaccesHit ? "npm reported a permissions error. On macOS/Linux this usually means npm's global prefix needs `sudo` or a fix to your npm prefix (https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)." : void 0
|
|
141457
|
+
});
|
|
141458
|
+
});
|
|
141459
|
+
});
|
|
141460
|
+
}
|
|
141461
|
+
var INSTALL_TIMEOUT_MS, MAX_OUTPUT_BYTES2, registerFnBinaryRoutes;
|
|
141462
|
+
var init_register_fn_binary_routes = __esm({
|
|
141463
|
+
"../dashboard/src/routes/register-fn-binary-routes.ts"() {
|
|
141464
|
+
"use strict";
|
|
141465
|
+
init_src();
|
|
141466
|
+
init_api_error();
|
|
141467
|
+
init_cli_package_version();
|
|
141468
|
+
INSTALL_TIMEOUT_MS = 18e4;
|
|
141469
|
+
MAX_OUTPUT_BYTES2 = 64 * 1024;
|
|
141470
|
+
registerFnBinaryRoutes = (ctx) => {
|
|
141471
|
+
const { router, rethrowAsApiError: rethrowAsApiError8 } = ctx;
|
|
141472
|
+
router.get("/system/fn-binary/status", async (_req, res) => {
|
|
141473
|
+
try {
|
|
141474
|
+
const binary = await detectFnBinary();
|
|
141475
|
+
const expectedVersion = getCliPackageVersion();
|
|
141476
|
+
res.json(buildStatusPayload(binary, expectedVersion));
|
|
141477
|
+
} catch (err) {
|
|
141478
|
+
if (err instanceof ApiError) throw err;
|
|
141479
|
+
rethrowAsApiError8(err);
|
|
141480
|
+
}
|
|
141481
|
+
});
|
|
141482
|
+
router.post("/system/fn-binary/install", async (_req, res) => {
|
|
141483
|
+
try {
|
|
141484
|
+
const installResult = await runNpmInstall();
|
|
141485
|
+
const binary = await detectFnBinary();
|
|
141486
|
+
const expectedVersion = getCliPackageVersion();
|
|
141487
|
+
const status = buildStatusPayload(binary, expectedVersion);
|
|
141488
|
+
res.json({ ...status, installResult });
|
|
141489
|
+
} catch (err) {
|
|
141490
|
+
if (err instanceof ApiError) throw err;
|
|
141491
|
+
rethrowAsApiError8(err);
|
|
141492
|
+
}
|
|
141493
|
+
});
|
|
141494
|
+
};
|
|
141495
|
+
}
|
|
141496
|
+
});
|
|
141497
|
+
|
|
140882
141498
|
// ../dashboard/src/update-check.ts
|
|
140883
|
-
import { readFileSync as
|
|
141499
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
140884
141500
|
import { mkdir as mkdir17, rm as rm5, writeFile as writeFile15 } from "node:fs/promises";
|
|
140885
141501
|
import { join as join47 } from "node:path";
|
|
140886
141502
|
function ttlForFrequency(frequency) {
|
|
@@ -140920,7 +141536,7 @@ function isValidResult(value) {
|
|
|
140920
141536
|
}
|
|
140921
141537
|
function readCachedUpdateCheck(fusionDir) {
|
|
140922
141538
|
try {
|
|
140923
|
-
const raw =
|
|
141539
|
+
const raw = readFileSync11(getCachePath(fusionDir), "utf-8");
|
|
140924
141540
|
const parsed = JSON.parse(raw);
|
|
140925
141541
|
return isValidResult(parsed) ? parsed : null;
|
|
140926
141542
|
} catch {
|
|
@@ -140987,65 +141603,6 @@ var init_update_check = __esm({
|
|
|
140987
141603
|
}
|
|
140988
141604
|
});
|
|
140989
141605
|
|
|
140990
|
-
// ../dashboard/src/cli-package-version.ts
|
|
140991
|
-
import { existsSync as existsSync32, readFileSync as readFileSync11 } from "node:fs";
|
|
140992
|
-
import { dirname as dirname15, resolve as resolve23 } from "node:path";
|
|
140993
|
-
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
140994
|
-
function readCliPackageVersion(pkgPath) {
|
|
140995
|
-
if (!existsSync32(pkgPath)) {
|
|
140996
|
-
return null;
|
|
140997
|
-
}
|
|
140998
|
-
try {
|
|
140999
|
-
const parsed = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
141000
|
-
if (parsed.name === CLI_PACKAGE_NAME && typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
141001
|
-
return {
|
|
141002
|
-
packageJsonPath: pkgPath,
|
|
141003
|
-
version: parsed.version
|
|
141004
|
-
};
|
|
141005
|
-
}
|
|
141006
|
-
} catch {
|
|
141007
|
-
}
|
|
141008
|
-
return null;
|
|
141009
|
-
}
|
|
141010
|
-
function resolveCliPackageVersionInfo(startDir) {
|
|
141011
|
-
let currentDir = startDir;
|
|
141012
|
-
for (let i = 0; i < 8; i += 1) {
|
|
141013
|
-
const versionInfo = readCliPackageVersion(resolve23(currentDir, "package.json"));
|
|
141014
|
-
if (versionInfo) {
|
|
141015
|
-
return versionInfo;
|
|
141016
|
-
}
|
|
141017
|
-
const parentDir = resolve23(currentDir, "..");
|
|
141018
|
-
if (parentDir === currentDir) {
|
|
141019
|
-
break;
|
|
141020
|
-
}
|
|
141021
|
-
currentDir = parentDir;
|
|
141022
|
-
}
|
|
141023
|
-
currentDir = startDir;
|
|
141024
|
-
for (let i = 0; i < 8; i += 1) {
|
|
141025
|
-
const versionInfo = readCliPackageVersion(resolve23(currentDir, "..", "cli", "package.json"));
|
|
141026
|
-
if (versionInfo) {
|
|
141027
|
-
return versionInfo;
|
|
141028
|
-
}
|
|
141029
|
-
const parentDir = resolve23(currentDir, "..");
|
|
141030
|
-
if (parentDir === currentDir) {
|
|
141031
|
-
break;
|
|
141032
|
-
}
|
|
141033
|
-
currentDir = parentDir;
|
|
141034
|
-
}
|
|
141035
|
-
return null;
|
|
141036
|
-
}
|
|
141037
|
-
function getCliPackageVersion(importMetaUrl = import.meta.url) {
|
|
141038
|
-
const startDir = dirname15(fileURLToPath4(importMetaUrl));
|
|
141039
|
-
return resolveCliPackageVersionInfo(startDir)?.version ?? process.env.npm_package_version ?? "0.0.0";
|
|
141040
|
-
}
|
|
141041
|
-
var CLI_PACKAGE_NAME;
|
|
141042
|
-
var init_cli_package_version = __esm({
|
|
141043
|
-
"../dashboard/src/cli-package-version.ts"() {
|
|
141044
|
-
"use strict";
|
|
141045
|
-
CLI_PACKAGE_NAME = "@runfusion/fusion";
|
|
141046
|
-
}
|
|
141047
|
-
});
|
|
141048
|
-
|
|
141049
141606
|
// ../dashboard/src/routes/register-update-check-routes.ts
|
|
141050
141607
|
var registerUpdateCheckRoutes;
|
|
141051
141608
|
var init_register_update_check_routes = __esm({
|
|
@@ -145824,7 +146381,7 @@ function detectPortFromLogLine(line) {
|
|
|
145824
146381
|
return detectViteLine(cleanLine) ?? detectNextLine(cleanLine) ?? detectStorybookLine(cleanLine) ?? detectAngularLine(cleanLine) ?? detectGenericUrl(cleanLine) ?? detectGenericPortLine(cleanLine);
|
|
145825
146382
|
}
|
|
145826
146383
|
function probePort(host, port, timeoutMs) {
|
|
145827
|
-
return new Promise((
|
|
146384
|
+
return new Promise((resolve42) => {
|
|
145828
146385
|
let settled = false;
|
|
145829
146386
|
const socket = createConnection({ host, port });
|
|
145830
146387
|
const settle = (isOpen) => {
|
|
@@ -145838,7 +146395,7 @@ function probePort(host, port, timeoutMs) {
|
|
|
145838
146395
|
} else {
|
|
145839
146396
|
socket.destroy();
|
|
145840
146397
|
}
|
|
145841
|
-
|
|
146398
|
+
resolve42(isOpen);
|
|
145842
146399
|
};
|
|
145843
146400
|
socket.setTimeout(timeoutMs);
|
|
145844
146401
|
socket.once("connect", () => settle(true));
|
|
@@ -145879,7 +146436,7 @@ var init_dev_server_port_detect = __esm({
|
|
|
145879
146436
|
|
|
145880
146437
|
// ../dashboard/src/dev-server-process.ts
|
|
145881
146438
|
import { EventEmitter as EventEmitter34 } from "node:events";
|
|
145882
|
-
import { spawn as
|
|
146439
|
+
import { spawn as spawn14 } from "node:child_process";
|
|
145883
146440
|
function killManagedProcess2(child, signal) {
|
|
145884
146441
|
if (typeof child.pid !== "number") {
|
|
145885
146442
|
return;
|
|
@@ -145958,15 +146515,15 @@ var init_dev_server_process = __esm({
|
|
|
145958
146515
|
detectedUrl: void 0,
|
|
145959
146516
|
detectedPort: void 0
|
|
145960
146517
|
});
|
|
145961
|
-
const child =
|
|
146518
|
+
const child = spawn14(safeCommand, [], {
|
|
145962
146519
|
cwd: safeCwd,
|
|
145963
146520
|
detached: process.platform !== "win32",
|
|
145964
146521
|
shell: true,
|
|
145965
146522
|
stdio: ["pipe", "pipe", "pipe"]
|
|
145966
146523
|
});
|
|
145967
146524
|
this.childProcess = child;
|
|
145968
|
-
this.closePromise = new Promise((
|
|
145969
|
-
this.resolveClosePromise =
|
|
146525
|
+
this.closePromise = new Promise((resolve42) => {
|
|
146526
|
+
this.resolveClosePromise = resolve42;
|
|
145970
146527
|
});
|
|
145971
146528
|
const runningState = await this.store.updateState({
|
|
145972
146529
|
pid: child.pid,
|
|
@@ -147592,6 +148149,7 @@ function createApiRoutes(store, options) {
|
|
|
147592
148149
|
registerCustomProviderRoutes(routeContext);
|
|
147593
148150
|
registerAuthRoutes(routeContext);
|
|
147594
148151
|
registerRuntimeProviderRoutes(routeContext);
|
|
148152
|
+
registerFnBinaryRoutes(routeContext);
|
|
147595
148153
|
router.post("/ai/refine-text", async (req, res) => {
|
|
147596
148154
|
try {
|
|
147597
148155
|
const { text, type } = req.body;
|
|
@@ -149182,15 +149740,15 @@ Description: ${step.description}`
|
|
|
149182
149740
|
return;
|
|
149183
149741
|
}
|
|
149184
149742
|
}
|
|
149185
|
-
const { resolve:
|
|
149743
|
+
const { resolve: resolve42, dirname: dirname30, join: join70 } = await import("node:path");
|
|
149186
149744
|
const { readdir: readdir12, stat: stat12 } = await import("node:fs/promises");
|
|
149187
149745
|
const rawPath = req.query.path || process.env.HOME || process.env.USERPROFILE || "/";
|
|
149188
149746
|
const showHidden = req.query.showHidden === "true";
|
|
149189
|
-
const resolvedPath =
|
|
149747
|
+
const resolvedPath = resolve42(rawPath);
|
|
149190
149748
|
if (rawPath.includes("..")) {
|
|
149191
149749
|
throw badRequest("Path must not contain '..' traversal");
|
|
149192
149750
|
}
|
|
149193
|
-
if (resolvedPath !==
|
|
149751
|
+
if (resolvedPath !== resolve42(resolvedPath)) {
|
|
149194
149752
|
throw badRequest("Path must be absolute");
|
|
149195
149753
|
}
|
|
149196
149754
|
let pathStat;
|
|
@@ -149217,7 +149775,7 @@ Description: ${step.description}`
|
|
|
149217
149775
|
entries.push({ name: entry.name, path: entryPath, hasChildren });
|
|
149218
149776
|
}
|
|
149219
149777
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
149220
|
-
const parentPath =
|
|
149778
|
+
const parentPath = dirname30(resolvedPath) === resolvedPath ? null : dirname30(resolvedPath);
|
|
149221
149779
|
res.json({ currentPath: resolvedPath, parentPath, entries });
|
|
149222
149780
|
} catch (err) {
|
|
149223
149781
|
if (err instanceof ApiError) {
|
|
@@ -149727,6 +150285,7 @@ var init_routes = __esm({
|
|
|
149727
150285
|
init_register_usage_routes();
|
|
149728
150286
|
init_register_auth_routes();
|
|
149729
150287
|
init_register_runtime_provider_routes();
|
|
150288
|
+
init_register_fn_binary_routes();
|
|
149730
150289
|
init_register_update_check_routes();
|
|
149731
150290
|
init_register_integrated_routers();
|
|
149732
150291
|
init_resolve_diff_base();
|
|
@@ -156484,7 +157043,7 @@ var init_task_lifecycle = __esm({
|
|
|
156484
157043
|
// src/commands/port-prompt.ts
|
|
156485
157044
|
import { createInterface } from "node:readline";
|
|
156486
157045
|
function promptForPort(defaultPort = 4040, input = process.stdin) {
|
|
156487
|
-
return new Promise((
|
|
157046
|
+
return new Promise((resolve42, reject2) => {
|
|
156488
157047
|
const rl = createInterface({
|
|
156489
157048
|
input,
|
|
156490
157049
|
output: process.stdout
|
|
@@ -156501,7 +157060,7 @@ function promptForPort(defaultPort = 4040, input = process.stdin) {
|
|
|
156501
157060
|
if (trimmed === "") {
|
|
156502
157061
|
process.removeListener("SIGINT", sigintHandler);
|
|
156503
157062
|
rl.close();
|
|
156504
|
-
|
|
157063
|
+
resolve42(defaultPort);
|
|
156505
157064
|
return;
|
|
156506
157065
|
}
|
|
156507
157066
|
const port = parseInt(trimmed, 10);
|
|
@@ -156517,7 +157076,7 @@ function promptForPort(defaultPort = 4040, input = process.stdin) {
|
|
|
156517
157076
|
}
|
|
156518
157077
|
process.removeListener("SIGINT", sigintHandler);
|
|
156519
157078
|
rl.close();
|
|
156520
|
-
|
|
157079
|
+
resolve42(port);
|
|
156521
157080
|
});
|
|
156522
157081
|
};
|
|
156523
157082
|
ask();
|
|
@@ -157268,13 +157827,109 @@ var init_claude_cli_extension = __esm({
|
|
|
157268
157827
|
}
|
|
157269
157828
|
});
|
|
157270
157829
|
|
|
157830
|
+
// src/commands/droid-cli-extension.ts
|
|
157831
|
+
import { existsSync as existsSync40, readFileSync as readFileSync18 } from "node:fs";
|
|
157832
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
157833
|
+
import { dirname as dirname24, resolve as resolve30 } from "node:path";
|
|
157834
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
157835
|
+
function resolveDroidCliExtensionFromModuleUrl(moduleUrl) {
|
|
157836
|
+
let pkgJsonPath;
|
|
157837
|
+
const here = dirname24(fileURLToPath8(moduleUrl));
|
|
157838
|
+
for (const rel of ["droid-cli", "../droid-cli", "../../droid-cli"]) {
|
|
157839
|
+
const candidate = resolve30(here, rel, "package.json");
|
|
157840
|
+
if (existsSync40(candidate)) {
|
|
157841
|
+
pkgJsonPath = candidate;
|
|
157842
|
+
break;
|
|
157843
|
+
}
|
|
157844
|
+
}
|
|
157845
|
+
if (!pkgJsonPath) {
|
|
157846
|
+
try {
|
|
157847
|
+
pkgJsonPath = require_2.resolve("@fusion/droid-cli/package.json");
|
|
157848
|
+
} catch {
|
|
157849
|
+
return { status: "not-installed" };
|
|
157850
|
+
}
|
|
157851
|
+
}
|
|
157852
|
+
let pkgJson;
|
|
157853
|
+
try {
|
|
157854
|
+
pkgJson = JSON.parse(readFileSync18(pkgJsonPath, "utf-8"));
|
|
157855
|
+
} catch (err) {
|
|
157856
|
+
return {
|
|
157857
|
+
status: "error",
|
|
157858
|
+
reason: `Failed to read @fusion/droid-cli package.json: ${err instanceof Error ? err.message : String(err)}`
|
|
157859
|
+
};
|
|
157860
|
+
}
|
|
157861
|
+
const extensions = pkgJson.pi?.extensions;
|
|
157862
|
+
if (!Array.isArray(extensions) || extensions.length === 0) {
|
|
157863
|
+
return {
|
|
157864
|
+
status: "missing-entry",
|
|
157865
|
+
reason: "@fusion/droid-cli package.json has no pi.extensions array"
|
|
157866
|
+
};
|
|
157867
|
+
}
|
|
157868
|
+
const rawEntry = extensions[0];
|
|
157869
|
+
if (typeof rawEntry !== "string" || rawEntry.length === 0) {
|
|
157870
|
+
return {
|
|
157871
|
+
status: "missing-entry",
|
|
157872
|
+
reason: "@fusion/droid-cli pi.extensions[0] is not a valid path string"
|
|
157873
|
+
};
|
|
157874
|
+
}
|
|
157875
|
+
const entryPath = resolve30(dirname24(pkgJsonPath), rawEntry);
|
|
157876
|
+
if (!existsSync40(entryPath)) {
|
|
157877
|
+
return {
|
|
157878
|
+
status: "missing-entry",
|
|
157879
|
+
reason: `@fusion/droid-cli extension file not found at ${entryPath}`
|
|
157880
|
+
};
|
|
157881
|
+
}
|
|
157882
|
+
return {
|
|
157883
|
+
status: "ok",
|
|
157884
|
+
path: entryPath,
|
|
157885
|
+
packageVersion: pkgJson.version ?? "unknown"
|
|
157886
|
+
};
|
|
157887
|
+
}
|
|
157888
|
+
function resolveDroidCliExtension() {
|
|
157889
|
+
return resolveDroidCliExtensionFromModuleUrl(import.meta.url);
|
|
157890
|
+
}
|
|
157891
|
+
function resolveDroidCliExtensionPaths(globalSettings) {
|
|
157892
|
+
const enabled = globalSettings?.useDroidCli === true;
|
|
157893
|
+
if (!enabled) {
|
|
157894
|
+
return { paths: [], resolution: null };
|
|
157895
|
+
}
|
|
157896
|
+
const resolution = resolveDroidCliExtension();
|
|
157897
|
+
switch (resolution.status) {
|
|
157898
|
+
case "ok":
|
|
157899
|
+
return { paths: [resolution.path], resolution };
|
|
157900
|
+
case "not-installed":
|
|
157901
|
+
return {
|
|
157902
|
+
paths: [],
|
|
157903
|
+
resolution,
|
|
157904
|
+
warning: "useDroidCli is on but @fusion/droid-cli is not installed in node_modules. Run `pnpm install`."
|
|
157905
|
+
};
|
|
157906
|
+
case "missing-entry":
|
|
157907
|
+
case "error":
|
|
157908
|
+
return { paths: [], resolution, warning: resolution.reason };
|
|
157909
|
+
}
|
|
157910
|
+
}
|
|
157911
|
+
function setCachedDroidCliResolution(resolution) {
|
|
157912
|
+
cachedResolution2 = resolution;
|
|
157913
|
+
}
|
|
157914
|
+
function getCachedDroidCliResolution() {
|
|
157915
|
+
return cachedResolution2;
|
|
157916
|
+
}
|
|
157917
|
+
var require_2, cachedResolution2;
|
|
157918
|
+
var init_droid_cli_extension = __esm({
|
|
157919
|
+
"src/commands/droid-cli-extension.ts"() {
|
|
157920
|
+
"use strict";
|
|
157921
|
+
require_2 = createRequire5(import.meta.url);
|
|
157922
|
+
cachedResolution2 = null;
|
|
157923
|
+
}
|
|
157924
|
+
});
|
|
157925
|
+
|
|
157271
157926
|
// src/update-cache.ts
|
|
157272
|
-
import { readFileSync as
|
|
157927
|
+
import { readFileSync as readFileSync19 } from "node:fs";
|
|
157273
157928
|
import { join as join56 } from "node:path";
|
|
157274
157929
|
function getCachedUpdateStatus(currentVersion) {
|
|
157275
157930
|
try {
|
|
157276
157931
|
const cachePath = join56(resolveGlobalDir(), "update-check.json");
|
|
157277
|
-
const raw =
|
|
157932
|
+
const raw = readFileSync19(cachePath, "utf-8");
|
|
157278
157933
|
const parsed = JSON.parse(raw);
|
|
157279
157934
|
if (parsed.updateAvailable === true && typeof parsed.latestVersion === "string" && parsed.latestVersion.length > 0 && typeof parsed.currentVersion === "string" && parsed.currentVersion.length > 0) {
|
|
157280
157935
|
if (typeof currentVersion === "string" && currentVersion.length > 0 && parsed.currentVersion !== currentVersion) {
|
|
@@ -157305,17 +157960,17 @@ var init_update_cache = __esm({
|
|
|
157305
157960
|
});
|
|
157306
157961
|
|
|
157307
157962
|
// src/commands/self-extension.ts
|
|
157308
|
-
import { existsSync as
|
|
157309
|
-
import { dirname as
|
|
157310
|
-
import { fileURLToPath as
|
|
157963
|
+
import { existsSync as existsSync41, readFileSync as readFileSync20 } from "node:fs";
|
|
157964
|
+
import { dirname as dirname25, resolve as resolve31 } from "node:path";
|
|
157965
|
+
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
157311
157966
|
function resolveSelfExtension() {
|
|
157312
|
-
const here =
|
|
157967
|
+
const here = dirname25(fileURLToPath9(import.meta.url));
|
|
157313
157968
|
let pkgDir;
|
|
157314
157969
|
let cur = here;
|
|
157315
157970
|
for (let i = 0; i < 5; i++) {
|
|
157316
|
-
if (
|
|
157971
|
+
if (existsSync41(resolve31(cur, "package.json"))) {
|
|
157317
157972
|
try {
|
|
157318
|
-
const parsed = JSON.parse(
|
|
157973
|
+
const parsed = JSON.parse(readFileSync20(resolve31(cur, "package.json"), "utf-8"));
|
|
157319
157974
|
if (parsed.name === "@runfusion/fusion") {
|
|
157320
157975
|
pkgDir = cur;
|
|
157321
157976
|
break;
|
|
@@ -157323,7 +157978,7 @@ function resolveSelfExtension() {
|
|
|
157323
157978
|
} catch {
|
|
157324
157979
|
}
|
|
157325
157980
|
}
|
|
157326
|
-
const parent2 =
|
|
157981
|
+
const parent2 = resolve31(cur, "..");
|
|
157327
157982
|
if (parent2 === cur) break;
|
|
157328
157983
|
cur = parent2;
|
|
157329
157984
|
}
|
|
@@ -157332,12 +157987,12 @@ function resolveSelfExtension() {
|
|
|
157332
157987
|
}
|
|
157333
157988
|
let pkgJson;
|
|
157334
157989
|
try {
|
|
157335
|
-
pkgJson = JSON.parse(
|
|
157990
|
+
pkgJson = JSON.parse(readFileSync20(resolve31(pkgDir, "package.json"), "utf-8"));
|
|
157336
157991
|
} catch (err) {
|
|
157337
157992
|
return { status: "missing", reason: `Failed to read @runfusion/fusion package.json: ${err instanceof Error ? err.message : String(err)}` };
|
|
157338
157993
|
}
|
|
157339
|
-
const srcEntry =
|
|
157340
|
-
if (
|
|
157994
|
+
const srcEntry = resolve31(pkgDir, "src", "extension.ts");
|
|
157995
|
+
if (existsSync41(srcEntry)) {
|
|
157341
157996
|
return { status: "ok", path: srcEntry, packageVersion: pkgJson.version ?? "unknown" };
|
|
157342
157997
|
}
|
|
157343
157998
|
const extensions = pkgJson.pi?.extensions;
|
|
@@ -157348,8 +158003,8 @@ function resolveSelfExtension() {
|
|
|
157348
158003
|
if (typeof rawEntry !== "string" || rawEntry.length === 0) {
|
|
157349
158004
|
return { status: "missing", reason: "@runfusion/fusion pi.extensions[0] is not a valid path string" };
|
|
157350
158005
|
}
|
|
157351
|
-
const entryPath =
|
|
157352
|
-
if (!
|
|
158006
|
+
const entryPath = resolve31(pkgDir, rawEntry);
|
|
158007
|
+
if (!existsSync41(entryPath)) {
|
|
157353
158008
|
return { status: "missing", reason: `@runfusion/fusion extension file not found at ${entryPath}` };
|
|
157354
158009
|
}
|
|
157355
158010
|
return { status: "ok", path: entryPath, packageVersion: pkgJson.version ?? "unknown" };
|
|
@@ -157561,7 +158216,7 @@ var init_use_projects = __esm({
|
|
|
157561
158216
|
});
|
|
157562
158217
|
|
|
157563
158218
|
// src/commands/dashboard-tui/utils.ts
|
|
157564
|
-
import { spawn as
|
|
158219
|
+
import { spawn as spawn15 } from "node:child_process";
|
|
157565
158220
|
function isTTYAvailable() {
|
|
157566
158221
|
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
157567
158222
|
}
|
|
@@ -157572,14 +158227,14 @@ async function copyToClipboard(text) {
|
|
|
157572
158227
|
{ cmd: "xsel", args: ["--clipboard", "--input"] }
|
|
157573
158228
|
];
|
|
157574
158229
|
for (const { cmd, args } of candidates) {
|
|
157575
|
-
const ok = await new Promise((
|
|
158230
|
+
const ok = await new Promise((resolve42) => {
|
|
157576
158231
|
try {
|
|
157577
|
-
const child =
|
|
157578
|
-
child.once("error", () =>
|
|
157579
|
-
child.once("close", (code) =>
|
|
158232
|
+
const child = spawn15(cmd, args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
158233
|
+
child.once("error", () => resolve42(false));
|
|
158234
|
+
child.once("close", (code) => resolve42(code === 0));
|
|
157580
158235
|
child.stdin.end(text);
|
|
157581
158236
|
} catch {
|
|
157582
|
-
|
|
158237
|
+
resolve42(false);
|
|
157583
158238
|
}
|
|
157584
158239
|
});
|
|
157585
158240
|
if (ok) return true;
|
|
@@ -157601,7 +158256,7 @@ import { useState as useState2, useSyncExternalStore, useCallback as useCallback
|
|
|
157601
158256
|
import { Box, Text, useInput, useApp, useStdout } from "ink";
|
|
157602
158257
|
import Spinner from "ink-spinner";
|
|
157603
158258
|
import TextInput from "ink-text-input";
|
|
157604
|
-
import { spawn as
|
|
158259
|
+
import { spawn as spawn16 } from "node:child_process";
|
|
157605
158260
|
import { appendFileSync } from "node:fs";
|
|
157606
158261
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
157607
158262
|
function tuiDebug(tag, data) {
|
|
@@ -157627,7 +158282,7 @@ function openInBrowser(url) {
|
|
|
157627
158282
|
args = [url];
|
|
157628
158283
|
}
|
|
157629
158284
|
try {
|
|
157630
|
-
const child =
|
|
158285
|
+
const child = spawn16(cmd, args, { detached: true, stdio: "ignore" });
|
|
157631
158286
|
child.unref();
|
|
157632
158287
|
} catch {
|
|
157633
158288
|
}
|
|
@@ -161640,8 +162295,8 @@ async function resolveCachedStartupUpdateStatus(importMetaUrl) {
|
|
|
161640
162295
|
try {
|
|
161641
162296
|
const updateCheckEnabled = await Promise.race([
|
|
161642
162297
|
isUpdateCheckEnabled(),
|
|
161643
|
-
new Promise((
|
|
161644
|
-
setTimeout(() =>
|
|
162298
|
+
new Promise((resolve42) => {
|
|
162299
|
+
setTimeout(() => resolve42(false), 3e3);
|
|
161645
162300
|
})
|
|
161646
162301
|
]);
|
|
161647
162302
|
if (!updateCheckEnabled) {
|
|
@@ -162361,6 +163016,23 @@ async function runDashboard(port, opts = {}) {
|
|
|
162361
163016
|
return [];
|
|
162362
163017
|
}
|
|
162363
163018
|
})();
|
|
163019
|
+
const droidCliPaths = await (async () => {
|
|
163020
|
+
try {
|
|
163021
|
+
const globalSettings = await store.getGlobalSettingsStore().getSettings();
|
|
163022
|
+
const result = resolveDroidCliExtensionPaths(globalSettings);
|
|
163023
|
+
setCachedDroidCliResolution(result.resolution);
|
|
163024
|
+
if (result.warning) {
|
|
163025
|
+
console.warn(`[extensions] droid-cli: ${result.warning}`);
|
|
163026
|
+
}
|
|
163027
|
+
return result.paths;
|
|
163028
|
+
} catch (err) {
|
|
163029
|
+
console.warn(
|
|
163030
|
+
`[extensions] Unable to evaluate useDroidCli setting: ${err instanceof Error ? err.message : String(err)}`
|
|
163031
|
+
);
|
|
163032
|
+
setCachedDroidCliResolution(null);
|
|
163033
|
+
return [];
|
|
163034
|
+
}
|
|
163035
|
+
})();
|
|
162364
163036
|
const selfExtension = resolveSelfExtension();
|
|
162365
163037
|
const selfExtensionPaths = selfExtension.status === "ok" ? [selfExtension.path] : [];
|
|
162366
163038
|
if (selfExtension.status !== "ok") {
|
|
@@ -162372,7 +163044,8 @@ async function runDashboard(port, opts = {}) {
|
|
|
162372
163044
|
...selfExtensionPaths,
|
|
162373
163045
|
...getEnabledPiExtensionPaths(cwd),
|
|
162374
163046
|
...packageExtensionPaths,
|
|
162375
|
-
...claudeCliPaths
|
|
163047
|
+
...claudeCliPaths,
|
|
163048
|
+
...droidCliPaths
|
|
162376
163049
|
],
|
|
162377
163050
|
cwd,
|
|
162378
163051
|
join57(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
@@ -162569,6 +163242,17 @@ async function runDashboard(port, opts = {}) {
|
|
|
162569
163242
|
}
|
|
162570
163243
|
return { status: r.status, reason: r.reason };
|
|
162571
163244
|
},
|
|
163245
|
+
getDroidCliExtensionStatus: () => {
|
|
163246
|
+
const r = getCachedDroidCliResolution();
|
|
163247
|
+
if (!r) return null;
|
|
163248
|
+
if (r.status === "ok") {
|
|
163249
|
+
return { status: "ok", path: r.path, packageVersion: r.packageVersion };
|
|
163250
|
+
}
|
|
163251
|
+
if (r.status === "not-installed") {
|
|
163252
|
+
return { status: "not-installed" };
|
|
163253
|
+
}
|
|
163254
|
+
return { status: r.status, reason: r.reason };
|
|
163255
|
+
},
|
|
162572
163256
|
onUseClaudeCliToggled: (_prev, next) => {
|
|
162573
163257
|
if (!next) return;
|
|
162574
163258
|
void (async () => {
|
|
@@ -162586,6 +163270,11 @@ async function runDashboard(port, opts = {}) {
|
|
|
162586
163270
|
}
|
|
162587
163271
|
})();
|
|
162588
163272
|
},
|
|
163273
|
+
onUseDroidCliToggled: (_prev, next) => {
|
|
163274
|
+
if (next) {
|
|
163275
|
+
logSink.log("Droid CLI enabled \u2014 restart required for full effect", "extensions");
|
|
163276
|
+
}
|
|
163277
|
+
},
|
|
162589
163278
|
skillsAdapter,
|
|
162590
163279
|
https: loadTlsCredentialsFromEnv(),
|
|
162591
163280
|
daemon: dashboardAuthToken ? { token: dashboardAuthToken } : void 0,
|
|
@@ -162752,6 +163441,17 @@ async function runDashboard(port, opts = {}) {
|
|
|
162752
163441
|
}
|
|
162753
163442
|
return { status: r.status, reason: r.reason };
|
|
162754
163443
|
},
|
|
163444
|
+
getDroidCliExtensionStatus: () => {
|
|
163445
|
+
const r = getCachedDroidCliResolution();
|
|
163446
|
+
if (!r) return null;
|
|
163447
|
+
if (r.status === "ok") {
|
|
163448
|
+
return { status: "ok", path: r.path, packageVersion: r.packageVersion };
|
|
163449
|
+
}
|
|
163450
|
+
if (r.status === "not-installed") {
|
|
163451
|
+
return { status: "not-installed" };
|
|
163452
|
+
}
|
|
163453
|
+
return { status: r.status, reason: r.reason };
|
|
163454
|
+
},
|
|
162755
163455
|
onUseClaudeCliToggled: (_prev, next) => {
|
|
162756
163456
|
if (!next) return;
|
|
162757
163457
|
void (async () => {
|
|
@@ -162769,6 +163469,11 @@ async function runDashboard(port, opts = {}) {
|
|
|
162769
163469
|
}
|
|
162770
163470
|
})();
|
|
162771
163471
|
},
|
|
163472
|
+
onUseDroidCliToggled: (_prev, next) => {
|
|
163473
|
+
if (next) {
|
|
163474
|
+
logSink.log("Droid CLI enabled \u2014 restart required for full effect", "extensions");
|
|
163475
|
+
}
|
|
163476
|
+
},
|
|
162772
163477
|
skillsAdapter,
|
|
162773
163478
|
https: loadTlsCredentialsFromEnv(),
|
|
162774
163479
|
daemon: dashboardAuthToken ? { token: dashboardAuthToken } : void 0,
|
|
@@ -163345,6 +164050,7 @@ var init_dashboard = __esm({
|
|
|
163345
164050
|
init_project_context();
|
|
163346
164051
|
init_claude_skills_runner();
|
|
163347
164052
|
init_claude_cli_extension();
|
|
164053
|
+
init_droid_cli_extension();
|
|
163348
164054
|
init_update_cache();
|
|
163349
164055
|
init_self_extension();
|
|
163350
164056
|
init_custom_provider_registry();
|
|
@@ -164122,6 +164828,23 @@ async function runServe(port, opts = {}) {
|
|
|
164122
164828
|
return [];
|
|
164123
164829
|
}
|
|
164124
164830
|
})();
|
|
164831
|
+
const droidCliPaths = await (async () => {
|
|
164832
|
+
try {
|
|
164833
|
+
const globalSettings = await store.getGlobalSettingsStore().getSettings();
|
|
164834
|
+
const result = resolveDroidCliExtensionPaths(globalSettings);
|
|
164835
|
+
setCachedDroidCliResolution(result.resolution);
|
|
164836
|
+
if (result.warning) {
|
|
164837
|
+
console.warn(`[extensions] droid-cli: ${result.warning}`);
|
|
164838
|
+
}
|
|
164839
|
+
return result.paths;
|
|
164840
|
+
} catch (err) {
|
|
164841
|
+
console.warn(
|
|
164842
|
+
`[extensions] Unable to evaluate useDroidCli setting: ${err instanceof Error ? err.message : String(err)}`
|
|
164843
|
+
);
|
|
164844
|
+
setCachedDroidCliResolution(null);
|
|
164845
|
+
return [];
|
|
164846
|
+
}
|
|
164847
|
+
})();
|
|
164125
164848
|
const selfExtension = resolveSelfExtension();
|
|
164126
164849
|
const selfExtensionPaths = selfExtension.status === "ok" ? [selfExtension.path] : [];
|
|
164127
164850
|
if (selfExtension.status !== "ok") {
|
|
@@ -164133,7 +164856,8 @@ async function runServe(port, opts = {}) {
|
|
|
164133
164856
|
...selfExtensionPaths,
|
|
164134
164857
|
...getEnabledPiExtensionPaths(cwd),
|
|
164135
164858
|
...packageExtensionPaths,
|
|
164136
|
-
...claudeCliPaths
|
|
164859
|
+
...claudeCliPaths,
|
|
164860
|
+
...droidCliPaths
|
|
164137
164861
|
],
|
|
164138
164862
|
cwd,
|
|
164139
164863
|
join58(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
@@ -164292,6 +165016,17 @@ async function runServe(port, opts = {}) {
|
|
|
164292
165016
|
}
|
|
164293
165017
|
return { status: r.status, reason: r.reason };
|
|
164294
165018
|
},
|
|
165019
|
+
getDroidCliExtensionStatus: () => {
|
|
165020
|
+
const r = getCachedDroidCliResolution();
|
|
165021
|
+
if (!r) return null;
|
|
165022
|
+
if (r.status === "ok") {
|
|
165023
|
+
return { status: "ok", path: r.path, packageVersion: r.packageVersion };
|
|
165024
|
+
}
|
|
165025
|
+
if (r.status === "not-installed") {
|
|
165026
|
+
return { status: "not-installed" };
|
|
165027
|
+
}
|
|
165028
|
+
return { status: r.status, reason: r.reason };
|
|
165029
|
+
},
|
|
164295
165030
|
onUseClaudeCliToggled: (_prev, next) => {
|
|
164296
165031
|
if (!next) return;
|
|
164297
165032
|
void (async () => {
|
|
@@ -164308,14 +165043,19 @@ async function runServe(port, opts = {}) {
|
|
|
164308
165043
|
}
|
|
164309
165044
|
})();
|
|
164310
165045
|
},
|
|
165046
|
+
onUseDroidCliToggled: (_prev, next) => {
|
|
165047
|
+
if (next) {
|
|
165048
|
+
console.log("[extensions] Droid CLI enabled \u2014 restart required for full effect");
|
|
165049
|
+
}
|
|
165050
|
+
},
|
|
164311
165051
|
headless: true,
|
|
164312
165052
|
skillsAdapter,
|
|
164313
165053
|
daemon: daemonToken ? { token: daemonToken } : void 0,
|
|
164314
165054
|
https: loadTlsCredentialsFromEnv()
|
|
164315
165055
|
});
|
|
164316
165056
|
const server = app.listen(selectedPort, selectedHost);
|
|
164317
|
-
await new Promise((
|
|
164318
|
-
server.once("listening",
|
|
165057
|
+
await new Promise((resolve42, reject2) => {
|
|
165058
|
+
server.once("listening", resolve42);
|
|
164319
165059
|
server.once("error", reject2);
|
|
164320
165060
|
});
|
|
164321
165061
|
const actualPort = server.address().port;
|
|
@@ -164459,6 +165199,7 @@ var init_serve = __esm({
|
|
|
164459
165199
|
init_project_context();
|
|
164460
165200
|
init_claude_skills_runner();
|
|
164461
165201
|
init_claude_cli_extension();
|
|
165202
|
+
init_droid_cli_extension();
|
|
164462
165203
|
init_self_extension();
|
|
164463
165204
|
init_custom_provider_registry();
|
|
164464
165205
|
DIAGNOSTIC_INTERVAL_MS2 = 30 * 60 * 1e3;
|
|
@@ -164730,6 +165471,23 @@ async function runDaemon(opts = {}) {
|
|
|
164730
165471
|
return [];
|
|
164731
165472
|
}
|
|
164732
165473
|
})();
|
|
165474
|
+
const droidCliPaths = await (async () => {
|
|
165475
|
+
try {
|
|
165476
|
+
const globalSettings = await store.getGlobalSettingsStore().getSettings();
|
|
165477
|
+
const result = resolveDroidCliExtensionPaths(globalSettings);
|
|
165478
|
+
setCachedDroidCliResolution(result.resolution);
|
|
165479
|
+
if (result.warning) {
|
|
165480
|
+
console.warn(`[extensions] droid-cli: ${result.warning}`);
|
|
165481
|
+
}
|
|
165482
|
+
return result.paths;
|
|
165483
|
+
} catch (err) {
|
|
165484
|
+
console.warn(
|
|
165485
|
+
`[extensions] Unable to evaluate useDroidCli setting: ${err instanceof Error ? err.message : String(err)}`
|
|
165486
|
+
);
|
|
165487
|
+
setCachedDroidCliResolution(null);
|
|
165488
|
+
return [];
|
|
165489
|
+
}
|
|
165490
|
+
})();
|
|
164733
165491
|
const selfExtension = resolveSelfExtension();
|
|
164734
165492
|
const selfExtensionPaths = selfExtension.status === "ok" ? [selfExtension.path] : [];
|
|
164735
165493
|
if (selfExtension.status !== "ok") {
|
|
@@ -164741,7 +165499,7 @@ async function runDaemon(opts = {}) {
|
|
|
164741
165499
|
claudeCliPaths[0] ?? null
|
|
164742
165500
|
);
|
|
164743
165501
|
const extensionsResult = await discoverAndLoadExtensions4(
|
|
164744
|
-
reconciledExtensionPaths,
|
|
165502
|
+
[...reconciledExtensionPaths, ...droidCliPaths],
|
|
164745
165503
|
cwd,
|
|
164746
165504
|
join59(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
164747
165505
|
);
|
|
@@ -164812,6 +165570,17 @@ async function runDaemon(opts = {}) {
|
|
|
164812
165570
|
}
|
|
164813
165571
|
return { status: r.status, reason: r.reason };
|
|
164814
165572
|
},
|
|
165573
|
+
getDroidCliExtensionStatus: () => {
|
|
165574
|
+
const r = getCachedDroidCliResolution();
|
|
165575
|
+
if (!r) return null;
|
|
165576
|
+
if (r.status === "ok") {
|
|
165577
|
+
return { status: "ok", path: r.path, packageVersion: r.packageVersion };
|
|
165578
|
+
}
|
|
165579
|
+
if (r.status === "not-installed") {
|
|
165580
|
+
return { status: "not-installed" };
|
|
165581
|
+
}
|
|
165582
|
+
return { status: r.status, reason: r.reason };
|
|
165583
|
+
},
|
|
164815
165584
|
onUseClaudeCliToggled: (_prev, next) => {
|
|
164816
165585
|
if (!next) return;
|
|
164817
165586
|
void (async () => {
|
|
@@ -164828,14 +165597,19 @@ async function runDaemon(opts = {}) {
|
|
|
164828
165597
|
}
|
|
164829
165598
|
})();
|
|
164830
165599
|
},
|
|
165600
|
+
onUseDroidCliToggled: (_prev, next) => {
|
|
165601
|
+
if (next) {
|
|
165602
|
+
console.log("[extensions] Droid CLI enabled \u2014 restart required for full effect");
|
|
165603
|
+
}
|
|
165604
|
+
},
|
|
164831
165605
|
headless: true,
|
|
164832
165606
|
daemon: { token: daemonToken },
|
|
164833
165607
|
skillsAdapter,
|
|
164834
165608
|
https: loadTlsCredentialsFromEnv()
|
|
164835
165609
|
});
|
|
164836
165610
|
const server = app.listen(selectedPort, selectedHost);
|
|
164837
|
-
await new Promise((
|
|
164838
|
-
server.once("listening",
|
|
165611
|
+
await new Promise((resolve42, reject2) => {
|
|
165612
|
+
server.once("listening", resolve42);
|
|
164839
165613
|
server.once("error", reject2);
|
|
164840
165614
|
});
|
|
164841
165615
|
const actualPort = server.address().port;
|
|
@@ -164929,6 +165703,7 @@ var init_daemon = __esm({
|
|
|
164929
165703
|
init_provider_settings();
|
|
164930
165704
|
init_claude_skills_runner();
|
|
164931
165705
|
init_claude_cli_extension();
|
|
165706
|
+
init_droid_cli_extension();
|
|
164932
165707
|
init_self_extension();
|
|
164933
165708
|
init_provider_auth();
|
|
164934
165709
|
init_auth_paths2();
|
|
@@ -164944,13 +165719,13 @@ var desktop_exports = {};
|
|
|
164944
165719
|
__export(desktop_exports, {
|
|
164945
165720
|
runDesktop: () => runDesktop
|
|
164946
165721
|
});
|
|
164947
|
-
import { spawn as
|
|
165722
|
+
import { spawn as spawn17 } from "node:child_process";
|
|
164948
165723
|
import { once as once2 } from "node:events";
|
|
164949
165724
|
import { join as join60 } from "node:path";
|
|
164950
|
-
import { createRequire as
|
|
165725
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
164951
165726
|
function runCommand(command, args, cwd) {
|
|
164952
|
-
return new Promise((
|
|
164953
|
-
const child =
|
|
165727
|
+
return new Promise((resolve42, reject2) => {
|
|
165728
|
+
const child = spawn17(command, args, {
|
|
164954
165729
|
cwd,
|
|
164955
165730
|
stdio: "inherit",
|
|
164956
165731
|
env: process.env
|
|
@@ -164958,7 +165733,7 @@ function runCommand(command, args, cwd) {
|
|
|
164958
165733
|
child.on("error", (error) => reject2(error));
|
|
164959
165734
|
child.on("exit", (code) => {
|
|
164960
165735
|
if (code === 0) {
|
|
164961
|
-
|
|
165736
|
+
resolve42();
|
|
164962
165737
|
return;
|
|
164963
165738
|
}
|
|
164964
165739
|
reject2(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
@@ -165001,8 +165776,8 @@ async function startDashboardRuntime(rootDir, paused) {
|
|
|
165001
165776
|
};
|
|
165002
165777
|
}
|
|
165003
165778
|
async function closeDashboardRuntime(runtime) {
|
|
165004
|
-
await new Promise((
|
|
165005
|
-
runtime.server.close(() =>
|
|
165779
|
+
await new Promise((resolve42) => {
|
|
165780
|
+
runtime.server.close(() => resolve42());
|
|
165006
165781
|
});
|
|
165007
165782
|
runtime.store.close();
|
|
165008
165783
|
}
|
|
@@ -165035,7 +165810,7 @@ async function runDesktop(options = {}) {
|
|
|
165035
165810
|
electronEnv.FUSION_DASHBOARD_URL = process.env.FUSION_DASHBOARD_URL ?? "http://localhost:5173";
|
|
165036
165811
|
electronEnv.NODE_ENV = "development";
|
|
165037
165812
|
}
|
|
165038
|
-
const electronProcess =
|
|
165813
|
+
const electronProcess = spawn17(electronBinary, electronArgs, {
|
|
165039
165814
|
cwd: rootDir,
|
|
165040
165815
|
stdio: "inherit",
|
|
165041
165816
|
env: electronEnv
|
|
@@ -165074,7 +165849,7 @@ var init_desktop = __esm({
|
|
|
165074
165849
|
"use strict";
|
|
165075
165850
|
init_src();
|
|
165076
165851
|
init_src4();
|
|
165077
|
-
require3 =
|
|
165852
|
+
require3 = createRequire6(import.meta.url);
|
|
165078
165853
|
}
|
|
165079
165854
|
});
|
|
165080
165855
|
|
|
@@ -165110,7 +165885,7 @@ __export(task_exports, {
|
|
|
165110
165885
|
runTaskUpdate: () => runTaskUpdate
|
|
165111
165886
|
});
|
|
165112
165887
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
165113
|
-
import { watchFile, unwatchFile, statSync as statSync6, existsSync as
|
|
165888
|
+
import { watchFile, unwatchFile, statSync as statSync6, existsSync as existsSync42, readFileSync as readFileSync21 } from "node:fs";
|
|
165114
165889
|
import { basename as basename17, join as join61 } from "node:path";
|
|
165115
165890
|
function getGitHubIssueUrl(sourceMetadata) {
|
|
165116
165891
|
if (!sourceMetadata || typeof sourceMetadata !== "object") return void 0;
|
|
@@ -165275,9 +166050,9 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName,
|
|
|
165275
166050
|
console.log(` Path: .fusion/tasks/${task.id}/`);
|
|
165276
166051
|
if (attachFiles && attachFiles.length > 0) {
|
|
165277
166052
|
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
165278
|
-
const { basename: basename22, extname: extname3, resolve:
|
|
166053
|
+
const { basename: basename22, extname: extname3, resolve: resolve42 } = await import("node:path");
|
|
165279
166054
|
for (const filePath of attachFiles) {
|
|
165280
|
-
const resolvedPath =
|
|
166055
|
+
const resolvedPath = resolve42(filePath);
|
|
165281
166056
|
const filename = basename22(resolvedPath);
|
|
165282
166057
|
const ext = extname3(filename).toLowerCase();
|
|
165283
166058
|
const mimeType = MIME_TYPES[ext];
|
|
@@ -165412,7 +166187,7 @@ async function runTaskLogs(id, options = {}, projectName) {
|
|
|
165412
166187
|
if (options.follow) {
|
|
165413
166188
|
const projectPath = projectContext?.projectPath ?? process.cwd();
|
|
165414
166189
|
const logPath = join61(projectPath, ".fusion", "tasks", id, "agent.log");
|
|
165415
|
-
if (!
|
|
166190
|
+
if (!existsSync42(logPath)) {
|
|
165416
166191
|
console.log(`
|
|
165417
166192
|
Waiting for log file to be created...`);
|
|
165418
166193
|
}
|
|
@@ -165441,7 +166216,7 @@ async function runTaskLogs(id, options = {}, projectName) {
|
|
|
165441
166216
|
lastPosition = 0;
|
|
165442
166217
|
}
|
|
165443
166218
|
if (stats.size > lastPosition) {
|
|
165444
|
-
const content =
|
|
166219
|
+
const content = readFileSync21(logPath, "utf-8");
|
|
165445
166220
|
const lines = content.slice(lastPosition).split("\n");
|
|
165446
166221
|
for (const line of lines) {
|
|
165447
166222
|
if (!line.trim()) continue;
|
|
@@ -165575,8 +166350,8 @@ async function runTaskMerge(id, projectName) {
|
|
|
165575
166350
|
async function runTaskAttach(id, filePath, projectName) {
|
|
165576
166351
|
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
165577
166352
|
const { basename: basename22, extname: extname3 } = await import("node:path");
|
|
165578
|
-
const { resolve:
|
|
165579
|
-
const resolvedPath =
|
|
166353
|
+
const { resolve: resolve42 } = await import("node:path");
|
|
166354
|
+
const resolvedPath = resolve42(filePath);
|
|
165580
166355
|
const filename = basename22(resolvedPath);
|
|
165581
166356
|
const ext = extname3(filename).toLowerCase();
|
|
165582
166357
|
const mimeType = MIME_TYPES[ext];
|
|
@@ -166115,12 +166890,12 @@ async function promptText(question) {
|
|
|
166115
166890
|
console.log(" (Enter your response. Type DONE on its own line when finished):\n");
|
|
166116
166891
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
166117
166892
|
const lines = [];
|
|
166118
|
-
return new Promise((
|
|
166893
|
+
return new Promise((resolve42) => {
|
|
166119
166894
|
const askLine = () => {
|
|
166120
166895
|
rl.question(" ").then((line) => {
|
|
166121
166896
|
if (line.trim() === "DONE") {
|
|
166122
166897
|
rl.close();
|
|
166123
|
-
|
|
166898
|
+
resolve42(lines.join("\n"));
|
|
166124
166899
|
} else {
|
|
166125
166900
|
lines.push(line);
|
|
166126
166901
|
askLine();
|
|
@@ -166285,7 +167060,7 @@ async function runTaskPlan(initialPlanArg, yesFlag = false, projectName) {
|
|
|
166285
167060
|
} catch (err) {
|
|
166286
167061
|
clearThinking();
|
|
166287
167062
|
if (err instanceof RateLimitError2) {
|
|
166288
|
-
console.error("\n Rate limit exceeded. Maximum
|
|
167063
|
+
console.error("\n Rate limit exceeded. Maximum 1000 planning sessions per hour.\n");
|
|
166289
167064
|
process.exit(1);
|
|
166290
167065
|
}
|
|
166291
167066
|
console.error(`
|
|
@@ -166689,7 +167464,7 @@ __export(settings_export_exports, {
|
|
|
166689
167464
|
runSettingsExport: () => runSettingsExport
|
|
166690
167465
|
});
|
|
166691
167466
|
import { writeFile as writeFile18 } from "node:fs/promises";
|
|
166692
|
-
import { resolve as
|
|
167467
|
+
import { resolve as resolve32, join as join62 } from "node:path";
|
|
166693
167468
|
async function runSettingsExport(options = {}) {
|
|
166694
167469
|
const scope = options.scope ?? "both";
|
|
166695
167470
|
const project = options.projectName ? await resolveProject(options.projectName) : void 0;
|
|
@@ -166700,7 +167475,7 @@ async function runSettingsExport(options = {}) {
|
|
|
166700
167475
|
const exportData = await exportSettings(store, { scope });
|
|
166701
167476
|
let targetPath;
|
|
166702
167477
|
if (outputPath) {
|
|
166703
|
-
targetPath =
|
|
167478
|
+
targetPath = resolve32(outputPath);
|
|
166704
167479
|
} else {
|
|
166705
167480
|
const filename = generateExportFilename();
|
|
166706
167481
|
targetPath = join62(process.cwd(), filename);
|
|
@@ -166749,8 +167524,8 @@ var settings_import_exports = {};
|
|
|
166749
167524
|
__export(settings_import_exports, {
|
|
166750
167525
|
runSettingsImport: () => runSettingsImport
|
|
166751
167526
|
});
|
|
166752
|
-
import { existsSync as
|
|
166753
|
-
import { resolve as
|
|
167527
|
+
import { existsSync as existsSync43 } from "node:fs";
|
|
167528
|
+
import { resolve as resolve33 } from "node:path";
|
|
166754
167529
|
async function runSettingsImport(filePath, options = {}) {
|
|
166755
167530
|
const scope = options.scope ?? "both";
|
|
166756
167531
|
const project = options.projectName ? await resolveProject(options.projectName) : void 0;
|
|
@@ -166759,8 +167534,8 @@ async function runSettingsImport(filePath, options = {}) {
|
|
|
166759
167534
|
const merge = options.merge ?? true;
|
|
166760
167535
|
const skipConfirm = options.yes ?? false;
|
|
166761
167536
|
try {
|
|
166762
|
-
const resolvedPath =
|
|
166763
|
-
if (!
|
|
167537
|
+
const resolvedPath = resolve33(filePath);
|
|
167538
|
+
if (!existsSync43(resolvedPath)) {
|
|
166764
167539
|
console.error(`Error: File not found: ${filePath}`);
|
|
166765
167540
|
process.exit(1);
|
|
166766
167541
|
}
|
|
@@ -167233,8 +168008,8 @@ var init_backup2 = __esm({
|
|
|
167233
168008
|
});
|
|
167234
168009
|
|
|
167235
168010
|
// src/project-resolver.ts
|
|
167236
|
-
import { existsSync as
|
|
167237
|
-
import { basename as basename18, dirname as
|
|
168011
|
+
import { existsSync as existsSync44, statSync as statSync7 } from "node:fs";
|
|
168012
|
+
import { basename as basename18, dirname as dirname26, resolve as resolve34, normalize as normalize5 } from "node:path";
|
|
167238
168013
|
import { createInterface as createInterface5 } from "node:readline/promises";
|
|
167239
168014
|
async function getCentralCore() {
|
|
167240
168015
|
if (!centralCoreInstance) {
|
|
@@ -167251,13 +168026,13 @@ async function getProjectManager() {
|
|
|
167251
168026
|
return projectManagerInstance;
|
|
167252
168027
|
}
|
|
167253
168028
|
function findKbDir(startPath) {
|
|
167254
|
-
let current =
|
|
168029
|
+
let current = resolve34(startPath);
|
|
167255
168030
|
for (let i = 0; i < 100; i++) {
|
|
167256
|
-
const dbPath =
|
|
168031
|
+
const dbPath = resolve34(current, ".fusion", "fusion.db");
|
|
167257
168032
|
if (isValidSqliteDatabaseFile(dbPath)) {
|
|
167258
168033
|
return current;
|
|
167259
168034
|
}
|
|
167260
|
-
const parent2 =
|
|
168035
|
+
const parent2 = dirname26(current);
|
|
167261
168036
|
if (parent2 === current) {
|
|
167262
168037
|
break;
|
|
167263
168038
|
}
|
|
@@ -167309,7 +168084,7 @@ async function resolveProject2(options = {}) {
|
|
|
167309
168084
|
{ searchedName: options.project, availableProjects: projects.map((p) => p.name) }
|
|
167310
168085
|
);
|
|
167311
168086
|
}
|
|
167312
|
-
if (!
|
|
168087
|
+
if (!existsSync44(match.path)) {
|
|
167313
168088
|
throw new ProjectResolutionError(
|
|
167314
168089
|
`Project "${match.name}" is registered but the directory no longer exists: ${match.path}
|
|
167315
168090
|
|
|
@@ -167320,14 +168095,14 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
|
|
|
167320
168095
|
}
|
|
167321
168096
|
return createResolvedProject(match);
|
|
167322
168097
|
}
|
|
167323
|
-
const cwd = options.cwd ?
|
|
168098
|
+
const cwd = options.cwd ? resolve34(options.cwd) : process.cwd();
|
|
167324
168099
|
const fusionDir = findKbDir(cwd);
|
|
167325
168100
|
if (fusionDir) {
|
|
167326
168101
|
const allProjects2 = await central.listProjects();
|
|
167327
168102
|
const normalizedKbDir = normalize5(fusionDir);
|
|
167328
168103
|
const match = allProjects2.find((p) => normalize5(p.path) === normalizedKbDir);
|
|
167329
168104
|
if (match) {
|
|
167330
|
-
if (!
|
|
168105
|
+
if (!existsSync44(match.path)) {
|
|
167331
168106
|
throw new ProjectResolutionError(
|
|
167332
168107
|
`Project "${match.name}" is registered but the directory no longer exists: ${match.path}
|
|
167333
168108
|
|
|
@@ -167392,7 +168167,7 @@ Run \`fn project add ` + fusionDir + "` to register it, or use --project <name>.
|
|
|
167392
168167
|
}
|
|
167393
168168
|
if (allProjects.length === 1) {
|
|
167394
168169
|
const project = allProjects[0];
|
|
167395
|
-
if (!
|
|
168170
|
+
if (!existsSync44(project.path)) {
|
|
167396
168171
|
throw new ProjectResolutionError(
|
|
167397
168172
|
`The only registered project "${project.name}" has a missing directory: ${project.path}
|
|
167398
168173
|
|
|
@@ -167832,8 +168607,8 @@ __export(project_exports, {
|
|
|
167832
168607
|
runProjectSetDefault: () => runProjectSetDefault,
|
|
167833
168608
|
runProjectShow: () => runProjectShow
|
|
167834
168609
|
});
|
|
167835
|
-
import { resolve as
|
|
167836
|
-
import { existsSync as
|
|
168610
|
+
import { resolve as resolve35, isAbsolute as isAbsolute19, relative as relative14, basename as basename19 } from "node:path";
|
|
168611
|
+
import { existsSync as existsSync45, statSync as statSync8 } from "node:fs";
|
|
167837
168612
|
import { createInterface as createInterface7 } from "node:readline/promises";
|
|
167838
168613
|
function formatDisplayPath(projectPath) {
|
|
167839
168614
|
const rel = relative14(process.cwd(), projectPath);
|
|
@@ -167961,8 +168736,8 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
167961
168736
|
const pathInput = await rl.question(` Project path [${defaultPath}]: `);
|
|
167962
168737
|
projectPath = pathInput.trim() || defaultPath;
|
|
167963
168738
|
}
|
|
167964
|
-
const absolutePath2 = isAbsolute19(projectPath) ? projectPath :
|
|
167965
|
-
if (!
|
|
168739
|
+
const absolutePath2 = isAbsolute19(projectPath) ? projectPath : resolve35(process.cwd(), projectPath);
|
|
168740
|
+
if (!existsSync45(absolutePath2)) {
|
|
167966
168741
|
console.error(`
|
|
167967
168742
|
\u2717 Path does not exist: ${projectPath}`);
|
|
167968
168743
|
rl.close();
|
|
@@ -167974,8 +168749,8 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
167974
168749
|
rl.close();
|
|
167975
168750
|
process.exit(1);
|
|
167976
168751
|
}
|
|
167977
|
-
const kbDbPath2 =
|
|
167978
|
-
if (!
|
|
168752
|
+
const kbDbPath2 = resolve35(absolutePath2, ".fusion", "fusion.db");
|
|
168753
|
+
if (!existsSync45(kbDbPath2) && !options.force) {
|
|
167979
168754
|
console.log(`
|
|
167980
168755
|
No fn project found at ${formatDisplayPath(absolutePath2)}`);
|
|
167981
168756
|
const init = await rl.question(" Initialize fn here first? [Y/n] ");
|
|
@@ -168006,8 +168781,8 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
168006
168781
|
console.error(" Name must be 1-64 characters and contain only: a-z, A-Z, 0-9, _, -\n");
|
|
168007
168782
|
process.exit(1);
|
|
168008
168783
|
}
|
|
168009
|
-
const absolutePath = isAbsolute19(projectPath) ? projectPath :
|
|
168010
|
-
if (!
|
|
168784
|
+
const absolutePath = isAbsolute19(projectPath) ? projectPath : resolve35(process.cwd(), projectPath);
|
|
168785
|
+
if (!existsSync45(absolutePath)) {
|
|
168011
168786
|
console.error(`
|
|
168012
168787
|
\u2717 Path does not exist: ${projectPath}
|
|
168013
168788
|
`);
|
|
@@ -168019,8 +168794,8 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
168019
168794
|
`);
|
|
168020
168795
|
process.exit(1);
|
|
168021
168796
|
}
|
|
168022
|
-
const kbDbPath =
|
|
168023
|
-
if (!
|
|
168797
|
+
const kbDbPath = resolve35(absolutePath, ".fusion", "fusion.db");
|
|
168798
|
+
if (!existsSync45(kbDbPath) && !options.force) {
|
|
168024
168799
|
console.error(`
|
|
168025
168800
|
\u2717 No fn project found at ${formatDisplayPath(absolutePath)}`);
|
|
168026
168801
|
console.error(" Run `fn init` first to initialize the project.\n");
|
|
@@ -168276,10 +169051,10 @@ var init_project = __esm({
|
|
|
168276
169051
|
});
|
|
168277
169052
|
|
|
168278
169053
|
// src/commands/skill-installation.ts
|
|
168279
|
-
import { cpSync as cpSync2, existsSync as
|
|
169054
|
+
import { cpSync as cpSync2, existsSync as existsSync46, mkdirSync as mkdirSync8 } from "node:fs";
|
|
168280
169055
|
import { homedir as homedir10 } from "node:os";
|
|
168281
|
-
import { dirname as
|
|
168282
|
-
import { fileURLToPath as
|
|
169056
|
+
import { dirname as dirname27, join as join63, resolve as resolve36 } from "node:path";
|
|
169057
|
+
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
168283
169058
|
function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.env.USERPROFILE || homedir10()) {
|
|
168284
169059
|
return [
|
|
168285
169060
|
{ client: "claude", targetDir: join63(homeDir, ".claude", "skills", FUSION_SKILL_NAME2) },
|
|
@@ -168288,9 +169063,9 @@ function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.e
|
|
|
168288
169063
|
];
|
|
168289
169064
|
}
|
|
168290
169065
|
function resolveBundledFusionSkillSource() {
|
|
168291
|
-
const here =
|
|
168292
|
-
const source =
|
|
168293
|
-
return
|
|
169066
|
+
const here = fileURLToPath10(import.meta.url);
|
|
169067
|
+
const source = resolve36(dirname27(here), "..", "..", "skill", FUSION_SKILL_NAME2);
|
|
169068
|
+
return existsSync46(source) ? source : null;
|
|
168294
169069
|
}
|
|
168295
169070
|
function installBundledFusionSkill(options = {}) {
|
|
168296
169071
|
const sourceDir = options.sourceDir ?? resolveBundledFusionSkillSource();
|
|
@@ -168308,7 +169083,7 @@ function installBundledFusionSkill(options = {}) {
|
|
|
168308
169083
|
}
|
|
168309
169084
|
const results = targets.map((target) => {
|
|
168310
169085
|
try {
|
|
168311
|
-
if (
|
|
169086
|
+
if (existsSync46(target.targetDir)) {
|
|
168312
169087
|
return {
|
|
168313
169088
|
client: target.client,
|
|
168314
169089
|
targetDir: target.targetDir,
|
|
@@ -168316,7 +169091,7 @@ function installBundledFusionSkill(options = {}) {
|
|
|
168316
169091
|
reason: "existing install preserved"
|
|
168317
169092
|
};
|
|
168318
169093
|
}
|
|
168319
|
-
mkdirSync8(
|
|
169094
|
+
mkdirSync8(dirname27(target.targetDir), { recursive: true });
|
|
168320
169095
|
cpSync2(sourceDir, target.targetDir, { recursive: true });
|
|
168321
169096
|
return {
|
|
168322
169097
|
client: target.client,
|
|
@@ -168347,17 +169122,17 @@ var init_exports = {};
|
|
|
168347
169122
|
__export(init_exports, {
|
|
168348
169123
|
runInit: () => runInit
|
|
168349
169124
|
});
|
|
168350
|
-
import { existsSync as
|
|
168351
|
-
import { join as join64, resolve as
|
|
169125
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync9, writeFileSync as writeFileSync3, readFileSync as readFileSync22 } from "node:fs";
|
|
169126
|
+
import { join as join64, resolve as resolve37, basename as basename20 } from "node:path";
|
|
168352
169127
|
import { exec as exec12 } from "node:child_process";
|
|
168353
169128
|
import { promisify as promisify17 } from "node:util";
|
|
168354
169129
|
async function runInit(options = {}) {
|
|
168355
|
-
const cwd = options.path ?
|
|
169130
|
+
const cwd = options.path ? resolve37(options.path) : process.cwd();
|
|
168356
169131
|
const fusionDir = join64(cwd, ".fusion");
|
|
168357
169132
|
const dbPath = join64(fusionDir, "fusion.db");
|
|
168358
|
-
const hasDbPath =
|
|
169133
|
+
const hasDbPath = existsSync47(dbPath);
|
|
168359
169134
|
const hasValidDb = hasDbPath && isValidSqliteDatabaseFile(dbPath);
|
|
168360
|
-
if (
|
|
169135
|
+
if (existsSync47(fusionDir) && hasDbPath && hasValidDb) {
|
|
168361
169136
|
const central2 = new CentralCore();
|
|
168362
169137
|
await central2.init();
|
|
168363
169138
|
const existing = await central2.getProjectByPath(cwd);
|
|
@@ -168379,7 +169154,7 @@ async function runInit(options = {}) {
|
|
|
168379
169154
|
await central2.close();
|
|
168380
169155
|
return;
|
|
168381
169156
|
}
|
|
168382
|
-
if (
|
|
169157
|
+
if (existsSync47(fusionDir) && hasDbPath && !hasValidDb) {
|
|
168383
169158
|
throw new Error(
|
|
168384
169159
|
`Existing database at ${dbPath} is not a valid SQLite database. Restore it from .fusion/backups or move it aside before re-running fn init.`
|
|
168385
169160
|
);
|
|
@@ -168387,7 +169162,7 @@ async function runInit(options = {}) {
|
|
|
168387
169162
|
const projectName = options.name ?? await detectProjectName(cwd);
|
|
168388
169163
|
console.log(`Initializing fn project: "${projectName}"`);
|
|
168389
169164
|
console.log(` Path: ${cwd}`);
|
|
168390
|
-
if (!
|
|
169165
|
+
if (!existsSync47(fusionDir)) {
|
|
168391
169166
|
mkdirSync9(fusionDir, { recursive: true });
|
|
168392
169167
|
console.log(` \u2713 Created .fusion/ directory`);
|
|
168393
169168
|
}
|
|
@@ -168400,7 +169175,7 @@ async function runInit(options = {}) {
|
|
|
168400
169175
|
}
|
|
168401
169176
|
await addLocalStorageToGitignore(cwd);
|
|
168402
169177
|
await warnIfQmdMissing();
|
|
168403
|
-
if (!
|
|
169178
|
+
if (!existsSync47(dbPath)) {
|
|
168404
169179
|
writeFileSync3(dbPath, "");
|
|
168405
169180
|
console.log(` \u2713 Created fusion.db`);
|
|
168406
169181
|
}
|
|
@@ -168450,7 +169225,7 @@ async function runInit(options = {}) {
|
|
|
168450
169225
|
}
|
|
168451
169226
|
}
|
|
168452
169227
|
async function detectProjectName(dir2) {
|
|
168453
|
-
if (!
|
|
169228
|
+
if (!existsSync47(join64(dir2, ".git"))) {
|
|
168454
169229
|
return basename20(dir2) || "my-project";
|
|
168455
169230
|
}
|
|
168456
169231
|
try {
|
|
@@ -168472,9 +169247,9 @@ async function detectProjectName(dir2) {
|
|
|
168472
169247
|
async function addLocalStorageToGitignore(cwd) {
|
|
168473
169248
|
const gitignorePath = join64(cwd, ".gitignore");
|
|
168474
169249
|
let content = "";
|
|
168475
|
-
if (
|
|
169250
|
+
if (existsSync47(gitignorePath)) {
|
|
168476
169251
|
try {
|
|
168477
|
-
content =
|
|
169252
|
+
content = readFileSync22(gitignorePath, "utf-8");
|
|
168478
169253
|
} catch {
|
|
168479
169254
|
}
|
|
168480
169255
|
}
|
|
@@ -168514,7 +169289,7 @@ async function initializeGitRepo(cwd) {
|
|
|
168514
169289
|
await ensureGitConfig(cwd, "user.name", "Fusion");
|
|
168515
169290
|
await ensureGitConfig(cwd, "user.email", "noreply@runfusion.ai");
|
|
168516
169291
|
const gitkeepPath = join64(cwd, ".gitkeep");
|
|
168517
|
-
if (!
|
|
169292
|
+
if (!existsSync47(gitkeepPath)) {
|
|
168518
169293
|
writeFileSync3(gitkeepPath, "\n");
|
|
168519
169294
|
}
|
|
168520
169295
|
await execAsync11("git add .gitkeep", { cwd, timeout: 1e4 });
|
|
@@ -168652,8 +169427,8 @@ var agent_import_exports = {};
|
|
|
168652
169427
|
__export(agent_import_exports, {
|
|
168653
169428
|
runAgentImport: () => runAgentImport
|
|
168654
169429
|
});
|
|
168655
|
-
import { existsSync as
|
|
168656
|
-
import { resolve as
|
|
169430
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync10, readFileSync as readFileSync23, statSync as statSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
169431
|
+
import { resolve as resolve38 } from "node:path";
|
|
168657
169432
|
function slugifyPathSegment(input) {
|
|
168658
169433
|
if (!input || typeof input !== "string") {
|
|
168659
169434
|
return "unnamed";
|
|
@@ -168702,16 +169477,16 @@ async function importSkillsToProject(projectPath, skills, companySlug, dryRun) {
|
|
|
168702
169477
|
errors: []
|
|
168703
169478
|
};
|
|
168704
169479
|
const companyDir = slugifyPathSegment(companySlug ?? "unknown-company");
|
|
168705
|
-
const baseSkillsDir =
|
|
169480
|
+
const baseSkillsDir = resolve38(projectPath, "skills", "imported", companyDir);
|
|
168706
169481
|
for (const skill of skills) {
|
|
168707
169482
|
if (!skill.name || typeof skill.name !== "string" || skill.name.trim().length === 0) {
|
|
168708
169483
|
result.errors.push({ name: "(unnamed)", error: "Skill is missing required 'name' field" });
|
|
168709
169484
|
continue;
|
|
168710
169485
|
}
|
|
168711
169486
|
const skillSlug = slugifyPathSegment(skill.name);
|
|
168712
|
-
const skillDir =
|
|
168713
|
-
const skillPath =
|
|
168714
|
-
if (
|
|
169487
|
+
const skillDir = resolve38(baseSkillsDir, skillSlug);
|
|
169488
|
+
const skillPath = resolve38(skillDir, "SKILL.md");
|
|
169489
|
+
if (existsSync48(skillPath)) {
|
|
168715
169490
|
result.skipped.push(skill.name);
|
|
168716
169491
|
continue;
|
|
168717
169492
|
}
|
|
@@ -168783,8 +169558,8 @@ function isArchivePath(path5) {
|
|
|
168783
169558
|
async function runAgentImport(source, options) {
|
|
168784
169559
|
const dryRun = options?.dryRun ?? false;
|
|
168785
169560
|
const skipExisting = options?.skipExisting ?? false;
|
|
168786
|
-
const sourcePath =
|
|
168787
|
-
if (!
|
|
169561
|
+
const sourcePath = resolve38(source);
|
|
169562
|
+
if (!existsSync48(sourcePath)) {
|
|
168788
169563
|
console.error(`Path not found: ${sourcePath}`);
|
|
168789
169564
|
process.exit(1);
|
|
168790
169565
|
}
|
|
@@ -168830,7 +169605,7 @@ async function runAgentImport(source, options) {
|
|
|
168830
169605
|
isPackageImport = true;
|
|
168831
169606
|
({ items: importItems, result } = prepareAgentCompaniesImport(pkg, conversionOptions));
|
|
168832
169607
|
} else if (sourcePath.endsWith(".md")) {
|
|
168833
|
-
const content =
|
|
169608
|
+
const content = readFileSync23(sourcePath, "utf-8");
|
|
168834
169609
|
const { manifest } = parseSingleAgentManifest(content);
|
|
168835
169610
|
const pkg = {
|
|
168836
169611
|
company: void 0,
|
|
@@ -168922,7 +169697,7 @@ var agent_export_exports = {};
|
|
|
168922
169697
|
__export(agent_export_exports, {
|
|
168923
169698
|
runAgentExport: () => runAgentExport
|
|
168924
169699
|
});
|
|
168925
|
-
import { resolve as
|
|
169700
|
+
import { resolve as resolve39 } from "node:path";
|
|
168926
169701
|
async function getProjectPath4(projectName) {
|
|
168927
169702
|
if (projectName) {
|
|
168928
169703
|
const context = await resolveProject(projectName);
|
|
@@ -168960,7 +169735,7 @@ async function runAgentExport(outputDir, options) {
|
|
|
168960
169735
|
console.error("No agents found to export");
|
|
168961
169736
|
process.exit(1);
|
|
168962
169737
|
}
|
|
168963
|
-
const result = await exportAgentsToDirectory(agents,
|
|
169738
|
+
const result = await exportAgentsToDirectory(agents, resolve39(outputDir), {
|
|
168964
169739
|
companyName: options?.companyName,
|
|
168965
169740
|
companySlug: options?.companySlug
|
|
168966
169741
|
});
|
|
@@ -169179,7 +169954,7 @@ __export(plugin_exports, {
|
|
|
169179
169954
|
runPluginList: () => runPluginList,
|
|
169180
169955
|
runPluginUninstall: () => runPluginUninstall
|
|
169181
169956
|
});
|
|
169182
|
-
import { existsSync as
|
|
169957
|
+
import { existsSync as existsSync49 } from "node:fs";
|
|
169183
169958
|
import { join as join65 } from "node:path";
|
|
169184
169959
|
import { readFile as readFile23 } from "node:fs/promises";
|
|
169185
169960
|
import * as readline from "node:readline";
|
|
@@ -169219,7 +169994,7 @@ async function createPluginLoader(pluginStore, projectName) {
|
|
|
169219
169994
|
}
|
|
169220
169995
|
async function loadManifestFromPath(pluginPath) {
|
|
169221
169996
|
const manifestPath = join65(pluginPath, "manifest.json");
|
|
169222
|
-
if (!
|
|
169997
|
+
if (!existsSync49(manifestPath)) {
|
|
169223
169998
|
throw new Error(`Plugin manifest not found at: ${manifestPath}`);
|
|
169224
169999
|
}
|
|
169225
170000
|
const content = await readFile23(manifestPath, "utf-8");
|
|
@@ -169277,7 +170052,7 @@ async function runPluginInstall(source, options) {
|
|
|
169277
170052
|
console.error("Please provide a local path to the plugin directory.");
|
|
169278
170053
|
process.exit(1);
|
|
169279
170054
|
}
|
|
169280
|
-
if (!
|
|
170055
|
+
if (!existsSync49(source)) {
|
|
169281
170056
|
console.error(`Plugin path does not exist: ${source}`);
|
|
169282
170057
|
process.exit(1);
|
|
169283
170058
|
}
|
|
@@ -169322,14 +170097,14 @@ async function runPluginUninstall(id, options) {
|
|
|
169322
170097
|
console.log(` Uninstall "${plugin4.name}"?`);
|
|
169323
170098
|
console.log(` This will stop and remove the plugin.`);
|
|
169324
170099
|
console.log();
|
|
169325
|
-
const response = await new Promise((
|
|
170100
|
+
const response = await new Promise((resolve42) => {
|
|
169326
170101
|
const rl = readline.createInterface({
|
|
169327
170102
|
input: process.stdin,
|
|
169328
170103
|
output: process.stdout
|
|
169329
170104
|
});
|
|
169330
170105
|
rl.question(" Continue? [y/N] ", (answer) => {
|
|
169331
170106
|
rl.close();
|
|
169332
|
-
|
|
170107
|
+
resolve42(answer.toLowerCase());
|
|
169333
170108
|
});
|
|
169334
170109
|
});
|
|
169335
170110
|
if (response !== "y" && response !== "yes") {
|
|
@@ -169409,7 +170184,7 @@ var plugin_scaffold_exports = {};
|
|
|
169409
170184
|
__export(plugin_scaffold_exports, {
|
|
169410
170185
|
runPluginCreate: () => runPluginCreate
|
|
169411
170186
|
});
|
|
169412
|
-
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as
|
|
170187
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as existsSync50 } from "node:fs";
|
|
169413
170188
|
import { join as join66 } from "node:path";
|
|
169414
170189
|
function toTitleCase(str) {
|
|
169415
170190
|
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -169544,7 +170319,7 @@ async function runPluginCreate(name, options) {
|
|
|
169544
170319
|
}
|
|
169545
170320
|
const targetDir = options?.output ?? name;
|
|
169546
170321
|
const targetPath = join66(process.cwd(), targetDir);
|
|
169547
|
-
if (
|
|
170322
|
+
if (existsSync50(targetPath)) {
|
|
169548
170323
|
console.error(`Error: Directory '${targetDir}' already exists.`);
|
|
169549
170324
|
console.error("Please choose a different name or remove the existing directory.");
|
|
169550
170325
|
process.exit(1);
|
|
@@ -169594,7 +170369,7 @@ __export(skills_exports, {
|
|
|
169594
170369
|
runSkillsSearch: () => runSkillsSearch,
|
|
169595
170370
|
searchSkills: () => searchSkills
|
|
169596
170371
|
});
|
|
169597
|
-
import { spawn as
|
|
170372
|
+
import { spawn as spawn18 } from "node:child_process";
|
|
169598
170373
|
async function searchSkills(query, limit = 10) {
|
|
169599
170374
|
const url = `${SKILLS_API_BASE}/api/search?q=${encodeURIComponent(query)}&limit=${limit}`;
|
|
169600
170375
|
try {
|
|
@@ -169672,14 +170447,14 @@ async function runSkillsInstall(args, options) {
|
|
|
169672
170447
|
npxArgs.push("--skill", options.skill);
|
|
169673
170448
|
}
|
|
169674
170449
|
npxArgs.push("-y", "-a", "pi");
|
|
169675
|
-
const child =
|
|
170450
|
+
const child = spawn18("npx", npxArgs, {
|
|
169676
170451
|
cwd: process.cwd(),
|
|
169677
170452
|
stdio: "inherit",
|
|
169678
170453
|
shell: true
|
|
169679
170454
|
});
|
|
169680
|
-
const exitCode = await new Promise((
|
|
170455
|
+
const exitCode = await new Promise((resolve42, reject2) => {
|
|
169681
170456
|
child.on("exit", (code) => {
|
|
169682
|
-
|
|
170457
|
+
resolve42(code ?? 1);
|
|
169683
170458
|
});
|
|
169684
170459
|
child.on("error", (err) => {
|
|
169685
170460
|
reject2(err);
|
|
@@ -169712,7 +170487,7 @@ __export(research_exports, {
|
|
|
169712
170487
|
runResearchShow: () => runResearchShow
|
|
169713
170488
|
});
|
|
169714
170489
|
import { writeFile as writeFile19 } from "node:fs/promises";
|
|
169715
|
-
import { join as join67, resolve as
|
|
170490
|
+
import { join as join67, resolve as resolve40 } from "node:path";
|
|
169716
170491
|
async function getStore3(projectName) {
|
|
169717
170492
|
const project = projectName ? await resolveProject(projectName) : void 0;
|
|
169718
170493
|
const store = new TaskStore(project?.projectPath ?? process.cwd());
|
|
@@ -169868,7 +170643,7 @@ async function runResearchExport(options) {
|
|
|
169868
170643
|
}
|
|
169869
170644
|
const content = format === "json" ? JSON.stringify(run, null, 2) : renderMarkdown(run);
|
|
169870
170645
|
const ext = format === "json" ? "json" : "md";
|
|
169871
|
-
const outputPath = options.output ?
|
|
170646
|
+
const outputPath = options.output ? resolve40(options.output) : join67(process.cwd(), `research-${run.id.toLowerCase()}.${ext}`);
|
|
169872
170647
|
await writeFile19(outputPath, content, "utf8");
|
|
169873
170648
|
store.getResearchStore().createExport(run.id, format, content);
|
|
169874
170649
|
if (options.json) {
|
|
@@ -169933,21 +170708,21 @@ __export(native_patch_exports, {
|
|
|
169933
170708
|
isTerminalAvailable: () => isTerminalAvailable,
|
|
169934
170709
|
setupNativeResolution: () => setupNativeResolution
|
|
169935
170710
|
});
|
|
169936
|
-
import { join as join68, basename as basename21, dirname as
|
|
169937
|
-
import { existsSync as
|
|
170711
|
+
import { join as join68, basename as basename21, dirname as dirname28 } from "node:path";
|
|
170712
|
+
import { existsSync as existsSync51, copyFileSync, mkdirSync as mkdirSync12, symlinkSync as symlinkSync2, rmSync as rmSync5, lstatSync as lstatSync3, readlinkSync as readlinkSync2 } from "node:fs";
|
|
169938
170713
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
169939
170714
|
function findStagedNativeDir2() {
|
|
169940
|
-
const
|
|
170715
|
+
const platform4 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
|
|
169941
170716
|
const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
|
|
169942
|
-
const prebuildName = `${
|
|
169943
|
-
const execDir =
|
|
170717
|
+
const prebuildName = `${platform4}-${arch}`;
|
|
170718
|
+
const execDir = dirname28(process.execPath);
|
|
169944
170719
|
const nextToBinary = join68(execDir, "runtime", prebuildName);
|
|
169945
|
-
if (
|
|
170720
|
+
if (existsSync51(join68(nextToBinary, "pty.node"))) {
|
|
169946
170721
|
return nextToBinary;
|
|
169947
170722
|
}
|
|
169948
170723
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
169949
170724
|
const envPath = join68(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
169950
|
-
if (
|
|
170725
|
+
if (existsSync51(join68(envPath, "pty.node"))) {
|
|
169951
170726
|
return envPath;
|
|
169952
170727
|
}
|
|
169953
170728
|
}
|
|
@@ -169957,11 +170732,11 @@ function cleanupStaleBunfsLinks() {
|
|
|
169957
170732
|
if (process.platform === "win32") return;
|
|
169958
170733
|
const bunfsRoot = "/$bunfs/root";
|
|
169959
170734
|
try {
|
|
169960
|
-
if (
|
|
170735
|
+
if (existsSync51(bunfsRoot)) {
|
|
169961
170736
|
const stats = lstatSync3(bunfsRoot);
|
|
169962
170737
|
if (stats.isSymbolicLink()) {
|
|
169963
170738
|
const target = readlinkSync2(bunfsRoot);
|
|
169964
|
-
if (target.includes("fn-bunfs-") && !
|
|
170739
|
+
if (target.includes("fn-bunfs-") && !existsSync51(target)) {
|
|
169965
170740
|
rmSync5(bunfsRoot);
|
|
169966
170741
|
console.log("[fn-native-patch] Cleaned up stale /$bunfs/root symlink");
|
|
169967
170742
|
}
|
|
@@ -169989,14 +170764,14 @@ function setupNativeResolution() {
|
|
|
169989
170764
|
mkdirSync12(platformDir, { recursive: true });
|
|
169990
170765
|
const ptyNodeDest = join68(platformDir, "pty.node");
|
|
169991
170766
|
copyFileSync(join68(nativeDir, "pty.node"), ptyNodeDest);
|
|
169992
|
-
if (
|
|
170767
|
+
if (existsSync51(join68(nativeDir, "spawn-helper"))) {
|
|
169993
170768
|
copyFileSync(join68(nativeDir, "spawn-helper"), join68(platformDir, "spawn-helper"));
|
|
169994
170769
|
}
|
|
169995
170770
|
process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
|
|
169996
170771
|
if (process.platform !== "win32") {
|
|
169997
170772
|
const bunfsRoot = "/$bunfs/root";
|
|
169998
170773
|
try {
|
|
169999
|
-
if (
|
|
170774
|
+
if (existsSync51(bunfsRoot)) {
|
|
170000
170775
|
const stats = lstatSync3(bunfsRoot);
|
|
170001
170776
|
if (stats.isSymbolicLink()) {
|
|
170002
170777
|
rmSync5(bunfsRoot);
|
|
@@ -170019,7 +170794,7 @@ function setupNativeResolution() {
|
|
|
170019
170794
|
function cleanupNativeResolution() {
|
|
170020
170795
|
if (bunfsSymlinkPath && process.platform !== "win32") {
|
|
170021
170796
|
try {
|
|
170022
|
-
if (
|
|
170797
|
+
if (existsSync51(bunfsSymlinkPath)) {
|
|
170023
170798
|
const stats = lstatSync3(bunfsSymlinkPath);
|
|
170024
170799
|
if (stats.isSymbolicLink()) {
|
|
170025
170800
|
rmSync5(bunfsSymlinkPath);
|
|
@@ -170065,11 +170840,12 @@ var init_native_patch = __esm({
|
|
|
170065
170840
|
});
|
|
170066
170841
|
|
|
170067
170842
|
// src/bin.ts
|
|
170068
|
-
import { existsSync as
|
|
170069
|
-
import { createRequire as
|
|
170070
|
-
import { join as join69, dirname as
|
|
170843
|
+
import { existsSync as existsSync52, mkdtempSync as mkdtempSync2, readFileSync as readFileSync24, symlinkSync as symlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
170844
|
+
import { createRequire as createRequire7 } from "node:module";
|
|
170845
|
+
import { join as join69, dirname as dirname29, resolve as resolve41 } from "node:path";
|
|
170071
170846
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
170072
170847
|
import { performance as performance3 } from "node:perf_hooks";
|
|
170848
|
+
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
170073
170849
|
var isBunBinary3 = typeof Bun !== "undefined" && !!Bun.embeddedFiles;
|
|
170074
170850
|
function configurePiPackage() {
|
|
170075
170851
|
if (process.env.PI_PACKAGE_DIR) {
|
|
@@ -170082,13 +170858,13 @@ function configurePiPackage() {
|
|
|
170082
170858
|
type: "module"
|
|
170083
170859
|
};
|
|
170084
170860
|
try {
|
|
170085
|
-
const require4 =
|
|
170861
|
+
const require4 = createRequire7(import.meta.url);
|
|
170086
170862
|
const piPackagePath = require4.resolve("@mariozechner/pi-coding-agent/package.json");
|
|
170087
|
-
const piPackageDir =
|
|
170088
|
-
packageJson = JSON.parse(
|
|
170863
|
+
const piPackageDir = dirname29(piPackagePath);
|
|
170864
|
+
packageJson = JSON.parse(readFileSync24(piPackagePath, "utf-8"));
|
|
170089
170865
|
for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
|
|
170090
170866
|
const source = join69(piPackageDir, entry);
|
|
170091
|
-
if (
|
|
170867
|
+
if (existsSync52(source)) {
|
|
170092
170868
|
symlinkSync3(source, join69(tmp, entry));
|
|
170093
170869
|
}
|
|
170094
170870
|
}
|
|
@@ -170107,8 +170883,8 @@ setInterval(() => {
|
|
|
170107
170883
|
performance3.clearMarks();
|
|
170108
170884
|
}, 3e4).unref();
|
|
170109
170885
|
function loadEnvFile(path5) {
|
|
170110
|
-
if (!
|
|
170111
|
-
const contents =
|
|
170886
|
+
if (!existsSync52(path5)) return;
|
|
170887
|
+
const contents = readFileSync24(path5, "utf-8");
|
|
170112
170888
|
for (const rawLine of contents.split(/\r?\n/)) {
|
|
170113
170889
|
const line = rawLine.trim();
|
|
170114
170890
|
if (!line || line.startsWith("#")) continue;
|
|
@@ -170419,8 +171195,36 @@ function getFlagValueNumber(args, flag) {
|
|
|
170419
171195
|
const parsed = Number(value);
|
|
170420
171196
|
return Number.isFinite(parsed) ? parsed : void 0;
|
|
170421
171197
|
}
|
|
171198
|
+
function readOwnCliVersion() {
|
|
171199
|
+
let currentDir;
|
|
171200
|
+
try {
|
|
171201
|
+
currentDir = dirname29(fileURLToPath11(import.meta.url));
|
|
171202
|
+
} catch {
|
|
171203
|
+
return void 0;
|
|
171204
|
+
}
|
|
171205
|
+
for (let i = 0; i < 8; i += 1) {
|
|
171206
|
+
const pkgPath = resolve41(currentDir, "package.json");
|
|
171207
|
+
if (existsSync52(pkgPath)) {
|
|
171208
|
+
try {
|
|
171209
|
+
const parsed = JSON.parse(readFileSync24(pkgPath, "utf-8"));
|
|
171210
|
+
if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string") {
|
|
171211
|
+
return parsed.version;
|
|
171212
|
+
}
|
|
171213
|
+
} catch {
|
|
171214
|
+
}
|
|
171215
|
+
}
|
|
171216
|
+
const parentDir = resolve41(currentDir, "..");
|
|
171217
|
+
if (parentDir === currentDir) break;
|
|
171218
|
+
currentDir = parentDir;
|
|
171219
|
+
}
|
|
171220
|
+
return void 0;
|
|
171221
|
+
}
|
|
170422
171222
|
async function main() {
|
|
170423
171223
|
const { cleanedArgs: args, projectName } = extractGlobalProjectFlag(process.argv.slice(2));
|
|
171224
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
171225
|
+
console.log(readOwnCliVersion() ?? "unknown");
|
|
171226
|
+
process.exit(0);
|
|
171227
|
+
}
|
|
170424
171228
|
if (args.includes("--help") || args.includes("-h")) {
|
|
170425
171229
|
console.log(HELP);
|
|
170426
171230
|
process.exit(0);
|