@perkos/perkos-a2a 0.8.31 → 0.8.33

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
@@ -17431,7 +17431,7 @@ var require_finalhandler = __commonJS({
17431
17431
  module.exports = finalhandler;
17432
17432
  function finalhandler(req, res, options) {
17433
17433
  var opts = options || {};
17434
- var env2 = opts.env || process.env.NODE_ENV || "development";
17434
+ var env = opts.env || process.env.NODE_ENV || "development";
17435
17435
  var onerror = opts.onerror;
17436
17436
  return function(err) {
17437
17437
  var headers;
@@ -17448,7 +17448,7 @@ var require_finalhandler = __commonJS({
17448
17448
  } else {
17449
17449
  headers = getErrorHeaders(err);
17450
17450
  }
17451
- msg = getErrorMessage(err, status, env2);
17451
+ msg = getErrorMessage(err, status, env);
17452
17452
  } else {
17453
17453
  status = 404;
17454
17454
  msg = "Cannot " + req.method + " " + encodeUrl(getResourceName(req));
@@ -17479,9 +17479,9 @@ var require_finalhandler = __commonJS({
17479
17479
  }
17480
17480
  return headers;
17481
17481
  }
17482
- function getErrorMessage(err, status, env2) {
17482
+ function getErrorMessage(err, status, env) {
17483
17483
  var msg;
17484
- if (env2 !== "production") {
17484
+ if (env !== "production") {
17485
17485
  msg = err.stack;
17486
17486
  if (!msg && typeof err.toString === "function") {
17487
17487
  msg = err.toString();
@@ -20614,10 +20614,10 @@ var require_application = __commonJS({
20614
20614
  this.defaultConfiguration();
20615
20615
  };
20616
20616
  app.defaultConfiguration = function defaultConfiguration() {
20617
- var env2 = process.env.NODE_ENV || "development";
20617
+ var env = process.env.NODE_ENV || "development";
20618
20618
  this.enable("x-powered-by");
20619
20619
  this.set("etag", "weak");
20620
- this.set("env", env2);
20620
+ this.set("env", env);
20621
20621
  this.set("query parser", "extended");
20622
20622
  this.set("subdomain offset", 2);
20623
20623
  this.set("trust proxy", false);
@@ -20625,7 +20625,7 @@ var require_application = __commonJS({
20625
20625
  configurable: true,
20626
20626
  value: true
20627
20627
  });
20628
- debug("booting in %s mode", env2);
20628
+ debug("booting in %s mode", env);
20629
20629
  this.on("mount", function onmount(parent) {
20630
20630
  if (this.settings[trustProxyDefaultSymbol] === true && typeof parent.settings["trust proxy fn"] === "function") {
20631
20631
  delete this.settings["trust proxy"];
@@ -20642,7 +20642,7 @@ var require_application = __commonJS({
20642
20642
  this.set("view", View);
20643
20643
  this.set("views", resolve("views"));
20644
20644
  this.set("jsonp callback name", "callback");
20645
- if (env2 === "production") {
20645
+ if (env === "production") {
20646
20646
  this.enable("view cache");
20647
20647
  }
20648
20648
  Object.defineProperty(this, "router", {
@@ -26267,7 +26267,7 @@ var RelayClient = class {
26267
26267
  from: this.options.agentName,
26268
26268
  payload,
26269
26269
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
26270
- }, "task_response", Number(process.env.A2A_RELAY_RESPONSE_WAIT_MS || 6e4));
26270
+ }, "task_response", 6e4);
26271
26271
  }
26272
26272
  /** Discover agents connected to the relay */
26273
26273
  async discover() {
@@ -26690,10 +26690,6 @@ var RelayHub = class {
26690
26690
 
26691
26691
  // src/runtime-reply.ts
26692
26692
  import { randomUUID as randomUUID3 } from "crypto";
26693
- function env(name) {
26694
- const value = process.env[name];
26695
- return value && value.trim() ? value.trim() : void 0;
26696
- }
26697
26693
  function stripTaskMarker(text, marker) {
26698
26694
  const trimmed = text.trim();
26699
26695
  if (!trimmed.includes(marker)) return trimmed;
@@ -26715,8 +26711,12 @@ function withRequestedMarker(reply, text) {
26715
26711
  if (!marker || reply.trim().endsWith(marker)) return reply;
26716
26712
  return `${reply.trim()} ${marker}`;
26717
26713
  }
26714
+ function runtimeOption(config, key) {
26715
+ const value = config.runtime?.[key];
26716
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
26717
+ }
26718
26718
  function agentIdFor(config) {
26719
- return env("A2A_AGENT_ID") || env("HERMES_AGENT_ID") || config.agentName || "perkos-a2a-agent";
26719
+ return runtimeOption(config, "agentId") || config.agentName || "perkos-a2a-agent";
26720
26720
  }
26721
26721
  function llmSystemPrompt(config) {
26722
26722
  const agentName = config.agentName || config.runtime?.kind || "PerkOS A2A agent";
@@ -26729,7 +26729,7 @@ function llmSystemPrompt(config) {
26729
26729
  }
26730
26730
  async function generateRuntimeReply(config, text, marker) {
26731
26731
  const runtimeKind = config.runtime?.kind || "openclaw";
26732
- const apiKey = env("PERKOS_LLM_API_KEY") || env("OPENAI_API_KEY") || env("OLLAMA_API_KEY");
26732
+ const apiKey = runtimeOption(config, "llmApiKey");
26733
26733
  if (!apiKey) {
26734
26734
  const agentName = config.agentName || config.runtime?.kind || "PerkOS A2A agent";
26735
26735
  const lower = text.toLowerCase();
@@ -26754,8 +26754,8 @@ async function generateRuntimeReply(config, text, marker) {
26754
26754
  `Do not include ${marker}; the A2A bridge will attach the marker/task result.`
26755
26755
  ].join("\n");
26756
26756
  if (runtimeKind === "hermes") {
26757
- const base2 = (env("OPENAI_BASE_URL") || "https://api.llm.perkos.xyz/v1").replace(/\/+$/, "");
26758
- const model2 = env("HERMES_INFERENCE_MODEL") || env("OPENAI_MODEL") || "kimi-k2.6:cloud";
26757
+ const base2 = (runtimeOption(config, "openAiBaseUrl") || "https://api.llm.perkos.xyz/v1").replace(/\/+$/, "");
26758
+ const model2 = runtimeOption(config, "model") || "kimi-k2.6:cloud";
26759
26759
  const response2 = await fetch(`${base2}/chat/completions`, {
26760
26760
  method: "POST",
26761
26761
  headers,
@@ -26775,8 +26775,8 @@ async function generateRuntimeReply(config, text, marker) {
26775
26775
  const data2 = await response2.json();
26776
26776
  return stripTaskMarker(data2.choices?.[0]?.message?.content || "Task completed.", marker);
26777
26777
  }
26778
- const base = (env("OLLAMA_BASE_URL") || "https://api.llm.perkos.xyz").replace(/\/+$/, "");
26779
- const model = env("OLLAMA_MODEL") || "kimi-k2.6:cloud";
26778
+ const base = (runtimeOption(config, "ollamaBaseUrl") || "https://api.llm.perkos.xyz").replace(/\/+$/, "");
26779
+ const model = runtimeOption(config, "model") || "kimi-k2.6:cloud";
26780
26780
  const response = await fetch(`${base}/api/chat`, {
26781
26781
  method: "POST",
26782
26782
  headers,
@@ -26829,7 +26829,7 @@ var PACKAGE_VERSION = (() => {
26829
26829
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
26830
26830
  return pkg.version || "unknown";
26831
26831
  } catch {
26832
- return process.env.npm_package_version || "unknown";
26832
+ return "unknown";
26833
26833
  }
26834
26834
  })();
26835
26835
  async function detectNetworking() {
@@ -26868,6 +26868,7 @@ var A2AServer = class {
26868
26868
  messageInjector = null;
26869
26869
  taskResultHandler = null;
26870
26870
  taskFailureHandler = null;
26871
+ lastRuntimeDelivery = null;
26871
26872
  constructor(config, logger) {
26872
26873
  this.config = config;
26873
26874
  this.logger = logger || { info: console.log, error: console.error };
@@ -26899,6 +26900,12 @@ var A2AServer = class {
26899
26900
  getTasks() {
26900
26901
  return this.tasks.values();
26901
26902
  }
26903
+ recordRuntimeDelivery(result) {
26904
+ this.lastRuntimeDelivery = {
26905
+ ...result,
26906
+ timestamp: result.timestamp || (/* @__PURE__ */ new Date()).toISOString()
26907
+ };
26908
+ }
26902
26909
  isClientOnly() {
26903
26910
  return this.clientOnly;
26904
26911
  }
@@ -26925,6 +26932,8 @@ var A2AServer = class {
26925
26932
  });
26926
26933
  this.app.get("/health", (_req, res) => {
26927
26934
  const runtimeKind = this.config.runtime?.kind || "unknown";
26935
+ const runtimeDeliveryConfigured = Boolean(this.messageInjector || this.taskResultHandler || runtimeKind === "none");
26936
+ const runtimeDeliveryValidated = this.lastRuntimeDelivery?.ok ?? (runtimeKind === "none" ? true : null);
26928
26937
  res.json({
26929
26938
  ok: true,
26930
26939
  agent: this.config.agentName,
@@ -26933,9 +26942,10 @@ var A2AServer = class {
26933
26942
  protocolVersion: PROTOCOL_VERSION,
26934
26943
  version: PACKAGE_VERSION,
26935
26944
  runtimeKind,
26936
- runtimeDeliveryConfigured: Boolean(this.messageInjector || this.taskResultHandler || runtimeKind === "none"),
26937
- runtimeDeliveryValidated: null,
26938
- runtimeDeliveryStatus: "not_validated_by_health",
26945
+ runtimeDeliveryConfigured,
26946
+ runtimeDeliveryValidated,
26947
+ runtimeDeliveryStatus: this.lastRuntimeDelivery?.status || (runtimeKind === "none" ? "disabled" : "not_validated_by_health"),
26948
+ lastRuntimeDelivery: this.lastRuntimeDelivery,
26939
26949
  peers: Object.keys(this.config.peers),
26940
26950
  taskCount: this.tasks.size,
26941
26951
  relayConnected: this.isRelayConnected(),
@@ -27154,7 +27164,7 @@ var A2AServer = class {
27154
27164
  }
27155
27165
  return initial;
27156
27166
  }
27157
- async waitForRemoteTaskTerminal(targetUrl, headers, taskId, timeoutMs = Number(process.env.A2A_SEND_WAIT_MS || 45e3), pollMs = Number(process.env.A2A_SEND_POLL_MS || 1e3)) {
27167
+ async waitForRemoteTaskTerminal(targetUrl, headers, taskId, timeoutMs = 45e3, pollMs = 1e3) {
27158
27168
  const deadline = Date.now() + timeoutMs;
27159
27169
  while (Date.now() < deadline) {
27160
27170
  await new Promise((resolve) => setTimeout(resolve, pollMs));
@@ -27174,7 +27184,7 @@ var A2AServer = class {
27174
27184
  }
27175
27185
  return null;
27176
27186
  }
27177
- async waitForLocalTaskTerminal(taskId, timeoutMs = Number(process.env.A2A_RELAY_WAIT_MS || 45e3), pollMs = Number(process.env.A2A_RELAY_POLL_MS || 1e3)) {
27187
+ async waitForLocalTaskTerminal(taskId, timeoutMs = 45e3, pollMs = 1e3) {
27178
27188
  const deadline = Date.now() + timeoutMs;
27179
27189
  while (Date.now() < deadline) {
27180
27190
  const task = this.tasks.get(taskId);
@@ -27736,7 +27746,7 @@ ${replyResultText2}` : void 0,
27736
27746
  return true;
27737
27747
  }
27738
27748
  if (!wantsDelegation && !envelope.route.length) return false;
27739
- if (delegationDepth(text) >= Number(process.env.A2A_MAX_DELEGATION_DEPTH || 8)) {
27749
+ if (delegationDepth(text) >= 8) {
27740
27750
  completeTaskWithReply(task, [
27741
27751
  `A2A delegation stopped by ${selfName}: max delegation depth reached.`,
27742
27752
  "This prevents routing loops across heterogeneous agents.",
@@ -27819,10 +27829,10 @@ function openclawEventSessionKey(config) {
27819
27829
  }
27820
27830
  async function deliverToHermes(config, message, logger) {
27821
27831
  const runtime = config.runtime || {};
27822
- const baseUrl = (runtime.hermesUrl || process.env.HERMES_API_URL || process.env.HERMES_WORKSPACE_URL || "http://127.0.0.1:8642").replace(/\/+$/, "");
27823
- const endpoint = runtime.hermesEndpoint || process.env.HERMES_API_ENDPOINT || process.env.HERMES_WORKSPACE_ENDPOINT || "/v1/responses";
27824
- const sessionKey = runtime.sessionKey || process.env.HERMES_SESSION_ID || process.env.HERMES_SESSION_KEY || "a2a";
27825
- const token = runtime.hermesToken || process.env.API_SERVER_KEY || process.env.HERMES_API_KEY || process.env.HERMES_WORKSPACE_TOKEN || process.env.HERMES_SESSION_TOKEN;
27832
+ const baseUrl = (runtime.hermesUrl || "http://127.0.0.1:8642").replace(/\/+$/, "");
27833
+ const endpoint = runtime.hermesEndpoint || "/v1/responses";
27834
+ const sessionKey = runtime.sessionKey || "a2a";
27835
+ const token = runtime.hermesToken;
27826
27836
  const url = `${baseUrl}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
27827
27837
  const headers = {
27828
27838
  "content-type": "application/json",
@@ -27831,7 +27841,7 @@ async function deliverToHermes(config, message, logger) {
27831
27841
  };
27832
27842
  if (token) headers.authorization = `Bearer ${token}`;
27833
27843
  const normalizedEndpoint = endpoint.replace(/^\/?/, "/");
27834
- const body = normalizedEndpoint.startsWith("/v1/chat/completions") ? { model: process.env.HERMES_MODEL || "hermes-agent", messages: [{ role: "user", content: message }], stream: false } : normalizedEndpoint.startsWith("/v1/runs") ? { input: message, session_id: sessionKey } : normalizedEndpoint.startsWith("/v1/responses") ? { model: process.env.HERMES_MODEL || "hermes-agent", input: message, store: true } : { sessionKey, message };
27844
+ const body = normalizedEndpoint.startsWith("/v1/chat/completions") ? { model: "hermes-agent", messages: [{ role: "user", content: message }], stream: false } : normalizedEndpoint.startsWith("/v1/runs") ? { input: message, session_id: sessionKey } : normalizedEndpoint.startsWith("/v1/responses") ? { model: "hermes-agent", input: message, store: true } : { sessionKey, message };
27835
27845
  const response = await fetch(url, {
27836
27846
  method: "POST",
27837
27847
  headers,