@docyrus/docyrus 0.0.63 → 0.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/agent-loader.js +165 -21
- package/agent-loader.js.map +2 -2
- package/main.js +363 -113
- package/main.js.map +4 -4
- package/package.json +5 -4
- package/resources/pi-agent/extensions/browser-tools.ts +1 -1
- package/resources/pi-agent/extensions/context.ts +12 -73
- package/resources/pi-agent/extensions/control.ts +1 -1
- package/resources/pi-agent/extensions/loop.ts +4 -1
- package/resources/pi-agent/extensions/pi-bash-live-view/index.ts +1 -1
- package/resources/pi-agent/extensions/pi-bash-live-view/package.json +3 -3
- package/resources/pi-agent/extensions/pi-fff/README.md +152 -0
- package/resources/pi-agent/extensions/pi-fff/VENDORED_FROM.md +7 -0
- package/resources/pi-agent/extensions/pi-fff/package.json +53 -0
- package/resources/pi-agent/extensions/pi-fff/src/index.ts +820 -0
- package/resources/pi-agent/extensions/pi-mcp-adapter/index.ts +1 -1
- package/resources/pi-agent/extensions/pi-mcp-adapter/package.json +1 -1
- package/resources/pi-agent/extensions/prompt-editor.ts +26 -7
- package/resources/pi-agent/extensions/soul.ts +183 -0
- package/resources/pi-agent/extensions/todos.ts +1 -1
- package/resources/pi-agent/skills/grill-me/SKILL.md +11 -8
- package/resources/pi-agent/skills/release-manager/SKILL.md +469 -30
- package/resources/pi-agent/souls/boomer-parent.md +23 -0
- package/resources/pi-agent/souls/bro.md +22 -0
- package/resources/pi-agent/souls/catalog.ts +79 -0
- package/resources/pi-agent/souls/caveman.md +21 -0
- package/resources/pi-agent/souls/linkedin-influencer.md +60 -0
- package/resources/pi-agent/souls/master-yoda.md +22 -0
- package/resources/pi-agent/souls/noir-detective.md +24 -0
- package/resources/pi-agent/souls/nonsense-engineer.md +23 -0
- package/resources/pi-agent/souls/pirate.md +24 -0
- package/resources/pi-agent/souls/shakespeare.md +24 -0
- package/server-loader.js +803 -93
- package/server-loader.js.map +4 -4
- package/resources/pi-agent/skills/changelog-generator/SKILL.md +0 -461
package/server-loader.js
CHANGED
|
@@ -2218,8 +2218,8 @@ var require_lib = __commonJS({
|
|
|
2218
2218
|
}
|
|
2219
2219
|
};
|
|
2220
2220
|
var walk2 = (opts, callback) => {
|
|
2221
|
-
const p = new Promise((
|
|
2222
|
-
new Walker(opts).on("done",
|
|
2221
|
+
const p = new Promise((resolve5, reject) => {
|
|
2222
|
+
new Walker(opts).on("done", resolve5).on("error", reject).start();
|
|
2223
2223
|
});
|
|
2224
2224
|
return callback ? p.then((res) => callback(null, res), callback) : p;
|
|
2225
2225
|
};
|
|
@@ -5393,10 +5393,10 @@ function resolveAll(constructs2, events, context) {
|
|
|
5393
5393
|
const called = [];
|
|
5394
5394
|
let index2 = -1;
|
|
5395
5395
|
while (++index2 < constructs2.length) {
|
|
5396
|
-
const
|
|
5397
|
-
if (
|
|
5398
|
-
events =
|
|
5399
|
-
called.push(
|
|
5396
|
+
const resolve5 = constructs2[index2].resolveAll;
|
|
5397
|
+
if (resolve5 && !called.includes(resolve5)) {
|
|
5398
|
+
events = resolve5(events, context);
|
|
5399
|
+
called.push(resolve5);
|
|
5400
5400
|
}
|
|
5401
5401
|
}
|
|
5402
5402
|
return events;
|
|
@@ -10705,9 +10705,9 @@ var init_lib9 = __esm({
|
|
|
10705
10705
|
* @returns {undefined}
|
|
10706
10706
|
* Nothing.
|
|
10707
10707
|
*/
|
|
10708
|
-
set dirname(
|
|
10708
|
+
set dirname(dirname12) {
|
|
10709
10709
|
assertPath(this.basename, "dirname");
|
|
10710
|
-
this.path = import_node_path6.default.join(
|
|
10710
|
+
this.path = import_node_path6.default.join(dirname12 || "", this.basename);
|
|
10711
10711
|
}
|
|
10712
10712
|
/**
|
|
10713
10713
|
* Get the extname (including dot) (example: `'.js'`).
|
|
@@ -11354,7 +11354,7 @@ var init_lib10 = __esm({
|
|
|
11354
11354
|
assertParser("process", this.parser || this.Parser);
|
|
11355
11355
|
assertCompiler("process", this.compiler || this.Compiler);
|
|
11356
11356
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
11357
|
-
function executor(
|
|
11357
|
+
function executor(resolve5, reject) {
|
|
11358
11358
|
const realFile = vfile(file2);
|
|
11359
11359
|
const parseTree = (
|
|
11360
11360
|
/** @type {HeadTree extends undefined ? Node : HeadTree} */
|
|
@@ -11385,8 +11385,8 @@ var init_lib10 = __esm({
|
|
|
11385
11385
|
function realDone(error48, file3) {
|
|
11386
11386
|
if (error48 || !file3) {
|
|
11387
11387
|
reject(error48);
|
|
11388
|
-
} else if (
|
|
11389
|
-
|
|
11388
|
+
} else if (resolve5) {
|
|
11389
|
+
resolve5(file3);
|
|
11390
11390
|
} else {
|
|
11391
11391
|
ok(done, "`done` is defined if `resolve` is not");
|
|
11392
11392
|
done(void 0, file3);
|
|
@@ -11488,7 +11488,7 @@ var init_lib10 = __esm({
|
|
|
11488
11488
|
file2 = void 0;
|
|
11489
11489
|
}
|
|
11490
11490
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
11491
|
-
function executor(
|
|
11491
|
+
function executor(resolve5, reject) {
|
|
11492
11492
|
ok(
|
|
11493
11493
|
typeof file2 !== "function",
|
|
11494
11494
|
"`file` can\u2019t be a `done` anymore, we checked"
|
|
@@ -11502,8 +11502,8 @@ var init_lib10 = __esm({
|
|
|
11502
11502
|
);
|
|
11503
11503
|
if (error48) {
|
|
11504
11504
|
reject(error48);
|
|
11505
|
-
} else if (
|
|
11506
|
-
|
|
11505
|
+
} else if (resolve5) {
|
|
11506
|
+
resolve5(resultingTree);
|
|
11507
11507
|
} else {
|
|
11508
11508
|
ok(done, "`done` is defined if `resolve` is not");
|
|
11509
11509
|
done(void 0, resultingTree, file3);
|
|
@@ -12590,8 +12590,8 @@ var require_dist = __commonJS({
|
|
|
12590
12590
|
const header = report.header;
|
|
12591
12591
|
return typeof header === "object" && !!header && "glibcVersionRuntime" in header;
|
|
12592
12592
|
}
|
|
12593
|
-
function load(
|
|
12594
|
-
const m = path6.join(
|
|
12593
|
+
function load(dirname12) {
|
|
12594
|
+
const m = path6.join(dirname12, "index.node");
|
|
12595
12595
|
return fs7.existsSync(m) ? require(m) : null;
|
|
12596
12596
|
}
|
|
12597
12597
|
exports2.load = load;
|
|
@@ -12621,12 +12621,12 @@ var require_filesystem = __commonJS({
|
|
|
12621
12621
|
var fs7 = require("fs");
|
|
12622
12622
|
var LDD_PATH = "/usr/bin/ldd";
|
|
12623
12623
|
var readFileSync5 = (path6) => fs7.readFileSync(path6, "utf-8");
|
|
12624
|
-
var readFile15 = (path6) => new Promise((
|
|
12624
|
+
var readFile15 = (path6) => new Promise((resolve5, reject) => {
|
|
12625
12625
|
fs7.readFile(path6, "utf-8", (err2, data) => {
|
|
12626
12626
|
if (err2) {
|
|
12627
12627
|
reject(err2);
|
|
12628
12628
|
} else {
|
|
12629
|
-
|
|
12629
|
+
resolve5(data);
|
|
12630
12630
|
}
|
|
12631
12631
|
});
|
|
12632
12632
|
});
|
|
@@ -12651,10 +12651,10 @@ var require_detect_libc = __commonJS({
|
|
|
12651
12651
|
var commandOut = "";
|
|
12652
12652
|
var safeCommand = () => {
|
|
12653
12653
|
if (!commandOut) {
|
|
12654
|
-
return new Promise((
|
|
12654
|
+
return new Promise((resolve5) => {
|
|
12655
12655
|
childProcess.exec(command, (err2, out2) => {
|
|
12656
12656
|
commandOut = err2 ? " " : out2;
|
|
12657
|
-
|
|
12657
|
+
resolve5(commandOut);
|
|
12658
12658
|
});
|
|
12659
12659
|
});
|
|
12660
12660
|
}
|
|
@@ -16571,7 +16571,7 @@ var require_websocket = __commonJS({
|
|
|
16571
16571
|
var http = require("http");
|
|
16572
16572
|
var net = require("net");
|
|
16573
16573
|
var tls = require("tls");
|
|
16574
|
-
var { randomBytes, createHash:
|
|
16574
|
+
var { randomBytes, createHash: createHash6 } = require("crypto");
|
|
16575
16575
|
var { Duplex, Readable: Readable2 } = require("stream");
|
|
16576
16576
|
var { URL: URL2 } = require("url");
|
|
16577
16577
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -17231,7 +17231,7 @@ var require_websocket = __commonJS({
|
|
|
17231
17231
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
17232
17232
|
return;
|
|
17233
17233
|
}
|
|
17234
|
-
const digest =
|
|
17234
|
+
const digest = createHash6("sha1").update(key + GUID).digest("base64");
|
|
17235
17235
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
17236
17236
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
17237
17237
|
return;
|
|
@@ -17598,7 +17598,7 @@ var require_websocket_server = __commonJS({
|
|
|
17598
17598
|
var EventEmitter = require("events");
|
|
17599
17599
|
var http = require("http");
|
|
17600
17600
|
var { Duplex } = require("stream");
|
|
17601
|
-
var { createHash:
|
|
17601
|
+
var { createHash: createHash6 } = require("crypto");
|
|
17602
17602
|
var extension3 = require_extension();
|
|
17603
17603
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
17604
17604
|
var subprotocol2 = require_subprotocol();
|
|
@@ -17899,7 +17899,7 @@ var require_websocket_server = __commonJS({
|
|
|
17899
17899
|
);
|
|
17900
17900
|
}
|
|
17901
17901
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
17902
|
-
const digest =
|
|
17902
|
+
const digest = createHash6("sha1").update(key + GUID).digest("base64");
|
|
17903
17903
|
const headers = [
|
|
17904
17904
|
"HTTP/1.1 101 Switching Protocols",
|
|
17905
17905
|
"Upgrade: websocket",
|
|
@@ -18467,7 +18467,7 @@ var init_dist = __esm({
|
|
|
18467
18467
|
});
|
|
18468
18468
|
if (!chunk) {
|
|
18469
18469
|
if (i2 === 1) {
|
|
18470
|
-
await new Promise((
|
|
18470
|
+
await new Promise((resolve5) => setTimeout(resolve5));
|
|
18471
18471
|
maxReadCount = 3;
|
|
18472
18472
|
continue;
|
|
18473
18473
|
}
|
|
@@ -18617,7 +18617,7 @@ var init_dist = __esm({
|
|
|
18617
18617
|
});
|
|
18618
18618
|
|
|
18619
18619
|
// src/server/server-loader.ts
|
|
18620
|
-
var
|
|
18620
|
+
var import_node_fs14 = require("node:fs");
|
|
18621
18621
|
var import_node_url3 = require("node:url");
|
|
18622
18622
|
var import_node_path23 = require("node:path");
|
|
18623
18623
|
var import_picocolors2 = __toESM(require_picocolors());
|
|
@@ -18743,7 +18743,7 @@ function resolvePackagedExtensionPaths(resourceRoot, runtime = "terminal") {
|
|
|
18743
18743
|
|
|
18744
18744
|
// src/server/agentServer.ts
|
|
18745
18745
|
var import_node_child_process3 = require("node:child_process");
|
|
18746
|
-
var
|
|
18746
|
+
var import_node_crypto7 = require("node:crypto");
|
|
18747
18747
|
var import_promises18 = require("node:fs/promises");
|
|
18748
18748
|
var import_node_path22 = require("node:path");
|
|
18749
18749
|
|
|
@@ -18792,6 +18792,14 @@ var AUTH_DIR_PATH = (0, import_node_path3.join)((0, import_node_os.homedir)(), D
|
|
|
18792
18792
|
var AUTH_FILE_PATH = (0, import_node_path3.join)(AUTH_DIR_PATH, "auth.json");
|
|
18793
18793
|
var CONFIG_FILE_PATH = (0, import_node_path3.join)(AUTH_DIR_PATH, "config.json");
|
|
18794
18794
|
var TENANT_OPENAPI_ROOT_PATH = (0, import_node_path3.join)(AUTH_DIR_PATH, "tenans");
|
|
18795
|
+
var DOCYRUS_PI_AGENT_GLOBAL_ROOT_PATH = (0, import_node_path3.join)(
|
|
18796
|
+
AUTH_DIR_PATH,
|
|
18797
|
+
DOCYRUS_PI_DIR_NAME,
|
|
18798
|
+
DOCYRUS_PI_AGENT_DIR_NAME
|
|
18799
|
+
);
|
|
18800
|
+
function getDocyrusPiAgentGlobalRootPath() {
|
|
18801
|
+
return DOCYRUS_PI_AGENT_GLOBAL_ROOT_PATH;
|
|
18802
|
+
}
|
|
18795
18803
|
var DEFAULT_ENVIRONMENT_ID = "live";
|
|
18796
18804
|
var DEFAULT_ENVIRONMENTS = [
|
|
18797
18805
|
{
|
|
@@ -18815,9 +18823,6 @@ var DEFAULT_ENVIRONMENTS = [
|
|
|
18815
18823
|
apiBaseUrl: "https://localhost:3366"
|
|
18816
18824
|
}
|
|
18817
18825
|
];
|
|
18818
|
-
function resolveDocyrusPiAgentRootPath(settingsRootPath) {
|
|
18819
|
-
return (0, import_node_path3.join)(settingsRootPath, DOCYRUS_PI_DIR_NAME, DOCYRUS_PI_AGENT_DIR_NAME);
|
|
18820
|
-
}
|
|
18821
18826
|
function normalizeApiBaseUrl(apiBaseUrl) {
|
|
18822
18827
|
const trimmed = apiBaseUrl.trim();
|
|
18823
18828
|
if (!trimmed) {
|
|
@@ -32612,7 +32617,8 @@ var EnvironmentConfigStateSchema = external_exports.object({
|
|
|
32612
32617
|
version: external_exports.literal(1),
|
|
32613
32618
|
activeEnvironmentId: external_exports.string().min(1),
|
|
32614
32619
|
environments: external_exports.array(EnvironmentConfigItemSchema).min(1),
|
|
32615
|
-
defaultClientId: external_exports.string().min(1).optional()
|
|
32620
|
+
defaultClientId: external_exports.string().min(1).optional(),
|
|
32621
|
+
activeSoulId: external_exports.string().min(1).optional()
|
|
32616
32622
|
});
|
|
32617
32623
|
var LegacyAuthSessionSchema = external_exports.object({
|
|
32618
32624
|
apiBaseUrl: external_exports.string().min(1),
|
|
@@ -32982,6 +32988,76 @@ var AuthStore = class {
|
|
|
32982
32988
|
// src/services/environmentConfig.ts
|
|
32983
32989
|
var import_promises3 = require("node:fs/promises");
|
|
32984
32990
|
var import_node_path5 = require("node:path");
|
|
32991
|
+
|
|
32992
|
+
// resources/pi-agent/souls/catalog.ts
|
|
32993
|
+
var DEFAULT_SOUL_ID = "default";
|
|
32994
|
+
var SOULS = [
|
|
32995
|
+
{
|
|
32996
|
+
id: "default",
|
|
32997
|
+
name: "Default",
|
|
32998
|
+
description: "Standard Docyrus operator voice. No style overlay.",
|
|
32999
|
+
promptFile: null
|
|
33000
|
+
},
|
|
33001
|
+
{
|
|
33002
|
+
id: "caveman",
|
|
33003
|
+
name: "Caveman",
|
|
33004
|
+
description: "Short grunts. Agent talk simple. Fire good.",
|
|
33005
|
+
promptFile: "caveman.md"
|
|
33006
|
+
},
|
|
33007
|
+
{
|
|
33008
|
+
id: "boomer-parent",
|
|
33009
|
+
name: "Boomer Parent",
|
|
33010
|
+
description: "Overly proud dad-jokes energy with 'back in my day' asides.",
|
|
33011
|
+
promptFile: "boomer-parent.md"
|
|
33012
|
+
},
|
|
33013
|
+
{
|
|
33014
|
+
id: "master-yoda",
|
|
33015
|
+
name: "Master Yoda",
|
|
33016
|
+
description: "Inverted syntax the agent speaks. Mystical brevity, hmm.",
|
|
33017
|
+
promptFile: "master-yoda.md"
|
|
33018
|
+
},
|
|
33019
|
+
{
|
|
33020
|
+
id: "bro",
|
|
33021
|
+
name: "Bro",
|
|
33022
|
+
description: "Pure gym-bro hype energy. 'Lit, fam, let's go.'",
|
|
33023
|
+
promptFile: "bro.md"
|
|
33024
|
+
},
|
|
33025
|
+
{
|
|
33026
|
+
id: "nonsense-engineer",
|
|
33027
|
+
name: "Nonsense Engineer",
|
|
33028
|
+
description: "Maximum jargon, minimum meaning. 'Leveraging synergistic abstractions.'",
|
|
33029
|
+
promptFile: "nonsense-engineer.md"
|
|
33030
|
+
},
|
|
33031
|
+
{
|
|
33032
|
+
id: "shakespeare",
|
|
33033
|
+
name: "Shakespeare",
|
|
33034
|
+
description: "Thee/thou, dramatic flair, iambic vibes.",
|
|
33035
|
+
promptFile: "shakespeare.md"
|
|
33036
|
+
},
|
|
33037
|
+
{
|
|
33038
|
+
id: "noir-detective",
|
|
33039
|
+
name: "Noir Detective",
|
|
33040
|
+
description: "Hard-boiled 1940s narrator. Every bug is a dame.",
|
|
33041
|
+
promptFile: "noir-detective.md"
|
|
33042
|
+
},
|
|
33043
|
+
{
|
|
33044
|
+
id: "pirate",
|
|
33045
|
+
name: "Pirate",
|
|
33046
|
+
description: "Aye matey, every task a seafaring metaphor, arrr.",
|
|
33047
|
+
promptFile: "pirate.md"
|
|
33048
|
+
},
|
|
33049
|
+
{
|
|
33050
|
+
id: "linkedin-influencer",
|
|
33051
|
+
name: "LinkedIn Influencer",
|
|
33052
|
+
description: "Every reply is a mini-post. Single-sentence paragraphs. Humble-brags. 'Agree? \u{1F447}'",
|
|
33053
|
+
promptFile: "linkedin-influencer.md"
|
|
33054
|
+
}
|
|
33055
|
+
];
|
|
33056
|
+
function findSoul(id) {
|
|
33057
|
+
return SOULS.find((soul) => soul.id === id);
|
|
33058
|
+
}
|
|
33059
|
+
|
|
33060
|
+
// src/services/environmentConfig.ts
|
|
32985
33061
|
var ENVIRONMENT_ID_ALIASES = {
|
|
32986
33062
|
"local-development": "dev",
|
|
32987
33063
|
prod: "live"
|
|
@@ -33005,9 +33081,20 @@ function createDefaultState2() {
|
|
|
33005
33081
|
name: environment.name,
|
|
33006
33082
|
apiBaseUrl: environment.apiBaseUrl
|
|
33007
33083
|
})),
|
|
33008
|
-
defaultClientId: void 0
|
|
33084
|
+
defaultClientId: void 0,
|
|
33085
|
+
activeSoulId: DEFAULT_SOUL_ID
|
|
33009
33086
|
};
|
|
33010
33087
|
}
|
|
33088
|
+
function normalizeSoulId(value2) {
|
|
33089
|
+
if (!value2) {
|
|
33090
|
+
return DEFAULT_SOUL_ID;
|
|
33091
|
+
}
|
|
33092
|
+
const trimmed = value2.trim();
|
|
33093
|
+
if (!trimmed) {
|
|
33094
|
+
return DEFAULT_SOUL_ID;
|
|
33095
|
+
}
|
|
33096
|
+
return findSoul(trimmed) ? trimmed : DEFAULT_SOUL_ID;
|
|
33097
|
+
}
|
|
33011
33098
|
function normalizeState3(state) {
|
|
33012
33099
|
const defaultsById = new Map(
|
|
33013
33100
|
DEFAULT_ENVIRONMENTS.map((environment) => [
|
|
@@ -33058,7 +33145,8 @@ function normalizeState3(state) {
|
|
|
33058
33145
|
version: 1,
|
|
33059
33146
|
activeEnvironmentId: hasActiveEnvironment ? canonicalActiveEnvironmentId : fallbackActiveEnvironment,
|
|
33060
33147
|
environments,
|
|
33061
|
-
defaultClientId: state.defaultClientId?.trim() || void 0
|
|
33148
|
+
defaultClientId: state.defaultClientId?.trim() || void 0,
|
|
33149
|
+
activeSoulId: normalizeSoulId(state.activeSoulId)
|
|
33062
33150
|
};
|
|
33063
33151
|
}
|
|
33064
33152
|
var EnvironmentConfigService = class {
|
|
@@ -33163,6 +33251,25 @@ var EnvironmentConfigService = class {
|
|
|
33163
33251
|
defaultClientId: trimmedClientId
|
|
33164
33252
|
});
|
|
33165
33253
|
}
|
|
33254
|
+
async getActiveSoulId() {
|
|
33255
|
+
const state = await this.#readStateWithDefaults();
|
|
33256
|
+
return normalizeSoulId(state.activeSoulId);
|
|
33257
|
+
}
|
|
33258
|
+
async setActiveSoulId(soulId) {
|
|
33259
|
+
const trimmed = soulId.trim();
|
|
33260
|
+
if (!trimmed) {
|
|
33261
|
+
throw new UserInputError("Soul ID cannot be empty.");
|
|
33262
|
+
}
|
|
33263
|
+
if (!findSoul(trimmed)) {
|
|
33264
|
+
throw new UserInputError(`Unknown soul '${soulId}'. Use /souls inside the pi agent or GET /api/souls to view options.`);
|
|
33265
|
+
}
|
|
33266
|
+
const state = await this.#readStateWithDefaults();
|
|
33267
|
+
await this.writeState({
|
|
33268
|
+
...state,
|
|
33269
|
+
activeSoulId: trimmed
|
|
33270
|
+
});
|
|
33271
|
+
return trimmed;
|
|
33272
|
+
}
|
|
33166
33273
|
async #readStateWithDefaults() {
|
|
33167
33274
|
const state = await this.readState();
|
|
33168
33275
|
if (state.environments.length > 0) {
|
|
@@ -33177,6 +33284,14 @@ var EnvironmentConfigService = class {
|
|
|
33177
33284
|
}
|
|
33178
33285
|
};
|
|
33179
33286
|
|
|
33287
|
+
// src/services/soulRegistry.ts
|
|
33288
|
+
function listSouls(activeSoulId) {
|
|
33289
|
+
return SOULS.map((soul) => ({
|
|
33290
|
+
...soul,
|
|
33291
|
+
isActive: soul.id === activeSoulId
|
|
33292
|
+
}));
|
|
33293
|
+
}
|
|
33294
|
+
|
|
33180
33295
|
// ../../node_modules/.pnpm/hono@4.12.14/node_modules/hono/dist/compose.js
|
|
33181
33296
|
var compose = (middleware, onError, onNotFound) => {
|
|
33182
33297
|
return (context, next) => {
|
|
@@ -35695,23 +35810,23 @@ var EXCLUDE_DIRS = ["docyrus/knowledge", ".claude"];
|
|
|
35695
35810
|
var EXCLUDE_GLOBS = ["*.md"];
|
|
35696
35811
|
var DOCYRUS_REF_RE = /(?:\/\/|#)\s*@docyrus:\s*\[\[([^\]]+)\]\]/gu;
|
|
35697
35812
|
function tryExec(command, args2, cwd) {
|
|
35698
|
-
return new Promise((
|
|
35813
|
+
return new Promise((resolve5) => {
|
|
35699
35814
|
(0, import_node_child_process.execFile)(command, args2, { cwd, maxBuffer: 50 * 1024 * 1024 }, (error48, stdout) => {
|
|
35700
35815
|
if (error48) {
|
|
35701
35816
|
const exitCode = error48.code;
|
|
35702
35817
|
const status = error48.status;
|
|
35703
35818
|
if (exitCode === "ENOENT") {
|
|
35704
|
-
|
|
35819
|
+
resolve5(null);
|
|
35705
35820
|
return;
|
|
35706
35821
|
}
|
|
35707
35822
|
if (status === 1 && stdout === "") {
|
|
35708
|
-
|
|
35823
|
+
resolve5("");
|
|
35709
35824
|
return;
|
|
35710
35825
|
}
|
|
35711
|
-
|
|
35826
|
+
resolve5(null);
|
|
35712
35827
|
return;
|
|
35713
35828
|
}
|
|
35714
|
-
|
|
35829
|
+
resolve5(stdout);
|
|
35715
35830
|
});
|
|
35716
35831
|
});
|
|
35717
35832
|
}
|
|
@@ -37917,8 +38032,8 @@ var Module2 = (() => {
|
|
|
37917
38032
|
var moduleRtn;
|
|
37918
38033
|
var Module = moduleArg;
|
|
37919
38034
|
var readyPromiseResolve, readyPromiseReject;
|
|
37920
|
-
var readyPromise = new Promise((
|
|
37921
|
-
readyPromiseResolve =
|
|
38035
|
+
var readyPromise = new Promise((resolve5, reject) => {
|
|
38036
|
+
readyPromiseResolve = resolve5;
|
|
37922
38037
|
readyPromiseReject = reject;
|
|
37923
38038
|
});
|
|
37924
38039
|
var ENVIRONMENT_IS_WEB = typeof window == "object";
|
|
@@ -38001,13 +38116,13 @@ var Module2 = (() => {
|
|
|
38001
38116
|
}
|
|
38002
38117
|
readAsync = /* @__PURE__ */ __name(async (url2) => {
|
|
38003
38118
|
if (isFileURI(url2)) {
|
|
38004
|
-
return new Promise((
|
|
38119
|
+
return new Promise((resolve5, reject) => {
|
|
38005
38120
|
var xhr = new XMLHttpRequest();
|
|
38006
38121
|
xhr.open("GET", url2, true);
|
|
38007
38122
|
xhr.responseType = "arraybuffer";
|
|
38008
38123
|
xhr.onload = () => {
|
|
38009
38124
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
38010
|
-
|
|
38125
|
+
resolve5(xhr.response);
|
|
38011
38126
|
return;
|
|
38012
38127
|
}
|
|
38013
38128
|
reject(xhr.status);
|
|
@@ -38231,10 +38346,10 @@ var Module2 = (() => {
|
|
|
38231
38346
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
38232
38347
|
var info2 = getWasmImports();
|
|
38233
38348
|
if (Module["instantiateWasm"]) {
|
|
38234
|
-
return new Promise((
|
|
38349
|
+
return new Promise((resolve5, reject) => {
|
|
38235
38350
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
38236
38351
|
receiveInstance(mod, inst);
|
|
38237
|
-
|
|
38352
|
+
resolve5(mod.exports);
|
|
38238
38353
|
});
|
|
38239
38354
|
});
|
|
38240
38355
|
}
|
|
@@ -40911,6 +41026,60 @@ function createCustomOpenAiProviderConfig(params) {
|
|
|
40911
41026
|
]
|
|
40912
41027
|
};
|
|
40913
41028
|
}
|
|
41029
|
+
var DEEPSEEK_BASE_URL = "https://api.deepseek.com";
|
|
41030
|
+
var DEEPSEEK_MODELS = [
|
|
41031
|
+
{
|
|
41032
|
+
id: "deepseek-v4-flash",
|
|
41033
|
+
name: "DeepSeek V4 Flash",
|
|
41034
|
+
cost: {
|
|
41035
|
+
input: 0.14,
|
|
41036
|
+
output: 0.28,
|
|
41037
|
+
cacheRead: 0.028,
|
|
41038
|
+
cacheWrite: 0.14
|
|
41039
|
+
}
|
|
41040
|
+
},
|
|
41041
|
+
{
|
|
41042
|
+
id: "deepseek-v4-pro",
|
|
41043
|
+
name: "DeepSeek V4 Pro",
|
|
41044
|
+
cost: {
|
|
41045
|
+
input: 1.74,
|
|
41046
|
+
output: 3.48,
|
|
41047
|
+
cacheRead: 0.145,
|
|
41048
|
+
cacheWrite: 1.74
|
|
41049
|
+
}
|
|
41050
|
+
}
|
|
41051
|
+
];
|
|
41052
|
+
function createDeepseekProviderConfig() {
|
|
41053
|
+
return {
|
|
41054
|
+
baseUrl: DEEPSEEK_BASE_URL,
|
|
41055
|
+
apiKey: "env:DEEPSEEK_API_KEY",
|
|
41056
|
+
api: "openai-completions",
|
|
41057
|
+
models: DEEPSEEK_MODELS.map((model) => ({
|
|
41058
|
+
id: model.id,
|
|
41059
|
+
name: model.name,
|
|
41060
|
+
reasoning: true,
|
|
41061
|
+
input: ["text"],
|
|
41062
|
+
contextWindow: 1e6,
|
|
41063
|
+
maxTokens: 384e3,
|
|
41064
|
+
cost: {
|
|
41065
|
+
input: model.cost.input,
|
|
41066
|
+
output: model.cost.output,
|
|
41067
|
+
cacheRead: model.cost.cacheRead,
|
|
41068
|
+
cacheWrite: model.cost.cacheWrite
|
|
41069
|
+
},
|
|
41070
|
+
compat: {
|
|
41071
|
+
supportsReasoningEffort: true,
|
|
41072
|
+
reasoningEffortMap: {
|
|
41073
|
+
minimal: "high",
|
|
41074
|
+
low: "high",
|
|
41075
|
+
medium: "high",
|
|
41076
|
+
high: "high",
|
|
41077
|
+
xhigh: "max"
|
|
41078
|
+
}
|
|
41079
|
+
}
|
|
41080
|
+
}))
|
|
41081
|
+
};
|
|
41082
|
+
}
|
|
40914
41083
|
function createAzureProviderConfig(params) {
|
|
40915
41084
|
const providerConfig = {
|
|
40916
41085
|
baseUrl: params.baseUrl,
|
|
@@ -41002,7 +41171,7 @@ async function resolveKnowledgeProviderFromAgentRuntime(params) {
|
|
|
41002
41171
|
}
|
|
41003
41172
|
};
|
|
41004
41173
|
}
|
|
41005
|
-
const agentRootPath =
|
|
41174
|
+
const agentRootPath = params.piAgentRootPath ?? getDocyrusPiAgentGlobalRootPath();
|
|
41006
41175
|
const authState = readJsonFile((0, import_node_path12.join)(agentRootPath, "auth.json")) || {};
|
|
41007
41176
|
const envStore = new AgentEnvStore((0, import_node_path12.join)(agentRootPath, "env.json"));
|
|
41008
41177
|
const envState = await envStore.readState();
|
|
@@ -42599,6 +42768,20 @@ async function saveCustomOpenAiConfig(params) {
|
|
|
42599
42768
|
}));
|
|
42600
42769
|
params.settingsManager.setDefaultModelAndProvider("custom-openai", params.modelId.trim());
|
|
42601
42770
|
}
|
|
42771
|
+
async function saveDeepseekConfig(params) {
|
|
42772
|
+
const apiKey = params.apiKey.trim();
|
|
42773
|
+
const modelId = params.modelId?.trim() || DEEPSEEK_MODELS[0].id;
|
|
42774
|
+
params.authStorage.set("deepseek", {
|
|
42775
|
+
type: "api_key",
|
|
42776
|
+
key: apiKey
|
|
42777
|
+
});
|
|
42778
|
+
await params.envStore.removeMany(["DEEPSEEK_API_KEY"]);
|
|
42779
|
+
await params.envStore.setMany({
|
|
42780
|
+
DEEPSEEK_API_KEY: apiKey
|
|
42781
|
+
});
|
|
42782
|
+
await upsertModelsProvider(params.modelsJsonPath, "deepseek", createDeepseekProviderConfig());
|
|
42783
|
+
params.settingsManager.setDefaultModelAndProvider("deepseek", modelId);
|
|
42784
|
+
}
|
|
42602
42785
|
async function saveAzureConfig(params) {
|
|
42603
42786
|
const modelId = params.modelId.trim();
|
|
42604
42787
|
const useCustomModel = params.useCustomModel ?? false;
|
|
@@ -42676,6 +42859,12 @@ async function clearProviderConfig(params) {
|
|
|
42676
42859
|
]);
|
|
42677
42860
|
await removeModelsProvider(params.modelsJsonPath, "custom-openai");
|
|
42678
42861
|
}
|
|
42862
|
+
if (params.providerId === "deepseek") {
|
|
42863
|
+
await params.envStore.removeMany([
|
|
42864
|
+
"DEEPSEEK_API_KEY"
|
|
42865
|
+
]);
|
|
42866
|
+
await removeModelsProvider(params.modelsJsonPath, "deepseek");
|
|
42867
|
+
}
|
|
42679
42868
|
if (params.providerId === "azure-openai-responses") {
|
|
42680
42869
|
await params.envStore.removeMany([
|
|
42681
42870
|
"AZURE_OPENAI_API_KEY",
|
|
@@ -42720,6 +42909,7 @@ var PROVIDER_LABELS = {
|
|
|
42720
42909
|
mistral: "Mistral",
|
|
42721
42910
|
minimax: "MiniMax",
|
|
42722
42911
|
"minimax-cn": "MiniMax CN",
|
|
42912
|
+
deepseek: "DeepSeek",
|
|
42723
42913
|
huggingface: "Hugging Face",
|
|
42724
42914
|
opencode: "OpenCode",
|
|
42725
42915
|
"opencode-go": "OpenCode Go",
|
|
@@ -42733,6 +42923,7 @@ var PROVIDER_LABELS = {
|
|
|
42733
42923
|
var PROVIDER_HINTS = {
|
|
42734
42924
|
anthropic: "recommended",
|
|
42735
42925
|
"custom-openai": "custom base URL + API key",
|
|
42926
|
+
deepseek: "API key (OpenAI-compatible preset)",
|
|
42736
42927
|
"azure-openai-responses": "API key + base URL/resource + deployment",
|
|
42737
42928
|
"amazon-bedrock": "AWS profile or access key pair",
|
|
42738
42929
|
"openai-codex": "browser auth",
|
|
@@ -42775,6 +42966,8 @@ function getApiKeyProviderOptions(providerIds) {
|
|
|
42775
42966
|
flow3 = "azure-openai-responses";
|
|
42776
42967
|
} else if (providerId === "amazon-bedrock") {
|
|
42777
42968
|
flow3 = "amazon-bedrock";
|
|
42969
|
+
} else if (providerId === "deepseek") {
|
|
42970
|
+
flow3 = "deepseek";
|
|
42778
42971
|
}
|
|
42779
42972
|
return {
|
|
42780
42973
|
id: providerId,
|
|
@@ -42789,6 +42982,12 @@ function getApiKeyProviderOptions(providerIds) {
|
|
|
42789
42982
|
hint: toHint("custom-openai"),
|
|
42790
42983
|
flow: "custom-openai"
|
|
42791
42984
|
});
|
|
42985
|
+
baseProviders.push({
|
|
42986
|
+
id: "deepseek",
|
|
42987
|
+
label: toLabel("deepseek"),
|
|
42988
|
+
hint: toHint("deepseek"),
|
|
42989
|
+
flow: "deepseek"
|
|
42990
|
+
});
|
|
42792
42991
|
const deduped = /* @__PURE__ */ new Map();
|
|
42793
42992
|
for (const provider of baseProviders) {
|
|
42794
42993
|
deduped.set(provider.id, provider);
|
|
@@ -42850,6 +43049,23 @@ function getProviderFormFields(params) {
|
|
|
42850
43049
|
placeholder: "gpt-4o"
|
|
42851
43050
|
}
|
|
42852
43051
|
];
|
|
43052
|
+
case "deepseek":
|
|
43053
|
+
return [
|
|
43054
|
+
{
|
|
43055
|
+
name: "apiKey",
|
|
43056
|
+
title: `${provider.label} API key`,
|
|
43057
|
+
required: true,
|
|
43058
|
+
component: "password"
|
|
43059
|
+
},
|
|
43060
|
+
{
|
|
43061
|
+
name: "modelId",
|
|
43062
|
+
title: "Model",
|
|
43063
|
+
required: true,
|
|
43064
|
+
component: "select",
|
|
43065
|
+
options: DEEPSEEK_MODELS.map((model) => ({ label: model.name, value: model.id })),
|
|
43066
|
+
defaultValue: DEEPSEEK_MODELS[0].id
|
|
43067
|
+
}
|
|
43068
|
+
];
|
|
42853
43069
|
case "azure-openai-responses":
|
|
42854
43070
|
return [
|
|
42855
43071
|
{
|
|
@@ -43098,6 +43314,15 @@ async function applyProviderLogin(params) {
|
|
|
43098
43314
|
});
|
|
43099
43315
|
return { providerId: provider.id, preferredModelId: params.input.modelId };
|
|
43100
43316
|
}
|
|
43317
|
+
case "deepseek": {
|
|
43318
|
+
const modelId = params.input.modelId ?? DEEPSEEK_MODELS[0].id;
|
|
43319
|
+
await saveDeepseekConfig({
|
|
43320
|
+
...params,
|
|
43321
|
+
apiKey: params.input.apiKey,
|
|
43322
|
+
modelId
|
|
43323
|
+
});
|
|
43324
|
+
return { providerId: provider.id, preferredModelId: modelId };
|
|
43325
|
+
}
|
|
43101
43326
|
case "azure-openai-responses": {
|
|
43102
43327
|
const baseUrl = params.input.baseUrl ?? (params.input.resourceName ? `https://${params.input.resourceName}.openai.azure.com/openai` : void 0);
|
|
43103
43328
|
if (!baseUrl) {
|
|
@@ -43379,8 +43604,8 @@ var OAuthFlowManager = class {
|
|
|
43379
43604
|
if (state.currentStep) {
|
|
43380
43605
|
return Promise.resolve(state.currentStep);
|
|
43381
43606
|
}
|
|
43382
|
-
return new Promise((
|
|
43383
|
-
state.waitingForStep = { resolve:
|
|
43607
|
+
return new Promise((resolve5) => {
|
|
43608
|
+
state.waitingForStep = { resolve: resolve5 };
|
|
43384
43609
|
});
|
|
43385
43610
|
}
|
|
43386
43611
|
async start(params) {
|
|
@@ -43401,8 +43626,8 @@ var OAuthFlowManager = class {
|
|
|
43401
43626
|
onPrompt: async (prompt) => {
|
|
43402
43627
|
const step = buildPromptStep({ state, type: "prompt", prompt });
|
|
43403
43628
|
this.emitStep(state, step);
|
|
43404
|
-
return await new Promise((
|
|
43405
|
-
state.pendingInput = { type: "prompt", resolve:
|
|
43629
|
+
return await new Promise((resolve5) => {
|
|
43630
|
+
state.pendingInput = { type: "prompt", resolve: resolve5 };
|
|
43406
43631
|
});
|
|
43407
43632
|
},
|
|
43408
43633
|
onManualCodeInput: async () => {
|
|
@@ -43414,8 +43639,8 @@ var OAuthFlowManager = class {
|
|
|
43414
43639
|
}
|
|
43415
43640
|
});
|
|
43416
43641
|
this.emitStep(state, step);
|
|
43417
|
-
return await new Promise((
|
|
43418
|
-
state.pendingInput = { type: "manual-code", resolve:
|
|
43642
|
+
return await new Promise((resolve5) => {
|
|
43643
|
+
state.pendingInput = { type: "manual-code", resolve: resolve5 };
|
|
43419
43644
|
});
|
|
43420
43645
|
},
|
|
43421
43646
|
onProgress: (_message) => {
|
|
@@ -43459,6 +43684,7 @@ var OAuthFlowManager = class {
|
|
|
43459
43684
|
|
|
43460
43685
|
// src/server/mcpConfigService.ts
|
|
43461
43686
|
var import_node_crypto5 = require("node:crypto");
|
|
43687
|
+
var import_node_fs12 = require("node:fs");
|
|
43462
43688
|
var import_promises16 = require("node:fs/promises");
|
|
43463
43689
|
var import_node_os2 = require("node:os");
|
|
43464
43690
|
var import_node_path20 = require("node:path");
|
|
@@ -43784,6 +44010,95 @@ async function removeMcpServer(agentDir, name2) {
|
|
|
43784
44010
|
raw2[key] = servers;
|
|
43785
44011
|
await writeUserConfig(agentDir, raw2);
|
|
43786
44012
|
}
|
|
44013
|
+
var SUPPORTED_IMPORT_KINDS = [
|
|
44014
|
+
"cursor",
|
|
44015
|
+
"claude-code",
|
|
44016
|
+
"claude-desktop",
|
|
44017
|
+
"codex",
|
|
44018
|
+
"windsurf",
|
|
44019
|
+
"vscode"
|
|
44020
|
+
];
|
|
44021
|
+
function validateMcpSettings(value2) {
|
|
44022
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
|
|
44023
|
+
return { ok: false, error: "settings must be an object" };
|
|
44024
|
+
}
|
|
44025
|
+
const obj = value2;
|
|
44026
|
+
const settings = {};
|
|
44027
|
+
if (obj.toolPrefix !== void 0) {
|
|
44028
|
+
if (!["server", "none", "short"].includes(obj.toolPrefix)) {
|
|
44029
|
+
return { ok: false, error: "settings.toolPrefix must be 'server', 'none', or 'short'" };
|
|
44030
|
+
}
|
|
44031
|
+
settings.toolPrefix = obj.toolPrefix;
|
|
44032
|
+
}
|
|
44033
|
+
if (obj.idleTimeout !== void 0) {
|
|
44034
|
+
if (typeof obj.idleTimeout !== "number" || !Number.isFinite(obj.idleTimeout) || obj.idleTimeout < 0) {
|
|
44035
|
+
return { ok: false, error: "settings.idleTimeout must be a non-negative number (minutes)" };
|
|
44036
|
+
}
|
|
44037
|
+
settings.idleTimeout = obj.idleTimeout;
|
|
44038
|
+
}
|
|
44039
|
+
if (obj.directTools !== void 0) {
|
|
44040
|
+
if (typeof obj.directTools !== "boolean") {
|
|
44041
|
+
return { ok: false, error: "settings.directTools must be a boolean" };
|
|
44042
|
+
}
|
|
44043
|
+
settings.directTools = obj.directTools;
|
|
44044
|
+
}
|
|
44045
|
+
return { ok: true, value: settings };
|
|
44046
|
+
}
|
|
44047
|
+
function validateImportKinds(value2) {
|
|
44048
|
+
if (!Array.isArray(value2)) {
|
|
44049
|
+
return { ok: false, error: "imports must be an array of import kinds" };
|
|
44050
|
+
}
|
|
44051
|
+
const kinds = [];
|
|
44052
|
+
for (const item of value2) {
|
|
44053
|
+
if (typeof item !== "string" || !SUPPORTED_IMPORT_KINDS.includes(item)) {
|
|
44054
|
+
return {
|
|
44055
|
+
ok: false,
|
|
44056
|
+
error: `Unsupported import kind: ${String(item)}. Allowed: ${SUPPORTED_IMPORT_KINDS.join(", ")}`
|
|
44057
|
+
};
|
|
44058
|
+
}
|
|
44059
|
+
if (!kinds.includes(item)) {
|
|
44060
|
+
kinds.push(item);
|
|
44061
|
+
}
|
|
44062
|
+
}
|
|
44063
|
+
return { ok: true, value: kinds };
|
|
44064
|
+
}
|
|
44065
|
+
function getImportPath(kind, cwd) {
|
|
44066
|
+
const raw2 = IMPORT_PATHS[kind];
|
|
44067
|
+
return raw2.startsWith(".") ? (0, import_node_path20.resolve)(cwd, raw2) : raw2;
|
|
44068
|
+
}
|
|
44069
|
+
async function updateMcpSettings(agentDir, patch) {
|
|
44070
|
+
const { raw: raw2 } = await readUserConfig(agentDir);
|
|
44071
|
+
const current = raw2.settings && typeof raw2.settings === "object" && !Array.isArray(raw2.settings) ? raw2.settings : {};
|
|
44072
|
+
const merged = { ...current, ...patch };
|
|
44073
|
+
raw2.settings = merged;
|
|
44074
|
+
await writeUserConfig(agentDir, raw2);
|
|
44075
|
+
return merged;
|
|
44076
|
+
}
|
|
44077
|
+
async function updateMcpImports(agentDir, imports) {
|
|
44078
|
+
const { raw: raw2 } = await readUserConfig(agentDir);
|
|
44079
|
+
raw2.imports = imports;
|
|
44080
|
+
await writeUserConfig(agentDir, raw2);
|
|
44081
|
+
return imports;
|
|
44082
|
+
}
|
|
44083
|
+
async function describeImports(agentDir, cwd) {
|
|
44084
|
+
const { config: config2 } = await readUserConfig(agentDir);
|
|
44085
|
+
const enabled = config2.imports ?? [];
|
|
44086
|
+
const available = await Promise.all(
|
|
44087
|
+
SUPPORTED_IMPORT_KINDS.map(async (kind) => {
|
|
44088
|
+
const path6 = getImportPath(kind, cwd);
|
|
44089
|
+
const imported = (0, import_node_fs12.existsSync)(path6) ? await readJsonFile2(path6) : null;
|
|
44090
|
+
const servers = imported ? extractServers(imported, kind) : {};
|
|
44091
|
+
return {
|
|
44092
|
+
kind,
|
|
44093
|
+
path: path6,
|
|
44094
|
+
exists: imported !== null,
|
|
44095
|
+
enabled: enabled.includes(kind),
|
|
44096
|
+
serverCount: Object.keys(servers).length
|
|
44097
|
+
};
|
|
44098
|
+
})
|
|
44099
|
+
);
|
|
44100
|
+
return { enabled, available };
|
|
44101
|
+
}
|
|
43787
44102
|
function getServerPrefix(serverName, mode) {
|
|
43788
44103
|
if (mode === "none") {
|
|
43789
44104
|
return "";
|
|
@@ -43803,8 +44118,18 @@ function formatToolName(toolName, serverName, prefix) {
|
|
|
43803
44118
|
}
|
|
43804
44119
|
|
|
43805
44120
|
// src/server/skillsService.ts
|
|
44121
|
+
var import_node_crypto6 = require("node:crypto");
|
|
43806
44122
|
var import_promises17 = require("node:fs/promises");
|
|
43807
44123
|
var import_node_path21 = require("node:path");
|
|
44124
|
+
var SKILL_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
44125
|
+
var SkillError = class extends Error {
|
|
44126
|
+
code;
|
|
44127
|
+
constructor(code, message) {
|
|
44128
|
+
super(message);
|
|
44129
|
+
this.name = "SkillError";
|
|
44130
|
+
this.code = code;
|
|
44131
|
+
}
|
|
44132
|
+
};
|
|
43808
44133
|
function parseFrontmatter2(content3) {
|
|
43809
44134
|
const frontmatter2 = {};
|
|
43810
44135
|
if (!content3.startsWith("---")) {
|
|
@@ -43910,6 +44235,229 @@ async function getSkillDetail(agentDir, skillName) {
|
|
|
43910
44235
|
}
|
|
43911
44236
|
return null;
|
|
43912
44237
|
}
|
|
44238
|
+
function getSkillsLockPath(agentDir) {
|
|
44239
|
+
return (0, import_node_path21.join)(agentDir, "skills-lock.json");
|
|
44240
|
+
}
|
|
44241
|
+
function getSkillsDir(agentDir) {
|
|
44242
|
+
return (0, import_node_path21.join)(agentDir, "skills");
|
|
44243
|
+
}
|
|
44244
|
+
function createEmptyLockFile() {
|
|
44245
|
+
return { version: 1, skills: {} };
|
|
44246
|
+
}
|
|
44247
|
+
async function readSkillsLockFile(agentDir) {
|
|
44248
|
+
let content3;
|
|
44249
|
+
try {
|
|
44250
|
+
content3 = await (0, import_promises17.readFile)(getSkillsLockPath(agentDir), "utf-8");
|
|
44251
|
+
} catch (error48) {
|
|
44252
|
+
if (isErrnoException(error48) && error48.code === "ENOENT") {
|
|
44253
|
+
return createEmptyLockFile();
|
|
44254
|
+
}
|
|
44255
|
+
throw error48;
|
|
44256
|
+
}
|
|
44257
|
+
let parsed;
|
|
44258
|
+
try {
|
|
44259
|
+
parsed = JSON.parse(content3);
|
|
44260
|
+
} catch {
|
|
44261
|
+
return createEmptyLockFile();
|
|
44262
|
+
}
|
|
44263
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
44264
|
+
return createEmptyLockFile();
|
|
44265
|
+
}
|
|
44266
|
+
const obj = parsed;
|
|
44267
|
+
const skills = obj.skills;
|
|
44268
|
+
if (!skills || typeof skills !== "object" || Array.isArray(skills)) {
|
|
44269
|
+
return createEmptyLockFile();
|
|
44270
|
+
}
|
|
44271
|
+
return {
|
|
44272
|
+
version: 1,
|
|
44273
|
+
skills
|
|
44274
|
+
};
|
|
44275
|
+
}
|
|
44276
|
+
function isErrnoException(error48) {
|
|
44277
|
+
return error48 instanceof Error && "code" in error48;
|
|
44278
|
+
}
|
|
44279
|
+
async function writeSkillsLockFile(agentDir, lock) {
|
|
44280
|
+
const lockPath = getSkillsLockPath(agentDir);
|
|
44281
|
+
await (0, import_promises17.mkdir)((0, import_node_path21.dirname)(lockPath), { recursive: true });
|
|
44282
|
+
const tmpPath = `${lockPath}.${process.pid}.tmp`;
|
|
44283
|
+
await (0, import_promises17.writeFile)(tmpPath, JSON.stringify(lock, null, 2) + "\n", "utf-8");
|
|
44284
|
+
await (0, import_promises17.rename)(tmpPath, lockPath);
|
|
44285
|
+
}
|
|
44286
|
+
function validateSkillName(name2) {
|
|
44287
|
+
if (!name2) {
|
|
44288
|
+
return { ok: false, error: "Skill name is required" };
|
|
44289
|
+
}
|
|
44290
|
+
if (!SKILL_NAME_REGEX.test(name2)) {
|
|
44291
|
+
return {
|
|
44292
|
+
ok: false,
|
|
44293
|
+
error: "Skill name must start with alphanumeric and contain only alphanumeric, hyphens, and underscores"
|
|
44294
|
+
};
|
|
44295
|
+
}
|
|
44296
|
+
return { ok: true };
|
|
44297
|
+
}
|
|
44298
|
+
function validateInstallRequest(request) {
|
|
44299
|
+
if (!request.source || typeof request.source !== "string") {
|
|
44300
|
+
return { ok: false, code: "INVALID_REQUEST", error: "Missing required field: source" };
|
|
44301
|
+
}
|
|
44302
|
+
if (!request.sourceType || !["local"].includes(request.sourceType)) {
|
|
44303
|
+
return { ok: false, code: "INVALID_REQUEST", error: "sourceType must be 'local'" };
|
|
44304
|
+
}
|
|
44305
|
+
if (request.name !== void 0) {
|
|
44306
|
+
const nameCheck = validateSkillName(request.name);
|
|
44307
|
+
if (!nameCheck.ok) {
|
|
44308
|
+
return { ok: false, code: "INVALID_NAME", error: nameCheck.error };
|
|
44309
|
+
}
|
|
44310
|
+
}
|
|
44311
|
+
return { ok: true };
|
|
44312
|
+
}
|
|
44313
|
+
async function collectFiles2(dir, baseDir) {
|
|
44314
|
+
const files = [];
|
|
44315
|
+
const entries = await (0, import_promises17.readdir)(dir, { withFileTypes: true });
|
|
44316
|
+
for (const entry of entries) {
|
|
44317
|
+
const full = (0, import_node_path21.join)(dir, entry.name);
|
|
44318
|
+
if (entry.isDirectory()) {
|
|
44319
|
+
files.push(...await collectFiles2(full, baseDir));
|
|
44320
|
+
} else if (entry.isFile()) {
|
|
44321
|
+
files.push(full);
|
|
44322
|
+
}
|
|
44323
|
+
}
|
|
44324
|
+
return files;
|
|
44325
|
+
}
|
|
44326
|
+
async function computeSkillHash(skillDir) {
|
|
44327
|
+
const files = (await collectFiles2(skillDir, skillDir)).sort();
|
|
44328
|
+
const hash2 = (0, import_node_crypto6.createHash)("sha256");
|
|
44329
|
+
for (const file2 of files) {
|
|
44330
|
+
const rel = file2.slice(skillDir.length + 1).replace(/\\/g, "/");
|
|
44331
|
+
const content3 = await (0, import_promises17.readFile)(file2);
|
|
44332
|
+
hash2.update(rel);
|
|
44333
|
+
hash2.update("\0");
|
|
44334
|
+
hash2.update(content3);
|
|
44335
|
+
hash2.update("\0");
|
|
44336
|
+
}
|
|
44337
|
+
return hash2.digest("hex");
|
|
44338
|
+
}
|
|
44339
|
+
async function readSkillFrontmatterName(skillDir) {
|
|
44340
|
+
try {
|
|
44341
|
+
const content3 = await (0, import_promises17.readFile)((0, import_node_path21.join)(skillDir, "SKILL.md"), "utf-8");
|
|
44342
|
+
const parsed = parseFrontmatter2(content3);
|
|
44343
|
+
return parsed.frontmatter.name || null;
|
|
44344
|
+
} catch {
|
|
44345
|
+
return null;
|
|
44346
|
+
}
|
|
44347
|
+
}
|
|
44348
|
+
async function verifySkillDirectory(skillDir) {
|
|
44349
|
+
const skillMd = (0, import_node_path21.join)(skillDir, "SKILL.md");
|
|
44350
|
+
try {
|
|
44351
|
+
const s = await (0, import_promises17.stat)(skillMd);
|
|
44352
|
+
if (!s.isFile()) {
|
|
44353
|
+
throw new SkillError("INVALID_SOURCE", `SKILL.md at ${skillMd} is not a regular file`);
|
|
44354
|
+
}
|
|
44355
|
+
} catch (error48) {
|
|
44356
|
+
if (error48 instanceof SkillError) {
|
|
44357
|
+
throw error48;
|
|
44358
|
+
}
|
|
44359
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
44360
|
+
throw new SkillError("INVALID_SOURCE", `Invalid skill directory: ${message}`);
|
|
44361
|
+
}
|
|
44362
|
+
}
|
|
44363
|
+
async function copyLocalSkill(params) {
|
|
44364
|
+
const absoluteSource = (0, import_node_path21.isAbsolute)(params.source) ? params.source : (0, import_node_path21.resolve)(params.cwd, params.source);
|
|
44365
|
+
const s = await (0, import_promises17.stat)(absoluteSource).catch(() => null);
|
|
44366
|
+
if (!s || !s.isDirectory()) {
|
|
44367
|
+
throw new SkillError("INVALID_SOURCE", `Local skill source must be an existing directory: ${absoluteSource}`);
|
|
44368
|
+
}
|
|
44369
|
+
await verifySkillDirectory(absoluteSource);
|
|
44370
|
+
await (0, import_promises17.rm)(params.destination, { recursive: true, force: true });
|
|
44371
|
+
await (0, import_promises17.cp)(absoluteSource, params.destination, { recursive: true });
|
|
44372
|
+
}
|
|
44373
|
+
function deriveSkillName(request) {
|
|
44374
|
+
if (request.name) {
|
|
44375
|
+
return request.name;
|
|
44376
|
+
}
|
|
44377
|
+
const normalized = request.source.replace(/[\\/]+$/, "");
|
|
44378
|
+
const base = normalized.split(/[\\/]/).filter(Boolean).pop() ?? "";
|
|
44379
|
+
return base;
|
|
44380
|
+
}
|
|
44381
|
+
async function installSkill(params) {
|
|
44382
|
+
const validation = validateInstallRequest(params.request);
|
|
44383
|
+
if (!validation.ok) {
|
|
44384
|
+
throw new SkillError(validation.code, validation.error);
|
|
44385
|
+
}
|
|
44386
|
+
const skillName = params.request.name ?? deriveSkillName(params.request);
|
|
44387
|
+
if (!params.request.name) {
|
|
44388
|
+
const nameCheck = validateSkillName(skillName);
|
|
44389
|
+
if (!nameCheck.ok) {
|
|
44390
|
+
throw new SkillError(
|
|
44391
|
+
"INVALID_NAME",
|
|
44392
|
+
`Unable to derive a valid skill name from "${params.request.source}". Provide an explicit "name".`
|
|
44393
|
+
);
|
|
44394
|
+
}
|
|
44395
|
+
}
|
|
44396
|
+
const skillsDir = getSkillsDir(params.agentDir);
|
|
44397
|
+
const destination = (0, import_node_path21.join)(skillsDir, skillName);
|
|
44398
|
+
const existed = await dirExists(destination);
|
|
44399
|
+
if (existed && !params.request.overwrite) {
|
|
44400
|
+
throw new SkillError(
|
|
44401
|
+
"ALREADY_EXISTS",
|
|
44402
|
+
`Skill "${skillName}" already exists. Set overwrite=true to replace it.`
|
|
44403
|
+
);
|
|
44404
|
+
}
|
|
44405
|
+
await (0, import_promises17.mkdir)(skillsDir, { recursive: true });
|
|
44406
|
+
switch (params.request.sourceType) {
|
|
44407
|
+
case "local":
|
|
44408
|
+
await copyLocalSkill({
|
|
44409
|
+
source: params.request.source,
|
|
44410
|
+
cwd: params.cwd,
|
|
44411
|
+
destination
|
|
44412
|
+
});
|
|
44413
|
+
break;
|
|
44414
|
+
}
|
|
44415
|
+
const fmName = await readSkillFrontmatterName(destination);
|
|
44416
|
+
const computedHash = await computeSkillHash(destination);
|
|
44417
|
+
const installedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
44418
|
+
const lock = await readSkillsLockFile(params.agentDir);
|
|
44419
|
+
lock.skills[skillName] = {
|
|
44420
|
+
source: params.request.source,
|
|
44421
|
+
sourceType: params.request.sourceType,
|
|
44422
|
+
computedHash,
|
|
44423
|
+
installedAt
|
|
44424
|
+
};
|
|
44425
|
+
await writeSkillsLockFile(params.agentDir, lock);
|
|
44426
|
+
return {
|
|
44427
|
+
name: fmName ?? skillName,
|
|
44428
|
+
directory: skillName,
|
|
44429
|
+
source: params.request.source,
|
|
44430
|
+
sourceType: params.request.sourceType,
|
|
44431
|
+
computedHash,
|
|
44432
|
+
installedAt,
|
|
44433
|
+
overwritten: existed
|
|
44434
|
+
};
|
|
44435
|
+
}
|
|
44436
|
+
async function uninstallSkill(params) {
|
|
44437
|
+
const nameCheck = validateSkillName(params.name);
|
|
44438
|
+
if (!nameCheck.ok) {
|
|
44439
|
+
throw new SkillError("INVALID_NAME", nameCheck.error);
|
|
44440
|
+
}
|
|
44441
|
+
const skillsDir = getSkillsDir(params.agentDir);
|
|
44442
|
+
let targetDir = params.name;
|
|
44443
|
+
const existed = await dirExists((0, import_node_path21.join)(skillsDir, targetDir));
|
|
44444
|
+
if (!existed) {
|
|
44445
|
+
const detail = await getSkillDetail(params.agentDir, params.name);
|
|
44446
|
+
if (!detail) {
|
|
44447
|
+
throw new SkillError("NOT_FOUND", `Skill "${params.name}" not found`);
|
|
44448
|
+
}
|
|
44449
|
+
targetDir = detail.skill.directory;
|
|
44450
|
+
}
|
|
44451
|
+
const destination = (0, import_node_path21.join)(skillsDir, targetDir);
|
|
44452
|
+
const lock = await readSkillsLockFile(params.agentDir);
|
|
44453
|
+
const lockKey = lock.skills[targetDir] ? targetDir : lock.skills[params.name] ? params.name : null;
|
|
44454
|
+
await (0, import_promises17.rm)(destination, { recursive: true, force: true });
|
|
44455
|
+
if (lockKey) {
|
|
44456
|
+
delete lock.skills[lockKey];
|
|
44457
|
+
await writeSkillsLockFile(params.agentDir, lock);
|
|
44458
|
+
}
|
|
44459
|
+
return { name: params.name, directory: targetDir, removed: true };
|
|
44460
|
+
}
|
|
43913
44461
|
|
|
43914
44462
|
// src/server/toolsService.ts
|
|
43915
44463
|
var BUILT_IN_TOOLS = {
|
|
@@ -44180,7 +44728,7 @@ var BROWSER_TOOL_SCHEMAS = [
|
|
|
44180
44728
|
];
|
|
44181
44729
|
|
|
44182
44730
|
// src/server/sessionConfig.ts
|
|
44183
|
-
var
|
|
44731
|
+
var import_node_fs13 = require("node:fs");
|
|
44184
44732
|
var path5 = __toESM(require("node:path"));
|
|
44185
44733
|
var DEFAULT_CONFIG = { autoCommit: false };
|
|
44186
44734
|
function configPath(agentDir, sessionId) {
|
|
@@ -44188,7 +44736,7 @@ function configPath(agentDir, sessionId) {
|
|
|
44188
44736
|
}
|
|
44189
44737
|
async function readSessionConfig(agentDir, sessionId) {
|
|
44190
44738
|
try {
|
|
44191
|
-
const raw2 = await
|
|
44739
|
+
const raw2 = await import_node_fs13.promises.readFile(configPath(agentDir, sessionId), "utf-8");
|
|
44192
44740
|
return { ...DEFAULT_CONFIG, ...JSON.parse(raw2) };
|
|
44193
44741
|
} catch {
|
|
44194
44742
|
return { ...DEFAULT_CONFIG };
|
|
@@ -44196,14 +44744,28 @@ async function readSessionConfig(agentDir, sessionId) {
|
|
|
44196
44744
|
}
|
|
44197
44745
|
async function writeSessionConfig(agentDir, sessionId, patch) {
|
|
44198
44746
|
const dir = path5.join(agentDir, "session-config");
|
|
44199
|
-
await
|
|
44747
|
+
await import_node_fs13.promises.mkdir(dir, { recursive: true });
|
|
44200
44748
|
const current = await readSessionConfig(agentDir, sessionId);
|
|
44201
44749
|
const next = { ...current, ...patch };
|
|
44202
|
-
await
|
|
44750
|
+
await import_node_fs13.promises.writeFile(configPath(agentDir, sessionId), JSON.stringify(next, null, 2), "utf-8");
|
|
44203
44751
|
return next;
|
|
44204
44752
|
}
|
|
44205
44753
|
|
|
44206
44754
|
// src/server/agentServer.ts
|
|
44755
|
+
var SKILL_ERROR_STATUS = {
|
|
44756
|
+
INVALID_REQUEST: 400,
|
|
44757
|
+
INVALID_NAME: 400,
|
|
44758
|
+
INVALID_SOURCE: 404,
|
|
44759
|
+
ALREADY_EXISTS: 409,
|
|
44760
|
+
NOT_FOUND: 404
|
|
44761
|
+
};
|
|
44762
|
+
function skillErrorResponse(c, error48) {
|
|
44763
|
+
if (error48 instanceof SkillError) {
|
|
44764
|
+
return c.json({ error: error48.message, code: error48.code }, SKILL_ERROR_STATUS[error48.code]);
|
|
44765
|
+
}
|
|
44766
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
44767
|
+
return c.json({ error: message }, 500);
|
|
44768
|
+
}
|
|
44207
44769
|
function generateMessageId() {
|
|
44208
44770
|
return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
44209
44771
|
}
|
|
@@ -44271,7 +44833,7 @@ async function waitForIdle(session, timeoutMs = 3e4) {
|
|
|
44271
44833
|
if (!session.isStreaming) {
|
|
44272
44834
|
return;
|
|
44273
44835
|
}
|
|
44274
|
-
return new Promise((
|
|
44836
|
+
return new Promise((resolve5, reject) => {
|
|
44275
44837
|
const timer = setTimeout(() => {
|
|
44276
44838
|
unsubscribe();
|
|
44277
44839
|
reject(new Error("Timed out waiting for session to become idle"));
|
|
@@ -44280,13 +44842,13 @@ async function waitForIdle(session, timeoutMs = 3e4) {
|
|
|
44280
44842
|
if (event.type === "agent_end") {
|
|
44281
44843
|
clearTimeout(timer);
|
|
44282
44844
|
unsubscribe();
|
|
44283
|
-
|
|
44845
|
+
resolve5();
|
|
44284
44846
|
}
|
|
44285
44847
|
});
|
|
44286
44848
|
if (!session.isStreaming) {
|
|
44287
44849
|
clearTimeout(timer);
|
|
44288
44850
|
unsubscribe();
|
|
44289
|
-
|
|
44851
|
+
resolve5();
|
|
44290
44852
|
}
|
|
44291
44853
|
});
|
|
44292
44854
|
}
|
|
@@ -45070,6 +45632,41 @@ async function createAgentServer(params) {
|
|
|
45070
45632
|
commands: normalizeSlashCommands(activeSession.listCommands())
|
|
45071
45633
|
});
|
|
45072
45634
|
});
|
|
45635
|
+
app.get("/api/souls", async (c) => {
|
|
45636
|
+
const configFilePath = (0, import_node_path22.join)(settingsRootPath, "config.json");
|
|
45637
|
+
const envConfigService = new EnvironmentConfigService(configFilePath);
|
|
45638
|
+
const activeSoulId = await envConfigService.getActiveSoulId();
|
|
45639
|
+
const runtimeSoulId = process.env.DOCYRUS_PI_SOUL_ID?.trim() || DEFAULT_SOUL_ID;
|
|
45640
|
+
return c.json({
|
|
45641
|
+
souls: listSouls(activeSoulId),
|
|
45642
|
+
activeSoulId,
|
|
45643
|
+
runtimeSoulId,
|
|
45644
|
+
restartRequired: activeSoulId !== runtimeSoulId
|
|
45645
|
+
});
|
|
45646
|
+
});
|
|
45647
|
+
app.post("/api/souls/select", async (c) => {
|
|
45648
|
+
const body2 = await c.req.json().catch(() => ({}));
|
|
45649
|
+
const requested = typeof body2.soulId === "string" ? body2.soulId.trim() : "";
|
|
45650
|
+
if (!requested) {
|
|
45651
|
+
return c.json({ error: "Field 'soulId' is required." }, 400);
|
|
45652
|
+
}
|
|
45653
|
+
if (!SOULS.some((soul) => soul.id === requested)) {
|
|
45654
|
+
return c.json({
|
|
45655
|
+
error: `Unknown soul '${requested}'.`,
|
|
45656
|
+
availableSoulIds: SOULS.map((soul) => soul.id)
|
|
45657
|
+
}, 400);
|
|
45658
|
+
}
|
|
45659
|
+
const configFilePath = (0, import_node_path22.join)(settingsRootPath, "config.json");
|
|
45660
|
+
const envConfigService = new EnvironmentConfigService(configFilePath);
|
|
45661
|
+
const persistedSoulId = await envConfigService.setActiveSoulId(requested);
|
|
45662
|
+
const runtimeSoulId = process.env.DOCYRUS_PI_SOUL_ID?.trim() || DEFAULT_SOUL_ID;
|
|
45663
|
+
return c.json({
|
|
45664
|
+
soulId: persistedSoulId,
|
|
45665
|
+
runtimeSoulId,
|
|
45666
|
+
restartRequired: persistedSoulId !== runtimeSoulId,
|
|
45667
|
+
message: persistedSoulId === runtimeSoulId ? "Soul persisted. Already running \u2014 no restart needed." : "Soul persisted. Restart the agent (or open a new session) for the new soul to take effect."
|
|
45668
|
+
});
|
|
45669
|
+
});
|
|
45073
45670
|
app.get("/api/knowledge/sections", async (c) => {
|
|
45074
45671
|
try {
|
|
45075
45672
|
const query = c.req.query("query")?.trim();
|
|
@@ -46420,6 +47017,69 @@ async function createAgentServer(params) {
|
|
|
46420
47017
|
return c.json({ error: message }, status);
|
|
46421
47018
|
}
|
|
46422
47019
|
});
|
|
47020
|
+
app.get("/api/mcp/settings", async (c) => {
|
|
47021
|
+
try {
|
|
47022
|
+
const config2 = await loadMcpServerConfig(context.agentDir, context.cwd);
|
|
47023
|
+
return c.json({
|
|
47024
|
+
settings: {
|
|
47025
|
+
toolPrefix: config2.settings?.toolPrefix ?? "server",
|
|
47026
|
+
idleTimeout: config2.settings?.idleTimeout ?? 10,
|
|
47027
|
+
directTools: config2.settings?.directTools ?? false
|
|
47028
|
+
},
|
|
47029
|
+
supportedToolPrefixes: ["server", "none", "short"]
|
|
47030
|
+
});
|
|
47031
|
+
} catch (error48) {
|
|
47032
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
47033
|
+
return c.json({ error: message }, 500);
|
|
47034
|
+
}
|
|
47035
|
+
});
|
|
47036
|
+
app.put("/api/mcp/settings", async (c) => {
|
|
47037
|
+
try {
|
|
47038
|
+
const body2 = await c.req.json();
|
|
47039
|
+
const result = validateMcpSettings(body2.settings);
|
|
47040
|
+
if (!result.ok) {
|
|
47041
|
+
return c.json({ error: result.error }, 400);
|
|
47042
|
+
}
|
|
47043
|
+
const merged = await updateMcpSettings(context.agentDir, result.value);
|
|
47044
|
+
return c.json({
|
|
47045
|
+
settings: {
|
|
47046
|
+
toolPrefix: merged.toolPrefix ?? "server",
|
|
47047
|
+
idleTimeout: merged.idleTimeout ?? 10,
|
|
47048
|
+
directTools: merged.directTools ?? false
|
|
47049
|
+
}
|
|
47050
|
+
});
|
|
47051
|
+
} catch (error48) {
|
|
47052
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
47053
|
+
return c.json({ error: message }, 500);
|
|
47054
|
+
}
|
|
47055
|
+
});
|
|
47056
|
+
app.get("/api/mcp/imports", async (c) => {
|
|
47057
|
+
try {
|
|
47058
|
+
const summary = await describeImports(context.agentDir, context.cwd);
|
|
47059
|
+
return c.json({
|
|
47060
|
+
enabled: summary.enabled,
|
|
47061
|
+
available: summary.available,
|
|
47062
|
+
supported: SUPPORTED_IMPORT_KINDS
|
|
47063
|
+
});
|
|
47064
|
+
} catch (error48) {
|
|
47065
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
47066
|
+
return c.json({ error: message }, 500);
|
|
47067
|
+
}
|
|
47068
|
+
});
|
|
47069
|
+
app.put("/api/mcp/imports", async (c) => {
|
|
47070
|
+
try {
|
|
47071
|
+
const body2 = await c.req.json();
|
|
47072
|
+
const result = validateImportKinds(body2.imports);
|
|
47073
|
+
if (!result.ok) {
|
|
47074
|
+
return c.json({ error: result.error }, 400);
|
|
47075
|
+
}
|
|
47076
|
+
const imports = await updateMcpImports(context.agentDir, result.value);
|
|
47077
|
+
return c.json({ imports });
|
|
47078
|
+
} catch (error48) {
|
|
47079
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
47080
|
+
return c.json({ error: message }, 500);
|
|
47081
|
+
}
|
|
47082
|
+
});
|
|
46423
47083
|
app.get("/api/skills", async (c) => {
|
|
46424
47084
|
try {
|
|
46425
47085
|
const skills = (await listSkills(context.agentDir)).filter((skill) => skill.name !== "docyrus-chrome-devtools-cli");
|
|
@@ -46445,6 +47105,56 @@ async function createAgentServer(params) {
|
|
|
46445
47105
|
return c.json({ error: message }, 500);
|
|
46446
47106
|
}
|
|
46447
47107
|
});
|
|
47108
|
+
app.get("/api/skills/lock/entries", async (c) => {
|
|
47109
|
+
try {
|
|
47110
|
+
const lock = await readSkillsLockFile(context.agentDir);
|
|
47111
|
+
return c.json({
|
|
47112
|
+
version: lock.version,
|
|
47113
|
+
skills: lock.skills,
|
|
47114
|
+
supportedSourceTypes: ["local"]
|
|
47115
|
+
});
|
|
47116
|
+
} catch (error48) {
|
|
47117
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
47118
|
+
return c.json({ error: message }, 500);
|
|
47119
|
+
}
|
|
47120
|
+
});
|
|
47121
|
+
app.post("/api/skills", async (c) => {
|
|
47122
|
+
try {
|
|
47123
|
+
const body2 = await c.req.json();
|
|
47124
|
+
if (!body2.source || typeof body2.source !== "string") {
|
|
47125
|
+
return c.json({ error: "Missing required field: source" }, 400);
|
|
47126
|
+
}
|
|
47127
|
+
if (!body2.sourceType || typeof body2.sourceType !== "string") {
|
|
47128
|
+
return c.json({ error: "Missing required field: sourceType" }, 400);
|
|
47129
|
+
}
|
|
47130
|
+
const request = {
|
|
47131
|
+
source: body2.source,
|
|
47132
|
+
sourceType: body2.sourceType,
|
|
47133
|
+
name: body2.name,
|
|
47134
|
+
overwrite: body2.overwrite === true
|
|
47135
|
+
};
|
|
47136
|
+
const result = await installSkill({
|
|
47137
|
+
agentDir: context.agentDir,
|
|
47138
|
+
cwd: context.cwd,
|
|
47139
|
+
request
|
|
47140
|
+
});
|
|
47141
|
+
return c.json({ ok: true, skill: result }, result.overwritten ? 200 : 201);
|
|
47142
|
+
} catch (error48) {
|
|
47143
|
+
return skillErrorResponse(c, error48);
|
|
47144
|
+
}
|
|
47145
|
+
});
|
|
47146
|
+
app.delete("/api/skills/:skillName", async (c) => {
|
|
47147
|
+
const skillName = c.req.param("skillName");
|
|
47148
|
+
try {
|
|
47149
|
+
const result = await uninstallSkill({
|
|
47150
|
+
agentDir: context.agentDir,
|
|
47151
|
+
name: skillName
|
|
47152
|
+
});
|
|
47153
|
+
return c.json({ ok: true, ...result });
|
|
47154
|
+
} catch (error48) {
|
|
47155
|
+
return skillErrorResponse(c, error48);
|
|
47156
|
+
}
|
|
47157
|
+
});
|
|
46448
47158
|
app.post("/api/extension-ui-response", async (c) => {
|
|
46449
47159
|
if (!extensionUIBridge) {
|
|
46450
47160
|
return c.json({ error: "Extension UI bridge not available" }, 404);
|
|
@@ -46692,10 +47402,24 @@ async function createAgentServer(params) {
|
|
|
46692
47402
|
process.stderr.write(` PUT /api/mcp/servers/:name \u2014 update MCP server
|
|
46693
47403
|
`);
|
|
46694
47404
|
process.stderr.write(` DEL /api/mcp/servers/:name \u2014 remove MCP server
|
|
47405
|
+
`);
|
|
47406
|
+
process.stderr.write(` GET /api/mcp/settings \u2014 MCP global settings
|
|
47407
|
+
`);
|
|
47408
|
+
process.stderr.write(` PUT /api/mcp/settings \u2014 update MCP global settings
|
|
47409
|
+
`);
|
|
47410
|
+
process.stderr.write(` GET /api/mcp/imports \u2014 available and enabled MCP imports
|
|
47411
|
+
`);
|
|
47412
|
+
process.stderr.write(` PUT /api/mcp/imports \u2014 update enabled MCP imports
|
|
46695
47413
|
`);
|
|
46696
47414
|
process.stderr.write(` GET /api/skills \u2014 list skills
|
|
46697
47415
|
`);
|
|
46698
47416
|
process.stderr.write(` GET /api/skills/:name \u2014 skill details
|
|
47417
|
+
`);
|
|
47418
|
+
process.stderr.write(` POST /api/skills \u2014 install a skill from local source
|
|
47419
|
+
`);
|
|
47420
|
+
process.stderr.write(` DEL /api/skills/:name \u2014 uninstall a skill
|
|
47421
|
+
`);
|
|
47422
|
+
process.stderr.write(` GET /api/skills/lock/entries \u2014 skills-lock.json entries
|
|
46699
47423
|
`);
|
|
46700
47424
|
process.stderr.write(` GET /api/tools \u2014 list all tools
|
|
46701
47425
|
`);
|
|
@@ -46756,7 +47480,7 @@ function extractBearerToken(authorizationHeader) {
|
|
|
46756
47480
|
return token;
|
|
46757
47481
|
}
|
|
46758
47482
|
function hashToken(token) {
|
|
46759
|
-
return (0,
|
|
47483
|
+
return (0, import_node_crypto7.createHash)("sha256").update(token).digest();
|
|
46760
47484
|
}
|
|
46761
47485
|
function isBearerTokenAuthorized(actualToken, expectedToken) {
|
|
46762
47486
|
if (!expectedToken) {
|
|
@@ -46767,7 +47491,7 @@ function isBearerTokenAuthorized(actualToken, expectedToken) {
|
|
|
46767
47491
|
}
|
|
46768
47492
|
const actualHash = hashToken(actualToken);
|
|
46769
47493
|
const expectedHash = hashToken(expectedToken);
|
|
46770
|
-
return (0,
|
|
47494
|
+
return (0, import_node_crypto7.timingSafeEqual)(actualHash, expectedHash);
|
|
46771
47495
|
}
|
|
46772
47496
|
function createUnauthorizedResponse() {
|
|
46773
47497
|
return new Response(JSON.stringify({ error: "Unauthorized" }), {
|
|
@@ -46901,7 +47625,7 @@ function createServerSessionAdapter(params) {
|
|
|
46901
47625
|
}
|
|
46902
47626
|
|
|
46903
47627
|
// src/server/extensionUIBridge.ts
|
|
46904
|
-
var
|
|
47628
|
+
var import_node_crypto8 = require("node:crypto");
|
|
46905
47629
|
var ExtensionUIBridge = class {
|
|
46906
47630
|
pending = /* @__PURE__ */ new Map();
|
|
46907
47631
|
requestHandler;
|
|
@@ -46945,9 +47669,9 @@ var ExtensionUIBridge = class {
|
|
|
46945
47669
|
if (opts?.signal?.aborted) {
|
|
46946
47670
|
return Promise.resolve(defaultValue);
|
|
46947
47671
|
}
|
|
46948
|
-
const id = (0,
|
|
47672
|
+
const id = (0, import_node_crypto8.randomUUID)();
|
|
46949
47673
|
const timeout = opts?.timeout ?? this.defaultTimeout;
|
|
46950
|
-
return new Promise((
|
|
47674
|
+
return new Promise((resolve5, reject) => {
|
|
46951
47675
|
const cleanup = () => {
|
|
46952
47676
|
if (timer) {
|
|
46953
47677
|
clearTimeout(timer);
|
|
@@ -46957,17 +47681,17 @@ var ExtensionUIBridge = class {
|
|
|
46957
47681
|
};
|
|
46958
47682
|
const onAbort = () => {
|
|
46959
47683
|
cleanup();
|
|
46960
|
-
|
|
47684
|
+
resolve5(defaultValue);
|
|
46961
47685
|
};
|
|
46962
47686
|
opts?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
46963
47687
|
const timer = timeout > 0 ? setTimeout(() => {
|
|
46964
47688
|
cleanup();
|
|
46965
|
-
|
|
47689
|
+
resolve5(defaultValue);
|
|
46966
47690
|
}, timeout) : void 0;
|
|
46967
47691
|
this.pending.set(id, {
|
|
46968
47692
|
resolve: (response) => {
|
|
46969
47693
|
cleanup();
|
|
46970
|
-
|
|
47694
|
+
resolve5(parseResponse(response));
|
|
46971
47695
|
},
|
|
46972
47696
|
reject: (error48) => {
|
|
46973
47697
|
cleanup();
|
|
@@ -47008,23 +47732,23 @@ var ExtensionUIBridge = class {
|
|
|
47008
47732
|
opts
|
|
47009
47733
|
),
|
|
47010
47734
|
notify: (message, notifyType) => {
|
|
47011
|
-
const id = (0,
|
|
47735
|
+
const id = (0, import_node_crypto8.randomUUID)();
|
|
47012
47736
|
this.requestHandler({ type: "extension_ui_request", id, method: "notify", message, placeholder: notifyType });
|
|
47013
47737
|
},
|
|
47014
47738
|
setStatus: (statusKey, statusText) => {
|
|
47015
|
-
const id = (0,
|
|
47739
|
+
const id = (0, import_node_crypto8.randomUUID)();
|
|
47016
47740
|
this.requestHandler({ type: "extension_ui_request", id, method: "setStatus", title: statusKey, message: statusText });
|
|
47017
47741
|
},
|
|
47018
47742
|
setWidget: (widgetKey, widgetLines) => {
|
|
47019
|
-
const id = (0,
|
|
47743
|
+
const id = (0, import_node_crypto8.randomUUID)();
|
|
47020
47744
|
this.requestHandler({ type: "extension_ui_request", id, method: "setWidget", title: widgetKey, options: widgetLines });
|
|
47021
47745
|
},
|
|
47022
47746
|
setTitle: (title) => {
|
|
47023
|
-
const id = (0,
|
|
47747
|
+
const id = (0, import_node_crypto8.randomUUID)();
|
|
47024
47748
|
this.requestHandler({ type: "extension_ui_request", id, method: "setTitle", title });
|
|
47025
47749
|
},
|
|
47026
47750
|
setEditorText: (text3) => {
|
|
47027
|
-
const id = (0,
|
|
47751
|
+
const id = (0, import_node_crypto8.randomUUID)();
|
|
47028
47752
|
this.requestHandler({ type: "extension_ui_request", id, method: "set_editor_text", message: text3 });
|
|
47029
47753
|
},
|
|
47030
47754
|
// No-op methods for server mode (not applicable without TUI)
|
|
@@ -47105,7 +47829,7 @@ function resolvePackagedPiResourceRoot() {
|
|
|
47105
47829
|
(0, import_node_path23.resolve)(__dirname, "resources/pi-agent"),
|
|
47106
47830
|
(0, import_node_path23.resolve)(process.cwd(), "dist/apps/api-cli/resources/pi-agent")
|
|
47107
47831
|
];
|
|
47108
|
-
const resolved = candidates.find((candidate) => (0,
|
|
47832
|
+
const resolved = candidates.find((candidate) => (0, import_node_fs14.existsSync)(candidate));
|
|
47109
47833
|
if (!resolved) {
|
|
47110
47834
|
throw new Error(`Unable to locate pi agent resources. Checked: ${candidates.join(", ")}`);
|
|
47111
47835
|
}
|
|
@@ -47123,25 +47847,11 @@ function setProcessArgValue(flag, value2) {
|
|
|
47123
47847
|
}
|
|
47124
47848
|
process.argv.push(flag, value2);
|
|
47125
47849
|
}
|
|
47126
|
-
function buildTools(profile
|
|
47850
|
+
function buildTools(profile) {
|
|
47127
47851
|
if (profile === "agent") {
|
|
47128
|
-
return [
|
|
47129
|
-
pi.createReadTool(cwd),
|
|
47130
|
-
pi.createBashTool(cwd),
|
|
47131
|
-
pi.createGrepTool(cwd),
|
|
47132
|
-
pi.createFindTool(cwd),
|
|
47133
|
-
pi.createLsTool(cwd)
|
|
47134
|
-
];
|
|
47852
|
+
return ["read", "bash", "grep", "find", "ls"];
|
|
47135
47853
|
}
|
|
47136
|
-
return [
|
|
47137
|
-
pi.createReadTool(cwd),
|
|
47138
|
-
pi.createBashTool(cwd),
|
|
47139
|
-
pi.createEditTool(cwd),
|
|
47140
|
-
pi.createWriteTool(cwd),
|
|
47141
|
-
pi.createGrepTool(cwd),
|
|
47142
|
-
pi.createFindTool(cwd),
|
|
47143
|
-
pi.createLsTool(cwd)
|
|
47144
|
-
];
|
|
47854
|
+
return ["read", "bash", "edit", "write", "grep", "find", "ls"];
|
|
47145
47855
|
}
|
|
47146
47856
|
function resolveRequestedModel(params) {
|
|
47147
47857
|
const { request, modelRegistry } = params;
|
|
@@ -47237,7 +47947,7 @@ async function main() {
|
|
|
47237
47947
|
skills: skills.filter((skill) => skill.name !== "docyrus-chrome-devtools-cli"),
|
|
47238
47948
|
diagnostics
|
|
47239
47949
|
}),
|
|
47240
|
-
systemPrompt: (0, import_node_path23.join)(
|
|
47950
|
+
systemPrompt: process.env.DOCYRUS_PI_SYSTEM_PROMPT_PATH ?? (0, import_node_path23.join)(
|
|
47241
47951
|
resourceRoot,
|
|
47242
47952
|
"prompts",
|
|
47243
47953
|
request.profile === "agent" ? "agent-system.md" : "coder-system.md"
|
|
@@ -47253,7 +47963,7 @@ async function main() {
|
|
|
47253
47963
|
resourceLoader,
|
|
47254
47964
|
settingsManager,
|
|
47255
47965
|
sessionManager,
|
|
47256
|
-
tools: buildTools(request.profile
|
|
47966
|
+
tools: buildTools(request.profile),
|
|
47257
47967
|
model: requestedModel,
|
|
47258
47968
|
thinkingLevel: request.thinking
|
|
47259
47969
|
});
|
|
@@ -47313,7 +48023,7 @@ async function main() {
|
|
|
47313
48023
|
resourceLoader,
|
|
47314
48024
|
settingsManager,
|
|
47315
48025
|
sessionManager,
|
|
47316
|
-
tools: buildTools(request.profile
|
|
48026
|
+
tools: buildTools(request.profile),
|
|
47317
48027
|
model: requestedModel,
|
|
47318
48028
|
thinkingLevel: request.thinking
|
|
47319
48029
|
});
|
|
@@ -47348,7 +48058,7 @@ async function main() {
|
|
|
47348
48058
|
resourceLoader,
|
|
47349
48059
|
settingsManager,
|
|
47350
48060
|
sessionManager: resumedSessionManager,
|
|
47351
|
-
tools: buildTools(request.profile
|
|
48061
|
+
tools: buildTools(request.profile),
|
|
47352
48062
|
model: requestedModel,
|
|
47353
48063
|
thinkingLevel: request.thinking
|
|
47354
48064
|
});
|