poe-code 3.0.73 → 3.0.75
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/cli/commands/ralph.js +1 -3
- package/dist/cli/commands/ralph.js.map +1 -1
- package/dist/cli/commands/spawn.js +3 -3
- package/dist/cli/commands/spawn.js.map +1 -1
- package/dist/cli/service-registry.d.ts +1 -0
- package/dist/cli/service-registry.js.map +1 -1
- package/dist/index.js +2026 -102
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-code.js +1 -0
- package/dist/providers/claude-code.js.map +2 -2
- package/dist/providers/codex.js +1 -0
- package/dist/providers/codex.js.map +2 -2
- package/dist/providers/create-provider.d.ts +1 -0
- package/dist/providers/create-provider.js +1 -0
- package/dist/providers/create-provider.js.map +1 -1
- package/dist/providers/kimi.js +1 -0
- package/dist/providers/kimi.js.map +2 -2
- package/dist/providers/opencode.js +1 -0
- package/dist/providers/opencode.js.map +2 -2
- package/dist/providers/poe-agent.d.ts +3 -1
- package/dist/providers/poe-agent.js +1510 -15
- package/dist/providers/poe-agent.js.map +4 -4
- package/dist/sdk/spawn.js +6 -1
- package/dist/sdk/spawn.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6471,13 +6471,13 @@ var init_acp_transport = __esm({
|
|
|
6471
6471
|
env,
|
|
6472
6472
|
requestTimeoutMs,
|
|
6473
6473
|
firstRequestId,
|
|
6474
|
-
spawn:
|
|
6474
|
+
spawn: spawn7 = spawnChildProcess4
|
|
6475
6475
|
} = options;
|
|
6476
6476
|
this.command = command;
|
|
6477
6477
|
this.closed = new Promise((resolve) => {
|
|
6478
6478
|
this.resolveClosed = resolve;
|
|
6479
6479
|
});
|
|
6480
|
-
this.child =
|
|
6480
|
+
this.child = spawn7(command, [...args], {
|
|
6481
6481
|
cwd,
|
|
6482
6482
|
env,
|
|
6483
6483
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -7466,6 +7466,7 @@ function createProvider(opts) {
|
|
|
7466
7466
|
branding: opts.branding,
|
|
7467
7467
|
disabled: opts.disabled,
|
|
7468
7468
|
supportsStdinPrompt: opts.supportsStdinPrompt,
|
|
7469
|
+
supportsMcpSpawn: opts.supportsMcpSpawn,
|
|
7469
7470
|
configurePrompts: opts.configurePrompts,
|
|
7470
7471
|
postConfigureMessages: opts.postConfigureMessages,
|
|
7471
7472
|
isolatedEnv: opts.isolatedEnv,
|
|
@@ -7695,17 +7696,1433 @@ var init_chat = __esm({
|
|
|
7695
7696
|
}
|
|
7696
7697
|
});
|
|
7697
7698
|
|
|
7699
|
+
// packages/tiny-mcp-client/src/internal.ts
|
|
7700
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
7701
|
+
import { PassThrough } from "node:stream";
|
|
7702
|
+
function defaultStdioSpawn(command, args, options) {
|
|
7703
|
+
return spawn4(command, args, options);
|
|
7704
|
+
}
|
|
7705
|
+
function defaultHttpTransportFetch(input, init) {
|
|
7706
|
+
return fetch(input, init);
|
|
7707
|
+
}
|
|
7708
|
+
function serializeJsonRpcMessage2(message) {
|
|
7709
|
+
return `${JSON.stringify(message)}
|
|
7710
|
+
`;
|
|
7711
|
+
}
|
|
7712
|
+
function chunkToString3(chunk) {
|
|
7713
|
+
if (typeof chunk === "string") {
|
|
7714
|
+
return chunk;
|
|
7715
|
+
}
|
|
7716
|
+
if (chunk instanceof Uint8Array) {
|
|
7717
|
+
return Buffer.from(chunk).toString("utf8");
|
|
7718
|
+
}
|
|
7719
|
+
return String(chunk);
|
|
7720
|
+
}
|
|
7721
|
+
function normalizeLine2(line) {
|
|
7722
|
+
return line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
7723
|
+
}
|
|
7724
|
+
async function* readLines3(stream) {
|
|
7725
|
+
let buffer = "";
|
|
7726
|
+
for await (const chunk of stream) {
|
|
7727
|
+
buffer += chunkToString3(chunk);
|
|
7728
|
+
while (true) {
|
|
7729
|
+
const newlineIndex = buffer.indexOf("\n");
|
|
7730
|
+
if (newlineIndex === -1) {
|
|
7731
|
+
break;
|
|
7732
|
+
}
|
|
7733
|
+
const line = buffer.slice(0, newlineIndex);
|
|
7734
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
7735
|
+
yield normalizeLine2(line);
|
|
7736
|
+
}
|
|
7737
|
+
}
|
|
7738
|
+
if (buffer.length > 0) {
|
|
7739
|
+
yield normalizeLine2(buffer);
|
|
7740
|
+
}
|
|
7741
|
+
}
|
|
7742
|
+
function isObjectRecord3(value) {
|
|
7743
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7744
|
+
}
|
|
7745
|
+
function hasOwn2(value, property) {
|
|
7746
|
+
return Object.prototype.hasOwnProperty.call(value, property);
|
|
7747
|
+
}
|
|
7748
|
+
function isRequestId2(value) {
|
|
7749
|
+
return typeof value === "string" || typeof value === "number";
|
|
7750
|
+
}
|
|
7751
|
+
function isLogLevel(value) {
|
|
7752
|
+
return value === "debug" || value === "info" || value === "notice" || value === "warning" || value === "error" || value === "critical" || value === "alert" || value === "emergency";
|
|
7753
|
+
}
|
|
7754
|
+
function toRequestId2(value) {
|
|
7755
|
+
return isRequestId2(value) ? value : null;
|
|
7756
|
+
}
|
|
7757
|
+
function parseError2() {
|
|
7758
|
+
return new McpError(ERROR_PARSE, "Parse error");
|
|
7759
|
+
}
|
|
7760
|
+
function invalidRequest2() {
|
|
7761
|
+
return new McpError(ERROR_INVALID_REQUEST, "Invalid Request");
|
|
7762
|
+
}
|
|
7763
|
+
function isJsonRpcErrorObject2(value) {
|
|
7764
|
+
if (!isObjectRecord3(value)) {
|
|
7765
|
+
return false;
|
|
7766
|
+
}
|
|
7767
|
+
if (typeof value.code !== "number" || typeof value.message !== "string") {
|
|
7768
|
+
return false;
|
|
7769
|
+
}
|
|
7770
|
+
return value.data === void 0 || hasOwn2(value, "data");
|
|
7771
|
+
}
|
|
7772
|
+
function parseJsonRpcPayload(parsed) {
|
|
7773
|
+
if (!isObjectRecord3(parsed)) {
|
|
7774
|
+
return {
|
|
7775
|
+
type: "invalid",
|
|
7776
|
+
id: null,
|
|
7777
|
+
error: invalidRequest2()
|
|
7778
|
+
};
|
|
7779
|
+
}
|
|
7780
|
+
const id = toRequestId2(parsed.id);
|
|
7781
|
+
if (parsed.jsonrpc !== "2.0") {
|
|
7782
|
+
return {
|
|
7783
|
+
type: "invalid",
|
|
7784
|
+
id,
|
|
7785
|
+
error: invalidRequest2()
|
|
7786
|
+
};
|
|
7787
|
+
}
|
|
7788
|
+
const hasMethod = hasOwn2(parsed, "method");
|
|
7789
|
+
const hasId = hasOwn2(parsed, "id");
|
|
7790
|
+
if (hasMethod) {
|
|
7791
|
+
if (typeof parsed.method !== "string") {
|
|
7792
|
+
return {
|
|
7793
|
+
type: "invalid",
|
|
7794
|
+
id,
|
|
7795
|
+
error: invalidRequest2()
|
|
7796
|
+
};
|
|
7797
|
+
}
|
|
7798
|
+
if (hasId) {
|
|
7799
|
+
if (!isRequestId2(parsed.id)) {
|
|
7800
|
+
return {
|
|
7801
|
+
type: "invalid",
|
|
7802
|
+
id: null,
|
|
7803
|
+
error: invalidRequest2()
|
|
7804
|
+
};
|
|
7805
|
+
}
|
|
7806
|
+
const request = {
|
|
7807
|
+
jsonrpc: "2.0",
|
|
7808
|
+
id: parsed.id,
|
|
7809
|
+
method: parsed.method
|
|
7810
|
+
};
|
|
7811
|
+
if (hasOwn2(parsed, "params")) {
|
|
7812
|
+
request.params = parsed.params;
|
|
7813
|
+
}
|
|
7814
|
+
return {
|
|
7815
|
+
type: "request",
|
|
7816
|
+
message: request
|
|
7817
|
+
};
|
|
7818
|
+
}
|
|
7819
|
+
const notification = {
|
|
7820
|
+
jsonrpc: "2.0",
|
|
7821
|
+
method: parsed.method
|
|
7822
|
+
};
|
|
7823
|
+
if (hasOwn2(parsed, "params")) {
|
|
7824
|
+
notification.params = parsed.params;
|
|
7825
|
+
}
|
|
7826
|
+
return {
|
|
7827
|
+
type: "notification",
|
|
7828
|
+
message: notification
|
|
7829
|
+
};
|
|
7830
|
+
}
|
|
7831
|
+
if (!hasId || !isRequestId2(parsed.id)) {
|
|
7832
|
+
return {
|
|
7833
|
+
type: "invalid",
|
|
7834
|
+
id,
|
|
7835
|
+
error: invalidRequest2()
|
|
7836
|
+
};
|
|
7837
|
+
}
|
|
7838
|
+
const hasResult = hasOwn2(parsed, "result");
|
|
7839
|
+
const hasError = hasOwn2(parsed, "error");
|
|
7840
|
+
if (hasResult === hasError) {
|
|
7841
|
+
return {
|
|
7842
|
+
type: "invalid",
|
|
7843
|
+
id: parsed.id,
|
|
7844
|
+
error: invalidRequest2()
|
|
7845
|
+
};
|
|
7846
|
+
}
|
|
7847
|
+
if (hasResult) {
|
|
7848
|
+
return {
|
|
7849
|
+
type: "response",
|
|
7850
|
+
message: {
|
|
7851
|
+
jsonrpc: "2.0",
|
|
7852
|
+
id: parsed.id,
|
|
7853
|
+
result: parsed.result
|
|
7854
|
+
}
|
|
7855
|
+
};
|
|
7856
|
+
}
|
|
7857
|
+
if (!isJsonRpcErrorObject2(parsed.error)) {
|
|
7858
|
+
return {
|
|
7859
|
+
type: "invalid",
|
|
7860
|
+
id: parsed.id,
|
|
7861
|
+
error: invalidRequest2()
|
|
7862
|
+
};
|
|
7863
|
+
}
|
|
7864
|
+
return {
|
|
7865
|
+
type: "response",
|
|
7866
|
+
message: {
|
|
7867
|
+
jsonrpc: "2.0",
|
|
7868
|
+
id: parsed.id,
|
|
7869
|
+
error: parsed.error
|
|
7870
|
+
}
|
|
7871
|
+
};
|
|
7872
|
+
}
|
|
7873
|
+
var MCP_PROTOCOL_VERSION, McpClient, ERROR_PARSE, ERROR_INVALID_REQUEST, ERROR_METHOD_NOT_FOUND, ERROR_INTERNAL, StdioTransport, HttpTransport, HttpTransportGetSseNotSupportedError, McpError, SseParser, JsonRpcMessageLayer2;
|
|
7874
|
+
var init_internal = __esm({
|
|
7875
|
+
"packages/tiny-mcp-client/src/internal.ts"() {
|
|
7876
|
+
"use strict";
|
|
7877
|
+
MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
7878
|
+
McpClient = class {
|
|
7879
|
+
currentState = "disconnected";
|
|
7880
|
+
currentServerCapabilities = null;
|
|
7881
|
+
currentServerInfo = null;
|
|
7882
|
+
currentInstructions;
|
|
7883
|
+
options;
|
|
7884
|
+
transport = null;
|
|
7885
|
+
messageLayer = null;
|
|
7886
|
+
constructor(options) {
|
|
7887
|
+
this.options = options;
|
|
7888
|
+
}
|
|
7889
|
+
get state() {
|
|
7890
|
+
return this.currentState;
|
|
7891
|
+
}
|
|
7892
|
+
get serverCapabilities() {
|
|
7893
|
+
return this.currentServerCapabilities;
|
|
7894
|
+
}
|
|
7895
|
+
get serverInfo() {
|
|
7896
|
+
return this.currentServerInfo;
|
|
7897
|
+
}
|
|
7898
|
+
get instructions() {
|
|
7899
|
+
return this.currentInstructions;
|
|
7900
|
+
}
|
|
7901
|
+
getMessageLayerOrThrow() {
|
|
7902
|
+
if (this.currentState === "disconnected") {
|
|
7903
|
+
throw new Error("MCP client is disconnected");
|
|
7904
|
+
}
|
|
7905
|
+
if (this.currentState === "closed") {
|
|
7906
|
+
throw new Error("MCP client is closed");
|
|
7907
|
+
}
|
|
7908
|
+
if (this.messageLayer === null) {
|
|
7909
|
+
throw new Error("MCP client is disconnected");
|
|
7910
|
+
}
|
|
7911
|
+
return this.messageLayer;
|
|
7912
|
+
}
|
|
7913
|
+
async connect(transport) {
|
|
7914
|
+
if (this.currentState !== "disconnected" && this.currentState !== "closed") {
|
|
7915
|
+
throw new Error("MCP client is already connected");
|
|
7916
|
+
}
|
|
7917
|
+
const transportClosedReason = transport.closed.then((closedEvent) => closedEvent.reason).catch(
|
|
7918
|
+
(error2) => error2 instanceof Error ? error2 : new Error(String(error2))
|
|
7919
|
+
);
|
|
7920
|
+
const messageLayer = new JsonRpcMessageLayer2(
|
|
7921
|
+
transport.readable,
|
|
7922
|
+
transport.writable,
|
|
7923
|
+
3e4,
|
|
7924
|
+
transportClosedReason
|
|
7925
|
+
);
|
|
7926
|
+
const {
|
|
7927
|
+
onSamplingRequest,
|
|
7928
|
+
onRootsList,
|
|
7929
|
+
onToolsChanged,
|
|
7930
|
+
onResourcesChanged,
|
|
7931
|
+
onResourceUpdated,
|
|
7932
|
+
onPromptsChanged,
|
|
7933
|
+
onLog,
|
|
7934
|
+
onProgress
|
|
7935
|
+
} = this.options;
|
|
7936
|
+
messageLayer.onRequest("ping", () => ({}));
|
|
7937
|
+
if (onSamplingRequest !== void 0) {
|
|
7938
|
+
messageLayer.onRequest(
|
|
7939
|
+
"sampling/createMessage",
|
|
7940
|
+
(params) => onSamplingRequest(params)
|
|
7941
|
+
);
|
|
7942
|
+
}
|
|
7943
|
+
if (onRootsList !== void 0) {
|
|
7944
|
+
messageLayer.onRequest("roots/list", async () => ({
|
|
7945
|
+
roots: await onRootsList()
|
|
7946
|
+
}));
|
|
7947
|
+
}
|
|
7948
|
+
messageLayer.onNotification("notifications/tools/list_changed", async () => {
|
|
7949
|
+
if (onToolsChanged === void 0) {
|
|
7950
|
+
return;
|
|
7951
|
+
}
|
|
7952
|
+
await onToolsChanged();
|
|
7953
|
+
});
|
|
7954
|
+
messageLayer.onNotification("notifications/resources/list_changed", async () => {
|
|
7955
|
+
if (onResourcesChanged === void 0) {
|
|
7956
|
+
return;
|
|
7957
|
+
}
|
|
7958
|
+
await onResourcesChanged();
|
|
7959
|
+
});
|
|
7960
|
+
messageLayer.onNotification("notifications/resources/updated", async (params) => {
|
|
7961
|
+
if (onResourceUpdated === void 0) {
|
|
7962
|
+
return;
|
|
7963
|
+
}
|
|
7964
|
+
if (typeof params !== "object" || params === null || Array.isArray(params)) {
|
|
7965
|
+
return;
|
|
7966
|
+
}
|
|
7967
|
+
const { uri } = params;
|
|
7968
|
+
if (typeof uri !== "string") {
|
|
7969
|
+
return;
|
|
7970
|
+
}
|
|
7971
|
+
await onResourceUpdated(uri);
|
|
7972
|
+
});
|
|
7973
|
+
messageLayer.onNotification("notifications/prompts/list_changed", async () => {
|
|
7974
|
+
if (onPromptsChanged === void 0) {
|
|
7975
|
+
return;
|
|
7976
|
+
}
|
|
7977
|
+
await onPromptsChanged();
|
|
7978
|
+
});
|
|
7979
|
+
messageLayer.onNotification("notifications/message", async (params) => {
|
|
7980
|
+
if (onLog === void 0 || !isObjectRecord3(params) || !isLogLevel(params.level)) {
|
|
7981
|
+
return;
|
|
7982
|
+
}
|
|
7983
|
+
if (!hasOwn2(params, "data")) {
|
|
7984
|
+
return;
|
|
7985
|
+
}
|
|
7986
|
+
const message = {
|
|
7987
|
+
level: params.level,
|
|
7988
|
+
data: params.data
|
|
7989
|
+
};
|
|
7990
|
+
if (params.logger !== void 0) {
|
|
7991
|
+
if (typeof params.logger !== "string") {
|
|
7992
|
+
return;
|
|
7993
|
+
}
|
|
7994
|
+
message.logger = params.logger;
|
|
7995
|
+
}
|
|
7996
|
+
await onLog(message);
|
|
7997
|
+
});
|
|
7998
|
+
messageLayer.onNotification("notifications/progress", async (params) => {
|
|
7999
|
+
if (onProgress === void 0 || !isObjectRecord3(params)) {
|
|
8000
|
+
return;
|
|
8001
|
+
}
|
|
8002
|
+
const { progressToken, progress } = params;
|
|
8003
|
+
if (!isRequestId2(progressToken) || typeof progress !== "number") {
|
|
8004
|
+
return;
|
|
8005
|
+
}
|
|
8006
|
+
const progressParams = {
|
|
8007
|
+
progressToken,
|
|
8008
|
+
progress
|
|
8009
|
+
};
|
|
8010
|
+
if (params.total !== void 0) {
|
|
8011
|
+
if (typeof params.total !== "number") {
|
|
8012
|
+
return;
|
|
8013
|
+
}
|
|
8014
|
+
progressParams.total = params.total;
|
|
8015
|
+
}
|
|
8016
|
+
if (params.message !== void 0) {
|
|
8017
|
+
if (typeof params.message !== "string") {
|
|
8018
|
+
return;
|
|
8019
|
+
}
|
|
8020
|
+
progressParams.message = params.message;
|
|
8021
|
+
}
|
|
8022
|
+
await onProgress(progressParams);
|
|
8023
|
+
});
|
|
8024
|
+
messageLayer.onNotification("notifications/cancelled", () => void 0);
|
|
8025
|
+
this.transport = transport;
|
|
8026
|
+
this.messageLayer = messageLayer;
|
|
8027
|
+
this.currentState = "initializing";
|
|
8028
|
+
transport.closed.then((closedEvent) => {
|
|
8029
|
+
if (this.transport !== transport) {
|
|
8030
|
+
return;
|
|
8031
|
+
}
|
|
8032
|
+
this.messageLayer?.dispose(closedEvent.reason);
|
|
8033
|
+
this.messageLayer = null;
|
|
8034
|
+
this.transport = null;
|
|
8035
|
+
this.currentState = "closed";
|
|
8036
|
+
}).catch((error2) => {
|
|
8037
|
+
if (this.transport !== transport) {
|
|
8038
|
+
return;
|
|
8039
|
+
}
|
|
8040
|
+
const reason = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
8041
|
+
this.messageLayer?.dispose(reason);
|
|
8042
|
+
this.messageLayer = null;
|
|
8043
|
+
this.transport = null;
|
|
8044
|
+
this.currentState = "closed";
|
|
8045
|
+
});
|
|
8046
|
+
const capabilities = {
|
|
8047
|
+
...this.options.capabilities ?? {}
|
|
8048
|
+
};
|
|
8049
|
+
if (onSamplingRequest !== void 0 && capabilities.sampling === void 0) {
|
|
8050
|
+
capabilities.sampling = {};
|
|
8051
|
+
}
|
|
8052
|
+
if (onRootsList !== void 0) {
|
|
8053
|
+
capabilities.roots = {
|
|
8054
|
+
...capabilities.roots ?? {}
|
|
8055
|
+
};
|
|
8056
|
+
}
|
|
8057
|
+
const initializeResult = await messageLayer.sendRequest("initialize", {
|
|
8058
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
8059
|
+
clientInfo: this.options.clientInfo,
|
|
8060
|
+
capabilities
|
|
8061
|
+
});
|
|
8062
|
+
if (initializeResult.protocolVersion !== MCP_PROTOCOL_VERSION) {
|
|
8063
|
+
throw new McpError(
|
|
8064
|
+
ERROR_INVALID_REQUEST,
|
|
8065
|
+
`Unsupported protocol version: ${initializeResult.protocolVersion}`
|
|
8066
|
+
);
|
|
8067
|
+
}
|
|
8068
|
+
this.currentServerCapabilities = initializeResult.capabilities;
|
|
8069
|
+
this.currentServerInfo = initializeResult.serverInfo;
|
|
8070
|
+
this.currentInstructions = initializeResult.instructions;
|
|
8071
|
+
messageLayer.sendNotification("notifications/initialized");
|
|
8072
|
+
this.currentState = "ready";
|
|
8073
|
+
return initializeResult;
|
|
8074
|
+
}
|
|
8075
|
+
getServerCapabilitiesOrThrow() {
|
|
8076
|
+
if (this.currentServerCapabilities === null) {
|
|
8077
|
+
throw new Error("MCP client has not completed initialization");
|
|
8078
|
+
}
|
|
8079
|
+
return this.currentServerCapabilities;
|
|
8080
|
+
}
|
|
8081
|
+
async listTools(params = {}) {
|
|
8082
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8083
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8084
|
+
if (serverCapabilities.tools === void 0) {
|
|
8085
|
+
throw new Error("Server does not support tools");
|
|
8086
|
+
}
|
|
8087
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
8088
|
+
return await messageLayer.sendRequest("tools/list", requestParams);
|
|
8089
|
+
}
|
|
8090
|
+
async callTool(params, options = {}) {
|
|
8091
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8092
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8093
|
+
if (serverCapabilities.tools === void 0) {
|
|
8094
|
+
throw new Error("Server does not support tools");
|
|
8095
|
+
}
|
|
8096
|
+
const requestParams = options.progressToken === void 0 ? params : {
|
|
8097
|
+
...params,
|
|
8098
|
+
_meta: {
|
|
8099
|
+
progressToken: options.progressToken
|
|
8100
|
+
}
|
|
8101
|
+
};
|
|
8102
|
+
let requestId;
|
|
8103
|
+
const requestPromise = messageLayer.sendRequest("tools/call", requestParams, {
|
|
8104
|
+
onRequestId: (nextRequestId) => {
|
|
8105
|
+
requestId = nextRequestId;
|
|
8106
|
+
}
|
|
8107
|
+
});
|
|
8108
|
+
if (options.signal === void 0) {
|
|
8109
|
+
return await requestPromise;
|
|
8110
|
+
}
|
|
8111
|
+
const signal = options.signal;
|
|
8112
|
+
let abortListener;
|
|
8113
|
+
const abortPromise = new Promise((_, reject) => {
|
|
8114
|
+
const rejectWithAbortReason = () => {
|
|
8115
|
+
if (requestId !== void 0) {
|
|
8116
|
+
messageLayer.sendNotification("notifications/cancelled", { requestId });
|
|
8117
|
+
}
|
|
8118
|
+
reject(signal.reason);
|
|
8119
|
+
};
|
|
8120
|
+
abortListener = rejectWithAbortReason;
|
|
8121
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
8122
|
+
if (signal.aborted) {
|
|
8123
|
+
signal.removeEventListener("abort", abortListener);
|
|
8124
|
+
rejectWithAbortReason();
|
|
8125
|
+
}
|
|
8126
|
+
});
|
|
8127
|
+
try {
|
|
8128
|
+
return await Promise.race([requestPromise, abortPromise]);
|
|
8129
|
+
} finally {
|
|
8130
|
+
if (abortListener !== void 0) {
|
|
8131
|
+
signal.removeEventListener("abort", abortListener);
|
|
8132
|
+
}
|
|
8133
|
+
}
|
|
8134
|
+
}
|
|
8135
|
+
async listResources(params = {}) {
|
|
8136
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8137
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8138
|
+
if (serverCapabilities.resources === void 0) {
|
|
8139
|
+
throw new Error("Server does not support resources");
|
|
8140
|
+
}
|
|
8141
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
8142
|
+
return await messageLayer.sendRequest("resources/list", requestParams);
|
|
8143
|
+
}
|
|
8144
|
+
async listResourceTemplates(params = {}) {
|
|
8145
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8146
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8147
|
+
if (serverCapabilities.resources === void 0) {
|
|
8148
|
+
throw new Error("Server does not support resources");
|
|
8149
|
+
}
|
|
8150
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
8151
|
+
return await messageLayer.sendRequest("resources/templates/list", requestParams);
|
|
8152
|
+
}
|
|
8153
|
+
async readResource(params) {
|
|
8154
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8155
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8156
|
+
if (serverCapabilities.resources === void 0) {
|
|
8157
|
+
throw new Error("Server does not support resources");
|
|
8158
|
+
}
|
|
8159
|
+
return await messageLayer.sendRequest("resources/read", params);
|
|
8160
|
+
}
|
|
8161
|
+
async subscribe(uri) {
|
|
8162
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8163
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8164
|
+
if (serverCapabilities.resources?.subscribe !== true) {
|
|
8165
|
+
throw new Error("Server does not support resource subscriptions");
|
|
8166
|
+
}
|
|
8167
|
+
await messageLayer.sendRequest("resources/subscribe", { uri });
|
|
8168
|
+
}
|
|
8169
|
+
async unsubscribe(uri) {
|
|
8170
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8171
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8172
|
+
if (serverCapabilities.resources?.subscribe !== true) {
|
|
8173
|
+
throw new Error("Server does not support resource subscriptions");
|
|
8174
|
+
}
|
|
8175
|
+
await messageLayer.sendRequest("resources/unsubscribe", { uri });
|
|
8176
|
+
}
|
|
8177
|
+
async listPrompts(params = {}) {
|
|
8178
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8179
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8180
|
+
if (serverCapabilities.prompts === void 0) {
|
|
8181
|
+
throw new Error("Server does not support prompts");
|
|
8182
|
+
}
|
|
8183
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
8184
|
+
return await messageLayer.sendRequest("prompts/list", requestParams);
|
|
8185
|
+
}
|
|
8186
|
+
async getPrompt(params) {
|
|
8187
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8188
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8189
|
+
if (serverCapabilities.prompts === void 0) {
|
|
8190
|
+
throw new Error("Server does not support prompts");
|
|
8191
|
+
}
|
|
8192
|
+
return await messageLayer.sendRequest("prompts/get", params);
|
|
8193
|
+
}
|
|
8194
|
+
async complete(params) {
|
|
8195
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8196
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8197
|
+
if (serverCapabilities.completions === void 0) {
|
|
8198
|
+
throw new Error("Server does not support completions");
|
|
8199
|
+
}
|
|
8200
|
+
return await messageLayer.sendRequest("completion/complete", params);
|
|
8201
|
+
}
|
|
8202
|
+
async setLogLevel(level) {
|
|
8203
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8204
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
8205
|
+
if (serverCapabilities.logging === void 0) {
|
|
8206
|
+
throw new Error("Server does not support logging");
|
|
8207
|
+
}
|
|
8208
|
+
await messageLayer.sendRequest("logging/setLevel", { level });
|
|
8209
|
+
}
|
|
8210
|
+
async cancel(requestId, reason) {
|
|
8211
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8212
|
+
const params = { requestId };
|
|
8213
|
+
if (reason !== void 0) {
|
|
8214
|
+
params.reason = reason;
|
|
8215
|
+
}
|
|
8216
|
+
messageLayer.sendNotification("notifications/cancelled", params);
|
|
8217
|
+
}
|
|
8218
|
+
async sendRootsChanged() {
|
|
8219
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8220
|
+
messageLayer.sendNotification("notifications/roots/list_changed");
|
|
8221
|
+
}
|
|
8222
|
+
async ping() {
|
|
8223
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
8224
|
+
await messageLayer.sendRequest("ping");
|
|
8225
|
+
}
|
|
8226
|
+
async close() {
|
|
8227
|
+
if (this.currentState === "closed") {
|
|
8228
|
+
return;
|
|
8229
|
+
}
|
|
8230
|
+
const closeError = new Error("MCP client closed");
|
|
8231
|
+
this.messageLayer?.dispose(closeError);
|
|
8232
|
+
this.transport?.dispose(closeError);
|
|
8233
|
+
this.messageLayer = null;
|
|
8234
|
+
this.transport = null;
|
|
8235
|
+
this.currentState = "closed";
|
|
8236
|
+
}
|
|
8237
|
+
};
|
|
8238
|
+
ERROR_PARSE = -32700;
|
|
8239
|
+
ERROR_INVALID_REQUEST = -32600;
|
|
8240
|
+
ERROR_METHOD_NOT_FOUND = -32601;
|
|
8241
|
+
ERROR_INTERNAL = -32603;
|
|
8242
|
+
StdioTransport = class _StdioTransport {
|
|
8243
|
+
readable;
|
|
8244
|
+
writable;
|
|
8245
|
+
closed;
|
|
8246
|
+
child;
|
|
8247
|
+
disposed = false;
|
|
8248
|
+
stderrOutput = "";
|
|
8249
|
+
static STDERR_MAX_LENGTH = 65536;
|
|
8250
|
+
constructor({
|
|
8251
|
+
command,
|
|
8252
|
+
args = [],
|
|
8253
|
+
cwd,
|
|
8254
|
+
env,
|
|
8255
|
+
spawn: spawnProcess = defaultStdioSpawn
|
|
8256
|
+
}) {
|
|
8257
|
+
this.child = spawnProcess(command, args, {
|
|
8258
|
+
cwd,
|
|
8259
|
+
env,
|
|
8260
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8261
|
+
});
|
|
8262
|
+
const child = this.child;
|
|
8263
|
+
this.readable = child.stdout;
|
|
8264
|
+
this.writable = child.stdin;
|
|
8265
|
+
child.stderr.on("data", (chunk) => {
|
|
8266
|
+
this.stderrOutput += chunkToString3(chunk);
|
|
8267
|
+
if (this.stderrOutput.length > _StdioTransport.STDERR_MAX_LENGTH) {
|
|
8268
|
+
this.stderrOutput = this.stderrOutput.slice(-_StdioTransport.STDERR_MAX_LENGTH);
|
|
8269
|
+
}
|
|
8270
|
+
});
|
|
8271
|
+
this.closed = new Promise((resolve) => {
|
|
8272
|
+
let settled = false;
|
|
8273
|
+
const resolveClosed = (event) => {
|
|
8274
|
+
if (settled) {
|
|
8275
|
+
return;
|
|
8276
|
+
}
|
|
8277
|
+
settled = true;
|
|
8278
|
+
resolve(event);
|
|
8279
|
+
};
|
|
8280
|
+
child.once("exit", (code, signal) => {
|
|
8281
|
+
const closedEvent = {
|
|
8282
|
+
reason: new Error("Stdio transport process exited")
|
|
8283
|
+
};
|
|
8284
|
+
if (code !== null) {
|
|
8285
|
+
closedEvent.code = code;
|
|
8286
|
+
}
|
|
8287
|
+
if (signal !== null) {
|
|
8288
|
+
closedEvent.signal = signal;
|
|
8289
|
+
}
|
|
8290
|
+
resolveClosed(closedEvent);
|
|
8291
|
+
});
|
|
8292
|
+
child.once("error", (error2) => {
|
|
8293
|
+
const closedEvent = {
|
|
8294
|
+
reason: error2 instanceof Error ? error2 : new Error(String(error2))
|
|
8295
|
+
};
|
|
8296
|
+
if (child.exitCode !== null) {
|
|
8297
|
+
closedEvent.code = child.exitCode;
|
|
8298
|
+
}
|
|
8299
|
+
if (child.signalCode !== null) {
|
|
8300
|
+
closedEvent.signal = child.signalCode;
|
|
8301
|
+
}
|
|
8302
|
+
resolveClosed(closedEvent);
|
|
8303
|
+
});
|
|
8304
|
+
});
|
|
8305
|
+
}
|
|
8306
|
+
getStderrOutput() {
|
|
8307
|
+
return this.stderrOutput;
|
|
8308
|
+
}
|
|
8309
|
+
dispose(reason = new Error("Stdio transport disposed")) {
|
|
8310
|
+
void reason;
|
|
8311
|
+
if (this.disposed) {
|
|
8312
|
+
return;
|
|
8313
|
+
}
|
|
8314
|
+
this.disposed = true;
|
|
8315
|
+
if (!this.child.stdin.destroyed && !this.child.stdin.writableEnded) {
|
|
8316
|
+
this.child.stdin.end();
|
|
8317
|
+
}
|
|
8318
|
+
if (this.child.exitCode === null && this.child.signalCode === null && !this.child.killed) {
|
|
8319
|
+
this.child.kill("SIGTERM");
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
};
|
|
8323
|
+
HttpTransport = class {
|
|
8324
|
+
readable;
|
|
8325
|
+
writable;
|
|
8326
|
+
closed;
|
|
8327
|
+
url;
|
|
8328
|
+
headers;
|
|
8329
|
+
fetchImpl;
|
|
8330
|
+
readStream = new PassThrough();
|
|
8331
|
+
writeStream = new PassThrough();
|
|
8332
|
+
resolveClosed;
|
|
8333
|
+
sessionId;
|
|
8334
|
+
lastEventId;
|
|
8335
|
+
getSseStreamStarted = false;
|
|
8336
|
+
disposed = false;
|
|
8337
|
+
inFlightFetchAbortControllers = /* @__PURE__ */ new Set();
|
|
8338
|
+
openSseReaders = /* @__PURE__ */ new Set();
|
|
8339
|
+
constructor({
|
|
8340
|
+
url: url2,
|
|
8341
|
+
headers = {},
|
|
8342
|
+
fetch: fetchImpl = defaultHttpTransportFetch
|
|
8343
|
+
}) {
|
|
8344
|
+
this.url = url2;
|
|
8345
|
+
this.headers = headers;
|
|
8346
|
+
this.fetchImpl = fetchImpl;
|
|
8347
|
+
this.readable = this.readStream;
|
|
8348
|
+
this.writable = this.writeStream;
|
|
8349
|
+
this.closed = new Promise((resolve) => {
|
|
8350
|
+
this.resolveClosed = resolve;
|
|
8351
|
+
});
|
|
8352
|
+
this.readStream.once("error", (error2) => {
|
|
8353
|
+
this.dispose(error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
8354
|
+
});
|
|
8355
|
+
this.writeStream.once("error", (error2) => {
|
|
8356
|
+
this.dispose(error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
8357
|
+
});
|
|
8358
|
+
this.consumeWrittenLines().catch((error2) => {
|
|
8359
|
+
this.dispose(error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
8360
|
+
});
|
|
8361
|
+
}
|
|
8362
|
+
dispose(reason = new Error("HTTP transport disposed")) {
|
|
8363
|
+
if (this.disposed) {
|
|
8364
|
+
return;
|
|
8365
|
+
}
|
|
8366
|
+
this.disposed = true;
|
|
8367
|
+
this.abortInFlightFetches();
|
|
8368
|
+
this.cancelOpenSseReaders();
|
|
8369
|
+
this.terminateSession();
|
|
8370
|
+
if (!this.writeStream.destroyed && !this.writeStream.writableEnded) {
|
|
8371
|
+
this.writeStream.end();
|
|
8372
|
+
}
|
|
8373
|
+
if (!this.readStream.destroyed && !this.readStream.writableEnded) {
|
|
8374
|
+
this.readStream.end();
|
|
8375
|
+
}
|
|
8376
|
+
const resolveClosed = this.resolveClosed;
|
|
8377
|
+
this.resolveClosed = void 0;
|
|
8378
|
+
resolveClosed?.({ reason });
|
|
8379
|
+
}
|
|
8380
|
+
abortInFlightFetches() {
|
|
8381
|
+
for (const abortController of this.inFlightFetchAbortControllers) {
|
|
8382
|
+
abortController.abort();
|
|
8383
|
+
}
|
|
8384
|
+
this.inFlightFetchAbortControllers.clear();
|
|
8385
|
+
}
|
|
8386
|
+
cancelOpenSseReaders() {
|
|
8387
|
+
for (const reader of this.openSseReaders) {
|
|
8388
|
+
void reader.cancel().catch(() => void 0);
|
|
8389
|
+
}
|
|
8390
|
+
this.openSseReaders.clear();
|
|
8391
|
+
}
|
|
8392
|
+
async fetchWithAbort(input, init) {
|
|
8393
|
+
const abortController = new AbortController();
|
|
8394
|
+
this.inFlightFetchAbortControllers.add(abortController);
|
|
8395
|
+
try {
|
|
8396
|
+
return await this.fetchImpl(input, {
|
|
8397
|
+
...init,
|
|
8398
|
+
signal: abortController.signal
|
|
8399
|
+
});
|
|
8400
|
+
} finally {
|
|
8401
|
+
this.inFlightFetchAbortControllers.delete(abortController);
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
8404
|
+
async consumeWrittenLines() {
|
|
8405
|
+
for await (const line of readLines3(this.writeStream)) {
|
|
8406
|
+
if (this.disposed || line.length === 0) {
|
|
8407
|
+
continue;
|
|
8408
|
+
}
|
|
8409
|
+
const hasSessionId = this.sessionId !== void 0;
|
|
8410
|
+
const response = await this.fetchWithAbort(this.url, {
|
|
8411
|
+
method: "POST",
|
|
8412
|
+
headers: this.createPostHeaders(),
|
|
8413
|
+
body: line
|
|
8414
|
+
});
|
|
8415
|
+
if (hasSessionId && response.status === 404) {
|
|
8416
|
+
this.sessionId = void 0;
|
|
8417
|
+
this.dispose(new Error("HTTP transport session expired (404 response)"));
|
|
8418
|
+
return;
|
|
8419
|
+
}
|
|
8420
|
+
await this.throwForPostHttpError(response);
|
|
8421
|
+
this.captureSessionId(response);
|
|
8422
|
+
this.maybeOpenGetSseStream();
|
|
8423
|
+
await this.forwardResponseMessages(response);
|
|
8424
|
+
}
|
|
8425
|
+
}
|
|
8426
|
+
createPostHeaders() {
|
|
8427
|
+
const headers = new Headers(this.headers);
|
|
8428
|
+
headers.set("Accept", "application/json, text/event-stream");
|
|
8429
|
+
headers.set("Content-Type", "application/json");
|
|
8430
|
+
if (this.sessionId !== void 0) {
|
|
8431
|
+
headers.set("Mcp-Session-Id", this.sessionId);
|
|
8432
|
+
}
|
|
8433
|
+
return headers;
|
|
8434
|
+
}
|
|
8435
|
+
createGetHeaders() {
|
|
8436
|
+
const headers = new Headers(this.headers);
|
|
8437
|
+
headers.set("Accept", "text/event-stream");
|
|
8438
|
+
if (this.sessionId !== void 0) {
|
|
8439
|
+
headers.set("Mcp-Session-Id", this.sessionId);
|
|
8440
|
+
}
|
|
8441
|
+
if (this.lastEventId !== void 0) {
|
|
8442
|
+
headers.set("Last-Event-ID", this.lastEventId);
|
|
8443
|
+
}
|
|
8444
|
+
return headers;
|
|
8445
|
+
}
|
|
8446
|
+
createDeleteHeaders(sessionId) {
|
|
8447
|
+
const headers = new Headers(this.headers);
|
|
8448
|
+
headers.set("Mcp-Session-Id", sessionId);
|
|
8449
|
+
return headers;
|
|
8450
|
+
}
|
|
8451
|
+
captureSessionId(response) {
|
|
8452
|
+
const sessionId = response.headers.get("Mcp-Session-Id");
|
|
8453
|
+
if (sessionId === null || sessionId.length === 0) {
|
|
8454
|
+
return;
|
|
8455
|
+
}
|
|
8456
|
+
this.sessionId = sessionId;
|
|
8457
|
+
}
|
|
8458
|
+
maybeOpenGetSseStream() {
|
|
8459
|
+
if (this.disposed || this.sessionId === void 0 || this.getSseStreamStarted) {
|
|
8460
|
+
return;
|
|
8461
|
+
}
|
|
8462
|
+
this.getSseStreamStarted = true;
|
|
8463
|
+
this.consumeGetSseStream().catch((error2) => {
|
|
8464
|
+
if (error2 instanceof HttpTransportGetSseNotSupportedError || this.disposed) {
|
|
8465
|
+
return;
|
|
8466
|
+
}
|
|
8467
|
+
this.dispose(error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
8468
|
+
});
|
|
8469
|
+
}
|
|
8470
|
+
terminateSession() {
|
|
8471
|
+
if (this.sessionId === void 0) {
|
|
8472
|
+
return;
|
|
8473
|
+
}
|
|
8474
|
+
const sessionId = this.sessionId;
|
|
8475
|
+
this.sessionId = void 0;
|
|
8476
|
+
this.sendSessionTerminationRequest(sessionId).catch(() => void 0);
|
|
8477
|
+
}
|
|
8478
|
+
async sendSessionTerminationRequest(sessionId) {
|
|
8479
|
+
const response = await this.fetchImpl(this.url, {
|
|
8480
|
+
method: "DELETE",
|
|
8481
|
+
headers: this.createDeleteHeaders(sessionId)
|
|
8482
|
+
});
|
|
8483
|
+
if (response.status === 405) {
|
|
8484
|
+
return;
|
|
8485
|
+
}
|
|
8486
|
+
}
|
|
8487
|
+
async consumeGetSseStream() {
|
|
8488
|
+
const response = await this.fetchWithAbort(this.url, {
|
|
8489
|
+
method: "GET",
|
|
8490
|
+
headers: this.createGetHeaders()
|
|
8491
|
+
});
|
|
8492
|
+
if (response.status === 405) {
|
|
8493
|
+
throw new HttpTransportGetSseNotSupportedError();
|
|
8494
|
+
}
|
|
8495
|
+
const contentType = response.headers.get("Content-Type");
|
|
8496
|
+
if (contentType === null) {
|
|
8497
|
+
return;
|
|
8498
|
+
}
|
|
8499
|
+
if (contentType.toLowerCase().includes("text/event-stream")) {
|
|
8500
|
+
await this.forwardSseResponseMessages(response);
|
|
8501
|
+
this.getSseStreamStarted = false;
|
|
8502
|
+
if (!this.disposed && this.sessionId !== void 0 && this.lastEventId !== void 0) {
|
|
8503
|
+
this.maybeOpenGetSseStream();
|
|
8504
|
+
}
|
|
8505
|
+
}
|
|
8506
|
+
}
|
|
8507
|
+
async throwForPostHttpError(response) {
|
|
8508
|
+
if (response.status < 400) {
|
|
8509
|
+
return;
|
|
8510
|
+
}
|
|
8511
|
+
const responseBody = (await response.text()).trim();
|
|
8512
|
+
const statusDescriptor = `${response.status} ${response.statusText}`.trim();
|
|
8513
|
+
const message = responseBody.length === 0 ? `HTTP transport POST failed (${statusDescriptor})` : `HTTP transport POST failed (${statusDescriptor}): ${responseBody}`;
|
|
8514
|
+
throw new Error(message);
|
|
8515
|
+
}
|
|
8516
|
+
async forwardResponseMessages(response) {
|
|
8517
|
+
if (response.status === 202) {
|
|
8518
|
+
return;
|
|
8519
|
+
}
|
|
8520
|
+
const contentType = response.headers.get("Content-Type");
|
|
8521
|
+
if (contentType === null) {
|
|
8522
|
+
return;
|
|
8523
|
+
}
|
|
8524
|
+
const normalizedContentType = contentType.toLowerCase();
|
|
8525
|
+
if (normalizedContentType.includes("text/event-stream")) {
|
|
8526
|
+
await this.forwardSseResponseMessages(response);
|
|
8527
|
+
return;
|
|
8528
|
+
}
|
|
8529
|
+
if (normalizedContentType.includes("application/json")) {
|
|
8530
|
+
await this.forwardJsonResponseMessage(response);
|
|
8531
|
+
}
|
|
8532
|
+
}
|
|
8533
|
+
async forwardSseResponseMessages(response) {
|
|
8534
|
+
if (response.body === null) {
|
|
8535
|
+
return;
|
|
8536
|
+
}
|
|
8537
|
+
const parser = new SseParser();
|
|
8538
|
+
const decoder = new TextDecoder();
|
|
8539
|
+
const reader = response.body.getReader();
|
|
8540
|
+
this.openSseReaders.add(reader);
|
|
8541
|
+
try {
|
|
8542
|
+
while (true) {
|
|
8543
|
+
const { done, value } = await reader.read();
|
|
8544
|
+
if (done) {
|
|
8545
|
+
break;
|
|
8546
|
+
}
|
|
8547
|
+
if (value === void 0) {
|
|
8548
|
+
continue;
|
|
8549
|
+
}
|
|
8550
|
+
const messages = parser.push(decoder.decode(value, { stream: true }));
|
|
8551
|
+
this.writeSseMessages(messages);
|
|
8552
|
+
this.lastEventId = parser.lastEventId;
|
|
8553
|
+
}
|
|
8554
|
+
const trailingChunk = decoder.decode();
|
|
8555
|
+
if (trailingChunk.length > 0) {
|
|
8556
|
+
this.writeSseMessages(parser.push(trailingChunk));
|
|
8557
|
+
this.lastEventId = parser.lastEventId;
|
|
8558
|
+
}
|
|
8559
|
+
this.writeSseMessages(parser.flush());
|
|
8560
|
+
this.lastEventId = parser.lastEventId;
|
|
8561
|
+
} finally {
|
|
8562
|
+
this.openSseReaders.delete(reader);
|
|
8563
|
+
reader.releaseLock();
|
|
8564
|
+
}
|
|
8565
|
+
}
|
|
8566
|
+
async forwardJsonResponseMessage(response) {
|
|
8567
|
+
const payload = await response.text();
|
|
8568
|
+
if (payload.length === 0) {
|
|
8569
|
+
return;
|
|
8570
|
+
}
|
|
8571
|
+
const parsedPayload = JSON.parse(payload);
|
|
8572
|
+
this.writeReadableLine(JSON.stringify(parsedPayload));
|
|
8573
|
+
}
|
|
8574
|
+
writeSseMessages(messages) {
|
|
8575
|
+
for (const message of messages) {
|
|
8576
|
+
this.writeReadableLine(message.data);
|
|
8577
|
+
}
|
|
8578
|
+
}
|
|
8579
|
+
writeReadableLine(line) {
|
|
8580
|
+
if (this.disposed || this.readStream.destroyed || this.readStream.writableEnded) {
|
|
8581
|
+
return;
|
|
8582
|
+
}
|
|
8583
|
+
this.readStream.write(`${line}
|
|
8584
|
+
`);
|
|
8585
|
+
}
|
|
8586
|
+
};
|
|
8587
|
+
HttpTransportGetSseNotSupportedError = class extends Error {
|
|
8588
|
+
constructor() {
|
|
8589
|
+
super("HTTP transport server does not support GET SSE streams");
|
|
8590
|
+
}
|
|
8591
|
+
};
|
|
8592
|
+
McpError = class extends Error {
|
|
8593
|
+
code;
|
|
8594
|
+
constructor(code, message, data) {
|
|
8595
|
+
super(message);
|
|
8596
|
+
this.name = "McpError";
|
|
8597
|
+
this.code = code;
|
|
8598
|
+
if (data !== void 0) {
|
|
8599
|
+
this.data = data;
|
|
8600
|
+
}
|
|
8601
|
+
}
|
|
8602
|
+
};
|
|
8603
|
+
SseParser = class {
|
|
8604
|
+
buffer = "";
|
|
8605
|
+
eventType;
|
|
8606
|
+
dataLines = [];
|
|
8607
|
+
eventId = "";
|
|
8608
|
+
hasEventId = false;
|
|
8609
|
+
_lastEventId;
|
|
8610
|
+
get lastEventId() {
|
|
8611
|
+
return this._lastEventId;
|
|
8612
|
+
}
|
|
8613
|
+
push(chunk) {
|
|
8614
|
+
if (chunk.length === 0) {
|
|
8615
|
+
return [];
|
|
8616
|
+
}
|
|
8617
|
+
this.buffer += chunk;
|
|
8618
|
+
const messages = [];
|
|
8619
|
+
while (true) {
|
|
8620
|
+
const newlineIndex = this.buffer.indexOf("\n");
|
|
8621
|
+
if (newlineIndex === -1) {
|
|
8622
|
+
break;
|
|
8623
|
+
}
|
|
8624
|
+
const line = normalizeLine2(this.buffer.slice(0, newlineIndex));
|
|
8625
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
8626
|
+
this.consumeLine(line, messages);
|
|
8627
|
+
}
|
|
8628
|
+
return messages;
|
|
8629
|
+
}
|
|
8630
|
+
flush() {
|
|
8631
|
+
const messages = [];
|
|
8632
|
+
if (this.buffer.length > 0) {
|
|
8633
|
+
this.consumeLine(normalizeLine2(this.buffer), messages);
|
|
8634
|
+
this.buffer = "";
|
|
8635
|
+
}
|
|
8636
|
+
this.emitEvent(messages);
|
|
8637
|
+
return messages;
|
|
8638
|
+
}
|
|
8639
|
+
consumeLine(line, messages) {
|
|
8640
|
+
if (line.length === 0) {
|
|
8641
|
+
this.emitEvent(messages);
|
|
8642
|
+
return;
|
|
8643
|
+
}
|
|
8644
|
+
if (line.startsWith(":")) {
|
|
8645
|
+
return;
|
|
8646
|
+
}
|
|
8647
|
+
const separatorIndex = line.indexOf(":");
|
|
8648
|
+
const field = separatorIndex === -1 ? line : line.slice(0, separatorIndex);
|
|
8649
|
+
const rawValue = separatorIndex === -1 ? "" : line.slice(separatorIndex + 1);
|
|
8650
|
+
const value = rawValue.startsWith(" ") ? rawValue.slice(1) : rawValue;
|
|
8651
|
+
if (field === "event") {
|
|
8652
|
+
this.eventType = value;
|
|
8653
|
+
return;
|
|
8654
|
+
}
|
|
8655
|
+
if (field === "data") {
|
|
8656
|
+
this.dataLines.push(value);
|
|
8657
|
+
return;
|
|
8658
|
+
}
|
|
8659
|
+
if (field === "id") {
|
|
8660
|
+
if (value.includes("\0")) {
|
|
8661
|
+
return;
|
|
8662
|
+
}
|
|
8663
|
+
this.eventId = value;
|
|
8664
|
+
this.hasEventId = true;
|
|
8665
|
+
}
|
|
8666
|
+
}
|
|
8667
|
+
emitEvent(messages) {
|
|
8668
|
+
const eventType = this.eventType ?? "message";
|
|
8669
|
+
if (this.hasEventId) {
|
|
8670
|
+
this._lastEventId = this.eventId;
|
|
8671
|
+
}
|
|
8672
|
+
if (this.dataLines.length === 0 || eventType !== "message") {
|
|
8673
|
+
this.resetEvent();
|
|
8674
|
+
return;
|
|
8675
|
+
}
|
|
8676
|
+
const message = {
|
|
8677
|
+
data: this.dataLines.join("\n")
|
|
8678
|
+
};
|
|
8679
|
+
if (this.hasEventId) {
|
|
8680
|
+
message.id = this.eventId;
|
|
8681
|
+
}
|
|
8682
|
+
messages.push(message);
|
|
8683
|
+
this.resetEvent();
|
|
8684
|
+
}
|
|
8685
|
+
resetEvent() {
|
|
8686
|
+
this.eventType = void 0;
|
|
8687
|
+
this.dataLines = [];
|
|
8688
|
+
this.eventId = "";
|
|
8689
|
+
this.hasEventId = false;
|
|
8690
|
+
}
|
|
8691
|
+
};
|
|
8692
|
+
JsonRpcMessageLayer2 = class {
|
|
8693
|
+
requestTimeoutMs;
|
|
8694
|
+
input;
|
|
8695
|
+
output;
|
|
8696
|
+
inputClosedReason;
|
|
8697
|
+
nextRequestId = 1;
|
|
8698
|
+
disposedError;
|
|
8699
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
8700
|
+
activeIncomingRequests = /* @__PURE__ */ new Map();
|
|
8701
|
+
requestHandlers = /* @__PURE__ */ new Map();
|
|
8702
|
+
notificationHandlers = /* @__PURE__ */ new Map();
|
|
8703
|
+
constructor(input, output, requestTimeoutMs = 3e4, inputClosedReason) {
|
|
8704
|
+
if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs < 0) {
|
|
8705
|
+
throw new Error("requestTimeoutMs must be a non-negative finite number");
|
|
8706
|
+
}
|
|
8707
|
+
this.input = input;
|
|
8708
|
+
this.output = output;
|
|
8709
|
+
this.inputClosedReason = inputClosedReason;
|
|
8710
|
+
this.requestTimeoutMs = requestTimeoutMs;
|
|
8711
|
+
this.consumeInput().catch(() => void 0);
|
|
8712
|
+
}
|
|
8713
|
+
sendNotification(method, params) {
|
|
8714
|
+
if (this.disposedError !== void 0) {
|
|
8715
|
+
throw this.disposedError;
|
|
8716
|
+
}
|
|
8717
|
+
const message = {
|
|
8718
|
+
jsonrpc: "2.0",
|
|
8719
|
+
method
|
|
8720
|
+
};
|
|
8721
|
+
if (params !== void 0) {
|
|
8722
|
+
message.params = params;
|
|
8723
|
+
}
|
|
8724
|
+
this.output.write(serializeJsonRpcMessage2(message));
|
|
8725
|
+
}
|
|
8726
|
+
onRequest(method, handler) {
|
|
8727
|
+
this.requestHandlers.set(method, handler);
|
|
8728
|
+
}
|
|
8729
|
+
onNotification(method, handler) {
|
|
8730
|
+
this.notificationHandlers.set(method, handler);
|
|
8731
|
+
}
|
|
8732
|
+
sendRequest(method, params, options = {}) {
|
|
8733
|
+
if (this.disposedError !== void 0) {
|
|
8734
|
+
throw this.disposedError;
|
|
8735
|
+
}
|
|
8736
|
+
const id = this.nextRequestId;
|
|
8737
|
+
this.nextRequestId += 1;
|
|
8738
|
+
const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;
|
|
8739
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
8740
|
+
throw new Error("timeoutMs must be a non-negative finite number");
|
|
8741
|
+
}
|
|
8742
|
+
if (options.onRequestId !== void 0) {
|
|
8743
|
+
options.onRequestId(id);
|
|
8744
|
+
}
|
|
8745
|
+
const message = {
|
|
8746
|
+
jsonrpc: "2.0",
|
|
8747
|
+
id,
|
|
8748
|
+
method
|
|
8749
|
+
};
|
|
8750
|
+
if (params !== void 0) {
|
|
8751
|
+
message.params = params;
|
|
8752
|
+
}
|
|
8753
|
+
return new Promise((resolve, reject) => {
|
|
8754
|
+
const timeout = setTimeout(() => {
|
|
8755
|
+
this.pendingRequests.delete(id);
|
|
8756
|
+
reject(new Error(`JSON-RPC request "${method}" timed out after ${timeoutMs}ms`));
|
|
8757
|
+
}, timeoutMs);
|
|
8758
|
+
this.pendingRequests.set(id, { resolve, reject, timeout });
|
|
8759
|
+
try {
|
|
8760
|
+
this.output.write(serializeJsonRpcMessage2(message));
|
|
8761
|
+
} catch (error2) {
|
|
8762
|
+
clearTimeout(timeout);
|
|
8763
|
+
this.pendingRequests.delete(id);
|
|
8764
|
+
reject(error2);
|
|
8765
|
+
}
|
|
8766
|
+
});
|
|
8767
|
+
}
|
|
8768
|
+
dispose(reason = new Error("JSON-RPC message layer disposed")) {
|
|
8769
|
+
if (this.disposedError !== void 0) {
|
|
8770
|
+
return;
|
|
8771
|
+
}
|
|
8772
|
+
this.disposedError = reason;
|
|
8773
|
+
for (const pending of this.pendingRequests.values()) {
|
|
8774
|
+
clearTimeout(pending.timeout);
|
|
8775
|
+
pending.reject(reason);
|
|
8776
|
+
}
|
|
8777
|
+
this.pendingRequests.clear();
|
|
8778
|
+
this.activeIncomingRequests.clear();
|
|
8779
|
+
}
|
|
8780
|
+
async consumeInput() {
|
|
8781
|
+
try {
|
|
8782
|
+
for await (const line of readLines3(this.input)) {
|
|
8783
|
+
if (this.disposedError !== void 0) {
|
|
8784
|
+
break;
|
|
8785
|
+
}
|
|
8786
|
+
if (line.length === 0) {
|
|
8787
|
+
continue;
|
|
8788
|
+
}
|
|
8789
|
+
let parsedLine;
|
|
8790
|
+
try {
|
|
8791
|
+
parsedLine = JSON.parse(line);
|
|
8792
|
+
} catch {
|
|
8793
|
+
await this.processParsedMessage({
|
|
8794
|
+
type: "invalid",
|
|
8795
|
+
id: null,
|
|
8796
|
+
error: parseError2()
|
|
8797
|
+
});
|
|
8798
|
+
continue;
|
|
8799
|
+
}
|
|
8800
|
+
if (Array.isArray(parsedLine)) {
|
|
8801
|
+
for (const message of parsedLine) {
|
|
8802
|
+
if (this.disposedError !== void 0) {
|
|
8803
|
+
break;
|
|
8804
|
+
}
|
|
8805
|
+
await this.processParsedMessage(parseJsonRpcPayload(message));
|
|
8806
|
+
}
|
|
8807
|
+
continue;
|
|
8808
|
+
}
|
|
8809
|
+
await this.processParsedMessage(parseJsonRpcPayload(parsedLine));
|
|
8810
|
+
}
|
|
8811
|
+
} catch (error2) {
|
|
8812
|
+
if (this.disposedError === void 0) {
|
|
8813
|
+
this.dispose(
|
|
8814
|
+
error2 instanceof Error ? error2 : new Error(`JSON-RPC input stream failed: ${String(error2)}`)
|
|
8815
|
+
);
|
|
8816
|
+
}
|
|
8817
|
+
return;
|
|
8818
|
+
}
|
|
8819
|
+
if (this.disposedError === void 0) {
|
|
8820
|
+
const streamClosedReason = await this.resolveInputStreamClosedReason();
|
|
8821
|
+
if (this.disposedError === void 0) {
|
|
8822
|
+
this.dispose(streamClosedReason);
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
}
|
|
8826
|
+
async resolveInputStreamClosedReason() {
|
|
8827
|
+
const streamClosedError = new Error("JSON-RPC input stream closed");
|
|
8828
|
+
if (this.inputClosedReason === void 0) {
|
|
8829
|
+
return streamClosedError;
|
|
8830
|
+
}
|
|
8831
|
+
try {
|
|
8832
|
+
return await Promise.race([
|
|
8833
|
+
this.inputClosedReason,
|
|
8834
|
+
new Promise((resolve) => {
|
|
8835
|
+
setTimeout(() => {
|
|
8836
|
+
resolve(streamClosedError);
|
|
8837
|
+
}, 50);
|
|
8838
|
+
})
|
|
8839
|
+
]);
|
|
8840
|
+
} catch {
|
|
8841
|
+
return streamClosedError;
|
|
8842
|
+
}
|
|
8843
|
+
}
|
|
8844
|
+
async processParsedMessage(parsed) {
|
|
8845
|
+
if (parsed.type === "request") {
|
|
8846
|
+
const handler = this.requestHandlers.get(parsed.message.method);
|
|
8847
|
+
if (handler === void 0) {
|
|
8848
|
+
this.output.write(
|
|
8849
|
+
serializeJsonRpcMessage2({
|
|
8850
|
+
jsonrpc: "2.0",
|
|
8851
|
+
id: parsed.message.id,
|
|
8852
|
+
error: {
|
|
8853
|
+
code: ERROR_METHOD_NOT_FOUND,
|
|
8854
|
+
message: `Method not found: ${parsed.message.method}`
|
|
8855
|
+
}
|
|
8856
|
+
})
|
|
8857
|
+
);
|
|
8858
|
+
return;
|
|
8859
|
+
}
|
|
8860
|
+
this.handleIncomingRequest(parsed.message, handler);
|
|
8861
|
+
return;
|
|
8862
|
+
}
|
|
8863
|
+
if (parsed.type === "notification") {
|
|
8864
|
+
if (parsed.message.method === "notifications/cancelled") {
|
|
8865
|
+
this.handleCancellationNotification(parsed.message.params);
|
|
8866
|
+
}
|
|
8867
|
+
const handler = this.notificationHandlers.get(parsed.message.method);
|
|
8868
|
+
if (handler === void 0) {
|
|
8869
|
+
return;
|
|
8870
|
+
}
|
|
8871
|
+
try {
|
|
8872
|
+
await handler(parsed.message.params, {
|
|
8873
|
+
method: parsed.message.method
|
|
8874
|
+
});
|
|
8875
|
+
} catch {
|
|
8876
|
+
return;
|
|
8877
|
+
}
|
|
8878
|
+
return;
|
|
8879
|
+
}
|
|
8880
|
+
if (parsed.type === "invalid") {
|
|
8881
|
+
const errorResponse = {
|
|
8882
|
+
jsonrpc: "2.0",
|
|
8883
|
+
id: parsed.id,
|
|
8884
|
+
error: {
|
|
8885
|
+
code: parsed.error.code,
|
|
8886
|
+
message: parsed.error.message
|
|
8887
|
+
}
|
|
8888
|
+
};
|
|
8889
|
+
if (parsed.error.data !== void 0) {
|
|
8890
|
+
errorResponse.error.data = parsed.error.data;
|
|
8891
|
+
}
|
|
8892
|
+
this.output.write(`${JSON.stringify(errorResponse)}
|
|
8893
|
+
`);
|
|
8894
|
+
return;
|
|
8895
|
+
}
|
|
8896
|
+
if (parsed.type !== "response") {
|
|
8897
|
+
return;
|
|
8898
|
+
}
|
|
8899
|
+
const pending = this.pendingRequests.get(parsed.message.id);
|
|
8900
|
+
if (pending === void 0) {
|
|
8901
|
+
return;
|
|
8902
|
+
}
|
|
8903
|
+
this.pendingRequests.delete(parsed.message.id);
|
|
8904
|
+
clearTimeout(pending.timeout);
|
|
8905
|
+
if ("result" in parsed.message) {
|
|
8906
|
+
pending.resolve(parsed.message.result);
|
|
8907
|
+
return;
|
|
8908
|
+
}
|
|
8909
|
+
pending.reject(
|
|
8910
|
+
new McpError(
|
|
8911
|
+
parsed.message.error.code,
|
|
8912
|
+
parsed.message.error.message,
|
|
8913
|
+
parsed.message.error.data
|
|
8914
|
+
)
|
|
8915
|
+
);
|
|
8916
|
+
}
|
|
8917
|
+
handleIncomingRequest(message, handler) {
|
|
8918
|
+
const activeRequest = {
|
|
8919
|
+
cancelled: false
|
|
8920
|
+
};
|
|
8921
|
+
this.activeIncomingRequests.set(message.id, activeRequest);
|
|
8922
|
+
void (async () => {
|
|
8923
|
+
try {
|
|
8924
|
+
const result = await handler(message.params, {
|
|
8925
|
+
id: message.id,
|
|
8926
|
+
method: message.method
|
|
8927
|
+
});
|
|
8928
|
+
if (this.disposedError !== void 0 || activeRequest.cancelled) {
|
|
8929
|
+
return;
|
|
8930
|
+
}
|
|
8931
|
+
this.output.write(
|
|
8932
|
+
serializeJsonRpcMessage2({
|
|
8933
|
+
jsonrpc: "2.0",
|
|
8934
|
+
id: message.id,
|
|
8935
|
+
result
|
|
8936
|
+
})
|
|
8937
|
+
);
|
|
8938
|
+
} catch (error2) {
|
|
8939
|
+
if (this.disposedError !== void 0 || activeRequest.cancelled) {
|
|
8940
|
+
return;
|
|
8941
|
+
}
|
|
8942
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
8943
|
+
this.output.write(
|
|
8944
|
+
serializeJsonRpcMessage2({
|
|
8945
|
+
jsonrpc: "2.0",
|
|
8946
|
+
id: message.id,
|
|
8947
|
+
error: {
|
|
8948
|
+
code: ERROR_INTERNAL,
|
|
8949
|
+
message: errorMessage
|
|
8950
|
+
}
|
|
8951
|
+
})
|
|
8952
|
+
);
|
|
8953
|
+
} finally {
|
|
8954
|
+
const inFlightRequest = this.activeIncomingRequests.get(message.id);
|
|
8955
|
+
if (inFlightRequest === activeRequest) {
|
|
8956
|
+
this.activeIncomingRequests.delete(message.id);
|
|
8957
|
+
}
|
|
8958
|
+
}
|
|
8959
|
+
})();
|
|
8960
|
+
}
|
|
8961
|
+
handleCancellationNotification(params) {
|
|
8962
|
+
if (!isObjectRecord3(params)) {
|
|
8963
|
+
return;
|
|
8964
|
+
}
|
|
8965
|
+
const requestId = params.requestId;
|
|
8966
|
+
if (!isRequestId2(requestId)) {
|
|
8967
|
+
return;
|
|
8968
|
+
}
|
|
8969
|
+
const activeRequest = this.activeIncomingRequests.get(requestId);
|
|
8970
|
+
if (activeRequest === void 0) {
|
|
8971
|
+
return;
|
|
8972
|
+
}
|
|
8973
|
+
activeRequest.cancelled = true;
|
|
8974
|
+
this.activeIncomingRequests.delete(requestId);
|
|
8975
|
+
}
|
|
8976
|
+
};
|
|
8977
|
+
}
|
|
8978
|
+
});
|
|
8979
|
+
|
|
8980
|
+
// packages/tiny-mcp-client/src/index.ts
|
|
8981
|
+
var init_src7 = __esm({
|
|
8982
|
+
"packages/tiny-mcp-client/src/index.ts"() {
|
|
8983
|
+
"use strict";
|
|
8984
|
+
init_internal();
|
|
8985
|
+
}
|
|
8986
|
+
});
|
|
8987
|
+
|
|
8988
|
+
// packages/poe-agent/src/mcp-tool-executor.ts
|
|
8989
|
+
function namespaceMcpToolName(serverName, toolName) {
|
|
8990
|
+
return `mcp__${serverName}__${toolName}`;
|
|
8991
|
+
}
|
|
8992
|
+
function mcpToolToOpenAiTool(serverName, mcpTool) {
|
|
8993
|
+
const parameters = {
|
|
8994
|
+
type: "object",
|
|
8995
|
+
properties: getInputSchemaProperties(mcpTool.inputSchema)
|
|
8996
|
+
};
|
|
8997
|
+
const required2 = getInputSchemaRequired(mcpTool.inputSchema);
|
|
8998
|
+
if (required2) {
|
|
8999
|
+
parameters.required = required2;
|
|
9000
|
+
}
|
|
9001
|
+
return {
|
|
9002
|
+
type: "function",
|
|
9003
|
+
function: {
|
|
9004
|
+
name: namespaceMcpToolName(serverName, mcpTool.name),
|
|
9005
|
+
description: mcpTool.description ?? "",
|
|
9006
|
+
parameters
|
|
9007
|
+
}
|
|
9008
|
+
};
|
|
9009
|
+
}
|
|
9010
|
+
function callToolResultToString(result) {
|
|
9011
|
+
const content = result.content.map(contentItemToString).join("\n");
|
|
9012
|
+
if (result.isError) {
|
|
9013
|
+
throw new Error(content);
|
|
9014
|
+
}
|
|
9015
|
+
return content;
|
|
9016
|
+
}
|
|
9017
|
+
function getInputSchemaProperties(inputSchema) {
|
|
9018
|
+
const properties = inputSchema.properties;
|
|
9019
|
+
return isObjectRecord4(properties) ? properties : {};
|
|
9020
|
+
}
|
|
9021
|
+
function getInputSchemaRequired(inputSchema) {
|
|
9022
|
+
const required2 = inputSchema.required;
|
|
9023
|
+
if (!Array.isArray(required2) || required2.some((value) => typeof value !== "string")) {
|
|
9024
|
+
return void 0;
|
|
9025
|
+
}
|
|
9026
|
+
return required2;
|
|
9027
|
+
}
|
|
9028
|
+
function contentItemToString(item) {
|
|
9029
|
+
switch (item.type) {
|
|
9030
|
+
case "text":
|
|
9031
|
+
return item.text;
|
|
9032
|
+
case "image":
|
|
9033
|
+
return `[image: ${item.mimeType}]`;
|
|
9034
|
+
case "audio":
|
|
9035
|
+
return `[audio: ${item.mimeType}]`;
|
|
9036
|
+
case "resource":
|
|
9037
|
+
return resourceContentsToString(item.resource);
|
|
9038
|
+
}
|
|
9039
|
+
}
|
|
9040
|
+
function resourceContentsToString(resource) {
|
|
9041
|
+
if ("text" in resource) {
|
|
9042
|
+
return resource.text;
|
|
9043
|
+
}
|
|
9044
|
+
return `[blob: ${resource.uri}]`;
|
|
9045
|
+
}
|
|
9046
|
+
function isObjectRecord4(value) {
|
|
9047
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9048
|
+
}
|
|
9049
|
+
var McpToolExecutor;
|
|
9050
|
+
var init_mcp_tool_executor = __esm({
|
|
9051
|
+
"packages/poe-agent/src/mcp-tool-executor.ts"() {
|
|
9052
|
+
"use strict";
|
|
9053
|
+
McpToolExecutor = class {
|
|
9054
|
+
discoveredTools = [];
|
|
9055
|
+
toolToClient = /* @__PURE__ */ new Map();
|
|
9056
|
+
clients = /* @__PURE__ */ new Set();
|
|
9057
|
+
disposed = false;
|
|
9058
|
+
async addServer(serverName, client) {
|
|
9059
|
+
this.clients.add(client);
|
|
9060
|
+
let nextCursor;
|
|
9061
|
+
while (true) {
|
|
9062
|
+
const page = nextCursor === void 0 ? await client.listTools() : await client.listTools({ cursor: nextCursor });
|
|
9063
|
+
for (const mcpTool of page.tools) {
|
|
9064
|
+
const openAiTool = mcpToolToOpenAiTool(serverName, mcpTool);
|
|
9065
|
+
this.discoveredTools.push(openAiTool);
|
|
9066
|
+
this.toolToClient.set(openAiTool.function.name, {
|
|
9067
|
+
client,
|
|
9068
|
+
originalName: mcpTool.name
|
|
9069
|
+
});
|
|
9070
|
+
}
|
|
9071
|
+
if (page.nextCursor === void 0) {
|
|
9072
|
+
return;
|
|
9073
|
+
}
|
|
9074
|
+
nextCursor = page.nextCursor;
|
|
9075
|
+
}
|
|
9076
|
+
}
|
|
9077
|
+
getAvailableTools() {
|
|
9078
|
+
return [...this.discoveredTools];
|
|
9079
|
+
}
|
|
9080
|
+
async executeTool(name, args) {
|
|
9081
|
+
if (this.disposed) {
|
|
9082
|
+
throw new Error("MCP tool executor is disposed");
|
|
9083
|
+
}
|
|
9084
|
+
const registration = this.toolToClient.get(name);
|
|
9085
|
+
if (!registration) {
|
|
9086
|
+
throw new Error(`MCP tool not found: ${name}`);
|
|
9087
|
+
}
|
|
9088
|
+
const result = await registration.client.callTool({
|
|
9089
|
+
name: registration.originalName,
|
|
9090
|
+
arguments: args
|
|
9091
|
+
});
|
|
9092
|
+
return callToolResultToString(result);
|
|
9093
|
+
}
|
|
9094
|
+
async dispose() {
|
|
9095
|
+
this.disposed = true;
|
|
9096
|
+
const closeOperations = [];
|
|
9097
|
+
for (const client of this.clients) {
|
|
9098
|
+
if (client.close === void 0) {
|
|
9099
|
+
continue;
|
|
9100
|
+
}
|
|
9101
|
+
closeOperations.push(client.close());
|
|
9102
|
+
}
|
|
9103
|
+
await Promise.allSettled(closeOperations);
|
|
9104
|
+
this.clients.clear();
|
|
9105
|
+
}
|
|
9106
|
+
};
|
|
9107
|
+
}
|
|
9108
|
+
});
|
|
9109
|
+
|
|
9110
|
+
// packages/poe-agent/src/SYSTEM_PROMPT.md
|
|
9111
|
+
var SYSTEM_PROMPT_default;
|
|
9112
|
+
var init_SYSTEM_PROMPT = __esm({
|
|
9113
|
+
"packages/poe-agent/src/SYSTEM_PROMPT.md"() {
|
|
9114
|
+
SYSTEM_PROMPT_default = "You are a Poe agent, built by Poe \u2014 an interactive CLI tool that helps users with software engineering tasks.\n\n## Security\n\nAssist with defensive security only. Refuse malicious code, credential harvesting, or bulk crawling for secrets. Allow security analysis, detection rules, vulnerability explanations, and defensive tools.\n\nNever generate or guess URLs unless they help with programming. You may use URLs from user messages or local files.\n\n## Behavior\n\n- Be concise and direct. Minimize output tokens. Skip preamble and postamble.\n- Do what was asked \u2014 nothing more, nothing less.\n- Prefer editing existing files over creating new ones. Never create docs/READMEs unless asked.\n- Prioritize technical accuracy over validating beliefs. Disagree when necessary.\n- Read before you write.\n";
|
|
9115
|
+
}
|
|
9116
|
+
});
|
|
9117
|
+
|
|
7698
9118
|
// packages/poe-agent/src/system-prompt.ts
|
|
7699
|
-
import { readFileSync } from "node:fs";
|
|
7700
|
-
import { readFile as readFile2 } from "node:fs/promises";
|
|
7701
9119
|
async function loadSystemPrompt() {
|
|
7702
|
-
return
|
|
9120
|
+
return SYSTEM_PROMPT_default;
|
|
7703
9121
|
}
|
|
7704
|
-
var systemPromptUrl;
|
|
7705
9122
|
var init_system_prompt = __esm({
|
|
7706
9123
|
"packages/poe-agent/src/system-prompt.ts"() {
|
|
7707
9124
|
"use strict";
|
|
7708
|
-
|
|
9125
|
+
init_SYSTEM_PROMPT();
|
|
7709
9126
|
}
|
|
7710
9127
|
});
|
|
7711
9128
|
|
|
@@ -8033,7 +9450,41 @@ async function createAgentSession(options = {}) {
|
|
|
8033
9450
|
cwd: options.cwd,
|
|
8034
9451
|
allowedPaths: options.allowedPaths
|
|
8035
9452
|
});
|
|
8036
|
-
const
|
|
9453
|
+
const builtInTools = toolExecutor.getAvailableTools();
|
|
9454
|
+
const builtInToolNames = new Set(builtInTools.map((tool) => tool.function.name));
|
|
9455
|
+
let tools = builtInTools;
|
|
9456
|
+
let chatToolExecutor = toolExecutor;
|
|
9457
|
+
let mcpToolExecutor;
|
|
9458
|
+
if (options.mcpServers !== void 0) {
|
|
9459
|
+
const createdMcpToolExecutor = new McpToolExecutor();
|
|
9460
|
+
mcpToolExecutor = createdMcpToolExecutor;
|
|
9461
|
+
try {
|
|
9462
|
+
for (const [serverName, serverDefinition] of Object.entries(options.mcpServers)) {
|
|
9463
|
+
const mcpClient = new McpClient({
|
|
9464
|
+
clientInfo: {
|
|
9465
|
+
name: "poe-agent",
|
|
9466
|
+
version: "0.0.1"
|
|
9467
|
+
}
|
|
9468
|
+
});
|
|
9469
|
+
const transport = createMcpTransport(serverDefinition);
|
|
9470
|
+
await mcpClient.connect(transport);
|
|
9471
|
+
await createdMcpToolExecutor.addServer(serverName, mcpClient);
|
|
9472
|
+
}
|
|
9473
|
+
} catch (error2) {
|
|
9474
|
+
await createdMcpToolExecutor.dispose();
|
|
9475
|
+
throw error2;
|
|
9476
|
+
}
|
|
9477
|
+
const mcpTools = createdMcpToolExecutor.getAvailableTools();
|
|
9478
|
+
tools = [...builtInTools, ...mcpTools];
|
|
9479
|
+
chatToolExecutor = {
|
|
9480
|
+
executeTool(name, args) {
|
|
9481
|
+
if (builtInToolNames.has(name)) {
|
|
9482
|
+
return toolExecutor.executeTool(name, args);
|
|
9483
|
+
}
|
|
9484
|
+
return createdMcpToolExecutor.executeTool(name, args);
|
|
9485
|
+
}
|
|
9486
|
+
};
|
|
9487
|
+
}
|
|
8037
9488
|
let currentOnSessionUpdate;
|
|
8038
9489
|
const chatService = new PoeChatService({
|
|
8039
9490
|
apiKey,
|
|
@@ -8041,7 +9492,7 @@ async function createAgentSession(options = {}) {
|
|
|
8041
9492
|
baseUrl: options.baseUrl,
|
|
8042
9493
|
fetch: options.fetch,
|
|
8043
9494
|
systemPrompt,
|
|
8044
|
-
toolExecutor,
|
|
9495
|
+
toolExecutor: chatToolExecutor,
|
|
8045
9496
|
maxToolCallIterations: options.maxToolCallIterations,
|
|
8046
9497
|
onToolCall: (event) => {
|
|
8047
9498
|
if (!currentOnSessionUpdate) return;
|
|
@@ -8079,12 +9530,32 @@ async function createAgentSession(options = {}) {
|
|
|
8079
9530
|
disposed = true;
|
|
8080
9531
|
chatService.clearConversationHistory();
|
|
8081
9532
|
const disposableToolExecutor = toolExecutor;
|
|
9533
|
+
const disposePromises = [];
|
|
8082
9534
|
if (typeof disposableToolExecutor.dispose === "function") {
|
|
8083
|
-
|
|
9535
|
+
disposePromises.push(Promise.resolve(disposableToolExecutor.dispose()));
|
|
9536
|
+
}
|
|
9537
|
+
if (mcpToolExecutor) {
|
|
9538
|
+
disposePromises.push(mcpToolExecutor.dispose());
|
|
9539
|
+
}
|
|
9540
|
+
if (disposePromises.length > 0) {
|
|
9541
|
+
await Promise.all(disposePromises);
|
|
8084
9542
|
}
|
|
8085
9543
|
}
|
|
8086
9544
|
};
|
|
8087
9545
|
}
|
|
9546
|
+
function createMcpTransport(server) {
|
|
9547
|
+
if (server.transport === "stdio") {
|
|
9548
|
+
return new StdioTransport({
|
|
9549
|
+
command: server.command,
|
|
9550
|
+
args: server.args,
|
|
9551
|
+
env: server.env
|
|
9552
|
+
});
|
|
9553
|
+
}
|
|
9554
|
+
return new HttpTransport({
|
|
9555
|
+
url: server.url,
|
|
9556
|
+
headers: server.headers
|
|
9557
|
+
});
|
|
9558
|
+
}
|
|
8088
9559
|
async function resolveApiKey(explicitApiKey) {
|
|
8089
9560
|
const normalizedExplicitApiKey = normalizeNonEmptyString(explicitApiKey);
|
|
8090
9561
|
if (normalizedExplicitApiKey) {
|
|
@@ -8148,6 +9619,8 @@ var init_agent_session = __esm({
|
|
|
8148
9619
|
"use strict";
|
|
8149
9620
|
init_src();
|
|
8150
9621
|
init_chat();
|
|
9622
|
+
init_src7();
|
|
9623
|
+
init_mcp_tool_executor();
|
|
8151
9624
|
init_system_prompt();
|
|
8152
9625
|
init_tool_executor();
|
|
8153
9626
|
}
|
|
@@ -8158,7 +9631,7 @@ var src_exports = {};
|
|
|
8158
9631
|
__export(src_exports, {
|
|
8159
9632
|
createAgentSession: () => createAgentSession
|
|
8160
9633
|
});
|
|
8161
|
-
var
|
|
9634
|
+
var init_src8 = __esm({
|
|
8162
9635
|
"packages/poe-agent/src/index.ts"() {
|
|
8163
9636
|
"use strict";
|
|
8164
9637
|
init_agent_session();
|
|
@@ -8217,6 +9690,18 @@ function createToolRenderState() {
|
|
|
8217
9690
|
toolCallTitles: /* @__PURE__ */ new Map()
|
|
8218
9691
|
};
|
|
8219
9692
|
}
|
|
9693
|
+
function toAgentSessionMcpServers(servers) {
|
|
9694
|
+
const mappedServers = {};
|
|
9695
|
+
for (const [name, server] of Object.entries(servers)) {
|
|
9696
|
+
mappedServers[name] = {
|
|
9697
|
+
transport: "stdio",
|
|
9698
|
+
command: server.command,
|
|
9699
|
+
...server.args && server.args.length > 0 ? { args: [...server.args] } : {},
|
|
9700
|
+
...server.env && Object.keys(server.env).length > 0 ? { env: { ...server.env } } : {}
|
|
9701
|
+
};
|
|
9702
|
+
}
|
|
9703
|
+
return Object.keys(mappedServers).length > 0 ? mappedServers : void 0;
|
|
9704
|
+
}
|
|
8220
9705
|
function toErrorMessage2(value) {
|
|
8221
9706
|
if (value instanceof Error) {
|
|
8222
9707
|
return value.message;
|
|
@@ -8441,6 +9926,7 @@ function createInMemoryAcpTransport(options) {
|
|
|
8441
9926
|
const closedPromise = new Promise((resolve) => {
|
|
8442
9927
|
resolveClosed = resolve;
|
|
8443
9928
|
});
|
|
9929
|
+
const sessionMcpServers = options.mcpServers ? toAgentSessionMcpServers(options.mcpServers) : void 0;
|
|
8444
9930
|
const closeTransport = (reason) => {
|
|
8445
9931
|
if (closed) {
|
|
8446
9932
|
return;
|
|
@@ -8476,10 +9962,12 @@ function createInMemoryAcpTransport(options) {
|
|
|
8476
9962
|
}
|
|
8477
9963
|
if (method === "session/new") {
|
|
8478
9964
|
const request = params;
|
|
8479
|
-
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (
|
|
9965
|
+
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src8(), src_exports));
|
|
8480
9966
|
const session = await createAgentSession2({
|
|
8481
9967
|
model: options.model,
|
|
8482
|
-
cwd: request.cwd || options.cwd
|
|
9968
|
+
cwd: request.cwd || options.cwd,
|
|
9969
|
+
...options.baseUrl ? { baseUrl: options.baseUrl } : {},
|
|
9970
|
+
...sessionMcpServers ? { mcpServers: sessionMcpServers } : {}
|
|
8483
9971
|
});
|
|
8484
9972
|
const sessionId = `poe-agent-session-${sessionCounter + 1}`;
|
|
8485
9973
|
sessionCounter += 1;
|
|
@@ -8550,7 +10038,9 @@ async function runPoeAgentAcpLifecycle(options) {
|
|
|
8550
10038
|
let assistantText = "";
|
|
8551
10039
|
const transport = createInMemoryAcpTransport({
|
|
8552
10040
|
model: options.model,
|
|
8553
|
-
cwd: options.cwd
|
|
10041
|
+
cwd: options.cwd,
|
|
10042
|
+
baseUrl: options.baseUrl,
|
|
10043
|
+
mcpServers: options.mcpServers
|
|
8554
10044
|
});
|
|
8555
10045
|
const client = new AcpClient({ transport });
|
|
8556
10046
|
try {
|
|
@@ -8604,6 +10094,8 @@ function spawnPoeAgentWithAcp(options) {
|
|
|
8604
10094
|
prompt: options.prompt,
|
|
8605
10095
|
model,
|
|
8606
10096
|
cwd,
|
|
10097
|
+
baseUrl: options.baseUrl,
|
|
10098
|
+
mcpServers: options.mcpServers,
|
|
8607
10099
|
onEvent: (event) => {
|
|
8608
10100
|
queue.push(event);
|
|
8609
10101
|
}
|
|
@@ -8628,6 +10120,7 @@ var init_poe_agent = __esm({
|
|
|
8628
10120
|
label: "Poe Agent",
|
|
8629
10121
|
summary: "Run one-shot prompts with the built-in Poe agent runtime.",
|
|
8630
10122
|
supportsStdinPrompt: true,
|
|
10123
|
+
supportsMcpSpawn: true,
|
|
8631
10124
|
manifest: {
|
|
8632
10125
|
configure: []
|
|
8633
10126
|
},
|
|
@@ -8635,7 +10128,9 @@ var init_poe_agent = __esm({
|
|
|
8635
10128
|
const result = await runPoeAgentAcpLifecycle({
|
|
8636
10129
|
prompt: options.prompt,
|
|
8637
10130
|
model: options.model ?? DEFAULT_FRONTIER_MODEL,
|
|
8638
|
-
cwd: options.cwd ?? context.env.cwd
|
|
10131
|
+
cwd: options.cwd ?? context.env.cwd,
|
|
10132
|
+
baseUrl: context.env.poeApiBaseUrl,
|
|
10133
|
+
mcpServers: options.mcpServers
|
|
8639
10134
|
});
|
|
8640
10135
|
return {
|
|
8641
10136
|
stdout: result.stdout,
|
|
@@ -8648,7 +10143,7 @@ var init_poe_agent = __esm({
|
|
|
8648
10143
|
});
|
|
8649
10144
|
|
|
8650
10145
|
// src/sdk/spawn.ts
|
|
8651
|
-
function
|
|
10146
|
+
function spawn5(service, promptOrOptions, maybeOptions) {
|
|
8652
10147
|
const options = typeof promptOrOptions === "string" ? { ...maybeOptions, prompt: promptOrOptions } : promptOrOptions;
|
|
8653
10148
|
const emptyEvents = (async function* () {
|
|
8654
10149
|
})();
|
|
@@ -8687,10 +10182,13 @@ function spawn4(service, promptOrOptions, maybeOptions) {
|
|
|
8687
10182
|
};
|
|
8688
10183
|
}
|
|
8689
10184
|
if (service === "poe-agent") {
|
|
10185
|
+
const poeBaseUrl = typeof process.env.POE_BASE_URL === "string" ? process.env.POE_BASE_URL.trim() || void 0 : void 0;
|
|
8690
10186
|
const { events: innerEvents, done } = spawnPoeAgentWithAcp({
|
|
8691
10187
|
prompt: options.prompt,
|
|
8692
10188
|
cwd: options.cwd,
|
|
8693
|
-
model: options.model
|
|
10189
|
+
model: options.model,
|
|
10190
|
+
...poeBaseUrl ? { baseUrl: poeBaseUrl } : {},
|
|
10191
|
+
...options.mcpServers ? { mcpServers: options.mcpServers } : {}
|
|
8694
10192
|
});
|
|
8695
10193
|
resolveEventsOnce(innerEvents);
|
|
8696
10194
|
const final = await done;
|
|
@@ -8763,8 +10261,8 @@ var init_spawn3 = __esm({
|
|
|
8763
10261
|
await init_container();
|
|
8764
10262
|
init_src5();
|
|
8765
10263
|
init_poe_agent();
|
|
8766
|
-
|
|
8767
|
-
const { events, result } =
|
|
10264
|
+
spawn5.pretty = async function pretty(service, promptOrOptions, maybeOptions) {
|
|
10265
|
+
const { events, result } = spawn5(service, promptOrOptions, maybeOptions);
|
|
8768
10266
|
await renderAcpStream(events);
|
|
8769
10267
|
return result;
|
|
8770
10268
|
};
|
|
@@ -9402,7 +10900,7 @@ function registerAgentCommand(program, container) {
|
|
|
9402
10900
|
}
|
|
9403
10901
|
let session;
|
|
9404
10902
|
try {
|
|
9405
|
-
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (
|
|
10903
|
+
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src8(), src_exports));
|
|
9406
10904
|
session = await createAgentSession2({
|
|
9407
10905
|
model: options.model,
|
|
9408
10906
|
apiKey: options.apiKey,
|
|
@@ -9576,7 +11074,12 @@ function registerSpawnCommand(program, container, options = {}) {
|
|
|
9576
11074
|
}
|
|
9577
11075
|
}
|
|
9578
11076
|
try {
|
|
9579
|
-
assertMcpSpawnSupport(
|
|
11077
|
+
assertMcpSpawnSupport(
|
|
11078
|
+
adapter.label,
|
|
11079
|
+
canonicalService,
|
|
11080
|
+
adapter.supportsMcpSpawn === true,
|
|
11081
|
+
mcpServers
|
|
11082
|
+
);
|
|
9580
11083
|
if (flags.dryRun) {
|
|
9581
11084
|
await spawnCore(container, canonicalService, spawnOptions, {
|
|
9582
11085
|
dryRun: true,
|
|
@@ -9593,7 +11096,7 @@ function registerSpawnCommand(program, container, options = {}) {
|
|
|
9593
11096
|
if (!proceed) {
|
|
9594
11097
|
return;
|
|
9595
11098
|
}
|
|
9596
|
-
const { events, result } =
|
|
11099
|
+
const { events, result } = spawn5(canonicalService, {
|
|
9597
11100
|
prompt: spawnOptions.prompt,
|
|
9598
11101
|
args: spawnOptions.args,
|
|
9599
11102
|
model: spawnOptions.model,
|
|
@@ -9677,14 +11180,14 @@ function parseMcpSpawnConfig(input) {
|
|
|
9677
11180
|
"--mcp-config must be valid JSON in this shape: {name: {command, args?, env?}}"
|
|
9678
11181
|
);
|
|
9679
11182
|
}
|
|
9680
|
-
if (!
|
|
11183
|
+
if (!isObjectRecord5(parsed)) {
|
|
9681
11184
|
throw new ValidationError(
|
|
9682
11185
|
"--mcp-config must be an object in this shape: {name: {command, args?, env?}}"
|
|
9683
11186
|
);
|
|
9684
11187
|
}
|
|
9685
11188
|
const servers = {};
|
|
9686
11189
|
for (const [name, value] of Object.entries(parsed)) {
|
|
9687
|
-
if (!
|
|
11190
|
+
if (!isObjectRecord5(value)) {
|
|
9688
11191
|
throw new ValidationError(
|
|
9689
11192
|
`--mcp-config entry "${name}" must be an object: {command, args?, env?}`
|
|
9690
11193
|
);
|
|
@@ -9714,7 +11217,7 @@ function parseMcpSpawnConfig(input) {
|
|
|
9714
11217
|
}
|
|
9715
11218
|
let env;
|
|
9716
11219
|
if ("env" in value && value.env !== void 0) {
|
|
9717
|
-
if (!
|
|
11220
|
+
if (!isObjectRecord5(value.env)) {
|
|
9718
11221
|
throw new ValidationError(
|
|
9719
11222
|
`--mcp-config entry "${name}".env must be an object of string values`
|
|
9720
11223
|
);
|
|
@@ -9737,11 +11240,11 @@ function parseMcpSpawnConfig(input) {
|
|
|
9737
11240
|
}
|
|
9738
11241
|
return Object.keys(servers).length > 0 ? servers : void 0;
|
|
9739
11242
|
}
|
|
9740
|
-
function assertMcpSpawnSupport(label, service, servers) {
|
|
11243
|
+
function assertMcpSpawnSupport(label, service, providerSupportsMcpSpawn, servers) {
|
|
9741
11244
|
if (!servers || Object.keys(servers).length === 0) {
|
|
9742
11245
|
return;
|
|
9743
11246
|
}
|
|
9744
|
-
if (supportsMcpAtSpawn(service)) {
|
|
11247
|
+
if (supportsMcpAtSpawn(service) || providerSupportsMcpSpawn) {
|
|
9745
11248
|
return;
|
|
9746
11249
|
}
|
|
9747
11250
|
const supported = listMcpSupportedAgents();
|
|
@@ -9750,7 +11253,7 @@ function assertMcpSpawnSupport(label, service, servers) {
|
|
|
9750
11253
|
Agents with spawn-time MCP support: ${supported.join(", ")}`
|
|
9751
11254
|
);
|
|
9752
11255
|
}
|
|
9753
|
-
function
|
|
11256
|
+
function isObjectRecord5(value) {
|
|
9754
11257
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9755
11258
|
}
|
|
9756
11259
|
var init_spawn4 = __esm({
|
|
@@ -9777,7 +11280,7 @@ async function research(container, options) {
|
|
|
9777
11280
|
});
|
|
9778
11281
|
const researchPrompt = buildResearchPrompt(options.prompt);
|
|
9779
11282
|
const mode = options.mode ?? "read";
|
|
9780
|
-
const { events, result } =
|
|
11283
|
+
const { events, result } = spawn5(options.agent, {
|
|
9781
11284
|
prompt: researchPrompt,
|
|
9782
11285
|
args: options.args ?? [],
|
|
9783
11286
|
model: options.model,
|
|
@@ -10272,7 +11775,7 @@ var init_research2 = __esm({
|
|
|
10272
11775
|
});
|
|
10273
11776
|
|
|
10274
11777
|
// src/cli/isolated-env-runner.ts
|
|
10275
|
-
import { spawn as
|
|
11778
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
10276
11779
|
async function isolatedEnvRunner(input) {
|
|
10277
11780
|
const details = await resolveIsolatedEnvDetails(
|
|
10278
11781
|
input.env,
|
|
@@ -10297,7 +11800,7 @@ async function isolatedEnvRunner(input) {
|
|
|
10297
11800
|
);
|
|
10298
11801
|
args = buildArgsWithMergedSettings(args, resolvedSettings);
|
|
10299
11802
|
}
|
|
10300
|
-
const child =
|
|
11803
|
+
const child = spawn6(details.agentBinary, args, {
|
|
10301
11804
|
stdio: "inherit",
|
|
10302
11805
|
env: {
|
|
10303
11806
|
...process.env,
|
|
@@ -32072,7 +33575,7 @@ var init_content = __esm({
|
|
|
32072
33575
|
});
|
|
32073
33576
|
|
|
32074
33577
|
// packages/tiny-stdio-mcp-server/src/index.ts
|
|
32075
|
-
var
|
|
33578
|
+
var init_src9 = __esm({
|
|
32076
33579
|
"packages/tiny-stdio-mcp-server/src/index.ts"() {
|
|
32077
33580
|
"use strict";
|
|
32078
33581
|
init_server();
|
|
@@ -32376,7 +33879,7 @@ var generateTextSchema, generateImageSchema, generateVideoSchema, generateAudioS
|
|
|
32376
33879
|
var init_mcp_server = __esm({
|
|
32377
33880
|
"src/cli/mcp-server.ts"() {
|
|
32378
33881
|
"use strict";
|
|
32379
|
-
|
|
33882
|
+
init_src9();
|
|
32380
33883
|
init_client_instance();
|
|
32381
33884
|
init_constants();
|
|
32382
33885
|
generateTextSchema = defineSchema({
|
|
@@ -32886,7 +34389,7 @@ var init_apply = __esm({
|
|
|
32886
34389
|
});
|
|
32887
34390
|
|
|
32888
34391
|
// packages/agent-mcp-config/src/index.ts
|
|
32889
|
-
var
|
|
34392
|
+
var init_src10 = __esm({
|
|
32890
34393
|
"packages/agent-mcp-config/src/index.ts"() {
|
|
32891
34394
|
"use strict";
|
|
32892
34395
|
init_configs2();
|
|
@@ -33066,7 +34569,7 @@ var init_mcp2 = __esm({
|
|
|
33066
34569
|
init_shared();
|
|
33067
34570
|
init_mcp_output_format();
|
|
33068
34571
|
init_command_not_found();
|
|
33069
|
-
|
|
34572
|
+
init_src10();
|
|
33070
34573
|
init_execution_context();
|
|
33071
34574
|
DEFAULT_MCP_AGENT = "claude-code";
|
|
33072
34575
|
}
|
|
@@ -33110,7 +34613,7 @@ var init_configs3 = __esm({
|
|
|
33110
34613
|
});
|
|
33111
34614
|
|
|
33112
34615
|
// packages/agent-skill-config/src/templates.ts
|
|
33113
|
-
import { readFile as
|
|
34616
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
33114
34617
|
async function getTemplates() {
|
|
33115
34618
|
if (templatesCache) {
|
|
33116
34619
|
return templatesCache;
|
|
@@ -33119,7 +34622,7 @@ async function getTemplates() {
|
|
|
33119
34622
|
"./templates/poe-generate.md",
|
|
33120
34623
|
import.meta.url
|
|
33121
34624
|
);
|
|
33122
|
-
const poeGenerateTemplate = await
|
|
34625
|
+
const poeGenerateTemplate = await readFile2(poeGenerateTemplateUrl, "utf8");
|
|
33123
34626
|
templatesCache = {
|
|
33124
34627
|
"poe-generate.md": poeGenerateTemplate
|
|
33125
34628
|
};
|
|
@@ -33266,7 +34769,7 @@ var init_apply2 = __esm({
|
|
|
33266
34769
|
});
|
|
33267
34770
|
|
|
33268
34771
|
// packages/agent-skill-config/src/index.ts
|
|
33269
|
-
var
|
|
34772
|
+
var init_src11 = __esm({
|
|
33270
34773
|
"packages/agent-skill-config/src/index.ts"() {
|
|
33271
34774
|
"use strict";
|
|
33272
34775
|
init_configs3();
|
|
@@ -33491,7 +34994,7 @@ var init_skill = __esm({
|
|
|
33491
34994
|
"src/cli/commands/skill.ts"() {
|
|
33492
34995
|
"use strict";
|
|
33493
34996
|
init_src4();
|
|
33494
|
-
|
|
34997
|
+
init_src11();
|
|
33495
34998
|
init_shared();
|
|
33496
34999
|
init_command_not_found();
|
|
33497
35000
|
DEFAULT_SKILL_AGENT = "claude-code";
|
|
@@ -33784,7 +35287,7 @@ var init_list = __esm({
|
|
|
33784
35287
|
});
|
|
33785
35288
|
|
|
33786
35289
|
// packages/worktree/src/index.ts
|
|
33787
|
-
var
|
|
35290
|
+
var init_src12 = __esm({
|
|
33788
35291
|
"packages/worktree/src/index.ts"() {
|
|
33789
35292
|
"use strict";
|
|
33790
35293
|
init_create();
|
|
@@ -33941,6 +35444,47 @@ function normalizeStatus(value) {
|
|
|
33941
35444
|
`Invalid story status "${value}". Expected one of: open, in_progress, done`
|
|
33942
35445
|
);
|
|
33943
35446
|
}
|
|
35447
|
+
function normalizeRequirementStatus(value) {
|
|
35448
|
+
if (value === void 0 || value === null) return "pending";
|
|
35449
|
+
if (typeof value !== "string") throw new Error("Invalid requirement status: expected string");
|
|
35450
|
+
const normalized = value.trim().toLowerCase();
|
|
35451
|
+
if (!normalized) return "pending";
|
|
35452
|
+
if (normalized === "pending") return "pending";
|
|
35453
|
+
if (normalized === "verifying") return "verifying";
|
|
35454
|
+
if (normalized === "passed") return "passed";
|
|
35455
|
+
if (normalized === "failed") return "failed";
|
|
35456
|
+
throw new Error(
|
|
35457
|
+
`Invalid requirement status "${value}". Expected one of: pending, verifying, passed, failed`
|
|
35458
|
+
);
|
|
35459
|
+
}
|
|
35460
|
+
function parseScenario(value, index, reqIndex) {
|
|
35461
|
+
if (!isRecord5(value)) throw new Error(`Invalid requirements[${reqIndex}].scenarios[${index}]: expected object`);
|
|
35462
|
+
return {
|
|
35463
|
+
name: asRequiredString(value.name, `requirements[${reqIndex}].scenarios[${index}].name`),
|
|
35464
|
+
when: asRequiredString(value.when, `requirements[${reqIndex}].scenarios[${index}].when`),
|
|
35465
|
+
then: asRequiredString(value.then, `requirements[${reqIndex}].scenarios[${index}].then`)
|
|
35466
|
+
};
|
|
35467
|
+
}
|
|
35468
|
+
function parseRequirement(value, index) {
|
|
35469
|
+
if (!isRecord5(value)) throw new Error(`Invalid requirements[${index}]: expected object`);
|
|
35470
|
+
const scenariosValue = value.scenarios;
|
|
35471
|
+
const scenarios = scenariosValue === void 0 || scenariosValue === null ? [] : scenariosValue;
|
|
35472
|
+
if (!Array.isArray(scenarios)) {
|
|
35473
|
+
throw new Error(`Invalid requirements[${index}].scenarios: expected array`);
|
|
35474
|
+
}
|
|
35475
|
+
const id = asOptionalString(value.id, `requirements[${index}].id`) ?? `R-${String(index + 1).padStart(3, "0")}`;
|
|
35476
|
+
const req = {
|
|
35477
|
+
id,
|
|
35478
|
+
title: asOptionalString(value.title, `requirements[${index}].title`) ?? `Requirement ${id}`,
|
|
35479
|
+
description: asOptionalString(value.description, `requirements[${index}].description`),
|
|
35480
|
+
scenarios: scenarios.map((s, i) => parseScenario(s, i, index)),
|
|
35481
|
+
status: normalizeRequirementStatus(value.status),
|
|
35482
|
+
verifiedAt: asIsoString(value.verifiedAt, `requirements[${index}].verifiedAt`)
|
|
35483
|
+
};
|
|
35484
|
+
const extra = collectExtra(value, KNOWN_REQUIREMENT_KEYS);
|
|
35485
|
+
if (extra) req._extra = extra;
|
|
35486
|
+
return req;
|
|
35487
|
+
}
|
|
33944
35488
|
function collectExtra(record2, knownKeys) {
|
|
33945
35489
|
const extra = {};
|
|
33946
35490
|
let hasExtra = false;
|
|
@@ -33988,6 +35532,11 @@ function parsePlan(yamlContent) {
|
|
|
33988
35532
|
if (!Array.isArray(stories)) {
|
|
33989
35533
|
throw new Error("Invalid stories: expected array");
|
|
33990
35534
|
}
|
|
35535
|
+
const requirementsValue = doc.requirements;
|
|
35536
|
+
const requirements = requirementsValue === void 0 || requirementsValue === null ? [] : requirementsValue;
|
|
35537
|
+
if (!Array.isArray(requirements)) {
|
|
35538
|
+
throw new Error("Invalid requirements: expected array");
|
|
35539
|
+
}
|
|
33991
35540
|
const KNOWN_PLAN_KEYS = /* @__PURE__ */ new Set([
|
|
33992
35541
|
"version",
|
|
33993
35542
|
"project",
|
|
@@ -33995,6 +35544,7 @@ function parsePlan(yamlContent) {
|
|
|
33995
35544
|
"goals",
|
|
33996
35545
|
"nonGoals",
|
|
33997
35546
|
"qualityGates",
|
|
35547
|
+
"requirements",
|
|
33998
35548
|
"stories"
|
|
33999
35549
|
]);
|
|
34000
35550
|
const plan = {
|
|
@@ -34004,13 +35554,14 @@ function parsePlan(yamlContent) {
|
|
|
34004
35554
|
goals: asStringArray(doc.goals, "goals"),
|
|
34005
35555
|
nonGoals: asStringArray(doc.nonGoals, "nonGoals"),
|
|
34006
35556
|
qualityGates: asStringArray(doc.qualityGates, "qualityGates"),
|
|
35557
|
+
requirements: requirements.map((r, i) => parseRequirement(r, i)),
|
|
34007
35558
|
stories: stories.map((s, i) => parseStory(s, i))
|
|
34008
35559
|
};
|
|
34009
35560
|
const extra = collectExtra(doc, KNOWN_PLAN_KEYS);
|
|
34010
35561
|
if (extra) plan._extra = extra;
|
|
34011
35562
|
return plan;
|
|
34012
35563
|
}
|
|
34013
|
-
var KNOWN_STORY_KEYS;
|
|
35564
|
+
var KNOWN_STORY_KEYS, KNOWN_REQUIREMENT_KEYS;
|
|
34014
35565
|
var init_parser = __esm({
|
|
34015
35566
|
"packages/ralph/src/plan/parser.ts"() {
|
|
34016
35567
|
"use strict";
|
|
@@ -34025,6 +35576,14 @@ var init_parser = __esm({
|
|
|
34025
35576
|
"completedAt",
|
|
34026
35577
|
"updatedAt"
|
|
34027
35578
|
]);
|
|
35579
|
+
KNOWN_REQUIREMENT_KEYS = /* @__PURE__ */ new Set([
|
|
35580
|
+
"id",
|
|
35581
|
+
"title",
|
|
35582
|
+
"description",
|
|
35583
|
+
"scenarios",
|
|
35584
|
+
"status",
|
|
35585
|
+
"verifiedAt"
|
|
35586
|
+
]);
|
|
34028
35587
|
}
|
|
34029
35588
|
});
|
|
34030
35589
|
|
|
@@ -34052,8 +35611,33 @@ function serializeStory(story) {
|
|
|
34052
35611
|
if (story.updatedAt !== void 0) {
|
|
34053
35612
|
ordered.updatedAt = story.updatedAt;
|
|
34054
35613
|
}
|
|
34055
|
-
if (story._extra) {
|
|
34056
|
-
Object.assign(ordered, story._extra);
|
|
35614
|
+
if (story._extra) {
|
|
35615
|
+
Object.assign(ordered, story._extra);
|
|
35616
|
+
}
|
|
35617
|
+
return ordered;
|
|
35618
|
+
}
|
|
35619
|
+
function serializeScenario(scenario) {
|
|
35620
|
+
return {
|
|
35621
|
+
name: scenario.name,
|
|
35622
|
+
when: scenario.when,
|
|
35623
|
+
then: scenario.then
|
|
35624
|
+
};
|
|
35625
|
+
}
|
|
35626
|
+
function serializeRequirement(req) {
|
|
35627
|
+
const ordered = {
|
|
35628
|
+
id: req.id,
|
|
35629
|
+
title: req.title
|
|
35630
|
+
};
|
|
35631
|
+
if (req.description !== void 0) {
|
|
35632
|
+
ordered.description = req.description;
|
|
35633
|
+
}
|
|
35634
|
+
ordered.scenarios = req.scenarios.map(serializeScenario);
|
|
35635
|
+
ordered.status = req.status;
|
|
35636
|
+
if (req.verifiedAt !== void 0) {
|
|
35637
|
+
ordered.verifiedAt = req.verifiedAt;
|
|
35638
|
+
}
|
|
35639
|
+
if (req._extra) {
|
|
35640
|
+
Object.assign(ordered, req._extra);
|
|
34057
35641
|
}
|
|
34058
35642
|
return ordered;
|
|
34059
35643
|
}
|
|
@@ -34068,6 +35652,9 @@ function serializePlan(prd) {
|
|
|
34068
35652
|
ordered.goals = prd.goals;
|
|
34069
35653
|
ordered.nonGoals = prd.nonGoals;
|
|
34070
35654
|
ordered.qualityGates = prd.qualityGates;
|
|
35655
|
+
if (prd.requirements.length > 0) {
|
|
35656
|
+
ordered.requirements = prd.requirements.map(serializeRequirement);
|
|
35657
|
+
}
|
|
34071
35658
|
if (prd._extra) {
|
|
34072
35659
|
Object.assign(ordered, prd._extra);
|
|
34073
35660
|
}
|
|
@@ -34109,6 +35696,31 @@ var init_renderer2 = __esm({
|
|
|
34109
35696
|
}
|
|
34110
35697
|
});
|
|
34111
35698
|
|
|
35699
|
+
// packages/ralph/src/prompt/resolver.ts
|
|
35700
|
+
import { resolve as resolvePath3, join as join3 } from "node:path";
|
|
35701
|
+
async function resolveTemplate(name, options) {
|
|
35702
|
+
const paths = [
|
|
35703
|
+
resolvePath3(options.cwd, ".agents/poe-code-ralph", name)
|
|
35704
|
+
];
|
|
35705
|
+
if (options.homeDir) {
|
|
35706
|
+
paths.push(join3(options.homeDir, ".poe-code", "ralph", name));
|
|
35707
|
+
}
|
|
35708
|
+
paths.push(join3(options.bundledDir, name));
|
|
35709
|
+
for (const p of paths) {
|
|
35710
|
+
try {
|
|
35711
|
+
return await options.fs.readFile(p, "utf8");
|
|
35712
|
+
} catch {
|
|
35713
|
+
continue;
|
|
35714
|
+
}
|
|
35715
|
+
}
|
|
35716
|
+
return null;
|
|
35717
|
+
}
|
|
35718
|
+
var init_resolver = __esm({
|
|
35719
|
+
"packages/ralph/src/prompt/resolver.ts"() {
|
|
35720
|
+
"use strict";
|
|
35721
|
+
}
|
|
35722
|
+
});
|
|
35723
|
+
|
|
34112
35724
|
// packages/ralph/src/story/selector.ts
|
|
34113
35725
|
function isStaleStory(story, nowMs, staleSeconds) {
|
|
34114
35726
|
if (!Number.isFinite(staleSeconds) || staleSeconds < 0) return false;
|
|
@@ -34236,9 +35848,67 @@ var init_updater = __esm({
|
|
|
34236
35848
|
}
|
|
34237
35849
|
});
|
|
34238
35850
|
|
|
34239
|
-
// packages/ralph/src/
|
|
35851
|
+
// packages/ralph/src/requirement/selector.ts
|
|
35852
|
+
function selectRequirement(plan, options = {}) {
|
|
35853
|
+
const ignoreIds = options.ignoreIds ?? null;
|
|
35854
|
+
return plan.requirements.find((r) => r.status !== "passed" && (!ignoreIds || !ignoreIds.has(r.id))) ?? null;
|
|
35855
|
+
}
|
|
35856
|
+
var init_selector2 = __esm({
|
|
35857
|
+
"packages/ralph/src/requirement/selector.ts"() {
|
|
35858
|
+
"use strict";
|
|
35859
|
+
}
|
|
35860
|
+
});
|
|
35861
|
+
|
|
35862
|
+
// packages/ralph/src/requirement/updater.ts
|
|
34240
35863
|
import { dirname as dirname5 } from "node:path";
|
|
34241
35864
|
import * as fsPromises6 from "node:fs/promises";
|
|
35865
|
+
function lockPlanFile3(path22) {
|
|
35866
|
+
return lockFile(path22, { retries: 20, minTimeout: 25, maxTimeout: 250 });
|
|
35867
|
+
}
|
|
35868
|
+
function findRequirement(plan, requirementId) {
|
|
35869
|
+
const req = plan.requirements.find((r) => r.id === requirementId);
|
|
35870
|
+
if (!req) {
|
|
35871
|
+
throw new Error(`Requirement not found: ${requirementId}`);
|
|
35872
|
+
}
|
|
35873
|
+
return req;
|
|
35874
|
+
}
|
|
35875
|
+
async function updateRequirementStatus(planPath, requirementId, status, options = {}) {
|
|
35876
|
+
const fs3 = options.fs ?? fsPromises6;
|
|
35877
|
+
const lock = options.lock ?? lockPlanFile3;
|
|
35878
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
35879
|
+
await fs3.mkdir(dirname5(planPath), { recursive: true });
|
|
35880
|
+
const release = await lock(planPath);
|
|
35881
|
+
try {
|
|
35882
|
+
const yaml = await fs3.readFile(planPath, "utf8");
|
|
35883
|
+
const plan = parsePlan(yaml);
|
|
35884
|
+
const req = findRequirement(plan, requirementId);
|
|
35885
|
+
req.status = status;
|
|
35886
|
+
if (status === "passed") {
|
|
35887
|
+
req.verifiedAt = now.toISOString();
|
|
35888
|
+
} else if (status === "pending" || status === "failed") {
|
|
35889
|
+
req.verifiedAt = void 0;
|
|
35890
|
+
}
|
|
35891
|
+
await writePlan(planPath, plan, {
|
|
35892
|
+
fs: fs3,
|
|
35893
|
+
lock: async () => async () => {
|
|
35894
|
+
}
|
|
35895
|
+
});
|
|
35896
|
+
} finally {
|
|
35897
|
+
await release();
|
|
35898
|
+
}
|
|
35899
|
+
}
|
|
35900
|
+
var init_updater2 = __esm({
|
|
35901
|
+
"packages/ralph/src/requirement/updater.ts"() {
|
|
35902
|
+
"use strict";
|
|
35903
|
+
init_lock();
|
|
35904
|
+
init_parser();
|
|
35905
|
+
init_writer();
|
|
35906
|
+
}
|
|
35907
|
+
});
|
|
35908
|
+
|
|
35909
|
+
// packages/ralph/src/run/metadata.ts
|
|
35910
|
+
import { dirname as dirname6 } from "node:path";
|
|
35911
|
+
import * as fsPromises7 from "node:fs/promises";
|
|
34242
35912
|
function formatCommitLine(commit) {
|
|
34243
35913
|
const hash2 = commit.hash.length > 7 ? commit.hash.slice(0, 7) : commit.hash;
|
|
34244
35914
|
return `${hash2} ${commit.subject}`;
|
|
@@ -34257,8 +35927,8 @@ function appendSection(lines, title, items, options) {
|
|
|
34257
35927
|
lines.push("");
|
|
34258
35928
|
}
|
|
34259
35929
|
async function writeRunMeta(path22, metadata, options = {}) {
|
|
34260
|
-
const fs3 = options.fs ??
|
|
34261
|
-
await fs3.mkdir(
|
|
35930
|
+
const fs3 = options.fs ?? fsPromises7;
|
|
35931
|
+
await fs3.mkdir(dirname6(path22), { recursive: true });
|
|
34262
35932
|
const lines = [];
|
|
34263
35933
|
lines.push("# Ralph Run Summary", "");
|
|
34264
35934
|
lines.push(`- Run ID: ${metadata.runId}`);
|
|
@@ -34382,8 +36052,8 @@ var init_overbaking = __esm({
|
|
|
34382
36052
|
});
|
|
34383
36053
|
|
|
34384
36054
|
// packages/ralph/src/build/loop.ts
|
|
34385
|
-
import { basename as basename2, dirname as
|
|
34386
|
-
import * as
|
|
36055
|
+
import { basename as basename2, dirname as dirname7, resolve as resolvePath4 } from "node:path";
|
|
36056
|
+
import * as fsPromises8 from "node:fs/promises";
|
|
34387
36057
|
import { execSync as execSync2 } from "node:child_process";
|
|
34388
36058
|
async function defaultStreamingSpawn(agentId, options) {
|
|
34389
36059
|
const { events, done } = spawnStreaming({
|
|
@@ -34411,8 +36081,8 @@ async function defaultStreamingSpawn(agentId, options) {
|
|
|
34411
36081
|
};
|
|
34412
36082
|
}
|
|
34413
36083
|
function absPath(cwd, path22) {
|
|
34414
|
-
if (!path22) return
|
|
34415
|
-
return path22.startsWith("/") ? path22 :
|
|
36084
|
+
if (!path22) return resolvePath4(cwd);
|
|
36085
|
+
return path22.startsWith("/") ? path22 : resolvePath4(cwd, path22);
|
|
34416
36086
|
}
|
|
34417
36087
|
function pad2(value) {
|
|
34418
36088
|
return value < 10 ? `0${value}` : String(value);
|
|
@@ -34459,10 +36129,10 @@ async function appendToErrorsLog(fs3, errorsLogPath, message) {
|
|
|
34459
36129
|
throw error2;
|
|
34460
36130
|
}
|
|
34461
36131
|
}
|
|
34462
|
-
await fs3.mkdir(
|
|
36132
|
+
await fs3.mkdir(dirname7(errorsLogPath), { recursive: true });
|
|
34463
36133
|
await fs3.writeFile(errorsLogPath, `${previous}${next}`, { encoding: "utf8" });
|
|
34464
36134
|
}
|
|
34465
|
-
function
|
|
36135
|
+
function lockPlanFile4(path22) {
|
|
34466
36136
|
return lockFile(path22, { retries: 20, minTimeout: 25, maxTimeout: 250 });
|
|
34467
36137
|
}
|
|
34468
36138
|
function getCurrentBranch(cwd) {
|
|
@@ -34490,7 +36160,7 @@ function defaultExec(command, options) {
|
|
|
34490
36160
|
return Promise.resolve({ stdout: result, stderr: "" });
|
|
34491
36161
|
}
|
|
34492
36162
|
async function defaultCopyFile(src, dest) {
|
|
34493
|
-
await
|
|
36163
|
+
await fsPromises8.copyFile(src, dest);
|
|
34494
36164
|
}
|
|
34495
36165
|
function formatQualityGates(gates) {
|
|
34496
36166
|
if (gates.length === 0) return "- (none)";
|
|
@@ -34539,6 +36209,41 @@ async function selectStoryFromFile(planPath, options) {
|
|
|
34539
36209
|
await release();
|
|
34540
36210
|
}
|
|
34541
36211
|
}
|
|
36212
|
+
function formatRequirementBlock(req) {
|
|
36213
|
+
const description = req.description?.trim() ? req.description.trim() : "(none)";
|
|
36214
|
+
const scenarios = req.scenarios.length === 0 ? "- (none)" : req.scenarios.map((s) => `- **${s.name}**
|
|
36215
|
+
When: ${s.when}
|
|
36216
|
+
Then: ${s.then}`).join("\n");
|
|
36217
|
+
return [
|
|
36218
|
+
`### ${req.id}: ${req.title}`,
|
|
36219
|
+
`Status: ${req.status}`,
|
|
36220
|
+
"",
|
|
36221
|
+
"Description:",
|
|
36222
|
+
description,
|
|
36223
|
+
"",
|
|
36224
|
+
"Scenarios:",
|
|
36225
|
+
scenarios,
|
|
36226
|
+
""
|
|
36227
|
+
].join("\n");
|
|
36228
|
+
}
|
|
36229
|
+
async function selectRequirementFromFile(planPath, options) {
|
|
36230
|
+
const release = await options.lock(planPath);
|
|
36231
|
+
try {
|
|
36232
|
+
const raw = await options.fs.readFile(planPath, "utf8");
|
|
36233
|
+
const plan = parsePlan(raw);
|
|
36234
|
+
const selected = selectRequirement(plan, { ignoreIds: options.ignoreRequirementIds });
|
|
36235
|
+
if (!selected) return null;
|
|
36236
|
+
selected.status = "verifying";
|
|
36237
|
+
await writePlan(planPath, plan, {
|
|
36238
|
+
fs: options.fs,
|
|
36239
|
+
lock: async () => async () => {
|
|
36240
|
+
}
|
|
36241
|
+
});
|
|
36242
|
+
return { requirement: selected, qualityGates: plan.qualityGates };
|
|
36243
|
+
} finally {
|
|
36244
|
+
await release();
|
|
36245
|
+
}
|
|
36246
|
+
}
|
|
34542
36247
|
function formatOverbakeWarning(args) {
|
|
34543
36248
|
return [
|
|
34544
36249
|
`[OVERBAKE] ${args.storyId}: ${args.storyTitle}`,
|
|
@@ -34563,9 +36268,9 @@ async function defaultPromptOverbake(args) {
|
|
|
34563
36268
|
return value;
|
|
34564
36269
|
}
|
|
34565
36270
|
async function buildLoop(options) {
|
|
34566
|
-
const fs3 = options.deps?.fs ??
|
|
34567
|
-
const lock = options.deps?.lock ??
|
|
34568
|
-
const
|
|
36271
|
+
const fs3 = options.deps?.fs ?? fsPromises8;
|
|
36272
|
+
const lock = options.deps?.lock ?? lockPlanFile4;
|
|
36273
|
+
const spawn7 = options.deps?.spawn ?? defaultStreamingSpawn;
|
|
34569
36274
|
const git = options.deps?.git ?? {
|
|
34570
36275
|
getHead,
|
|
34571
36276
|
getCommitList,
|
|
@@ -34619,7 +36324,7 @@ async function buildLoop(options) {
|
|
|
34619
36324
|
});
|
|
34620
36325
|
worktreeBranch = entry.branch;
|
|
34621
36326
|
const worktreePath = entry.path;
|
|
34622
|
-
const symlinkFn = fs3.symlink ?? ((target, path22) =>
|
|
36327
|
+
const symlinkFn = fs3.symlink ?? ((target, path22) => fsPromises8.symlink(target, path22));
|
|
34623
36328
|
const exec2 = worktreeDeps.exec;
|
|
34624
36329
|
const dirsToLink = [".poe-code-ralph", ".agents/poe-code-ralph"];
|
|
34625
36330
|
for (const dir of dirsToLink) {
|
|
@@ -34630,14 +36335,14 @@ async function buildLoop(options) {
|
|
|
34630
36335
|
}
|
|
34631
36336
|
const src = absPath(originalCwd, dir);
|
|
34632
36337
|
const dest = absPath(worktreePath, dir);
|
|
34633
|
-
await fs3.mkdir(
|
|
36338
|
+
await fs3.mkdir(dirname7(dest), { recursive: true });
|
|
34634
36339
|
try {
|
|
34635
36340
|
await symlinkFn(src, dest);
|
|
34636
36341
|
} catch {
|
|
34637
36342
|
}
|
|
34638
36343
|
}
|
|
34639
36344
|
const destPlanPath = absPath(worktreePath, options.planPath);
|
|
34640
|
-
await fs3.mkdir(
|
|
36345
|
+
await fs3.mkdir(dirname7(destPlanPath), { recursive: true });
|
|
34641
36346
|
await copyFile3(planPath, destPlanPath);
|
|
34642
36347
|
const copiedRaw = await fs3.readFile(destPlanPath, "utf8");
|
|
34643
36348
|
const copiedPlan = parsePlan(copiedRaw);
|
|
@@ -34673,6 +36378,7 @@ async function buildLoop(options) {
|
|
|
34673
36378
|
}
|
|
34674
36379
|
const runsDir = absPath(cwd, ".poe-code-ralph/runs");
|
|
34675
36380
|
const runId = options.deps?.runId ?? createRunId(nowFn());
|
|
36381
|
+
const loopStartTime = nowFn();
|
|
34676
36382
|
const overbaking = new OverbakingDetector({ threshold: options.maxFailures });
|
|
34677
36383
|
const skippedStoryIds = /* @__PURE__ */ new Set();
|
|
34678
36384
|
const storiesDone = [];
|
|
@@ -34688,19 +36394,13 @@ async function buildLoop(options) {
|
|
|
34688
36394
|
ignoreStoryIds: skippedStoryIds
|
|
34689
36395
|
});
|
|
34690
36396
|
if (!selection) {
|
|
34691
|
-
|
|
34692
|
-
runId,
|
|
34693
|
-
iterationsCompleted: iterations.length,
|
|
34694
|
-
storiesDone,
|
|
34695
|
-
iterations,
|
|
34696
|
-
stopReason: "no_actionable_stories"
|
|
34697
|
-
});
|
|
36397
|
+
break;
|
|
34698
36398
|
}
|
|
34699
36399
|
const story = selection.story;
|
|
34700
36400
|
const storyBlock = formatStoryBlock(story);
|
|
34701
|
-
const logPath =
|
|
34702
|
-
const metaPath =
|
|
34703
|
-
const renderedPromptPath =
|
|
36401
|
+
const logPath = resolvePath4(runsDir, `run-${runId}-iter-${i}.log`);
|
|
36402
|
+
const metaPath = resolvePath4(runsDir, `run-${runId}-iter-${i}.md`);
|
|
36403
|
+
const renderedPromptPath = resolvePath4(
|
|
34704
36404
|
absPath(cwd, ".poe-code-ralph/.tmp"),
|
|
34705
36405
|
`prompt-build-${runId}-iter-${i}.md`
|
|
34706
36406
|
);
|
|
@@ -34725,7 +36425,7 @@ async function buildLoop(options) {
|
|
|
34725
36425
|
STORY_BLOCK: storyBlock,
|
|
34726
36426
|
QUALITY_GATES: formatQualityGates(selection.qualityGates)
|
|
34727
36427
|
});
|
|
34728
|
-
await fs3.mkdir(
|
|
36428
|
+
await fs3.mkdir(dirname7(renderedPromptPath), { recursive: true });
|
|
34729
36429
|
await fs3.writeFile(renderedPromptPath, prompt, { encoding: "utf8" });
|
|
34730
36430
|
stdout.write(`[${i}/${options.maxIterations}] ${story.title}
|
|
34731
36431
|
`);
|
|
@@ -34734,7 +36434,7 @@ async function buildLoop(options) {
|
|
|
34734
36434
|
let stderrForErrorsLog;
|
|
34735
36435
|
let overbakeAction = null;
|
|
34736
36436
|
try {
|
|
34737
|
-
const result = await
|
|
36437
|
+
const result = await spawn7(options.agent, {
|
|
34738
36438
|
prompt,
|
|
34739
36439
|
cwd,
|
|
34740
36440
|
model: options.model,
|
|
@@ -34765,7 +36465,7 @@ ${agentStderr}` : ""
|
|
|
34765
36465
|
stderrForErrorsLog = combinedOutput;
|
|
34766
36466
|
status = "failure";
|
|
34767
36467
|
}
|
|
34768
|
-
await fs3.mkdir(
|
|
36468
|
+
await fs3.mkdir(dirname7(logPath), { recursive: true });
|
|
34769
36469
|
await fs3.writeFile(logPath, combinedOutput, { encoding: "utf8" });
|
|
34770
36470
|
if (status === "failure" && stderrForErrorsLog.trim().length > 0) {
|
|
34771
36471
|
await appendToErrorsLog(fs3, errorsLogPath, stderrForErrorsLog);
|
|
@@ -34866,16 +36566,239 @@ ${agentStderr}` : ""
|
|
|
34866
36566
|
});
|
|
34867
36567
|
}
|
|
34868
36568
|
}
|
|
36569
|
+
if (iterations.length >= options.maxIterations) {
|
|
36570
|
+
return finalizeWorktreeResult({
|
|
36571
|
+
runId,
|
|
36572
|
+
iterationsCompleted: iterations.length,
|
|
36573
|
+
storiesDone,
|
|
36574
|
+
iterations,
|
|
36575
|
+
stopReason: "max_iterations"
|
|
36576
|
+
});
|
|
36577
|
+
}
|
|
36578
|
+
const verifyTemplate = await resolveTemplate("PROMPT_verify.md", {
|
|
36579
|
+
fs: fs3,
|
|
36580
|
+
cwd,
|
|
36581
|
+
bundledDir: absPath(cwd, ".agents/poe-code-ralph")
|
|
36582
|
+
});
|
|
36583
|
+
if (!verifyTemplate) {
|
|
36584
|
+
return finalizeWorktreeResult({
|
|
36585
|
+
runId,
|
|
36586
|
+
iterationsCompleted: iterations.length,
|
|
36587
|
+
storiesDone,
|
|
36588
|
+
iterations,
|
|
36589
|
+
stopReason: "no_actionable_stories"
|
|
36590
|
+
});
|
|
36591
|
+
}
|
|
36592
|
+
const currentPlan = parsePlan(await fs3.readFile(planPath, "utf8"));
|
|
36593
|
+
const hasPendingRequirements = currentPlan.requirements.some((r) => r.status !== "passed");
|
|
36594
|
+
if (!hasPendingRequirements) {
|
|
36595
|
+
return finalizeWorktreeResult({
|
|
36596
|
+
runId,
|
|
36597
|
+
iterationsCompleted: iterations.length,
|
|
36598
|
+
storiesDone,
|
|
36599
|
+
iterations,
|
|
36600
|
+
stopReason: "no_actionable_stories"
|
|
36601
|
+
});
|
|
36602
|
+
}
|
|
36603
|
+
const skippedRequirementIds = /* @__PURE__ */ new Set();
|
|
36604
|
+
for (let vi = iterations.length + 1; vi <= options.maxIterations; vi++) {
|
|
36605
|
+
const iterationStart = nowFn();
|
|
36606
|
+
const headBefore = git.getHead(cwd);
|
|
36607
|
+
const reqSelection = await selectRequirementFromFile(planPath, {
|
|
36608
|
+
fs: fs3,
|
|
36609
|
+
lock,
|
|
36610
|
+
now: iterationStart,
|
|
36611
|
+
ignoreRequirementIds: skippedRequirementIds
|
|
36612
|
+
});
|
|
36613
|
+
if (!reqSelection) {
|
|
36614
|
+
return finalizeWorktreeResult({
|
|
36615
|
+
runId,
|
|
36616
|
+
iterationsCompleted: iterations.length,
|
|
36617
|
+
storiesDone,
|
|
36618
|
+
iterations,
|
|
36619
|
+
stopReason: "all_verified"
|
|
36620
|
+
});
|
|
36621
|
+
}
|
|
36622
|
+
const req = reqSelection.requirement;
|
|
36623
|
+
const reqBlock = formatRequirementBlock(req);
|
|
36624
|
+
const logPath = resolvePath4(runsDir, `run-${runId}-iter-${vi}.log`);
|
|
36625
|
+
const metaPath = resolvePath4(runsDir, `run-${runId}-iter-${vi}.md`);
|
|
36626
|
+
const renderedPromptPath = resolvePath4(
|
|
36627
|
+
absPath(cwd, ".poe-code-ralph/.tmp"),
|
|
36628
|
+
`prompt-verify-${runId}-iter-${vi}.md`
|
|
36629
|
+
);
|
|
36630
|
+
const prompt = renderPrompt(verifyTemplate, {
|
|
36631
|
+
PLAN_PATH: planPath,
|
|
36632
|
+
PROGRESS_PATH: progressPath,
|
|
36633
|
+
REPO_ROOT: cwd,
|
|
36634
|
+
GUARDRAILS_PATH: guardrailsPath,
|
|
36635
|
+
ERRORS_LOG_PATH: errorsLogPath,
|
|
36636
|
+
ACTIVITY_LOG_PATH: activityLogPath,
|
|
36637
|
+
GUARDRAILS_REF: guardrailsRef,
|
|
36638
|
+
CONTEXT_REF: contextRef,
|
|
36639
|
+
ACTIVITY_CMD: activityCmd,
|
|
36640
|
+
COMMIT: options.commit,
|
|
36641
|
+
RUN_ID: runId,
|
|
36642
|
+
ITERATION: vi,
|
|
36643
|
+
RUN_LOG_PATH: logPath,
|
|
36644
|
+
RUN_META_PATH: metaPath,
|
|
36645
|
+
REQUIREMENT_ID: req.id,
|
|
36646
|
+
REQUIREMENT_TITLE: req.title,
|
|
36647
|
+
REQUIREMENT_BLOCK: reqBlock,
|
|
36648
|
+
QUALITY_GATES: formatQualityGates(reqSelection.qualityGates)
|
|
36649
|
+
});
|
|
36650
|
+
await fs3.mkdir(dirname7(renderedPromptPath), { recursive: true });
|
|
36651
|
+
await fs3.writeFile(renderedPromptPath, prompt, { encoding: "utf8" });
|
|
36652
|
+
stdout.write(`[${vi}/${options.maxIterations}] Verify: ${req.title}
|
|
36653
|
+
`);
|
|
36654
|
+
let status;
|
|
36655
|
+
let combinedOutput;
|
|
36656
|
+
let stderrForErrorsLog;
|
|
36657
|
+
try {
|
|
36658
|
+
const result = await spawn7(options.agent, {
|
|
36659
|
+
prompt,
|
|
36660
|
+
cwd,
|
|
36661
|
+
model: options.model,
|
|
36662
|
+
mode: "yolo",
|
|
36663
|
+
useStdin: true
|
|
36664
|
+
});
|
|
36665
|
+
const agentStdout = result.stdout ?? "";
|
|
36666
|
+
const agentStderr = result.stderr ?? "";
|
|
36667
|
+
stderrForErrorsLog = agentStderr;
|
|
36668
|
+
combinedOutput = [
|
|
36669
|
+
agentStdout ? `# stdout
|
|
36670
|
+
${agentStdout}` : "",
|
|
36671
|
+
agentStderr ? `# stderr
|
|
36672
|
+
${agentStderr}` : ""
|
|
36673
|
+
].filter(Boolean).join("\n");
|
|
36674
|
+
if (result.exitCode !== 0) {
|
|
36675
|
+
status = "failure";
|
|
36676
|
+
} else if (detectCompletion(agentStdout)) {
|
|
36677
|
+
status = "success";
|
|
36678
|
+
} else {
|
|
36679
|
+
status = "incomplete";
|
|
36680
|
+
}
|
|
36681
|
+
} catch (error2) {
|
|
36682
|
+
const detail = error2 instanceof Error ? error2.message : `Unknown error: ${String(error2)}`;
|
|
36683
|
+
combinedOutput = `Agent execution error: ${detail}`;
|
|
36684
|
+
stderrForErrorsLog = combinedOutput;
|
|
36685
|
+
status = "failure";
|
|
36686
|
+
}
|
|
36687
|
+
await fs3.mkdir(dirname7(logPath), { recursive: true });
|
|
36688
|
+
await fs3.writeFile(logPath, combinedOutput, { encoding: "utf8" });
|
|
36689
|
+
if (status === "failure" && stderrForErrorsLog.trim().length > 0) {
|
|
36690
|
+
await appendToErrorsLog(fs3, errorsLogPath, stderrForErrorsLog);
|
|
36691
|
+
}
|
|
36692
|
+
const overbakeEvent = overbaking.record(req.id, status);
|
|
36693
|
+
let overbakeAction = null;
|
|
36694
|
+
if (overbakeEvent.shouldWarn) {
|
|
36695
|
+
const warning = formatOverbakeWarning({
|
|
36696
|
+
storyId: req.id,
|
|
36697
|
+
storyTitle: req.title,
|
|
36698
|
+
consecutiveFailures: overbakeEvent.consecutiveFailures,
|
|
36699
|
+
threshold: overbakeEvent.threshold
|
|
36700
|
+
});
|
|
36701
|
+
stderr.write(warning);
|
|
36702
|
+
await appendToErrorsLog(fs3, errorsLogPath, warning);
|
|
36703
|
+
}
|
|
36704
|
+
if (overbakeEvent.overbaked) {
|
|
36705
|
+
if (options.pauseOnOverbake) {
|
|
36706
|
+
overbakeAction = await promptOverbake({
|
|
36707
|
+
storyId: req.id,
|
|
36708
|
+
storyTitle: req.title,
|
|
36709
|
+
consecutiveFailures: overbakeEvent.consecutiveFailures,
|
|
36710
|
+
threshold: overbakeEvent.threshold
|
|
36711
|
+
});
|
|
36712
|
+
} else {
|
|
36713
|
+
overbakeAction = "skip";
|
|
36714
|
+
}
|
|
36715
|
+
if (overbakeAction === "skip") {
|
|
36716
|
+
skippedRequirementIds.add(req.id);
|
|
36717
|
+
}
|
|
36718
|
+
}
|
|
36719
|
+
const iterationEnd = nowFn();
|
|
36720
|
+
const durationSeconds = Math.max(
|
|
36721
|
+
0,
|
|
36722
|
+
Math.round((iterationEnd.getTime() - iterationStart.getTime()) / 1e3)
|
|
36723
|
+
);
|
|
36724
|
+
if (status === "success") {
|
|
36725
|
+
await updateRequirementStatus(planPath, req.id, "passed", {
|
|
36726
|
+
fs: fs3,
|
|
36727
|
+
lock,
|
|
36728
|
+
now: iterationEnd
|
|
36729
|
+
});
|
|
36730
|
+
} else {
|
|
36731
|
+
await updateRequirementStatus(planPath, req.id, "pending", {
|
|
36732
|
+
fs: fs3,
|
|
36733
|
+
lock,
|
|
36734
|
+
now: iterationEnd
|
|
36735
|
+
});
|
|
36736
|
+
}
|
|
36737
|
+
const headAfter = git.getHead(cwd);
|
|
36738
|
+
const dirtyFiles = git.getDirtyFiles(cwd);
|
|
36739
|
+
const commits = headBefore && headAfter && headBefore !== headAfter ? git.getCommitList(cwd, headBefore, headAfter) : [];
|
|
36740
|
+
const changedFiles = headBefore && headAfter && headBefore !== headAfter ? git.getChangedFiles(cwd, headBefore, headAfter) : [];
|
|
36741
|
+
await writeRunMeta(
|
|
36742
|
+
metaPath,
|
|
36743
|
+
{
|
|
36744
|
+
runId,
|
|
36745
|
+
iteration: vi,
|
|
36746
|
+
mode: "verify",
|
|
36747
|
+
storyId: req.id,
|
|
36748
|
+
storyTitle: req.title,
|
|
36749
|
+
started: formatTimestamp2(iterationStart),
|
|
36750
|
+
ended: formatTimestamp2(iterationEnd),
|
|
36751
|
+
duration: `${durationSeconds}s`,
|
|
36752
|
+
status,
|
|
36753
|
+
logPath,
|
|
36754
|
+
overbaking: {
|
|
36755
|
+
maxFailures: overbakeEvent.threshold,
|
|
36756
|
+
consecutiveFailures: overbakeEvent.consecutiveFailures,
|
|
36757
|
+
triggered: overbakeEvent.overbaked,
|
|
36758
|
+
action: overbakeAction ?? void 0
|
|
36759
|
+
},
|
|
36760
|
+
git: {
|
|
36761
|
+
headBefore,
|
|
36762
|
+
headAfter,
|
|
36763
|
+
commits,
|
|
36764
|
+
changedFiles,
|
|
36765
|
+
dirtyFiles
|
|
36766
|
+
}
|
|
36767
|
+
},
|
|
36768
|
+
{ fs: fs3 }
|
|
36769
|
+
);
|
|
36770
|
+
iterations.push({
|
|
36771
|
+
iteration: vi,
|
|
36772
|
+
storyId: req.id,
|
|
36773
|
+
storyTitle: req.title,
|
|
36774
|
+
status,
|
|
36775
|
+
logPath,
|
|
36776
|
+
metaPath
|
|
36777
|
+
});
|
|
36778
|
+
if (overbakeAction === "abort") {
|
|
36779
|
+
return finalizeWorktreeResult({
|
|
36780
|
+
runId,
|
|
36781
|
+
iterationsCompleted: iterations.length,
|
|
36782
|
+
storiesDone,
|
|
36783
|
+
iterations,
|
|
36784
|
+
stopReason: "overbake_abort"
|
|
36785
|
+
});
|
|
36786
|
+
}
|
|
36787
|
+
}
|
|
36788
|
+
const finalPlan = parsePlan(await fs3.readFile(planPath, "utf8"));
|
|
36789
|
+
const allPassed = finalPlan.requirements.every((r) => r.status === "passed");
|
|
34869
36790
|
return finalizeWorktreeResult({
|
|
34870
36791
|
runId,
|
|
34871
36792
|
iterationsCompleted: iterations.length,
|
|
34872
36793
|
storiesDone,
|
|
34873
36794
|
iterations,
|
|
34874
|
-
stopReason: "max_iterations"
|
|
36795
|
+
stopReason: allPassed ? "all_verified" : "max_iterations"
|
|
34875
36796
|
});
|
|
34876
36797
|
async function finalizeWorktreeResult(result) {
|
|
36798
|
+
const totalDurationMs = Math.max(0, nowFn().getTime() - loopStartTime.getTime());
|
|
36799
|
+
const fullResult = { ...result, totalDurationMs };
|
|
34877
36800
|
if (!options.worktree?.enabled || !worktreeName) {
|
|
34878
|
-
return
|
|
36801
|
+
return fullResult;
|
|
34879
36802
|
}
|
|
34880
36803
|
const worktreeDeps = options.deps?.worktree ?? {
|
|
34881
36804
|
fs: {
|
|
@@ -34889,7 +36812,7 @@ ${agentStderr}` : ""
|
|
|
34889
36812
|
await updateWorktreeStatus(registryFile, worktreeName, worktreeStatus, {
|
|
34890
36813
|
fs: worktreeDeps.fs
|
|
34891
36814
|
});
|
|
34892
|
-
|
|
36815
|
+
fullResult.worktreeBranch = worktreeBranch;
|
|
34893
36816
|
if (worktreeBranch) {
|
|
34894
36817
|
const mergeHint = [
|
|
34895
36818
|
"",
|
|
@@ -34900,7 +36823,7 @@ ${agentStderr}` : ""
|
|
|
34900
36823
|
].join("\n");
|
|
34901
36824
|
stdout.write(mergeHint);
|
|
34902
36825
|
}
|
|
34903
|
-
return
|
|
36826
|
+
return fullResult;
|
|
34904
36827
|
}
|
|
34905
36828
|
}
|
|
34906
36829
|
var init_loop = __esm({
|
|
@@ -34910,14 +36833,17 @@ var init_loop = __esm({
|
|
|
34910
36833
|
init_src5();
|
|
34911
36834
|
init_src4();
|
|
34912
36835
|
init_src2();
|
|
34913
|
-
|
|
36836
|
+
init_src12();
|
|
34914
36837
|
init_detector();
|
|
34915
36838
|
init_utils2();
|
|
34916
36839
|
init_parser();
|
|
34917
36840
|
init_writer();
|
|
34918
36841
|
init_renderer2();
|
|
36842
|
+
init_resolver();
|
|
34919
36843
|
init_selector();
|
|
34920
36844
|
init_updater();
|
|
36845
|
+
init_selector2();
|
|
36846
|
+
init_updater2();
|
|
34921
36847
|
init_metadata();
|
|
34922
36848
|
init_overbaking();
|
|
34923
36849
|
}
|
|
@@ -34925,7 +36851,7 @@ var init_loop = __esm({
|
|
|
34925
36851
|
|
|
34926
36852
|
// packages/ralph/src/plan/resolver.ts
|
|
34927
36853
|
import path17 from "node:path";
|
|
34928
|
-
import * as
|
|
36854
|
+
import * as fsPromises9 from "node:fs/promises";
|
|
34929
36855
|
function isPlanCandidateFile(fileName) {
|
|
34930
36856
|
const lower = fileName.toLowerCase();
|
|
34931
36857
|
if (!lower.startsWith("plan")) {
|
|
@@ -34967,9 +36893,9 @@ async function listPlanCandidates(fs3, cwd) {
|
|
|
34967
36893
|
}
|
|
34968
36894
|
async function resolvePlanPath(options) {
|
|
34969
36895
|
const fs3 = options.fs ?? {
|
|
34970
|
-
readdir:
|
|
34971
|
-
stat:
|
|
34972
|
-
readFile:
|
|
36896
|
+
readdir: fsPromises9.readdir,
|
|
36897
|
+
stat: fsPromises9.stat,
|
|
36898
|
+
readFile: fsPromises9.readFile
|
|
34973
36899
|
};
|
|
34974
36900
|
const cwd = options.cwd;
|
|
34975
36901
|
const provided = options.plan?.trim();
|
|
@@ -35020,7 +36946,7 @@ async function resolvePlanPath(options) {
|
|
|
35020
36946
|
}
|
|
35021
36947
|
return selection;
|
|
35022
36948
|
}
|
|
35023
|
-
var
|
|
36949
|
+
var init_resolver2 = __esm({
|
|
35024
36950
|
"packages/ralph/src/plan/resolver.ts"() {
|
|
35025
36951
|
"use strict";
|
|
35026
36952
|
init_src4();
|
|
@@ -35031,7 +36957,7 @@ var init_resolver = __esm({
|
|
|
35031
36957
|
|
|
35032
36958
|
// packages/ralph/src/plan/generator.ts
|
|
35033
36959
|
import path18 from "node:path";
|
|
35034
|
-
import * as
|
|
36960
|
+
import * as fsPromises10 from "node:fs/promises";
|
|
35035
36961
|
var PLAN_PROMPT_TEMPLATE;
|
|
35036
36962
|
var init_generator = __esm({
|
|
35037
36963
|
"packages/ralph/src/plan/generator.ts"() {
|
|
@@ -35085,8 +37011,8 @@ var init_generator = __esm({
|
|
|
35085
37011
|
});
|
|
35086
37012
|
|
|
35087
37013
|
// packages/ralph/src/log/activity.ts
|
|
35088
|
-
import { dirname as
|
|
35089
|
-
import * as
|
|
37014
|
+
import { dirname as dirname8 } from "node:path";
|
|
37015
|
+
import * as fsPromises11 from "node:fs/promises";
|
|
35090
37016
|
function pad22(value) {
|
|
35091
37017
|
return value < 10 ? `0${value}` : String(value);
|
|
35092
37018
|
}
|
|
@@ -35111,8 +37037,8 @@ function validateLogPath(path22) {
|
|
|
35111
37037
|
}
|
|
35112
37038
|
async function logActivity(path22, message, options = {}) {
|
|
35113
37039
|
validateLogPath(path22);
|
|
35114
|
-
const fs3 = options.fs ??
|
|
35115
|
-
const parent =
|
|
37040
|
+
const fs3 = options.fs ?? fsPromises11;
|
|
37041
|
+
const parent = dirname8(path22);
|
|
35116
37042
|
if (parent && parent !== ".") {
|
|
35117
37043
|
await fs3.mkdir(parent, { recursive: true });
|
|
35118
37044
|
}
|
|
@@ -35133,7 +37059,7 @@ var init_activity = __esm({
|
|
|
35133
37059
|
|
|
35134
37060
|
// packages/ralph/src/config/loader.ts
|
|
35135
37061
|
import path19 from "node:path";
|
|
35136
|
-
import * as
|
|
37062
|
+
import * as fsPromises12 from "node:fs/promises";
|
|
35137
37063
|
import YAML from "yaml";
|
|
35138
37064
|
function isPlainObject2(value) {
|
|
35139
37065
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -35237,7 +37163,7 @@ function mergeConfigs(base, override) {
|
|
|
35237
37163
|
return result;
|
|
35238
37164
|
}
|
|
35239
37165
|
async function loadConfig(cwd, deps) {
|
|
35240
|
-
const fs3 = deps?.fs ??
|
|
37166
|
+
const fs3 = deps?.fs ?? fsPromises12;
|
|
35241
37167
|
const sources = [];
|
|
35242
37168
|
let merged = {};
|
|
35243
37169
|
if (deps?.homeDir) {
|
|
@@ -35270,12 +37196,12 @@ async function ralphBuild(options) {
|
|
|
35270
37196
|
cwd: options.cwd ?? process.cwd()
|
|
35271
37197
|
});
|
|
35272
37198
|
}
|
|
35273
|
-
var
|
|
37199
|
+
var init_src13 = __esm({
|
|
35274
37200
|
"packages/ralph/src/index.ts"() {
|
|
35275
37201
|
"use strict";
|
|
35276
37202
|
init_loop();
|
|
35277
37203
|
init_parser();
|
|
35278
|
-
|
|
37204
|
+
init_resolver2();
|
|
35279
37205
|
init_generator();
|
|
35280
37206
|
init_activity();
|
|
35281
37207
|
init_loader();
|
|
@@ -35359,7 +37285,7 @@ var init_ralph_worktree = __esm({
|
|
|
35359
37285
|
"src/cli/commands/ralph-worktree.ts"() {
|
|
35360
37286
|
"use strict";
|
|
35361
37287
|
init_src4();
|
|
35362
|
-
|
|
37288
|
+
init_src12();
|
|
35363
37289
|
init_src5();
|
|
35364
37290
|
init_src2();
|
|
35365
37291
|
init_errors();
|
|
@@ -35889,7 +37815,6 @@ function registerRalphCommand(program, container) {
|
|
|
35889
37815
|
resources.logger.success("Dry run complete. No agents spawned.");
|
|
35890
37816
|
return;
|
|
35891
37817
|
}
|
|
35892
|
-
const buildStart = Date.now();
|
|
35893
37818
|
const buildResult = await ralphBuild({
|
|
35894
37819
|
planPath,
|
|
35895
37820
|
progressPath: config2.progressPath,
|
|
@@ -35907,11 +37832,10 @@ function registerRalphCommand(program, container) {
|
|
|
35907
37832
|
worktree,
|
|
35908
37833
|
deps: { stdout: process.stdout }
|
|
35909
37834
|
});
|
|
35910
|
-
const duration3 = formatDuration(Date.now() - buildStart);
|
|
35911
37835
|
resources.logger.resolved("Run summary", [
|
|
35912
37836
|
`Iterations: ${buildResult.iterationsCompleted}/${maxIterations}`,
|
|
35913
37837
|
`Stories done: ${buildResult.storiesDone.length}`,
|
|
35914
|
-
`Duration: ${
|
|
37838
|
+
`Duration: ${formatDuration(buildResult.totalDurationMs)}`
|
|
35915
37839
|
].join("\n "));
|
|
35916
37840
|
resources.logger.success("Ralph run finished.");
|
|
35917
37841
|
} finally {
|
|
@@ -35930,8 +37854,8 @@ var init_ralph = __esm({
|
|
|
35930
37854
|
"src/cli/commands/ralph.ts"() {
|
|
35931
37855
|
"use strict";
|
|
35932
37856
|
init_src4();
|
|
35933
|
-
|
|
35934
|
-
|
|
37857
|
+
init_src13();
|
|
37858
|
+
init_src11();
|
|
35935
37859
|
init_src2();
|
|
35936
37860
|
init_errors();
|
|
35937
37861
|
init_shared();
|
|
@@ -36447,7 +38371,7 @@ var init_package = __esm({
|
|
|
36447
38371
|
"package.json"() {
|
|
36448
38372
|
package_default = {
|
|
36449
38373
|
name: "poe-code",
|
|
36450
|
-
version: "3.0.
|
|
38374
|
+
version: "3.0.75",
|
|
36451
38375
|
description: "CLI tool to configure Poe API for developer workflows.",
|
|
36452
38376
|
type: "module",
|
|
36453
38377
|
main: "./dist/index.js",
|
|
@@ -36961,12 +38885,12 @@ import * as nodeFsSync3 from "node:fs";
|
|
|
36961
38885
|
import { realpathSync } from "node:fs";
|
|
36962
38886
|
import { homedir as homedir5 } from "node:os";
|
|
36963
38887
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
36964
|
-
import { join as
|
|
38888
|
+
import { join as join4 } from "node:path";
|
|
36965
38889
|
import chalk13 from "chalk";
|
|
36966
38890
|
function createCliMain(programFactory) {
|
|
36967
38891
|
return async function runCli() {
|
|
36968
38892
|
const homeDir = homedir5();
|
|
36969
|
-
const logDir =
|
|
38893
|
+
const logDir = join4(homeDir, ".poe-code", "logs");
|
|
36970
38894
|
const promptRunner = createPromptRunner();
|
|
36971
38895
|
const shouldLogToStderr = process.env.POE_CODE_STDERR_LOGS === "1" || process.env.POE_CODE_STDERR_LOGS === "true";
|
|
36972
38896
|
const errorLogger = new ErrorLogger({
|
|
@@ -37001,7 +38925,7 @@ function createCliMain(programFactory) {
|
|
|
37001
38925
|
} else {
|
|
37002
38926
|
log2.error(`Error: ${error2.message}`);
|
|
37003
38927
|
log2.message(
|
|
37004
|
-
`See logs at ${
|
|
38928
|
+
`See logs at ${join4(logDir, "errors.log")} for more details.`,
|
|
37005
38929
|
{ symbol: chalk13.magenta("\u25CF") }
|
|
37006
38930
|
);
|
|
37007
38931
|
}
|
|
@@ -37170,6 +39094,6 @@ export {
|
|
|
37170
39094
|
getPoeApiKey,
|
|
37171
39095
|
isCliInvocation2 as isCliInvocation,
|
|
37172
39096
|
main,
|
|
37173
|
-
|
|
39097
|
+
spawn5 as spawn
|
|
37174
39098
|
};
|
|
37175
39099
|
//# sourceMappingURL=index.js.map
|