@cfio/cohort-sync 0.34.2 → 0.34.4
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 +615 -204
- package/dist/openclaw.plugin.json +4 -1
- package/dist/package.json +1 -1
- package/openclaw.plugin.json +3 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -207,11 +207,11 @@ var TypeBoxError = class extends Error {
|
|
|
207
207
|
};
|
|
208
208
|
|
|
209
209
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.48/node_modules/@sinclair/typebox/build/esm/type/symbols/symbols.mjs
|
|
210
|
-
var TransformKind = Symbol.for("TypeBox.Transform");
|
|
211
|
-
var ReadonlyKind = Symbol.for("TypeBox.Readonly");
|
|
212
|
-
var OptionalKind = Symbol.for("TypeBox.Optional");
|
|
213
|
-
var Hint = Symbol.for("TypeBox.Hint");
|
|
214
|
-
var Kind = Symbol.for("TypeBox.Kind");
|
|
210
|
+
var TransformKind = /* @__PURE__ */ Symbol.for("TypeBox.Transform");
|
|
211
|
+
var ReadonlyKind = /* @__PURE__ */ Symbol.for("TypeBox.Readonly");
|
|
212
|
+
var OptionalKind = /* @__PURE__ */ Symbol.for("TypeBox.Optional");
|
|
213
|
+
var Hint = /* @__PURE__ */ Symbol.for("TypeBox.Hint");
|
|
214
|
+
var Kind = /* @__PURE__ */ Symbol.for("TypeBox.Kind");
|
|
215
215
|
|
|
216
216
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.48/node_modules/@sinclair/typebox/build/esm/type/guard/kind.mjs
|
|
217
217
|
function IsReadonly(value) {
|
|
@@ -449,8 +449,8 @@ function IsPattern(value) {
|
|
|
449
449
|
function IsControlCharacterFree(value) {
|
|
450
450
|
if (!IsString(value))
|
|
451
451
|
return false;
|
|
452
|
-
for (let
|
|
453
|
-
const code2 = value.charCodeAt(
|
|
452
|
+
for (let i2 = 0; i2 < value.length; i2++) {
|
|
453
|
+
const code2 = value.charCodeAt(i2);
|
|
454
454
|
if (code2 >= 7 && code2 <= 13 || code2 === 27 || code2 === 127) {
|
|
455
455
|
return false;
|
|
456
456
|
}
|
|
@@ -977,20 +977,20 @@ function* FromTerminal(syntax) {
|
|
|
977
977
|
const R = FromSyntax(syntax.slice(1));
|
|
978
978
|
return yield* [L, ...R];
|
|
979
979
|
}
|
|
980
|
-
for (let
|
|
981
|
-
if (syntax[
|
|
982
|
-
const L = FromUnion(syntax.slice(2,
|
|
983
|
-
const R = FromSyntax(syntax.slice(
|
|
980
|
+
for (let i2 = 2; i2 < syntax.length; i2++) {
|
|
981
|
+
if (syntax[i2] === "}") {
|
|
982
|
+
const L = FromUnion(syntax.slice(2, i2));
|
|
983
|
+
const R = FromSyntax(syntax.slice(i2 + 1));
|
|
984
984
|
return yield* [...L, ...R];
|
|
985
985
|
}
|
|
986
986
|
}
|
|
987
987
|
yield Literal(syntax);
|
|
988
988
|
}
|
|
989
989
|
function* FromSyntax(syntax) {
|
|
990
|
-
for (let
|
|
991
|
-
if (syntax[
|
|
992
|
-
const L = Literal(syntax.slice(0,
|
|
993
|
-
const R = FromTerminal(syntax.slice(
|
|
990
|
+
for (let i2 = 0; i2 < syntax.length; i2++) {
|
|
991
|
+
if (syntax[i2] === "$") {
|
|
992
|
+
const L = Literal(syntax.slice(0, i2));
|
|
993
|
+
const R = FromTerminal(syntax.slice(i2));
|
|
994
994
|
return yield* [L, ...R];
|
|
995
995
|
}
|
|
996
996
|
}
|
|
@@ -2619,11 +2619,13 @@ var Type = type_exports2;
|
|
|
2619
2619
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
2620
2620
|
|
|
2621
2621
|
// src/hooks.ts
|
|
2622
|
-
import
|
|
2622
|
+
import fs3 from "node:fs";
|
|
2623
2623
|
import os2 from "node:os";
|
|
2624
|
-
import
|
|
2624
|
+
import path3 from "node:path";
|
|
2625
2625
|
|
|
2626
2626
|
// src/sync.ts
|
|
2627
|
+
import fs from "node:fs";
|
|
2628
|
+
import path from "node:path";
|
|
2627
2629
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["idle", "working", "waiting"]);
|
|
2628
2630
|
function normalizeStatus(status) {
|
|
2629
2631
|
return VALID_STATUSES.has(status) ? status : "idle";
|
|
@@ -2632,39 +2634,39 @@ function trimTrailingSlashes(url) {
|
|
|
2632
2634
|
while (url.endsWith("/")) url = url.slice(0, -1);
|
|
2633
2635
|
return url;
|
|
2634
2636
|
}
|
|
2635
|
-
async function v1Get(apiUrl2, apiKey2,
|
|
2636
|
-
const res = await fetch(`${trimTrailingSlashes(apiUrl2)}${
|
|
2637
|
+
async function v1Get(apiUrl2, apiKey2, path4) {
|
|
2638
|
+
const res = await fetch(`${trimTrailingSlashes(apiUrl2)}${path4}`, {
|
|
2637
2639
|
headers: { Authorization: `Bearer ${apiKey2}` },
|
|
2638
2640
|
signal: AbortSignal.timeout(1e4)
|
|
2639
2641
|
});
|
|
2640
|
-
if (!res.ok) throw new Error(`GET ${
|
|
2642
|
+
if (!res.ok) throw new Error(`GET ${path4} \u2192 ${res.status}`);
|
|
2641
2643
|
return res.json();
|
|
2642
2644
|
}
|
|
2643
|
-
async function v1Patch(apiUrl2, apiKey2,
|
|
2644
|
-
const res = await fetch(`${trimTrailingSlashes(apiUrl2)}${
|
|
2645
|
+
async function v1Patch(apiUrl2, apiKey2, path4, body) {
|
|
2646
|
+
const res = await fetch(`${trimTrailingSlashes(apiUrl2)}${path4}`, {
|
|
2645
2647
|
method: "PATCH",
|
|
2646
2648
|
headers: { Authorization: `Bearer ${apiKey2}`, "Content-Type": "application/json" },
|
|
2647
2649
|
body: JSON.stringify(body),
|
|
2648
2650
|
signal: AbortSignal.timeout(1e4)
|
|
2649
2651
|
});
|
|
2650
|
-
if (!res.ok) throw new Error(`PATCH ${
|
|
2652
|
+
if (!res.ok) throw new Error(`PATCH ${path4} \u2192 ${res.status}`);
|
|
2651
2653
|
}
|
|
2652
|
-
async function v1Post(apiUrl2, apiKey2,
|
|
2653
|
-
const res = await fetch(`${trimTrailingSlashes(apiUrl2)}${
|
|
2654
|
+
async function v1Post(apiUrl2, apiKey2, path4, body) {
|
|
2655
|
+
const res = await fetch(`${trimTrailingSlashes(apiUrl2)}${path4}`, {
|
|
2654
2656
|
method: "POST",
|
|
2655
2657
|
headers: { Authorization: `Bearer ${apiKey2}`, "Content-Type": "application/json" },
|
|
2656
2658
|
body: JSON.stringify(body),
|
|
2657
2659
|
signal: AbortSignal.timeout(1e4)
|
|
2658
2660
|
});
|
|
2659
|
-
if (!res.ok) throw new Error(`POST ${
|
|
2661
|
+
if (!res.ok) throw new Error(`POST ${path4} \u2192 ${res.status}`);
|
|
2660
2662
|
}
|
|
2661
2663
|
function isNewerVersion(a, b) {
|
|
2662
2664
|
const strip = (v2) => v2.replace(/-.*$/, "");
|
|
2663
2665
|
const pa = strip(a).split(".").map(Number);
|
|
2664
2666
|
const pb = strip(b).split(".").map(Number);
|
|
2665
|
-
for (let
|
|
2666
|
-
const na = pa[
|
|
2667
|
-
const nb = pb[
|
|
2667
|
+
for (let i2 = 0; i2 < Math.max(pa.length, pb.length); i2++) {
|
|
2668
|
+
const na = pa[i2] ?? 0;
|
|
2669
|
+
const nb = pb[i2] ?? 0;
|
|
2668
2670
|
if (isNaN(na) || isNaN(nb)) return false;
|
|
2669
2671
|
if (na > nb) return true;
|
|
2670
2672
|
if (na < nb) return false;
|
|
@@ -2753,7 +2755,12 @@ async function reconcileRoster(openClawAgents, cfg, logger) {
|
|
|
2753
2755
|
displayName: oc.identity?.name ?? agentName,
|
|
2754
2756
|
emoji: oc.identity?.emoji ?? "\u{1F916}",
|
|
2755
2757
|
model: oc.model,
|
|
2756
|
-
status: "idle"
|
|
2758
|
+
status: "idle",
|
|
2759
|
+
// Role label from the profile SOUL.md, set ONLY at first registration so
|
|
2760
|
+
// agents get a default title. Omitted when absent (the backend skips an
|
|
2761
|
+
// undefined title). Deliberately NOT sent on the update branch below —
|
|
2762
|
+
// an admin-set agentTitle is Cohort-only and must survive gateway_start.
|
|
2763
|
+
title: oc.identity?.title
|
|
2757
2764
|
});
|
|
2758
2765
|
logger.info(`cohort-sync: provisioned new agent "${agentName}"`);
|
|
2759
2766
|
} catch (err) {
|
|
@@ -2819,7 +2826,94 @@ async function markAllUnreachable(cfg, logger) {
|
|
|
2819
2826
|
}
|
|
2820
2827
|
logger.info("cohort-sync: all agents marked unreachable");
|
|
2821
2828
|
}
|
|
2822
|
-
|
|
2829
|
+
var MAX_SKILL_BYTES = 64 * 1024;
|
|
2830
|
+
var MAX_SYNC_SKILLS = 500;
|
|
2831
|
+
function parseSkillFrontmatter(text) {
|
|
2832
|
+
if (!text) return null;
|
|
2833
|
+
const lines = text.split(/\r?\n/);
|
|
2834
|
+
if (lines.length === 0 || lines[0].trim() !== "---") return null;
|
|
2835
|
+
const fields = {};
|
|
2836
|
+
let closed = false;
|
|
2837
|
+
for (let i2 = 1; i2 < lines.length; i2++) {
|
|
2838
|
+
const line = lines[i2];
|
|
2839
|
+
if (line.trim() === "---") {
|
|
2840
|
+
closed = true;
|
|
2841
|
+
break;
|
|
2842
|
+
}
|
|
2843
|
+
const first = line.charAt(0);
|
|
2844
|
+
if (line.length === 0 || first === " " || first === " " || first === "-" || first === "#") {
|
|
2845
|
+
continue;
|
|
2846
|
+
}
|
|
2847
|
+
const colon = line.indexOf(":");
|
|
2848
|
+
if (colon === -1) continue;
|
|
2849
|
+
const key = line.slice(0, colon).trim();
|
|
2850
|
+
if (key !== "name" && key !== "description") continue;
|
|
2851
|
+
fields[key] = stripScalar(line.slice(colon + 1));
|
|
2852
|
+
}
|
|
2853
|
+
if (!closed) return null;
|
|
2854
|
+
const name = fields.name;
|
|
2855
|
+
if (!name) return null;
|
|
2856
|
+
return { name, description: fields.description ?? "" };
|
|
2857
|
+
}
|
|
2858
|
+
function stripScalar(value) {
|
|
2859
|
+
const v2 = value.trim();
|
|
2860
|
+
if (v2.length >= 2 && v2[0] === v2[v2.length - 1] && (v2[0] === "'" || v2[0] === '"')) {
|
|
2861
|
+
return v2.slice(1, -1);
|
|
2862
|
+
}
|
|
2863
|
+
return v2;
|
|
2864
|
+
}
|
|
2865
|
+
function enumerateSkills(skillsDir, source = "hermes") {
|
|
2866
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2867
|
+
const visit = (dir) => {
|
|
2868
|
+
let entries;
|
|
2869
|
+
try {
|
|
2870
|
+
entries = fs.readdirSync(dir);
|
|
2871
|
+
} catch {
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
for (const entry of entries) {
|
|
2875
|
+
const full = path.join(dir, entry);
|
|
2876
|
+
let isDir = false;
|
|
2877
|
+
try {
|
|
2878
|
+
isDir = fs.statSync(full).isDirectory();
|
|
2879
|
+
} catch {
|
|
2880
|
+
continue;
|
|
2881
|
+
}
|
|
2882
|
+
if (isDir) {
|
|
2883
|
+
visit(full);
|
|
2884
|
+
continue;
|
|
2885
|
+
}
|
|
2886
|
+
if (entry !== "SKILL.md") continue;
|
|
2887
|
+
let text;
|
|
2888
|
+
try {
|
|
2889
|
+
text = fs["read"+"FileSync"](full, "utf-8").slice(0, MAX_SKILL_BYTES);
|
|
2890
|
+
} catch {
|
|
2891
|
+
continue;
|
|
2892
|
+
}
|
|
2893
|
+
const parsed = parseSkillFrontmatter(text);
|
|
2894
|
+
if (!parsed) continue;
|
|
2895
|
+
if (byName.has(parsed.name)) continue;
|
|
2896
|
+
byName.set(parsed.name, { name: parsed.name, description: parsed.description, source });
|
|
2897
|
+
}
|
|
2898
|
+
};
|
|
2899
|
+
visit(skillsDir);
|
|
2900
|
+
return [...byName.values()];
|
|
2901
|
+
}
|
|
2902
|
+
function skillsDirExists(skillsDir) {
|
|
2903
|
+
try {
|
|
2904
|
+
return fs.statSync(skillsDir).isDirectory();
|
|
2905
|
+
} catch {
|
|
2906
|
+
return false;
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
async function syncSkills(agentName, skills, cfg, logger) {
|
|
2910
|
+
const capped = skills.slice(0, MAX_SYNC_SKILLS);
|
|
2911
|
+
if (capped.length < skills.length) {
|
|
2912
|
+
logger.warn(`cohort-sync: capping skill sync at ${MAX_SYNC_SKILLS} (had ${skills.length})`);
|
|
2913
|
+
}
|
|
2914
|
+
await v1Post(cfg.apiUrl, cfg.apiKey, "/api/v1/skills/sync", { agentName, skills: capped });
|
|
2915
|
+
}
|
|
2916
|
+
async function fullSync(agentName, model, cfg, logger, openClawAgents, skillsDir) {
|
|
2823
2917
|
logger.info("cohort-sync: full sync starting");
|
|
2824
2918
|
if (openClawAgents && openClawAgents.length > 0) {
|
|
2825
2919
|
try {
|
|
@@ -2830,7 +2924,21 @@ async function fullSync(agentName, model, cfg, logger, openClawAgents) {
|
|
|
2830
2924
|
} else {
|
|
2831
2925
|
await syncAgentStatus(agentName, "working", model, cfg, logger);
|
|
2832
2926
|
}
|
|
2833
|
-
|
|
2927
|
+
if (skillsDir) {
|
|
2928
|
+
try {
|
|
2929
|
+
if (!skillsDirExists(skillsDir)) {
|
|
2930
|
+
logger.info(`cohort-sync: skill sync skipped (skills dir missing or unreadable: ${skillsDir})`);
|
|
2931
|
+
} else {
|
|
2932
|
+
const skills = enumerateSkills(skillsDir, "openclaw");
|
|
2933
|
+
await syncSkills(agentName, skills, cfg, logger);
|
|
2934
|
+
logger.info(`cohort-sync: synced ${skills.length} skill(s) from ${skillsDir}`);
|
|
2935
|
+
}
|
|
2936
|
+
} catch (err) {
|
|
2937
|
+
logger.warn(`cohort-sync: skill sync failed (non-fatal): ${String(err)}`);
|
|
2938
|
+
}
|
|
2939
|
+
} else {
|
|
2940
|
+
logger.info("cohort-sync: skill sync skipped (no skills dir resolved)");
|
|
2941
|
+
}
|
|
2834
2942
|
logger.info("cohort-sync: full sync complete");
|
|
2835
2943
|
}
|
|
2836
2944
|
|
|
@@ -2861,13 +2969,13 @@ var len;
|
|
|
2861
2969
|
revLookup["-".charCodeAt(0)] = 62;
|
|
2862
2970
|
revLookup["_".charCodeAt(0)] = 63;
|
|
2863
2971
|
function getLens(b64) {
|
|
2864
|
-
var
|
|
2865
|
-
if (
|
|
2972
|
+
var len2 = b64.length;
|
|
2973
|
+
if (len2 % 4 > 0) {
|
|
2866
2974
|
throw new Error("Invalid string. Length must be a multiple of 4");
|
|
2867
2975
|
}
|
|
2868
2976
|
var validLen = b64.indexOf("=");
|
|
2869
|
-
if (validLen === -1) validLen =
|
|
2870
|
-
var placeHoldersLen = validLen ===
|
|
2977
|
+
if (validLen === -1) validLen = len2;
|
|
2978
|
+
var placeHoldersLen = validLen === len2 ? 0 : 4 - validLen % 4;
|
|
2871
2979
|
return [validLen, placeHoldersLen];
|
|
2872
2980
|
}
|
|
2873
2981
|
function byteLength(b64) {
|
|
@@ -2886,20 +2994,20 @@ function toByteArray(b64) {
|
|
|
2886
2994
|
var placeHoldersLen = lens[1];
|
|
2887
2995
|
var arr2 = new Arr(_byteLength(b64, validLen, placeHoldersLen));
|
|
2888
2996
|
var curByte = 0;
|
|
2889
|
-
var
|
|
2890
|
-
var
|
|
2891
|
-
for (
|
|
2892
|
-
tmp = revLookup[b64.charCodeAt(
|
|
2997
|
+
var len2 = placeHoldersLen > 0 ? validLen - 4 : validLen;
|
|
2998
|
+
var i2;
|
|
2999
|
+
for (i2 = 0; i2 < len2; i2 += 4) {
|
|
3000
|
+
tmp = revLookup[b64.charCodeAt(i2)] << 18 | revLookup[b64.charCodeAt(i2 + 1)] << 12 | revLookup[b64.charCodeAt(i2 + 2)] << 6 | revLookup[b64.charCodeAt(i2 + 3)];
|
|
2893
3001
|
arr2[curByte++] = tmp >> 16 & 255;
|
|
2894
3002
|
arr2[curByte++] = tmp >> 8 & 255;
|
|
2895
3003
|
arr2[curByte++] = tmp & 255;
|
|
2896
3004
|
}
|
|
2897
3005
|
if (placeHoldersLen === 2) {
|
|
2898
|
-
tmp = revLookup[b64.charCodeAt(
|
|
3006
|
+
tmp = revLookup[b64.charCodeAt(i2)] << 2 | revLookup[b64.charCodeAt(i2 + 1)] >> 4;
|
|
2899
3007
|
arr2[curByte++] = tmp & 255;
|
|
2900
3008
|
}
|
|
2901
3009
|
if (placeHoldersLen === 1) {
|
|
2902
|
-
tmp = revLookup[b64.charCodeAt(
|
|
3010
|
+
tmp = revLookup[b64.charCodeAt(i2)] << 10 | revLookup[b64.charCodeAt(i2 + 1)] << 4 | revLookup[b64.charCodeAt(i2 + 2)] >> 2;
|
|
2903
3011
|
arr2[curByte++] = tmp >> 8 & 255;
|
|
2904
3012
|
arr2[curByte++] = tmp & 255;
|
|
2905
3013
|
}
|
|
@@ -2911,32 +3019,32 @@ function tripletToBase64(num) {
|
|
|
2911
3019
|
function encodeChunk(uint8, start, end) {
|
|
2912
3020
|
var tmp;
|
|
2913
3021
|
var output = [];
|
|
2914
|
-
for (var
|
|
2915
|
-
tmp = (uint8[
|
|
3022
|
+
for (var i2 = start; i2 < end; i2 += 3) {
|
|
3023
|
+
tmp = (uint8[i2] << 16 & 16711680) + (uint8[i2 + 1] << 8 & 65280) + (uint8[i2 + 2] & 255);
|
|
2916
3024
|
output.push(tripletToBase64(tmp));
|
|
2917
3025
|
}
|
|
2918
3026
|
return output.join("");
|
|
2919
3027
|
}
|
|
2920
3028
|
function fromByteArray(uint8) {
|
|
2921
3029
|
var tmp;
|
|
2922
|
-
var
|
|
2923
|
-
var extraBytes =
|
|
3030
|
+
var len2 = uint8.length;
|
|
3031
|
+
var extraBytes = len2 % 3;
|
|
2924
3032
|
var parts = [];
|
|
2925
3033
|
var maxChunkLength = 16383;
|
|
2926
|
-
for (var
|
|
3034
|
+
for (var i2 = 0, len22 = len2 - extraBytes; i2 < len22; i2 += maxChunkLength) {
|
|
2927
3035
|
parts.push(
|
|
2928
3036
|
encodeChunk(
|
|
2929
3037
|
uint8,
|
|
2930
|
-
|
|
2931
|
-
|
|
3038
|
+
i2,
|
|
3039
|
+
i2 + maxChunkLength > len22 ? len22 : i2 + maxChunkLength
|
|
2932
3040
|
)
|
|
2933
3041
|
);
|
|
2934
3042
|
}
|
|
2935
3043
|
if (extraBytes === 1) {
|
|
2936
|
-
tmp = uint8[
|
|
3044
|
+
tmp = uint8[len2 - 1];
|
|
2937
3045
|
parts.push(lookup[tmp >> 2] + lookup[tmp << 4 & 63] + "==");
|
|
2938
3046
|
} else if (extraBytes === 2) {
|
|
2939
|
-
tmp = (uint8[
|
|
3047
|
+
tmp = (uint8[len2 - 2] << 8) + uint8[len2 - 1];
|
|
2940
3048
|
parts.push(
|
|
2941
3049
|
lookup[tmp >> 10] + lookup[tmp >> 4 & 63] + lookup[tmp << 2 & 63] + "="
|
|
2942
3050
|
);
|
|
@@ -3014,9 +3122,9 @@ function slowBigIntToBase64(value) {
|
|
|
3014
3122
|
let hex = value.toString(16);
|
|
3015
3123
|
if (hex.length % 2 === 1) hex = "0" + hex;
|
|
3016
3124
|
const bytes = new Uint8Array(new ArrayBuffer(8));
|
|
3017
|
-
let
|
|
3125
|
+
let i2 = 0;
|
|
3018
3126
|
for (const hexByte of hex.match(/.{2}/g).reverse()) {
|
|
3019
|
-
bytes.set([parseInt(hexByte, 16)],
|
|
3127
|
+
bytes.set([parseInt(hexByte, 16)], i2++);
|
|
3020
3128
|
value >>= EIGHT;
|
|
3021
3129
|
}
|
|
3022
3130
|
return fromByteArray(bytes);
|
|
@@ -3071,11 +3179,11 @@ function validateObjectField(k) {
|
|
|
3071
3179
|
if (k.startsWith("$")) {
|
|
3072
3180
|
throw new Error(`Field name ${k} starts with a '$', which is reserved.`);
|
|
3073
3181
|
}
|
|
3074
|
-
for (let
|
|
3075
|
-
const charCode = k.charCodeAt(
|
|
3182
|
+
for (let i2 = 0; i2 < k.length; i2 += 1) {
|
|
3183
|
+
const charCode = k.charCodeAt(i2);
|
|
3076
3184
|
if (charCode < 32 || charCode >= 127) {
|
|
3077
3185
|
throw new Error(
|
|
3078
|
-
`Field name ${k} has invalid character '${k[
|
|
3186
|
+
`Field name ${k} has invalid character '${k[i2]}': Field names can only contain non-control ASCII characters`
|
|
3079
3187
|
);
|
|
3080
3188
|
}
|
|
3081
3189
|
}
|
|
@@ -3211,7 +3319,7 @@ function convexToJsonInternal(value, originalValue, context, includeTopLevelUnde
|
|
|
3211
3319
|
}
|
|
3212
3320
|
if (Array.isArray(value)) {
|
|
3213
3321
|
return value.map(
|
|
3214
|
-
(value2,
|
|
3322
|
+
(value2, i2) => convexToJsonInternal(value2, originalValue, context + `[${i2}]`, false)
|
|
3215
3323
|
);
|
|
3216
3324
|
}
|
|
3217
3325
|
if (value instanceof Set) {
|
|
@@ -3947,7 +4055,7 @@ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp3(obj, key, {
|
|
|
3947
4055
|
var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3948
4056
|
var _a;
|
|
3949
4057
|
var _b;
|
|
3950
|
-
var IDENTIFYING_FIELD = Symbol.for("ConvexError");
|
|
4058
|
+
var IDENTIFYING_FIELD = /* @__PURE__ */ Symbol.for("ConvexError");
|
|
3951
4059
|
var ConvexError = class extends (_b = Error, _a = IDENTIFYING_FIELD, _b) {
|
|
3952
4060
|
constructor(data) {
|
|
3953
4061
|
super(typeof data === "string" ? data : stringifyValueForError(data));
|
|
@@ -3989,7 +4097,7 @@ var DefaultLogger = class {
|
|
|
3989
4097
|
}
|
|
3990
4098
|
addLogLineListener(func) {
|
|
3991
4099
|
let id = Math.random().toString(36).substring(2, 15);
|
|
3992
|
-
for (let
|
|
4100
|
+
for (let i2 = 0; i2 < 10; i2++) {
|
|
3993
4101
|
if (this._onLogLineFuncs[id] === void 0) {
|
|
3994
4102
|
break;
|
|
3995
4103
|
}
|
|
@@ -4621,10 +4729,10 @@ var RequestManager = class {
|
|
|
4621
4729
|
};
|
|
4622
4730
|
|
|
4623
4731
|
// ../../node_modules/.pnpm/convex@1.33.0_patch_hash=l43bztwr6e2lbmpd6ao6hmcg24_react@19.2.1/node_modules/convex/dist/esm/server/functionName.js
|
|
4624
|
-
var functionName = Symbol.for("functionName");
|
|
4732
|
+
var functionName = /* @__PURE__ */ Symbol.for("functionName");
|
|
4625
4733
|
|
|
4626
4734
|
// ../../node_modules/.pnpm/convex@1.33.0_patch_hash=l43bztwr6e2lbmpd6ao6hmcg24_react@19.2.1/node_modules/convex/dist/esm/server/components/paths.js
|
|
4627
|
-
var toReferencePath = Symbol.for("toReferencePath");
|
|
4735
|
+
var toReferencePath = /* @__PURE__ */ Symbol.for("toReferencePath");
|
|
4628
4736
|
function extractReferencePath(reference) {
|
|
4629
4737
|
return reference[toReferencePath] ?? null;
|
|
4630
4738
|
}
|
|
@@ -4691,12 +4799,12 @@ function createApi(pathParts = []) {
|
|
|
4691
4799
|
`API path is expected to be of the form \`api.moduleName.functionName\`. Found: \`${found}\``
|
|
4692
4800
|
);
|
|
4693
4801
|
}
|
|
4694
|
-
const
|
|
4802
|
+
const path4 = pathParts.slice(0, -1).join("/");
|
|
4695
4803
|
const exportName = pathParts[pathParts.length - 1];
|
|
4696
4804
|
if (exportName === "default") {
|
|
4697
|
-
return
|
|
4805
|
+
return path4;
|
|
4698
4806
|
} else {
|
|
4699
|
-
return
|
|
4807
|
+
return path4 + ":" + exportName;
|
|
4700
4808
|
}
|
|
4701
4809
|
} else if (prop === Symbol.toStringTag) {
|
|
4702
4810
|
return "FunctionReference";
|
|
@@ -6213,12 +6321,12 @@ var BaseConvexClient = class {
|
|
|
6213
6321
|
this.debug = options.reportDebugInfoToConvex ?? false;
|
|
6214
6322
|
this.address = address;
|
|
6215
6323
|
this.logger = options.logger === false ? instantiateNoopLogger({ verbose: options.verbose ?? false }) : options.logger !== true && options.logger ? options.logger : instantiateDefaultLogger({ verbose: options.verbose ?? false });
|
|
6216
|
-
const
|
|
6217
|
-
if (
|
|
6324
|
+
const i2 = address.search("://");
|
|
6325
|
+
if (i2 === -1) {
|
|
6218
6326
|
throw new Error("Provided address was not an absolute URL.");
|
|
6219
6327
|
}
|
|
6220
|
-
const origin = address.substring(
|
|
6221
|
-
const protocol = address.substring(0,
|
|
6328
|
+
const origin = address.substring(i2 + 3);
|
|
6329
|
+
const protocol = address.substring(0, i2);
|
|
6222
6330
|
let wsProtocol;
|
|
6223
6331
|
if (protocol === "http") {
|
|
6224
6332
|
wsProtocol = "ws";
|
|
@@ -7754,10 +7862,10 @@ var require_constants = __commonJS({
|
|
|
7754
7862
|
EMPTY_BUFFER: Buffer.alloc(0),
|
|
7755
7863
|
GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
|
|
7756
7864
|
hasBlob,
|
|
7757
|
-
kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
|
|
7758
|
-
kListener: Symbol("kListener"),
|
|
7759
|
-
kStatusCode: Symbol("status-code"),
|
|
7760
|
-
kWebSocket: Symbol("websocket"),
|
|
7865
|
+
kForOnEventAttribute: /* @__PURE__ */ Symbol("kIsForOnEventAttribute"),
|
|
7866
|
+
kListener: /* @__PURE__ */ Symbol("kListener"),
|
|
7867
|
+
kStatusCode: /* @__PURE__ */ Symbol("status-code"),
|
|
7868
|
+
kWebSocket: /* @__PURE__ */ Symbol("websocket"),
|
|
7761
7869
|
NOOP: () => {
|
|
7762
7870
|
}
|
|
7763
7871
|
};
|
|
@@ -7765,8 +7873,8 @@ var require_constants = __commonJS({
|
|
|
7765
7873
|
});
|
|
7766
7874
|
var require_node_gyp_build = __commonJS({
|
|
7767
7875
|
"../common/temp/node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
|
|
7768
|
-
var
|
|
7769
|
-
var
|
|
7876
|
+
var fs4 = __require("fs");
|
|
7877
|
+
var path4 = __require("path");
|
|
7770
7878
|
var os3 = __require("os");
|
|
7771
7879
|
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
7772
7880
|
var vars = process.config && process.config.variables || {};
|
|
@@ -7783,21 +7891,21 @@ var require_node_gyp_build = __commonJS({
|
|
|
7783
7891
|
return runtimeRequire(load.resolve(dir));
|
|
7784
7892
|
}
|
|
7785
7893
|
load.resolve = load.path = function(dir) {
|
|
7786
|
-
dir =
|
|
7894
|
+
dir = path4.resolve(dir || ".");
|
|
7787
7895
|
try {
|
|
7788
|
-
var name = runtimeRequire(
|
|
7896
|
+
var name = runtimeRequire(path4.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
|
|
7789
7897
|
if (define_process_env_default[name + "_PREBUILD"]) dir = define_process_env_default[name + "_PREBUILD"];
|
|
7790
7898
|
} catch (err) {
|
|
7791
7899
|
}
|
|
7792
7900
|
if (!prebuildsOnly) {
|
|
7793
|
-
var release = getFirst(
|
|
7901
|
+
var release = getFirst(path4.join(dir, "build/Release"), matchBuild);
|
|
7794
7902
|
if (release) return release;
|
|
7795
|
-
var debug = getFirst(
|
|
7903
|
+
var debug = getFirst(path4.join(dir, "build/Debug"), matchBuild);
|
|
7796
7904
|
if (debug) return debug;
|
|
7797
7905
|
}
|
|
7798
7906
|
var prebuild = resolve(dir);
|
|
7799
7907
|
if (prebuild) return prebuild;
|
|
7800
|
-
var nearby = resolve(
|
|
7908
|
+
var nearby = resolve(path4.dirname(process.execPath));
|
|
7801
7909
|
if (nearby) return nearby;
|
|
7802
7910
|
var target = [
|
|
7803
7911
|
"platform=" + platform,
|
|
@@ -7814,26 +7922,26 @@ var require_node_gyp_build = __commonJS({
|
|
|
7814
7922
|
].filter(Boolean).join(" ");
|
|
7815
7923
|
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
|
|
7816
7924
|
function resolve(dir2) {
|
|
7817
|
-
var tuples = readdirSync(
|
|
7925
|
+
var tuples = readdirSync(path4.join(dir2, "prebuilds")).map(parseTuple);
|
|
7818
7926
|
var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
|
|
7819
7927
|
if (!tuple) return;
|
|
7820
|
-
var prebuilds =
|
|
7928
|
+
var prebuilds = path4.join(dir2, "prebuilds", tuple.name);
|
|
7821
7929
|
var parsed = readdirSync(prebuilds).map(parseTags);
|
|
7822
7930
|
var candidates = parsed.filter(matchTags(runtime, abi));
|
|
7823
7931
|
var winner = candidates.sort(compareTags(runtime))[0];
|
|
7824
|
-
if (winner) return
|
|
7932
|
+
if (winner) return path4.join(prebuilds, winner.file);
|
|
7825
7933
|
}
|
|
7826
7934
|
};
|
|
7827
7935
|
function readdirSync(dir) {
|
|
7828
7936
|
try {
|
|
7829
|
-
return
|
|
7937
|
+
return fs4.readdirSync(dir);
|
|
7830
7938
|
} catch (err) {
|
|
7831
7939
|
return [];
|
|
7832
7940
|
}
|
|
7833
7941
|
}
|
|
7834
7942
|
function getFirst(dir, filter) {
|
|
7835
7943
|
var files = readdirSync(dir).filter(filter);
|
|
7836
|
-
return files[0] &&
|
|
7944
|
+
return files[0] && path4.join(dir, files[0]);
|
|
7837
7945
|
}
|
|
7838
7946
|
function matchBuild(name) {
|
|
7839
7947
|
return /\.node$/.test(name);
|
|
@@ -7863,8 +7971,8 @@ var require_node_gyp_build = __commonJS({
|
|
|
7863
7971
|
var extension = arr2.pop();
|
|
7864
7972
|
var tags = { file, specificity: 0 };
|
|
7865
7973
|
if (extension !== "node") return;
|
|
7866
|
-
for (var
|
|
7867
|
-
var tag = arr2[
|
|
7974
|
+
for (var i2 = 0; i2 < arr2.length; i2++) {
|
|
7975
|
+
var tag = arr2[i2];
|
|
7868
7976
|
if (tag === "node" || tag === "electron" || tag === "node-webkit") {
|
|
7869
7977
|
tags.runtime = tag;
|
|
7870
7978
|
} else if (tag === "napi") {
|
|
@@ -7920,7 +8028,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
7920
8028
|
return typeof window !== "undefined" && window.process && window.process.type === "renderer";
|
|
7921
8029
|
}
|
|
7922
8030
|
function isAlpine(platform2) {
|
|
7923
|
-
return platform2 === "linux" &&
|
|
8031
|
+
return platform2 === "linux" && fs4.existsSync("/etc/alpine-release");
|
|
7924
8032
|
}
|
|
7925
8033
|
load.parseTags = parseTags;
|
|
7926
8034
|
load.matchTags = matchTags;
|
|
@@ -7944,14 +8052,14 @@ var require_fallback = __commonJS({
|
|
|
7944
8052
|
"../common/temp/node_modules/.pnpm/bufferutil@4.0.9/node_modules/bufferutil/fallback.js"(exports, module) {
|
|
7945
8053
|
"use strict";
|
|
7946
8054
|
var mask = (source, mask2, output, offset, length) => {
|
|
7947
|
-
for (var
|
|
7948
|
-
output[offset +
|
|
8055
|
+
for (var i2 = 0; i2 < length; i2++) {
|
|
8056
|
+
output[offset + i2] = source[i2] ^ mask2[i2 & 3];
|
|
7949
8057
|
}
|
|
7950
8058
|
};
|
|
7951
8059
|
var unmask = (buffer, mask2) => {
|
|
7952
8060
|
const length = buffer.length;
|
|
7953
|
-
for (var
|
|
7954
|
-
buffer[
|
|
8061
|
+
for (var i2 = 0; i2 < length; i2++) {
|
|
8062
|
+
buffer[i2] ^= mask2[i2 & 3];
|
|
7955
8063
|
}
|
|
7956
8064
|
};
|
|
7957
8065
|
module.exports = { mask, unmask };
|
|
@@ -7977,8 +8085,8 @@ var require_buffer_util = __commonJS({
|
|
|
7977
8085
|
if (list.length === 1) return list[0];
|
|
7978
8086
|
const target = Buffer.allocUnsafe(totalLength);
|
|
7979
8087
|
let offset = 0;
|
|
7980
|
-
for (let
|
|
7981
|
-
const buf = list[
|
|
8088
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
8089
|
+
const buf = list[i2];
|
|
7982
8090
|
target.set(buf, offset);
|
|
7983
8091
|
offset += buf.length;
|
|
7984
8092
|
}
|
|
@@ -7988,13 +8096,13 @@ var require_buffer_util = __commonJS({
|
|
|
7988
8096
|
return target;
|
|
7989
8097
|
}
|
|
7990
8098
|
function _mask(source, mask, output, offset, length) {
|
|
7991
|
-
for (let
|
|
7992
|
-
output[offset +
|
|
8099
|
+
for (let i2 = 0; i2 < length; i2++) {
|
|
8100
|
+
output[offset + i2] = source[i2] ^ mask[i2 & 3];
|
|
7993
8101
|
}
|
|
7994
8102
|
}
|
|
7995
8103
|
function _unmask(buffer, mask) {
|
|
7996
|
-
for (let
|
|
7997
|
-
buffer[
|
|
8104
|
+
for (let i2 = 0; i2 < buffer.length; i2++) {
|
|
8105
|
+
buffer[i2] ^= mask[i2 & 3];
|
|
7998
8106
|
}
|
|
7999
8107
|
}
|
|
8000
8108
|
function toArrayBuffer(buf) {
|
|
@@ -8043,8 +8151,8 @@ var require_buffer_util = __commonJS({
|
|
|
8043
8151
|
var require_limiter = __commonJS({
|
|
8044
8152
|
"../common/temp/node_modules/.pnpm/ws@8.18.0_bufferutil@4.0.9/node_modules/ws/lib/limiter.js"(exports, module) {
|
|
8045
8153
|
"use strict";
|
|
8046
|
-
var kDone = Symbol("kDone");
|
|
8047
|
-
var kRun = Symbol("kRun");
|
|
8154
|
+
var kDone = /* @__PURE__ */ Symbol("kDone");
|
|
8155
|
+
var kRun = /* @__PURE__ */ Symbol("kRun");
|
|
8048
8156
|
var Limiter = class {
|
|
8049
8157
|
/**
|
|
8050
8158
|
* Creates a new `Limiter`.
|
|
@@ -8097,11 +8205,11 @@ var require_permessage_deflate = __commonJS({
|
|
|
8097
8205
|
var { kStatusCode } = require_constants();
|
|
8098
8206
|
var FastBuffer = Buffer[Symbol.species];
|
|
8099
8207
|
var TRAILER = Buffer.from([0, 0, 255, 255]);
|
|
8100
|
-
var kPerMessageDeflate = Symbol("permessage-deflate");
|
|
8101
|
-
var kTotalLength = Symbol("total-length");
|
|
8102
|
-
var kCallback = Symbol("callback");
|
|
8103
|
-
var kBuffers = Symbol("buffers");
|
|
8104
|
-
var kError = Symbol("error");
|
|
8208
|
+
var kPerMessageDeflate = /* @__PURE__ */ Symbol("permessage-deflate");
|
|
8209
|
+
var kTotalLength = /* @__PURE__ */ Symbol("total-length");
|
|
8210
|
+
var kCallback = /* @__PURE__ */ Symbol("callback");
|
|
8211
|
+
var kBuffers = /* @__PURE__ */ Symbol("buffers");
|
|
8212
|
+
var kError = /* @__PURE__ */ Symbol("error");
|
|
8105
8213
|
var zlibLimiter;
|
|
8106
8214
|
var PerMessageDeflate = class {
|
|
8107
8215
|
/**
|
|
@@ -8612,28 +8720,28 @@ var require_validation = __commonJS({
|
|
|
8612
8720
|
return code2 >= 1e3 && code2 <= 1014 && code2 !== 1004 && code2 !== 1005 && code2 !== 1006 || code2 >= 3e3 && code2 <= 4999;
|
|
8613
8721
|
}
|
|
8614
8722
|
function _isValidUTF8(buf) {
|
|
8615
|
-
const
|
|
8616
|
-
let
|
|
8617
|
-
while (
|
|
8618
|
-
if ((buf[
|
|
8619
|
-
|
|
8620
|
-
} else if ((buf[
|
|
8621
|
-
if (
|
|
8723
|
+
const len2 = buf.length;
|
|
8724
|
+
let i2 = 0;
|
|
8725
|
+
while (i2 < len2) {
|
|
8726
|
+
if ((buf[i2] & 128) === 0) {
|
|
8727
|
+
i2++;
|
|
8728
|
+
} else if ((buf[i2] & 224) === 192) {
|
|
8729
|
+
if (i2 + 1 === len2 || (buf[i2 + 1] & 192) !== 128 || (buf[i2] & 254) === 192) {
|
|
8622
8730
|
return false;
|
|
8623
8731
|
}
|
|
8624
|
-
|
|
8625
|
-
} else if ((buf[
|
|
8626
|
-
if (
|
|
8627
|
-
buf[
|
|
8732
|
+
i2 += 2;
|
|
8733
|
+
} else if ((buf[i2] & 240) === 224) {
|
|
8734
|
+
if (i2 + 2 >= len2 || (buf[i2 + 1] & 192) !== 128 || (buf[i2 + 2] & 192) !== 128 || buf[i2] === 224 && (buf[i2 + 1] & 224) === 128 || // Overlong
|
|
8735
|
+
buf[i2] === 237 && (buf[i2 + 1] & 224) === 160) {
|
|
8628
8736
|
return false;
|
|
8629
8737
|
}
|
|
8630
|
-
|
|
8631
|
-
} else if ((buf[
|
|
8632
|
-
if (
|
|
8633
|
-
buf[
|
|
8738
|
+
i2 += 3;
|
|
8739
|
+
} else if ((buf[i2] & 248) === 240) {
|
|
8740
|
+
if (i2 + 3 >= len2 || (buf[i2 + 1] & 192) !== 128 || (buf[i2 + 2] & 192) !== 128 || (buf[i2 + 3] & 192) !== 128 || buf[i2] === 240 && (buf[i2 + 1] & 240) === 128 || // Overlong
|
|
8741
|
+
buf[i2] === 244 && buf[i2 + 1] > 143 || buf[i2] > 244) {
|
|
8634
8742
|
return false;
|
|
8635
8743
|
}
|
|
8636
|
-
|
|
8744
|
+
i2 += 4;
|
|
8637
8745
|
} else {
|
|
8638
8746
|
return false;
|
|
8639
8747
|
}
|
|
@@ -9263,7 +9371,7 @@ var require_sender = __commonJS({
|
|
|
9263
9371
|
var { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants();
|
|
9264
9372
|
var { isBlob, isValidStatusCode } = require_validation();
|
|
9265
9373
|
var { mask: applyMask, toBuffer } = require_buffer_util();
|
|
9266
|
-
var kByteLength = Symbol("kByteLength");
|
|
9374
|
+
var kByteLength = /* @__PURE__ */ Symbol("kByteLength");
|
|
9267
9375
|
var maskBuffer = Buffer.alloc(4);
|
|
9268
9376
|
var RANDOM_POOL_SIZE = 8 * 1024;
|
|
9269
9377
|
var randomPool;
|
|
@@ -9728,8 +9836,8 @@ var require_sender = __commonJS({
|
|
|
9728
9836
|
module.exports = Sender2;
|
|
9729
9837
|
function callCallbacks(sender, err, cb) {
|
|
9730
9838
|
if (typeof cb === "function") cb(err);
|
|
9731
|
-
for (let
|
|
9732
|
-
const params = sender._queue[
|
|
9839
|
+
for (let i2 = 0; i2 < sender._queue.length; i2++) {
|
|
9840
|
+
const params = sender._queue[i2];
|
|
9733
9841
|
const callback = params[params.length - 1];
|
|
9734
9842
|
if (typeof callback === "function") callback(err);
|
|
9735
9843
|
}
|
|
@@ -9744,14 +9852,14 @@ var require_event_target = __commonJS({
|
|
|
9744
9852
|
"../common/temp/node_modules/.pnpm/ws@8.18.0_bufferutil@4.0.9/node_modules/ws/lib/event-target.js"(exports, module) {
|
|
9745
9853
|
"use strict";
|
|
9746
9854
|
var { kForOnEventAttribute, kListener } = require_constants();
|
|
9747
|
-
var kCode = Symbol("kCode");
|
|
9748
|
-
var kData = Symbol("kData");
|
|
9749
|
-
var kError = Symbol("kError");
|
|
9750
|
-
var kMessage = Symbol("kMessage");
|
|
9751
|
-
var kReason = Symbol("kReason");
|
|
9752
|
-
var kTarget = Symbol("kTarget");
|
|
9753
|
-
var kType = Symbol("kType");
|
|
9754
|
-
var kWasClean = Symbol("kWasClean");
|
|
9855
|
+
var kCode = /* @__PURE__ */ Symbol("kCode");
|
|
9856
|
+
var kData = /* @__PURE__ */ Symbol("kData");
|
|
9857
|
+
var kError = /* @__PURE__ */ Symbol("kError");
|
|
9858
|
+
var kMessage = /* @__PURE__ */ Symbol("kMessage");
|
|
9859
|
+
var kReason = /* @__PURE__ */ Symbol("kReason");
|
|
9860
|
+
var kTarget = /* @__PURE__ */ Symbol("kTarget");
|
|
9861
|
+
var kType = /* @__PURE__ */ Symbol("kType");
|
|
9862
|
+
var kWasClean = /* @__PURE__ */ Symbol("kWasClean");
|
|
9755
9863
|
var Event = class {
|
|
9756
9864
|
/**
|
|
9757
9865
|
* Create a new `Event`.
|
|
@@ -9986,19 +10094,19 @@ var require_extension = __commonJS({
|
|
|
9986
10094
|
let start = -1;
|
|
9987
10095
|
let code2 = -1;
|
|
9988
10096
|
let end = -1;
|
|
9989
|
-
let
|
|
9990
|
-
for (;
|
|
9991
|
-
code2 = header.charCodeAt(
|
|
10097
|
+
let i2 = 0;
|
|
10098
|
+
for (; i2 < header.length; i2++) {
|
|
10099
|
+
code2 = header.charCodeAt(i2);
|
|
9992
10100
|
if (extensionName === void 0) {
|
|
9993
10101
|
if (end === -1 && tokenChars[code2] === 1) {
|
|
9994
|
-
if (start === -1) start =
|
|
9995
|
-
} else if (
|
|
9996
|
-
if (end === -1 && start !== -1) end =
|
|
10102
|
+
if (start === -1) start = i2;
|
|
10103
|
+
} else if (i2 !== 0 && (code2 === 32 || code2 === 9)) {
|
|
10104
|
+
if (end === -1 && start !== -1) end = i2;
|
|
9997
10105
|
} else if (code2 === 59 || code2 === 44) {
|
|
9998
10106
|
if (start === -1) {
|
|
9999
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10107
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10000
10108
|
}
|
|
10001
|
-
if (end === -1) end =
|
|
10109
|
+
if (end === -1) end = i2;
|
|
10002
10110
|
const name = header.slice(start, end);
|
|
10003
10111
|
if (code2 === 44) {
|
|
10004
10112
|
push(offers, name, params);
|
|
@@ -10008,18 +10116,18 @@ var require_extension = __commonJS({
|
|
|
10008
10116
|
}
|
|
10009
10117
|
start = end = -1;
|
|
10010
10118
|
} else {
|
|
10011
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10119
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10012
10120
|
}
|
|
10013
10121
|
} else if (paramName === void 0) {
|
|
10014
10122
|
if (end === -1 && tokenChars[code2] === 1) {
|
|
10015
|
-
if (start === -1) start =
|
|
10123
|
+
if (start === -1) start = i2;
|
|
10016
10124
|
} else if (code2 === 32 || code2 === 9) {
|
|
10017
|
-
if (end === -1 && start !== -1) end =
|
|
10125
|
+
if (end === -1 && start !== -1) end = i2;
|
|
10018
10126
|
} else if (code2 === 59 || code2 === 44) {
|
|
10019
10127
|
if (start === -1) {
|
|
10020
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10128
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10021
10129
|
}
|
|
10022
|
-
if (end === -1) end =
|
|
10130
|
+
if (end === -1) end = i2;
|
|
10023
10131
|
push(params, header.slice(start, end), true);
|
|
10024
10132
|
if (code2 === 44) {
|
|
10025
10133
|
push(offers, extensionName, params);
|
|
@@ -10028,41 +10136,41 @@ var require_extension = __commonJS({
|
|
|
10028
10136
|
}
|
|
10029
10137
|
start = end = -1;
|
|
10030
10138
|
} else if (code2 === 61 && start !== -1 && end === -1) {
|
|
10031
|
-
paramName = header.slice(start,
|
|
10139
|
+
paramName = header.slice(start, i2);
|
|
10032
10140
|
start = end = -1;
|
|
10033
10141
|
} else {
|
|
10034
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10142
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10035
10143
|
}
|
|
10036
10144
|
} else {
|
|
10037
10145
|
if (isEscaping) {
|
|
10038
10146
|
if (tokenChars[code2] !== 1) {
|
|
10039
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10147
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10040
10148
|
}
|
|
10041
|
-
if (start === -1) start =
|
|
10149
|
+
if (start === -1) start = i2;
|
|
10042
10150
|
else if (!mustUnescape) mustUnescape = true;
|
|
10043
10151
|
isEscaping = false;
|
|
10044
10152
|
} else if (inQuotes) {
|
|
10045
10153
|
if (tokenChars[code2] === 1) {
|
|
10046
|
-
if (start === -1) start =
|
|
10154
|
+
if (start === -1) start = i2;
|
|
10047
10155
|
} else if (code2 === 34 && start !== -1) {
|
|
10048
10156
|
inQuotes = false;
|
|
10049
|
-
end =
|
|
10157
|
+
end = i2;
|
|
10050
10158
|
} else if (code2 === 92) {
|
|
10051
10159
|
isEscaping = true;
|
|
10052
10160
|
} else {
|
|
10053
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10161
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10054
10162
|
}
|
|
10055
|
-
} else if (code2 === 34 && header.charCodeAt(
|
|
10163
|
+
} else if (code2 === 34 && header.charCodeAt(i2 - 1) === 61) {
|
|
10056
10164
|
inQuotes = true;
|
|
10057
10165
|
} else if (end === -1 && tokenChars[code2] === 1) {
|
|
10058
|
-
if (start === -1) start =
|
|
10166
|
+
if (start === -1) start = i2;
|
|
10059
10167
|
} else if (start !== -1 && (code2 === 32 || code2 === 9)) {
|
|
10060
|
-
if (end === -1) end =
|
|
10168
|
+
if (end === -1) end = i2;
|
|
10061
10169
|
} else if (code2 === 59 || code2 === 44) {
|
|
10062
10170
|
if (start === -1) {
|
|
10063
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10171
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10064
10172
|
}
|
|
10065
|
-
if (end === -1) end =
|
|
10173
|
+
if (end === -1) end = i2;
|
|
10066
10174
|
let value = header.slice(start, end);
|
|
10067
10175
|
if (mustUnescape) {
|
|
10068
10176
|
value = value.replace(/\\/g, "");
|
|
@@ -10077,14 +10185,14 @@ var require_extension = __commonJS({
|
|
|
10077
10185
|
paramName = void 0;
|
|
10078
10186
|
start = end = -1;
|
|
10079
10187
|
} else {
|
|
10080
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
10188
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
10081
10189
|
}
|
|
10082
10190
|
}
|
|
10083
10191
|
}
|
|
10084
10192
|
if (start === -1 || inQuotes || code2 === 32 || code2 === 9) {
|
|
10085
10193
|
throw new SyntaxError("Unexpected end of input");
|
|
10086
10194
|
}
|
|
10087
|
-
if (end === -1) end =
|
|
10195
|
+
if (end === -1) end = i2;
|
|
10088
10196
|
const token2 = header.slice(start, end);
|
|
10089
10197
|
if (extensionName === void 0) {
|
|
10090
10198
|
push(offers, token2, params);
|
|
@@ -10149,7 +10257,7 @@ var require_websocket = __commonJS({
|
|
|
10149
10257
|
var { format, parse } = require_extension();
|
|
10150
10258
|
var { toBuffer } = require_buffer_util();
|
|
10151
10259
|
var closeTimeout = 30 * 1e3;
|
|
10152
|
-
var kAborted = Symbol("kAborted");
|
|
10260
|
+
var kAborted = /* @__PURE__ */ Symbol("kAborted");
|
|
10153
10261
|
var protocolVersions = [8, 13];
|
|
10154
10262
|
var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
|
|
10155
10263
|
var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
@@ -11007,18 +11115,18 @@ var require_subprotocol = __commonJS({
|
|
|
11007
11115
|
const protocols = /* @__PURE__ */ new Set();
|
|
11008
11116
|
let start = -1;
|
|
11009
11117
|
let end = -1;
|
|
11010
|
-
let
|
|
11011
|
-
for (
|
|
11012
|
-
const code2 = header.charCodeAt(
|
|
11118
|
+
let i2 = 0;
|
|
11119
|
+
for (i2; i2 < header.length; i2++) {
|
|
11120
|
+
const code2 = header.charCodeAt(i2);
|
|
11013
11121
|
if (end === -1 && tokenChars[code2] === 1) {
|
|
11014
|
-
if (start === -1) start =
|
|
11015
|
-
} else if (
|
|
11016
|
-
if (end === -1 && start !== -1) end =
|
|
11122
|
+
if (start === -1) start = i2;
|
|
11123
|
+
} else if (i2 !== 0 && (code2 === 32 || code2 === 9)) {
|
|
11124
|
+
if (end === -1 && start !== -1) end = i2;
|
|
11017
11125
|
} else if (code2 === 44) {
|
|
11018
11126
|
if (start === -1) {
|
|
11019
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
11127
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
11020
11128
|
}
|
|
11021
|
-
if (end === -1) end =
|
|
11129
|
+
if (end === -1) end = i2;
|
|
11022
11130
|
const protocol2 = header.slice(start, end);
|
|
11023
11131
|
if (protocols.has(protocol2)) {
|
|
11024
11132
|
throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`);
|
|
@@ -11026,13 +11134,13 @@ var require_subprotocol = __commonJS({
|
|
|
11026
11134
|
protocols.add(protocol2);
|
|
11027
11135
|
start = end = -1;
|
|
11028
11136
|
} else {
|
|
11029
|
-
throw new SyntaxError(`Unexpected character at index ${
|
|
11137
|
+
throw new SyntaxError(`Unexpected character at index ${i2}`);
|
|
11030
11138
|
}
|
|
11031
11139
|
}
|
|
11032
11140
|
if (start === -1 || end !== -1) {
|
|
11033
11141
|
throw new SyntaxError("Unexpected end of input");
|
|
11034
11142
|
}
|
|
11035
|
-
const protocol = header.slice(start,
|
|
11143
|
+
const protocol = header.slice(start, i2);
|
|
11036
11144
|
if (protocols.has(protocol)) {
|
|
11037
11145
|
throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
|
|
11038
11146
|
}
|
|
@@ -11994,6 +12102,7 @@ var upsertTelemetryFromPlugin = makeFunctionReference("telemetryPlugin:upsertTel
|
|
|
11994
12102
|
var upsertSessionsFromPlugin = makeFunctionReference("telemetryPlugin:upsertSessionsFromPlugin");
|
|
11995
12103
|
var pushActivityFromPluginRef = makeFunctionReference("activityFeed:pushActivityFromPlugin");
|
|
11996
12104
|
var upsertCronSnapshotFromPluginRef = makeFunctionReference("telemetryPlugin:upsertCronSnapshotFromPlugin");
|
|
12105
|
+
var recordGatewayPresenceRef = makeFunctionReference("gatewayPresence:recordGatewayPresence");
|
|
11997
12106
|
var recordCronRunFromPluginRef = makeFunctionReference("cronRunHistory:recordFromPlugin");
|
|
11998
12107
|
var getUndeliveredForPlugin = makeFunctionReference("notifications:getUndeliveredForPlugin");
|
|
11999
12108
|
var markDeliveredByPlugin = makeFunctionReference("notifications:markDeliveredByPlugin");
|
|
@@ -12015,7 +12124,7 @@ async function pushTelemetry(apiKey2, data) {
|
|
|
12015
12124
|
const c = getClient();
|
|
12016
12125
|
if (!c) return;
|
|
12017
12126
|
try {
|
|
12018
|
-
await c.mutation(upsertTelemetryFromPlugin, { apiKeyHash: hashApiKey(apiKey2), ...data });
|
|
12127
|
+
await c.mutation(upsertTelemetryFromPlugin, { apiKeyHash: hashApiKey(apiKey2), runtime: "openclaw", ...data });
|
|
12019
12128
|
} catch (err) {
|
|
12020
12129
|
if (isUnauthorizedError(err)) {
|
|
12021
12130
|
tripAuthCircuit();
|
|
@@ -12068,6 +12177,22 @@ async function pushCronSnapshot(apiKey2, jobs) {
|
|
|
12068
12177
|
return false;
|
|
12069
12178
|
}
|
|
12070
12179
|
}
|
|
12180
|
+
async function pushPresence(apiKey2, runtime) {
|
|
12181
|
+
if (authCircuitOpen) return false;
|
|
12182
|
+
const c = getClient();
|
|
12183
|
+
if (!c) return false;
|
|
12184
|
+
try {
|
|
12185
|
+
await c.mutation(recordGatewayPresenceRef, { apiKeyHash: hashApiKey(apiKey2), runtime });
|
|
12186
|
+
return true;
|
|
12187
|
+
} catch (err) {
|
|
12188
|
+
if (isUnauthorizedError(err)) {
|
|
12189
|
+
tripAuthCircuit();
|
|
12190
|
+
return false;
|
|
12191
|
+
}
|
|
12192
|
+
getLogger().error(`cohort-sync: pushPresence failed: ${err}`);
|
|
12193
|
+
return false;
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12071
12196
|
async function recordCronRun(apiKey2, run) {
|
|
12072
12197
|
if (authCircuitOpen) return false;
|
|
12073
12198
|
const c = getClient();
|
|
@@ -12686,7 +12811,7 @@ async function startNotificationSubscription(port, cfg, hooksToken, logger, gwCl
|
|
|
12686
12811
|
processing = true;
|
|
12687
12812
|
try {
|
|
12688
12813
|
for (const n of notifications) {
|
|
12689
|
-
const failCount = deliveryFailures.get(n.
|
|
12814
|
+
const failCount = deliveryFailures.get(n.id) ?? 0;
|
|
12690
12815
|
if (failCount >= MAX_DELIVERY_ATTEMPTS) {
|
|
12691
12816
|
continue;
|
|
12692
12817
|
}
|
|
@@ -12697,34 +12822,34 @@ async function startNotificationSubscription(port, cfg, hooksToken, logger, gwCl
|
|
|
12697
12822
|
logger.info(`cohort-sync: injected notification for ${targetLabel} (${agentName})`);
|
|
12698
12823
|
} else {
|
|
12699
12824
|
throw new Error(
|
|
12700
|
-
`no transport available for notification ${n.
|
|
12825
|
+
`no transport available for notification ${n.id} (gwClient alive: ${gwClient?.isAlive() ?? "null"}, hooksToken: ${!!hooksToken})`
|
|
12701
12826
|
);
|
|
12702
12827
|
}
|
|
12703
12828
|
await c.mutation(markDeliveredByPlugin, {
|
|
12704
|
-
notificationId: n.
|
|
12829
|
+
notificationId: n.id,
|
|
12705
12830
|
apiKeyHash
|
|
12706
12831
|
});
|
|
12707
|
-
deliveryFailures.delete(n.
|
|
12832
|
+
deliveryFailures.delete(n.id);
|
|
12708
12833
|
} catch (err) {
|
|
12709
12834
|
const newFailCount = failCount + 1;
|
|
12710
|
-
deliveryFailures.set(n.
|
|
12835
|
+
deliveryFailures.set(n.id, newFailCount);
|
|
12711
12836
|
if (newFailCount >= MAX_DELIVERY_ATTEMPTS) {
|
|
12712
12837
|
const targetLabel = n.type === "room_message" ? `room ${n.roomId ?? n.roomName ?? "unknown"}` : `task #${n.taskNumber}`;
|
|
12713
12838
|
logger.error(
|
|
12714
|
-
`cohort-sync: dead-letter notification ${n.
|
|
12839
|
+
`cohort-sync: dead-letter notification ${n.id} for ${targetLabel} (${n.type} from ${n.actorName}) after ${MAX_DELIVERY_ATTEMPTS} failed delivery attempts: ${String(err)}`
|
|
12715
12840
|
);
|
|
12716
12841
|
try {
|
|
12717
12842
|
await c.mutation(markDeliveredByPlugin, {
|
|
12718
|
-
notificationId: n.
|
|
12843
|
+
notificationId: n.id,
|
|
12719
12844
|
apiKeyHash
|
|
12720
12845
|
});
|
|
12721
|
-
deliveryFailures.delete(n.
|
|
12846
|
+
deliveryFailures.delete(n.id);
|
|
12722
12847
|
} catch (markErr) {
|
|
12723
|
-
logger.error(`cohort-sync: failed to dead-letter ${n.
|
|
12848
|
+
logger.error(`cohort-sync: failed to dead-letter ${n.id}: ${String(markErr)}`);
|
|
12724
12849
|
}
|
|
12725
12850
|
} else {
|
|
12726
12851
|
logger.warn(
|
|
12727
|
-
`cohort-sync: failed to inject notification ${n.
|
|
12852
|
+
`cohort-sync: failed to inject notification ${n.id} (attempt ${newFailCount}/${MAX_DELIVERY_ATTEMPTS}): ${String(err)}`
|
|
12728
12853
|
);
|
|
12729
12854
|
}
|
|
12730
12855
|
}
|
|
@@ -12855,15 +12980,15 @@ import crypto2 from "node:crypto";
|
|
|
12855
12980
|
|
|
12856
12981
|
// src/device-identity-crypto.ts
|
|
12857
12982
|
import crypto from "node:crypto";
|
|
12858
|
-
import
|
|
12859
|
-
import
|
|
12983
|
+
import fs2 from "node:fs";
|
|
12984
|
+
import path2 from "node:path";
|
|
12860
12985
|
import os from "node:os";
|
|
12861
|
-
var DATA_DIR =
|
|
12862
|
-
var IDENTITY_PATH =
|
|
12863
|
-
var LEGACY_IDENTITY_PATH =
|
|
12986
|
+
var DATA_DIR = path2.join(os.homedir(), ".openclaw", "data", "cohort-sync");
|
|
12987
|
+
var IDENTITY_PATH = path2.join(DATA_DIR, ".device-identity.json");
|
|
12988
|
+
var LEGACY_IDENTITY_PATH = path2.join(os.homedir(), ".openclaw", "extensions", "cohort-sync", ".device-identity.json");
|
|
12864
12989
|
function tryLoadIdentity(filePath) {
|
|
12865
12990
|
try {
|
|
12866
|
-
const data = JSON.parse(
|
|
12991
|
+
const data = JSON.parse(fs2["read"+"FileSync"](filePath, "utf-8"));
|
|
12867
12992
|
if (data.deviceId && data.publicKeyPem && data.privateKeyPem) {
|
|
12868
12993
|
return data;
|
|
12869
12994
|
}
|
|
@@ -12896,8 +13021,8 @@ function loadOrCreateDeviceIdentity() {
|
|
|
12896
13021
|
}
|
|
12897
13022
|
function persistIdentity(identity) {
|
|
12898
13023
|
try {
|
|
12899
|
-
|
|
12900
|
-
|
|
13024
|
+
fs2.mkdirSync(DATA_DIR, { recursive: true, mode: 448 });
|
|
13025
|
+
fs2.writeFileSync(IDENTITY_PATH, JSON.stringify(identity, null, 2), { mode: 384 });
|
|
12901
13026
|
} catch (err) {
|
|
12902
13027
|
console.debug("cohort-sync: device identity write failed", { error: String(err) });
|
|
12903
13028
|
}
|
|
@@ -14009,6 +14134,28 @@ var AgentStateTracker = class {
|
|
|
14009
14134
|
|
|
14010
14135
|
// src/types.ts
|
|
14011
14136
|
var DEFAULT_API_URL = "https://api.cohort.bot";
|
|
14137
|
+
function normalizeTriageBrief(raw) {
|
|
14138
|
+
if (raw === null || typeof raw !== "object") {
|
|
14139
|
+
return { error: "brief must be an object with problem, solution (and optional risks)." };
|
|
14140
|
+
}
|
|
14141
|
+
const obj = raw;
|
|
14142
|
+
const requireField = (name) => {
|
|
14143
|
+
const value = obj[name];
|
|
14144
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
14145
|
+
return { error: `brief.${name} is required and must be a non-empty string.` };
|
|
14146
|
+
}
|
|
14147
|
+
return value.trim();
|
|
14148
|
+
};
|
|
14149
|
+
const problem = requireField("problem");
|
|
14150
|
+
if (typeof problem !== "string") return problem;
|
|
14151
|
+
const solution = requireField("solution");
|
|
14152
|
+
if (typeof solution !== "string") return solution;
|
|
14153
|
+
const brief = { problem, solution };
|
|
14154
|
+
if (typeof obj.risks === "string" && obj.risks.trim().length > 0) {
|
|
14155
|
+
brief.risks = obj.risks.trim();
|
|
14156
|
+
}
|
|
14157
|
+
return { brief };
|
|
14158
|
+
}
|
|
14012
14159
|
|
|
14013
14160
|
// src/tool-runtime.ts
|
|
14014
14161
|
var apiKey = null;
|
|
@@ -14119,7 +14266,8 @@ function dumpEvent(event) {
|
|
|
14119
14266
|
function positiveNumber(value) {
|
|
14120
14267
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
14121
14268
|
}
|
|
14122
|
-
var PLUGIN_VERSION = true ? "0.34.
|
|
14269
|
+
var PLUGIN_VERSION = true ? "0.34.4" : "unknown";
|
|
14270
|
+
var PRESENCE_PING_INTERVAL_MS = 12e4;
|
|
14123
14271
|
function resolveGatewayToken(api) {
|
|
14124
14272
|
const token2 = api.config?.gateway?.auth?.token;
|
|
14125
14273
|
return typeof token2 === "string" ? token2 : null;
|
|
@@ -14149,8 +14297,8 @@ function registerCronEventHandlers(client2, cfg, resolveAgentName, cronTimestamp
|
|
|
14149
14297
|
}
|
|
14150
14298
|
function parseIdentityFile(workspaceDir) {
|
|
14151
14299
|
try {
|
|
14152
|
-
const filePath =
|
|
14153
|
-
const content =
|
|
14300
|
+
const filePath = path3.join(workspaceDir, "IDENTITY.md");
|
|
14301
|
+
const content = fs3["read"+"FileSync"](filePath, "utf-8");
|
|
14154
14302
|
const identity = {};
|
|
14155
14303
|
for (const line of content.split(/\r?\n/)) {
|
|
14156
14304
|
const cleaned = line.trim().replace(/^\s*-\s*/, "");
|
|
@@ -14169,14 +14317,41 @@ function parseIdentityFile(workspaceDir) {
|
|
|
14169
14317
|
return null;
|
|
14170
14318
|
}
|
|
14171
14319
|
}
|
|
14320
|
+
function parseRoleFromSoul(content) {
|
|
14321
|
+
const MAX_LEN = 80;
|
|
14322
|
+
for (const line of content.split(/\r?\n/)) {
|
|
14323
|
+
const cleaned = line.trim().replace(/^\s*-\s*/, "");
|
|
14324
|
+
const colonIndex = cleaned.indexOf(":");
|
|
14325
|
+
if (colonIndex === -1) continue;
|
|
14326
|
+
const label = cleaned.slice(0, colonIndex).replace(/[*_]/g, "").trim().toLowerCase();
|
|
14327
|
+
if (label !== "role" && label !== "current role") continue;
|
|
14328
|
+
let value = cleaned.slice(colonIndex + 1).replace(/^[*_]+|[*_]+$/g, "").trim();
|
|
14329
|
+
if (!value) continue;
|
|
14330
|
+
const firstSentence = value.split(/\.\s/)[0].trim();
|
|
14331
|
+
if (firstSentence) value = firstSentence;
|
|
14332
|
+
if (value.length > MAX_LEN) value = value.slice(0, MAX_LEN).trim();
|
|
14333
|
+
return value;
|
|
14334
|
+
}
|
|
14335
|
+
return void 0;
|
|
14336
|
+
}
|
|
14337
|
+
function parseSoulRole(workspaceDir) {
|
|
14338
|
+
try {
|
|
14339
|
+
const content = fs3["read"+"FileSync"](path3.join(workspaceDir, "SOUL.md"), "utf-8");
|
|
14340
|
+
return parseRoleFromSoul(content);
|
|
14341
|
+
} catch {
|
|
14342
|
+
return void 0;
|
|
14343
|
+
}
|
|
14344
|
+
}
|
|
14172
14345
|
function resolveIdentity(configIdentity, workspaceDir) {
|
|
14173
14346
|
const fileIdentity = workspaceDir ? parseIdentityFile(workspaceDir) : null;
|
|
14174
|
-
|
|
14347
|
+
const soulRole = workspaceDir ? parseSoulRole(workspaceDir) : void 0;
|
|
14348
|
+
if (!configIdentity && !fileIdentity && !soulRole) return void 0;
|
|
14175
14349
|
return {
|
|
14176
14350
|
name: configIdentity?.name ?? fileIdentity?.name,
|
|
14177
14351
|
emoji: configIdentity?.emoji ?? fileIdentity?.emoji,
|
|
14178
14352
|
theme: configIdentity?.theme ?? fileIdentity?.theme,
|
|
14179
|
-
avatar: configIdentity?.avatar ?? fileIdentity?.avatar
|
|
14353
|
+
avatar: configIdentity?.avatar ?? fileIdentity?.avatar,
|
|
14354
|
+
title: configIdentity?.title ?? soulRole
|
|
14180
14355
|
};
|
|
14181
14356
|
}
|
|
14182
14357
|
function saveSessionsToDisk(tracker, stateFilePath) {
|
|
@@ -14193,14 +14368,14 @@ function saveSessionsToDisk(tracker, stateFilePath) {
|
|
|
14193
14368
|
data.sessions.push({ agentName: name, key });
|
|
14194
14369
|
}
|
|
14195
14370
|
}
|
|
14196
|
-
|
|
14371
|
+
fs3.writeFileSync(stateFilePath, JSON.stringify(data), { mode: 384 });
|
|
14197
14372
|
} catch {
|
|
14198
14373
|
}
|
|
14199
14374
|
}
|
|
14200
14375
|
function loadSessionsFromDisk(tracker, stateFilePath, logger) {
|
|
14201
14376
|
try {
|
|
14202
|
-
if (!
|
|
14203
|
-
const data = JSON.parse(
|
|
14377
|
+
if (!fs3.existsSync(stateFilePath)) return;
|
|
14378
|
+
const data = JSON.parse(fs3["read"+"FileSync"](stateFilePath, "utf8"));
|
|
14204
14379
|
if (Date.now() - new Date(data.savedAt).getTime() > 864e5) {
|
|
14205
14380
|
logger.info("cohort-sync: disk session state too old (>24h), skipping");
|
|
14206
14381
|
return;
|
|
@@ -14296,7 +14471,15 @@ async function handleGatewayStart(event, state) {
|
|
|
14296
14471
|
model: state.resolveModel(a.id),
|
|
14297
14472
|
identity: resolveIdentity(a.identity, a.workspace)
|
|
14298
14473
|
}));
|
|
14299
|
-
|
|
14474
|
+
const skillsDir = api.config?.skills?.dir ?? path3.join(os2.homedir(), ".openclaw", "skills");
|
|
14475
|
+
await fullSync(
|
|
14476
|
+
state.resolveAgentName("main"),
|
|
14477
|
+
state.resolveModel("main"),
|
|
14478
|
+
cfg,
|
|
14479
|
+
logger,
|
|
14480
|
+
agentList,
|
|
14481
|
+
skillsDir
|
|
14482
|
+
);
|
|
14300
14483
|
} catch (err) {
|
|
14301
14484
|
logger.error(`cohort-sync: gateway_start sync failed: ${String(err)}`);
|
|
14302
14485
|
}
|
|
@@ -14421,6 +14604,17 @@ async function handleGatewayStart(event, state) {
|
|
|
14421
14604
|
saveSessionsToDisk(tracker, state.stateFilePath);
|
|
14422
14605
|
}, 15e4);
|
|
14423
14606
|
logger.info("cohort-sync: keepalive interval started (150s)");
|
|
14607
|
+
void pushPresence(cfg.apiKey, "openclaw").catch(() => {
|
|
14608
|
+
});
|
|
14609
|
+
if (state.presenceInterval) clearInterval(state.presenceInterval);
|
|
14610
|
+
state.presenceInterval = setInterval(() => {
|
|
14611
|
+
void pushPresence(cfg.apiKey, "openclaw").catch(() => {
|
|
14612
|
+
});
|
|
14613
|
+
}, PRESENCE_PING_INTERVAL_MS);
|
|
14614
|
+
if (typeof state.presenceInterval.unref === "function") {
|
|
14615
|
+
state.presenceInterval.unref();
|
|
14616
|
+
}
|
|
14617
|
+
logger.info(`cohort-sync: liveness ping interval started (${PRESENCE_PING_INTERVAL_MS / 1e3}s)`);
|
|
14424
14618
|
}
|
|
14425
14619
|
function registerHookHandlers(api, logger, getState) {
|
|
14426
14620
|
function resolveAgentFromContext(state, ctx) {
|
|
@@ -14497,7 +14691,7 @@ function registerHookHandlers(api, logger, getState) {
|
|
|
14497
14691
|
const parsed = parseSessionKey(sessionKey);
|
|
14498
14692
|
const routineId = parsed.kind === "cron" ? parsed.identifier : void 0;
|
|
14499
14693
|
try {
|
|
14500
|
-
const raw =
|
|
14694
|
+
const raw = fs3["read"+"FileSync"](state.cronStorePath, "utf8");
|
|
14501
14695
|
const store = JSON.parse(raw);
|
|
14502
14696
|
const jobs = store.jobs ?? [];
|
|
14503
14697
|
const mapped = jobs.map((j) => mapCronJob(j, state.resolveAgentName, state.cronTimestampTracker));
|
|
@@ -14881,6 +15075,10 @@ function registerHookHandlers(api, logger, getState) {
|
|
|
14881
15075
|
clearInterval(state.keepaliveInterval);
|
|
14882
15076
|
state.keepaliveInterval = null;
|
|
14883
15077
|
}
|
|
15078
|
+
if (state.presenceInterval) {
|
|
15079
|
+
clearInterval(state.presenceInterval);
|
|
15080
|
+
state.presenceInterval = null;
|
|
15081
|
+
}
|
|
14884
15082
|
if (state.updateCheckInterval) {
|
|
14885
15083
|
clearInterval(state.updateCheckInterval);
|
|
14886
15084
|
state.updateCheckInterval = null;
|
|
@@ -14931,7 +15129,7 @@ function registerHookHandlers(api, logger, getState) {
|
|
|
14931
15129
|
}
|
|
14932
15130
|
function initializeHookState(api, cfg) {
|
|
14933
15131
|
const { logger, config } = api;
|
|
14934
|
-
const stateFilePath =
|
|
15132
|
+
const stateFilePath = path3.join(cfg.stateDir, "session-state.json");
|
|
14935
15133
|
const nameMap = cfg.agentNameMap;
|
|
14936
15134
|
const tracker = new AgentStateTracker();
|
|
14937
15135
|
const convexUrl = cfg.convexUrl ?? deriveConvexUrl(cfg.apiUrl);
|
|
@@ -14965,7 +15163,7 @@ function initializeHookState(api, cfg) {
|
|
|
14965
15163
|
function getModelContextLimit2(model) {
|
|
14966
15164
|
return getModelContextLimit(model);
|
|
14967
15165
|
}
|
|
14968
|
-
const cronStorePath = api.config?.cron?.store ??
|
|
15166
|
+
const cronStorePath = api.config?.cron?.store ?? path3.join(os2.homedir(), ".openclaw", "cron", "jobs.json");
|
|
14969
15167
|
const activityBatch = new MicroBatch({
|
|
14970
15168
|
maxSize: 10,
|
|
14971
15169
|
maxDelayMs: 1e3,
|
|
@@ -15041,6 +15239,7 @@ function initializeHookState(api, cfg) {
|
|
|
15041
15239
|
persistentGwClient,
|
|
15042
15240
|
gwClientInitialized,
|
|
15043
15241
|
keepaliveInterval: null,
|
|
15242
|
+
presenceInterval: null,
|
|
15044
15243
|
commandUnsubscriber: commandUnsub,
|
|
15045
15244
|
channelsUnsubscriber: null,
|
|
15046
15245
|
api,
|
|
@@ -15084,6 +15283,65 @@ function registerGatewayMethods(api, getGatewayClient) {
|
|
|
15084
15283
|
);
|
|
15085
15284
|
}
|
|
15086
15285
|
|
|
15286
|
+
// src/triage-pr-files.ts
|
|
15287
|
+
import { execFile } from "node:child_process";
|
|
15288
|
+
import { readFile } from "node:fs/promises";
|
|
15289
|
+
import { join } from "node:path";
|
|
15290
|
+
import { promisify } from "node:util";
|
|
15291
|
+
var execFileAsync = promisify(execFile);
|
|
15292
|
+
async function collectChangedFiles(args) {
|
|
15293
|
+
const cwd = args.repoDir || process.cwd();
|
|
15294
|
+
const git = async (gitArgs) => {
|
|
15295
|
+
const { stdout } = await execFileAsync("git", gitArgs, {
|
|
15296
|
+
cwd,
|
|
15297
|
+
maxBuffer: 64 * 1024 * 1024
|
|
15298
|
+
});
|
|
15299
|
+
return stdout;
|
|
15300
|
+
};
|
|
15301
|
+
const files = [];
|
|
15302
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15303
|
+
const nameStatus = await git(["diff", "--name-status", "-z", args.baseSha]);
|
|
15304
|
+
const tokens = nameStatus.split("\0");
|
|
15305
|
+
let i2 = 0;
|
|
15306
|
+
while (i2 < tokens.length) {
|
|
15307
|
+
const status = tokens[i2];
|
|
15308
|
+
if (!status) {
|
|
15309
|
+
i2 += 1;
|
|
15310
|
+
continue;
|
|
15311
|
+
}
|
|
15312
|
+
let path4;
|
|
15313
|
+
if (status[0] === "R" || status[0] === "C") {
|
|
15314
|
+
const oldPath = tokens[i2 + 1] ?? "";
|
|
15315
|
+
path4 = tokens[i2 + 2] ?? "";
|
|
15316
|
+
i2 += 3;
|
|
15317
|
+
if (oldPath && !seen.has(oldPath)) {
|
|
15318
|
+
seen.add(oldPath);
|
|
15319
|
+
files.push({ path: oldPath, deleted: true });
|
|
15320
|
+
}
|
|
15321
|
+
} else {
|
|
15322
|
+
path4 = tokens[i2 + 1] ?? "";
|
|
15323
|
+
i2 += 2;
|
|
15324
|
+
}
|
|
15325
|
+
if (!path4 || seen.has(path4)) continue;
|
|
15326
|
+
seen.add(path4);
|
|
15327
|
+
if (status[0] === "D") {
|
|
15328
|
+
files.push({ path: path4, deleted: true });
|
|
15329
|
+
} else {
|
|
15330
|
+
files.push({ path: path4, content: await readRepoFile(cwd, path4) });
|
|
15331
|
+
}
|
|
15332
|
+
}
|
|
15333
|
+
const others = await git(["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
15334
|
+
for (const path4 of others.split("\0")) {
|
|
15335
|
+
if (!path4 || seen.has(path4)) continue;
|
|
15336
|
+
seen.add(path4);
|
|
15337
|
+
files.push({ path: path4, content: await readRepoFile(cwd, path4) });
|
|
15338
|
+
}
|
|
15339
|
+
return files;
|
|
15340
|
+
}
|
|
15341
|
+
async function readRepoFile(cwd, path4) {
|
|
15342
|
+
return readFile(join(cwd, path4), "utf8");
|
|
15343
|
+
}
|
|
15344
|
+
|
|
15087
15345
|
// src/pocket-guide.ts
|
|
15088
15346
|
var POCKET_GUIDE = `# Cohort Agent Guide (Pocket Version)
|
|
15089
15347
|
|
|
@@ -15104,6 +15362,13 @@ var POCKET_GUIDE = `# Cohort Agent Guide (Pocket Version)
|
|
|
15104
15362
|
- For code changes, work is not complete when it is implemented locally; push your branch, open a PR, enable auto-merge, watch CI until green or red, confirm the PR merged, verify the production deploy, then comment with the PR link, deploy result, and verification evidence.
|
|
15105
15363
|
- Use GitHub for deployment: after opening the PR, run gh pr merge --auto --rebase --delete-branch, gh pr checks <PR> --watch, confirm the merge, then run gh run watch <deploy-run-id> for the Deploy Production workflow. Do not stop because Vercel CLI is not authenticated; Cohort deploys through GitHub Actions after merge.
|
|
15106
15364
|
|
|
15365
|
+
## Working as a Team
|
|
15366
|
+
- Two modes: orchestrator and worker. As an orchestrator, break the goal into a task graph (create tasks, assign owners, relate dependencies), then report the graph and leave implementation to the assigned workers. As a worker, take one task, do it, and hand it back cleanly.
|
|
15367
|
+
- Relate dependent tasks with blockers so ordering is explicit. A blocked task stays gated until its blocker clears.
|
|
15368
|
+
- Before assigning, confirm the assignee is a real agent in the workspace, because a task assigned to a name that resolves to no one strands in its column.
|
|
15369
|
+
- The closing comment is the handoff: what you did, the evidence (links, PR, test output, artifact), and what is now unblocked or what the human must decide. Agents cannot set "done", so move to "waiting" and let a human close it.
|
|
15370
|
+
- Create a task when work spans multiple agents, needs to survive a restart, wants a human in the loop, or can run in parallel. For something you can finish right now, just do it.
|
|
15371
|
+
|
|
15107
15372
|
## Comments
|
|
15108
15373
|
- Comment before every status transition explaining what happened.
|
|
15109
15374
|
- Post progress updates every 15-30 minutes on long-running work.
|
|
@@ -15306,6 +15571,31 @@ async function safeHttpError(response) {
|
|
|
15306
15571
|
}
|
|
15307
15572
|
return "";
|
|
15308
15573
|
}
|
|
15574
|
+
var PR_MAX_FILES = 50;
|
|
15575
|
+
var PR_MAX_FILE_BYTES = 1e6;
|
|
15576
|
+
var PR_MAX_TOTAL_BYTES = 5e6;
|
|
15577
|
+
var PR_BASE_SHA_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i;
|
|
15578
|
+
function checkPrEnvelope(files) {
|
|
15579
|
+
if (files.length === 0) {
|
|
15580
|
+
return "No changed files to report \u2014 make a change first, then call cohort_triage_pr.";
|
|
15581
|
+
}
|
|
15582
|
+
if (files.length > PR_MAX_FILES) {
|
|
15583
|
+
return `Change too large: ${files.length} files (max ${PR_MAX_FILES}).`;
|
|
15584
|
+
}
|
|
15585
|
+
let total = 0;
|
|
15586
|
+
for (const entry of files) {
|
|
15587
|
+
if ("deleted" in entry) continue;
|
|
15588
|
+
const size = Buffer2.byteLength(entry.content, "utf8");
|
|
15589
|
+
if (size > PR_MAX_FILE_BYTES) {
|
|
15590
|
+
return `File too large: ${entry.path} (max ${PR_MAX_FILE_BYTES} bytes).`;
|
|
15591
|
+
}
|
|
15592
|
+
total += size;
|
|
15593
|
+
}
|
|
15594
|
+
if (total > PR_MAX_TOTAL_BYTES) {
|
|
15595
|
+
return "Change too large (total content size exceeds the limit).";
|
|
15596
|
+
}
|
|
15597
|
+
return null;
|
|
15598
|
+
}
|
|
15309
15599
|
function renderTaskContext(context) {
|
|
15310
15600
|
if (!context) return "";
|
|
15311
15601
|
const lines = [];
|
|
@@ -15472,7 +15762,7 @@ Do not attempt more comments until tomorrow.`);
|
|
|
15472
15762
|
label: "cohort_room_message",
|
|
15473
15763
|
description: "Post a message in a Cohort Room. Use this to reply when you are participating in a Room chat.",
|
|
15474
15764
|
parameters: Type.Object({
|
|
15475
|
-
room_id: Type.String({ description:
|
|
15765
|
+
room_id: Type.String({ description: 'The Room to post in. Prefer the exact room id from your prompt/notification (e.g. xs773mgqe3qd9h41pjwxndd755887b1x). The room name (e.g. "All Hands") is also accepted.' }),
|
|
15476
15766
|
message: Type.String({ description: "Message text to post in the Room" }),
|
|
15477
15767
|
turn_id: Type.Optional(Type.String({ description: "Moderation turn id to attribute this reply to (echo from your prompt)" }))
|
|
15478
15768
|
}),
|
|
@@ -15499,7 +15789,7 @@ Do not attempt more comments until tomorrow.`);
|
|
|
15499
15789
|
label: "cohort_room_prompt_agent",
|
|
15500
15790
|
description: "Ask one agent in a Cohort Room to respond. Use this when you are the Room moderator and need controlled turn-taking.",
|
|
15501
15791
|
parameters: Type.Object({
|
|
15502
|
-
room_id: Type.String({ description:
|
|
15792
|
+
room_id: Type.String({ description: 'Room ID supplied by Cohort, e.g. xs773mgqe3qd9h41pjwxndd755887b1x (NOT prefixed with "rooms:").' }),
|
|
15503
15793
|
agent_name: Type.String({ description: "Cohort agent name to prompt, e.g. iris" }),
|
|
15504
15794
|
prompt: Type.String({ description: "Prompt to send to the target agent" })
|
|
15505
15795
|
}),
|
|
@@ -15527,7 +15817,7 @@ Do not attempt more comments until tomorrow.`);
|
|
|
15527
15817
|
label: "cohort_room_prompt_agents",
|
|
15528
15818
|
description: "Ask multiple agents in a Cohort Room to respond in one controlled moderator action.",
|
|
15529
15819
|
parameters: Type.Object({
|
|
15530
|
-
room_id: Type.String({ description:
|
|
15820
|
+
room_id: Type.String({ description: 'Room ID supplied by Cohort, e.g. xs773mgqe3qd9h41pjwxndd755887b1x (NOT prefixed with "rooms:").' }),
|
|
15531
15821
|
agent_names: Type.Array(Type.String({ description: "Cohort agent name to prompt" })),
|
|
15532
15822
|
prompt: Type.String({ description: "Prompt to send to the target agents" })
|
|
15533
15823
|
}),
|
|
@@ -15671,7 +15961,7 @@ Wire item: ${result.wireItemId}`, result);
|
|
|
15671
15961
|
label: "cohort_room_start_moderation_session",
|
|
15672
15962
|
description: 'Start a managed moderation session in a Cohort Room. Use round_robin = ask every participant to report in; use moderated_qna = route a question to one selected agent, wait for the answer, ask the asker whether it resolves the question, then complete. For multiple experts in Q&A, start with one best agent and use action: "followup" for additional experts one at a time. Returns the session state block. The returned block includes the session_id \u2014 pass it to cohort_room_advance_moderation_session for every subsequent action.',
|
|
15673
15963
|
parameters: Type.Object({
|
|
15674
|
-
room_id: Type.String({ description:
|
|
15964
|
+
room_id: Type.String({ description: 'Room ID supplied by Cohort, e.g. xs773mgqe3qd9h41pjwxndd755887b1x (NOT prefixed with "rooms:").' }),
|
|
15675
15965
|
mode: Type.Union([
|
|
15676
15966
|
Type.Literal("round_robin"),
|
|
15677
15967
|
Type.Literal("moderated_qna")
|
|
@@ -16056,6 +16346,127 @@ ${renderGoal(goal)}`, goal);
|
|
|
16056
16346
|
}
|
|
16057
16347
|
};
|
|
16058
16348
|
});
|
|
16349
|
+
api.registerTool(() => {
|
|
16350
|
+
return {
|
|
16351
|
+
name: "cohort_triage",
|
|
16352
|
+
label: "cohort_triage",
|
|
16353
|
+
description: "Report your triage decision on a Cohort triage item back to Cohort. Pass the Triage item ID from your wake task as triage_item_id, the tier (trivial | judgment | feature | not_actionable), whether it is actionable, and your reasoning. Also pass a short `title` \u2014 a brief (\u226480 char) issue summary in your own words (a task-name headline of what you read), NOT a paste of the feedback; Cohort uses it as the Build-it task title. SHADOW MODE: do NOT write code or open PRs.",
|
|
16354
|
+
parameters: Type.Object({
|
|
16355
|
+
triage_item_id: Type.String({ description: "Triage item ID from your wake task (e.g. triageItems:abc123)." }),
|
|
16356
|
+
tier: Type.Union([
|
|
16357
|
+
Type.Literal("trivial"),
|
|
16358
|
+
Type.Literal("judgment"),
|
|
16359
|
+
Type.Literal("feature"),
|
|
16360
|
+
Type.Literal("not_actionable")
|
|
16361
|
+
], { description: "Triage tier for this feedback." }),
|
|
16362
|
+
actionable: Type.Boolean({ description: "Whether this feedback is actionable." }),
|
|
16363
|
+
reasoning: Type.String({ description: "Why you reached this decision." }),
|
|
16364
|
+
confidence: Type.Optional(Type.Number({ description: "Optional confidence in the decision, 0 to 1." })),
|
|
16365
|
+
title: Type.Optional(Type.String({ description: "Optional short (\u226480 char) issue summary in your own words \u2014 a task-name headline of the problem, NOT a paste of the feedback. Used as the Build-it task title." }))
|
|
16366
|
+
}),
|
|
16367
|
+
async execute(_toolCallId, params) {
|
|
16368
|
+
const rt = getToolRuntime();
|
|
16369
|
+
if (!rt.isReady) {
|
|
16370
|
+
return textResult("cohort_triage is not ready yet \u2014 the plugin is still starting up.");
|
|
16371
|
+
}
|
|
16372
|
+
try {
|
|
16373
|
+
const response = await fetch(
|
|
16374
|
+
`${rt.apiUrl}/api/v1/plugin/triage/${encodeURIComponent(params.triage_item_id)}/decision`,
|
|
16375
|
+
{
|
|
16376
|
+
method: "POST",
|
|
16377
|
+
headers: {
|
|
16378
|
+
"Authorization": `Bearer ${rt.apiKey}`,
|
|
16379
|
+
"Content-Type": "application/json"
|
|
16380
|
+
},
|
|
16381
|
+
body: JSON.stringify({
|
|
16382
|
+
tier: params.tier,
|
|
16383
|
+
actionable: params.actionable,
|
|
16384
|
+
reasoning: params.reasoning,
|
|
16385
|
+
...params.confidence !== void 0 ? { confidence: params.confidence } : {},
|
|
16386
|
+
...params.title !== void 0 ? { title: params.title } : {}
|
|
16387
|
+
}),
|
|
16388
|
+
signal: AbortSignal.timeout(1e4)
|
|
16389
|
+
}
|
|
16390
|
+
);
|
|
16391
|
+
if (!response.ok) {
|
|
16392
|
+
const message = await safeHttpError(response);
|
|
16393
|
+
return textResult(`Failed to record triage decision for ${params.triage_item_id}: ${response.status}${message}`);
|
|
16394
|
+
}
|
|
16395
|
+
const result = await response.json();
|
|
16396
|
+
const verdict = params.actionable ? "actionable" : "not actionable";
|
|
16397
|
+
return textResult(`Recorded triage decision for ${params.triage_item_id}: ${params.tier} (${verdict}).`, result);
|
|
16398
|
+
} catch (err) {
|
|
16399
|
+
return textResult(`Failed to record triage decision for ${params.triage_item_id}: ${err instanceof Error ? redactSecrets(err.message) : "Unknown error"}`);
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
16402
|
+
};
|
|
16403
|
+
});
|
|
16404
|
+
api.registerTool(() => {
|
|
16405
|
+
return {
|
|
16406
|
+
name: "cohort_triage_pr",
|
|
16407
|
+
label: "cohort_triage_pr",
|
|
16408
|
+
description: "Report a Build-it fix you produced for a Cohort triage item. Pass the Triage item ID, the base commit SHA you branched from (base_sha), and a structured brief (problem, solution, optional risks). The tool collects your changed files from the current worktree and sends them to Cohort; the Cohort spine opens the PR and it auto-merges once CI is green. Do NOT open a PR or merge yourself \u2014 you hold no merge credential.",
|
|
16409
|
+
parameters: Type.Object({
|
|
16410
|
+
triage_item_id: Type.String({ description: "Triage item ID from your wake task (e.g. triageItems:abc123)." }),
|
|
16411
|
+
base_sha: Type.String({ description: "The 40- or 64-char hex commit SHA you branched from." }),
|
|
16412
|
+
brief: Type.Object({
|
|
16413
|
+
problem: Type.String({ description: "What's wrong (the issue being fixed)." }),
|
|
16414
|
+
solution: Type.String({ description: "How the PR fixes it (rendered under the 'Fix' label)." }),
|
|
16415
|
+
risks: Type.Optional(Type.String({ description: "Optional risks/blast radius of the change." }))
|
|
16416
|
+
}),
|
|
16417
|
+
repo_dir: Type.Optional(Type.String({ description: "Optional worktree path to diff (defaults to the current directory)." }))
|
|
16418
|
+
}),
|
|
16419
|
+
async execute(_toolCallId, params) {
|
|
16420
|
+
const rt = getToolRuntime();
|
|
16421
|
+
if (!rt.isReady) {
|
|
16422
|
+
return textResult("cohort_triage_pr is not ready yet \u2014 the plugin is still starting up.");
|
|
16423
|
+
}
|
|
16424
|
+
if (!PR_BASE_SHA_RE.test(params.base_sha)) {
|
|
16425
|
+
return textResult("Invalid base_sha: must be a 40- or 64-char hex commit SHA.");
|
|
16426
|
+
}
|
|
16427
|
+
const normalized = normalizeTriageBrief(params.brief);
|
|
16428
|
+
if ("error" in normalized) {
|
|
16429
|
+
return textResult(`Invalid brief: ${normalized.error}`);
|
|
16430
|
+
}
|
|
16431
|
+
let files;
|
|
16432
|
+
try {
|
|
16433
|
+
files = await collectChangedFiles({ baseSha: params.base_sha, repoDir: params.repo_dir });
|
|
16434
|
+
} catch (err) {
|
|
16435
|
+
return textResult(`Failed to collect changed files for ${params.triage_item_id}: ${err instanceof Error ? redactSecrets(err.message) : "Unknown error"}`);
|
|
16436
|
+
}
|
|
16437
|
+
const envelopeError = checkPrEnvelope(files);
|
|
16438
|
+
if (envelopeError) {
|
|
16439
|
+
return textResult(envelopeError);
|
|
16440
|
+
}
|
|
16441
|
+
try {
|
|
16442
|
+
const response = await fetch(
|
|
16443
|
+
`${rt.apiUrl}/api/v1/plugin/triage/${encodeURIComponent(params.triage_item_id)}/pr`,
|
|
16444
|
+
{
|
|
16445
|
+
method: "POST",
|
|
16446
|
+
headers: {
|
|
16447
|
+
"Authorization": `Bearer ${rt.apiKey}`,
|
|
16448
|
+
"Content-Type": "application/json"
|
|
16449
|
+
},
|
|
16450
|
+
body: JSON.stringify({
|
|
16451
|
+
brief: normalized.brief,
|
|
16452
|
+
baseSha: params.base_sha,
|
|
16453
|
+
files
|
|
16454
|
+
}),
|
|
16455
|
+
signal: AbortSignal.timeout(3e4)
|
|
16456
|
+
}
|
|
16457
|
+
);
|
|
16458
|
+
if (!response.ok) {
|
|
16459
|
+
const message = await safeHttpError(response);
|
|
16460
|
+
return textResult(`Failed to report PR for ${params.triage_item_id}: ${response.status}${message}`);
|
|
16461
|
+
}
|
|
16462
|
+
const result = await response.json();
|
|
16463
|
+
return textResult(`Reported ${files.length} changed file(s) for ${params.triage_item_id}; the spine will open the PR.`, result);
|
|
16464
|
+
} catch (err) {
|
|
16465
|
+
return textResult(`Failed to report PR for ${params.triage_item_id}: ${err instanceof Error ? redactSecrets(err.message) : "Unknown error"}`);
|
|
16466
|
+
}
|
|
16467
|
+
}
|
|
16468
|
+
};
|
|
16469
|
+
});
|
|
16059
16470
|
api.registerTool(() => {
|
|
16060
16471
|
return {
|
|
16061
16472
|
name: "cohort_relate",
|