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/index.js CHANGED
@@ -6471,13 +6471,13 @@ var init_acp_transport = __esm({
6471
6471
  env,
6472
6472
  requestTimeoutMs,
6473
6473
  firstRequestId,
6474
- spawn: spawn6 = spawnChildProcess4
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 = spawn6(command, [...args], {
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 readFile2(systemPromptUrl, "utf8");
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
- systemPromptUrl = new URL("./SYSTEM_PROMPT.md", import.meta.url);
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 tools = toolExecutor.getAvailableTools();
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
- await disposableToolExecutor.dispose();
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 init_src7 = __esm({
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(() => (init_src7(), src_exports));
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 spawn4(service, promptOrOptions, maybeOptions) {
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
- spawn4.pretty = async function pretty(service, promptOrOptions, maybeOptions) {
8767
- const { events, result } = spawn4(service, promptOrOptions, maybeOptions);
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(() => (init_src7(), src_exports));
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(adapter.label, canonicalService, mcpServers);
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 } = spawn4(canonicalService, {
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 (!isObjectRecord3(parsed)) {
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 (!isObjectRecord3(value)) {
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 (!isObjectRecord3(value.env)) {
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 isObjectRecord3(value) {
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 } = spawn4(options.agent, {
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 spawn5 } from "node:child_process";
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 = spawn5(details.agentBinary, args, {
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 init_src8 = __esm({
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
- init_src8();
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 init_src9 = __esm({
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
- init_src9();
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 readFile3 } from "node:fs/promises";
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 readFile3(poeGenerateTemplateUrl, "utf8");
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 init_src10 = __esm({
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
- init_src10();
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 init_src11 = __esm({
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/run/metadata.ts
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 ?? fsPromises6;
34261
- await fs3.mkdir(dirname5(path22), { recursive: true });
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 dirname6, resolve as resolvePath3 } from "node:path";
34386
- import * as fsPromises7 from "node:fs/promises";
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 resolvePath3(cwd);
34415
- return path22.startsWith("/") ? path22 : resolvePath3(cwd, 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(dirname6(errorsLogPath), { recursive: true });
36132
+ await fs3.mkdir(dirname7(errorsLogPath), { recursive: true });
34463
36133
  await fs3.writeFile(errorsLogPath, `${previous}${next}`, { encoding: "utf8" });
34464
36134
  }
34465
- function lockPlanFile3(path22) {
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 fsPromises7.copyFile(src, dest);
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 ?? fsPromises7;
34567
- const lock = options.deps?.lock ?? lockPlanFile3;
34568
- const spawn6 = options.deps?.spawn ?? defaultStreamingSpawn;
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) => fsPromises7.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(dirname6(dest), { recursive: true });
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(dirname6(destPlanPath), { recursive: true });
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
- return finalizeWorktreeResult({
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 = resolvePath3(runsDir, `run-${runId}-iter-${i}.log`);
34702
- const metaPath = resolvePath3(runsDir, `run-${runId}-iter-${i}.md`);
34703
- const renderedPromptPath = resolvePath3(
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(dirname6(renderedPromptPath), { recursive: true });
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 spawn6(options.agent, {
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(dirname6(logPath), { recursive: true });
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 result;
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
- result.worktreeBranch = worktreeBranch;
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 result;
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
- init_src11();
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 fsPromises8 from "node:fs/promises";
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: fsPromises8.readdir,
34971
- stat: fsPromises8.stat,
34972
- readFile: fsPromises8.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 init_resolver = __esm({
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 fsPromises9 from "node:fs/promises";
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 dirname7 } from "node:path";
35089
- import * as fsPromises10 from "node:fs/promises";
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 ?? fsPromises10;
35115
- const parent = dirname7(path22);
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 fsPromises11 from "node:fs/promises";
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 ?? fsPromises11;
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 init_src12 = __esm({
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
- init_resolver();
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
- init_src11();
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: ${duration3}`
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
- init_src12();
35934
- init_src10();
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.73",
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 join3 } from "node:path";
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 = join3(homeDir, ".poe-code", "logs");
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 ${join3(logDir, "errors.log")} for more details.`,
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
- spawn4 as spawn
39097
+ spawn5 as spawn
37174
39098
  };
37175
39099
  //# sourceMappingURL=index.js.map