@docyrus/docyrus 0.0.70 → 0.0.72
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/agent-loader.js +1 -1
- package/agent-loader.js.map +2 -2
- package/main.js +79 -19
- package/main.js.map +3 -3
- package/package.json +3 -3
- package/server-loader.js +186 -81
- package/server-loader.js.map +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docyrus/docyrus",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.72",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Docyrus API CLI",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"@clack/prompts": "^0.11.0",
|
|
15
15
|
"@ff-labs/fff-node": "0.6.4",
|
|
16
16
|
"@hono/node-server": "^1.19.13",
|
|
17
|
-
"@mariozechner/pi-ai": "0.71.
|
|
18
|
-
"@mariozechner/pi-coding-agent": "0.71.
|
|
17
|
+
"@mariozechner/pi-ai": "0.71.1",
|
|
18
|
+
"@mariozechner/pi-coding-agent": "0.71.1",
|
|
19
19
|
"@modelcontextprotocol/ext-apps": "^1.2.2",
|
|
20
20
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
21
21
|
"@mozilla/readability": "^0.6.0",
|
package/server-loader.js
CHANGED
|
@@ -35692,12 +35692,27 @@ function createEventBridge(params) {
|
|
|
35692
35692
|
handleToolExecutionEnd(event);
|
|
35693
35693
|
break;
|
|
35694
35694
|
}
|
|
35695
|
+
case "message_end": {
|
|
35696
|
+
handleMessageEnd(event);
|
|
35697
|
+
break;
|
|
35698
|
+
}
|
|
35695
35699
|
case "agent_end": {
|
|
35696
35700
|
onDone();
|
|
35697
35701
|
break;
|
|
35698
35702
|
}
|
|
35699
35703
|
}
|
|
35700
35704
|
}
|
|
35705
|
+
function handleMessageEnd(event) {
|
|
35706
|
+
const message = event.message;
|
|
35707
|
+
if (!message) {
|
|
35708
|
+
return;
|
|
35709
|
+
}
|
|
35710
|
+
const stopReason = message.stopReason;
|
|
35711
|
+
if (stopReason !== "error" && stopReason !== "aborted") {
|
|
35712
|
+
return;
|
|
35713
|
+
}
|
|
35714
|
+
onError(extractAssistantEventErrorMessage(message));
|
|
35715
|
+
}
|
|
35701
35716
|
function handleMessageUpdate(event) {
|
|
35702
35717
|
const assistantEvent = event.assistantMessageEvent;
|
|
35703
35718
|
if (!assistantEvent) {
|
|
@@ -45351,88 +45366,11 @@ async function createAgentServer(params) {
|
|
|
45351
45366
|
modelIdsByProvider: getModelIdsByProvider()
|
|
45352
45367
|
});
|
|
45353
45368
|
}
|
|
45354
|
-
|
|
45355
|
-
app.use("/*", async (c, next) => {
|
|
45356
|
-
const unauthorizedResponse = authorizeServerRequest(c.req.raw, authToken);
|
|
45357
|
-
if (unauthorizedResponse) {
|
|
45358
|
-
return unauthorizedResponse;
|
|
45359
|
-
}
|
|
45360
|
-
await next();
|
|
45361
|
-
});
|
|
45362
|
-
app.get("/api/health", (c) => {
|
|
45363
|
-
return c.json({ ok: true });
|
|
45364
|
-
});
|
|
45365
|
-
app.get("/api/status", (c) => {
|
|
45366
|
-
return c.json({
|
|
45367
|
-
isStreaming: activeSession.isStreaming,
|
|
45368
|
-
model: activeSession.model ? { provider: activeSession.model.provider, id: activeSession.model.id } : null,
|
|
45369
|
-
mode: sessionMode
|
|
45370
|
-
});
|
|
45371
|
-
});
|
|
45372
|
-
app.post("/api/chat", async (c) => {
|
|
45373
|
-
const body2 = await c.req.json();
|
|
45374
|
-
const messages = body2.messages ?? [];
|
|
45375
|
-
if (body2.sessionId && body2.sessionId.trim() !== activeSession.id?.trim()) {
|
|
45376
|
-
try {
|
|
45377
|
-
activeSession = await onResumeSession(body2.sessionId);
|
|
45378
|
-
sessionMode = "normal";
|
|
45379
|
-
} catch (error48) {
|
|
45380
|
-
const msg = error48 instanceof Error ? error48.message : String(error48);
|
|
45381
|
-
return c.json({ error: `Failed to resume session: ${msg}` }, 400);
|
|
45382
|
-
}
|
|
45383
|
-
}
|
|
45384
|
-
const chatUnavailableReason = getChatUnavailableReason({ session: activeSession });
|
|
45385
|
-
if (chatUnavailableReason) {
|
|
45386
|
-
return c.json({ error: chatUnavailableReason }, 409);
|
|
45387
|
-
}
|
|
45388
|
-
const sessionId = body2.sessionId?.trim() || activeSession.id?.trim() || "active";
|
|
45389
|
-
const askUserResponse = extractAskUserToolResponse(messages);
|
|
45390
|
-
const pendingAskUser = pendingAskUserRequests.get(sessionId);
|
|
45391
|
-
const userMessage = askUserResponse ? pendingAskUser && pendingAskUser.toolCallId === askUserResponse.toolCallId ? formatAskUserResponsePrompt(askUserResponse.response) : void 0 : extractLastUserText(messages);
|
|
45392
|
-
if (!userMessage) {
|
|
45393
|
-
return c.json({
|
|
45394
|
-
error: askUserResponse ? "No matching pending ask_user request found" : "No user message found"
|
|
45395
|
-
}, 400);
|
|
45396
|
-
}
|
|
45397
|
-
if (askUserResponse) {
|
|
45398
|
-
pendingAskUserRequests.delete(sessionId);
|
|
45399
|
-
}
|
|
45400
|
-
let promptText = userMessage;
|
|
45401
|
-
if (!askUserResponse) {
|
|
45402
|
-
const modeCmd = parseModeSlashCommand(userMessage);
|
|
45403
|
-
if (modeCmd) {
|
|
45404
|
-
if (activeSession.isStreaming) {
|
|
45405
|
-
await activeSession.abort();
|
|
45406
|
-
await waitForIdle(activeSession);
|
|
45407
|
-
}
|
|
45408
|
-
await activeSession.prompt(`/${modeCmd.command}`);
|
|
45409
|
-
sessionMode = SESSION_MODE_COMMANDS[modeCmd.command] ?? sessionMode;
|
|
45410
|
-
if (!modeCmd.remainder) {
|
|
45411
|
-
const notifEncoder = new TextEncoder();
|
|
45412
|
-
const notifMessageId = generateMessageId();
|
|
45413
|
-
return c.body(
|
|
45414
|
-
makeModeNotificationStream({ command: modeCmd.command, messageId: notifMessageId, encoder: notifEncoder }),
|
|
45415
|
-
{
|
|
45416
|
-
headers: {
|
|
45417
|
-
"Content-Type": "text/event-stream",
|
|
45418
|
-
"Cache-Control": "no-cache",
|
|
45419
|
-
"Connection": "keep-alive",
|
|
45420
|
-
"x-vercel-ai-ui-message-stream": "v1"
|
|
45421
|
-
}
|
|
45422
|
-
}
|
|
45423
|
-
);
|
|
45424
|
-
}
|
|
45425
|
-
promptText = modeCmd.remainder;
|
|
45426
|
-
}
|
|
45427
|
-
}
|
|
45428
|
-
if (activeSession.isStreaming) {
|
|
45429
|
-
await activeSession.abort();
|
|
45430
|
-
await waitForIdle(activeSession);
|
|
45431
|
-
}
|
|
45369
|
+
function createPromptStreamResponse(promptText, sessionId) {
|
|
45432
45370
|
const messageId = generateMessageId();
|
|
45433
45371
|
const encoder = new TextEncoder();
|
|
45434
45372
|
const stream = new ReadableStream({
|
|
45435
|
-
start(controller) {
|
|
45373
|
+
async start(controller) {
|
|
45436
45374
|
let closed = false;
|
|
45437
45375
|
function writeChunk(chunk) {
|
|
45438
45376
|
if (closed) {
|
|
@@ -45456,6 +45394,10 @@ async function createAgentServer(params) {
|
|
|
45456
45394
|
} catch {
|
|
45457
45395
|
}
|
|
45458
45396
|
}
|
|
45397
|
+
if (activeSession.isStreaming) {
|
|
45398
|
+
await activeSession.abort();
|
|
45399
|
+
await waitForIdle(activeSession);
|
|
45400
|
+
}
|
|
45459
45401
|
writeChunk({ type: "start" });
|
|
45460
45402
|
writeChunk({ type: "start-step" });
|
|
45461
45403
|
let extensionUICleanup;
|
|
@@ -45535,7 +45477,7 @@ async function createAgentServer(params) {
|
|
|
45535
45477
|
});
|
|
45536
45478
|
}
|
|
45537
45479
|
});
|
|
45538
|
-
return
|
|
45480
|
+
return new Response(stream, {
|
|
45539
45481
|
headers: {
|
|
45540
45482
|
"Content-Type": "text/event-stream",
|
|
45541
45483
|
"Cache-Control": "no-cache",
|
|
@@ -45543,6 +45485,119 @@ async function createAgentServer(params) {
|
|
|
45543
45485
|
"x-vercel-ai-ui-message-stream": "v1"
|
|
45544
45486
|
}
|
|
45545
45487
|
});
|
|
45488
|
+
}
|
|
45489
|
+
app.use("/*", cors({ origin: "*" }));
|
|
45490
|
+
app.use("/*", async (c, next) => {
|
|
45491
|
+
const unauthorizedResponse = authorizeServerRequest(c.req.raw, authToken);
|
|
45492
|
+
if (unauthorizedResponse) {
|
|
45493
|
+
return unauthorizedResponse;
|
|
45494
|
+
}
|
|
45495
|
+
await next();
|
|
45496
|
+
});
|
|
45497
|
+
app.get("/api/health", (c) => {
|
|
45498
|
+
return c.json({ ok: true });
|
|
45499
|
+
});
|
|
45500
|
+
app.get("/api/status", (c) => {
|
|
45501
|
+
return c.json({
|
|
45502
|
+
isStreaming: activeSession.isStreaming,
|
|
45503
|
+
model: activeSession.model ? { provider: activeSession.model.provider, id: activeSession.model.id } : null,
|
|
45504
|
+
mode: sessionMode
|
|
45505
|
+
});
|
|
45506
|
+
});
|
|
45507
|
+
app.post("/api/chat", async (c) => {
|
|
45508
|
+
const body2 = await c.req.json();
|
|
45509
|
+
const messages = body2.messages ?? [];
|
|
45510
|
+
if (body2.sessionId && body2.sessionId.trim() !== activeSession.id?.trim()) {
|
|
45511
|
+
try {
|
|
45512
|
+
activeSession = await onResumeSession(body2.sessionId);
|
|
45513
|
+
sessionMode = "normal";
|
|
45514
|
+
} catch (error48) {
|
|
45515
|
+
const msg = error48 instanceof Error ? error48.message : String(error48);
|
|
45516
|
+
return c.json({ error: `Failed to resume session: ${msg}` }, 400);
|
|
45517
|
+
}
|
|
45518
|
+
}
|
|
45519
|
+
const chatUnavailableReason = getChatUnavailableReason({ session: activeSession });
|
|
45520
|
+
if (chatUnavailableReason) {
|
|
45521
|
+
return c.json({ error: chatUnavailableReason }, 409);
|
|
45522
|
+
}
|
|
45523
|
+
const sessionId = body2.sessionId?.trim() || activeSession.id?.trim() || "active";
|
|
45524
|
+
const askUserResponse = extractAskUserToolResponse(messages);
|
|
45525
|
+
const pendingAskUser = pendingAskUserRequests.get(sessionId);
|
|
45526
|
+
const userMessage = askUserResponse ? pendingAskUser && pendingAskUser.toolCallId === askUserResponse.toolCallId ? formatAskUserResponsePrompt(askUserResponse.response) : void 0 : extractLastUserText(messages);
|
|
45527
|
+
if (!userMessage) {
|
|
45528
|
+
return c.json({
|
|
45529
|
+
error: askUserResponse ? "No matching pending ask_user request found" : "No user message found"
|
|
45530
|
+
}, 400);
|
|
45531
|
+
}
|
|
45532
|
+
if (askUserResponse) {
|
|
45533
|
+
pendingAskUserRequests.delete(sessionId);
|
|
45534
|
+
}
|
|
45535
|
+
let promptText = userMessage;
|
|
45536
|
+
if (!askUserResponse) {
|
|
45537
|
+
const modeCmd = parseModeSlashCommand(userMessage);
|
|
45538
|
+
if (modeCmd) {
|
|
45539
|
+
if (activeSession.isStreaming) {
|
|
45540
|
+
await activeSession.abort();
|
|
45541
|
+
await waitForIdle(activeSession);
|
|
45542
|
+
}
|
|
45543
|
+
await activeSession.prompt(`/${modeCmd.command}`);
|
|
45544
|
+
sessionMode = SESSION_MODE_COMMANDS[modeCmd.command] ?? sessionMode;
|
|
45545
|
+
if (!modeCmd.remainder) {
|
|
45546
|
+
const notifEncoder = new TextEncoder();
|
|
45547
|
+
const notifMessageId = generateMessageId();
|
|
45548
|
+
return c.body(
|
|
45549
|
+
makeModeNotificationStream({ command: modeCmd.command, messageId: notifMessageId, encoder: notifEncoder }),
|
|
45550
|
+
{
|
|
45551
|
+
headers: {
|
|
45552
|
+
"Content-Type": "text/event-stream",
|
|
45553
|
+
"Cache-Control": "no-cache",
|
|
45554
|
+
"Connection": "keep-alive",
|
|
45555
|
+
"x-vercel-ai-ui-message-stream": "v1"
|
|
45556
|
+
}
|
|
45557
|
+
}
|
|
45558
|
+
);
|
|
45559
|
+
}
|
|
45560
|
+
promptText = modeCmd.remainder;
|
|
45561
|
+
}
|
|
45562
|
+
}
|
|
45563
|
+
return createPromptStreamResponse(promptText, sessionId);
|
|
45564
|
+
});
|
|
45565
|
+
app.post("/api/chat/retry", async (c) => {
|
|
45566
|
+
const body2 = await c.req.json().catch(() => ({}));
|
|
45567
|
+
if (body2.sessionId && body2.sessionId.trim() !== activeSession.id?.trim()) {
|
|
45568
|
+
try {
|
|
45569
|
+
activeSession = await onResumeSession(body2.sessionId);
|
|
45570
|
+
sessionMode = "normal";
|
|
45571
|
+
} catch (error48) {
|
|
45572
|
+
const msg = error48 instanceof Error ? error48.message : String(error48);
|
|
45573
|
+
return c.json({ error: `Failed to resume session: ${msg}` }, 400);
|
|
45574
|
+
}
|
|
45575
|
+
}
|
|
45576
|
+
const chatUnavailableReason = getChatUnavailableReason({ session: activeSession });
|
|
45577
|
+
if (chatUnavailableReason) {
|
|
45578
|
+
return c.json({ error: chatUnavailableReason }, 409);
|
|
45579
|
+
}
|
|
45580
|
+
const userMessages = activeSession.getUserMessagesForForking();
|
|
45581
|
+
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
45582
|
+
if (!lastUserMessage) {
|
|
45583
|
+
return c.json({ error: "Session has no user message to retry" }, 404);
|
|
45584
|
+
}
|
|
45585
|
+
if (activeSession.isStreaming) {
|
|
45586
|
+
await activeSession.abort();
|
|
45587
|
+
await waitForIdle(activeSession);
|
|
45588
|
+
}
|
|
45589
|
+
try {
|
|
45590
|
+
const navigation = await activeSession.navigateTree(lastUserMessage.entryId);
|
|
45591
|
+
if (navigation.cancelled) {
|
|
45592
|
+
return c.json({ error: "Retry cancelled by session" }, 409);
|
|
45593
|
+
}
|
|
45594
|
+
} catch (error48) {
|
|
45595
|
+
const msg = error48 instanceof Error ? error48.message : String(error48);
|
|
45596
|
+
return c.json({ error: `Failed to rewind session for retry: ${msg}` }, 500);
|
|
45597
|
+
}
|
|
45598
|
+
const sessionId = body2.sessionId?.trim() || activeSession.id?.trim() || "active";
|
|
45599
|
+
pendingAskUserRequests.delete(sessionId);
|
|
45600
|
+
return createPromptStreamResponse(lastUserMessage.text, sessionId);
|
|
45546
45601
|
});
|
|
45547
45602
|
app.post("/api/chat/abort", async (c) => {
|
|
45548
45603
|
if (!activeSession.isStreaming) {
|
|
@@ -45644,6 +45699,35 @@ async function createAgentServer(params) {
|
|
|
45644
45699
|
return c.json({ error: message }, 500);
|
|
45645
45700
|
}
|
|
45646
45701
|
});
|
|
45702
|
+
app.delete("/api/sessions/:sessionId", async (c) => {
|
|
45703
|
+
const sessionId = c.req.param("sessionId");
|
|
45704
|
+
try {
|
|
45705
|
+
const activeId = activeSession.id?.trim();
|
|
45706
|
+
if (activeId && activeId === sessionId) {
|
|
45707
|
+
return c.json({
|
|
45708
|
+
error: "Cannot delete the active session. Create or switch to a different session first."
|
|
45709
|
+
}, 409);
|
|
45710
|
+
}
|
|
45711
|
+
const sessions = await sessionManager.list();
|
|
45712
|
+
const match2 = sessions.find((s) => s.id === sessionId);
|
|
45713
|
+
if (!match2) {
|
|
45714
|
+
return c.json({ error: "Session not found" }, 404);
|
|
45715
|
+
}
|
|
45716
|
+
if (match2.path) {
|
|
45717
|
+
await (0, import_promises18.rm)(match2.path, { force: true });
|
|
45718
|
+
}
|
|
45719
|
+
const sessionConfigPath = (0, import_node_path22.join)(
|
|
45720
|
+
resolveDocyrusTrackedSessionConfigRootPath(context.cwd),
|
|
45721
|
+
`${sessionId}.json`
|
|
45722
|
+
);
|
|
45723
|
+
await (0, import_promises18.rm)(sessionConfigPath, { force: true }).catch(() => {
|
|
45724
|
+
});
|
|
45725
|
+
return c.body(null, 204);
|
|
45726
|
+
} catch (error48) {
|
|
45727
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
45728
|
+
return c.json({ error: message }, 500);
|
|
45729
|
+
}
|
|
45730
|
+
});
|
|
45647
45731
|
app.get("/api/sessions/:sessionId/messages", async (c) => {
|
|
45648
45732
|
const sessionId = c.req.param("sessionId");
|
|
45649
45733
|
try {
|
|
@@ -47362,6 +47446,8 @@ async function createAgentServer(params) {
|
|
|
47362
47446
|
|
|
47363
47447
|
`);
|
|
47364
47448
|
process.stderr.write(` POST /api/chat \u2014 send chat messages (SSE UIMessage stream)
|
|
47449
|
+
`);
|
|
47450
|
+
process.stderr.write(` POST /api/chat/retry \u2014 retry the last user message after an error
|
|
47365
47451
|
`);
|
|
47366
47452
|
process.stderr.write(` POST /api/chat/abort \u2014 abort active chat stream
|
|
47367
47453
|
`);
|
|
@@ -47372,6 +47458,8 @@ async function createAgentServer(params) {
|
|
|
47372
47458
|
process.stderr.write(` GET /api/sessions \u2014 list sessions
|
|
47373
47459
|
`);
|
|
47374
47460
|
process.stderr.write(` POST /api/sessions \u2014 create a new session
|
|
47461
|
+
`);
|
|
47462
|
+
process.stderr.write(` DEL /api/sessions/:sessionId \u2014 delete a session
|
|
47375
47463
|
`);
|
|
47376
47464
|
process.stderr.write(` GET /api/sessions/:sessionId/messages \u2014 session messages
|
|
47377
47465
|
`);
|
|
@@ -47605,6 +47693,12 @@ var SERVER_MODE_ALLOWED_MODEL_IDS_BY_PROVIDER = {
|
|
|
47605
47693
|
minimax: [
|
|
47606
47694
|
"MiniMax-M2.7",
|
|
47607
47695
|
"MiniMax-M2.7-highspeed"
|
|
47696
|
+
],
|
|
47697
|
+
moonshotai: [
|
|
47698
|
+
"kimi-k2.6"
|
|
47699
|
+
],
|
|
47700
|
+
deepseek: [
|
|
47701
|
+
"deepseek-v4-pro"
|
|
47608
47702
|
]
|
|
47609
47703
|
};
|
|
47610
47704
|
var ALLOWED_MODEL_IDS_BY_PROVIDER = Object.fromEntries(
|
|
@@ -47689,6 +47783,17 @@ function createServerSessionAdapter(params) {
|
|
|
47689
47783
|
listCommands() {
|
|
47690
47784
|
const getCommands = params.extensionsResult.runtime.getCommands;
|
|
47691
47785
|
return typeof getCommands === "function" ? getCommands() : [];
|
|
47786
|
+
},
|
|
47787
|
+
getUserMessagesForForking() {
|
|
47788
|
+
const fn = params.session.getUserMessagesForForking;
|
|
47789
|
+
return typeof fn === "function" ? fn.call(params.session) : [];
|
|
47790
|
+
},
|
|
47791
|
+
navigateTree(targetId, options) {
|
|
47792
|
+
const fn = params.session.navigateTree;
|
|
47793
|
+
if (typeof fn !== "function") {
|
|
47794
|
+
return Promise.resolve({ cancelled: true });
|
|
47795
|
+
}
|
|
47796
|
+
return fn.call(params.session, targetId, options);
|
|
47692
47797
|
}
|
|
47693
47798
|
};
|
|
47694
47799
|
}
|
|
@@ -47990,7 +48095,7 @@ async function main() {
|
|
|
47990
48095
|
process.env.PI_SKIP_VERSION_CHECK = "1";
|
|
47991
48096
|
settingsManager.setQuietStartup(true);
|
|
47992
48097
|
settingsManager.setCollapseChangelog(true);
|
|
47993
|
-
settingsManager.setLastChangelogVersion(version2);
|
|
48098
|
+
settingsManager.setLastChangelogVersion(pi.VERSION || version2);
|
|
47994
48099
|
}
|
|
47995
48100
|
renderStartupSplash(version2);
|
|
47996
48101
|
const spinner = createSpinner("Loading agent...");
|