@perkos/perkos-a2a 0.12.18 → 0.12.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/bridge-agent.js +25 -54
- package/dist/bridge-agent.js.map +1 -1
- package/dist/bridge-chat-reply.d.ts +14 -1
- package/dist/bridge-chat-reply.d.ts.map +1 -1
- package/dist/bridge-chat-reply.js +68 -3
- package/dist/bridge-chat-reply.js.map +1 -1
- package/dist/chat-types.d.ts +4 -0
- package/dist/chat-types.d.ts.map +1 -1
- package/dist/gateway-health.d.ts +5 -11
- package/dist/gateway-health.d.ts.map +1 -1
- package/dist/gateway-health.js +53 -15
- package/dist/gateway-health.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +360 -20
- package/dist/index.js.map +4 -4
- package/dist/platform-heartbeat.d.ts +22 -0
- package/dist/platform-heartbeat.d.ts.map +1 -0
- package/dist/platform-heartbeat.js +72 -0
- package/dist/platform-heartbeat.js.map +1 -0
- package/dist/project-chat-context.d.ts +3 -0
- package/dist/project-chat-context.d.ts.map +1 -0
- package/dist/project-chat-context.js +16 -0
- package/dist/project-chat-context.js.map +1 -0
- package/dist/relay-client.d.ts +21 -2
- package/dist/relay-client.d.ts.map +1 -1
- package/dist/relay-client.js +82 -17
- package/dist/relay-client.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -2
- package/dist/server.js.map +1 -1
- package/dist/task-context.d.ts +18 -0
- package/dist/task-context.d.ts.map +1 -0
- package/dist/task-context.js +35 -0
- package/dist/task-context.js.map +1 -0
- package/dist/types.d.ts +4 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -22632,6 +22632,218 @@ var require_constants = __commonJS({
|
|
|
22632
22632
|
}
|
|
22633
22633
|
});
|
|
22634
22634
|
|
|
22635
|
+
// ../../../../node_modules/node-gyp-build/node-gyp-build.js
|
|
22636
|
+
var require_node_gyp_build = __commonJS({
|
|
22637
|
+
"../../../../node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
|
|
22638
|
+
var fs = __require("fs");
|
|
22639
|
+
var path = __require("path");
|
|
22640
|
+
var os = __require("os");
|
|
22641
|
+
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
22642
|
+
var vars = process.config && process.config.variables || {};
|
|
22643
|
+
var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
|
|
22644
|
+
var abi = process.versions.modules;
|
|
22645
|
+
var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
|
|
22646
|
+
var arch = process.env.npm_config_arch || os.arch();
|
|
22647
|
+
var platform = process.env.npm_config_platform || os.platform();
|
|
22648
|
+
var libc = process.env.LIBC || (isAlpine(platform) ? "musl" : "glibc");
|
|
22649
|
+
var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
|
|
22650
|
+
var uv = (process.versions.uv || "").split(".")[0];
|
|
22651
|
+
module.exports = load;
|
|
22652
|
+
function load(dir) {
|
|
22653
|
+
return runtimeRequire(load.resolve(dir));
|
|
22654
|
+
}
|
|
22655
|
+
load.resolve = load.path = function(dir) {
|
|
22656
|
+
dir = path.resolve(dir || ".");
|
|
22657
|
+
try {
|
|
22658
|
+
var name = runtimeRequire(path.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
|
|
22659
|
+
if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
|
|
22660
|
+
} catch (err) {
|
|
22661
|
+
}
|
|
22662
|
+
if (!prebuildsOnly) {
|
|
22663
|
+
var release = getFirst(path.join(dir, "build/Release"), matchBuild);
|
|
22664
|
+
if (release) return release;
|
|
22665
|
+
var debug = getFirst(path.join(dir, "build/Debug"), matchBuild);
|
|
22666
|
+
if (debug) return debug;
|
|
22667
|
+
}
|
|
22668
|
+
var prebuild = resolve(dir);
|
|
22669
|
+
if (prebuild) return prebuild;
|
|
22670
|
+
var nearby = resolve(path.dirname(process.execPath));
|
|
22671
|
+
if (nearby) return nearby;
|
|
22672
|
+
var target = [
|
|
22673
|
+
"platform=" + platform,
|
|
22674
|
+
"arch=" + arch,
|
|
22675
|
+
"runtime=" + runtime,
|
|
22676
|
+
"abi=" + abi,
|
|
22677
|
+
"uv=" + uv,
|
|
22678
|
+
armv ? "armv=" + armv : "",
|
|
22679
|
+
"libc=" + libc,
|
|
22680
|
+
"node=" + process.versions.node,
|
|
22681
|
+
process.versions.electron ? "electron=" + process.versions.electron : "",
|
|
22682
|
+
typeof __webpack_require__ === "function" ? "webpack=true" : ""
|
|
22683
|
+
// eslint-disable-line
|
|
22684
|
+
].filter(Boolean).join(" ");
|
|
22685
|
+
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
|
|
22686
|
+
function resolve(dir2) {
|
|
22687
|
+
var tuples = readdirSync(path.join(dir2, "prebuilds")).map(parseTuple);
|
|
22688
|
+
var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
|
|
22689
|
+
if (!tuple) return;
|
|
22690
|
+
var prebuilds = path.join(dir2, "prebuilds", tuple.name);
|
|
22691
|
+
var parsed = readdirSync(prebuilds).map(parseTags);
|
|
22692
|
+
var candidates = parsed.filter(matchTags(runtime, abi));
|
|
22693
|
+
var winner = candidates.sort(compareTags(runtime))[0];
|
|
22694
|
+
if (winner) return path.join(prebuilds, winner.file);
|
|
22695
|
+
}
|
|
22696
|
+
};
|
|
22697
|
+
function readdirSync(dir) {
|
|
22698
|
+
try {
|
|
22699
|
+
return fs.readdirSync(dir);
|
|
22700
|
+
} catch (err) {
|
|
22701
|
+
return [];
|
|
22702
|
+
}
|
|
22703
|
+
}
|
|
22704
|
+
function getFirst(dir, filter) {
|
|
22705
|
+
var files = readdirSync(dir).filter(filter);
|
|
22706
|
+
return files[0] && path.join(dir, files[0]);
|
|
22707
|
+
}
|
|
22708
|
+
function matchBuild(name) {
|
|
22709
|
+
return /\.node$/.test(name);
|
|
22710
|
+
}
|
|
22711
|
+
function parseTuple(name) {
|
|
22712
|
+
var arr = name.split("-");
|
|
22713
|
+
if (arr.length !== 2) return;
|
|
22714
|
+
var platform2 = arr[0];
|
|
22715
|
+
var architectures = arr[1].split("+");
|
|
22716
|
+
if (!platform2) return;
|
|
22717
|
+
if (!architectures.length) return;
|
|
22718
|
+
if (!architectures.every(Boolean)) return;
|
|
22719
|
+
return { name, platform: platform2, architectures };
|
|
22720
|
+
}
|
|
22721
|
+
function matchTuple(platform2, arch2) {
|
|
22722
|
+
return function(tuple) {
|
|
22723
|
+
if (tuple == null) return false;
|
|
22724
|
+
if (tuple.platform !== platform2) return false;
|
|
22725
|
+
return tuple.architectures.includes(arch2);
|
|
22726
|
+
};
|
|
22727
|
+
}
|
|
22728
|
+
function compareTuples(a, b) {
|
|
22729
|
+
return a.architectures.length - b.architectures.length;
|
|
22730
|
+
}
|
|
22731
|
+
function parseTags(file) {
|
|
22732
|
+
var arr = file.split(".");
|
|
22733
|
+
var extension2 = arr.pop();
|
|
22734
|
+
var tags = { file, specificity: 0 };
|
|
22735
|
+
if (extension2 !== "node") return;
|
|
22736
|
+
for (var i = 0; i < arr.length; i++) {
|
|
22737
|
+
var tag = arr[i];
|
|
22738
|
+
if (tag === "node" || tag === "electron" || tag === "node-webkit") {
|
|
22739
|
+
tags.runtime = tag;
|
|
22740
|
+
} else if (tag === "napi") {
|
|
22741
|
+
tags.napi = true;
|
|
22742
|
+
} else if (tag.slice(0, 3) === "abi") {
|
|
22743
|
+
tags.abi = tag.slice(3);
|
|
22744
|
+
} else if (tag.slice(0, 2) === "uv") {
|
|
22745
|
+
tags.uv = tag.slice(2);
|
|
22746
|
+
} else if (tag.slice(0, 4) === "armv") {
|
|
22747
|
+
tags.armv = tag.slice(4);
|
|
22748
|
+
} else if (tag === "glibc" || tag === "musl") {
|
|
22749
|
+
tags.libc = tag;
|
|
22750
|
+
} else {
|
|
22751
|
+
continue;
|
|
22752
|
+
}
|
|
22753
|
+
tags.specificity++;
|
|
22754
|
+
}
|
|
22755
|
+
return tags;
|
|
22756
|
+
}
|
|
22757
|
+
function matchTags(runtime2, abi2) {
|
|
22758
|
+
return function(tags) {
|
|
22759
|
+
if (tags == null) return false;
|
|
22760
|
+
if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
|
|
22761
|
+
if (tags.abi && tags.abi !== abi2 && !tags.napi) return false;
|
|
22762
|
+
if (tags.uv && tags.uv !== uv) return false;
|
|
22763
|
+
if (tags.armv && tags.armv !== armv) return false;
|
|
22764
|
+
if (tags.libc && tags.libc !== libc) return false;
|
|
22765
|
+
return true;
|
|
22766
|
+
};
|
|
22767
|
+
}
|
|
22768
|
+
function runtimeAgnostic(tags) {
|
|
22769
|
+
return tags.runtime === "node" && tags.napi;
|
|
22770
|
+
}
|
|
22771
|
+
function compareTags(runtime2) {
|
|
22772
|
+
return function(a, b) {
|
|
22773
|
+
if (a.runtime !== b.runtime) {
|
|
22774
|
+
return a.runtime === runtime2 ? -1 : 1;
|
|
22775
|
+
} else if (a.abi !== b.abi) {
|
|
22776
|
+
return a.abi ? -1 : 1;
|
|
22777
|
+
} else if (a.specificity !== b.specificity) {
|
|
22778
|
+
return a.specificity > b.specificity ? -1 : 1;
|
|
22779
|
+
} else {
|
|
22780
|
+
return 0;
|
|
22781
|
+
}
|
|
22782
|
+
};
|
|
22783
|
+
}
|
|
22784
|
+
function isNwjs() {
|
|
22785
|
+
return !!(process.versions && process.versions.nw);
|
|
22786
|
+
}
|
|
22787
|
+
function isElectron() {
|
|
22788
|
+
if (process.versions && process.versions.electron) return true;
|
|
22789
|
+
if (process.env.ELECTRON_RUN_AS_NODE) return true;
|
|
22790
|
+
return typeof window !== "undefined" && window.process && window.process.type === "renderer";
|
|
22791
|
+
}
|
|
22792
|
+
function isAlpine(platform2) {
|
|
22793
|
+
return platform2 === "linux" && fs.existsSync("/etc/alpine-release");
|
|
22794
|
+
}
|
|
22795
|
+
load.parseTags = parseTags;
|
|
22796
|
+
load.matchTags = matchTags;
|
|
22797
|
+
load.compareTags = compareTags;
|
|
22798
|
+
load.parseTuple = parseTuple;
|
|
22799
|
+
load.matchTuple = matchTuple;
|
|
22800
|
+
load.compareTuples = compareTuples;
|
|
22801
|
+
}
|
|
22802
|
+
});
|
|
22803
|
+
|
|
22804
|
+
// ../../../../node_modules/node-gyp-build/index.js
|
|
22805
|
+
var require_node_gyp_build2 = __commonJS({
|
|
22806
|
+
"../../../../node_modules/node-gyp-build/index.js"(exports, module) {
|
|
22807
|
+
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
22808
|
+
if (typeof runtimeRequire.addon === "function") {
|
|
22809
|
+
module.exports = runtimeRequire.addon.bind(runtimeRequire);
|
|
22810
|
+
} else {
|
|
22811
|
+
module.exports = require_node_gyp_build();
|
|
22812
|
+
}
|
|
22813
|
+
}
|
|
22814
|
+
});
|
|
22815
|
+
|
|
22816
|
+
// ../../../../node_modules/bufferutil/fallback.js
|
|
22817
|
+
var require_fallback = __commonJS({
|
|
22818
|
+
"../../../../node_modules/bufferutil/fallback.js"(exports, module) {
|
|
22819
|
+
"use strict";
|
|
22820
|
+
var mask = (source, mask2, output, offset, length) => {
|
|
22821
|
+
for (var i = 0; i < length; i++) {
|
|
22822
|
+
output[offset + i] = source[i] ^ mask2[i & 3];
|
|
22823
|
+
}
|
|
22824
|
+
};
|
|
22825
|
+
var unmask = (buffer, mask2) => {
|
|
22826
|
+
const length = buffer.length;
|
|
22827
|
+
for (var i = 0; i < length; i++) {
|
|
22828
|
+
buffer[i] ^= mask2[i & 3];
|
|
22829
|
+
}
|
|
22830
|
+
};
|
|
22831
|
+
module.exports = { mask, unmask };
|
|
22832
|
+
}
|
|
22833
|
+
});
|
|
22834
|
+
|
|
22835
|
+
// ../../../../node_modules/bufferutil/index.js
|
|
22836
|
+
var require_bufferutil = __commonJS({
|
|
22837
|
+
"../../../../node_modules/bufferutil/index.js"(exports, module) {
|
|
22838
|
+
"use strict";
|
|
22839
|
+
try {
|
|
22840
|
+
module.exports = require_node_gyp_build2()(__dirname);
|
|
22841
|
+
} catch (e) {
|
|
22842
|
+
module.exports = require_fallback();
|
|
22843
|
+
}
|
|
22844
|
+
}
|
|
22845
|
+
});
|
|
22846
|
+
|
|
22635
22847
|
// node_modules/ws/lib/buffer-util.js
|
|
22636
22848
|
var require_buffer_util = __commonJS({
|
|
22637
22849
|
"node_modules/ws/lib/buffer-util.js"(exports, module) {
|
|
@@ -22692,7 +22904,7 @@ var require_buffer_util = __commonJS({
|
|
|
22692
22904
|
};
|
|
22693
22905
|
if (!process.env.WS_NO_BUFFER_UTIL) {
|
|
22694
22906
|
try {
|
|
22695
|
-
const bufferUtil =
|
|
22907
|
+
const bufferUtil = require_bufferutil();
|
|
22696
22908
|
module.exports.mask = function(source, mask, output, offset, length) {
|
|
22697
22909
|
if (length < 48) _mask(source, mask, output, offset, length);
|
|
22698
22910
|
else bufferUtil.mask(source, mask, output, offset, length);
|
|
@@ -23140,6 +23352,55 @@ var require_permessage_deflate = __commonJS({
|
|
|
23140
23352
|
}
|
|
23141
23353
|
});
|
|
23142
23354
|
|
|
23355
|
+
// ../../../../node_modules/utf-8-validate/fallback.js
|
|
23356
|
+
var require_fallback2 = __commonJS({
|
|
23357
|
+
"../../../../node_modules/utf-8-validate/fallback.js"(exports, module) {
|
|
23358
|
+
"use strict";
|
|
23359
|
+
function isValidUTF8(buf) {
|
|
23360
|
+
const len = buf.length;
|
|
23361
|
+
let i = 0;
|
|
23362
|
+
while (i < len) {
|
|
23363
|
+
if ((buf[i] & 128) === 0) {
|
|
23364
|
+
i++;
|
|
23365
|
+
} else if ((buf[i] & 224) === 192) {
|
|
23366
|
+
if (i + 1 === len || (buf[i + 1] & 192) !== 128 || (buf[i] & 254) === 192) {
|
|
23367
|
+
return false;
|
|
23368
|
+
}
|
|
23369
|
+
i += 2;
|
|
23370
|
+
} else if ((buf[i] & 240) === 224) {
|
|
23371
|
+
if (i + 2 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || buf[i] === 224 && (buf[i + 1] & 224) === 128 || // overlong
|
|
23372
|
+
buf[i] === 237 && (buf[i + 1] & 224) === 160) {
|
|
23373
|
+
return false;
|
|
23374
|
+
}
|
|
23375
|
+
i += 3;
|
|
23376
|
+
} else if ((buf[i] & 248) === 240) {
|
|
23377
|
+
if (i + 3 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || (buf[i + 3] & 192) !== 128 || buf[i] === 240 && (buf[i + 1] & 240) === 128 || // overlong
|
|
23378
|
+
buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) {
|
|
23379
|
+
return false;
|
|
23380
|
+
}
|
|
23381
|
+
i += 4;
|
|
23382
|
+
} else {
|
|
23383
|
+
return false;
|
|
23384
|
+
}
|
|
23385
|
+
}
|
|
23386
|
+
return true;
|
|
23387
|
+
}
|
|
23388
|
+
module.exports = isValidUTF8;
|
|
23389
|
+
}
|
|
23390
|
+
});
|
|
23391
|
+
|
|
23392
|
+
// ../../../../node_modules/utf-8-validate/index.js
|
|
23393
|
+
var require_utf_8_validate = __commonJS({
|
|
23394
|
+
"../../../../node_modules/utf-8-validate/index.js"(exports, module) {
|
|
23395
|
+
"use strict";
|
|
23396
|
+
try {
|
|
23397
|
+
module.exports = require_node_gyp_build2()(__dirname);
|
|
23398
|
+
} catch (e) {
|
|
23399
|
+
module.exports = require_fallback2();
|
|
23400
|
+
}
|
|
23401
|
+
}
|
|
23402
|
+
});
|
|
23403
|
+
|
|
23143
23404
|
// node_modules/ws/lib/validation.js
|
|
23144
23405
|
var require_validation = __commonJS({
|
|
23145
23406
|
"node_modules/ws/lib/validation.js"(exports, module) {
|
|
@@ -23331,7 +23592,7 @@ var require_validation = __commonJS({
|
|
|
23331
23592
|
};
|
|
23332
23593
|
} else if (!process.env.WS_NO_UTF_8_VALIDATE) {
|
|
23333
23594
|
try {
|
|
23334
|
-
const isValidUTF8 =
|
|
23595
|
+
const isValidUTF8 = require_utf_8_validate();
|
|
23335
23596
|
module.exports.isValidUTF8 = function(buf) {
|
|
23336
23597
|
return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
|
|
23337
23598
|
};
|
|
@@ -26252,6 +26513,8 @@ import { randomUUID } from "crypto";
|
|
|
26252
26513
|
var MIN_RECONNECT_MS = 1e3;
|
|
26253
26514
|
var MAX_RECONNECT_MS = 6e4;
|
|
26254
26515
|
var HEARTBEAT_INTERVAL_MS = 25e3;
|
|
26516
|
+
var ORPHAN_TTL_MS = 10 * 6e4;
|
|
26517
|
+
var ORPHAN_MAX = 256;
|
|
26255
26518
|
var RelayClient = class {
|
|
26256
26519
|
ws = null;
|
|
26257
26520
|
options;
|
|
@@ -26262,6 +26525,8 @@ var RelayClient = class {
|
|
|
26262
26525
|
connected = false;
|
|
26263
26526
|
stopped = false;
|
|
26264
26527
|
pendingCallbacks = /* @__PURE__ */ new Map();
|
|
26528
|
+
/** Responses that arrived with nobody waiting, claimable by a retry. */
|
|
26529
|
+
orphanResponses = /* @__PURE__ */ new Map();
|
|
26265
26530
|
constructor(options) {
|
|
26266
26531
|
this.options = options;
|
|
26267
26532
|
this.logger = options.logger || { info: console.log, error: console.error };
|
|
@@ -26282,12 +26547,25 @@ var RelayClient = class {
|
|
|
26282
26547
|
}
|
|
26283
26548
|
this.connected = false;
|
|
26284
26549
|
}
|
|
26285
|
-
/**
|
|
26286
|
-
|
|
26550
|
+
/**
|
|
26551
|
+
* Send a task to another agent via the relay.
|
|
26552
|
+
*
|
|
26553
|
+
* Pass `taskId` to retry a task that already went out: the relay dedups on
|
|
26554
|
+
* the id and will not run the work twice, and if the first attempt's response
|
|
26555
|
+
* arrived after we gave up it is claimed from the orphan buffer instead of
|
|
26556
|
+
* waiting again. Omit it for genuinely new work.
|
|
26557
|
+
*/
|
|
26558
|
+
async sendTask(targetAgent, payload, taskId) {
|
|
26559
|
+
const id = taskId ?? randomUUID();
|
|
26560
|
+
const alreadyAnswered = this.claimOrphan(id);
|
|
26561
|
+
if (alreadyAnswered) {
|
|
26562
|
+
this.logger.info(`[perkos-a2a] Reusing buffered response for task ${id}`);
|
|
26563
|
+
return alreadyAnswered;
|
|
26564
|
+
}
|
|
26287
26565
|
return this.sendAndWait({
|
|
26288
26566
|
type: "task",
|
|
26289
26567
|
to: targetAgent,
|
|
26290
|
-
id
|
|
26568
|
+
id,
|
|
26291
26569
|
from: this.options.agentName,
|
|
26292
26570
|
payload,
|
|
26293
26571
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -26372,10 +26650,10 @@ var RelayClient = class {
|
|
|
26372
26650
|
this.send(msg);
|
|
26373
26651
|
}
|
|
26374
26652
|
handleMessage(msg) {
|
|
26375
|
-
const
|
|
26376
|
-
if (
|
|
26653
|
+
const pending = this.pendingCallbacks.get(msg.id);
|
|
26654
|
+
if (pending && (msg.type === pending.expectedType || msg.type === "error")) {
|
|
26377
26655
|
this.pendingCallbacks.delete(msg.id);
|
|
26378
|
-
|
|
26656
|
+
pending.settle(msg);
|
|
26379
26657
|
return;
|
|
26380
26658
|
}
|
|
26381
26659
|
switch (msg.type) {
|
|
@@ -26385,8 +26663,15 @@ var RelayClient = class {
|
|
|
26385
26663
|
case "task":
|
|
26386
26664
|
this.options.onTask(msg);
|
|
26387
26665
|
break;
|
|
26666
|
+
case "task_ack":
|
|
26667
|
+
if (msg.payload?.deduplicated) {
|
|
26668
|
+
this.logger.info(`[perkos-a2a] Relay deduplicated task ${msg.id}; awaiting the original response`);
|
|
26669
|
+
}
|
|
26670
|
+
break;
|
|
26388
26671
|
case "task_response":
|
|
26389
|
-
this.
|
|
26672
|
+
this.bufferOrphan(msg);
|
|
26673
|
+
this.logger.info(`[perkos-a2a] Buffered unmatched task response: ${msg.id}`);
|
|
26674
|
+
this.options.onOrphanTaskResponse?.(msg);
|
|
26390
26675
|
break;
|
|
26391
26676
|
case "discover_response":
|
|
26392
26677
|
if (this.options.onDiscoverResponse) {
|
|
@@ -26407,18 +26692,39 @@ var RelayClient = class {
|
|
|
26407
26692
|
this.ws.send(JSON.stringify(msg));
|
|
26408
26693
|
}
|
|
26409
26694
|
}
|
|
26695
|
+
/** Take a buffered response for `id`, if one arrived while nobody waited. */
|
|
26696
|
+
claimOrphan(id) {
|
|
26697
|
+
const entry = this.orphanResponses.get(id);
|
|
26698
|
+
if (!entry) return null;
|
|
26699
|
+
this.orphanResponses.delete(id);
|
|
26700
|
+
if (entry.expiresAt <= Date.now()) return null;
|
|
26701
|
+
return entry.msg;
|
|
26702
|
+
}
|
|
26703
|
+
bufferOrphan(msg) {
|
|
26704
|
+
const now = Date.now();
|
|
26705
|
+
for (const [id, entry] of this.orphanResponses) {
|
|
26706
|
+
if (entry.expiresAt <= now) this.orphanResponses.delete(id);
|
|
26707
|
+
}
|
|
26708
|
+
this.orphanResponses.set(msg.id, { msg, expiresAt: now + ORPHAN_TTL_MS });
|
|
26709
|
+
while (this.orphanResponses.size > ORPHAN_MAX) {
|
|
26710
|
+
this.orphanResponses.delete(this.orphanResponses.keys().next().value);
|
|
26711
|
+
}
|
|
26712
|
+
}
|
|
26410
26713
|
async sendAndWait(msg, expectedType, timeoutMs) {
|
|
26411
26714
|
return new Promise((resolve, reject) => {
|
|
26412
26715
|
const timer = setTimeout(() => {
|
|
26413
26716
|
this.pendingCallbacks.delete(msg.id);
|
|
26414
26717
|
reject(new Error(`Relay request timed out after ${timeoutMs}ms`));
|
|
26415
26718
|
}, timeoutMs);
|
|
26416
|
-
this.pendingCallbacks.set(msg.id,
|
|
26417
|
-
|
|
26418
|
-
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26719
|
+
this.pendingCallbacks.set(msg.id, {
|
|
26720
|
+
expectedType,
|
|
26721
|
+
settle: (response) => {
|
|
26722
|
+
clearTimeout(timer);
|
|
26723
|
+
if (response.type === "error") {
|
|
26724
|
+
reject(new Error(`Relay error: ${response.payload.message}`));
|
|
26725
|
+
} else {
|
|
26726
|
+
resolve(response);
|
|
26727
|
+
}
|
|
26422
26728
|
}
|
|
26423
26729
|
});
|
|
26424
26730
|
this.send(msg);
|
|
@@ -27034,6 +27340,7 @@ var A2AServer = class {
|
|
|
27034
27340
|
messages: [message],
|
|
27035
27341
|
artifacts: [],
|
|
27036
27342
|
metadata: {
|
|
27343
|
+
...message?.metadata,
|
|
27037
27344
|
fromAgent: message?.metadata?.fromAgent || "unknown"
|
|
27038
27345
|
},
|
|
27039
27346
|
sessionKeyHint: "agent:main"
|
|
@@ -27281,9 +27588,9 @@ var A2AServer = class {
|
|
|
27281
27588
|
const payload = msg.payload;
|
|
27282
27589
|
const params = payload.params || payload;
|
|
27283
27590
|
const rpcId = payload.id || msg.id;
|
|
27284
|
-
const acceptQueued = params?.message?.metadata?.acceptQueued === true;
|
|
27285
27591
|
this.handleSendMessage(params, rpcId).then(async (response) => {
|
|
27286
27592
|
const task = response.result;
|
|
27593
|
+
const acceptQueued = task?.messages?.[0]?.metadata?.acceptQueued === true;
|
|
27287
27594
|
if (task?.id && !isTerminalTaskState(task.status?.state)) {
|
|
27288
27595
|
if (acceptQueued) {
|
|
27289
27596
|
this.relayClient?.sendTaskResponse(
|
|
@@ -27301,7 +27608,12 @@ var A2AServer = class {
|
|
|
27301
27608
|
return;
|
|
27302
27609
|
}
|
|
27303
27610
|
}
|
|
27304
|
-
|
|
27611
|
+
if (!acceptQueued) {
|
|
27612
|
+
this.relayClient?.sendTaskResponse(
|
|
27613
|
+
msg,
|
|
27614
|
+
response
|
|
27615
|
+
);
|
|
27616
|
+
}
|
|
27305
27617
|
}).catch((err) => {
|
|
27306
27618
|
const errMsg2 = err instanceof Error ? err.message : String(err);
|
|
27307
27619
|
this.logger.error(`[perkos-a2a] Failed to process relay task: ${errMsg2}`);
|
|
@@ -28439,11 +28751,24 @@ function openclawEventSessionKey(config) {
|
|
|
28439
28751
|
if (!key) return "agent:main:main";
|
|
28440
28752
|
return key.endsWith(":main") ? key : `${key}:main`;
|
|
28441
28753
|
}
|
|
28754
|
+
function openclawChatSessionKey(config, convId) {
|
|
28755
|
+
const configured = config.runtime?.sessionKey || "agent:main";
|
|
28756
|
+
const safe = convId.replace(/[^a-zA-Z0-9_.-]/g, "-").slice(0, 120) || "unknown";
|
|
28757
|
+
return `${configured}:perkos-chat-${safe}`;
|
|
28758
|
+
}
|
|
28442
28759
|
function parseWalletFromIdentity(identity) {
|
|
28443
28760
|
if (typeof identity !== "string" || !identity.startsWith("user:")) return null;
|
|
28444
28761
|
const addr = identity.slice("user:".length);
|
|
28445
28762
|
return addr.startsWith("0x") ? addr.toLowerCase() : null;
|
|
28446
28763
|
}
|
|
28764
|
+
var CHAT_CONTEXT_MESSAGE_LIMIT = 12;
|
|
28765
|
+
var CHAT_CONTEXT_CHAR_LIMIT = 6e3;
|
|
28766
|
+
function formatRecentChatContext(messages, currentMessageId) {
|
|
28767
|
+
const prior = messages.filter((message) => message.id !== currentMessageId).slice(-CHAT_CONTEXT_MESSAGE_LIMIT).map((message) => `${message.from}: ${message.text.trim()}`).filter((line) => line.length > 0);
|
|
28768
|
+
if (prior.length === 0) return "(No earlier messages in this conversation.)";
|
|
28769
|
+
const transcript = prior.join("\n");
|
|
28770
|
+
return transcript.length <= CHAT_CONTEXT_CHAR_LIMIT ? transcript : `\u2026${transcript.slice(-CHAT_CONTEXT_CHAR_LIMIT)}`;
|
|
28771
|
+
}
|
|
28447
28772
|
async function deliverToHermes(config, message, logger) {
|
|
28448
28773
|
const runtime = config.runtime || {};
|
|
28449
28774
|
const baseUrl = (runtime.hermesUrl || "http://127.0.0.1:8642").replace(/\/+$/, "");
|
|
@@ -28676,10 +29001,18 @@ function register(api) {
|
|
|
28676
29001
|
onChatDeliver: async (frame) => {
|
|
28677
29002
|
const walletAddress = parseWalletFromIdentity(frame.from);
|
|
28678
29003
|
const marker = `[PERKOS_CHAT:${frame.convId}]`;
|
|
29004
|
+
const recentPage = await chatClient?.getStore().readPage(frame.convId, {
|
|
29005
|
+
limit: CHAT_CONTEXT_MESSAGE_LIMIT + 1
|
|
29006
|
+
});
|
|
29007
|
+
const recentContext = formatRecentChatContext(
|
|
29008
|
+
recentPage?.messages ?? [],
|
|
29009
|
+
frame.id
|
|
29010
|
+
);
|
|
28679
29011
|
const eventText = [
|
|
28680
29012
|
marker,
|
|
28681
29013
|
`From: ${frame.from}`,
|
|
28682
29014
|
`Conversation: ${frame.convId}`,
|
|
29015
|
+
frame.projectId ? `Canonical projectId: ${frame.projectId}` : "",
|
|
28683
29016
|
walletAddress ? `Wallet: ${walletAddress}` : "",
|
|
28684
29017
|
"",
|
|
28685
29018
|
"A user is messaging you in a PerkOS chat conversation.",
|
|
@@ -28688,6 +29021,11 @@ function register(api) {
|
|
|
28688
29021
|
walletAddress ? ` walletAddress: "${walletAddress}"` : ` walletAddress: <derived from From>`,
|
|
28689
29022
|
` text: <your reply>`,
|
|
28690
29023
|
"",
|
|
29024
|
+
"Recent conversation context (oldest to newest):",
|
|
29025
|
+
recentContext,
|
|
29026
|
+
"",
|
|
29027
|
+
"Use the recent context. Do not ask again for information the user already provided.",
|
|
29028
|
+
"",
|
|
28691
29029
|
"Message body:",
|
|
28692
29030
|
frame.text
|
|
28693
29031
|
].filter(Boolean).join("\n");
|
|
@@ -28705,13 +29043,13 @@ function register(api) {
|
|
|
28705
29043
|
return;
|
|
28706
29044
|
}
|
|
28707
29045
|
if (enqueueSystemEvent) {
|
|
28708
|
-
enqueueSystemEvent(eventText, { sessionKey:
|
|
29046
|
+
enqueueSystemEvent(eventText, { sessionKey: openclawChatSessionKey(pluginConfig, frame.convId) });
|
|
28709
29047
|
}
|
|
28710
29048
|
wakeGatewayAgent(
|
|
28711
29049
|
requestHeartbeatNow,
|
|
28712
29050
|
`[PerkOS-Chat] inbound message in ${frame.convId}`,
|
|
28713
29051
|
logger,
|
|
28714
|
-
|
|
29052
|
+
openclawChatSessionKey(pluginConfig, frame.convId)
|
|
28715
29053
|
);
|
|
28716
29054
|
},
|
|
28717
29055
|
onChannelJoin: async (frame) => {
|
|
@@ -29118,7 +29456,9 @@ export {
|
|
|
29118
29456
|
RelayHub,
|
|
29119
29457
|
register as default,
|
|
29120
29458
|
detectNetworking,
|
|
29121
|
-
|
|
29459
|
+
formatRecentChatContext,
|
|
29460
|
+
isWebhookEvent,
|
|
29461
|
+
openclawChatSessionKey
|
|
29122
29462
|
};
|
|
29123
29463
|
/*! Bundled license information:
|
|
29124
29464
|
|