@lobehub/cli 0.0.24 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1427 -441
- package/man/man1/lh.1 +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -7440,11 +7440,21 @@ const DEFAULT_DESKTOP_HOTKEY_CONFIG = DESKTOP_HOTKEYS_REGISTRATION.reduce((acc,
|
|
|
7440
7440
|
}, {});
|
|
7441
7441
|
|
|
7442
7442
|
//#endregion
|
|
7443
|
-
//#region
|
|
7444
|
-
const
|
|
7445
|
-
const
|
|
7443
|
+
//#region ../../packages/business/const/src/branding.ts
|
|
7444
|
+
const ORG_NAME = "LobeHub";
|
|
7445
|
+
const COPYRIGHT = `© ${(/* @__PURE__ */ new Date()).getFullYear()} ${ORG_NAME}`;
|
|
7446
|
+
const COPYRIGHT_FULL = `${COPYRIGHT}. All rights reserved.`;
|
|
7447
|
+
|
|
7448
|
+
//#endregion
|
|
7449
|
+
//#region ../../packages/business/const/src/llm.ts
|
|
7446
7450
|
const DEFAULT_MODEL = "deepseek-v4-pro";
|
|
7447
7451
|
const DEFAULT_PROVIDER = "deepseek";
|
|
7452
|
+
const DEFAULT_MINI_MODEL = "gpt-5.4-mini";
|
|
7453
|
+
const DEFAULT_MINI_PROVIDER = "openai";
|
|
7454
|
+
|
|
7455
|
+
//#endregion
|
|
7456
|
+
//#region ../../packages/business/const/src/index.ts
|
|
7457
|
+
const isDev$1 = process.env.NODE_ENV === "development";
|
|
7448
7458
|
|
|
7449
7459
|
//#endregion
|
|
7450
7460
|
//#region ../../packages/const/src/meta.ts
|
|
@@ -7730,7 +7740,7 @@ const INTEREST_AREA_KEYS = [
|
|
|
7730
7740
|
const interestAreaKeySet = new Set(INTEREST_AREA_KEYS);
|
|
7731
7741
|
|
|
7732
7742
|
//#endregion
|
|
7733
|
-
//#region
|
|
7743
|
+
//#region node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.production.js
|
|
7734
7744
|
/**
|
|
7735
7745
|
* @license React
|
|
7736
7746
|
* react-jsx-runtime.production.js
|
|
@@ -7765,7 +7775,7 @@ var require_react_jsx_runtime_production = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
7765
7775
|
}));
|
|
7766
7776
|
|
|
7767
7777
|
//#endregion
|
|
7768
|
-
//#region
|
|
7778
|
+
//#region node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react.production.js
|
|
7769
7779
|
/**
|
|
7770
7780
|
* @license React
|
|
7771
7781
|
* react.production.js
|
|
@@ -8122,11 +8132,11 @@ var require_react_production = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
8122
8132
|
exports.useTransition = function() {
|
|
8123
8133
|
return ReactSharedInternals.H.useTransition();
|
|
8124
8134
|
};
|
|
8125
|
-
exports.version = "19.2.
|
|
8135
|
+
exports.version = "19.2.5";
|
|
8126
8136
|
}));
|
|
8127
8137
|
|
|
8128
8138
|
//#endregion
|
|
8129
|
-
//#region
|
|
8139
|
+
//#region node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react.development.js
|
|
8130
8140
|
/**
|
|
8131
8141
|
* @license React
|
|
8132
8142
|
* react.development.js
|
|
@@ -8880,20 +8890,20 @@ var require_react_development = /* @__PURE__ */ __commonJSMin(((exports, module)
|
|
|
8880
8890
|
exports.useTransition = function() {
|
|
8881
8891
|
return resolveDispatcher().useTransition();
|
|
8882
8892
|
};
|
|
8883
|
-
exports.version = "19.2.
|
|
8893
|
+
exports.version = "19.2.5";
|
|
8884
8894
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
8885
8895
|
})();
|
|
8886
8896
|
}));
|
|
8887
8897
|
|
|
8888
8898
|
//#endregion
|
|
8889
|
-
//#region
|
|
8899
|
+
//#region node_modules/.pnpm/react@19.2.5/node_modules/react/index.js
|
|
8890
8900
|
var require_react = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
8891
8901
|
if (process.env.NODE_ENV === "production") module.exports = require_react_production();
|
|
8892
8902
|
else module.exports = require_react_development();
|
|
8893
8903
|
}));
|
|
8894
8904
|
|
|
8895
8905
|
//#endregion
|
|
8896
|
-
//#region
|
|
8906
|
+
//#region node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js
|
|
8897
8907
|
/**
|
|
8898
8908
|
* @license React
|
|
8899
8909
|
* react-jsx-runtime.development.js
|
|
@@ -9093,14 +9103,14 @@ var require_react_jsx_runtime_development = /* @__PURE__ */ __commonJSMin(((expo
|
|
|
9093
9103
|
}));
|
|
9094
9104
|
|
|
9095
9105
|
//#endregion
|
|
9096
|
-
//#region
|
|
9106
|
+
//#region node_modules/.pnpm/react@19.2.5/node_modules/react/jsx-runtime.js
|
|
9097
9107
|
var require_jsx_runtime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
9098
9108
|
if (process.env.NODE_ENV === "production") module.exports = require_react_jsx_runtime_production();
|
|
9099
9109
|
else module.exports = require_react_jsx_runtime_development();
|
|
9100
9110
|
}));
|
|
9101
9111
|
|
|
9102
9112
|
//#endregion
|
|
9103
|
-
//#region
|
|
9113
|
+
//#region node_modules/.pnpm/@icons-pack+react-simple-icons@13.13.0_react@19.2.5/node_modules/@icons-pack/react-simple-icons/icons/SiCaldotcom.mjs
|
|
9104
9114
|
var import_jsx_runtime = require_jsx_runtime();
|
|
9105
9115
|
var import_react = /* @__PURE__ */ __toESM$2(require_react(), 1);
|
|
9106
9116
|
const defaultColor = "#292929";
|
|
@@ -9119,7 +9129,7 @@ const SiCaldotcom = import_react.forwardRef(function SiCaldotcom2({ title = "Cal
|
|
|
9119
9129
|
});
|
|
9120
9130
|
|
|
9121
9131
|
//#endregion
|
|
9122
|
-
//#region
|
|
9132
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/types/McpServerName.mjs
|
|
9123
9133
|
/**
|
|
9124
9134
|
* This file was auto-generated by Fern from our API Definition.
|
|
9125
9135
|
*/
|
|
@@ -9204,7 +9214,7 @@ const McpServerName = {
|
|
|
9204
9214
|
};
|
|
9205
9215
|
|
|
9206
9216
|
//#endregion
|
|
9207
|
-
//#region
|
|
9217
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/json.mjs
|
|
9208
9218
|
/**
|
|
9209
9219
|
* Serialize a value to JSON
|
|
9210
9220
|
* @param value A JavaScript value, usually an object or array, to be converted.
|
|
@@ -9217,7 +9227,7 @@ const toJson = (value, replacer, space) => {
|
|
|
9217
9227
|
};
|
|
9218
9228
|
|
|
9219
9229
|
//#endregion
|
|
9220
|
-
//#region
|
|
9230
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/errors/KlavisError.mjs
|
|
9221
9231
|
/**
|
|
9222
9232
|
* This file was auto-generated by Fern from our API Definition.
|
|
9223
9233
|
*/
|
|
@@ -9243,7 +9253,7 @@ function buildMessage({ message, statusCode, body }) {
|
|
|
9243
9253
|
}
|
|
9244
9254
|
|
|
9245
9255
|
//#endregion
|
|
9246
|
-
//#region
|
|
9256
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/errors/UnprocessableEntityError.mjs
|
|
9247
9257
|
/**
|
|
9248
9258
|
* This file was auto-generated by Fern from our API Definition.
|
|
9249
9259
|
*/
|
|
@@ -9260,7 +9270,7 @@ var UnprocessableEntityError = class UnprocessableEntityError extends KlavisErro
|
|
|
9260
9270
|
};
|
|
9261
9271
|
|
|
9262
9272
|
//#endregion
|
|
9263
|
-
//#region
|
|
9273
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/errors/BadRequestError.mjs
|
|
9264
9274
|
/**
|
|
9265
9275
|
* This file was auto-generated by Fern from our API Definition.
|
|
9266
9276
|
*/
|
|
@@ -9277,7 +9287,7 @@ var BadRequestError = class BadRequestError extends KlavisError {
|
|
|
9277
9287
|
};
|
|
9278
9288
|
|
|
9279
9289
|
//#endregion
|
|
9280
|
-
//#region
|
|
9290
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/Headers.mjs
|
|
9281
9291
|
let Headers$1;
|
|
9282
9292
|
if (typeof globalThis.Headers !== "undefined") Headers$1 = globalThis.Headers;
|
|
9283
9293
|
else Headers$1 = class Headers {
|
|
@@ -9333,7 +9343,7 @@ else Headers$1 = class Headers {
|
|
|
9333
9343
|
};
|
|
9334
9344
|
|
|
9335
9345
|
//#endregion
|
|
9336
|
-
//#region
|
|
9346
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/RawResponse.mjs
|
|
9337
9347
|
/**
|
|
9338
9348
|
* A raw response indicating that the request was aborted.
|
|
9339
9349
|
*/
|
|
@@ -9358,7 +9368,7 @@ const unknownRawResponse = {
|
|
|
9358
9368
|
};
|
|
9359
9369
|
|
|
9360
9370
|
//#endregion
|
|
9361
|
-
//#region
|
|
9371
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/Supplier.mjs
|
|
9362
9372
|
var __awaiter$21 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9363
9373
|
function adopt(value) {
|
|
9364
9374
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9388,7 +9398,7 @@ var __awaiter$21 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9388
9398
|
};
|
|
9389
9399
|
|
|
9390
9400
|
//#endregion
|
|
9391
|
-
//#region
|
|
9401
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/runtime/runtime.mjs
|
|
9392
9402
|
/**
|
|
9393
9403
|
* A constant that indicates which environment and version the SDK is running in.
|
|
9394
9404
|
*/
|
|
@@ -9420,7 +9430,7 @@ function evaluateRuntime() {
|
|
|
9420
9430
|
}
|
|
9421
9431
|
|
|
9422
9432
|
//#endregion
|
|
9423
|
-
//#region
|
|
9433
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/getFetchFn.mjs
|
|
9424
9434
|
var __awaiter$20 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9425
9435
|
function adopt(value) {
|
|
9426
9436
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9450,7 +9460,7 @@ var __awaiter$20 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9450
9460
|
};
|
|
9451
9461
|
|
|
9452
9462
|
//#endregion
|
|
9453
|
-
//#region
|
|
9463
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/getRequestBody.mjs
|
|
9454
9464
|
var __awaiter$19 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9455
9465
|
function adopt(value) {
|
|
9456
9466
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9480,7 +9490,7 @@ var __awaiter$19 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9480
9490
|
};
|
|
9481
9491
|
|
|
9482
9492
|
//#endregion
|
|
9483
|
-
//#region
|
|
9493
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/stream-wrappers/chooseStreamWrapper.mjs
|
|
9484
9494
|
var __awaiter$18 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9485
9495
|
function adopt(value) {
|
|
9486
9496
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9510,7 +9520,7 @@ var __awaiter$18 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9510
9520
|
};
|
|
9511
9521
|
|
|
9512
9522
|
//#endregion
|
|
9513
|
-
//#region
|
|
9523
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/getResponseBody.mjs
|
|
9514
9524
|
var __awaiter$17 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9515
9525
|
function adopt(value) {
|
|
9516
9526
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9540,7 +9550,7 @@ var __awaiter$17 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9540
9550
|
};
|
|
9541
9551
|
|
|
9542
9552
|
//#endregion
|
|
9543
|
-
//#region
|
|
9553
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/makeRequest.mjs
|
|
9544
9554
|
var __awaiter$16 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9545
9555
|
function adopt(value) {
|
|
9546
9556
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9570,7 +9580,7 @@ var __awaiter$16 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9570
9580
|
};
|
|
9571
9581
|
|
|
9572
9582
|
//#endregion
|
|
9573
|
-
//#region
|
|
9583
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/requestWithRetries.mjs
|
|
9574
9584
|
var __awaiter$15 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9575
9585
|
function adopt(value) {
|
|
9576
9586
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9600,7 +9610,7 @@ var __awaiter$15 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9600
9610
|
};
|
|
9601
9611
|
|
|
9602
9612
|
//#endregion
|
|
9603
|
-
//#region
|
|
9613
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/Fetcher.mjs
|
|
9604
9614
|
var __awaiter$14 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9605
9615
|
function adopt(value) {
|
|
9606
9616
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9630,7 +9640,7 @@ var __awaiter$14 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9630
9640
|
};
|
|
9631
9641
|
|
|
9632
9642
|
//#endregion
|
|
9633
|
-
//#region
|
|
9643
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/core/fetcher/HttpResponsePromise.mjs
|
|
9634
9644
|
var __awaiter$13 = void 0 && (void 0).__awaiter || function(thisArg, _arguments, P, generator) {
|
|
9635
9645
|
function adopt(value) {
|
|
9636
9646
|
return value instanceof P ? value : new P(function(resolve) {
|
|
@@ -9660,7 +9670,7 @@ var __awaiter$13 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9660
9670
|
};
|
|
9661
9671
|
|
|
9662
9672
|
//#endregion
|
|
9663
|
-
//#region
|
|
9673
|
+
//#region node_modules/.pnpm/url-join@4.0.1/node_modules/url-join/lib/url-join.js
|
|
9664
9674
|
var require_url_join = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
9665
9675
|
(function(name, context, definition) {
|
|
9666
9676
|
if (typeof module !== "undefined" && module.exports) module.exports = definition();
|
|
@@ -9699,7 +9709,7 @@ var require_url_join = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9699
9709
|
}));
|
|
9700
9710
|
|
|
9701
9711
|
//#endregion
|
|
9702
|
-
//#region
|
|
9712
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/mcpServer/client/Client.mjs
|
|
9703
9713
|
var import_url_join = /* @__PURE__ */ __toESM$2(require_url_join(), 1);
|
|
9704
9714
|
/**
|
|
9705
9715
|
* This file was auto-generated by Fern from our API Definition.
|
|
@@ -9733,7 +9743,7 @@ var __awaiter$12 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9733
9743
|
};
|
|
9734
9744
|
|
|
9735
9745
|
//#endregion
|
|
9736
|
-
//#region
|
|
9746
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/whiteLabeling/client/Client.mjs
|
|
9737
9747
|
/**
|
|
9738
9748
|
* This file was auto-generated by Fern from our API Definition.
|
|
9739
9749
|
*/
|
|
@@ -9766,7 +9776,7 @@ var __awaiter$11 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9766
9776
|
};
|
|
9767
9777
|
|
|
9768
9778
|
//#endregion
|
|
9769
|
-
//#region
|
|
9779
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/user/client/Client.mjs
|
|
9770
9780
|
/**
|
|
9771
9781
|
* This file was auto-generated by Fern from our API Definition.
|
|
9772
9782
|
*/
|
|
@@ -9799,7 +9809,7 @@ var __awaiter$10 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9799
9809
|
};
|
|
9800
9810
|
|
|
9801
9811
|
//#endregion
|
|
9802
|
-
//#region
|
|
9812
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/oauth/client/Client.mjs
|
|
9803
9813
|
/**
|
|
9804
9814
|
* This file was auto-generated by Fern from our API Definition.
|
|
9805
9815
|
*/
|
|
@@ -9832,7 +9842,7 @@ var __awaiter$9 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9832
9842
|
};
|
|
9833
9843
|
|
|
9834
9844
|
//#endregion
|
|
9835
|
-
//#region
|
|
9845
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/googleCloudOauth/client/Client.mjs
|
|
9836
9846
|
/**
|
|
9837
9847
|
* This file was auto-generated by Fern from our API Definition.
|
|
9838
9848
|
*/
|
|
@@ -9865,7 +9875,7 @@ var __awaiter$8 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9865
9875
|
};
|
|
9866
9876
|
|
|
9867
9877
|
//#endregion
|
|
9868
|
-
//#region
|
|
9878
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/googleFormsOauth/client/Client.mjs
|
|
9869
9879
|
/**
|
|
9870
9880
|
* This file was auto-generated by Fern from our API Definition.
|
|
9871
9881
|
*/
|
|
@@ -9898,7 +9908,7 @@ var __awaiter$7 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9898
9908
|
};
|
|
9899
9909
|
|
|
9900
9910
|
//#endregion
|
|
9901
|
-
//#region
|
|
9911
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/onedriveOauth/client/Client.mjs
|
|
9902
9912
|
/**
|
|
9903
9913
|
* This file was auto-generated by Fern from our API Definition.
|
|
9904
9914
|
*/
|
|
@@ -9931,7 +9941,7 @@ var __awaiter$6 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9931
9941
|
};
|
|
9932
9942
|
|
|
9933
9943
|
//#endregion
|
|
9934
|
-
//#region
|
|
9944
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/outlookOauth/client/Client.mjs
|
|
9935
9945
|
/**
|
|
9936
9946
|
* This file was auto-generated by Fern from our API Definition.
|
|
9937
9947
|
*/
|
|
@@ -9964,7 +9974,7 @@ var __awaiter$5 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9964
9974
|
};
|
|
9965
9975
|
|
|
9966
9976
|
//#endregion
|
|
9967
|
-
//#region
|
|
9977
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/mscalendarOauth/client/Client.mjs
|
|
9968
9978
|
/**
|
|
9969
9979
|
* This file was auto-generated by Fern from our API Definition.
|
|
9970
9980
|
*/
|
|
@@ -9997,7 +10007,7 @@ var __awaiter$4 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
9997
10007
|
};
|
|
9998
10008
|
|
|
9999
10009
|
//#endregion
|
|
10000
|
-
//#region
|
|
10010
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/teamsOauth/client/Client.mjs
|
|
10001
10011
|
/**
|
|
10002
10012
|
* This file was auto-generated by Fern from our API Definition.
|
|
10003
10013
|
*/
|
|
@@ -10030,7 +10040,7 @@ var __awaiter$3 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
10030
10040
|
};
|
|
10031
10041
|
|
|
10032
10042
|
//#endregion
|
|
10033
|
-
//#region
|
|
10043
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/zoomOauth/client/Client.mjs
|
|
10034
10044
|
/**
|
|
10035
10045
|
* This file was auto-generated by Fern from our API Definition.
|
|
10036
10046
|
*/
|
|
@@ -10063,7 +10073,7 @@ var __awaiter$2 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
10063
10073
|
};
|
|
10064
10074
|
|
|
10065
10075
|
//#endregion
|
|
10066
|
-
//#region
|
|
10076
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/sharesightOauth/client/Client.mjs
|
|
10067
10077
|
/**
|
|
10068
10078
|
* This file was auto-generated by Fern from our API Definition.
|
|
10069
10079
|
*/
|
|
@@ -10096,7 +10106,7 @@ var __awaiter$1 = void 0 && (void 0).__awaiter || function(thisArg, _arguments,
|
|
|
10096
10106
|
};
|
|
10097
10107
|
|
|
10098
10108
|
//#endregion
|
|
10099
|
-
//#region
|
|
10109
|
+
//#region node_modules/.pnpm/klavis@2.15.0/node_modules/klavis/dist/esm/api/resources/sandbox/client/Client.mjs
|
|
10100
10110
|
/**
|
|
10101
10111
|
* This file was auto-generated by Fern from our API Definition.
|
|
10102
10112
|
*/
|
|
@@ -10345,7 +10355,7 @@ const KLAVIS_SERVER_TYPES = [
|
|
|
10345
10355
|
|
|
10346
10356
|
//#endregion
|
|
10347
10357
|
//#region ../../package.json
|
|
10348
|
-
var version$3 = "2.2.
|
|
10358
|
+
var version$3 = "2.2.1";
|
|
10349
10359
|
|
|
10350
10360
|
//#endregion
|
|
10351
10361
|
//#region ../../packages/const/src/version.ts
|
|
@@ -11894,7 +11904,7 @@ const taskTemplates = [
|
|
|
11894
11904
|
const KNOWN_TASK_TEMPLATE_IDS = new Set(taskTemplates.map((t) => t.id));
|
|
11895
11905
|
|
|
11896
11906
|
//#endregion
|
|
11897
|
-
//#region
|
|
11907
|
+
//#region node_modules/.pnpm/url-join@5.0.0/node_modules/url-join/lib/url-join.js
|
|
11898
11908
|
function normalize(strArray) {
|
|
11899
11909
|
var resultArray = [];
|
|
11900
11910
|
if (strArray.length === 0) return "";
|
|
@@ -11943,7 +11953,7 @@ const TERMS_URL = urlJoin(OFFICIAL_SITE, "/terms");
|
|
|
11943
11953
|
const AGENTS_INDEX_GITHUB = "https://github.com/lobehub/lobe-chat-agents";
|
|
11944
11954
|
const AGENTS_INDEX_GITHUB_ISSUE = urlJoin(AGENTS_INDEX_GITHUB, "issues/new");
|
|
11945
11955
|
const RELEASES_URL = urlJoin(GITHUB, "releases");
|
|
11946
|
-
const CHANGELOG_URL = urlJoin(OFFICIAL_SITE, "changelog
|
|
11956
|
+
const CHANGELOG_URL = urlJoin(OFFICIAL_SITE, "changelog");
|
|
11947
11957
|
const DOWNLOAD_URL = {
|
|
11948
11958
|
android: "https://play.google.com/store/apps/details?id=com.lobehub.app",
|
|
11949
11959
|
default: urlJoin(OFFICIAL_SITE, "/downloads"),
|
|
@@ -18254,6 +18264,1206 @@ async function checkPlatformCapability(params) {
|
|
|
18254
18264
|
};
|
|
18255
18265
|
}
|
|
18256
18266
|
|
|
18267
|
+
//#endregion
|
|
18268
|
+
//#region src/tools/getAgentProfile.ts
|
|
18269
|
+
const IDENTITY_FILES$1 = ["IDENTITY.md", "SOUL.md"];
|
|
18270
|
+
/**
|
|
18271
|
+
* Try to extract a description from the workspace identity file.
|
|
18272
|
+
* Looks for Creature / Vibe / Description fields in IDENTITY.md or SOUL.md.
|
|
18273
|
+
*/
|
|
18274
|
+
function readDescriptionFromWorkspace(workspacePath) {
|
|
18275
|
+
for (const filename of IDENTITY_FILES$1) {
|
|
18276
|
+
const filePath = path.join(workspacePath, filename);
|
|
18277
|
+
if (!fs.existsSync(filePath)) continue;
|
|
18278
|
+
const match = fs.readFileSync(filePath, "utf8").match(/\*{0,2}(?:Creature|Vibe|Description):?\*{0,2}\s*(.+)/i);
|
|
18279
|
+
if (!match) continue;
|
|
18280
|
+
const value = match[1].trim();
|
|
18281
|
+
if (/^[_*((].*[))*_]$|^(?:tbd|todo|n\/?a|none|待定|未定)$/i.test(value)) continue;
|
|
18282
|
+
return value;
|
|
18283
|
+
}
|
|
18284
|
+
}
|
|
18285
|
+
function getOpenClawProfile(agentId) {
|
|
18286
|
+
let output;
|
|
18287
|
+
try {
|
|
18288
|
+
output = execFileSync("openclaw", [
|
|
18289
|
+
"agents",
|
|
18290
|
+
"list",
|
|
18291
|
+
"--json"
|
|
18292
|
+
], {
|
|
18293
|
+
encoding: "utf8",
|
|
18294
|
+
timeout: 5e3
|
|
18295
|
+
});
|
|
18296
|
+
} catch {
|
|
18297
|
+
return {};
|
|
18298
|
+
}
|
|
18299
|
+
let agents;
|
|
18300
|
+
try {
|
|
18301
|
+
agents = JSON.parse(output);
|
|
18302
|
+
} catch {
|
|
18303
|
+
return {};
|
|
18304
|
+
}
|
|
18305
|
+
const agent = agentId ? agents.find((a) => a.id === agentId) : agents.find((a) => a.isDefault) ?? agents[0];
|
|
18306
|
+
if (!agent) return {};
|
|
18307
|
+
const title = agent.identityName || void 0;
|
|
18308
|
+
return {
|
|
18309
|
+
avatar: agent.identityEmoji || "🦞",
|
|
18310
|
+
description: agent.workspace ? readDescriptionFromWorkspace(agent.workspace) : void 0,
|
|
18311
|
+
title
|
|
18312
|
+
};
|
|
18313
|
+
}
|
|
18314
|
+
/**
|
|
18315
|
+
* Read the active Hermes profile name from `hermes profile list` output.
|
|
18316
|
+
* The active profile is marked with ◆ in the first column.
|
|
18317
|
+
*/
|
|
18318
|
+
function getActiveHermesProfileName() {
|
|
18319
|
+
try {
|
|
18320
|
+
return execFileSync("hermes", ["profile", "list"], {
|
|
18321
|
+
encoding: "utf8",
|
|
18322
|
+
timeout: 5e3
|
|
18323
|
+
}).match(/◆(\S+)/)?.[1];
|
|
18324
|
+
} catch {
|
|
18325
|
+
return;
|
|
18326
|
+
}
|
|
18327
|
+
}
|
|
18328
|
+
/**
|
|
18329
|
+
* Read the filesystem path of a Hermes profile from `hermes profile show <name>`.
|
|
18330
|
+
*/
|
|
18331
|
+
function getHermesProfilePath(profileName) {
|
|
18332
|
+
try {
|
|
18333
|
+
return (execFileSync("hermes", [
|
|
18334
|
+
"profile",
|
|
18335
|
+
"show",
|
|
18336
|
+
profileName
|
|
18337
|
+
], {
|
|
18338
|
+
encoding: "utf8",
|
|
18339
|
+
timeout: 5e3
|
|
18340
|
+
}).match(/^Path:\s+(.+)/m)?.[1]?.trim())?.replace(/^~(?=\/|$)/, os.homedir());
|
|
18341
|
+
} catch {
|
|
18342
|
+
return;
|
|
18343
|
+
}
|
|
18344
|
+
}
|
|
18345
|
+
/**
|
|
18346
|
+
* Extract a one-line description from a Hermes SOUL.md file.
|
|
18347
|
+
* Strips HTML comments and Markdown headings, then returns the first
|
|
18348
|
+
* non-empty line of actual content.
|
|
18349
|
+
*/
|
|
18350
|
+
function readHermesSoulDescription(soulPath) {
|
|
18351
|
+
try {
|
|
18352
|
+
let stripped = fs.readFileSync(soulPath, "utf8");
|
|
18353
|
+
let previous;
|
|
18354
|
+
do {
|
|
18355
|
+
previous = stripped;
|
|
18356
|
+
stripped = stripped.replaceAll(/<!--[\s\S]*?-->/g, "").replaceAll(/[<>]/g, "").replaceAll(/^#+\s.*$/gm, "");
|
|
18357
|
+
} while (stripped !== previous);
|
|
18358
|
+
return stripped.split("\n").map((l) => l.trim()).find((l) => l.length > 0) || void 0;
|
|
18359
|
+
} catch {
|
|
18360
|
+
return;
|
|
18361
|
+
}
|
|
18362
|
+
}
|
|
18363
|
+
function getHermesProfile() {
|
|
18364
|
+
const profileName = getActiveHermesProfileName();
|
|
18365
|
+
if (!profileName) return {};
|
|
18366
|
+
const profilePath = getHermesProfilePath(profileName);
|
|
18367
|
+
return {
|
|
18368
|
+
avatar: "⚡",
|
|
18369
|
+
description: profilePath ? readHermesSoulDescription(path.join(profilePath, "SOUL.md")) : void 0,
|
|
18370
|
+
title: profileName
|
|
18371
|
+
};
|
|
18372
|
+
}
|
|
18373
|
+
/**
|
|
18374
|
+
* Fetch the agent profile (title, avatar, description) from the platform
|
|
18375
|
+
* installed on this device. Dispatched by the server via `device.getAgentProfile`.
|
|
18376
|
+
*
|
|
18377
|
+
* - openclaw: `openclaw agents list --json` for name + emoji, workspace
|
|
18378
|
+
* IDENTITY.md for description fallback
|
|
18379
|
+
* - hermes: active profile name + SOUL.md description
|
|
18380
|
+
*/
|
|
18381
|
+
async function getAgentProfile(params) {
|
|
18382
|
+
const { platform, agentId } = params;
|
|
18383
|
+
if (platform === "openclaw") return getOpenClawProfile(agentId);
|
|
18384
|
+
if (platform === "hermes") return getHermesProfile();
|
|
18385
|
+
return {};
|
|
18386
|
+
}
|
|
18387
|
+
|
|
18388
|
+
//#endregion
|
|
18389
|
+
//#region src/daemon/taskRegistry.ts
|
|
18390
|
+
function getRegistryPath() {
|
|
18391
|
+
return path.join(os.homedir(), ".lobehub", "task-registry.json");
|
|
18392
|
+
}
|
|
18393
|
+
function readRegistry() {
|
|
18394
|
+
try {
|
|
18395
|
+
return JSON.parse(fs.readFileSync(getRegistryPath(), "utf8"));
|
|
18396
|
+
} catch {
|
|
18397
|
+
return {};
|
|
18398
|
+
}
|
|
18399
|
+
}
|
|
18400
|
+
function writeRegistry(entries) {
|
|
18401
|
+
const dir = path.dirname(getRegistryPath());
|
|
18402
|
+
fs.mkdirSync(dir, {
|
|
18403
|
+
mode: 448,
|
|
18404
|
+
recursive: true
|
|
18405
|
+
});
|
|
18406
|
+
fs.writeFileSync(getRegistryPath(), JSON.stringify(entries, null, 2), { mode: 384 });
|
|
18407
|
+
}
|
|
18408
|
+
function saveTask(entry) {
|
|
18409
|
+
const registry = readRegistry();
|
|
18410
|
+
registry[entry.taskId] = entry;
|
|
18411
|
+
writeRegistry(registry);
|
|
18412
|
+
}
|
|
18413
|
+
function getTask(taskId) {
|
|
18414
|
+
return readRegistry()[taskId];
|
|
18415
|
+
}
|
|
18416
|
+
function removeTask(taskId) {
|
|
18417
|
+
const registry = readRegistry();
|
|
18418
|
+
delete registry[taskId];
|
|
18419
|
+
writeRegistry(registry);
|
|
18420
|
+
}
|
|
18421
|
+
function listTasks() {
|
|
18422
|
+
return Object.values(readRegistry());
|
|
18423
|
+
}
|
|
18424
|
+
|
|
18425
|
+
//#endregion
|
|
18426
|
+
//#region src/tools/heteroTask.ts
|
|
18427
|
+
const LOBEHUB_DIR_NAME = process.env.LOBEHUB_CLI_HOME || ".lobehub";
|
|
18428
|
+
const HERMES_SESSIONS_FILE = path.join(os.homedir(), LOBEHUB_DIR_NAME, "hermes-sessions.json");
|
|
18429
|
+
function getHermesSessionId(topicId) {
|
|
18430
|
+
try {
|
|
18431
|
+
return JSON.parse(fs.readFileSync(HERMES_SESSIONS_FILE, "utf8"))[topicId];
|
|
18432
|
+
} catch {
|
|
18433
|
+
return;
|
|
18434
|
+
}
|
|
18435
|
+
}
|
|
18436
|
+
function saveHermesSessionId(topicId, sessionId) {
|
|
18437
|
+
let data = {};
|
|
18438
|
+
try {
|
|
18439
|
+
data = JSON.parse(fs.readFileSync(HERMES_SESSIONS_FILE, "utf8"));
|
|
18440
|
+
} catch {}
|
|
18441
|
+
data[topicId] = sessionId;
|
|
18442
|
+
fs.mkdirSync(path.dirname(HERMES_SESSIONS_FILE), { recursive: true });
|
|
18443
|
+
fs.writeFileSync(HERMES_SESSIONS_FILE, JSON.stringify(data), "utf8");
|
|
18444
|
+
}
|
|
18445
|
+
/** Resolve the absolute path to the `lh` binary to avoid PATH issues in child processes. */
|
|
18446
|
+
function resolveLhPath() {
|
|
18447
|
+
try {
|
|
18448
|
+
return execFileSync("which", ["lh"], { encoding: "utf8" }).trim();
|
|
18449
|
+
} catch {
|
|
18450
|
+
return "lh";
|
|
18451
|
+
}
|
|
18452
|
+
}
|
|
18453
|
+
async function sendAutoNotify(topicId, taskId, text, agentId) {
|
|
18454
|
+
try {
|
|
18455
|
+
await (await getTrpcClient()).agentNotify.notify.mutate({
|
|
18456
|
+
agentId,
|
|
18457
|
+
content: text,
|
|
18458
|
+
role: "assistant",
|
|
18459
|
+
topicId
|
|
18460
|
+
});
|
|
18461
|
+
} catch (err) {
|
|
18462
|
+
log$7.error("Failed to send auto-notify:", err instanceof Error ? err.message : String(err));
|
|
18463
|
+
}
|
|
18464
|
+
}
|
|
18465
|
+
/**
|
|
18466
|
+
* Signal remote hetero task completion to the server so it can publish
|
|
18467
|
+
* `agent_runtime_end` to the gateway WS and close the frontend subscription.
|
|
18468
|
+
* Called on clean process exit (code=0, no signal) — error exits go through
|
|
18469
|
+
* `sendAutoNotify` which writes an error message AND triggers completion via
|
|
18470
|
+
* the `done` flag.
|
|
18471
|
+
*/
|
|
18472
|
+
async function sendDoneSignal(topicId, agentId) {
|
|
18473
|
+
try {
|
|
18474
|
+
await (await getTrpcClient()).agentNotify.notify.mutate({
|
|
18475
|
+
agentId,
|
|
18476
|
+
content: "",
|
|
18477
|
+
done: true,
|
|
18478
|
+
role: "assistant",
|
|
18479
|
+
topicId
|
|
18480
|
+
});
|
|
18481
|
+
} catch (err) {
|
|
18482
|
+
log$7.error("Failed to send done signal:", err instanceof Error ? err.message : String(err));
|
|
18483
|
+
}
|
|
18484
|
+
}
|
|
18485
|
+
/**
|
|
18486
|
+
* Build the notify protocol injected into the first message of a new hetero-agent session.
|
|
18487
|
+
* Tells the agent how to push updates back to the LobeHub user via `lh notify`.
|
|
18488
|
+
*/
|
|
18489
|
+
function buildNotifyProtocol(lhPath, topicId) {
|
|
18490
|
+
return `## Context: This task was dispatched by LobeHub
|
|
18491
|
+
|
|
18492
|
+
This conversation / task was sent to you by the **LobeHub platform** on behalf of a user. You are running as a background agent; the user is waiting for your response inside the LobeHub chat interface.
|
|
18493
|
+
|
|
18494
|
+
**When to call notify**: any time you have something meaningful to tell the user — a key finding, a decision you made, a result, a question, or your final answer. Think of it as speaking directly to the user in the chat window.
|
|
18495
|
+
|
|
18496
|
+
**What to hide**: internal work details such as tool call sequences, file reads, intermediate command output, retries, or low-level reasoning steps. The user cares about outcomes and insights, not your step-by-step mechanics.
|
|
18497
|
+
|
|
18498
|
+
## Sending messages back to the user
|
|
18499
|
+
|
|
18500
|
+
Use the \`${lhPath} notify\` command. All your updates appear as a **single message bubble** in the UI — create it once and update it in place.\n\n**Step 1 — Open the bubble on your first meaningful update** (captures the messageId):\n\`\`\`\nMSG_ID=$(${lhPath} notify --topic ${topicId} --role assistant --content "Starting..." --json | grep -o '"messageId":"[^"]*"' | cut -d'"' -f4)\n\`\`\`\n\n**Step 2 — Update the same bubble as you make progress**:\n\`\`\`\n${lhPath} notify --topic ${topicId} --role assistant --message-id "$MSG_ID" --content "Still working..."\n\`\`\`\n\n**Step 3 — Replace with your complete, final response when done**:\n\`\`\`\n${lhPath} notify --topic ${topicId} --role assistant --message-id "$MSG_ID" --content "<your full response here>"\n\`\`\`\n\nRules:\n- Always use \`--json\` on the first call and capture \`messageId\` from the output.\n- Always pass \`--message-id\` on every subsequent call so updates overwrite the same bubble.\n- Write what matters to the user — not implementation steps or internal tool calls.\n- Call notify at least once when the task is done, even if there were no intermediate updates.`;
|
|
18501
|
+
}
|
|
18502
|
+
async function runHeteroTask(params) {
|
|
18503
|
+
const { agentId, agentType, cwd, operationId, prompt, taskId, topicId } = params;
|
|
18504
|
+
const workDir = cwd || process.cwd();
|
|
18505
|
+
const lhPath = resolveLhPath();
|
|
18506
|
+
if (agentType === "openclaw") {
|
|
18507
|
+
const openclawAgent = process.env.OPENCLAW_AGENT_ID ?? "main";
|
|
18508
|
+
const enrichedPrompt = `${prompt}\n\n${buildNotifyProtocol(lhPath, topicId)}`;
|
|
18509
|
+
for (const existing of listTasks()) if (existing.topicId === topicId && existing.agentType === "openclaw") {
|
|
18510
|
+
try {
|
|
18511
|
+
process.kill(existing.pid, "SIGTERM");
|
|
18512
|
+
} catch {}
|
|
18513
|
+
removeTask(existing.taskId);
|
|
18514
|
+
}
|
|
18515
|
+
const child = spawn("openclaw", [
|
|
18516
|
+
"agent",
|
|
18517
|
+
"--agent",
|
|
18518
|
+
openclawAgent,
|
|
18519
|
+
"--session-id",
|
|
18520
|
+
topicId,
|
|
18521
|
+
"--message",
|
|
18522
|
+
enrichedPrompt,
|
|
18523
|
+
"--local"
|
|
18524
|
+
], {
|
|
18525
|
+
cwd: workDir,
|
|
18526
|
+
detached: true,
|
|
18527
|
+
env: { ...process.env },
|
|
18528
|
+
stdio: "ignore"
|
|
18529
|
+
});
|
|
18530
|
+
const pid = child.pid;
|
|
18531
|
+
if (pid === void 0) throw new Error("Failed to get PID for openclaw process");
|
|
18532
|
+
child.unref();
|
|
18533
|
+
saveTask({
|
|
18534
|
+
agentId,
|
|
18535
|
+
agentType,
|
|
18536
|
+
operationId,
|
|
18537
|
+
pid,
|
|
18538
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18539
|
+
taskId,
|
|
18540
|
+
topicId
|
|
18541
|
+
});
|
|
18542
|
+
log$7.info(`OpenClaw task started: taskId=${taskId} pid=${pid} agent=${openclawAgent}`);
|
|
18543
|
+
child.on("close", (code, signal) => {
|
|
18544
|
+
removeTask(taskId);
|
|
18545
|
+
if (code !== 0 || signal !== null) sendAutoNotify(topicId, taskId, signal ? `Task cancelled (signal: ${signal})` : `Task failed (exit code: ${code})`, agentId).finally(() => sendDoneSignal(topicId, agentId));
|
|
18546
|
+
else sendDoneSignal(topicId, agentId);
|
|
18547
|
+
});
|
|
18548
|
+
return JSON.stringify({
|
|
18549
|
+
pid,
|
|
18550
|
+
taskId
|
|
18551
|
+
});
|
|
18552
|
+
}
|
|
18553
|
+
if (agentType === "hermes") {
|
|
18554
|
+
for (const existing of listTasks()) if (existing.topicId === topicId && existing.agentType === "hermes") {
|
|
18555
|
+
try {
|
|
18556
|
+
process.kill(existing.pid, "SIGTERM");
|
|
18557
|
+
} catch {}
|
|
18558
|
+
removeTask(existing.taskId);
|
|
18559
|
+
}
|
|
18560
|
+
const existingSessionId = getHermesSessionId(topicId);
|
|
18561
|
+
const hermesArgs = [
|
|
18562
|
+
"chat",
|
|
18563
|
+
"--query",
|
|
18564
|
+
prompt,
|
|
18565
|
+
"--quiet",
|
|
18566
|
+
"--accept-hooks"
|
|
18567
|
+
];
|
|
18568
|
+
if (existingSessionId) hermesArgs.push("--resume", existingSessionId);
|
|
18569
|
+
const child = spawn("hermes", hermesArgs, {
|
|
18570
|
+
cwd: workDir,
|
|
18571
|
+
detached: true,
|
|
18572
|
+
env: { ...process.env },
|
|
18573
|
+
stdio: [
|
|
18574
|
+
"ignore",
|
|
18575
|
+
"pipe",
|
|
18576
|
+
"ignore"
|
|
18577
|
+
]
|
|
18578
|
+
});
|
|
18579
|
+
const pid = child.pid;
|
|
18580
|
+
if (pid === void 0) throw new Error("Failed to get PID for hermes process");
|
|
18581
|
+
child.unref();
|
|
18582
|
+
saveTask({
|
|
18583
|
+
agentId,
|
|
18584
|
+
agentType,
|
|
18585
|
+
operationId,
|
|
18586
|
+
pid,
|
|
18587
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18588
|
+
taskId,
|
|
18589
|
+
topicId
|
|
18590
|
+
});
|
|
18591
|
+
log$7.info(`Hermes task started: taskId=${taskId} pid=${pid}`);
|
|
18592
|
+
let stdout = "";
|
|
18593
|
+
child.stdout.on("data", (chunk) => {
|
|
18594
|
+
stdout += chunk.toString();
|
|
18595
|
+
});
|
|
18596
|
+
child.on("close", (code, signal) => {
|
|
18597
|
+
removeTask(taskId);
|
|
18598
|
+
if (code !== 0 || signal !== null) {
|
|
18599
|
+
sendAutoNotify(topicId, taskId, signal ? `Task cancelled (signal: ${signal})` : `Task failed (exit code: ${code})`, agentId).finally(() => sendDoneSignal(topicId, agentId));
|
|
18600
|
+
return;
|
|
18601
|
+
}
|
|
18602
|
+
const sessionId = stdout.match(/^session_id:\s*(\S+)/m)?.[1];
|
|
18603
|
+
const response = stdout.replace(/^session_id:[^\n]*\n?/, "").trim();
|
|
18604
|
+
if (sessionId) saveHermesSessionId(topicId, sessionId);
|
|
18605
|
+
if (response) sendAutoNotify(topicId, taskId, response, agentId).finally(() => sendDoneSignal(topicId, agentId));
|
|
18606
|
+
else sendDoneSignal(topicId, agentId);
|
|
18607
|
+
});
|
|
18608
|
+
return JSON.stringify({
|
|
18609
|
+
pid,
|
|
18610
|
+
taskId
|
|
18611
|
+
});
|
|
18612
|
+
}
|
|
18613
|
+
throw new Error(`Unsupported agentType: ${agentType}`);
|
|
18614
|
+
}
|
|
18615
|
+
async function cancelHeteroTask(params) {
|
|
18616
|
+
const { signal = "SIGINT", taskId } = params;
|
|
18617
|
+
const entry = getTask(taskId);
|
|
18618
|
+
if (!entry) return JSON.stringify({
|
|
18619
|
+
message: `No task found with taskId: ${taskId}`,
|
|
18620
|
+
success: false
|
|
18621
|
+
});
|
|
18622
|
+
try {
|
|
18623
|
+
process.kill(entry.pid, signal);
|
|
18624
|
+
} catch (err) {
|
|
18625
|
+
log$7.warn(`Failed to send ${signal} to pid ${entry.pid}: ${err instanceof Error ? err.message : String(err)}`);
|
|
18626
|
+
removeTask(taskId);
|
|
18627
|
+
await sendAutoNotify(entry.topicId, taskId, "Task already completed or cancelled", entry.agentId);
|
|
18628
|
+
}
|
|
18629
|
+
return JSON.stringify({
|
|
18630
|
+
pid: entry.pid,
|
|
18631
|
+
signal,
|
|
18632
|
+
taskId
|
|
18633
|
+
});
|
|
18634
|
+
}
|
|
18635
|
+
|
|
18636
|
+
//#endregion
|
|
18637
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatCommandOutput.ts
|
|
18638
|
+
var formatCommandOutput;
|
|
18639
|
+
var init_formatCommandOutput = __esmMin((() => {
|
|
18640
|
+
formatCommandOutput = ({ success, exitCode, output, error }) => {
|
|
18641
|
+
const parts = [success ? "Output retrieved." : `Failed: ${error}`];
|
|
18642
|
+
if (exitCode !== void 0) parts.push(`Exit code: ${exitCode}`);
|
|
18643
|
+
if (output) parts.push(`Output:\n${output}`);
|
|
18644
|
+
if (error && success) parts.push(`Error: ${error}`);
|
|
18645
|
+
return parts.join("\n\n");
|
|
18646
|
+
};
|
|
18647
|
+
}));
|
|
18648
|
+
|
|
18649
|
+
//#endregion
|
|
18650
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatCommandResult.ts
|
|
18651
|
+
var formatCommandResult;
|
|
18652
|
+
var init_formatCommandResult = __esmMin((() => {
|
|
18653
|
+
formatCommandResult = ({ success, shellId, error, stdout, stderr, exitCode }) => {
|
|
18654
|
+
const parts = [];
|
|
18655
|
+
const hasNonZeroExit = exitCode !== void 0 && exitCode !== 0;
|
|
18656
|
+
if (!success || hasNonZeroExit) {
|
|
18657
|
+
let header = "Command failed";
|
|
18658
|
+
if (hasNonZeroExit) header += ` with exit code ${exitCode}`;
|
|
18659
|
+
if (error) header += `: ${error}`;
|
|
18660
|
+
parts.push(header);
|
|
18661
|
+
} else if (shellId) parts.push(`Command started in background with shell_id: ${shellId}`);
|
|
18662
|
+
else parts.push("Command completed successfully.");
|
|
18663
|
+
if (stdout) parts.push(`Output:\n${stdout}`);
|
|
18664
|
+
if (stderr) parts.push(`Stderr:\n${stderr}`);
|
|
18665
|
+
return parts.join("\n\n");
|
|
18666
|
+
};
|
|
18667
|
+
}));
|
|
18668
|
+
|
|
18669
|
+
//#endregion
|
|
18670
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatEditResult.ts
|
|
18671
|
+
var formatEditResult;
|
|
18672
|
+
var init_formatEditResult = __esmMin((() => {
|
|
18673
|
+
formatEditResult = ({ replacements, filePath, linesAdded, linesDeleted }) => {
|
|
18674
|
+
return `Successfully replaced ${replacements} occurrence(s) in ${filePath}${linesAdded || linesDeleted ? ` (+${linesAdded || 0} -${linesDeleted || 0})` : ""}`;
|
|
18675
|
+
};
|
|
18676
|
+
}));
|
|
18677
|
+
|
|
18678
|
+
//#endregion
|
|
18679
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatFileContent.ts
|
|
18680
|
+
var formatFileContent;
|
|
18681
|
+
var init_formatFileContent = __esmMin((() => {
|
|
18682
|
+
formatFileContent = ({ path, content, lineRange }) => {
|
|
18683
|
+
return `File: ${path}${lineRange ? ` (lines ${lineRange[0]}-${lineRange[1]})` : ""}\n\n${content}`;
|
|
18684
|
+
};
|
|
18685
|
+
}));
|
|
18686
|
+
|
|
18687
|
+
//#endregion
|
|
18688
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatFileList.ts
|
|
18689
|
+
var formatFileSize, formatDate, formatFileList;
|
|
18690
|
+
var init_formatFileList = __esmMin((() => {
|
|
18691
|
+
formatFileSize = (bytes) => {
|
|
18692
|
+
if (bytes === 0) return "0 B";
|
|
18693
|
+
const k = 1024;
|
|
18694
|
+
const sizes = [
|
|
18695
|
+
"B",
|
|
18696
|
+
"KB",
|
|
18697
|
+
"MB",
|
|
18698
|
+
"GB",
|
|
18699
|
+
"TB"
|
|
18700
|
+
];
|
|
18701
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
18702
|
+
return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
18703
|
+
};
|
|
18704
|
+
formatDate = (date) => {
|
|
18705
|
+
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
18706
|
+
};
|
|
18707
|
+
formatFileList = ({ files, directory, sortBy, sortOrder, totalCount: totalCountParam }) => {
|
|
18708
|
+
if (files.length === 0) return `Directory ${directory} is empty`;
|
|
18709
|
+
const hasExtendedInfo = files.some((f) => f.size !== void 0 || f.modifiedTime !== void 0);
|
|
18710
|
+
const totalCount = totalCountParam ?? files.length;
|
|
18711
|
+
const isTruncated = totalCount > files.length;
|
|
18712
|
+
let header = `Found ${totalCount} item(s) in ${directory}`;
|
|
18713
|
+
const parts = [];
|
|
18714
|
+
if (isTruncated) parts.push(`showing first ${files.length}`);
|
|
18715
|
+
if (sortBy) parts.push(`sorted by ${sortBy} ${sortOrder || "desc"}`);
|
|
18716
|
+
if (parts.length > 0) header += ` (${parts.join(", ")})`;
|
|
18717
|
+
const fileList = files.map((f) => {
|
|
18718
|
+
const prefix = f.isDirectory ? "[D]" : "[F]";
|
|
18719
|
+
const name = f.name;
|
|
18720
|
+
if (hasExtendedInfo) {
|
|
18721
|
+
const date = f.modifiedTime ? formatDate(f.modifiedTime) : " ";
|
|
18722
|
+
const size = f.isDirectory ? " --" : f.size !== void 0 ? formatFileSize(f.size).padStart(10) : " ";
|
|
18723
|
+
return ` ${prefix} ${name.padEnd(40)} ${date} ${size}`;
|
|
18724
|
+
}
|
|
18725
|
+
return ` ${prefix} ${name}`;
|
|
18726
|
+
}).join("\n");
|
|
18727
|
+
return `${header}:\n${fileList}`;
|
|
18728
|
+
};
|
|
18729
|
+
}));
|
|
18730
|
+
|
|
18731
|
+
//#endregion
|
|
18732
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatFileSearchResults.ts
|
|
18733
|
+
var formatFileSearchResults;
|
|
18734
|
+
var init_formatFileSearchResults = __esmMin((() => {
|
|
18735
|
+
formatFileSearchResults = (results) => {
|
|
18736
|
+
if (results.length === 0) return "No files found";
|
|
18737
|
+
const fileList = results.map((f) => ` ${f.path}`).join("\n");
|
|
18738
|
+
return `Found ${results.length} file(s):\n${fileList}`;
|
|
18739
|
+
};
|
|
18740
|
+
}));
|
|
18741
|
+
|
|
18742
|
+
//#endregion
|
|
18743
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatGlobResults.ts
|
|
18744
|
+
var formatGlobResults;
|
|
18745
|
+
var init_formatGlobResults = __esmMin((() => {
|
|
18746
|
+
formatGlobResults = ({ totalFiles, files, maxDisplay = 50 }) => {
|
|
18747
|
+
const message = `Found ${totalFiles} files`;
|
|
18748
|
+
if (files.length === 0) return message;
|
|
18749
|
+
return `${message}:\n${files.slice(0, maxDisplay).map((f) => ` ${f}`).join("\n")}${files.length > maxDisplay ? `\n ... and ${files.length - maxDisplay} more` : ""}`;
|
|
18750
|
+
};
|
|
18751
|
+
}));
|
|
18752
|
+
|
|
18753
|
+
//#endregion
|
|
18754
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatGrepResults.ts
|
|
18755
|
+
var formatGrepResults;
|
|
18756
|
+
var init_formatGrepResults = __esmMin((() => {
|
|
18757
|
+
formatGrepResults = ({ totalMatches, matches, maxDisplay = 20 }) => {
|
|
18758
|
+
const message = `Found ${totalMatches} matches in ${matches.length} locations`;
|
|
18759
|
+
if (matches.length === 0) return message;
|
|
18760
|
+
return `${message}:\n${matches.slice(0, maxDisplay).map((m) => {
|
|
18761
|
+
if (typeof m === "string") return ` ${m}`;
|
|
18762
|
+
const parts = [];
|
|
18763
|
+
if (m.path) parts.push(m.path);
|
|
18764
|
+
if (m.lineNumber !== void 0) parts.push(`:${m.lineNumber}`);
|
|
18765
|
+
if (m.content) if (parts.length > 0) parts.push(`: ${m.content}`);
|
|
18766
|
+
else parts.push(m.content);
|
|
18767
|
+
return ` ${parts.join("")}`;
|
|
18768
|
+
}).join("\n")}${matches.length > maxDisplay ? `\n ... and ${matches.length - maxDisplay} more` : ""}`;
|
|
18769
|
+
};
|
|
18770
|
+
}));
|
|
18771
|
+
|
|
18772
|
+
//#endregion
|
|
18773
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatKillResult.ts
|
|
18774
|
+
var formatKillResult;
|
|
18775
|
+
var init_formatKillResult = __esmMin((() => {
|
|
18776
|
+
formatKillResult = ({ success, shellId, error }) => {
|
|
18777
|
+
return success ? `Successfully killed shell: ${shellId}` : `Failed to kill shell: ${error}`;
|
|
18778
|
+
};
|
|
18779
|
+
}));
|
|
18780
|
+
|
|
18781
|
+
//#endregion
|
|
18782
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatMoveResults.ts
|
|
18783
|
+
var formatMoveResults;
|
|
18784
|
+
var init_formatMoveResults = __esmMin((() => {
|
|
18785
|
+
formatMoveResults = (results) => {
|
|
18786
|
+
const successCount = results.filter((r) => r.success).length;
|
|
18787
|
+
const failedCount = results.length - successCount;
|
|
18788
|
+
const allSucceeded = failedCount === 0;
|
|
18789
|
+
const allFailed = successCount === 0;
|
|
18790
|
+
if (allSucceeded) return `Successfully moved ${results.length} item(s).`;
|
|
18791
|
+
if (allFailed) return `Failed to move all ${results.length} item(s).`;
|
|
18792
|
+
return `Moved ${successCount} item(s) successfully. Failed to move ${failedCount} item(s).`;
|
|
18793
|
+
};
|
|
18794
|
+
}));
|
|
18795
|
+
|
|
18796
|
+
//#endregion
|
|
18797
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatMultipleFiles.ts
|
|
18798
|
+
var formatMultipleFiles;
|
|
18799
|
+
var init_formatMultipleFiles = __esmMin((() => {
|
|
18800
|
+
formatMultipleFiles = (files) => {
|
|
18801
|
+
const fileContents = files.map((f) => `=== ${f.filename} ===\n${f.content}`).join("\n\n");
|
|
18802
|
+
return `Read ${files.length} file(s):\n\n${fileContents}`;
|
|
18803
|
+
};
|
|
18804
|
+
}));
|
|
18805
|
+
|
|
18806
|
+
//#endregion
|
|
18807
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatRenameResult.ts
|
|
18808
|
+
var formatRenameResult;
|
|
18809
|
+
var init_formatRenameResult = __esmMin((() => {
|
|
18810
|
+
formatRenameResult = ({ success, oldPath, newName, error }) => {
|
|
18811
|
+
return success ? `Successfully renamed file ${oldPath} to ${newName}` : `Failed to rename file: ${error}`;
|
|
18812
|
+
};
|
|
18813
|
+
}));
|
|
18814
|
+
|
|
18815
|
+
//#endregion
|
|
18816
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/formatWriteResult.ts
|
|
18817
|
+
var formatWriteResult;
|
|
18818
|
+
var init_formatWriteResult = __esmMin((() => {
|
|
18819
|
+
formatWriteResult = ({ success, path, error }) => {
|
|
18820
|
+
return success ? `Successfully wrote to ${path}` : `Failed to write file: ${error || "Unknown error"}`;
|
|
18821
|
+
};
|
|
18822
|
+
}));
|
|
18823
|
+
|
|
18824
|
+
//#endregion
|
|
18825
|
+
//#region ../../packages/prompts/src/prompts/fileSystem/index.ts
|
|
18826
|
+
var fileSystem_exports = /* @__PURE__ */ __exportAll({
|
|
18827
|
+
formatCommandOutput: () => formatCommandOutput,
|
|
18828
|
+
formatCommandResult: () => formatCommandResult,
|
|
18829
|
+
formatEditResult: () => formatEditResult,
|
|
18830
|
+
formatFileContent: () => formatFileContent,
|
|
18831
|
+
formatFileList: () => formatFileList,
|
|
18832
|
+
formatFileSearchResults: () => formatFileSearchResults,
|
|
18833
|
+
formatGlobResults: () => formatGlobResults,
|
|
18834
|
+
formatGrepResults: () => formatGrepResults,
|
|
18835
|
+
formatKillResult: () => formatKillResult,
|
|
18836
|
+
formatMoveResults: () => formatMoveResults,
|
|
18837
|
+
formatMultipleFiles: () => formatMultipleFiles,
|
|
18838
|
+
formatRenameResult: () => formatRenameResult,
|
|
18839
|
+
formatWriteResult: () => formatWriteResult
|
|
18840
|
+
});
|
|
18841
|
+
var init_fileSystem = __esmMin((() => {
|
|
18842
|
+
init_formatCommandOutput();
|
|
18843
|
+
init_formatCommandResult();
|
|
18844
|
+
init_formatEditResult();
|
|
18845
|
+
init_formatFileContent();
|
|
18846
|
+
init_formatFileList();
|
|
18847
|
+
init_formatFileSearchResults();
|
|
18848
|
+
init_formatGlobResults();
|
|
18849
|
+
init_formatGrepResults();
|
|
18850
|
+
init_formatKillResult();
|
|
18851
|
+
init_formatMoveResults();
|
|
18852
|
+
init_formatMultipleFiles();
|
|
18853
|
+
init_formatRenameResult();
|
|
18854
|
+
init_formatWriteResult();
|
|
18855
|
+
}));
|
|
18856
|
+
|
|
18857
|
+
//#endregion
|
|
18858
|
+
//#region ../../packages/tool-runtime/src/ComputerRuntime.ts
|
|
18859
|
+
init_fileSystem();
|
|
18860
|
+
/**
|
|
18861
|
+
* ComputerRuntime — abstract base for computer operations (file system, shell, search).
|
|
18862
|
+
*
|
|
18863
|
+
* Subclasses implement `callService` to delegate to their specific backend
|
|
18864
|
+
* (Electron IPC, cloud sandbox API, etc.). The base class handles:
|
|
18865
|
+
* - Normalizing raw results into formatted content via `@lobechat/prompts`
|
|
18866
|
+
* - Building consistent state objects for UI rendering
|
|
18867
|
+
*/
|
|
18868
|
+
var ComputerRuntime = class {
|
|
18869
|
+
async listFiles(args) {
|
|
18870
|
+
try {
|
|
18871
|
+
const result = await this.callService("listLocalFiles", args);
|
|
18872
|
+
if (!result.success) return this.errorOutput(result, {
|
|
18873
|
+
files: [],
|
|
18874
|
+
totalCount: 0
|
|
18875
|
+
});
|
|
18876
|
+
const files = result.result?.files || [];
|
|
18877
|
+
const totalCount = result.result?.totalCount;
|
|
18878
|
+
const state = {
|
|
18879
|
+
files,
|
|
18880
|
+
totalCount
|
|
18881
|
+
};
|
|
18882
|
+
return {
|
|
18883
|
+
content: formatFileList({
|
|
18884
|
+
directory: args.path,
|
|
18885
|
+
files: files.map((f) => ({
|
|
18886
|
+
isDirectory: f.isDirectory,
|
|
18887
|
+
name: f.name
|
|
18888
|
+
})),
|
|
18889
|
+
sortBy: args.sortBy,
|
|
18890
|
+
sortOrder: args.sortOrder,
|
|
18891
|
+
totalCount
|
|
18892
|
+
}),
|
|
18893
|
+
state,
|
|
18894
|
+
success: true
|
|
18895
|
+
};
|
|
18896
|
+
} catch (error) {
|
|
18897
|
+
return this.handleError(error);
|
|
18898
|
+
}
|
|
18899
|
+
}
|
|
18900
|
+
async readFile(args) {
|
|
18901
|
+
try {
|
|
18902
|
+
const result = await this.callService("readLocalFile", args);
|
|
18903
|
+
if (!result.success) return this.errorOutput(result, {
|
|
18904
|
+
content: "",
|
|
18905
|
+
endLine: args.loc?.[1],
|
|
18906
|
+
path: args.path,
|
|
18907
|
+
startLine: args.loc?.[0]
|
|
18908
|
+
});
|
|
18909
|
+
const r = result.result || {};
|
|
18910
|
+
const fileContent = r.content || "";
|
|
18911
|
+
const state = {
|
|
18912
|
+
charCount: r.charCount ?? fileContent.length,
|
|
18913
|
+
content: fileContent,
|
|
18914
|
+
endLine: args.loc?.[1],
|
|
18915
|
+
fileType: r.fileType,
|
|
18916
|
+
filename: r.filename,
|
|
18917
|
+
loc: r.loc,
|
|
18918
|
+
path: args.path,
|
|
18919
|
+
startLine: args.loc?.[0],
|
|
18920
|
+
totalCharCount: r.totalCharCount,
|
|
18921
|
+
totalLines: r.totalLineCount ?? r.totalLines
|
|
18922
|
+
};
|
|
18923
|
+
return {
|
|
18924
|
+
content: formatFileContent({
|
|
18925
|
+
content: fileContent,
|
|
18926
|
+
lineRange: args.loc,
|
|
18927
|
+
path: args.path
|
|
18928
|
+
}),
|
|
18929
|
+
state,
|
|
18930
|
+
success: true
|
|
18931
|
+
};
|
|
18932
|
+
} catch (error) {
|
|
18933
|
+
return this.handleError(error);
|
|
18934
|
+
}
|
|
18935
|
+
}
|
|
18936
|
+
async writeFile(args) {
|
|
18937
|
+
try {
|
|
18938
|
+
const result = await this.callService("writeLocalFile", args);
|
|
18939
|
+
if (!result.success) return this.errorOutput(result, {
|
|
18940
|
+
path: args.path,
|
|
18941
|
+
success: false
|
|
18942
|
+
});
|
|
18943
|
+
const state = {
|
|
18944
|
+
bytesWritten: result.result?.bytesWritten,
|
|
18945
|
+
path: args.path,
|
|
18946
|
+
success: true
|
|
18947
|
+
};
|
|
18948
|
+
return {
|
|
18949
|
+
content: formatWriteResult({
|
|
18950
|
+
path: args.path,
|
|
18951
|
+
success: true
|
|
18952
|
+
}),
|
|
18953
|
+
state,
|
|
18954
|
+
success: true
|
|
18955
|
+
};
|
|
18956
|
+
} catch (error) {
|
|
18957
|
+
return this.handleError(error);
|
|
18958
|
+
}
|
|
18959
|
+
}
|
|
18960
|
+
async editFile(args) {
|
|
18961
|
+
try {
|
|
18962
|
+
const result = await this.callService("editLocalFile", args);
|
|
18963
|
+
if (!result.success) return this.errorOutput(result, {
|
|
18964
|
+
path: args.file_path,
|
|
18965
|
+
replacements: 0
|
|
18966
|
+
});
|
|
18967
|
+
const state = {
|
|
18968
|
+
diffText: result.result?.diffText,
|
|
18969
|
+
linesAdded: result.result?.linesAdded,
|
|
18970
|
+
linesDeleted: result.result?.linesDeleted,
|
|
18971
|
+
path: args.file_path,
|
|
18972
|
+
replacements: result.result?.replacements || 0
|
|
18973
|
+
};
|
|
18974
|
+
return {
|
|
18975
|
+
content: formatEditResult({
|
|
18976
|
+
filePath: args.file_path,
|
|
18977
|
+
linesAdded: state.linesAdded,
|
|
18978
|
+
linesDeleted: state.linesDeleted,
|
|
18979
|
+
replacements: state.replacements
|
|
18980
|
+
}),
|
|
18981
|
+
state,
|
|
18982
|
+
success: true
|
|
18983
|
+
};
|
|
18984
|
+
} catch (error) {
|
|
18985
|
+
return this.handleError(error);
|
|
18986
|
+
}
|
|
18987
|
+
}
|
|
18988
|
+
async searchFiles(args) {
|
|
18989
|
+
try {
|
|
18990
|
+
const result = await this.callService("searchLocalFiles", args);
|
|
18991
|
+
if (!result.success) return this.errorOutput(result, {
|
|
18992
|
+
results: [],
|
|
18993
|
+
totalCount: 0
|
|
18994
|
+
});
|
|
18995
|
+
const rawResults = result.result?.results || result.result;
|
|
18996
|
+
const results = Array.isArray(rawResults) ? rawResults : [];
|
|
18997
|
+
const state = {
|
|
18998
|
+
results,
|
|
18999
|
+
totalCount: result.result?.totalCount || results.length
|
|
19000
|
+
};
|
|
19001
|
+
return {
|
|
19002
|
+
content: formatFileSearchResults(results.map((r) => ({ path: r.path }))),
|
|
19003
|
+
state,
|
|
19004
|
+
success: true
|
|
19005
|
+
};
|
|
19006
|
+
} catch (error) {
|
|
19007
|
+
return this.handleError(error);
|
|
19008
|
+
}
|
|
19009
|
+
}
|
|
19010
|
+
async moveFiles(args) {
|
|
19011
|
+
try {
|
|
19012
|
+
const result = await this.callService("moveLocalFiles", args);
|
|
19013
|
+
if (!result.success) return this.errorOutput(result, {
|
|
19014
|
+
results: [],
|
|
19015
|
+
successCount: 0,
|
|
19016
|
+
totalCount: args.items.length
|
|
19017
|
+
});
|
|
19018
|
+
const rawResults = result.result?.results || result.result;
|
|
19019
|
+
const results = Array.isArray(rawResults) ? rawResults : [];
|
|
19020
|
+
const state = {
|
|
19021
|
+
results,
|
|
19022
|
+
successCount: result.result?.successCount ?? results.filter((r) => r.success).length,
|
|
19023
|
+
totalCount: args.items.length
|
|
19024
|
+
};
|
|
19025
|
+
return {
|
|
19026
|
+
content: formatMoveResults(results),
|
|
19027
|
+
state,
|
|
19028
|
+
success: true
|
|
19029
|
+
};
|
|
19030
|
+
} catch (error) {
|
|
19031
|
+
return this.handleError(error);
|
|
19032
|
+
}
|
|
19033
|
+
}
|
|
19034
|
+
async renameFile(args) {
|
|
19035
|
+
try {
|
|
19036
|
+
const result = await this.callService("renameLocalFile", args);
|
|
19037
|
+
if (!result.success) {
|
|
19038
|
+
const errorMsg = result.error?.message || result.result?.error;
|
|
19039
|
+
return {
|
|
19040
|
+
content: formatRenameResult({
|
|
19041
|
+
error: errorMsg,
|
|
19042
|
+
newName: args.newName,
|
|
19043
|
+
oldPath: args.oldPath,
|
|
19044
|
+
success: false
|
|
19045
|
+
}),
|
|
19046
|
+
state: {
|
|
19047
|
+
error: errorMsg,
|
|
19048
|
+
newPath: "",
|
|
19049
|
+
oldPath: args.oldPath,
|
|
19050
|
+
success: false
|
|
19051
|
+
},
|
|
19052
|
+
success: true
|
|
19053
|
+
};
|
|
19054
|
+
}
|
|
19055
|
+
const state = {
|
|
19056
|
+
error: result.result?.error,
|
|
19057
|
+
newPath: result.result?.newPath || "",
|
|
19058
|
+
oldPath: args.oldPath,
|
|
19059
|
+
success: true
|
|
19060
|
+
};
|
|
19061
|
+
return {
|
|
19062
|
+
content: formatRenameResult({
|
|
19063
|
+
error: result.result?.error,
|
|
19064
|
+
newName: args.newName,
|
|
19065
|
+
oldPath: args.oldPath,
|
|
19066
|
+
success: true
|
|
19067
|
+
}),
|
|
19068
|
+
state,
|
|
19069
|
+
success: true
|
|
19070
|
+
};
|
|
19071
|
+
} catch (error) {
|
|
19072
|
+
return this.handleError(error);
|
|
19073
|
+
}
|
|
19074
|
+
}
|
|
19075
|
+
async runCommand(args) {
|
|
19076
|
+
try {
|
|
19077
|
+
const result = await this.callService("runCommand", args);
|
|
19078
|
+
if (!result.success) return this.errorOutput(result, {
|
|
19079
|
+
error: result.error?.message,
|
|
19080
|
+
exitCode: result.result?.exitCode ?? result.result?.exit_code,
|
|
19081
|
+
isBackground: args.background || false,
|
|
19082
|
+
stderr: result.result?.stderr,
|
|
19083
|
+
stdout: result.result?.stdout,
|
|
19084
|
+
success: false
|
|
19085
|
+
});
|
|
19086
|
+
const r = result.result || {};
|
|
19087
|
+
const state = {
|
|
19088
|
+
commandId: r.commandId || r.shell_id,
|
|
19089
|
+
error: r.error,
|
|
19090
|
+
exitCode: r.exitCode ?? r.exit_code,
|
|
19091
|
+
isBackground: args.background || false,
|
|
19092
|
+
output: r.output,
|
|
19093
|
+
stderr: r.stderr,
|
|
19094
|
+
stdout: r.stdout,
|
|
19095
|
+
success: result.success
|
|
19096
|
+
};
|
|
19097
|
+
return {
|
|
19098
|
+
content: formatCommandResult({
|
|
19099
|
+
error: r.error,
|
|
19100
|
+
exitCode: r.exitCode ?? r.exit_code,
|
|
19101
|
+
shellId: r.commandId || r.shell_id,
|
|
19102
|
+
stderr: r.stderr,
|
|
19103
|
+
stdout: r.stdout || r.output,
|
|
19104
|
+
success: result.success
|
|
19105
|
+
}),
|
|
19106
|
+
state,
|
|
19107
|
+
success: true
|
|
19108
|
+
};
|
|
19109
|
+
} catch (error) {
|
|
19110
|
+
return this.handleError(error);
|
|
19111
|
+
}
|
|
19112
|
+
}
|
|
19113
|
+
async getCommandOutput(args) {
|
|
19114
|
+
try {
|
|
19115
|
+
const result = await this.callService("getCommandOutput", args);
|
|
19116
|
+
if (!result.success) return this.errorOutput(result, {
|
|
19117
|
+
error: result.error?.message,
|
|
19118
|
+
success: false
|
|
19119
|
+
});
|
|
19120
|
+
const r = result.result || {};
|
|
19121
|
+
const state = {
|
|
19122
|
+
error: r.error,
|
|
19123
|
+
exitCode: r.exitCode ?? r.exit_code,
|
|
19124
|
+
newOutput: r.newOutput || r.output,
|
|
19125
|
+
success: result.success
|
|
19126
|
+
};
|
|
19127
|
+
return {
|
|
19128
|
+
content: formatCommandOutput({
|
|
19129
|
+
error: r.error,
|
|
19130
|
+
exitCode: r.exitCode ?? r.exit_code,
|
|
19131
|
+
output: r.newOutput || r.output,
|
|
19132
|
+
success: result.success
|
|
19133
|
+
}),
|
|
19134
|
+
state,
|
|
19135
|
+
success: true
|
|
19136
|
+
};
|
|
19137
|
+
} catch (error) {
|
|
19138
|
+
return this.handleError(error);
|
|
19139
|
+
}
|
|
19140
|
+
}
|
|
19141
|
+
async killCommand(args) {
|
|
19142
|
+
try {
|
|
19143
|
+
const result = await this.callService("killCommand", args);
|
|
19144
|
+
if (!result.success) return this.errorOutput(result, {
|
|
19145
|
+
commandId: args.commandId,
|
|
19146
|
+
error: result.error?.message,
|
|
19147
|
+
success: false
|
|
19148
|
+
});
|
|
19149
|
+
const state = {
|
|
19150
|
+
commandId: args.commandId,
|
|
19151
|
+
error: result.result?.error,
|
|
19152
|
+
success: result.success
|
|
19153
|
+
};
|
|
19154
|
+
return {
|
|
19155
|
+
content: formatKillResult({
|
|
19156
|
+
error: result.result?.error,
|
|
19157
|
+
shellId: args.commandId,
|
|
19158
|
+
success: result.success
|
|
19159
|
+
}),
|
|
19160
|
+
state,
|
|
19161
|
+
success: true
|
|
19162
|
+
};
|
|
19163
|
+
} catch (error) {
|
|
19164
|
+
return this.handleError(error);
|
|
19165
|
+
}
|
|
19166
|
+
}
|
|
19167
|
+
async grepContent(args) {
|
|
19168
|
+
try {
|
|
19169
|
+
const result = await this.callService("grepContent", args);
|
|
19170
|
+
if (!result.success) return this.errorOutput(result, {
|
|
19171
|
+
matches: [],
|
|
19172
|
+
pattern: args.pattern,
|
|
19173
|
+
totalMatches: 0
|
|
19174
|
+
});
|
|
19175
|
+
const r = result.result || {};
|
|
19176
|
+
const matches = r.matches || [];
|
|
19177
|
+
const totalMatches = r.totalMatches ?? r.total_matches ?? 0;
|
|
19178
|
+
const state = {
|
|
19179
|
+
matches,
|
|
19180
|
+
pattern: args.pattern,
|
|
19181
|
+
totalMatches
|
|
19182
|
+
};
|
|
19183
|
+
return {
|
|
19184
|
+
content: formatGrepResults({
|
|
19185
|
+
matches,
|
|
19186
|
+
totalMatches
|
|
19187
|
+
}),
|
|
19188
|
+
state,
|
|
19189
|
+
success: true
|
|
19190
|
+
};
|
|
19191
|
+
} catch (error) {
|
|
19192
|
+
return this.handleError(error);
|
|
19193
|
+
}
|
|
19194
|
+
}
|
|
19195
|
+
async globFiles(args) {
|
|
19196
|
+
try {
|
|
19197
|
+
const result = await this.callService("globLocalFiles", args);
|
|
19198
|
+
if (!result.success) return this.errorOutput(result, {
|
|
19199
|
+
files: [],
|
|
19200
|
+
pattern: args.pattern,
|
|
19201
|
+
totalCount: 0
|
|
19202
|
+
});
|
|
19203
|
+
const files = result.result?.files || [];
|
|
19204
|
+
const totalCount = result.result?.totalCount ?? result.result?.total_files ?? files.length;
|
|
19205
|
+
const state = {
|
|
19206
|
+
files,
|
|
19207
|
+
pattern: args.pattern,
|
|
19208
|
+
totalCount
|
|
19209
|
+
};
|
|
19210
|
+
return {
|
|
19211
|
+
content: formatGlobResults({
|
|
19212
|
+
files,
|
|
19213
|
+
totalFiles: totalCount
|
|
19214
|
+
}),
|
|
19215
|
+
state,
|
|
19216
|
+
success: true
|
|
19217
|
+
};
|
|
19218
|
+
} catch (error) {
|
|
19219
|
+
return this.handleError(error);
|
|
19220
|
+
}
|
|
19221
|
+
}
|
|
19222
|
+
handleError(error) {
|
|
19223
|
+
return {
|
|
19224
|
+
content: error instanceof Error ? error.message : String(error),
|
|
19225
|
+
error,
|
|
19226
|
+
success: false
|
|
19227
|
+
};
|
|
19228
|
+
}
|
|
19229
|
+
errorOutput(result, state) {
|
|
19230
|
+
return {
|
|
19231
|
+
content: result.error?.message || (result.error !== void 0 ? JSON.stringify(result.error) : void 0) || (typeof state?.stderr === "string" ? state.stderr : void 0) || (typeof state?.error === "string" ? state.error : void 0) || "[UNKNOWN_EXEC_ERROR] Tool execution failed",
|
|
19232
|
+
state,
|
|
19233
|
+
success: true
|
|
19234
|
+
};
|
|
19235
|
+
}
|
|
19236
|
+
};
|
|
19237
|
+
|
|
19238
|
+
//#endregion
|
|
19239
|
+
//#region ../../packages/tool-runtime/src/LocalSystemExecutionRuntime.ts
|
|
19240
|
+
/**
|
|
19241
|
+
* Maps IPC tool names to localFileService method names.
|
|
19242
|
+
* IPC service uses different method names than the standard tool names.
|
|
19243
|
+
*/
|
|
19244
|
+
const SERVICE_METHOD_MAP = {
|
|
19245
|
+
editLocalFile: "editLocalFile",
|
|
19246
|
+
getCommandOutput: "getCommandOutput",
|
|
19247
|
+
globLocalFiles: "globFiles",
|
|
19248
|
+
grepContent: "grepContent",
|
|
19249
|
+
killCommand: "killCommand",
|
|
19250
|
+
listLocalFiles: "listLocalFiles",
|
|
19251
|
+
moveLocalFiles: "moveLocalFiles",
|
|
19252
|
+
readLocalFile: "readLocalFile",
|
|
19253
|
+
renameLocalFile: "renameLocalFile",
|
|
19254
|
+
runCommand: "runCommand",
|
|
19255
|
+
searchLocalFiles: "searchLocalFiles",
|
|
19256
|
+
writeLocalFile: "writeFile"
|
|
19257
|
+
};
|
|
19258
|
+
/**
|
|
19259
|
+
* Local System Execution Runtime
|
|
19260
|
+
*
|
|
19261
|
+
* Extends ComputerRuntime for standard computer operations via Electron IPC.
|
|
19262
|
+
* Normalizes snake_case IPC results (exit_code, shell_id, total_matches)
|
|
19263
|
+
* into the camelCase format expected by ComputerRuntime.
|
|
19264
|
+
*/
|
|
19265
|
+
var LocalSystemExecutionRuntime = class extends ComputerRuntime {
|
|
19266
|
+
service;
|
|
19267
|
+
constructor(service) {
|
|
19268
|
+
super();
|
|
19269
|
+
this.service = service;
|
|
19270
|
+
}
|
|
19271
|
+
async callService(toolName, params) {
|
|
19272
|
+
const methodName = SERVICE_METHOD_MAP[toolName];
|
|
19273
|
+
if (!methodName) return {
|
|
19274
|
+
error: { message: `Unknown tool: ${toolName}` },
|
|
19275
|
+
result: null,
|
|
19276
|
+
success: false
|
|
19277
|
+
};
|
|
19278
|
+
const ipcParams = this.denormalizeParams(toolName, params);
|
|
19279
|
+
const method = this.service[methodName];
|
|
19280
|
+
const result = await method(ipcParams);
|
|
19281
|
+
return this.normalizeResult(toolName, result);
|
|
19282
|
+
}
|
|
19283
|
+
/**
|
|
19284
|
+
* Map ComputerRuntime normalized params back to IPC field names.
|
|
19285
|
+
*/
|
|
19286
|
+
denormalizeParams(toolName, params) {
|
|
19287
|
+
switch (toolName) {
|
|
19288
|
+
case "editLocalFile": return {
|
|
19289
|
+
file_path: params.path,
|
|
19290
|
+
new_string: params.replace,
|
|
19291
|
+
old_string: params.search,
|
|
19292
|
+
replace_all: params.all
|
|
19293
|
+
};
|
|
19294
|
+
case "listLocalFiles": return {
|
|
19295
|
+
limit: params.limit,
|
|
19296
|
+
path: params.directoryPath,
|
|
19297
|
+
sortBy: params.sortBy,
|
|
19298
|
+
sortOrder: params.sortOrder
|
|
19299
|
+
};
|
|
19300
|
+
case "moveLocalFiles": return { items: params.operations?.map((op) => ({
|
|
19301
|
+
newPath: op.destination,
|
|
19302
|
+
oldPath: op.source
|
|
19303
|
+
})) };
|
|
19304
|
+
case "renameLocalFile": return {
|
|
19305
|
+
newName: params.newName,
|
|
19306
|
+
path: params.oldPath
|
|
19307
|
+
};
|
|
19308
|
+
case "getCommandOutput": return {
|
|
19309
|
+
filter: params.filter,
|
|
19310
|
+
shell_id: params.commandId,
|
|
19311
|
+
timeout: params.timeout
|
|
19312
|
+
};
|
|
19313
|
+
case "killCommand": return { shell_id: params.commandId };
|
|
19314
|
+
case "readLocalFile": {
|
|
19315
|
+
const loc = params.startLine !== void 0 || params.endLine !== void 0 ? [params.startLine ?? 0, params.endLine ?? 200] : void 0;
|
|
19316
|
+
return {
|
|
19317
|
+
fullContent: params.fullContent,
|
|
19318
|
+
loc,
|
|
19319
|
+
path: params.path
|
|
19320
|
+
};
|
|
19321
|
+
}
|
|
19322
|
+
case "globLocalFiles": return {
|
|
19323
|
+
pattern: params.pattern,
|
|
19324
|
+
scope: params.directory
|
|
19325
|
+
};
|
|
19326
|
+
default: return params;
|
|
19327
|
+
}
|
|
19328
|
+
}
|
|
19329
|
+
/**
|
|
19330
|
+
* Batch read multiple files — unique to local system.
|
|
19331
|
+
*/
|
|
19332
|
+
async readFiles(params) {
|
|
19333
|
+
try {
|
|
19334
|
+
const { formatMultipleFiles } = await Promise.resolve().then(() => (init_fileSystem(), fileSystem_exports));
|
|
19335
|
+
const results = await this.service.readLocalFiles(params);
|
|
19336
|
+
return {
|
|
19337
|
+
content: formatMultipleFiles(results),
|
|
19338
|
+
state: { filesContent: results },
|
|
19339
|
+
success: true
|
|
19340
|
+
};
|
|
19341
|
+
} catch (error) {
|
|
19342
|
+
return this.handleError(error);
|
|
19343
|
+
}
|
|
19344
|
+
}
|
|
19345
|
+
/**
|
|
19346
|
+
* Normalize raw IPC results into the ServiceResult format.
|
|
19347
|
+
* IPC methods return domain objects directly; we wrap them appropriately.
|
|
19348
|
+
*/
|
|
19349
|
+
normalizeResult(toolName, raw) {
|
|
19350
|
+
switch (toolName) {
|
|
19351
|
+
case "runCommand": return {
|
|
19352
|
+
result: {
|
|
19353
|
+
error: raw.error,
|
|
19354
|
+
exitCode: raw.exit_code,
|
|
19355
|
+
output: raw.output,
|
|
19356
|
+
commandId: raw.shell_id,
|
|
19357
|
+
stderr: raw.stderr,
|
|
19358
|
+
stdout: raw.stdout,
|
|
19359
|
+
success: raw.success
|
|
19360
|
+
},
|
|
19361
|
+
success: raw.success
|
|
19362
|
+
};
|
|
19363
|
+
case "getCommandOutput": return {
|
|
19364
|
+
result: {
|
|
19365
|
+
exitCode: raw.exit_code,
|
|
19366
|
+
error: raw.error,
|
|
19367
|
+
newOutput: raw.output,
|
|
19368
|
+
success: raw.success
|
|
19369
|
+
},
|
|
19370
|
+
success: raw.success
|
|
19371
|
+
};
|
|
19372
|
+
case "killCommand": return {
|
|
19373
|
+
result: {
|
|
19374
|
+
error: raw.error,
|
|
19375
|
+
success: raw.success
|
|
19376
|
+
},
|
|
19377
|
+
success: raw.success
|
|
19378
|
+
};
|
|
19379
|
+
case "grepContent": return {
|
|
19380
|
+
error: raw.error ? { message: String(raw.error) } : void 0,
|
|
19381
|
+
result: {
|
|
19382
|
+
matches: raw.matches,
|
|
19383
|
+
totalMatches: raw.total_matches
|
|
19384
|
+
},
|
|
19385
|
+
success: raw.success
|
|
19386
|
+
};
|
|
19387
|
+
case "globLocalFiles": return {
|
|
19388
|
+
error: raw.error ? { message: String(raw.error) } : void 0,
|
|
19389
|
+
result: {
|
|
19390
|
+
files: raw.files,
|
|
19391
|
+
totalCount: raw.total_files
|
|
19392
|
+
},
|
|
19393
|
+
success: raw.success
|
|
19394
|
+
};
|
|
19395
|
+
case "listLocalFiles": return {
|
|
19396
|
+
result: {
|
|
19397
|
+
files: raw.files,
|
|
19398
|
+
totalCount: raw.totalCount
|
|
19399
|
+
},
|
|
19400
|
+
success: true
|
|
19401
|
+
};
|
|
19402
|
+
case "readLocalFile": return {
|
|
19403
|
+
result: {
|
|
19404
|
+
charCount: raw.charCount,
|
|
19405
|
+
content: raw.content,
|
|
19406
|
+
fileType: raw.fileType,
|
|
19407
|
+
filename: raw.filename,
|
|
19408
|
+
loc: raw.loc,
|
|
19409
|
+
totalCharCount: raw.totalCharCount,
|
|
19410
|
+
totalLineCount: raw.totalLineCount
|
|
19411
|
+
},
|
|
19412
|
+
success: true
|
|
19413
|
+
};
|
|
19414
|
+
case "writeLocalFile": return {
|
|
19415
|
+
result: {
|
|
19416
|
+
bytesWritten: raw.bytesWritten,
|
|
19417
|
+
success: raw.success
|
|
19418
|
+
},
|
|
19419
|
+
success: raw.success ?? true
|
|
19420
|
+
};
|
|
19421
|
+
case "editLocalFile": return {
|
|
19422
|
+
result: {
|
|
19423
|
+
diffText: raw.diffText,
|
|
19424
|
+
error: raw.error,
|
|
19425
|
+
linesAdded: raw.linesAdded,
|
|
19426
|
+
linesDeleted: raw.linesDeleted,
|
|
19427
|
+
replacements: raw.replacements
|
|
19428
|
+
},
|
|
19429
|
+
success: raw.success
|
|
19430
|
+
};
|
|
19431
|
+
case "searchLocalFiles": {
|
|
19432
|
+
const results = Array.isArray(raw) ? raw : [];
|
|
19433
|
+
return {
|
|
19434
|
+
result: {
|
|
19435
|
+
results,
|
|
19436
|
+
totalCount: results.length
|
|
19437
|
+
},
|
|
19438
|
+
success: true
|
|
19439
|
+
};
|
|
19440
|
+
}
|
|
19441
|
+
case "moveLocalFiles": {
|
|
19442
|
+
const results = Array.isArray(raw) ? raw : [];
|
|
19443
|
+
return {
|
|
19444
|
+
result: {
|
|
19445
|
+
results,
|
|
19446
|
+
successCount: results.filter((r) => r.success).length
|
|
19447
|
+
},
|
|
19448
|
+
success: true
|
|
19449
|
+
};
|
|
19450
|
+
}
|
|
19451
|
+
case "renameLocalFile": return {
|
|
19452
|
+
result: {
|
|
19453
|
+
error: raw.error,
|
|
19454
|
+
newPath: raw.newPath,
|
|
19455
|
+
success: raw.success
|
|
19456
|
+
},
|
|
19457
|
+
success: raw.success
|
|
19458
|
+
};
|
|
19459
|
+
default: return {
|
|
19460
|
+
result: raw,
|
|
19461
|
+
success: true
|
|
19462
|
+
};
|
|
19463
|
+
}
|
|
19464
|
+
}
|
|
19465
|
+
};
|
|
19466
|
+
|
|
18257
19467
|
//#endregion
|
|
18258
19468
|
//#region node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js
|
|
18259
19469
|
var require_ms = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
@@ -206440,375 +207650,6 @@ async function runCommand$1({ command, cwd, description, env: extraEnv, run_in_b
|
|
|
206440
207650
|
}
|
|
206441
207651
|
}
|
|
206442
207652
|
|
|
206443
|
-
//#endregion
|
|
206444
|
-
//#region src/tools/getAgentProfile.ts
|
|
206445
|
-
const IDENTITY_FILES$1 = ["IDENTITY.md", "SOUL.md"];
|
|
206446
|
-
/**
|
|
206447
|
-
* Try to extract a description from the workspace identity file.
|
|
206448
|
-
* Looks for Creature / Vibe / Description fields in IDENTITY.md or SOUL.md.
|
|
206449
|
-
*/
|
|
206450
|
-
function readDescriptionFromWorkspace(workspacePath) {
|
|
206451
|
-
for (const filename of IDENTITY_FILES$1) {
|
|
206452
|
-
const filePath = path.join(workspacePath, filename);
|
|
206453
|
-
if (!fs.existsSync(filePath)) continue;
|
|
206454
|
-
const match = fs.readFileSync(filePath, "utf8").match(/\*{0,2}(?:Creature|Vibe|Description):?\*{0,2}\s*(.+)/i);
|
|
206455
|
-
if (!match) continue;
|
|
206456
|
-
const value = match[1].trim();
|
|
206457
|
-
if (/^[_*((].*[))*_]$|^(?:tbd|todo|n\/?a|none|待定|未定)$/i.test(value)) continue;
|
|
206458
|
-
return value;
|
|
206459
|
-
}
|
|
206460
|
-
}
|
|
206461
|
-
function getOpenClawProfile(agentId) {
|
|
206462
|
-
let output;
|
|
206463
|
-
try {
|
|
206464
|
-
output = execFileSync("openclaw", [
|
|
206465
|
-
"agents",
|
|
206466
|
-
"list",
|
|
206467
|
-
"--json"
|
|
206468
|
-
], {
|
|
206469
|
-
encoding: "utf8",
|
|
206470
|
-
timeout: 5e3
|
|
206471
|
-
});
|
|
206472
|
-
} catch {
|
|
206473
|
-
return {};
|
|
206474
|
-
}
|
|
206475
|
-
let agents;
|
|
206476
|
-
try {
|
|
206477
|
-
agents = JSON.parse(output);
|
|
206478
|
-
} catch {
|
|
206479
|
-
return {};
|
|
206480
|
-
}
|
|
206481
|
-
const agent = agentId ? agents.find((a) => a.id === agentId) : agents.find((a) => a.isDefault) ?? agents[0];
|
|
206482
|
-
if (!agent) return {};
|
|
206483
|
-
const title = agent.identityName || void 0;
|
|
206484
|
-
return {
|
|
206485
|
-
avatar: agent.identityEmoji || "🦞",
|
|
206486
|
-
description: agent.workspace ? readDescriptionFromWorkspace(agent.workspace) : void 0,
|
|
206487
|
-
title
|
|
206488
|
-
};
|
|
206489
|
-
}
|
|
206490
|
-
/**
|
|
206491
|
-
* Read the active Hermes profile name from `hermes profile list` output.
|
|
206492
|
-
* The active profile is marked with ◆ in the first column.
|
|
206493
|
-
*/
|
|
206494
|
-
function getActiveHermesProfileName() {
|
|
206495
|
-
try {
|
|
206496
|
-
return execFileSync("hermes", ["profile", "list"], {
|
|
206497
|
-
encoding: "utf8",
|
|
206498
|
-
timeout: 5e3
|
|
206499
|
-
}).match(/◆(\S+)/)?.[1];
|
|
206500
|
-
} catch {
|
|
206501
|
-
return;
|
|
206502
|
-
}
|
|
206503
|
-
}
|
|
206504
|
-
/**
|
|
206505
|
-
* Read the filesystem path of a Hermes profile from `hermes profile show <name>`.
|
|
206506
|
-
*/
|
|
206507
|
-
function getHermesProfilePath(profileName) {
|
|
206508
|
-
try {
|
|
206509
|
-
return (execFileSync("hermes", [
|
|
206510
|
-
"profile",
|
|
206511
|
-
"show",
|
|
206512
|
-
profileName
|
|
206513
|
-
], {
|
|
206514
|
-
encoding: "utf8",
|
|
206515
|
-
timeout: 5e3
|
|
206516
|
-
}).match(/^Path:\s+(.+)/m)?.[1]?.trim())?.replace(/^~(?=\/|$)/, os.homedir());
|
|
206517
|
-
} catch {
|
|
206518
|
-
return;
|
|
206519
|
-
}
|
|
206520
|
-
}
|
|
206521
|
-
/**
|
|
206522
|
-
* Extract a one-line description from a Hermes SOUL.md file.
|
|
206523
|
-
* Strips HTML comments and Markdown headings, then returns the first
|
|
206524
|
-
* non-empty line of actual content.
|
|
206525
|
-
*/
|
|
206526
|
-
function readHermesSoulDescription(soulPath) {
|
|
206527
|
-
try {
|
|
206528
|
-
let stripped = fs.readFileSync(soulPath, "utf8");
|
|
206529
|
-
let previous;
|
|
206530
|
-
do {
|
|
206531
|
-
previous = stripped;
|
|
206532
|
-
stripped = stripped.replaceAll(/<!--[\s\S]*?-->/g, "").replaceAll(/[<>]/g, "").replaceAll(/^#+\s.*$/gm, "");
|
|
206533
|
-
} while (stripped !== previous);
|
|
206534
|
-
return stripped.split("\n").map((l) => l.trim()).find((l) => l.length > 0) || void 0;
|
|
206535
|
-
} catch {
|
|
206536
|
-
return;
|
|
206537
|
-
}
|
|
206538
|
-
}
|
|
206539
|
-
function getHermesProfile() {
|
|
206540
|
-
const profileName = getActiveHermesProfileName();
|
|
206541
|
-
if (!profileName) return {};
|
|
206542
|
-
const profilePath = getHermesProfilePath(profileName);
|
|
206543
|
-
return {
|
|
206544
|
-
avatar: "⚡",
|
|
206545
|
-
description: profilePath ? readHermesSoulDescription(path.join(profilePath, "SOUL.md")) : void 0,
|
|
206546
|
-
title: profileName
|
|
206547
|
-
};
|
|
206548
|
-
}
|
|
206549
|
-
/**
|
|
206550
|
-
* Fetch the agent profile (title, avatar, description) from the platform
|
|
206551
|
-
* installed on this device. Dispatched by the server via `device.getAgentProfile`.
|
|
206552
|
-
*
|
|
206553
|
-
* - openclaw: `openclaw agents list --json` for name + emoji, workspace
|
|
206554
|
-
* IDENTITY.md for description fallback
|
|
206555
|
-
* - hermes: active profile name + SOUL.md description
|
|
206556
|
-
*/
|
|
206557
|
-
async function getAgentProfile(params) {
|
|
206558
|
-
const { platform, agentId } = params;
|
|
206559
|
-
if (platform === "openclaw") return getOpenClawProfile(agentId);
|
|
206560
|
-
if (platform === "hermes") return getHermesProfile();
|
|
206561
|
-
return {};
|
|
206562
|
-
}
|
|
206563
|
-
|
|
206564
|
-
//#endregion
|
|
206565
|
-
//#region src/daemon/taskRegistry.ts
|
|
206566
|
-
function getRegistryPath() {
|
|
206567
|
-
return path.join(os.homedir(), ".lobehub", "task-registry.json");
|
|
206568
|
-
}
|
|
206569
|
-
function readRegistry() {
|
|
206570
|
-
try {
|
|
206571
|
-
return JSON.parse(fs.readFileSync(getRegistryPath(), "utf8"));
|
|
206572
|
-
} catch {
|
|
206573
|
-
return {};
|
|
206574
|
-
}
|
|
206575
|
-
}
|
|
206576
|
-
function writeRegistry(entries) {
|
|
206577
|
-
const dir = path.dirname(getRegistryPath());
|
|
206578
|
-
fs.mkdirSync(dir, {
|
|
206579
|
-
mode: 448,
|
|
206580
|
-
recursive: true
|
|
206581
|
-
});
|
|
206582
|
-
fs.writeFileSync(getRegistryPath(), JSON.stringify(entries, null, 2), { mode: 384 });
|
|
206583
|
-
}
|
|
206584
|
-
function saveTask(entry) {
|
|
206585
|
-
const registry = readRegistry();
|
|
206586
|
-
registry[entry.taskId] = entry;
|
|
206587
|
-
writeRegistry(registry);
|
|
206588
|
-
}
|
|
206589
|
-
function getTask(taskId) {
|
|
206590
|
-
return readRegistry()[taskId];
|
|
206591
|
-
}
|
|
206592
|
-
function removeTask(taskId) {
|
|
206593
|
-
const registry = readRegistry();
|
|
206594
|
-
delete registry[taskId];
|
|
206595
|
-
writeRegistry(registry);
|
|
206596
|
-
}
|
|
206597
|
-
function listTasks() {
|
|
206598
|
-
return Object.values(readRegistry());
|
|
206599
|
-
}
|
|
206600
|
-
|
|
206601
|
-
//#endregion
|
|
206602
|
-
//#region src/tools/heteroTask.ts
|
|
206603
|
-
const LOBEHUB_DIR_NAME = process.env.LOBEHUB_CLI_HOME || ".lobehub";
|
|
206604
|
-
const HERMES_SESSIONS_FILE = path.join(os.homedir(), LOBEHUB_DIR_NAME, "hermes-sessions.json");
|
|
206605
|
-
function getHermesSessionId(topicId) {
|
|
206606
|
-
try {
|
|
206607
|
-
return JSON.parse(fs.readFileSync(HERMES_SESSIONS_FILE, "utf8"))[topicId];
|
|
206608
|
-
} catch {
|
|
206609
|
-
return;
|
|
206610
|
-
}
|
|
206611
|
-
}
|
|
206612
|
-
function saveHermesSessionId(topicId, sessionId) {
|
|
206613
|
-
let data = {};
|
|
206614
|
-
try {
|
|
206615
|
-
data = JSON.parse(fs.readFileSync(HERMES_SESSIONS_FILE, "utf8"));
|
|
206616
|
-
} catch {}
|
|
206617
|
-
data[topicId] = sessionId;
|
|
206618
|
-
fs.mkdirSync(path.dirname(HERMES_SESSIONS_FILE), { recursive: true });
|
|
206619
|
-
fs.writeFileSync(HERMES_SESSIONS_FILE, JSON.stringify(data), "utf8");
|
|
206620
|
-
}
|
|
206621
|
-
/** Resolve the absolute path to the `lh` binary to avoid PATH issues in child processes. */
|
|
206622
|
-
function resolveLhPath() {
|
|
206623
|
-
try {
|
|
206624
|
-
return execFileSync("which", ["lh"], { encoding: "utf8" }).trim();
|
|
206625
|
-
} catch {
|
|
206626
|
-
return "lh";
|
|
206627
|
-
}
|
|
206628
|
-
}
|
|
206629
|
-
async function sendAutoNotify(topicId, taskId, text, agentId) {
|
|
206630
|
-
try {
|
|
206631
|
-
await (await getTrpcClient()).agentNotify.notify.mutate({
|
|
206632
|
-
agentId,
|
|
206633
|
-
content: text,
|
|
206634
|
-
role: "assistant",
|
|
206635
|
-
topicId
|
|
206636
|
-
});
|
|
206637
|
-
} catch (err) {
|
|
206638
|
-
log$7.error("Failed to send auto-notify:", err instanceof Error ? err.message : String(err));
|
|
206639
|
-
}
|
|
206640
|
-
}
|
|
206641
|
-
/**
|
|
206642
|
-
* Signal remote hetero task completion to the server so it can publish
|
|
206643
|
-
* `agent_runtime_end` to the gateway WS and close the frontend subscription.
|
|
206644
|
-
* Called on clean process exit (code=0, no signal) — error exits go through
|
|
206645
|
-
* `sendAutoNotify` which writes an error message AND triggers completion via
|
|
206646
|
-
* the `done` flag.
|
|
206647
|
-
*/
|
|
206648
|
-
async function sendDoneSignal(topicId, agentId) {
|
|
206649
|
-
try {
|
|
206650
|
-
await (await getTrpcClient()).agentNotify.notify.mutate({
|
|
206651
|
-
agentId,
|
|
206652
|
-
content: "",
|
|
206653
|
-
done: true,
|
|
206654
|
-
role: "assistant",
|
|
206655
|
-
topicId
|
|
206656
|
-
});
|
|
206657
|
-
} catch (err) {
|
|
206658
|
-
log$7.error("Failed to send done signal:", err instanceof Error ? err.message : String(err));
|
|
206659
|
-
}
|
|
206660
|
-
}
|
|
206661
|
-
/**
|
|
206662
|
-
* Build the notify protocol injected into the first message of a new hetero-agent session.
|
|
206663
|
-
* Tells the agent how to push updates back to the LobeHub user via `lh notify`.
|
|
206664
|
-
*/
|
|
206665
|
-
function buildNotifyProtocol(lhPath, topicId) {
|
|
206666
|
-
return `## Context: This task was dispatched by LobeHub
|
|
206667
|
-
|
|
206668
|
-
This conversation / task was sent to you by the **LobeHub platform** on behalf of a user. You are running as a background agent; the user is waiting for your response inside the LobeHub chat interface.
|
|
206669
|
-
|
|
206670
|
-
**When to call notify**: any time you have something meaningful to tell the user — a key finding, a decision you made, a result, a question, or your final answer. Think of it as speaking directly to the user in the chat window.
|
|
206671
|
-
|
|
206672
|
-
**What to hide**: internal work details such as tool call sequences, file reads, intermediate command output, retries, or low-level reasoning steps. The user cares about outcomes and insights, not your step-by-step mechanics.
|
|
206673
|
-
|
|
206674
|
-
## Sending messages back to the user
|
|
206675
|
-
|
|
206676
|
-
Use the \`${lhPath} notify\` command. All your updates appear as a **single message bubble** in the UI — create it once and update it in place.\n\n**Step 1 — Open the bubble on your first meaningful update** (captures the messageId):\n\`\`\`\nMSG_ID=$(${lhPath} notify --topic ${topicId} --role assistant --content "Starting..." --json | grep -o '"messageId":"[^"]*"' | cut -d'"' -f4)\n\`\`\`\n\n**Step 2 — Update the same bubble as you make progress**:\n\`\`\`\n${lhPath} notify --topic ${topicId} --role assistant --message-id "$MSG_ID" --content "Still working..."\n\`\`\`\n\n**Step 3 — Replace with your complete, final response when done**:\n\`\`\`\n${lhPath} notify --topic ${topicId} --role assistant --message-id "$MSG_ID" --content "<your full response here>"\n\`\`\`\n\nRules:\n- Always use \`--json\` on the first call and capture \`messageId\` from the output.\n- Always pass \`--message-id\` on every subsequent call so updates overwrite the same bubble.\n- Write what matters to the user — not implementation steps or internal tool calls.\n- Call notify at least once when the task is done, even if there were no intermediate updates.`;
|
|
206677
|
-
}
|
|
206678
|
-
async function runHeteroTask(params) {
|
|
206679
|
-
const { agentId, agentType, cwd, operationId, prompt, taskId, topicId } = params;
|
|
206680
|
-
const workDir = cwd || process.cwd();
|
|
206681
|
-
const lhPath = resolveLhPath();
|
|
206682
|
-
if (agentType === "openclaw") {
|
|
206683
|
-
const openclawAgent = process.env.OPENCLAW_AGENT_ID ?? "main";
|
|
206684
|
-
const enrichedPrompt = `${prompt}\n\n${buildNotifyProtocol(lhPath, topicId)}`;
|
|
206685
|
-
for (const existing of listTasks()) if (existing.topicId === topicId && existing.agentType === "openclaw") {
|
|
206686
|
-
try {
|
|
206687
|
-
process.kill(existing.pid, "SIGTERM");
|
|
206688
|
-
} catch {}
|
|
206689
|
-
removeTask(existing.taskId);
|
|
206690
|
-
}
|
|
206691
|
-
const child = spawn("openclaw", [
|
|
206692
|
-
"agent",
|
|
206693
|
-
"--agent",
|
|
206694
|
-
openclawAgent,
|
|
206695
|
-
"--session-id",
|
|
206696
|
-
topicId,
|
|
206697
|
-
"--message",
|
|
206698
|
-
enrichedPrompt,
|
|
206699
|
-
"--local"
|
|
206700
|
-
], {
|
|
206701
|
-
cwd: workDir,
|
|
206702
|
-
detached: true,
|
|
206703
|
-
env: { ...process.env },
|
|
206704
|
-
stdio: "ignore"
|
|
206705
|
-
});
|
|
206706
|
-
const pid = child.pid;
|
|
206707
|
-
if (pid === void 0) throw new Error("Failed to get PID for openclaw process");
|
|
206708
|
-
child.unref();
|
|
206709
|
-
saveTask({
|
|
206710
|
-
agentId,
|
|
206711
|
-
agentType,
|
|
206712
|
-
operationId,
|
|
206713
|
-
pid,
|
|
206714
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
206715
|
-
taskId,
|
|
206716
|
-
topicId
|
|
206717
|
-
});
|
|
206718
|
-
log$7.info(`OpenClaw task started: taskId=${taskId} pid=${pid} agent=${openclawAgent}`);
|
|
206719
|
-
child.on("close", (code, signal) => {
|
|
206720
|
-
removeTask(taskId);
|
|
206721
|
-
if (code !== 0 || signal !== null) sendAutoNotify(topicId, taskId, signal ? `Task cancelled (signal: ${signal})` : `Task failed (exit code: ${code})`, agentId).finally(() => sendDoneSignal(topicId, agentId));
|
|
206722
|
-
else sendDoneSignal(topicId, agentId);
|
|
206723
|
-
});
|
|
206724
|
-
return JSON.stringify({
|
|
206725
|
-
pid,
|
|
206726
|
-
taskId
|
|
206727
|
-
});
|
|
206728
|
-
}
|
|
206729
|
-
if (agentType === "hermes") {
|
|
206730
|
-
for (const existing of listTasks()) if (existing.topicId === topicId && existing.agentType === "hermes") {
|
|
206731
|
-
try {
|
|
206732
|
-
process.kill(existing.pid, "SIGTERM");
|
|
206733
|
-
} catch {}
|
|
206734
|
-
removeTask(existing.taskId);
|
|
206735
|
-
}
|
|
206736
|
-
const existingSessionId = getHermesSessionId(topicId);
|
|
206737
|
-
const hermesArgs = [
|
|
206738
|
-
"chat",
|
|
206739
|
-
"--query",
|
|
206740
|
-
prompt,
|
|
206741
|
-
"--quiet",
|
|
206742
|
-
"--accept-hooks"
|
|
206743
|
-
];
|
|
206744
|
-
if (existingSessionId) hermesArgs.push("--resume", existingSessionId);
|
|
206745
|
-
const child = spawn("hermes", hermesArgs, {
|
|
206746
|
-
cwd: workDir,
|
|
206747
|
-
detached: true,
|
|
206748
|
-
env: { ...process.env },
|
|
206749
|
-
stdio: [
|
|
206750
|
-
"ignore",
|
|
206751
|
-
"pipe",
|
|
206752
|
-
"ignore"
|
|
206753
|
-
]
|
|
206754
|
-
});
|
|
206755
|
-
const pid = child.pid;
|
|
206756
|
-
if (pid === void 0) throw new Error("Failed to get PID for hermes process");
|
|
206757
|
-
child.unref();
|
|
206758
|
-
saveTask({
|
|
206759
|
-
agentId,
|
|
206760
|
-
agentType,
|
|
206761
|
-
operationId,
|
|
206762
|
-
pid,
|
|
206763
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
206764
|
-
taskId,
|
|
206765
|
-
topicId
|
|
206766
|
-
});
|
|
206767
|
-
log$7.info(`Hermes task started: taskId=${taskId} pid=${pid}`);
|
|
206768
|
-
let stdout = "";
|
|
206769
|
-
child.stdout.on("data", (chunk) => {
|
|
206770
|
-
stdout += chunk.toString();
|
|
206771
|
-
});
|
|
206772
|
-
child.on("close", (code, signal) => {
|
|
206773
|
-
removeTask(taskId);
|
|
206774
|
-
if (code !== 0 || signal !== null) {
|
|
206775
|
-
sendAutoNotify(topicId, taskId, signal ? `Task cancelled (signal: ${signal})` : `Task failed (exit code: ${code})`, agentId).finally(() => sendDoneSignal(topicId, agentId));
|
|
206776
|
-
return;
|
|
206777
|
-
}
|
|
206778
|
-
const sessionId = stdout.match(/^session_id:\s*(\S+)/m)?.[1];
|
|
206779
|
-
const response = stdout.replace(/^session_id:[^\n]*\n?/, "").trim();
|
|
206780
|
-
if (sessionId) saveHermesSessionId(topicId, sessionId);
|
|
206781
|
-
if (response) sendAutoNotify(topicId, taskId, response, agentId).finally(() => sendDoneSignal(topicId, agentId));
|
|
206782
|
-
else sendDoneSignal(topicId, agentId);
|
|
206783
|
-
});
|
|
206784
|
-
return JSON.stringify({
|
|
206785
|
-
pid,
|
|
206786
|
-
taskId
|
|
206787
|
-
});
|
|
206788
|
-
}
|
|
206789
|
-
throw new Error(`Unsupported agentType: ${agentType}`);
|
|
206790
|
-
}
|
|
206791
|
-
async function cancelHeteroTask(params) {
|
|
206792
|
-
const { signal = "SIGINT", taskId } = params;
|
|
206793
|
-
const entry = getTask(taskId);
|
|
206794
|
-
if (!entry) return JSON.stringify({
|
|
206795
|
-
message: `No task found with taskId: ${taskId}`,
|
|
206796
|
-
success: false
|
|
206797
|
-
});
|
|
206798
|
-
try {
|
|
206799
|
-
process.kill(entry.pid, signal);
|
|
206800
|
-
} catch (err) {
|
|
206801
|
-
log$7.warn(`Failed to send ${signal} to pid ${entry.pid}: ${err instanceof Error ? err.message : String(err)}`);
|
|
206802
|
-
removeTask(taskId);
|
|
206803
|
-
await sendAutoNotify(entry.topicId, taskId, "Task already completed or cancelled", entry.agentId);
|
|
206804
|
-
}
|
|
206805
|
-
return JSON.stringify({
|
|
206806
|
-
pid: entry.pid,
|
|
206807
|
-
signal,
|
|
206808
|
-
taskId
|
|
206809
|
-
});
|
|
206810
|
-
}
|
|
206811
|
-
|
|
206812
207653
|
//#endregion
|
|
206813
207654
|
//#region src/tools/shell.ts
|
|
206814
207655
|
const processManager = new ShellProcessManager();
|
|
@@ -206829,42 +207670,186 @@ async function killCommand(params) {
|
|
|
206829
207670
|
}
|
|
206830
207671
|
|
|
206831
207672
|
//#endregion
|
|
206832
|
-
//#region src/tools/
|
|
206833
|
-
|
|
206834
|
-
|
|
206835
|
-
|
|
206836
|
-
|
|
206837
|
-
|
|
207673
|
+
//#region src/tools/localSystemRuntime.ts
|
|
207674
|
+
/**
|
|
207675
|
+
* Stub for `ILocalSystemService` methods the CLI does not expose (batch read,
|
|
207676
|
+
* move, rename). These are never routed by {@link runLocalSystemTool}; the
|
|
207677
|
+
* interface just requires them, so we fail loudly if one is ever reached.
|
|
207678
|
+
*/
|
|
207679
|
+
const unsupported = (method) => () => Promise.reject(/* @__PURE__ */ new Error(`${method} is not supported by the LobeHub CLI`));
|
|
207680
|
+
const runtime = new LocalSystemExecutionRuntime({
|
|
207681
|
+
editLocalFile,
|
|
206838
207682
|
getCommandOutput,
|
|
206839
207683
|
globFiles: globLocalFiles,
|
|
206840
207684
|
grepContent,
|
|
206841
207685
|
killCommand,
|
|
206842
|
-
listFiles: listLocalFiles,
|
|
206843
|
-
readFile: readLocalFile,
|
|
206844
|
-
runCommand,
|
|
206845
|
-
runHeteroTask,
|
|
206846
|
-
searchFiles: searchLocalFiles,
|
|
206847
|
-
writeFile: writeLocalFile,
|
|
206848
|
-
editLocalFile,
|
|
206849
|
-
globLocalFiles,
|
|
206850
207686
|
listLocalFiles,
|
|
207687
|
+
moveLocalFiles: unsupported("moveLocalFiles"),
|
|
206851
207688
|
readLocalFile,
|
|
207689
|
+
readLocalFiles: unsupported("readLocalFiles"),
|
|
207690
|
+
renameLocalFile: unsupported("renameLocalFile"),
|
|
207691
|
+
runCommand,
|
|
206852
207692
|
searchLocalFiles,
|
|
206853
|
-
writeLocalFile
|
|
207693
|
+
writeFile: writeLocalFile
|
|
207694
|
+
});
|
|
207695
|
+
/**
|
|
207696
|
+
* Legacy API name aliases used by older gateway versions. Normalized to the
|
|
207697
|
+
* current tool names before dispatch.
|
|
207698
|
+
*/
|
|
207699
|
+
const LEGACY_API_ALIASES = {
|
|
207700
|
+
editLocalFile: "editFile",
|
|
207701
|
+
globLocalFiles: "globFiles",
|
|
207702
|
+
listLocalFiles: "listFiles",
|
|
207703
|
+
readLocalFile: "readFile",
|
|
207704
|
+
searchLocalFiles: "searchFiles",
|
|
207705
|
+
writeLocalFile: "writeFile"
|
|
206854
207706
|
};
|
|
206855
|
-
|
|
206856
|
-
|
|
206857
|
-
|
|
206858
|
-
|
|
206859
|
-
|
|
206860
|
-
|
|
207707
|
+
/**
|
|
207708
|
+
* Resolve a relative path against a scope (CWD). Mirrors the desktop gateway's
|
|
207709
|
+
* inline copy of the renderer-side `resolveArgsWithScope` helper so the CLI and
|
|
207710
|
+
* desktop produce identical scoping for search/grep tools.
|
|
207711
|
+
*/
|
|
207712
|
+
const resolveArgsWithScope = (args, pathField) => {
|
|
207713
|
+
const scope = args.scope;
|
|
207714
|
+
const bag = args;
|
|
207715
|
+
const currentPath = typeof bag[pathField] === "string" ? bag[pathField] : void 0;
|
|
207716
|
+
if (!scope) return args;
|
|
207717
|
+
if (!currentPath) return {
|
|
207718
|
+
...args,
|
|
207719
|
+
[pathField]: scope
|
|
206861
207720
|
};
|
|
207721
|
+
if (path.isAbsolute(currentPath)) return args;
|
|
207722
|
+
return {
|
|
207723
|
+
...args,
|
|
207724
|
+
[pathField]: path.join(scope, currentPath)
|
|
207725
|
+
};
|
|
207726
|
+
};
|
|
207727
|
+
/**
|
|
207728
|
+
* Route file/shell tool calls through `LocalSystemExecutionRuntime` so the
|
|
207729
|
+
* result carries structured `state` (for client renders) and `content` is the
|
|
207730
|
+
* formatted prompt text — matching the desktop gateway path (PR #15114).
|
|
207731
|
+
*
|
|
207732
|
+
* Returns `null` when `apiName` is not a local-system tool, so the caller can
|
|
207733
|
+
* fall back to CLI-only tools (platform agents).
|
|
207734
|
+
*/
|
|
207735
|
+
async function runLocalSystemTool(apiName, args) {
|
|
207736
|
+
switch (LEGACY_API_ALIASES[apiName] ?? apiName) {
|
|
207737
|
+
case "listFiles": {
|
|
207738
|
+
const p = args;
|
|
207739
|
+
return runtime.listFiles({
|
|
207740
|
+
directoryPath: p.path,
|
|
207741
|
+
limit: p.limit,
|
|
207742
|
+
sortBy: p.sortBy,
|
|
207743
|
+
sortOrder: p.sortOrder
|
|
207744
|
+
});
|
|
207745
|
+
}
|
|
207746
|
+
case "readFile": {
|
|
207747
|
+
const p = args;
|
|
207748
|
+
return runtime.readFile({
|
|
207749
|
+
endLine: p.loc?.[1],
|
|
207750
|
+
path: p.path,
|
|
207751
|
+
startLine: p.loc?.[0]
|
|
207752
|
+
});
|
|
207753
|
+
}
|
|
207754
|
+
case "writeFile": return runtime.writeFile(args);
|
|
207755
|
+
case "editFile": {
|
|
207756
|
+
const p = args;
|
|
207757
|
+
return runtime.editFile({
|
|
207758
|
+
all: p.replace_all,
|
|
207759
|
+
path: p.file_path,
|
|
207760
|
+
replace: p.new_string,
|
|
207761
|
+
search: p.old_string
|
|
207762
|
+
});
|
|
207763
|
+
}
|
|
207764
|
+
case "searchFiles": {
|
|
207765
|
+
const resolved = resolveArgsWithScope(args, "directory");
|
|
207766
|
+
return runtime.searchFiles({
|
|
207767
|
+
...resolved,
|
|
207768
|
+
directory: resolved.directory || ""
|
|
207769
|
+
});
|
|
207770
|
+
}
|
|
207771
|
+
case "grepContent": {
|
|
207772
|
+
const resolved = resolveArgsWithScope(args, "path");
|
|
207773
|
+
return runtime.grepContent(resolved);
|
|
207774
|
+
}
|
|
207775
|
+
case "globFiles": {
|
|
207776
|
+
const p = args;
|
|
207777
|
+
return runtime.globFiles({
|
|
207778
|
+
directory: p.scope ?? p.cwd,
|
|
207779
|
+
pattern: p.pattern
|
|
207780
|
+
});
|
|
207781
|
+
}
|
|
207782
|
+
case "runCommand": {
|
|
207783
|
+
const p = args;
|
|
207784
|
+
return runtime.runCommand({
|
|
207785
|
+
...p,
|
|
207786
|
+
background: p.run_in_background
|
|
207787
|
+
});
|
|
207788
|
+
}
|
|
207789
|
+
case "getCommandOutput": {
|
|
207790
|
+
const p = args;
|
|
207791
|
+
return runtime.getCommandOutput({
|
|
207792
|
+
commandId: p.shell_id,
|
|
207793
|
+
filter: p.filter,
|
|
207794
|
+
timeout: p.timeout
|
|
207795
|
+
});
|
|
207796
|
+
}
|
|
207797
|
+
case "killCommand": {
|
|
207798
|
+
const p = args;
|
|
207799
|
+
return runtime.killCommand({ commandId: p.shell_id });
|
|
207800
|
+
}
|
|
207801
|
+
default: return null;
|
|
207802
|
+
}
|
|
207803
|
+
}
|
|
207804
|
+
|
|
207805
|
+
//#endregion
|
|
207806
|
+
//#region src/tools/index.ts
|
|
207807
|
+
/**
|
|
207808
|
+
* CLI-only tools (platform agents). File/shell tools are handled separately by
|
|
207809
|
+
* {@link runLocalSystemTool}, which routes them through
|
|
207810
|
+
* `LocalSystemExecutionRuntime` so the result carries structured `state`.
|
|
207811
|
+
*/
|
|
207812
|
+
const methodMap = {
|
|
207813
|
+
cancelHeteroTask,
|
|
207814
|
+
checkPlatformCapability,
|
|
207815
|
+
getAgentProfile,
|
|
207816
|
+
runHeteroTask
|
|
207817
|
+
};
|
|
207818
|
+
async function executeToolCall(apiName, argsStr, timeout) {
|
|
207819
|
+
let args;
|
|
206862
207820
|
try {
|
|
206863
|
-
|
|
206864
|
-
|
|
206865
|
-
|
|
206866
|
-
|
|
206867
|
-
|
|
207821
|
+
args = JSON.parse(argsStr);
|
|
207822
|
+
} catch (error) {
|
|
207823
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
207824
|
+
log$7.error(`Tool call failed: ${apiName} - ${errorMsg}`);
|
|
207825
|
+
return {
|
|
207826
|
+
content: "",
|
|
207827
|
+
error: errorMsg,
|
|
207828
|
+
success: false
|
|
207829
|
+
};
|
|
207830
|
+
}
|
|
207831
|
+
const finalArgs = typeof timeout === "number" && Number.isFinite(timeout) && !("timeout" in args) ? {
|
|
207832
|
+
...args,
|
|
207833
|
+
timeout
|
|
207834
|
+
} : args;
|
|
207835
|
+
try {
|
|
207836
|
+
const localResult = await runLocalSystemTool(apiName, finalArgs);
|
|
207837
|
+
if (localResult) {
|
|
207838
|
+
const { error } = localResult;
|
|
207839
|
+
return {
|
|
207840
|
+
content: localResult.content,
|
|
207841
|
+
error: error instanceof Error ? error.message : typeof error === "string" ? error : void 0,
|
|
207842
|
+
state: localResult.state,
|
|
207843
|
+
success: localResult.success
|
|
207844
|
+
};
|
|
207845
|
+
}
|
|
207846
|
+
const handler = methodMap[apiName];
|
|
207847
|
+
if (!handler) return {
|
|
207848
|
+
content: "",
|
|
207849
|
+
error: `Unknown tool API: ${apiName}`,
|
|
207850
|
+
success: false
|
|
207851
|
+
};
|
|
207852
|
+
const result = await handler(finalArgs);
|
|
206868
207853
|
return {
|
|
206869
207854
|
content: typeof result === "string" ? result : JSON.stringify(result),
|
|
206870
207855
|
success: true
|
|
@@ -207028,6 +208013,7 @@ async function runConnect(options, isDaemonChild) {
|
|
|
207028
208013
|
result: {
|
|
207029
208014
|
content: result.content,
|
|
207030
208015
|
error: result.error,
|
|
208016
|
+
state: result.state,
|
|
207031
208017
|
success: result.success
|
|
207032
208018
|
}
|
|
207033
208019
|
});
|