omnius 1.0.41 → 1.0.43
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 +84 -27
- package/dist/index.js +2626 -324
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -16271,8 +16271,8 @@ function tokenizeSkillQuery(value2) {
|
|
|
16271
16271
|
return out;
|
|
16272
16272
|
}
|
|
16273
16273
|
function compactSkillLine(value2, max = 180) {
|
|
16274
|
-
const
|
|
16275
|
-
return
|
|
16274
|
+
const clean5 = value2.replace(/\s+/g, " ").trim();
|
|
16275
|
+
return clean5.length > max ? `${clean5.slice(0, Math.max(0, max - 3)).trimEnd()}...` : clean5;
|
|
16276
16276
|
}
|
|
16277
16277
|
function skillHaystack(skill) {
|
|
16278
16278
|
return [
|
|
@@ -34756,7 +34756,7 @@ var init_key = __esm({
|
|
|
34756
34756
|
* @param {string | Uint8Array} s
|
|
34757
34757
|
* @param {boolean} [clean]
|
|
34758
34758
|
*/
|
|
34759
|
-
constructor(s2,
|
|
34759
|
+
constructor(s2, clean5) {
|
|
34760
34760
|
if (typeof s2 === "string") {
|
|
34761
34761
|
this._buf = fromString2(s2);
|
|
34762
34762
|
} else if (s2 instanceof Uint8Array) {
|
|
@@ -34764,10 +34764,10 @@ var init_key = __esm({
|
|
|
34764
34764
|
} else {
|
|
34765
34765
|
throw new Error("Invalid key, should be String of Uint8Array");
|
|
34766
34766
|
}
|
|
34767
|
-
if (
|
|
34768
|
-
|
|
34767
|
+
if (clean5 == null) {
|
|
34768
|
+
clean5 = true;
|
|
34769
34769
|
}
|
|
34770
|
-
if (
|
|
34770
|
+
if (clean5) {
|
|
34771
34771
|
this.clean();
|
|
34772
34772
|
}
|
|
34773
34773
|
if (this._buf.byteLength === 0 || this._buf[0] !== pathSep) {
|
|
@@ -85036,10 +85036,10 @@ var require_abort = __commonJS({
|
|
|
85036
85036
|
"../node_modules/asynckit/lib/abort.js"(exports, module) {
|
|
85037
85037
|
module.exports = abort;
|
|
85038
85038
|
function abort(state) {
|
|
85039
|
-
Object.keys(state.jobs).forEach(
|
|
85039
|
+
Object.keys(state.jobs).forEach(clean5.bind(state));
|
|
85040
85040
|
state.jobs = {};
|
|
85041
85041
|
}
|
|
85042
|
-
function
|
|
85042
|
+
function clean5(key) {
|
|
85043
85043
|
if (typeof this.jobs[key] == "function") {
|
|
85044
85044
|
this.jobs[key]();
|
|
85045
85045
|
}
|
|
@@ -91562,7 +91562,7 @@ var require_auto = __commonJS({
|
|
|
91562
91562
|
// ../node_modules/acme-client/src/client.js
|
|
91563
91563
|
var require_client = __commonJS({
|
|
91564
91564
|
"../node_modules/acme-client/src/client.js"(exports, module) {
|
|
91565
|
-
var { createHash:
|
|
91565
|
+
var { createHash: createHash28 } = __require("crypto");
|
|
91566
91566
|
var { getPemBodyAsB64u } = require_crypto();
|
|
91567
91567
|
var { log: log22 } = require_logger();
|
|
91568
91568
|
var HttpClient = require_http();
|
|
@@ -91873,14 +91873,14 @@ var require_client = __commonJS({
|
|
|
91873
91873
|
*/
|
|
91874
91874
|
async getChallengeKeyAuthorization(challenge) {
|
|
91875
91875
|
const jwk = this.http.getJwk();
|
|
91876
|
-
const keysum =
|
|
91876
|
+
const keysum = createHash28("sha256").update(JSON.stringify(jwk));
|
|
91877
91877
|
const thumbprint = keysum.digest("base64url");
|
|
91878
91878
|
const result = `${challenge.token}.${thumbprint}`;
|
|
91879
91879
|
if (challenge.type === "http-01") {
|
|
91880
91880
|
return result;
|
|
91881
91881
|
}
|
|
91882
91882
|
if (challenge.type === "dns-01") {
|
|
91883
|
-
return
|
|
91883
|
+
return createHash28("sha256").update(result).digest("base64url");
|
|
91884
91884
|
}
|
|
91885
91885
|
if (challenge.type === "tls-alpn-01") {
|
|
91886
91886
|
return result;
|
|
@@ -234560,7 +234560,7 @@ var require_websocket2 = __commonJS({
|
|
|
234560
234560
|
var http6 = __require("http");
|
|
234561
234561
|
var net5 = __require("net");
|
|
234562
234562
|
var tls2 = __require("tls");
|
|
234563
|
-
var { randomBytes: randomBytes26, createHash:
|
|
234563
|
+
var { randomBytes: randomBytes26, createHash: createHash28 } = __require("crypto");
|
|
234564
234564
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
234565
234565
|
var { URL: URL3 } = __require("url");
|
|
234566
234566
|
var PerMessageDeflate3 = require_permessage_deflate2();
|
|
@@ -235220,7 +235220,7 @@ var require_websocket2 = __commonJS({
|
|
|
235220
235220
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
235221
235221
|
return;
|
|
235222
235222
|
}
|
|
235223
|
-
const digest3 =
|
|
235223
|
+
const digest3 = createHash28("sha1").update(key + GUID).digest("base64");
|
|
235224
235224
|
if (res.headers["sec-websocket-accept"] !== digest3) {
|
|
235225
235225
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
235226
235226
|
return;
|
|
@@ -235587,7 +235587,7 @@ var require_websocket_server = __commonJS({
|
|
|
235587
235587
|
var EventEmitter13 = __require("events");
|
|
235588
235588
|
var http6 = __require("http");
|
|
235589
235589
|
var { Duplex: Duplex3 } = __require("stream");
|
|
235590
|
-
var { createHash:
|
|
235590
|
+
var { createHash: createHash28 } = __require("crypto");
|
|
235591
235591
|
var extension3 = require_extension2();
|
|
235592
235592
|
var PerMessageDeflate3 = require_permessage_deflate2();
|
|
235593
235593
|
var subprotocol3 = require_subprotocol();
|
|
@@ -235888,7 +235888,7 @@ var require_websocket_server = __commonJS({
|
|
|
235888
235888
|
);
|
|
235889
235889
|
}
|
|
235890
235890
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
235891
|
-
const digest3 =
|
|
235891
|
+
const digest3 = createHash28("sha1").update(key + GUID).digest("base64");
|
|
235892
235892
|
const headers = [
|
|
235893
235893
|
"HTTP/1.1 101 Switching Protocols",
|
|
235894
235894
|
"Upgrade: websocket",
|
|
@@ -245608,8 +245608,8 @@ var require_pattern = __commonJS({
|
|
|
245608
245608
|
}
|
|
245609
245609
|
exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
245610
245610
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
245611
|
-
const
|
|
245612
|
-
return endsWithSlashGlobStar(pattern) || isStaticPattern(
|
|
245611
|
+
const basename30 = path11.basename(pattern);
|
|
245612
|
+
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename30);
|
|
245613
245613
|
}
|
|
245614
245614
|
exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
|
245615
245615
|
function expandPatternsWithBraceExpansion(patterns) {
|
|
@@ -248695,13 +248695,13 @@ Justification: ${justification || "(none provided)"}`,
|
|
|
248695
248695
|
}
|
|
248696
248696
|
const snapshot = JSON.stringify(this.selfState, null, 2);
|
|
248697
248697
|
try {
|
|
248698
|
-
const { createHash:
|
|
248698
|
+
const { createHash: createHash28 } = await import("node:crypto");
|
|
248699
248699
|
const snapshotDir = join30(this.cwd, ".omnius", "identity", "snapshots");
|
|
248700
248700
|
await mkdir6(snapshotDir, { recursive: true });
|
|
248701
248701
|
const version4 = this.selfState.version;
|
|
248702
248702
|
const snapshotPath = join30(snapshotDir, `v${version4}.json`);
|
|
248703
248703
|
await writeFile11(snapshotPath, snapshot, "utf8");
|
|
248704
|
-
const hash =
|
|
248704
|
+
const hash = createHash28("sha256").update(snapshot).digest("hex");
|
|
248705
248705
|
await writeFile11(join30(this.cwd, ".omnius", "identity", "latest-hash.txt"), hash, "utf8");
|
|
248706
248706
|
let ipfsCid = "";
|
|
248707
248707
|
try {
|
|
@@ -248834,8 +248834,8 @@ New: ${newNarrative.slice(0, 200)}...`,
|
|
|
248834
248834
|
}
|
|
248835
248835
|
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
248836
248836
|
createDefaultState() {
|
|
248837
|
-
const { createHash:
|
|
248838
|
-
const machineId =
|
|
248837
|
+
const { createHash: createHash28 } = __require("node:crypto");
|
|
248838
|
+
const machineId = createHash28("sha256").update(this.cwd).digest("hex").slice(0, 12);
|
|
248839
248839
|
return {
|
|
248840
248840
|
self_id: `omnius-${machineId}`,
|
|
248841
248841
|
version: 1,
|
|
@@ -248917,9 +248917,9 @@ New: ${newNarrative.slice(0, 200)}...`,
|
|
|
248917
248917
|
let cid;
|
|
248918
248918
|
if (this.selfState.version > prevVersion) {
|
|
248919
248919
|
try {
|
|
248920
|
-
const { createHash:
|
|
248920
|
+
const { createHash: createHash28 } = await import("node:crypto");
|
|
248921
248921
|
const stateJson = JSON.stringify(this.selfState);
|
|
248922
|
-
const hash =
|
|
248922
|
+
const hash = createHash28("sha256").update(stateJson).digest("hex").slice(0, 32);
|
|
248923
248923
|
const cidsPath = join30(this.cwd, ".omnius", "identity", "cids.json");
|
|
248924
248924
|
const cidsData = { latest: "", hash, version: this.selfState.version };
|
|
248925
248925
|
try {
|
|
@@ -251005,22 +251005,22 @@ async function runProcess2(command, args, options2) {
|
|
|
251005
251005
|
return;
|
|
251006
251006
|
const parts = raw.split(/[\r\n]+/).filter((part) => part.trim());
|
|
251007
251007
|
for (const part of parts.length > 0 ? parts : [raw]) {
|
|
251008
|
-
const
|
|
251009
|
-
if (!
|
|
251008
|
+
const clean5 = cleanProgressText(part);
|
|
251009
|
+
if (!clean5)
|
|
251010
251010
|
continue;
|
|
251011
251011
|
const now = Date.now();
|
|
251012
|
-
const structured = parseStructuredProgress(
|
|
251013
|
-
if (
|
|
251012
|
+
const structured = parseStructuredProgress(clean5);
|
|
251013
|
+
if (clean5 === lastProgress && now - lastProgressAt < 750)
|
|
251014
251014
|
continue;
|
|
251015
|
-
lastProgress =
|
|
251015
|
+
lastProgress = clean5;
|
|
251016
251016
|
lastProgressAt = now;
|
|
251017
251017
|
if (structured) {
|
|
251018
251018
|
options2.onProgress({ ...structured, elapsedMs: now - startedAt2 });
|
|
251019
251019
|
} else {
|
|
251020
251020
|
options2.onProgress({
|
|
251021
251021
|
stage: stream === "stderr" ? "download" : "process",
|
|
251022
|
-
message:
|
|
251023
|
-
percent: parsePercent(
|
|
251022
|
+
message: clean5.length > 220 ? clean5.slice(0, 217) + "..." : clean5,
|
|
251023
|
+
percent: parsePercent(clean5),
|
|
251024
251024
|
elapsedMs: now - startedAt2
|
|
251025
251025
|
});
|
|
251026
251026
|
}
|
|
@@ -251063,10 +251063,10 @@ async function runProcess2(command, args, options2) {
|
|
|
251063
251063
|
});
|
|
251064
251064
|
}
|
|
251065
251065
|
function trimProcessText(text, max = 1800) {
|
|
251066
|
-
const
|
|
251067
|
-
if (
|
|
251068
|
-
return
|
|
251069
|
-
return
|
|
251066
|
+
const clean5 = text.trim();
|
|
251067
|
+
if (clean5.length <= max)
|
|
251068
|
+
return clean5;
|
|
251069
|
+
return clean5.slice(0, max - 20) + "\n... (truncated)";
|
|
251070
251070
|
}
|
|
251071
251071
|
function formatDiffusersFailure(stderrOrStdout) {
|
|
251072
251072
|
const text = trimProcessText(stderrOrStdout);
|
|
@@ -252632,13 +252632,13 @@ async function runProcess3(command, args, options2) {
|
|
|
252632
252632
|
return;
|
|
252633
252633
|
const parts = raw.split(/[\r\n]+/).filter((part) => part.trim());
|
|
252634
252634
|
for (const part of parts.length > 0 ? parts : [raw]) {
|
|
252635
|
-
const
|
|
252636
|
-
if (!
|
|
252635
|
+
const clean5 = cleanProgressText2(part);
|
|
252636
|
+
if (!clean5)
|
|
252637
252637
|
continue;
|
|
252638
|
-
const jsonStart =
|
|
252638
|
+
const jsonStart = clean5.indexOf("{");
|
|
252639
252639
|
if (jsonStart >= 0) {
|
|
252640
252640
|
try {
|
|
252641
|
-
const payload = JSON.parse(
|
|
252641
|
+
const payload = JSON.parse(clean5.slice(jsonStart));
|
|
252642
252642
|
if (payload.omnius_progress && payload.stage && payload.message) {
|
|
252643
252643
|
const rawTotalBytes = typeof payload.totalBytes === "number" ? payload.totalBytes : typeof payload.total_bytes === "number" ? payload.total_bytes : void 0;
|
|
252644
252644
|
const rawDownloadedBytes = typeof payload.downloadedBytes === "number" ? payload.downloadedBytes : typeof payload.downloaded_bytes === "number" ? payload.downloaded_bytes : void 0;
|
|
@@ -252662,10 +252662,10 @@ async function runProcess3(command, args, options2) {
|
|
|
252662
252662
|
}
|
|
252663
252663
|
}
|
|
252664
252664
|
const now = Date.now();
|
|
252665
|
-
if (
|
|
252666
|
-
lastProgress =
|
|
252665
|
+
if (clean5 !== lastProgress || now - lastProgressAt > 1500) {
|
|
252666
|
+
lastProgress = clean5;
|
|
252667
252667
|
lastProgressAt = now;
|
|
252668
|
-
options2.onProgress({ stage: "process", message:
|
|
252668
|
+
options2.onProgress({ stage: "process", message: clean5.slice(0, 180), elapsedMs: now - startedAt2 });
|
|
252669
252669
|
}
|
|
252670
252670
|
}
|
|
252671
252671
|
};
|
|
@@ -252725,10 +252725,10 @@ async function runProcess3(command, args, options2) {
|
|
|
252725
252725
|
});
|
|
252726
252726
|
}
|
|
252727
252727
|
function trimProcessText2(text, max = 1800) {
|
|
252728
|
-
const
|
|
252729
|
-
if (
|
|
252730
|
-
return
|
|
252731
|
-
return
|
|
252728
|
+
const clean5 = text.trim();
|
|
252729
|
+
if (clean5.length <= max)
|
|
252730
|
+
return clean5;
|
|
252731
|
+
return clean5.slice(0, max - 20) + "\n... (truncated)";
|
|
252732
252732
|
}
|
|
252733
252733
|
async function pythonCanImport2(command, code8, repoRoot, env2) {
|
|
252734
252734
|
return (await pythonImportResult(command, code8, repoRoot, env2)).code === 0;
|
|
@@ -265551,7 +265551,7 @@ var require_typescript = __commonJS({
|
|
|
265551
265551
|
commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
|
|
265552
265552
|
commentPragmas: () => commentPragmas,
|
|
265553
265553
|
commonOptionsWithBuild: () => commonOptionsWithBuild,
|
|
265554
|
-
compact: () =>
|
|
265554
|
+
compact: () => compact2,
|
|
265555
265555
|
compareBooleans: () => compareBooleans,
|
|
265556
265556
|
compareComparableValues: () => compareComparableValues,
|
|
265557
265557
|
compareDataObjects: () => compareDataObjects,
|
|
@@ -268066,7 +268066,7 @@ var require_typescript = __commonJS({
|
|
|
268066
268066
|
}
|
|
268067
268067
|
return true;
|
|
268068
268068
|
}
|
|
268069
|
-
function
|
|
268069
|
+
function compact2(array) {
|
|
268070
268070
|
let result;
|
|
268071
268071
|
if (array !== void 0) {
|
|
268072
268072
|
for (let i2 = 0; i2 < array.length; i2++) {
|
|
@@ -317409,8 +317409,8 @@ ${lanes.join("\n")}
|
|
|
317409
317409
|
}
|
|
317410
317410
|
}
|
|
317411
317411
|
function isUseStrictPrologueDirective(node) {
|
|
317412
|
-
const
|
|
317413
|
-
return
|
|
317412
|
+
const nodeText22 = getSourceTextOfNodeFromSourceFile(file, node.expression);
|
|
317413
|
+
return nodeText22 === '"use strict"' || nodeText22 === "'use strict'";
|
|
317414
317414
|
}
|
|
317415
317415
|
function bindWorker(node) {
|
|
317416
317416
|
switch (node.kind) {
|
|
@@ -350504,20 +350504,20 @@ ${lanes.join("\n")}
|
|
|
350504
350504
|
return isNullableType(type) ? getNonNullableType(type) : type;
|
|
350505
350505
|
}
|
|
350506
350506
|
function reportObjectPossiblyNullOrUndefinedError(node, facts) {
|
|
350507
|
-
const
|
|
350507
|
+
const nodeText22 = isEntityNameExpression(node) ? entityNameToString(node) : void 0;
|
|
350508
350508
|
if (node.kind === 106) {
|
|
350509
350509
|
error2(node, Diagnostics.The_value_0_cannot_be_used_here, "null");
|
|
350510
350510
|
return;
|
|
350511
350511
|
}
|
|
350512
|
-
if (
|
|
350513
|
-
if (isIdentifier(node) &&
|
|
350512
|
+
if (nodeText22 !== void 0 && nodeText22.length < 100) {
|
|
350513
|
+
if (isIdentifier(node) && nodeText22 === "undefined") {
|
|
350514
350514
|
error2(node, Diagnostics.The_value_0_cannot_be_used_here, "undefined");
|
|
350515
350515
|
return;
|
|
350516
350516
|
}
|
|
350517
350517
|
error2(
|
|
350518
350518
|
node,
|
|
350519
350519
|
facts & 16777216 ? facts & 33554432 ? Diagnostics._0_is_possibly_null_or_undefined : Diagnostics._0_is_possibly_undefined : Diagnostics._0_is_possibly_null,
|
|
350520
|
-
|
|
350520
|
+
nodeText22
|
|
350521
350521
|
);
|
|
350522
350522
|
} else {
|
|
350523
350523
|
error2(
|
|
@@ -350535,9 +350535,9 @@ ${lanes.join("\n")}
|
|
|
350535
350535
|
function checkNonNullTypeWithReporter(type, node, reportError) {
|
|
350536
350536
|
if (strictNullChecks && type.flags & 2) {
|
|
350537
350537
|
if (isEntityNameExpression(node)) {
|
|
350538
|
-
const
|
|
350539
|
-
if (
|
|
350540
|
-
error2(node, Diagnostics._0_is_of_type_unknown,
|
|
350538
|
+
const nodeText22 = entityNameToString(node);
|
|
350539
|
+
if (nodeText22.length < 100) {
|
|
350540
|
+
error2(node, Diagnostics._0_is_of_type_unknown, nodeText22);
|
|
350541
350541
|
return errorType;
|
|
350542
350542
|
}
|
|
350543
350543
|
}
|
|
@@ -350563,13 +350563,13 @@ ${lanes.join("\n")}
|
|
|
350563
350563
|
const nonNullType = checkNonNullType(type, node);
|
|
350564
350564
|
if (nonNullType.flags & 16) {
|
|
350565
350565
|
if (isEntityNameExpression(node)) {
|
|
350566
|
-
const
|
|
350567
|
-
if (isIdentifier(node) &&
|
|
350568
|
-
error2(node, Diagnostics.The_value_0_cannot_be_used_here,
|
|
350566
|
+
const nodeText22 = entityNameToString(node);
|
|
350567
|
+
if (isIdentifier(node) && nodeText22 === "undefined") {
|
|
350568
|
+
error2(node, Diagnostics.The_value_0_cannot_be_used_here, nodeText22);
|
|
350569
350569
|
return nonNullType;
|
|
350570
350570
|
}
|
|
350571
|
-
if (
|
|
350572
|
-
error2(node, Diagnostics._0_is_possibly_undefined,
|
|
350571
|
+
if (nodeText22.length < 100) {
|
|
350572
|
+
error2(node, Diagnostics._0_is_possibly_undefined, nodeText22);
|
|
350573
350573
|
return nonNullType;
|
|
350574
350574
|
}
|
|
350575
350575
|
}
|
|
@@ -374137,7 +374137,7 @@ ${lanes.join("\n")}
|
|
|
374137
374137
|
node.operatorToken,
|
|
374138
374138
|
visitNode(node.right, visitor, isExpression)
|
|
374139
374139
|
);
|
|
374140
|
-
const expr = some(pendingExpressions) ? factory2.inlineExpressions(
|
|
374140
|
+
const expr = some(pendingExpressions) ? factory2.inlineExpressions(compact2([...pendingExpressions, node])) : node;
|
|
374141
374141
|
pendingExpressions = savedPendingExpressions;
|
|
374142
374142
|
return expr;
|
|
374143
374143
|
}
|
|
@@ -394406,7 +394406,7 @@ ${lanes.join("\n")}
|
|
|
394406
394406
|
let parameterProperties;
|
|
394407
394407
|
if (ctor) {
|
|
394408
394408
|
const oldDiag2 = getSymbolAccessibilityDiagnostic;
|
|
394409
|
-
parameterProperties =
|
|
394409
|
+
parameterProperties = compact2(flatMap(ctor.parameters, (param) => {
|
|
394410
394410
|
if (!hasSyntacticModifier(
|
|
394411
394411
|
param,
|
|
394412
394412
|
31
|
|
@@ -402392,9 +402392,9 @@ ${lanes.join("\n")}
|
|
|
402392
402392
|
/*ignoreCase*/
|
|
402393
402393
|
false
|
|
402394
402394
|
)) {
|
|
402395
|
-
const
|
|
402396
|
-
if (
|
|
402397
|
-
const name10 = removeSuffix(removePrefix(
|
|
402395
|
+
const basename30 = getBaseFileName(a2.fileName);
|
|
402396
|
+
if (basename30 === "lib.d.ts" || basename30 === "lib.es6.d.ts") return 0;
|
|
402397
|
+
const name10 = removeSuffix(removePrefix(basename30, "lib."), ".d.ts");
|
|
402398
402398
|
const index = libs.indexOf(name10);
|
|
402399
402399
|
if (index !== -1) return index + 1;
|
|
402400
402400
|
}
|
|
@@ -411161,7 +411161,7 @@ ${lanes.join("\n")}
|
|
|
411161
411161
|
startWatching(state, buildOrder);
|
|
411162
411162
|
return isCircularBuildOrder(buildOrder) ? 4 : !buildOrder.some((p2) => state.diagnostics.has(toResolvedConfigFilePath(state, p2))) ? 0 : successfulProjects ? 2 : 1;
|
|
411163
411163
|
}
|
|
411164
|
-
function
|
|
411164
|
+
function clean5(state, project, onlyReferences) {
|
|
411165
411165
|
mark("SolutionBuilder::beforeClean");
|
|
411166
411166
|
const result = cleanWorker(state, project, onlyReferences);
|
|
411167
411167
|
mark("SolutionBuilder::afterClean");
|
|
@@ -411450,7 +411450,7 @@ ${lanes.join("\n")}
|
|
|
411450
411450
|
const state = createSolutionBuilderState(watch, hostOrHostWithWatch, rootNames, options2, baseWatchOptions);
|
|
411451
411451
|
return {
|
|
411452
411452
|
build: (project, cancellationToken, writeFile23, getCustomTransformers) => build(state, project, cancellationToken, writeFile23, getCustomTransformers),
|
|
411453
|
-
clean: (project) =>
|
|
411453
|
+
clean: (project) => clean5(state, project),
|
|
411454
411454
|
buildReferences: (project, cancellationToken, writeFile23, getCustomTransformers) => build(
|
|
411455
411455
|
state,
|
|
411456
411456
|
project,
|
|
@@ -411460,7 +411460,7 @@ ${lanes.join("\n")}
|
|
|
411460
411460
|
/*onlyReferences*/
|
|
411461
411461
|
true
|
|
411462
411462
|
),
|
|
411463
|
-
cleanReferences: (project) =>
|
|
411463
|
+
cleanReferences: (project) => clean5(
|
|
411464
411464
|
state,
|
|
411465
411465
|
project,
|
|
411466
411466
|
/*onlyReferences*/
|
|
@@ -421352,7 +421352,7 @@ interface Symbol {
|
|
|
421352
421352
|
parent = void 0;
|
|
421353
421353
|
emptyChildItemArray = [];
|
|
421354
421354
|
}
|
|
421355
|
-
function
|
|
421355
|
+
function nodeText2(node) {
|
|
421356
421356
|
return cleanText(node.getText(curSourceFile));
|
|
421357
421357
|
}
|
|
421358
421358
|
function navigationBarNodeKind(n2) {
|
|
@@ -421667,7 +421667,7 @@ interface Symbol {
|
|
|
421667
421667
|
const nameToItems = /* @__PURE__ */ new Map();
|
|
421668
421668
|
filterMutate(children2, (child, index) => {
|
|
421669
421669
|
const declName = child.name || getNameOfDeclaration(child.node);
|
|
421670
|
-
const name10 = declName &&
|
|
421670
|
+
const name10 = declName && nodeText2(declName);
|
|
421671
421671
|
if (!name10) {
|
|
421672
421672
|
return true;
|
|
421673
421673
|
}
|
|
@@ -421893,7 +421893,7 @@ interface Symbol {
|
|
|
421893
421893
|
return cleanText(getModuleName(node));
|
|
421894
421894
|
}
|
|
421895
421895
|
if (name10) {
|
|
421896
|
-
const text = isIdentifier(name10) ? name10.text : isElementAccessExpression(name10) ? `[${
|
|
421896
|
+
const text = isIdentifier(name10) ? name10.text : isElementAccessExpression(name10) ? `[${nodeText2(name10.argumentExpression)}]` : nodeText2(name10);
|
|
421897
421897
|
if (text.length > 0) {
|
|
421898
421898
|
return cleanText(text);
|
|
421899
421899
|
}
|
|
@@ -422056,9 +422056,9 @@ interface Symbol {
|
|
|
422056
422056
|
} else if (isVariableDeclaration(parent2)) {
|
|
422057
422057
|
return cleanText(declarationNameToString(parent2.name));
|
|
422058
422058
|
} else if (isBinaryExpression(parent2) && parent2.operatorToken.kind === 64) {
|
|
422059
|
-
return
|
|
422059
|
+
return nodeText2(parent2.left).replace(whiteSpaceRegex, "");
|
|
422060
422060
|
} else if (isPropertyAssignment(parent2)) {
|
|
422061
|
-
return
|
|
422061
|
+
return nodeText2(parent2.name);
|
|
422062
422062
|
} else if (getSyntacticModifierFlags(node) & 2048) {
|
|
422063
422063
|
return "default";
|
|
422064
422064
|
} else if (isClassLike(node)) {
|
|
@@ -431487,7 +431487,7 @@ ${newComment.split("\n").map((c9) => ` * ${c9}`).join("\n")}
|
|
|
431487
431487
|
}
|
|
431488
431488
|
const checker = context2.program.getTypeChecker();
|
|
431489
431489
|
const trackChanges = (cb) => ts_textChanges_exports.ChangeTracker.with(context2, cb);
|
|
431490
|
-
return
|
|
431490
|
+
return compact2([
|
|
431491
431491
|
getDeclarationSiteFix(context2, expression, errorCode, checker, trackChanges),
|
|
431492
431492
|
getUseSiteFix(context2, expression, errorCode, checker, trackChanges)
|
|
431493
431493
|
]);
|
|
@@ -455078,7 +455078,7 @@ ${content}
|
|
|
455078
455078
|
const lastToken = last2(children2);
|
|
455079
455079
|
const separateLastToken = separateTrailingSemicolon && lastToken.kind === 27;
|
|
455080
455080
|
const rightChildren = children2.slice(splitTokenIndex + 1, separateLastToken ? children2.length - 1 : void 0);
|
|
455081
|
-
const result =
|
|
455081
|
+
const result = compact2([
|
|
455082
455082
|
leftChildren.length ? createSyntaxList2(leftChildren) : void 0,
|
|
455083
455083
|
splitToken,
|
|
455084
455084
|
rightChildren.length ? createSyntaxList2(rightChildren) : void 0
|
|
@@ -461802,7 +461802,7 @@ ${options2.prefix}` : "\n" : options2.prefix
|
|
|
461802
461802
|
commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
|
|
461803
461803
|
commentPragmas: () => commentPragmas,
|
|
461804
461804
|
commonOptionsWithBuild: () => commonOptionsWithBuild,
|
|
461805
|
-
compact: () =>
|
|
461805
|
+
compact: () => compact2,
|
|
461806
461806
|
compareBooleans: () => compareBooleans,
|
|
461807
461807
|
compareComparableValues: () => compareComparableValues,
|
|
461808
461808
|
compareDataObjects: () => compareDataObjects,
|
|
@@ -466320,8 +466320,8 @@ ${options2.prefix}` : "\n" : options2.prefix
|
|
|
466320
466320
|
}
|
|
466321
466321
|
};
|
|
466322
466322
|
for (const file of files) {
|
|
466323
|
-
const
|
|
466324
|
-
if (
|
|
466323
|
+
const basename30 = getBaseFileName(file);
|
|
466324
|
+
if (basename30 === "package.json" || basename30 === "bower.json") {
|
|
466325
466325
|
createProjectWatcher(
|
|
466326
466326
|
file,
|
|
466327
466327
|
"FileWatcher"
|
|
@@ -470005,8 +470005,8 @@ All files are: ${JSON.stringify(names)}`,
|
|
|
470005
470005
|
var _a;
|
|
470006
470006
|
const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
|
|
470007
470007
|
if (!fileOrDirectoryPath) return;
|
|
470008
|
-
const
|
|
470009
|
-
if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (
|
|
470008
|
+
const basename30 = getBaseFileName(fileOrDirectoryPath);
|
|
470009
|
+
if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (basename30 === "package.json" || basename30 === "node_modules")) {
|
|
470010
470010
|
result.affectedModuleSpecifierCacheProjects.forEach((project) => {
|
|
470011
470011
|
var _a2;
|
|
470012
470012
|
(_a2 = project.getModuleSpecifierCache()) == null ? void 0 : _a2.clear();
|
|
@@ -478909,7 +478909,7 @@ var require_path_browserify = __commonJS({
|
|
|
478909
478909
|
if (hasRoot && end === 1) return "//";
|
|
478910
478910
|
return path11.slice(0, end);
|
|
478911
478911
|
},
|
|
478912
|
-
basename: function
|
|
478912
|
+
basename: function basename30(path11, ext) {
|
|
478913
478913
|
if (ext !== void 0 && typeof ext !== "string") throw new TypeError('"ext" argument must be a string');
|
|
478914
478914
|
assertPath(path11);
|
|
478915
478915
|
var start2 = 0;
|
|
@@ -512614,6 +512614,11 @@ var init_visual_memory = __esm({
|
|
|
512614
512614
|
type: "number",
|
|
512615
512615
|
description: "Recognition confidence threshold 0-1 (default: 0.5 for faces, 0.3 for objects)."
|
|
512616
512616
|
},
|
|
512617
|
+
format: {
|
|
512618
|
+
type: "string",
|
|
512619
|
+
enum: ["text", "json"],
|
|
512620
|
+
description: "Return format for identify/recognize results. Use json when another tool or service needs machine-readable matches."
|
|
512621
|
+
},
|
|
512617
512622
|
labels: {
|
|
512618
512623
|
type: "array",
|
|
512619
512624
|
description: "Text labels to score against image (for CLIP 'recognize' or 'describe').",
|
|
@@ -512661,6 +512666,7 @@ var init_visual_memory = __esm({
|
|
|
512661
512666
|
if (!image || !existsSync45(image)) {
|
|
512662
512667
|
return { success: false, output: "", error: "Provide a valid image path.", durationMs: performance.now() - start2 };
|
|
512663
512668
|
}
|
|
512669
|
+
const wantsJson = args["format"] === "json" || args["json"] === true;
|
|
512664
512670
|
const result = await this.runVisionPython(`
|
|
512665
512671
|
import json, sys
|
|
512666
512672
|
from insightface.app import FaceAnalysis
|
|
@@ -512690,6 +512696,10 @@ print(json.dumps({"success": True, "faces": results, "total": len(results)}))
|
|
|
512690
512696
|
`, 6e4);
|
|
512691
512697
|
if (!result.success)
|
|
512692
512698
|
return { success: false, output: "", error: result.error, durationMs: performance.now() - start2 };
|
|
512699
|
+
if (wantsJson) {
|
|
512700
|
+
const payload = JSON.stringify(result);
|
|
512701
|
+
return { success: true, output: payload, llmContent: payload, durationMs: performance.now() - start2 };
|
|
512702
|
+
}
|
|
512693
512703
|
return { success: true, output: `Detected ${result.total} face(s):
|
|
512694
512704
|
${JSON.stringify(result.faces, null, 2)}`, durationMs: performance.now() - start2 };
|
|
512695
512705
|
}
|
|
@@ -512771,6 +512781,7 @@ print(json.dumps({
|
|
|
512771
512781
|
if (!image || !existsSync45(image))
|
|
512772
512782
|
return { success: false, output: "", error: "Provide a valid image path.", durationMs: performance.now() - start2 };
|
|
512773
512783
|
const threshold = args["threshold"] || 0.5;
|
|
512784
|
+
const wantsJson = args["format"] === "json" || args["json"] === true;
|
|
512774
512785
|
const result = await this.runVisionPython(`
|
|
512775
512786
|
import json, sys, os, numpy as np
|
|
512776
512787
|
from insightface.app import FaceAnalysis
|
|
@@ -512838,6 +512849,15 @@ print(json.dumps({"success": True, "faces": results, "total_detected": len(faces
|
|
|
512838
512849
|
`, 6e4);
|
|
512839
512850
|
if (!result.success)
|
|
512840
512851
|
return { success: false, output: "", error: result.error, durationMs: performance.now() - start2 };
|
|
512852
|
+
if (wantsJson) {
|
|
512853
|
+
const payload = JSON.stringify(result);
|
|
512854
|
+
return {
|
|
512855
|
+
success: true,
|
|
512856
|
+
output: payload,
|
|
512857
|
+
llmContent: payload,
|
|
512858
|
+
durationMs: performance.now() - start2
|
|
512859
|
+
};
|
|
512860
|
+
}
|
|
512841
512861
|
const faces = result.faces || [];
|
|
512842
512862
|
if (faces.length === 0) {
|
|
512843
512863
|
return { success: true, output: "No faces detected in image.", durationMs: performance.now() - start2 };
|
|
@@ -512934,6 +512954,7 @@ print(json.dumps({
|
|
|
512934
512954
|
return { success: false, output: "", error: "Provide a valid image path.", durationMs: performance.now() - start2 };
|
|
512935
512955
|
const threshold = args["threshold"] || 0.3;
|
|
512936
512956
|
const extraLabels = args["labels"] || [];
|
|
512957
|
+
const wantsJson = args["format"] === "json" || args["json"] === true;
|
|
512937
512958
|
const result = await this.runVisionPython(`
|
|
512938
512959
|
import json, sys, os, numpy as np
|
|
512939
512960
|
import torch
|
|
@@ -513009,6 +513030,10 @@ print(json.dumps({
|
|
|
513009
513030
|
`, 12e4);
|
|
513010
513031
|
if (!result.success)
|
|
513011
513032
|
return { success: false, output: "", error: result.error, durationMs: performance.now() - start2 };
|
|
513033
|
+
if (wantsJson) {
|
|
513034
|
+
const payload = JSON.stringify(result);
|
|
513035
|
+
return { success: true, output: payload, llmContent: payload, durationMs: performance.now() - start2 };
|
|
513036
|
+
}
|
|
513012
513037
|
const matches = (result.matches || []).filter((m2) => m2.recognized);
|
|
513013
513038
|
const lines = matches.map((m2) => ` ${m2.label}: ${(m2.blended_score * 100).toFixed(0)}% (image=${(m2.image_similarity * 100).toFixed(0)}%, text=${(m2.text_similarity * 100).toFixed(0)}%)`);
|
|
513014
513039
|
let output = matches.length > 0 ? `Recognized ${result.recognized_count} object(s):
|
|
@@ -524884,6 +524909,9 @@ var init_temporalGraph = __esm({
|
|
|
524884
524909
|
nodesByType(nodeType, limit = 100) {
|
|
524885
524910
|
return this.db.prepare("SELECT * FROM kg_nodes WHERE node_type = ? ORDER BY mention_count DESC LIMIT ?").all(nodeType, limit).map((r2) => this.rowToNode(r2));
|
|
524886
524911
|
}
|
|
524912
|
+
allNodes(limit = 1e3) {
|
|
524913
|
+
return this.db.prepare("SELECT * FROM kg_nodes ORDER BY mention_count DESC, last_seen DESC LIMIT ?").all(limit).map((r2) => this.rowToNode(r2));
|
|
524914
|
+
}
|
|
524887
524915
|
/**
|
|
524888
524916
|
* Find code-symbol entity nodes by the inner symbol name. Symbol nodes
|
|
524889
524917
|
* stored by the cross-graph link layer use text `sym:{name}@{path}`;
|
|
@@ -524977,6 +525005,26 @@ var init_temporalGraph = __esm({
|
|
|
524977
525005
|
edge: this.rowToEdge(r2)
|
|
524978
525006
|
}));
|
|
524979
525007
|
}
|
|
525008
|
+
currentEdgesForSourceEpisode(sourceEpisodeId, limit = 200) {
|
|
525009
|
+
return this.db.prepare(`
|
|
525010
|
+
SELECT * FROM kg_edges
|
|
525011
|
+
WHERE source_episode_id = ? AND valid_until IS NULL
|
|
525012
|
+
ORDER BY confidence DESC, valid_from DESC
|
|
525013
|
+
LIMIT ?
|
|
525014
|
+
`).all(sourceEpisodeId, limit).map((r2) => this.rowToEdge(r2));
|
|
525015
|
+
}
|
|
525016
|
+
currentEdgesForSourceEpisodes(sourceEpisodeIds, limit = 1e3) {
|
|
525017
|
+
const ids = [...new Set(sourceEpisodeIds.filter(Boolean))];
|
|
525018
|
+
if (ids.length === 0)
|
|
525019
|
+
return [];
|
|
525020
|
+
const placeholders = ids.map(() => "?").join(", ");
|
|
525021
|
+
return this.db.prepare(`
|
|
525022
|
+
SELECT * FROM kg_edges
|
|
525023
|
+
WHERE source_episode_id IN (${placeholders}) AND valid_until IS NULL
|
|
525024
|
+
ORDER BY confidence DESC, valid_from DESC
|
|
525025
|
+
LIMIT ?
|
|
525026
|
+
`).all(...ids, limit).map((r2) => this.rowToEdge(r2));
|
|
525027
|
+
}
|
|
524980
525028
|
// ─── Statistics ──────────────────────────────────────────────────────────
|
|
524981
525029
|
nodeCount() {
|
|
524982
525030
|
return this.db.prepare("SELECT COUNT(*) as n FROM kg_nodes").get().n;
|
|
@@ -525118,6 +525166,7 @@ var init_multimodalIdentity = __esm({
|
|
|
525118
525166
|
const sender = input.sender;
|
|
525119
525167
|
const content = buildEpisodeContent(input);
|
|
525120
525168
|
const metadata = {
|
|
525169
|
+
...input.metadata || {},
|
|
525121
525170
|
mmidVersion: 1,
|
|
525122
525171
|
sourceSurface,
|
|
525123
525172
|
scope,
|
|
@@ -525132,6 +525181,7 @@ var init_multimodalIdentity = __esm({
|
|
|
525132
525181
|
embeddingSpaces: this.embeddingSpaces(input.embeddings)
|
|
525133
525182
|
};
|
|
525134
525183
|
const episodeId = this.episodeStore.insert({
|
|
525184
|
+
sessionId: input.sessionId,
|
|
525135
525185
|
modality,
|
|
525136
525186
|
content,
|
|
525137
525187
|
metadata,
|
|
@@ -525205,6 +525255,7 @@ var init_multimodalIdentity = __esm({
|
|
|
525205
525255
|
if (input.transcript && input.transcript.trim()) {
|
|
525206
525256
|
const transcriptMeta = { ...metadata, sourceEpisodeId: episodeId, transcriptOf: episodeId };
|
|
525207
525257
|
const transcriptEpisodeId = this.episodeStore.insert({
|
|
525258
|
+
sessionId: input.sessionId,
|
|
525208
525259
|
modality: "text",
|
|
525209
525260
|
content: input.transcript,
|
|
525210
525261
|
metadata: transcriptMeta,
|
|
@@ -525380,6 +525431,158 @@ var init_gistCompressor = __esm({
|
|
|
525380
525431
|
}
|
|
525381
525432
|
});
|
|
525382
525433
|
|
|
525434
|
+
// packages/memory/dist/graphWalk.js
|
|
525435
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
525436
|
+
function seededUnit(seed) {
|
|
525437
|
+
const digest3 = createHash12("sha256").update(seed || "graph-walk").digest();
|
|
525438
|
+
const value2 = digest3.readUInt32BE(0);
|
|
525439
|
+
return value2 / 4294967295;
|
|
525440
|
+
}
|
|
525441
|
+
function edgeKey(edge) {
|
|
525442
|
+
return String(edge.id ?? `${edge.srcId}:${edge.dstId}:${edge.relation}:${edge.sourceEpisodeId ?? ""}`);
|
|
525443
|
+
}
|
|
525444
|
+
function recencyScore(timestamp, now) {
|
|
525445
|
+
if (!timestamp || !Number.isFinite(timestamp))
|
|
525446
|
+
return 0;
|
|
525447
|
+
const ageMs = Math.max(0, now - timestamp);
|
|
525448
|
+
return Math.exp(-ageMs / (7 * 24 * 60 * 6e4));
|
|
525449
|
+
}
|
|
525450
|
+
function relationAllowed(edge, options2) {
|
|
525451
|
+
if (options2.allowedRelations?.length && !options2.allowedRelations.includes(edge.relation))
|
|
525452
|
+
return false;
|
|
525453
|
+
if (options2.deniedRelations?.includes(edge.relation))
|
|
525454
|
+
return false;
|
|
525455
|
+
return true;
|
|
525456
|
+
}
|
|
525457
|
+
function selectInnerGraphCandidates(graph, candidates, options2 = {}) {
|
|
525458
|
+
const minDegree = Math.max(1, Math.floor(options2.minDegree ?? 2));
|
|
525459
|
+
const candidateEpisodeIds = [...new Set(candidates.map((candidate) => candidate.episode.id).filter(Boolean))];
|
|
525460
|
+
const candidateScore = new Map(candidates.map((candidate) => [candidate.episode.id, candidate.score ?? 0]));
|
|
525461
|
+
const candidateTimestamp = new Map(candidates.map((candidate) => [candidate.episode.id, candidate.episode.timestamp]));
|
|
525462
|
+
const sourceEdges = graph.currentEdgesForSourceEpisodes(candidateEpisodeIds, Math.max(1e3, candidateEpisodeIds.length * 20));
|
|
525463
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
525464
|
+
for (const edge of sourceEdges) {
|
|
525465
|
+
if (!relationAllowed(edge, options2))
|
|
525466
|
+
continue;
|
|
525467
|
+
const episodeId = edge.sourceEpisodeId;
|
|
525468
|
+
if (!episodeId || !candidateEpisodeIds.includes(episodeId))
|
|
525469
|
+
continue;
|
|
525470
|
+
for (const nodeId of [edge.srcId, edge.dstId]) {
|
|
525471
|
+
const node = graph.getNode(nodeId);
|
|
525472
|
+
if (!node)
|
|
525473
|
+
continue;
|
|
525474
|
+
const entry = byNode.get(nodeId) ?? { node, candidateEpisodeIds: /* @__PURE__ */ new Set(), edges: /* @__PURE__ */ new Map() };
|
|
525475
|
+
entry.candidateEpisodeIds.add(episodeId);
|
|
525476
|
+
entry.edges.set(edgeKey(edge), edge);
|
|
525477
|
+
byNode.set(nodeId, entry);
|
|
525478
|
+
}
|
|
525479
|
+
}
|
|
525480
|
+
const now = Date.now();
|
|
525481
|
+
const results = [];
|
|
525482
|
+
for (const entry of byNode.values()) {
|
|
525483
|
+
const allEdges = graph.currentEdges(entry.node.id).filter((edge) => relationAllowed(edge, options2));
|
|
525484
|
+
const degree = allEdges.length;
|
|
525485
|
+
if (degree < minDegree)
|
|
525486
|
+
continue;
|
|
525487
|
+
const relationDiversity = new Set(allEdges.map((edge) => edge.relation)).size;
|
|
525488
|
+
const sourceEpisodeIds = [...new Set(allEdges.map((edge) => edge.sourceEpisodeId).filter((id) => Boolean(id)))];
|
|
525489
|
+
const selectedEpisodeIds = [...entry.candidateEpisodeIds];
|
|
525490
|
+
const sourceStrength = sourceEpisodeIds.length;
|
|
525491
|
+
const candidateStrength = selectedEpisodeIds.reduce((sum, id) => sum + (candidateScore.get(id) ?? 0), 0);
|
|
525492
|
+
const recency = selectedEpisodeIds.reduce((sum, id) => sum + recencyScore(candidateTimestamp.get(id), now), 0);
|
|
525493
|
+
const confidence2 = allEdges.reduce((sum, edge) => sum + (Number.isFinite(edge.confidence) ? edge.confidence : 0), 0) / Math.max(1, allEdges.length);
|
|
525494
|
+
const score = degree * 1.5 + relationDiversity * 1.2 + sourceStrength * 1.4 + selectedEpisodeIds.length * 1.6 + candidateStrength + recency + confidence2 + Math.log1p(entry.node.mentionCount);
|
|
525495
|
+
results.push({
|
|
525496
|
+
node: entry.node,
|
|
525497
|
+
score,
|
|
525498
|
+
degree,
|
|
525499
|
+
relationDiversity,
|
|
525500
|
+
sourceEpisodeIds,
|
|
525501
|
+
candidateEpisodeIds: selectedEpisodeIds,
|
|
525502
|
+
edges: allEdges
|
|
525503
|
+
});
|
|
525504
|
+
}
|
|
525505
|
+
return results.sort((a2, b) => b.score - a2.score || b.degree - a2.degree || a2.node.text.localeCompare(b.node.text));
|
|
525506
|
+
}
|
|
525507
|
+
function chooseInnerGraphSeed(candidates, seed = "graph-walk", topCandidatePool = 16) {
|
|
525508
|
+
if (candidates.length === 0)
|
|
525509
|
+
return null;
|
|
525510
|
+
const pool3 = candidates.slice(0, Math.max(1, Math.min(topCandidatePool, candidates.length)));
|
|
525511
|
+
const index = Math.min(pool3.length - 1, Math.floor(seededUnit(seed) * pool3.length));
|
|
525512
|
+
return pool3[index] ?? null;
|
|
525513
|
+
}
|
|
525514
|
+
function walkGraphFromSeed(graph, seed, options2 = {}) {
|
|
525515
|
+
const maxDepth = Math.max(0, Math.floor(options2.maxDepth ?? 2));
|
|
525516
|
+
const maxVisitedNodes = Math.max(1, Math.floor(options2.maxVisitedNodes ?? 64));
|
|
525517
|
+
const maxTraversedEdges = Math.max(1, Math.floor(options2.maxTraversedEdges ?? 160));
|
|
525518
|
+
const maxSourceEpisodes = Math.max(1, Math.floor(options2.maxSourceEpisodes ?? 80));
|
|
525519
|
+
const visited = /* @__PURE__ */ new Map();
|
|
525520
|
+
const depthByNodeId = {};
|
|
525521
|
+
const traversed = /* @__PURE__ */ new Map();
|
|
525522
|
+
const sourceEpisodeIds = [];
|
|
525523
|
+
const seenSourceEpisodes = /* @__PURE__ */ new Set();
|
|
525524
|
+
const queue = [{ node: seed.node, depth: 0 }];
|
|
525525
|
+
visited.set(seed.node.id, seed.node);
|
|
525526
|
+
depthByNodeId[seed.node.id] = 0;
|
|
525527
|
+
for (const id of seed.sourceEpisodeIds) {
|
|
525528
|
+
if (seenSourceEpisodes.size >= maxSourceEpisodes)
|
|
525529
|
+
break;
|
|
525530
|
+
seenSourceEpisodes.add(id);
|
|
525531
|
+
sourceEpisodeIds.push(id);
|
|
525532
|
+
}
|
|
525533
|
+
while (queue.length > 0) {
|
|
525534
|
+
const item = queue.shift();
|
|
525535
|
+
if (item.depth >= maxDepth)
|
|
525536
|
+
continue;
|
|
525537
|
+
const neighbors2 = graph.neighbors(item.node.id).filter(({ edge }) => relationAllowed(edge, options2)).sort((a2, b) => b.edge.confidence - a2.edge.confidence || b.node.mentionCount - a2.node.mentionCount);
|
|
525538
|
+
for (const { node, edge } of neighbors2) {
|
|
525539
|
+
if (traversed.size >= maxTraversedEdges)
|
|
525540
|
+
break;
|
|
525541
|
+
traversed.set(edgeKey(edge), edge);
|
|
525542
|
+
if (edge.sourceEpisodeId && !seenSourceEpisodes.has(edge.sourceEpisodeId) && seenSourceEpisodes.size < maxSourceEpisodes) {
|
|
525543
|
+
seenSourceEpisodes.add(edge.sourceEpisodeId);
|
|
525544
|
+
sourceEpisodeIds.push(edge.sourceEpisodeId);
|
|
525545
|
+
}
|
|
525546
|
+
if (!visited.has(node.id) && visited.size < maxVisitedNodes) {
|
|
525547
|
+
visited.set(node.id, node);
|
|
525548
|
+
depthByNodeId[node.id] = item.depth + 1;
|
|
525549
|
+
queue.push({ node, depth: item.depth + 1 });
|
|
525550
|
+
}
|
|
525551
|
+
}
|
|
525552
|
+
}
|
|
525553
|
+
return {
|
|
525554
|
+
visitedNodes: [...visited.values()],
|
|
525555
|
+
traversedEdges: [...traversed.values()],
|
|
525556
|
+
sourceEpisodeIds,
|
|
525557
|
+
depthByNodeId
|
|
525558
|
+
};
|
|
525559
|
+
}
|
|
525560
|
+
function selectAndWalkGraphCandidate(graph, candidates, options2 = {}) {
|
|
525561
|
+
const eligibleCandidates = selectInnerGraphCandidates(graph, candidates, options2);
|
|
525562
|
+
const seed = chooseInnerGraphSeed(eligibleCandidates, options2.seed, options2.topCandidatePool);
|
|
525563
|
+
if (!seed) {
|
|
525564
|
+
return {
|
|
525565
|
+
seed: null,
|
|
525566
|
+
eligibleCandidates,
|
|
525567
|
+
visitedNodes: [],
|
|
525568
|
+
traversedEdges: [],
|
|
525569
|
+
sourceEpisodeIds: [],
|
|
525570
|
+
depthByNodeId: {},
|
|
525571
|
+
fallbackReason: candidates.length === 0 ? "no episode candidates" : "no eligible inner graph nodes"
|
|
525572
|
+
};
|
|
525573
|
+
}
|
|
525574
|
+
return {
|
|
525575
|
+
seed,
|
|
525576
|
+
eligibleCandidates,
|
|
525577
|
+
...walkGraphFromSeed(graph, seed, options2)
|
|
525578
|
+
};
|
|
525579
|
+
}
|
|
525580
|
+
var init_graphWalk = __esm({
|
|
525581
|
+
"packages/memory/dist/graphWalk.js"() {
|
|
525582
|
+
"use strict";
|
|
525583
|
+
}
|
|
525584
|
+
});
|
|
525585
|
+
|
|
525383
525586
|
// packages/memory/dist/embeddings.js
|
|
525384
525587
|
async function generateEmbedding(text, config) {
|
|
525385
525588
|
const cfg = { ...DEFAULT_CONFIG5, ...config };
|
|
@@ -528615,8 +528818,8 @@ function slowWaveReplay(db, options2 = {}) {
|
|
|
528615
528818
|
try {
|
|
528616
528819
|
const referenced = db.prepare(`SELECT 1 FROM kg_edges WHERE source_episode_id = ? LIMIT 1`).get(id);
|
|
528617
528820
|
if (!referenced) {
|
|
528618
|
-
const
|
|
528619
|
-
const newNodeId = options2.graph.upsertNode({ text:
|
|
528821
|
+
const nodeText2 = `episode:${id}`;
|
|
528822
|
+
const newNodeId = options2.graph.upsertNode({ text: nodeText2, nodeType: "event" });
|
|
528620
528823
|
if (newNodeId)
|
|
528621
528824
|
integratedNodes.push(newNodeId);
|
|
528622
528825
|
}
|
|
@@ -529362,7 +529565,7 @@ var init_memoryStageContext = __esm({
|
|
|
529362
529565
|
});
|
|
529363
529566
|
|
|
529364
529567
|
// packages/memory/dist/sessionGist.js
|
|
529365
|
-
import { createHash as
|
|
529568
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
529366
529569
|
function inferDomain(input) {
|
|
529367
529570
|
const blob = [
|
|
529368
529571
|
input.goal,
|
|
@@ -529387,7 +529590,7 @@ function inferDomain(input) {
|
|
|
529387
529590
|
return ranked[0][0];
|
|
529388
529591
|
}
|
|
529389
529592
|
function computeGoalHash(goal) {
|
|
529390
|
-
return
|
|
529593
|
+
return createHash13("sha256").update(goal.trim().toLowerCase()).digest("hex").slice(0, 16);
|
|
529391
529594
|
}
|
|
529392
529595
|
function clip(text, n2) {
|
|
529393
529596
|
if (!text)
|
|
@@ -529598,12 +529801,12 @@ var init_toolOutcomes = __esm({
|
|
|
529598
529801
|
});
|
|
529599
529802
|
|
|
529600
529803
|
// packages/memory/dist/stagnationRecipes.js
|
|
529601
|
-
import { createHash as
|
|
529804
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
529602
529805
|
function fingerprintSignature(fp) {
|
|
529603
529806
|
const normClusters = (fp.errorClusters ?? []).map((s2) => (s2 || "").toLowerCase().replace(/[0-9]+/g, "N").replace(/\s+/g, " ").trim()).filter(Boolean).sort();
|
|
529604
529807
|
const tool = (fp.stuckTool ?? "").toLowerCase().trim();
|
|
529605
529808
|
const blob = `tool=${tool};clusters=${normClusters.join("|")}`;
|
|
529606
|
-
return
|
|
529809
|
+
return createHash14("sha256").update(blob).digest("hex").slice(0, 16);
|
|
529607
529810
|
}
|
|
529608
529811
|
function crystallize(store2, input) {
|
|
529609
529812
|
const sig = fingerprintSignature(input.fingerprint);
|
|
@@ -529660,7 +529863,7 @@ var init_stagnationRecipes = __esm({
|
|
|
529660
529863
|
});
|
|
529661
529864
|
|
|
529662
529865
|
// packages/memory/dist/codebaseMap.js
|
|
529663
|
-
import { createHash as
|
|
529866
|
+
import { createHash as createHash15, randomUUID as randomUUID12 } from "node:crypto";
|
|
529664
529867
|
function freshNodeId() {
|
|
529665
529868
|
return randomUUID12();
|
|
529666
529869
|
}
|
|
@@ -529674,7 +529877,7 @@ var init_codebaseMap = __esm({
|
|
|
529674
529877
|
touchCount = /* @__PURE__ */ new Map();
|
|
529675
529878
|
constructor(db, repoRoot, commitSha) {
|
|
529676
529879
|
this.db = db;
|
|
529677
|
-
this.repoFp =
|
|
529880
|
+
this.repoFp = createHash15("sha256").update(`${repoRoot}::${commitSha ?? "no-commit"}`).digest("hex").slice(0, 16);
|
|
529678
529881
|
this.ensureSchema();
|
|
529679
529882
|
}
|
|
529680
529883
|
ensureSchema() {
|
|
@@ -529856,7 +530059,7 @@ var init_codebaseMap = __esm({
|
|
|
529856
530059
|
}
|
|
529857
530060
|
/** Stable composite id: `<kind>:<sha16(path)>` so insert ON CONFLICT works. */
|
|
529858
530061
|
idFor(kind, path11) {
|
|
529859
|
-
const h =
|
|
530062
|
+
const h = createHash15("sha256").update(`${this.repoFp}:${kind}:${path11}`).digest("hex").slice(0, 24);
|
|
529860
530063
|
return `${kind}-${h}`;
|
|
529861
530064
|
}
|
|
529862
530065
|
};
|
|
@@ -530020,6 +530223,7 @@ __export(dist_exports2, {
|
|
|
530020
530223
|
characteristicsForStage: () => characteristicsForStage,
|
|
530021
530224
|
checkEmbeddingAvailable: () => checkEmbeddingAvailable,
|
|
530022
530225
|
checkEmbeddingDrift: () => checkEmbeddingDrift,
|
|
530226
|
+
chooseInnerGraphSeed: () => chooseInnerGraphSeed,
|
|
530023
530227
|
closeDb: () => closeDb,
|
|
530024
530228
|
compressAndStore: () => compressAndStore,
|
|
530025
530229
|
compressToGist: () => compressToGist,
|
|
@@ -530065,6 +530269,8 @@ __export(dist_exports2, {
|
|
|
530065
530269
|
retrieveByPPR: () => retrieveByPPR,
|
|
530066
530270
|
runConsolidationCycle: () => runConsolidationCycle,
|
|
530067
530271
|
sanitizeEmotionalState: () => sanitizeEmotionalState,
|
|
530272
|
+
selectAndWalkGraphCandidate: () => selectAndWalkGraphCandidate,
|
|
530273
|
+
selectInnerGraphCandidates: () => selectInnerGraphCandidates,
|
|
530068
530274
|
selfTrustFor: () => selfTrustFor,
|
|
530069
530275
|
slowWaveReplay: () => slowWaveReplay,
|
|
530070
530276
|
splanifoldCosine: () => cosine,
|
|
@@ -530077,6 +530283,7 @@ __export(dist_exports2, {
|
|
|
530077
530283
|
suggestRegulationActions: () => suggestRegulationActions,
|
|
530078
530284
|
thresholdsForStage: () => thresholdsForStage,
|
|
530079
530285
|
tokenSimilarity: () => tokenSimilarity,
|
|
530286
|
+
walkGraphFromSeed: () => walkGraphFromSeed,
|
|
530080
530287
|
wasHesitant: () => wasHesitant
|
|
530081
530288
|
});
|
|
530082
530289
|
var init_dist7 = __esm({
|
|
@@ -530096,6 +530303,7 @@ var init_dist7 = __esm({
|
|
|
530096
530303
|
init_zettelkasten();
|
|
530097
530304
|
init_gistCompressor();
|
|
530098
530305
|
init_pprRetrieval();
|
|
530306
|
+
init_graphWalk();
|
|
530099
530307
|
init_embeddings2();
|
|
530100
530308
|
init_proceduralMemoryStore();
|
|
530101
530309
|
init_splanifold();
|
|
@@ -532316,7 +532524,7 @@ import { existsSync as existsSync72, readFileSync as readFileSync56, statSync as
|
|
|
532316
532524
|
import { execSync as execSync45 } from "node:child_process";
|
|
532317
532525
|
import { homedir as homedir23, platform as platform2, arch as arch2, totalmem as totalmem2, freemem as freemem2, hostname as hostname3 } from "node:os";
|
|
532318
532526
|
import { join as join86 } from "node:path";
|
|
532319
|
-
import { createHash as
|
|
532527
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
532320
532528
|
function capturePreflightSnapshot(workingDir) {
|
|
532321
532529
|
const warnings = [];
|
|
532322
532530
|
const configFingerprints = {};
|
|
@@ -532483,7 +532691,7 @@ function expandPath(p2) {
|
|
|
532483
532691
|
return p2;
|
|
532484
532692
|
}
|
|
532485
532693
|
function sha2563(s2) {
|
|
532486
|
-
return
|
|
532694
|
+
return createHash16("sha256").update(s2).digest("hex").slice(0, 16);
|
|
532487
532695
|
}
|
|
532488
532696
|
function freeDiskBytes(path11 = "/tmp") {
|
|
532489
532697
|
try {
|
|
@@ -538505,8 +538713,8 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
538505
538713
|
if (process.env["OMNIUS_DISABLE_ADAPTIVE_RETRIEVAL"] !== "1") {
|
|
538506
538714
|
const goalForSig = (this._taskState.goal || "").slice(0, 200);
|
|
538507
538715
|
const recentTools = this._toolSequence.slice(-5).join("|");
|
|
538508
|
-
const { createHash:
|
|
538509
|
-
const sig =
|
|
538716
|
+
const { createHash: createHash28 } = await import("node:crypto");
|
|
538717
|
+
const sig = createHash28("sha256").update(`${goalForSig}::${recentTools}`).digest("hex").slice(0, 16);
|
|
538510
538718
|
if (this._lastPprSig === sig && this._lastPprMemoryLines.length > 0) {
|
|
538511
538719
|
compacted.push({
|
|
538512
538720
|
role: "system",
|
|
@@ -551340,10 +551548,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
551340
551548
|
wordTimestamps: false
|
|
551341
551549
|
});
|
|
551342
551550
|
if (outputDir) {
|
|
551343
|
-
const { basename:
|
|
551551
|
+
const { basename: basename30 } = await import("node:path");
|
|
551344
551552
|
const transcriptDir = join94(outputDir, ".omnius", "transcripts");
|
|
551345
551553
|
mkdirSync44(transcriptDir, { recursive: true });
|
|
551346
|
-
const outFile = join94(transcriptDir, `${
|
|
551554
|
+
const outFile = join94(transcriptDir, `${basename30(filePath)}.txt`);
|
|
551347
551555
|
writeFileSync39(outFile, result.text, "utf-8");
|
|
551348
551556
|
}
|
|
551349
551557
|
return {
|
|
@@ -551359,10 +551567,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
551359
551567
|
const fb = await transcribeFileViaWhisper(filePath, this.config.model);
|
|
551360
551568
|
if (fb) {
|
|
551361
551569
|
if (outputDir) {
|
|
551362
|
-
const { basename:
|
|
551570
|
+
const { basename: basename30 } = await import("node:path");
|
|
551363
551571
|
const transcriptDir = join94(outputDir, ".omnius", "transcripts");
|
|
551364
551572
|
mkdirSync44(transcriptDir, { recursive: true });
|
|
551365
|
-
const outFile = join94(transcriptDir, `${
|
|
551573
|
+
const outFile = join94(transcriptDir, `${basename30(filePath)}.txt`);
|
|
551366
551574
|
writeFileSync39(outFile, fb.text, "utf-8");
|
|
551367
551575
|
}
|
|
551368
551576
|
return fb;
|
|
@@ -553610,7 +553818,7 @@ var require_websocket3 = __commonJS({
|
|
|
553610
553818
|
var http6 = __require("http");
|
|
553611
553819
|
var net5 = __require("net");
|
|
553612
553820
|
var tls2 = __require("tls");
|
|
553613
|
-
var { randomBytes: randomBytes26, createHash:
|
|
553821
|
+
var { randomBytes: randomBytes26, createHash: createHash28 } = __require("crypto");
|
|
553614
553822
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
553615
553823
|
var { URL: URL3 } = __require("url");
|
|
553616
553824
|
var PerMessageDeflate3 = require_permessage_deflate3();
|
|
@@ -554270,7 +554478,7 @@ var require_websocket3 = __commonJS({
|
|
|
554270
554478
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
554271
554479
|
return;
|
|
554272
554480
|
}
|
|
554273
|
-
const digest3 =
|
|
554481
|
+
const digest3 = createHash28("sha1").update(key + GUID).digest("base64");
|
|
554274
554482
|
if (res.headers["sec-websocket-accept"] !== digest3) {
|
|
554275
554483
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
554276
554484
|
return;
|
|
@@ -554637,7 +554845,7 @@ var require_websocket_server2 = __commonJS({
|
|
|
554637
554845
|
var EventEmitter13 = __require("events");
|
|
554638
554846
|
var http6 = __require("http");
|
|
554639
554847
|
var { Duplex: Duplex3 } = __require("stream");
|
|
554640
|
-
var { createHash:
|
|
554848
|
+
var { createHash: createHash28 } = __require("crypto");
|
|
554641
554849
|
var extension3 = require_extension3();
|
|
554642
554850
|
var PerMessageDeflate3 = require_permessage_deflate3();
|
|
554643
554851
|
var subprotocol3 = require_subprotocol2();
|
|
@@ -554938,7 +555146,7 @@ var require_websocket_server2 = __commonJS({
|
|
|
554938
555146
|
);
|
|
554939
555147
|
}
|
|
554940
555148
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
554941
|
-
const digest3 =
|
|
555149
|
+
const digest3 = createHash28("sha1").update(key + GUID).digest("base64");
|
|
554942
555150
|
const headers = [
|
|
554943
555151
|
"HTTP/1.1 101 Switching Protocols",
|
|
554944
555152
|
"Upgrade: websocket",
|
|
@@ -555312,7 +555520,11 @@ function buildTelegramBotCommands(opts = {}) {
|
|
|
555312
555520
|
if (includeAuth) {
|
|
555313
555521
|
add2("auth", "Authenticate this Telegram user as the bot admin", "auth");
|
|
555314
555522
|
}
|
|
555523
|
+
add2("reflect", "Run scoped Telegram chat reflection", "reflect");
|
|
555524
|
+
add2("reflection", "Alias for scoped Telegram chat reflection", "reflect");
|
|
555525
|
+
add2("daydream", "Alias for scoped Telegram chat reflection", "reflect");
|
|
555315
555526
|
for (const cmd of listCommandRegistry({ includePlanned: false })) {
|
|
555527
|
+
if (cmd.name === "dream") continue;
|
|
555316
555528
|
add2(cmd.name, cmd.description || `Run /${cmd.name}`, cmd.name);
|
|
555317
555529
|
if (commands.length >= maxCommands) break;
|
|
555318
555530
|
}
|
|
@@ -558169,14 +558381,14 @@ var init_voice_session = __esm({
|
|
|
558169
558381
|
});
|
|
558170
558382
|
|
|
558171
558383
|
// packages/cli/src/tui/scoped-personality.ts
|
|
558172
|
-
import { createHash as
|
|
558384
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
558173
558385
|
import { existsSync as existsSync79, mkdirSync as mkdirSync45, readFileSync as readFileSync62, writeFileSync as writeFileSync40 } from "node:fs";
|
|
558174
558386
|
import { join as join95, resolve as resolve35 } from "node:path";
|
|
558175
558387
|
function safeName(input) {
|
|
558176
558388
|
return input.replace(/[^A-Za-z0-9_.-]/g, "-").slice(0, 80) || "default";
|
|
558177
558389
|
}
|
|
558178
558390
|
function scopeHash(scope) {
|
|
558179
|
-
return
|
|
558391
|
+
return createHash17("sha1").update(`${scope.kind}:${scope.id}`).digest("hex").slice(0, 16);
|
|
558180
558392
|
}
|
|
558181
558393
|
function scopedPersonalityDir(repoRoot, kind) {
|
|
558182
558394
|
return resolve35(repoRoot, ".omnius", "scoped-personality", kind);
|
|
@@ -558214,9 +558426,9 @@ function keywords(text) {
|
|
|
558214
558426
|
return out;
|
|
558215
558427
|
}
|
|
558216
558428
|
function compactLine(text, limit = 220) {
|
|
558217
|
-
const
|
|
558218
|
-
if (
|
|
558219
|
-
return `${
|
|
558429
|
+
const compact2 = text.replace(/\s+/g, " ").trim();
|
|
558430
|
+
if (compact2.length <= limit) return compact2;
|
|
558431
|
+
return `${compact2.slice(0, Math.max(0, limit - 3)).trimEnd()}...`;
|
|
558220
558432
|
}
|
|
558221
558433
|
function newDocument(scope) {
|
|
558222
558434
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -558321,8 +558533,8 @@ function updateScopedPersonality(scope, observation) {
|
|
|
558321
558533
|
}
|
|
558322
558534
|
const relationshipHints = observation.relationshipHints ?? [];
|
|
558323
558535
|
for (const hint of relationshipHints) {
|
|
558324
|
-
const
|
|
558325
|
-
if (
|
|
558536
|
+
const clean5 = compactLine(hint, 180);
|
|
558537
|
+
if (clean5 && !doc.relationshipModel.includes(clean5)) doc.relationshipModel.push(clean5);
|
|
558326
558538
|
}
|
|
558327
558539
|
doc.relationshipModel = doc.relationshipModel.slice(-12);
|
|
558328
558540
|
if (text) {
|
|
@@ -560017,7 +560229,7 @@ var init_types = __esm({
|
|
|
560017
560229
|
});
|
|
560018
560230
|
|
|
560019
560231
|
// packages/cli/src/tui/p2p/secret-vault.ts
|
|
560020
|
-
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes19, scryptSync as scryptSync2, createHash as
|
|
560232
|
+
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes19, scryptSync as scryptSync2, createHash as createHash18 } from "node:crypto";
|
|
560021
560233
|
import { readFileSync as readFileSync64, writeFileSync as writeFileSync42, existsSync as existsSync81, mkdirSync as mkdirSync47 } from "node:fs";
|
|
560022
560234
|
import { dirname as dirname25 } from "node:path";
|
|
560023
560235
|
var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
|
|
@@ -560262,7 +560474,7 @@ var init_secret_vault = __esm({
|
|
|
560262
560474
|
/** Generate a deterministic fingerprint of vault contents (for sync verification) */
|
|
560263
560475
|
fingerprint() {
|
|
560264
560476
|
const names = Array.from(this.secrets.keys()).sort();
|
|
560265
|
-
const hash =
|
|
560477
|
+
const hash = createHash18("sha256");
|
|
560266
560478
|
for (const name10 of names) {
|
|
560267
560479
|
hash.update(name10 + ":");
|
|
560268
560480
|
hash.update(this.secrets.get(name10).value);
|
|
@@ -560277,7 +560489,7 @@ var init_secret_vault = __esm({
|
|
|
560277
560489
|
// packages/cli/src/tui/p2p/peer-mesh.ts
|
|
560278
560490
|
import { EventEmitter as EventEmitter7 } from "node:events";
|
|
560279
560491
|
import { createServer as createServer5 } from "node:http";
|
|
560280
|
-
import { randomBytes as randomBytes20, createHash as
|
|
560492
|
+
import { randomBytes as randomBytes20, createHash as createHash19, generateKeyPairSync } from "node:crypto";
|
|
560281
560493
|
var PING_INTERVAL_MS, PEER_TIMEOUT_MS, GOSSIP_INTERVAL_MS, MAX_PEERS, PeerMesh;
|
|
560282
560494
|
var init_peer_mesh = __esm({
|
|
560283
560495
|
"packages/cli/src/tui/p2p/peer-mesh.ts"() {
|
|
@@ -560294,7 +560506,7 @@ var init_peer_mesh = __esm({
|
|
|
560294
560506
|
const { publicKey: publicKey2, privateKey } = generateKeyPairSync("ed25519");
|
|
560295
560507
|
this.publicKey = publicKey2.export({ type: "spki", format: "der" });
|
|
560296
560508
|
this.privateKey = privateKey.export({ type: "pkcs8", format: "der" });
|
|
560297
|
-
this.peerId =
|
|
560509
|
+
this.peerId = createHash19("sha256").update(this.publicKey).digest("base64url").slice(0, 22);
|
|
560298
560510
|
this.capabilities = options2.capabilities;
|
|
560299
560511
|
this.displayName = options2.displayName;
|
|
560300
560512
|
this._authKey = options2.authKey ?? randomBytes20(24).toString("base64url");
|
|
@@ -562017,7 +562229,7 @@ __export(omnius_directory_exports, {
|
|
|
562017
562229
|
import { cpSync, existsSync as existsSync83, mkdirSync as mkdirSync48, readFileSync as readFileSync66, writeFileSync as writeFileSync43, readdirSync as readdirSync26, statSync as statSync29, unlinkSync as unlinkSync14, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync3 } from "node:fs";
|
|
562018
562230
|
import { join as join100, relative as relative9, basename as basename17, dirname as dirname28 } from "node:path";
|
|
562019
562231
|
import { homedir as homedir27 } from "node:os";
|
|
562020
|
-
import { createHash as
|
|
562232
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
562021
562233
|
function findGitRoot(startDir) {
|
|
562022
562234
|
let dir = startDir;
|
|
562023
562235
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -562398,7 +562610,7 @@ function buildHandoffPrompt(repoRoot) {
|
|
|
562398
562610
|
return lines.join("\n");
|
|
562399
562611
|
}
|
|
562400
562612
|
function computeDedupeHash(task, savedAt) {
|
|
562401
|
-
return
|
|
562613
|
+
return createHash20("sha256").update(`${task}|${savedAt}`).digest("hex").slice(0, 16);
|
|
562402
562614
|
}
|
|
562403
562615
|
function generateSessionId() {
|
|
562404
562616
|
const timestamp = Date.now().toString(36);
|
|
@@ -562462,10 +562674,10 @@ function normalizeList(items, maxItems) {
|
|
|
562462
562674
|
const seen = /* @__PURE__ */ new Set();
|
|
562463
562675
|
const out = [];
|
|
562464
562676
|
for (const item of items) {
|
|
562465
|
-
const
|
|
562466
|
-
if (!
|
|
562467
|
-
seen.add(
|
|
562468
|
-
out.push(
|
|
562677
|
+
const clean5 = normalizeSessionText(item, 300);
|
|
562678
|
+
if (!clean5 || seen.has(clean5)) continue;
|
|
562679
|
+
seen.add(clean5);
|
|
562680
|
+
out.push(clean5);
|
|
562469
562681
|
if (out.length >= maxItems) break;
|
|
562470
562682
|
}
|
|
562471
562683
|
return out.length > 0 ? out : void 0;
|
|
@@ -562753,8 +562965,8 @@ function getLastTaskSummary(repoRoot) {
|
|
|
562753
562965
|
if (!ctx3 || ctx3.entries.length === 0) return null;
|
|
562754
562966
|
const last2 = ctx3.entries[ctx3.entries.length - 1];
|
|
562755
562967
|
const text = last2.summary || last2.task;
|
|
562756
|
-
const
|
|
562757
|
-
return
|
|
562968
|
+
const clean5 = text.replace(/^\[.*?\]\s*/, "").replace(/\s+/g, " ").trim();
|
|
562969
|
+
return clean5.length > 40 ? clean5.slice(0, 37) + "..." : clean5;
|
|
562758
562970
|
}
|
|
562759
562971
|
function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
562760
562972
|
const sessDir = join100(repoRoot, OMNIUS_DIR, SESSIONS_DIR);
|
|
@@ -562835,9 +563047,9 @@ function deleteSession(repoRoot, sessionId) {
|
|
|
562835
563047
|
}
|
|
562836
563048
|
function generateSessionName(lines) {
|
|
562837
563049
|
for (const line of lines.slice(0, 30)) {
|
|
562838
|
-
const
|
|
562839
|
-
if (
|
|
562840
|
-
const phrase =
|
|
563050
|
+
const clean5 = line.trim();
|
|
563051
|
+
if (clean5.length > 10 && !clean5.startsWith("i ") && !clean5.startsWith(" ")) {
|
|
563052
|
+
const phrase = clean5.replace(/^[>❯▹]\s*/, "").slice(0, 40);
|
|
562841
563053
|
return phrase.length > 37 ? phrase.slice(0, 37) + "..." : phrase;
|
|
562842
563054
|
}
|
|
562843
563055
|
}
|
|
@@ -564705,7 +564917,7 @@ function setTerminalTitle(task, version4) {
|
|
|
564705
564917
|
const title = task ? `${task.slice(0, 60)} · ${ver}` : ver;
|
|
564706
564918
|
process.stdout.write(`\x1B]2;${title}\x07`);
|
|
564707
564919
|
}
|
|
564708
|
-
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock, RESET2, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
|
|
564920
|
+
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock, RESET2, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
|
|
564709
564921
|
var init_status_bar = __esm({
|
|
564710
564922
|
"packages/cli/src/tui/status-bar.ts"() {
|
|
564711
564923
|
"use strict";
|
|
@@ -564877,6 +565089,7 @@ var init_status_bar = __esm({
|
|
|
564877
565089
|
BOX_FG = tuiBoxFg();
|
|
564878
565090
|
TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
|
|
564879
565091
|
TEXT_DIM = tuiTextDim();
|
|
565092
|
+
NO_SUB_AGENTS_HEADER_LABEL = " no sub-agents ";
|
|
564880
565093
|
BOX_TL = "╭";
|
|
564881
565094
|
BOX_TR = "╮";
|
|
564882
565095
|
BOX_BL = "╰";
|
|
@@ -565326,8 +565539,8 @@ var init_status_bar = __esm({
|
|
|
565326
565539
|
}
|
|
565327
565540
|
} else {
|
|
565328
565541
|
sysItems.push({
|
|
565329
|
-
render: () => `\x1B[38;5;${TEXT_DIM}m
|
|
565330
|
-
w:
|
|
565542
|
+
render: () => `\x1B[38;5;${TEXT_DIM}m${NO_SUB_AGENTS_HEADER_LABEL}`,
|
|
565543
|
+
w: NO_SUB_AGENTS_HEADER_LABEL.length
|
|
565331
565544
|
});
|
|
565332
565545
|
}
|
|
565333
565546
|
const sysSeparatorOffset = sysItems.reduce((sum, item) => sum + item.w, 0);
|
|
@@ -565410,7 +565623,10 @@ var init_status_bar = __esm({
|
|
|
565410
565623
|
return identity3.separatorOffsets.map((offset) => chrome.contentStartCol + offset).filter((col) => col > 1 && col < termWidth);
|
|
565411
565624
|
}
|
|
565412
565625
|
if (panel.meta.kind === "system" && this._sysSeparatorOffset !== null) {
|
|
565413
|
-
const
|
|
565626
|
+
const rendered = stripAnsi(panel.render(chrome.innerWidth));
|
|
565627
|
+
const renderedOffset = Array.from(rendered).indexOf("│");
|
|
565628
|
+
const offset = renderedOffset >= 0 ? renderedOffset : this._sysSeparatorOffset;
|
|
565629
|
+
const col = chrome.contentStartCol + offset;
|
|
565414
565630
|
if (col > 1 && col < termWidth) return [col];
|
|
565415
565631
|
}
|
|
565416
565632
|
return [];
|
|
@@ -565491,7 +565707,7 @@ var init_status_bar = __esm({
|
|
|
565491
565707
|
zones.push({ w: base3.length + 1, id: view.id, render: () => "" });
|
|
565492
565708
|
}
|
|
565493
565709
|
} else {
|
|
565494
|
-
zones.push({ w:
|
|
565710
|
+
zones.push({ w: NO_SUB_AGENTS_HEADER_LABEL.length, render: () => "" });
|
|
565495
565711
|
}
|
|
565496
565712
|
zones.push({ w: 2, render: () => "" });
|
|
565497
565713
|
const voiceLabel = this._voiceActive ? ` ${this._voiceModelId || "voice"} ` : " voice ";
|
|
@@ -567324,10 +567540,10 @@ ${CONTENT_BG_SEQ}`);
|
|
|
567324
567540
|
if (this._telegramStatus.active) {
|
|
567325
567541
|
const suffix = this._telegramStatus.activeSubAgents > 0 ? ` ${this._telegramStatus.activeSubAgents}` : "";
|
|
567326
567542
|
const label = `✈ tg${suffix}`;
|
|
567327
|
-
const
|
|
567543
|
+
const compact2 = `✈${suffix}`;
|
|
567328
567544
|
sections.push({
|
|
567329
567545
|
expanded: `\x1B[38;5;45m${label}\x1B[0m`,
|
|
567330
|
-
compact: `\x1B[38;5;45m${
|
|
567546
|
+
compact: `\x1B[38;5;45m${compact2}\x1B[0m`,
|
|
567331
567547
|
expandedW: 2 + 3 + suffix.length,
|
|
567332
567548
|
compactW: 2 + suffix.length,
|
|
567333
567549
|
empty: false
|
|
@@ -576056,17 +576272,17 @@ function toggleFocus(state) {
|
|
|
576056
576272
|
toggleFocus(state);
|
|
576057
576273
|
return;
|
|
576058
576274
|
}
|
|
576059
|
-
const
|
|
576060
|
-
if (!
|
|
576061
|
-
fn(Buffer.from(
|
|
576275
|
+
const clean5 = raw.replace(STDIN_MOUSE_FOCUS_RE, "");
|
|
576276
|
+
if (!clean5) return;
|
|
576277
|
+
fn(Buffer.from(clean5));
|
|
576062
576278
|
} else if (typeof args[0] === "string") {
|
|
576063
576279
|
if (args[0] === "") {
|
|
576064
576280
|
toggleFocus(state);
|
|
576065
576281
|
return;
|
|
576066
576282
|
}
|
|
576067
|
-
const
|
|
576068
|
-
if (!
|
|
576069
|
-
fn(
|
|
576283
|
+
const clean5 = args[0].replace(STDIN_MOUSE_FOCUS_RE, "");
|
|
576284
|
+
if (!clean5) return;
|
|
576285
|
+
fn(clean5);
|
|
576070
576286
|
} else {
|
|
576071
576287
|
fn(...args);
|
|
576072
576288
|
}
|
|
@@ -577844,8 +578060,8 @@ function normalizeAscii(ascii2, width, height) {
|
|
|
577844
578060
|
return lines.slice(0, height).map((line) => line.length > width ? line.slice(0, width) : line).join("\n").trimEnd();
|
|
577845
578061
|
}
|
|
577846
578062
|
function previewFailure(message2, width) {
|
|
577847
|
-
const
|
|
577848
|
-
const text = `[image-to-ascii preview failed: ${
|
|
578063
|
+
const clean5 = message2.replace(/\s+/g, " ").trim();
|
|
578064
|
+
const text = `[image-to-ascii preview failed: ${clean5 || "unknown error"}]`;
|
|
577849
578065
|
return text.length > width ? `${text.slice(0, Math.max(0, width - 1))}]` : text;
|
|
577850
578066
|
}
|
|
577851
578067
|
async function convertWithImageToAscii(imagePath, width, height, timeoutMs) {
|
|
@@ -580212,10 +580428,10 @@ except Exception as exc:
|
|
|
580212
580428
|
}));
|
|
580213
580429
|
}
|
|
580214
580430
|
saveSupertonicProfile(name10) {
|
|
580215
|
-
const
|
|
580216
|
-
if (!
|
|
580431
|
+
const clean5 = name10.trim().replace(/[^a-zA-Z0-9_.-]/g, "-");
|
|
580432
|
+
if (!clean5) return;
|
|
580217
580433
|
const store2 = this.loadSupertonicStore();
|
|
580218
|
-
store2.profiles[
|
|
580434
|
+
store2.profiles[clean5] = { ...store2.active };
|
|
580219
580435
|
this.saveSupertonicStore(store2);
|
|
580220
580436
|
}
|
|
580221
580437
|
loadSupertonicProfile(name10) {
|
|
@@ -588126,7 +588342,9 @@ async function showPlatformOnboardingMenu(ctx3, id) {
|
|
|
588126
588342
|
} else if (result.key === "telegram-start") {
|
|
588127
588343
|
const settings = ctx3.getTelegramSettings?.() ?? {};
|
|
588128
588344
|
if (!settings.key) renderWarning("No Telegram bot token configured.");
|
|
588129
|
-
else
|
|
588345
|
+
else if (ctx3.isTelegramActive?.()) {
|
|
588346
|
+
renderWarning("Telegram bridge already active. Use /telegram stop before restarting.");
|
|
588347
|
+
} else await ctx3.telegramStart?.(settings.key, settings.admin);
|
|
588130
588348
|
} else if (result.key === "telegram-stop") {
|
|
588131
588349
|
ctx3.telegramStop?.();
|
|
588132
588350
|
}
|
|
@@ -589926,14 +590144,14 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
|
|
|
589926
590144
|
if (!jsonDrop.confirmed || !jsonDrop.path) {
|
|
589927
590145
|
continue;
|
|
589928
590146
|
}
|
|
589929
|
-
const { basename:
|
|
590147
|
+
const { basename: basename30, join: pathJoin } = await import("node:path");
|
|
589930
590148
|
const {
|
|
589931
590149
|
copyFileSync: copyFileSync5,
|
|
589932
590150
|
mkdirSync: mkdirSync79,
|
|
589933
590151
|
existsSync: exists2
|
|
589934
590152
|
} = await import("node:fs");
|
|
589935
590153
|
const { homedir: homedir48 } = await import("node:os");
|
|
589936
|
-
const modelName =
|
|
590154
|
+
const modelName = basename30(onnxDrop.path, ".onnx").replace(
|
|
589937
590155
|
/[^a-zA-Z0-9_-]/g,
|
|
589938
590156
|
"-"
|
|
589939
590157
|
);
|
|
@@ -590320,7 +590538,7 @@ async function handleVoiceList(ctx3, focusFilename) {
|
|
|
590320
590538
|
copyFileSync: cpf,
|
|
590321
590539
|
mkdirSync: mkd
|
|
590322
590540
|
} = __require("node:fs");
|
|
590323
|
-
const { basename:
|
|
590541
|
+
const { basename: basename30, join: pjoin } = __require("node:path");
|
|
590324
590542
|
if (!fe(src2)) {
|
|
590325
590543
|
renderError(`File not found: ${src2}`);
|
|
590326
590544
|
helpers.render();
|
|
@@ -590333,7 +590551,7 @@ async function handleVoiceList(ctx3, focusFilename) {
|
|
|
590333
590551
|
"clone-refs"
|
|
590334
590552
|
);
|
|
590335
590553
|
mkd(refsDir, { recursive: true });
|
|
590336
|
-
const destName =
|
|
590554
|
+
const destName = basename30(src2);
|
|
590337
590555
|
const dest = pjoin(refsDir, destName);
|
|
590338
590556
|
cpf(src2, dest);
|
|
590339
590557
|
renderInfo(`Imported "${destName}" → ${dest}`);
|
|
@@ -593244,9 +593462,9 @@ async function showExposeDashboard(gateway, rl, ctx3) {
|
|
|
593244
593462
|
const recentEntries = [];
|
|
593245
593463
|
for (let i2 = streamLog.length - 1; i2 >= 0 && recentEntries.length < streamAreaHeight - 1; i2--) {
|
|
593246
593464
|
const entry = streamLog[i2];
|
|
593247
|
-
const
|
|
593248
|
-
if (!
|
|
593249
|
-
const truncated =
|
|
593465
|
+
const clean5 = entry.content.replace(/\n/g, "⏎").replace(/[\x00-\x1F\x7F]/g, "");
|
|
593466
|
+
if (!clean5) continue;
|
|
593467
|
+
const truncated = clean5.length > maxContentW ? clean5.slice(0, maxContentW - 1) + "…" : clean5;
|
|
593250
593468
|
recentEntries.unshift(` \x1B[38;5;245m${truncated}\x1B[0m`);
|
|
593251
593469
|
}
|
|
593252
593470
|
while (recentEntries.length < streamAreaHeight - 1)
|
|
@@ -593978,27 +594196,468 @@ var init_project_context = __esm({
|
|
|
593978
594196
|
}
|
|
593979
594197
|
});
|
|
593980
594198
|
|
|
593981
|
-
// packages/cli/src/tui/
|
|
593982
|
-
import { mkdirSync as mkdirSync55
|
|
593983
|
-
import {
|
|
593984
|
-
function
|
|
593985
|
-
const dir = join112(repoRoot, ".omnius"
|
|
594199
|
+
// packages/cli/src/tui/memory-paths.ts
|
|
594200
|
+
import { mkdirSync as mkdirSync55 } from "node:fs";
|
|
594201
|
+
import { join as join112 } from "node:path";
|
|
594202
|
+
function omniusMemoryDbPaths(repoRoot) {
|
|
594203
|
+
const dir = join112(repoRoot, ".omnius");
|
|
593986
594204
|
mkdirSync55(dir, { recursive: true });
|
|
593987
594205
|
return {
|
|
594206
|
+
dir,
|
|
593988
594207
|
episodes: join112(dir, "episodes.db"),
|
|
593989
594208
|
knowledge: join112(dir, "knowledge.db")
|
|
593990
594209
|
};
|
|
593991
594210
|
}
|
|
594211
|
+
var init_memory_paths = __esm({
|
|
594212
|
+
"packages/cli/src/tui/memory-paths.ts"() {
|
|
594213
|
+
"use strict";
|
|
594214
|
+
}
|
|
594215
|
+
});
|
|
594216
|
+
|
|
594217
|
+
// packages/cli/src/tui/visual-identity-association.ts
|
|
594218
|
+
var visual_identity_association_exports = {};
|
|
594219
|
+
__export(visual_identity_association_exports, {
|
|
594220
|
+
associateVisualIdentityFromImage: () => associateVisualIdentityFromImage,
|
|
594221
|
+
formatVisualIdentityAssociationContext: () => formatVisualIdentityAssociationContext,
|
|
594222
|
+
stageVisualIdentityAssertion: () => stageVisualIdentityAssertion
|
|
594223
|
+
});
|
|
594224
|
+
import { basename as basename20 } from "node:path";
|
|
594225
|
+
function normalizePersonName(name10) {
|
|
594226
|
+
return name10.trim().toLowerCase().replace(/\s+/g, " ");
|
|
594227
|
+
}
|
|
593992
594228
|
function personKey(name10) {
|
|
594229
|
+
return `person:${normalizePersonName(name10)}`;
|
|
594230
|
+
}
|
|
594231
|
+
function clamp016(value2, fallback = 0) {
|
|
594232
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return fallback;
|
|
594233
|
+
return Math.max(0, Math.min(1, value2));
|
|
594234
|
+
}
|
|
594235
|
+
function parseStructuredIdentifyResult(result) {
|
|
594236
|
+
const raw = String(result.llmContent || result.output || "").trim();
|
|
594237
|
+
if (!raw) return { matches: [], structured: false, raw };
|
|
594238
|
+
let parsed = null;
|
|
594239
|
+
try {
|
|
594240
|
+
parsed = JSON.parse(raw);
|
|
594241
|
+
} catch {
|
|
594242
|
+
return { matches: [], structured: false, raw };
|
|
594243
|
+
}
|
|
594244
|
+
const faces = Array.isArray(parsed.faces) ? parsed.faces : [];
|
|
594245
|
+
const matches = faces.filter((face) => face["identified"] === true && typeof face["name"] === "string" && String(face["name"]).trim()).map((face) => ({
|
|
594246
|
+
name: String(face["name"]).trim(),
|
|
594247
|
+
personId: typeof face["person_id"] === "string" ? face["person_id"] : void 0,
|
|
594248
|
+
confidence: clamp016(face["confidence"], 0),
|
|
594249
|
+
margin: typeof face["margin"] === "number" ? face["margin"] : void 0,
|
|
594250
|
+
bbox: Array.isArray(face["bbox"]) ? face["bbox"].map((n2) => Number(n2)).filter(Number.isFinite) : void 0
|
|
594251
|
+
}));
|
|
594252
|
+
return { matches, structured: true, raw };
|
|
594253
|
+
}
|
|
594254
|
+
function parseDetectedFaceCount(result) {
|
|
594255
|
+
const raw = String(result.llmContent || result.output || "").trim();
|
|
594256
|
+
if (!raw) return 0;
|
|
594257
|
+
try {
|
|
594258
|
+
const parsed = JSON.parse(raw);
|
|
594259
|
+
if (Array.isArray(parsed.faces)) return parsed.faces.length;
|
|
594260
|
+
if (typeof parsed.total === "number" && Number.isFinite(parsed.total)) return Math.max(0, Math.floor(parsed.total));
|
|
594261
|
+
} catch {
|
|
594262
|
+
}
|
|
594263
|
+
return 0;
|
|
594264
|
+
}
|
|
594265
|
+
function readMetadataObject(value2) {
|
|
594266
|
+
return value2 && typeof value2 === "object" ? value2 : {};
|
|
594267
|
+
}
|
|
594268
|
+
function sameScope(a2, b) {
|
|
594269
|
+
if (!b || !a2 || typeof a2 !== "object") return false;
|
|
594270
|
+
const raw = a2;
|
|
594271
|
+
return String(raw["kind"] ?? "") === String(b.kind) && String(raw["id"] ?? "") === String(b.id);
|
|
594272
|
+
}
|
|
594273
|
+
function episodeMatchesScope(ep, scope, sessionId) {
|
|
594274
|
+
if (!scope) return true;
|
|
594275
|
+
const metadata = readMetadataObject(ep.metadata);
|
|
594276
|
+
if (sameScope(metadata["scope"], scope)) return true;
|
|
594277
|
+
if (sessionId && ep.sessionId === sessionId) return true;
|
|
594278
|
+
const chatId = metadata["chat_id"] ?? metadata["chatId"];
|
|
594279
|
+
if ((scope.kind === "group" || scope.kind === "private") && chatId != null && String(chatId) === String(scope.id)) return true;
|
|
594280
|
+
const telegram = readMetadataObject(metadata["telegram"]);
|
|
594281
|
+
if ((scope.kind === "group" || scope.kind === "private") && telegram["chatId"] != null && String(telegram["chatId"]) === String(scope.id)) return true;
|
|
594282
|
+
return false;
|
|
594283
|
+
}
|
|
594284
|
+
function episodeSenderDisplay(ep) {
|
|
594285
|
+
const metadata = readMetadataObject(ep.metadata);
|
|
594286
|
+
const sender = readMetadataObject(metadata["sender"]);
|
|
594287
|
+
return String(sender["displayName"] || sender["username"] || sender["id"] || "").trim() || void 0;
|
|
594288
|
+
}
|
|
594289
|
+
function episodeMessageId(ep) {
|
|
594290
|
+
const metadata = readMetadataObject(ep.metadata);
|
|
594291
|
+
const message2 = readMetadataObject(metadata["message"]);
|
|
594292
|
+
return message2["id"];
|
|
594293
|
+
}
|
|
594294
|
+
function episodeSurface(ep) {
|
|
594295
|
+
const metadata = readMetadataObject(ep.metadata);
|
|
594296
|
+
return typeof metadata["sourceSurface"] === "string" ? metadata["sourceSurface"] : void 0;
|
|
594297
|
+
}
|
|
594298
|
+
function compactContent(value2, max = 220) {
|
|
594299
|
+
const clean5 = value2.replace(/\s+/g, " ").trim();
|
|
594300
|
+
return clean5.length > max ? `${clean5.slice(0, max - 1)}...` : clean5;
|
|
594301
|
+
}
|
|
594302
|
+
function pendingConsumedIds(store2, scope, sessionId) {
|
|
594303
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
594304
|
+
for (const ep of store2.recent(250)) {
|
|
594305
|
+
if (!episodeMatchesScope(ep, scope, sessionId)) continue;
|
|
594306
|
+
const metadata = readMetadataObject(ep.metadata);
|
|
594307
|
+
const consumedMeta = readMetadataObject(metadata["identityPendingConsumed"]);
|
|
594308
|
+
const pendingId = String(consumedMeta["pendingId"] || "").trim();
|
|
594309
|
+
if (pendingId) consumed.add(pendingId);
|
|
594310
|
+
}
|
|
594311
|
+
return consumed;
|
|
594312
|
+
}
|
|
594313
|
+
function activePendingVisualIdentities(store2, scope, sessionId, limit = 3) {
|
|
594314
|
+
const now = Date.now();
|
|
594315
|
+
const consumed = pendingConsumedIds(store2, scope, sessionId);
|
|
594316
|
+
const pending = [];
|
|
594317
|
+
for (const ep of store2.recent(250)) {
|
|
594318
|
+
if (!episodeMatchesScope(ep, scope, sessionId)) continue;
|
|
594319
|
+
const metadata = readMetadataObject(ep.metadata);
|
|
594320
|
+
const meta = readMetadataObject(metadata["identityPending"]);
|
|
594321
|
+
if (String(meta["kind"] || "") !== "visual_identity") continue;
|
|
594322
|
+
const pendingId = String(meta["pendingId"] || "").trim();
|
|
594323
|
+
const name10 = String(meta["name"] || "").trim();
|
|
594324
|
+
if (!pendingId || !name10 || consumed.has(pendingId)) continue;
|
|
594325
|
+
const expiresAt = typeof meta["expiresAt"] === "number" ? meta["expiresAt"] : 0;
|
|
594326
|
+
if (expiresAt > 0 && expiresAt < now) continue;
|
|
594327
|
+
pending.push({
|
|
594328
|
+
pendingId,
|
|
594329
|
+
name: name10,
|
|
594330
|
+
relation: String(meta["relation"] || "depicts"),
|
|
594331
|
+
confidence: clamp016(meta["confidence"], 0.92),
|
|
594332
|
+
note: typeof meta["note"] === "string" ? meta["note"] : void 0,
|
|
594333
|
+
episodeId: ep.id,
|
|
594334
|
+
createdAt: ep.timestamp,
|
|
594335
|
+
expiresAt,
|
|
594336
|
+
sender: readMetadataObject(metadata["sender"]),
|
|
594337
|
+
message: readMetadataObject(metadata["message"])
|
|
594338
|
+
});
|
|
594339
|
+
if (pending.length >= limit) break;
|
|
594340
|
+
}
|
|
594341
|
+
return pending;
|
|
594342
|
+
}
|
|
594343
|
+
function recallPersonEpisodes(store2, graph, name10, scope, sessionId, excludedEpisodeIds, limit) {
|
|
594344
|
+
const person = graph.findNode(personKey(name10), "person");
|
|
594345
|
+
if (!person) return [];
|
|
594346
|
+
const edges = graph.currentEdges(person.id);
|
|
594347
|
+
const ids = /* @__PURE__ */ new Set();
|
|
594348
|
+
for (const edge of edges) {
|
|
594349
|
+
if (edge.sourceEpisodeId && !excludedEpisodeIds.has(edge.sourceEpisodeId)) ids.add(edge.sourceEpisodeId);
|
|
594350
|
+
}
|
|
594351
|
+
const episodes = [...ids].map((id) => store2.get(id)).filter((ep) => Boolean(ep)).filter((ep) => episodeMatchesScope(ep, scope, sessionId)).sort((a2, b) => b.timestamp - a2.timestamp).slice(0, limit);
|
|
594352
|
+
return episodes.map((ep) => ({
|
|
594353
|
+
id: ep.id,
|
|
594354
|
+
timestamp: ep.timestamp,
|
|
594355
|
+
modality: ep.modality,
|
|
594356
|
+
content: compactContent(ep.gist || ep.content),
|
|
594357
|
+
sourceSurface: episodeSurface(ep),
|
|
594358
|
+
messageId: episodeMessageId(ep),
|
|
594359
|
+
senderDisplay: episodeSenderDisplay(ep)
|
|
594360
|
+
}));
|
|
594361
|
+
}
|
|
594362
|
+
function formatTimestamp2(ms) {
|
|
594363
|
+
try {
|
|
594364
|
+
return new Date(ms).toISOString();
|
|
594365
|
+
} catch {
|
|
594366
|
+
return String(ms);
|
|
594367
|
+
}
|
|
594368
|
+
}
|
|
594369
|
+
function formatVisualIdentityAssociationContext(result) {
|
|
594370
|
+
if (result.matches.length === 0 && result.pendingApplied.length === 0 && result.pendingSkipped.length === 0 && result.unknownFaceCount === 0) {
|
|
594371
|
+
return "";
|
|
594372
|
+
}
|
|
594373
|
+
const lines = [];
|
|
594374
|
+
if (result.pendingApplied.length > 0) {
|
|
594375
|
+
lines.push("## Pending Visual Identity Applied");
|
|
594376
|
+
lines.push("A prior explicit user identity assertion was waiting for the next image in this same scope. It has now been linked to this image.");
|
|
594377
|
+
for (const pending of result.pendingApplied) {
|
|
594378
|
+
lines.push(`- ${pending.name} confidence=${pending.confidence.toFixed(2)} pending_id=${pending.pendingId}`);
|
|
594379
|
+
}
|
|
594380
|
+
}
|
|
594381
|
+
if (result.matches.length > 0) {
|
|
594382
|
+
lines.push("## Scoped Visual Identity Recall");
|
|
594383
|
+
lines.push("Prior enrolled visual-memory face match found for the current image. This is not a new identity assertion from the caption or prompt.");
|
|
594384
|
+
for (const match of result.matches) {
|
|
594385
|
+
const confidence2 = Number.isFinite(match.confidence) ? ` confidence=${match.confidence.toFixed(2)}` : "";
|
|
594386
|
+
const margin = typeof match.margin === "number" ? ` margin=${match.margin.toFixed(2)}` : "";
|
|
594387
|
+
lines.push(`- ${match.name}${confidence2}${margin}`);
|
|
594388
|
+
}
|
|
594389
|
+
if (result.recalledEpisodes.length) {
|
|
594390
|
+
lines.push("Scoped related memory:");
|
|
594391
|
+
for (const ep of result.recalledEpisodes) {
|
|
594392
|
+
const sender = ep.senderDisplay ? ` ${ep.senderDisplay}:` : "";
|
|
594393
|
+
const msg = ep.messageId != null ? ` message=${ep.messageId}` : "";
|
|
594394
|
+
lines.push(`- ${formatTimestamp2(ep.timestamp)}${msg}${sender} ${ep.content}`);
|
|
594395
|
+
}
|
|
594396
|
+
} else {
|
|
594397
|
+
lines.push("Scoped related memory: no prior same-scope episode found beyond the enrolled visual identity.");
|
|
594398
|
+
}
|
|
594399
|
+
}
|
|
594400
|
+
if (result.pendingSkipped.length > 0) {
|
|
594401
|
+
lines.push("## Pending Visual Identity Not Applied");
|
|
594402
|
+
for (const skipped of result.pendingSkipped) {
|
|
594403
|
+
lines.push(`- ${skipped.name}: ${skipped.reason}`);
|
|
594404
|
+
}
|
|
594405
|
+
}
|
|
594406
|
+
if (result.matches.length === 0 && result.pendingApplied.length === 0 && result.unknownFaceCount > 0) {
|
|
594407
|
+
lines.push("## Unknown Visual Identity Candidate");
|
|
594408
|
+
lines.push(`${result.unknownFaceCount} face(s) detected, but no prior enrolled identity matched in this scope.`);
|
|
594409
|
+
lines.push("If the user's task depends on who this is, ask who the person is and offer to remember them. Do not guess a real identity.");
|
|
594410
|
+
}
|
|
594411
|
+
lines.push("Use identity_memory only when the user explicitly names, stages, enrolls, asks to identify, or asks to recall identity evidence.");
|
|
594412
|
+
return lines.join("\n");
|
|
594413
|
+
}
|
|
594414
|
+
function stageVisualIdentityAssertion(options2) {
|
|
594415
|
+
const name10 = options2.name.trim();
|
|
594416
|
+
if (!name10) throw new Error("Name is required to stage a visual identity assertion.");
|
|
594417
|
+
const pendingId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
594418
|
+
const expiresAt = Date.now() + (typeof options2.expiresInMs === "number" && Number.isFinite(options2.expiresInMs) ? Math.max(6e4, Math.min(864e5, options2.expiresInMs)) : 72e5);
|
|
594419
|
+
const dbPaths = omniusMemoryDbPaths(options2.repoRoot);
|
|
594420
|
+
const graph = new TemporalGraph(dbPaths.knowledge);
|
|
594421
|
+
const store2 = new EpisodeStore(dbPaths.episodes, graph);
|
|
594422
|
+
try {
|
|
594423
|
+
const service = new MultimodalIdentityService({ episodeStore: store2, graph });
|
|
594424
|
+
const result = service.ingest({
|
|
594425
|
+
sourceSurface: options2.sourceSurface,
|
|
594426
|
+
sessionId: options2.sessionId,
|
|
594427
|
+
scope: options2.scope,
|
|
594428
|
+
sender: options2.sender,
|
|
594429
|
+
message: options2.message,
|
|
594430
|
+
replyTo: options2.replyTo,
|
|
594431
|
+
modality: "social",
|
|
594432
|
+
content: options2.note || `Pending visual identity assertion for next image: ${name10}`,
|
|
594433
|
+
labels: ["pending_visual_identity", name10],
|
|
594434
|
+
metadata: {
|
|
594435
|
+
identityPending: {
|
|
594436
|
+
kind: "visual_identity",
|
|
594437
|
+
pendingId,
|
|
594438
|
+
target: "next_visual_media",
|
|
594439
|
+
name: name10,
|
|
594440
|
+
relation: options2.relation || "depicts",
|
|
594441
|
+
confidence: clamp016(options2.confidence, 0.92),
|
|
594442
|
+
note: options2.note,
|
|
594443
|
+
createdAt: Date.now(),
|
|
594444
|
+
expiresAt
|
|
594445
|
+
}
|
|
594446
|
+
},
|
|
594447
|
+
identityAssertions: [{
|
|
594448
|
+
name: name10,
|
|
594449
|
+
relation: options2.relation || "named_as",
|
|
594450
|
+
confidence: clamp016(options2.confidence, 0.92),
|
|
594451
|
+
assertedBy: options2.sender,
|
|
594452
|
+
note: options2.note || "Explicit user-provided identity staged for the next visual media."
|
|
594453
|
+
}]
|
|
594454
|
+
});
|
|
594455
|
+
return { pendingId, episodeId: result.episodeId, name: name10, expiresAt };
|
|
594456
|
+
} finally {
|
|
594457
|
+
store2.close();
|
|
594458
|
+
graph.close();
|
|
594459
|
+
}
|
|
594460
|
+
}
|
|
594461
|
+
async function associateVisualIdentityFromImage(options2) {
|
|
594462
|
+
const startedAt2 = Date.now();
|
|
594463
|
+
const visual = options2.visualMemoryTool ?? new VisualMemoryTool();
|
|
594464
|
+
const identify2 = await visual.execute({
|
|
594465
|
+
action: "identify",
|
|
594466
|
+
image: options2.imagePath,
|
|
594467
|
+
threshold: typeof options2.threshold === "number" ? options2.threshold : 0.5,
|
|
594468
|
+
format: "json"
|
|
594469
|
+
});
|
|
594470
|
+
const parsed = parseStructuredIdentifyResult(identify2);
|
|
594471
|
+
if (!identify2.success) {
|
|
594472
|
+
return {
|
|
594473
|
+
matches: [],
|
|
594474
|
+
unknownFaceCount: 0,
|
|
594475
|
+
pendingApplied: [],
|
|
594476
|
+
pendingSkipped: [],
|
|
594477
|
+
recalledEpisodes: [],
|
|
594478
|
+
committedEpisodeIds: [],
|
|
594479
|
+
structured: parsed.structured,
|
|
594480
|
+
contextBlock: "",
|
|
594481
|
+
degradedReason: identify2.error || "visual_memory identify failed",
|
|
594482
|
+
rawIdentifyOutput: parsed.raw
|
|
594483
|
+
};
|
|
594484
|
+
}
|
|
594485
|
+
if (!parsed.structured) {
|
|
594486
|
+
return {
|
|
594487
|
+
matches: [],
|
|
594488
|
+
unknownFaceCount: 0,
|
|
594489
|
+
pendingApplied: [],
|
|
594490
|
+
pendingSkipped: [],
|
|
594491
|
+
recalledEpisodes: [],
|
|
594492
|
+
committedEpisodeIds: [],
|
|
594493
|
+
structured: false,
|
|
594494
|
+
contextBlock: "",
|
|
594495
|
+
degradedReason: "visual_memory identify did not return structured JSON",
|
|
594496
|
+
rawIdentifyOutput: parsed.raw
|
|
594497
|
+
};
|
|
594498
|
+
}
|
|
594499
|
+
const dbPaths = omniusMemoryDbPaths(options2.repoRoot);
|
|
594500
|
+
const graph = new TemporalGraph(dbPaths.knowledge);
|
|
594501
|
+
const store2 = new EpisodeStore(dbPaths.episodes, graph);
|
|
594502
|
+
const committedEpisodeIds = [];
|
|
594503
|
+
const pendingApplied = [];
|
|
594504
|
+
const pendingSkipped = [];
|
|
594505
|
+
let unknownFaceCount = 0;
|
|
594506
|
+
try {
|
|
594507
|
+
const shouldCommit = options2.commitMatches !== false;
|
|
594508
|
+
const service = new MultimodalIdentityService({ episodeStore: store2, graph });
|
|
594509
|
+
if (parsed.matches.length === 0) {
|
|
594510
|
+
try {
|
|
594511
|
+
const detect2 = await visual.execute({ action: "detect", image: options2.imagePath, format: "json" });
|
|
594512
|
+
if (detect2.success) unknownFaceCount = parseDetectedFaceCount(detect2);
|
|
594513
|
+
} catch {
|
|
594514
|
+
}
|
|
594515
|
+
}
|
|
594516
|
+
if (shouldCommit && parsed.matches.length > 0) {
|
|
594517
|
+
for (const match of parsed.matches) {
|
|
594518
|
+
const result2 = service.ingest({
|
|
594519
|
+
sourceSurface: options2.sourceSurface,
|
|
594520
|
+
sessionId: options2.sessionId,
|
|
594521
|
+
scope: options2.scope,
|
|
594522
|
+
sender: options2.sender,
|
|
594523
|
+
message: options2.message,
|
|
594524
|
+
replyTo: options2.replyTo,
|
|
594525
|
+
modality: "visual",
|
|
594526
|
+
content: `Prior enrolled visual identity match: ${match.name}`,
|
|
594527
|
+
extractedContent: options2.extractedContent,
|
|
594528
|
+
media: options2.media ?? { path: options2.imagePath, mediaType: "photo" },
|
|
594529
|
+
labels: ["visual_identity_match", match.name],
|
|
594530
|
+
metadata: {
|
|
594531
|
+
visualIdentityAssociation: {
|
|
594532
|
+
version: 1,
|
|
594533
|
+
imagePath: options2.imagePath,
|
|
594534
|
+
name: match.name,
|
|
594535
|
+
personId: match.personId,
|
|
594536
|
+
confidence: match.confidence,
|
|
594537
|
+
margin: match.margin,
|
|
594538
|
+
elapsedMs: Date.now() - startedAt2
|
|
594539
|
+
}
|
|
594540
|
+
},
|
|
594541
|
+
identityAssertions: [{
|
|
594542
|
+
name: match.name,
|
|
594543
|
+
relation: "same_person_candidate",
|
|
594544
|
+
confidence: match.confidence,
|
|
594545
|
+
assertedBy: { id: "visual_memory", displayName: "visual_memory", isBot: true },
|
|
594546
|
+
note: `Prior enrolled visual-memory face match for ${basename20(options2.imagePath)}`
|
|
594547
|
+
}]
|
|
594548
|
+
});
|
|
594549
|
+
if (result2.episodeId) committedEpisodeIds.push(result2.episodeId);
|
|
594550
|
+
}
|
|
594551
|
+
}
|
|
594552
|
+
if (shouldCommit && parsed.matches.length === 0) {
|
|
594553
|
+
const pending = activePendingVisualIdentities(store2, options2.scope, options2.sessionId);
|
|
594554
|
+
for (const item of pending) {
|
|
594555
|
+
const enrollment = await visual.execute({ action: "enroll", image: options2.imagePath, name: item.name });
|
|
594556
|
+
if (!enrollment.success) {
|
|
594557
|
+
pendingSkipped.push({
|
|
594558
|
+
pendingId: item.pendingId,
|
|
594559
|
+
name: item.name,
|
|
594560
|
+
reason: enrollment.error || enrollment.output || "face enrollment failed"
|
|
594561
|
+
});
|
|
594562
|
+
continue;
|
|
594563
|
+
}
|
|
594564
|
+
const result2 = service.ingest({
|
|
594565
|
+
sourceSurface: options2.sourceSurface,
|
|
594566
|
+
sessionId: options2.sessionId,
|
|
594567
|
+
scope: options2.scope,
|
|
594568
|
+
sender: options2.sender,
|
|
594569
|
+
message: options2.message,
|
|
594570
|
+
replyTo: options2.replyTo,
|
|
594571
|
+
modality: "visual",
|
|
594572
|
+
content: `Applied pending visual identity assertion: ${item.name}`,
|
|
594573
|
+
extractedContent: options2.extractedContent,
|
|
594574
|
+
media: options2.media ?? { path: options2.imagePath, mediaType: "photo" },
|
|
594575
|
+
labels: ["pending_visual_identity_applied", item.name],
|
|
594576
|
+
metadata: {
|
|
594577
|
+
identityPendingConsumed: {
|
|
594578
|
+
pendingId: item.pendingId,
|
|
594579
|
+
sourceEpisodeId: item.episodeId,
|
|
594580
|
+
name: item.name,
|
|
594581
|
+
imagePath: options2.imagePath,
|
|
594582
|
+
consumedAt: Date.now(),
|
|
594583
|
+
enrollmentOutput: enrollment.output
|
|
594584
|
+
}
|
|
594585
|
+
},
|
|
594586
|
+
identityAssertions: [{
|
|
594587
|
+
name: item.name,
|
|
594588
|
+
relation: "depicts",
|
|
594589
|
+
confidence: item.confidence,
|
|
594590
|
+
assertedBy: item.sender || options2.sender,
|
|
594591
|
+
note: item.note || `Applied explicit pending identity assertion to ${basename20(options2.imagePath)}`
|
|
594592
|
+
}]
|
|
594593
|
+
});
|
|
594594
|
+
if (result2.episodeId) committedEpisodeIds.push(result2.episodeId);
|
|
594595
|
+
pendingApplied.push({
|
|
594596
|
+
pendingId: item.pendingId,
|
|
594597
|
+
name: item.name,
|
|
594598
|
+
confidence: item.confidence,
|
|
594599
|
+
sourceEpisodeId: item.episodeId,
|
|
594600
|
+
committedEpisodeId: result2.episodeId,
|
|
594601
|
+
enrollmentOutput: enrollment.output
|
|
594602
|
+
});
|
|
594603
|
+
}
|
|
594604
|
+
}
|
|
594605
|
+
const excluded = new Set(committedEpisodeIds);
|
|
594606
|
+
const limit = typeof options2.limit === "number" && Number.isFinite(options2.limit) ? Math.max(1, Math.min(12, Math.floor(options2.limit))) : 5;
|
|
594607
|
+
const recalledEpisodes = [];
|
|
594608
|
+
const seen = /* @__PURE__ */ new Set();
|
|
594609
|
+
const namesForRecall = [
|
|
594610
|
+
...parsed.matches.map((match) => match.name),
|
|
594611
|
+
...pendingApplied.map((pending) => pending.name)
|
|
594612
|
+
];
|
|
594613
|
+
for (const name10 of namesForRecall) {
|
|
594614
|
+
for (const ep of recallPersonEpisodes(store2, graph, name10, options2.scope, options2.sessionId, excluded, limit)) {
|
|
594615
|
+
if (seen.has(ep.id)) continue;
|
|
594616
|
+
seen.add(ep.id);
|
|
594617
|
+
recalledEpisodes.push(ep);
|
|
594618
|
+
}
|
|
594619
|
+
}
|
|
594620
|
+
const result = {
|
|
594621
|
+
matches: parsed.matches,
|
|
594622
|
+
unknownFaceCount,
|
|
594623
|
+
pendingApplied,
|
|
594624
|
+
pendingSkipped,
|
|
594625
|
+
recalledEpisodes: recalledEpisodes.slice(0, limit),
|
|
594626
|
+
committedEpisodeIds,
|
|
594627
|
+
structured: true,
|
|
594628
|
+
contextBlock: "",
|
|
594629
|
+
rawIdentifyOutput: parsed.raw
|
|
594630
|
+
};
|
|
594631
|
+
result.contextBlock = formatVisualIdentityAssociationContext(result);
|
|
594632
|
+
return result;
|
|
594633
|
+
} finally {
|
|
594634
|
+
store2.close();
|
|
594635
|
+
graph.close();
|
|
594636
|
+
}
|
|
594637
|
+
}
|
|
594638
|
+
var init_visual_identity_association = __esm({
|
|
594639
|
+
"packages/cli/src/tui/visual-identity-association.ts"() {
|
|
594640
|
+
"use strict";
|
|
594641
|
+
init_dist7();
|
|
594642
|
+
init_dist5();
|
|
594643
|
+
init_memory_paths();
|
|
594644
|
+
}
|
|
594645
|
+
});
|
|
594646
|
+
|
|
594647
|
+
// packages/cli/src/tui/identity-memory-tool.ts
|
|
594648
|
+
import { existsSync as existsSync98 } from "node:fs";
|
|
594649
|
+
import { basename as basename21, extname as extname14, resolve as resolve39 } from "node:path";
|
|
594650
|
+
function personKey2(name10) {
|
|
593993
594651
|
return `person:${name10.trim().toLowerCase().replace(/\s+/g, " ")}`;
|
|
593994
594652
|
}
|
|
593995
594653
|
function coerceAction(value2) {
|
|
593996
594654
|
const raw = String(value2 || "recall").trim().toLowerCase();
|
|
593997
594655
|
if (raw === "assert" || raw === "remember" || raw === "name") return "assert_identity";
|
|
594656
|
+
if (raw === "stage" || raw === "pending" || raw === "next" || raw === "expect") return "stage_identity";
|
|
593998
594657
|
if (raw === "enroll" || raw === "enrol" || raw === "face") return "enroll_face";
|
|
593999
594658
|
if (raw === "who" || raw === "recognize" || raw === "recognise") return "identify";
|
|
594000
594659
|
if (raw === "list") return "inspect";
|
|
594001
|
-
if (raw === "assert_identity" || raw === "enroll_face" || raw === "identify" || raw === "recall" || raw === "inspect") {
|
|
594660
|
+
if (raw === "assert_identity" || raw === "stage_identity" || raw === "enroll_face" || raw === "identify" || raw === "recall" || raw === "inspect") {
|
|
594002
594661
|
return raw;
|
|
594003
594662
|
}
|
|
594004
594663
|
return "recall";
|
|
@@ -594056,7 +594715,7 @@ async function resolveMediaFromArgs(args, opts) {
|
|
|
594056
594715
|
path: path11,
|
|
594057
594716
|
media,
|
|
594058
594717
|
modality: inferModality(media),
|
|
594059
|
-
label:
|
|
594718
|
+
label: basename21(path11)
|
|
594060
594719
|
};
|
|
594061
594720
|
}
|
|
594062
594721
|
function edgeDirection(edge, nodeId, otherText) {
|
|
@@ -594067,7 +594726,10 @@ function formatIdentityMemoryContext(surface) {
|
|
|
594067
594726
|
return [
|
|
594068
594727
|
"Identity memory contract:",
|
|
594069
594728
|
"- Use identity_memory when a user explicitly asks you to remember, name, enroll, identify, or recall a person/voice/object identity from scoped media.",
|
|
594070
|
-
"- Do not infer a real person's identity from an image on your own. Store identity only from an explicit user assertion or from a prior enrolled match.",
|
|
594729
|
+
"- Do not infer a real person's identity from an image on your own. Store identity only from an explicit user assertion or from a structured prior enrolled visual-memory match.",
|
|
594730
|
+
"- Image ingress may include a Scoped Visual Identity Recall block. Treat it as prior enrolled evidence scoped to the current chat/session, not as a new caption-derived assertion.",
|
|
594731
|
+
"- If the user gives a name before the image arrives, or says the next image/media will be someone, call identity_memory with action='stage_identity', name='<explicit name>'. The next same-scope image can then link and enroll that face.",
|
|
594732
|
+
"- If image ingress includes Unknown Visual Identity Candidate, ask who the person is only when identity matters to the user's task; if they provide a name, call identity_memory.",
|
|
594071
594733
|
"- For Telegram replies, use media='reply' when the user is naming or asking about the replied-to media; use media='latest' for the latest media in the same chat.",
|
|
594072
594734
|
"- For visual identity assertions such as 'this is Amy', call identity_memory with action='assert_identity', name='Amy', relation='depicts'. The tool stores graph evidence and attempts face enrollment.",
|
|
594073
594735
|
"- For 'who is this?' on an image, call identity_memory with action='identify'.",
|
|
@@ -594080,6 +594742,8 @@ var init_identity_memory_tool = __esm({
|
|
|
594080
594742
|
"use strict";
|
|
594081
594743
|
init_dist7();
|
|
594082
594744
|
init_dist5();
|
|
594745
|
+
init_memory_paths();
|
|
594746
|
+
init_visual_identity_association();
|
|
594083
594747
|
IdentityMemoryTool = class {
|
|
594084
594748
|
constructor(repoRoot, opts = {}) {
|
|
594085
594749
|
this.repoRoot = repoRoot;
|
|
@@ -594088,14 +594752,14 @@ var init_identity_memory_tool = __esm({
|
|
|
594088
594752
|
repoRoot;
|
|
594089
594753
|
opts;
|
|
594090
594754
|
name = "identity_memory";
|
|
594091
|
-
description = "Scoped multimodal identity memory. Agentically records explicit identity assertions, enrolls visual face evidence, identifies enrolled faces, and recalls stored person evidence without regex shortcuts.";
|
|
594755
|
+
description = "Scoped multimodal identity memory. Agentically records explicit identity assertions, stages next-media identity assertions, enrolls visual face evidence, identifies enrolled faces, and recalls stored person evidence without regex shortcuts.";
|
|
594092
594756
|
parameters = {
|
|
594093
594757
|
type: "object",
|
|
594094
594758
|
properties: {
|
|
594095
594759
|
action: {
|
|
594096
594760
|
type: "string",
|
|
594097
|
-
enum: ["assert_identity", "enroll_face", "identify", "recall", "inspect"],
|
|
594098
|
-
description: "assert_identity/enroll_face store explicit
|
|
594761
|
+
enum: ["assert_identity", "stage_identity", "enroll_face", "identify", "recall", "inspect"],
|
|
594762
|
+
description: "assert_identity/enroll_face store explicit current-media evidence; stage_identity stores an explicit name for the next visual media in this scope; identify recognizes current media; recall/inspect read stored identity evidence."
|
|
594099
594763
|
},
|
|
594100
594764
|
name: {
|
|
594101
594765
|
type: "string",
|
|
@@ -594133,6 +594797,10 @@ var init_identity_memory_tool = __esm({
|
|
|
594133
594797
|
limit: {
|
|
594134
594798
|
type: "number",
|
|
594135
594799
|
description: "Recall/inspect result limit. Default 12."
|
|
594800
|
+
},
|
|
594801
|
+
expires_in_minutes: {
|
|
594802
|
+
type: "number",
|
|
594803
|
+
description: "For stage_identity, how long the pending next-image assertion remains active. Default 120 minutes."
|
|
594136
594804
|
}
|
|
594137
594805
|
},
|
|
594138
594806
|
required: ["action"]
|
|
@@ -594140,7 +594808,7 @@ var init_identity_memory_tool = __esm({
|
|
|
594140
594808
|
async execute(args) {
|
|
594141
594809
|
const startedAt2 = Date.now();
|
|
594142
594810
|
const action = coerceAction(args["action"]);
|
|
594143
|
-
const dbPaths =
|
|
594811
|
+
const dbPaths = omniusMemoryDbPaths(this.repoRoot);
|
|
594144
594812
|
const store2 = new EpisodeStore(dbPaths.episodes);
|
|
594145
594813
|
const graph = new TemporalGraph(dbPaths.knowledge);
|
|
594146
594814
|
try {
|
|
@@ -594150,6 +594818,9 @@ var init_identity_memory_tool = __esm({
|
|
|
594150
594818
|
if (action === "recall" || action === "inspect") {
|
|
594151
594819
|
return this.recall(args, startedAt2, graph);
|
|
594152
594820
|
}
|
|
594821
|
+
if (action === "stage_identity") {
|
|
594822
|
+
return this.stageIdentity(args, startedAt2);
|
|
594823
|
+
}
|
|
594153
594824
|
return await this.assertIdentity(action, args, startedAt2, store2, graph);
|
|
594154
594825
|
} finally {
|
|
594155
594826
|
store2.close();
|
|
@@ -594176,6 +594847,7 @@ var init_identity_memory_tool = __esm({
|
|
|
594176
594847
|
const content = evidenceNote || this.opts.message?.text || (media?.caption ? `Identity assertion for ${name10}: ${media.caption}` : `Identity assertion for ${name10}`);
|
|
594177
594848
|
const result = service.ingest({
|
|
594178
594849
|
sourceSurface: this.opts.sourceSurface || "api",
|
|
594850
|
+
sessionId: this.opts.sessionId,
|
|
594179
594851
|
scope: this.opts.scope,
|
|
594180
594852
|
sender: this.opts.sender,
|
|
594181
594853
|
message: this.opts.message,
|
|
@@ -594201,7 +594873,7 @@ var init_identity_memory_tool = __esm({
|
|
|
594201
594873
|
} else if (shouldEnrollFace) {
|
|
594202
594874
|
faceLine = "face enrollment: skipped because no resolved image path was available";
|
|
594203
594875
|
}
|
|
594204
|
-
const mediaLine = resolvedMedia ? `media: ${resolvedMedia.label ||
|
|
594876
|
+
const mediaLine = resolvedMedia ? `media: ${resolvedMedia.label || basename21(resolvedMedia.path)} (${resolvedMedia.path})` : "media: none; stored as scoped textual identity evidence only";
|
|
594205
594877
|
const output = [
|
|
594206
594878
|
`Stored identity evidence for ${name10}.`,
|
|
594207
594879
|
`relation: ${relation}`,
|
|
@@ -594222,6 +594894,50 @@ var init_identity_memory_tool = __esm({
|
|
|
594222
594894
|
durationMs: Date.now() - startedAt2
|
|
594223
594895
|
};
|
|
594224
594896
|
}
|
|
594897
|
+
stageIdentity(args, startedAt2) {
|
|
594898
|
+
const name10 = String(args["name"] || "").trim();
|
|
594899
|
+
if (!name10) {
|
|
594900
|
+
return {
|
|
594901
|
+
success: false,
|
|
594902
|
+
output: "",
|
|
594903
|
+
error: "identity_memory stage_identity requires name. Pass the explicit user-provided name for the next visual media.",
|
|
594904
|
+
durationMs: Date.now() - startedAt2
|
|
594905
|
+
};
|
|
594906
|
+
}
|
|
594907
|
+
const evidenceNote = String(args["evidence_note"] ?? args["note"] ?? this.opts.message?.text ?? "").trim();
|
|
594908
|
+
const expiresMinutes = typeof args["expires_in_minutes"] === "number" && Number.isFinite(args["expires_in_minutes"]) ? Math.max(1, Math.min(1440, args["expires_in_minutes"])) : 120;
|
|
594909
|
+
const result = stageVisualIdentityAssertion({
|
|
594910
|
+
repoRoot: this.repoRoot,
|
|
594911
|
+
sourceSurface: this.opts.sourceSurface || "api",
|
|
594912
|
+
sessionId: this.opts.sessionId,
|
|
594913
|
+
scope: this.opts.scope,
|
|
594914
|
+
sender: this.opts.sender,
|
|
594915
|
+
message: this.opts.message,
|
|
594916
|
+
replyTo: this.opts.replyTo,
|
|
594917
|
+
name: name10,
|
|
594918
|
+
relation: "depicts",
|
|
594919
|
+
confidence: coerceConfidence(args["confidence"]),
|
|
594920
|
+
note: evidenceNote || `Explicit user-provided name for the next visual media: ${name10}`,
|
|
594921
|
+
expiresInMs: expiresMinutes * 6e4
|
|
594922
|
+
});
|
|
594923
|
+
return {
|
|
594924
|
+
success: true,
|
|
594925
|
+
output: [
|
|
594926
|
+
`Staged visual identity for next same-scope image: ${result.name}.`,
|
|
594927
|
+
`pending_id: ${result.pendingId}`,
|
|
594928
|
+
`episode: ${result.episodeId}`,
|
|
594929
|
+
`expires_at: ${new Date(result.expiresAt).toISOString()}`
|
|
594930
|
+
].join("\n"),
|
|
594931
|
+
llmContent: [
|
|
594932
|
+
`identity_memory staged next_visual_media name=${result.name}`,
|
|
594933
|
+
`pending_id=${result.pendingId}`,
|
|
594934
|
+
`episode_id=${result.episodeId}`,
|
|
594935
|
+
`expires_at=${new Date(result.expiresAt).toISOString()}`,
|
|
594936
|
+
"When the next image arrives in this same scope, image ingress can link and enroll it without guessing from text."
|
|
594937
|
+
].join("\n"),
|
|
594938
|
+
durationMs: Date.now() - startedAt2
|
|
594939
|
+
};
|
|
594940
|
+
}
|
|
594225
594941
|
async identify(args, startedAt2, graph) {
|
|
594226
594942
|
const resolvedMedia = await resolveMediaFromArgs(args, this.opts);
|
|
594227
594943
|
if (!resolvedMedia?.path) {
|
|
@@ -594240,23 +594956,40 @@ var init_identity_memory_tool = __esm({
|
|
|
594240
594956
|
durationMs: Date.now() - startedAt2
|
|
594241
594957
|
};
|
|
594242
594958
|
}
|
|
594243
|
-
const visual = this.opts.visualMemoryTool ?? new VisualMemoryTool();
|
|
594244
594959
|
const threshold = typeof args["threshold"] === "number" ? args["threshold"] : 0.5;
|
|
594245
|
-
const
|
|
594960
|
+
const association = await associateVisualIdentityFromImage({
|
|
594961
|
+
repoRoot: this.repoRoot,
|
|
594962
|
+
imagePath: resolvedMedia.path,
|
|
594963
|
+
sourceSurface: this.opts.sourceSurface || "api",
|
|
594964
|
+
scope: this.opts.scope,
|
|
594965
|
+
sender: this.opts.sender,
|
|
594966
|
+
message: this.opts.message,
|
|
594967
|
+
replyTo: this.opts.replyTo,
|
|
594968
|
+
sessionId: this.opts.sessionId,
|
|
594969
|
+
media: resolvedMedia.media ?? { path: resolvedMedia.path, mediaType: inferMediaTypeFromPath(resolvedMedia.path) },
|
|
594970
|
+
extractedContent: resolvedMedia.extractedContent,
|
|
594971
|
+
threshold,
|
|
594972
|
+
visualMemoryTool: this.opts.visualMemoryTool,
|
|
594973
|
+
limit: typeof args["limit"] === "number" ? args["limit"] : 5
|
|
594974
|
+
});
|
|
594246
594975
|
const known = graph.nodesByType("person", 50).filter((node) => node.text.startsWith("person:")).map((node) => node.text.slice("person:".length)).slice(0, 12);
|
|
594247
594976
|
const knownLine = known.length ? `known identity nodes: ${known.join(", ")}` : "known identity nodes: none";
|
|
594977
|
+
const matchLine = association.matches.length ? `visual matches: ${association.matches.map((match) => `${match.name} (${match.confidence.toFixed(2)})`).join(", ")}` : "visual matches: none";
|
|
594978
|
+
const context2 = association.contextBlock || association.degradedReason || "No enrolled face matched this image.";
|
|
594248
594979
|
return {
|
|
594249
|
-
success:
|
|
594980
|
+
success: !association.degradedReason,
|
|
594250
594981
|
output: [
|
|
594251
|
-
|
|
594982
|
+
matchLine,
|
|
594983
|
+
context2,
|
|
594252
594984
|
knownLine
|
|
594253
594985
|
].filter(Boolean).join("\n"),
|
|
594254
594986
|
llmContent: [
|
|
594255
|
-
|
|
594987
|
+
matchLine,
|
|
594988
|
+
association.contextBlock || association.degradedReason || "No enrolled face matched this image.",
|
|
594256
594989
|
knownLine,
|
|
594257
594990
|
"If no face matched and the user supplied a name, call identity_memory action='assert_identity'."
|
|
594258
594991
|
].join("\n"),
|
|
594259
|
-
error:
|
|
594992
|
+
error: association.degradedReason,
|
|
594260
594993
|
durationMs: Date.now() - startedAt2
|
|
594261
594994
|
};
|
|
594262
594995
|
}
|
|
@@ -594272,7 +595005,7 @@ ${people.join("\n")}` : "No stored explicit identity nodes found.",
|
|
|
594272
595005
|
durationMs: Date.now() - startedAt2
|
|
594273
595006
|
};
|
|
594274
595007
|
}
|
|
594275
|
-
const node = graph.findNode(
|
|
595008
|
+
const node = graph.findNode(personKey2(name10), "person");
|
|
594276
595009
|
if (!node) {
|
|
594277
595010
|
return {
|
|
594278
595011
|
success: true,
|
|
@@ -595081,7 +595814,7 @@ var init_banner = __esm({
|
|
|
595081
595814
|
|
|
595082
595815
|
// packages/cli/src/tui/carousel-descriptors.ts
|
|
595083
595816
|
import { existsSync as existsSync100, readFileSync as readFileSync80, writeFileSync as writeFileSync51, mkdirSync as mkdirSync57, readdirSync as readdirSync32 } from "node:fs";
|
|
595084
|
-
import { join as join114, basename as
|
|
595817
|
+
import { join as join114, basename as basename22 } from "node:path";
|
|
595085
595818
|
function loadToolProfile(repoRoot) {
|
|
595086
595819
|
const filePath = join114(repoRoot, OMNIUS_DIR, "context", TOOL_PROFILE_FILE);
|
|
595087
595820
|
try {
|
|
@@ -595177,7 +595910,7 @@ function generateDescriptors(repoRoot) {
|
|
|
595177
595910
|
extractFromSessions(repoRoot, tags);
|
|
595178
595911
|
extractFromMemory(repoRoot, tags);
|
|
595179
595912
|
extractFromToolProfile(profile, tags);
|
|
595180
|
-
const repoName2 =
|
|
595913
|
+
const repoName2 = basename22(repoRoot);
|
|
595181
595914
|
if (repoName2 && !tags.includes(repoName2)) {
|
|
595182
595915
|
tags.push(repoName2);
|
|
595183
595916
|
}
|
|
@@ -596197,7 +596930,7 @@ var init_promptLoader3 = __esm({
|
|
|
596197
596930
|
|
|
596198
596931
|
// packages/cli/src/tui/dream-engine.ts
|
|
596199
596932
|
import { mkdirSync as mkdirSync59, writeFileSync as writeFileSync52, readFileSync as readFileSync82, existsSync as existsSync102, readdirSync as readdirSync33 } from "node:fs";
|
|
596200
|
-
import { join as join117, basename as
|
|
596933
|
+
import { join as join117, basename as basename23 } from "node:path";
|
|
596201
596934
|
import { execSync as execSync54 } from "node:child_process";
|
|
596202
596935
|
function setDreamWriteContent(fn) {
|
|
596203
596936
|
_dreamWriteContent = fn;
|
|
@@ -596410,7 +597143,7 @@ var init_dream_engine = __esm({
|
|
|
596410
597143
|
const rawPath = String(args["path"] ?? "");
|
|
596411
597144
|
const content = String(args["content"] ?? "");
|
|
596412
597145
|
if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
|
|
596413
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join117(this.autoresearchDir,
|
|
597146
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join117(this.autoresearchDir, basename23(rawPath)) : join117(this.autoresearchDir, rawPath);
|
|
596414
597147
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
596415
597148
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .omnius/autoresearch/", durationMs: Date.now() - start2 };
|
|
596416
597149
|
}
|
|
@@ -596445,7 +597178,7 @@ var init_dream_engine = __esm({
|
|
|
596445
597178
|
const rawPath = String(args["path"] ?? "");
|
|
596446
597179
|
const oldStr = String(args["old_string"] ?? "");
|
|
596447
597180
|
const newStr = String(args["new_string"] ?? "");
|
|
596448
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join117(this.autoresearchDir,
|
|
597181
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join117(this.autoresearchDir, basename23(rawPath)) : join117(this.autoresearchDir, rawPath);
|
|
596449
597182
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
596450
597183
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .omnius/autoresearch/", durationMs: Date.now() - start2 };
|
|
596451
597184
|
}
|
|
@@ -596498,7 +597231,7 @@ var init_dream_engine = __esm({
|
|
|
596498
597231
|
const rawPath = String(args["path"] ?? "");
|
|
596499
597232
|
const content = String(args["content"] ?? "");
|
|
596500
597233
|
if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
|
|
596501
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join117(this.dreamsDir,
|
|
597234
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join117(this.dreamsDir, basename23(rawPath)) : join117(this.dreamsDir, rawPath);
|
|
596502
597235
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
596503
597236
|
return { success: false, output: "", error: "Dream mode: writes are confined to .omnius/dreams/", durationMs: Date.now() - start2 };
|
|
596504
597237
|
}
|
|
@@ -596533,7 +597266,7 @@ var init_dream_engine = __esm({
|
|
|
596533
597266
|
const rawPath = String(args["path"] ?? "");
|
|
596534
597267
|
const oldStr = String(args["old_string"] ?? "");
|
|
596535
597268
|
const newStr = String(args["new_string"] ?? "");
|
|
596536
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join117(this.dreamsDir,
|
|
597269
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join117(this.dreamsDir, basename23(rawPath)) : join117(this.dreamsDir, rawPath);
|
|
596537
597270
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
596538
597271
|
return { success: false, output: "", error: "Dream mode: edits are confined to .omnius/dreams/", durationMs: Date.now() - start2 };
|
|
596539
597272
|
}
|
|
@@ -598130,7 +598863,7 @@ var init_bless_engine = __esm({
|
|
|
598130
598863
|
|
|
598131
598864
|
// packages/cli/src/tui/dmn-engine.ts
|
|
598132
598865
|
import { existsSync as existsSync103, readFileSync as readFileSync83, writeFileSync as writeFileSync53, mkdirSync as mkdirSync60, readdirSync as readdirSync34, unlinkSync as unlinkSync18 } from "node:fs";
|
|
598133
|
-
import { join as join118, basename as
|
|
598866
|
+
import { join as join118, basename as basename24 } from "node:path";
|
|
598134
598867
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
598135
598868
|
const competenceReport = competence.length > 0 ? competence.map((c9) => {
|
|
598136
598869
|
const rate = c9.attempts > 0 ? Math.round(c9.successes / c9.attempts * 100) : 0;
|
|
@@ -598881,7 +599614,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
598881
599614
|
try {
|
|
598882
599615
|
const files = readdirSync34(dir).filter((f2) => f2.endsWith(".json"));
|
|
598883
599616
|
for (const f2 of files) {
|
|
598884
|
-
const topic =
|
|
599617
|
+
const topic = basename24(f2, ".json");
|
|
598885
599618
|
if (!topics.includes(topic)) topics.push(topic);
|
|
598886
599619
|
}
|
|
598887
599620
|
} catch {
|
|
@@ -598935,7 +599668,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
598935
599668
|
|
|
598936
599669
|
// packages/cli/src/tui/snr-engine.ts
|
|
598937
599670
|
import { existsSync as existsSync104, readdirSync as readdirSync35, readFileSync as readFileSync84 } from "node:fs";
|
|
598938
|
-
import { join as join119, basename as
|
|
599671
|
+
import { join as join119, basename as basename25 } from "node:path";
|
|
598939
599672
|
function computeDPrime(signalScores, noiseScores) {
|
|
598940
599673
|
if (signalScores.length === 0 || noiseScores.length === 0) return 0;
|
|
598941
599674
|
const mean = (arr) => arr.reduce((s2, v) => s2 + v, 0) / arr.length;
|
|
@@ -599229,7 +599962,7 @@ Call task_complete with the JSON array when done.`,
|
|
|
599229
599962
|
try {
|
|
599230
599963
|
const files = readdirSync35(dir).filter((f2) => f2.endsWith(".json"));
|
|
599231
599964
|
for (const f2 of files) {
|
|
599232
|
-
const topic =
|
|
599965
|
+
const topic = basename25(f2, ".json");
|
|
599233
599966
|
if (topics.length > 0 && !topics.includes(topic)) continue;
|
|
599234
599967
|
try {
|
|
599235
599968
|
const data = JSON.parse(readFileSync84(join119(dir, f2), "utf-8"));
|
|
@@ -599861,7 +600594,7 @@ import {
|
|
|
599861
600594
|
} from "node:fs";
|
|
599862
600595
|
import { mkdir as mkdir17 } from "node:fs/promises";
|
|
599863
600596
|
import {
|
|
599864
|
-
basename as
|
|
600597
|
+
basename as basename26,
|
|
599865
600598
|
dirname as dirname33,
|
|
599866
600599
|
extname as extname15,
|
|
599867
600600
|
isAbsolute as isAbsolute6,
|
|
@@ -600078,7 +600811,7 @@ function guardPath(root, rawPath) {
|
|
|
600078
600811
|
error: `Path escapes the public creative workspace. Use a relative path under ${rootAbs}.`
|
|
600079
600812
|
};
|
|
600080
600813
|
}
|
|
600081
|
-
if (
|
|
600814
|
+
if (basename26(abs) === MANIFEST_FILE) {
|
|
600082
600815
|
return { ok: false, error: "The creative workspace manifest is internal and cannot be edited." };
|
|
600083
600816
|
}
|
|
600084
600817
|
return { ok: true, path: { abs, rel } };
|
|
@@ -600170,7 +600903,7 @@ function rememberCreated(root, absPath) {
|
|
|
600170
600903
|
manifest.objects[rel] = {
|
|
600171
600904
|
logicalRel: rel,
|
|
600172
600905
|
storedRel,
|
|
600173
|
-
originalName:
|
|
600906
|
+
originalName: basename26(guarded.path.abs),
|
|
600174
600907
|
prefixBytes: prefix.length,
|
|
600175
600908
|
encrypted: true,
|
|
600176
600909
|
key: key.toString("base64"),
|
|
@@ -600221,7 +600954,7 @@ function materializeTelegramCreativeArtifactForSend(root, rawPath) {
|
|
|
600221
600954
|
}
|
|
600222
600955
|
const stageDir = join120(rootAbs, SEND_DIR, `${Date.now()}-${randomBytes21(8).toString("hex")}`);
|
|
600223
600956
|
mkdirSync61(stageDir, { recursive: true });
|
|
600224
|
-
const staged = join120(stageDir, object.originalName ||
|
|
600957
|
+
const staged = join120(stageDir, object.originalName || basename26(rel));
|
|
600225
600958
|
writeFileSync54(staged, payload);
|
|
600226
600959
|
return {
|
|
600227
600960
|
ok: true,
|
|
@@ -600437,7 +601170,7 @@ ${result.output}`,
|
|
|
600437
601170
|
});
|
|
600438
601171
|
|
|
600439
601172
|
// packages/cli/src/tui/stimulation.ts
|
|
600440
|
-
function
|
|
601173
|
+
function clamp017(value2) {
|
|
600441
601174
|
return Math.max(0, Math.min(1, value2));
|
|
600442
601175
|
}
|
|
600443
601176
|
function cloneState(state) {
|
|
@@ -600493,7 +601226,7 @@ var init_stimulation = __esm({
|
|
|
600493
601226
|
...DEFAULT_STATE,
|
|
600494
601227
|
...state,
|
|
600495
601228
|
phase: normalizePhase(state.phase) ?? DEFAULT_STATE.phase,
|
|
600496
|
-
attention:
|
|
601229
|
+
attention: clamp017(Number.isFinite(state.attention) ? Number(state.attention) : DEFAULT_STATE.attention),
|
|
600497
601230
|
updatedAtMs: Number.isFinite(state.updatedAtMs) ? Number(state.updatedAtMs) : now,
|
|
600498
601231
|
lastStimulusAtMs: Number.isFinite(state.lastStimulusAtMs) ? Number(state.lastStimulusAtMs) : now,
|
|
600499
601232
|
messagesSinceAnalysis: Math.max(0, Math.floor(Number(state.messagesSinceAnalysis ?? 0))),
|
|
@@ -600543,11 +601276,11 @@ var init_stimulation = __esm({
|
|
|
600543
601276
|
const state = this.stateFor(channelId, nowMs);
|
|
600544
601277
|
this.applyTimeDecay(state, nowMs);
|
|
600545
601278
|
if (Number.isFinite(decision.attentionScore)) {
|
|
600546
|
-
state.attention =
|
|
601279
|
+
state.attention = clamp017(Number(decision.attentionScore));
|
|
600547
601280
|
} else if (Number.isFinite(decision.attentionDelta)) {
|
|
600548
|
-
state.attention =
|
|
601281
|
+
state.attention = clamp017(state.attention + Number(decision.attentionDelta));
|
|
600549
601282
|
} else {
|
|
600550
|
-
state.attention =
|
|
601283
|
+
state.attention = clamp017(state.attention + (decision.shouldReply ? 0.22 : -0.1));
|
|
600551
601284
|
}
|
|
600552
601285
|
if (decision.phase) {
|
|
600553
601286
|
state.attention = Math.max(state.attention, PHASE_FLOORS[decision.phase]);
|
|
@@ -600603,7 +601336,7 @@ var init_stimulation = __esm({
|
|
|
600603
601336
|
const elapsedMs2 = Math.max(0, nowMs - (state.updatedAtMs || nowMs));
|
|
600604
601337
|
if (elapsedMs2 <= 0) return;
|
|
600605
601338
|
const halfLives = elapsedMs2 / (12 * 6e4);
|
|
600606
|
-
state.attention =
|
|
601339
|
+
state.attention = clamp017(state.attention * Math.pow(0.5, halfLives));
|
|
600607
601340
|
if (state.phase !== "engaged" || elapsedMs2 > 4 * 6e4) {
|
|
600608
601341
|
state.phase = phaseFromAttention(state.attention);
|
|
600609
601342
|
}
|
|
@@ -600615,7 +601348,7 @@ var init_stimulation = __esm({
|
|
|
600615
601348
|
// packages/cli/src/tui/telegram-channel-dmn.ts
|
|
600616
601349
|
import { existsSync as existsSync106, mkdirSync as mkdirSync62, readdirSync as readdirSync36, readFileSync as readFileSync86, writeFileSync as writeFileSync55 } from "node:fs";
|
|
600617
601350
|
import { join as join121 } from "node:path";
|
|
600618
|
-
import { createHash as
|
|
601351
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
600619
601352
|
function safeFilePart(value2) {
|
|
600620
601353
|
return value2.replace(/[^A-Za-z0-9_.-]+/g, "_").slice(0, 80) || "telegram";
|
|
600621
601354
|
}
|
|
@@ -600623,12 +601356,12 @@ function daydreamRoot(repoRoot) {
|
|
|
600623
601356
|
return join121(repoRoot, ".omnius", "telegram-daydreams");
|
|
600624
601357
|
}
|
|
600625
601358
|
function sessionDir(repoRoot, sessionKey) {
|
|
600626
|
-
const hash =
|
|
601359
|
+
const hash = createHash21("sha1").update(sessionKey).digest("hex").slice(0, 20);
|
|
600627
601360
|
return join121(daydreamRoot(repoRoot), safeFilePart(hash));
|
|
600628
601361
|
}
|
|
600629
601362
|
function compactLine2(value2, max = 220) {
|
|
600630
|
-
const
|
|
600631
|
-
return
|
|
601363
|
+
const clean5 = value2.replace(/\s+/g, " ").trim();
|
|
601364
|
+
return clean5.length > max ? `${clean5.slice(0, Math.max(0, max - 3)).trimEnd()}...` : clean5;
|
|
600632
601365
|
}
|
|
600633
601366
|
function isoFromMs(value2) {
|
|
600634
601367
|
return value2 ? new Date(value2).toISOString() : void 0;
|
|
@@ -600698,7 +601431,7 @@ function buildReplyOpportunities(input, openQuestions) {
|
|
|
600698
601431
|
}
|
|
600699
601432
|
return opportunities;
|
|
600700
601433
|
}
|
|
600701
|
-
function
|
|
601434
|
+
function clamp018(value2) {
|
|
600702
601435
|
if (!Number.isFinite(value2)) return 0;
|
|
600703
601436
|
return Math.max(0, Math.min(1, value2));
|
|
600704
601437
|
}
|
|
@@ -600709,7 +601442,7 @@ function pushStimulationSignal(signals, signal, source, weight) {
|
|
|
600709
601442
|
const cleanSignal = compactLine2(signal, 120);
|
|
600710
601443
|
const cleanSource = compactLine2(source, 180);
|
|
600711
601444
|
if (!cleanSignal || signals.some((entry) => entry.signal === cleanSignal && entry.source === cleanSource)) return;
|
|
600712
|
-
signals.push({ signal: cleanSignal, source: cleanSource, weight:
|
|
601445
|
+
signals.push({ signal: cleanSignal, source: cleanSource, weight: clamp018(weight) });
|
|
600713
601446
|
}
|
|
600714
601447
|
function buildMetaAnalysisSignals(input) {
|
|
600715
601448
|
const chatLabel = input.chatTitle || input.chatId;
|
|
@@ -600784,7 +601517,7 @@ function buildCuriosityThreads(input, openQuestions, stimulationSignals) {
|
|
|
600784
601517
|
question: text.endsWith("?") || text.endsWith("?") ? text : `What should be learned or clarified from: ${text || entry.mediaSummary || "recent media"}?`,
|
|
600785
601518
|
rationale: "Human curiosity, uncertainty, or multimodal content makes this a useful idle exploration target.",
|
|
600786
601519
|
sourceMessages: messageId,
|
|
600787
|
-
intensity:
|
|
601520
|
+
intensity: clamp018(0.5 + replyBoost + mediaBoost + questionBoost)
|
|
600788
601521
|
});
|
|
600789
601522
|
}
|
|
600790
601523
|
for (const question of openQuestions.slice(-4)) {
|
|
@@ -600804,7 +601537,7 @@ function buildCuriosityThreads(input, openQuestions, stimulationSignals) {
|
|
|
600804
601537
|
question: `Is there a useful clarification or memory consolidation around ${strongest.source}?`,
|
|
600805
601538
|
rationale: "Strongest stimulation signal can seed a low-intrusion reflection target.",
|
|
600806
601539
|
sourceMessages: [],
|
|
600807
|
-
intensity:
|
|
601540
|
+
intensity: clamp018(strongest.weight * 0.72)
|
|
600808
601541
|
});
|
|
600809
601542
|
}
|
|
600810
601543
|
return threads.sort((a2, b) => b.intensity - a2.intensity).slice(0, 8);
|
|
@@ -600864,8 +601597,8 @@ function participantForThread(input, thread) {
|
|
|
600864
601597
|
return input.participants.find((participant) => participant.username === sourceMessage.username);
|
|
600865
601598
|
}
|
|
600866
601599
|
if (sourceMessage?.speaker) {
|
|
600867
|
-
const
|
|
600868
|
-
return input.participants.find((participant) => participant.username ===
|
|
601600
|
+
const clean5 = sourceMessage.speaker.replace(/^@/, "");
|
|
601601
|
+
return input.participants.find((participant) => participant.username === clean5 || participant.firstName === sourceMessage.speaker);
|
|
600869
601602
|
}
|
|
600870
601603
|
return topParticipants(input)[0];
|
|
600871
601604
|
}
|
|
@@ -600878,7 +601611,7 @@ function buildOutreachPlans(input, curiosityThreads) {
|
|
|
600878
601611
|
purpose: "Continue the public thread only when the live model judges that the group would benefit from a concise follow-up.",
|
|
600879
601612
|
draftIntent: "Ask one concrete clarification, offer one useful synthesis, or stay silent if the room has moved on.",
|
|
600880
601613
|
gate: "model_decision",
|
|
600881
|
-
confidence:
|
|
601614
|
+
confidence: clamp018(thread.intensity * 0.86)
|
|
600882
601615
|
});
|
|
600883
601616
|
const participant = participantForThread(input, thread);
|
|
600884
601617
|
if (!participant) continue;
|
|
@@ -600890,7 +601623,7 @@ function buildOutreachPlans(input, curiosityThreads) {
|
|
|
600890
601623
|
purpose: "Offer a one-to-one follow-up only if private contact is allowed and the issue is personal, unresolved, or better handled outside the group.",
|
|
600891
601624
|
draftIntent: "Reference the public thread briefly, ask permission to continue privately, and do not reveal hidden meta-analysis.",
|
|
600892
601625
|
gate: "admin_review",
|
|
600893
|
-
confidence:
|
|
601626
|
+
confidence: clamp018(thread.intensity * 0.58)
|
|
600894
601627
|
});
|
|
600895
601628
|
}
|
|
600896
601629
|
return plans.slice(0, 8);
|
|
@@ -600941,7 +601674,48 @@ function buildMemoryProposals(input) {
|
|
|
600941
601674
|
}
|
|
600942
601675
|
return proposals.slice(0, 6);
|
|
600943
601676
|
}
|
|
600944
|
-
function
|
|
601677
|
+
function corpusPacket(corpus) {
|
|
601678
|
+
return {
|
|
601679
|
+
query: corpus?.query,
|
|
601680
|
+
selectionSeed: corpus?.selectionSeed,
|
|
601681
|
+
stats: corpus?.stats,
|
|
601682
|
+
fallbacks: corpus?.fallbacks ?? [],
|
|
601683
|
+
episodeIds: corpus?.episodeIds ?? [],
|
|
601684
|
+
candidateEpisodeIds: corpus?.candidateEpisodeIds ?? [],
|
|
601685
|
+
selectedEpisodeIds: corpus?.selectedEpisodeIds ?? []
|
|
601686
|
+
};
|
|
601687
|
+
}
|
|
601688
|
+
function selectedSeedPacket(corpus) {
|
|
601689
|
+
const seed = corpus?.graphWalk.seed;
|
|
601690
|
+
if (!seed) return void 0;
|
|
601691
|
+
return {
|
|
601692
|
+
nodeId: seed.node.id,
|
|
601693
|
+
nodeText: seed.node.text,
|
|
601694
|
+
nodeType: seed.node.nodeType,
|
|
601695
|
+
degree: seed.degree,
|
|
601696
|
+
score: seed.score,
|
|
601697
|
+
sourceEpisodeIds: seed.sourceEpisodeIds
|
|
601698
|
+
};
|
|
601699
|
+
}
|
|
601700
|
+
function graphWalkPacket(corpus) {
|
|
601701
|
+
return {
|
|
601702
|
+
visitedNodes: corpus?.graphWalk.visitedNodes.map((node) => ({
|
|
601703
|
+
id: node.id,
|
|
601704
|
+
text: node.text,
|
|
601705
|
+
nodeType: node.nodeType,
|
|
601706
|
+
depth: corpus.graphWalk.depthByNodeId[node.id] ?? 0
|
|
601707
|
+
})) ?? [],
|
|
601708
|
+
traversedEdges: corpus?.graphWalk.traversedEdges.map((edge) => ({
|
|
601709
|
+
id: edge.id,
|
|
601710
|
+
relation: edge.relation,
|
|
601711
|
+
fact: edge.fact,
|
|
601712
|
+
sourceEpisodeId: edge.sourceEpisodeId,
|
|
601713
|
+
confidence: edge.confidence
|
|
601714
|
+
})) ?? [],
|
|
601715
|
+
sourceEpisodeIds: corpus?.graphWalk.sourceEpisodeIds ?? []
|
|
601716
|
+
};
|
|
601717
|
+
}
|
|
601718
|
+
function buildTelegramChannelDaydream(input, corpus, extraction, extractionCommit) {
|
|
600945
601719
|
const firstTs = input.history.map((entry) => entry.ts).find((ts) => typeof ts === "number");
|
|
600946
601720
|
const lastTs = [...input.history].reverse().map((entry) => entry.ts).find((ts) => typeof ts === "number");
|
|
600947
601721
|
const metaAnalysisSignals = buildMetaAnalysisSignals(input);
|
|
@@ -600974,8 +601748,8 @@ function buildTelegramChannelDaydream(input) {
|
|
|
600974
601748
|
].filter((entry) => Boolean(entry));
|
|
600975
601749
|
const seed = `${input.sessionKey}:${input.generatedAtMs}:${input.history.length}`;
|
|
600976
601750
|
return {
|
|
600977
|
-
version:
|
|
600978
|
-
id:
|
|
601751
|
+
version: 3,
|
|
601752
|
+
id: createHash21("sha1").update(seed).digest("hex").slice(0, 16),
|
|
600979
601753
|
sessionKey: input.sessionKey,
|
|
600980
601754
|
chatId: input.chatId,
|
|
600981
601755
|
chatTitle: input.chatTitle,
|
|
@@ -600999,7 +601773,17 @@ function buildTelegramChannelDaydream(input) {
|
|
|
600999
601773
|
memoryProposals,
|
|
601000
601774
|
artifactProposals,
|
|
601001
601775
|
stimulationContext: input.stimulationContext,
|
|
601002
|
-
personaContext: input.personaContext
|
|
601776
|
+
personaContext: input.personaContext,
|
|
601777
|
+
corpus: corpusPacket(corpus),
|
|
601778
|
+
selectedSeed: selectedSeedPacket(corpus),
|
|
601779
|
+
graphWalk: graphWalkPacket(corpus),
|
|
601780
|
+
tagging: extraction?.tags ?? [],
|
|
601781
|
+
summation: extraction?.summaries ?? [],
|
|
601782
|
+
titling: extraction?.titles ?? [],
|
|
601783
|
+
extraction: extraction?.extractions ?? [],
|
|
601784
|
+
linking: extraction?.links ?? [],
|
|
601785
|
+
extractionFollowups: extraction?.followups ?? [],
|
|
601786
|
+
extractionCommit
|
|
601003
601787
|
};
|
|
601004
601788
|
}
|
|
601005
601789
|
function formatTelegramChannelDaydreamMarkdown(artifact) {
|
|
@@ -601010,6 +601794,41 @@ function formatTelegramChannelDaydreamMarkdown(artifact) {
|
|
|
601010
601794
|
`Generated: ${artifact.generatedAt}`,
|
|
601011
601795
|
`Session: ${artifact.sessionKey}`,
|
|
601012
601796
|
`Chat: ${artifact.chatTitle || artifact.chatId} (${artifact.chatType})`,
|
|
601797
|
+
"",
|
|
601798
|
+
"## Reflection Corpus",
|
|
601799
|
+
artifact.corpus.stats ? [
|
|
601800
|
+
`- retained messages: ${artifact.corpus.stats.retainedMessages}`,
|
|
601801
|
+
`- candidate episodes: ${artifact.corpus.stats.candidateEpisodes}`,
|
|
601802
|
+
`- selected episodes: ${artifact.corpus.stats.selectedEpisodes}`,
|
|
601803
|
+
`- vector search limit: ${artifact.corpus.stats.vectorSearchLimitUsed}`,
|
|
601804
|
+
`- graph walk: ${artifact.corpus.stats.graphNodesVisited} node(s), ${artifact.corpus.stats.graphEdgesTraversed} edge(s)`,
|
|
601805
|
+
artifact.corpus.fallbacks.length ? `- fallbacks: ${artifact.corpus.fallbacks.join("; ")}` : "- fallbacks: none"
|
|
601806
|
+
].join("\n") : "- Not available",
|
|
601807
|
+
artifact.selectedSeed ? `
|
|
601808
|
+
Selected seed: ${artifact.selectedSeed.nodeText} (${artifact.selectedSeed.nodeType}, degree ${artifact.selectedSeed.degree})` : "",
|
|
601809
|
+
"",
|
|
601810
|
+
"## Tags",
|
|
601811
|
+
artifact.tagging.length ? artifact.tagging.map((item) => `- ${item.label} [${item.kind}] confidence=${item.confidence.toFixed(2)}${item.sourceMessageIds.length ? ` messages=${item.sourceMessageIds.join(", ")}` : ""}`).join("\n") : "- None",
|
|
601812
|
+
"",
|
|
601813
|
+
"## Summaries",
|
|
601814
|
+
artifact.summation.length ? artifact.summation.map((item) => `- ${item.title} [${item.scope}] confidence=${item.confidence.toFixed(2)}
|
|
601815
|
+
${item.text}${item.sourceMessageIds.length ? `
|
|
601816
|
+
messages=${item.sourceMessageIds.join(", ")}` : ""}`).join("\n") : "- None",
|
|
601817
|
+
"",
|
|
601818
|
+
"## Titles",
|
|
601819
|
+
artifact.titling.length ? artifact.titling.map((item) => `- ${item.title} -> ${item.target} confidence=${item.confidence.toFixed(2)}`).join("\n") : "- None",
|
|
601820
|
+
"",
|
|
601821
|
+
"## Extractions",
|
|
601822
|
+
artifact.extraction.length ? artifact.extraction.map((item) => `- ${item.kind}: ${item.text} confidence=${item.confidence.toFixed(2)}${item.sourceMessageIds.length ? ` messages=${item.sourceMessageIds.join(", ")}` : ""}`).join("\n") : "- None",
|
|
601823
|
+
"",
|
|
601824
|
+
"## Links",
|
|
601825
|
+
artifact.linking.length ? artifact.linking.map((item) => `- ${item.srcNodeText} --${item.relation}--> ${item.dstNodeText} confidence=${item.confidence.toFixed(2)}
|
|
601826
|
+
${item.fact}${item.sourceMessageIds.length ? `
|
|
601827
|
+
messages=${item.sourceMessageIds.join(", ")}` : ""}`).join("\n") : "- None",
|
|
601828
|
+
"",
|
|
601829
|
+
"## Extraction Followups",
|
|
601830
|
+
artifact.extractionFollowups.length ? artifact.extractionFollowups.map((item) => `- ${item.target}${item.replyToMessageId ? ` reply_to=${item.replyToMessageId}` : ""} confidence=${item.confidence.toFixed(2)}
|
|
601831
|
+
${item.text || item.rationale}`).join("\n") : "- None",
|
|
601013
601832
|
"",
|
|
601014
601833
|
section("Meta-Analysis Signals", artifact.metaAnalysisSignals),
|
|
601015
601834
|
"",
|
|
@@ -601099,6 +601918,18 @@ function formatTelegramChannelDaydreamContext(artifact) {
|
|
|
601099
601918
|
"### Telegram Channel Daydream",
|
|
601100
601919
|
"Private idle reflection and stimulation artifact. Use it as context only; do not mention it unless the user asks about internal memory.",
|
|
601101
601920
|
`Generated: ${artifact.generatedAt}`,
|
|
601921
|
+
artifact.corpus?.stats ? `Corpus: ${artifact.corpus.stats.selectedEpisodes} selected episode(s), ${artifact.corpus.stats.graphNodesVisited} graph node(s), search limit ${artifact.corpus.stats.vectorSearchLimitUsed}` : "",
|
|
601922
|
+
artifact.selectedSeed ? `Selected seed: ${artifact.selectedSeed.nodeText} (degree ${artifact.selectedSeed.degree})` : "",
|
|
601923
|
+
artifact.tagging?.length ? `Tags:
|
|
601924
|
+
${artifact.tagging.slice(0, 8).map((item) => `- ${item.label} [${item.kind}] (${item.confidence.toFixed(2)})`).join("\n")}` : "",
|
|
601925
|
+
artifact.summation?.length ? `Summaries:
|
|
601926
|
+
${artifact.summation.slice(0, 4).map((item) => `- ${item.title}: ${item.text}`).join("\n")}` : "",
|
|
601927
|
+
artifact.extraction?.length ? `Extracted items:
|
|
601928
|
+
${artifact.extraction.slice(0, 6).map((item) => `- ${item.kind}: ${item.text}${item.sourceMessageIds.length ? ` (messages ${item.sourceMessageIds.join(", ")})` : ""}`).join("\n")}` : "",
|
|
601929
|
+
artifact.linking?.length ? `Graph links:
|
|
601930
|
+
${artifact.linking.slice(0, 5).map((item) => `- ${item.srcNodeText} --${item.relation}--> ${item.dstNodeText}`).join("\n")}` : "",
|
|
601931
|
+
artifact.extractionFollowups?.length ? `Extraction followups:
|
|
601932
|
+
${artifact.extractionFollowups.slice(0, 4).map((item) => `- ${item.target}${item.replyToMessageId ? ` reply_to=${item.replyToMessageId}` : ""}: ${item.text || item.rationale}`).join("\n")}` : "",
|
|
601102
601933
|
artifact.metaAnalysisSignals?.length ? `Meta-analysis signals:
|
|
601103
601934
|
${artifact.metaAnalysisSignals.slice(0, 4).map((line) => `- ${line}`).join("\n")}` : "",
|
|
601104
601935
|
artifact.humanStimulationSignals?.length ? `Human stimulation signals:
|
|
@@ -601128,6 +601959,715 @@ var init_telegram_channel_dmn = __esm({
|
|
|
601128
601959
|
}
|
|
601129
601960
|
});
|
|
601130
601961
|
|
|
601962
|
+
// packages/cli/src/tui/telegram-reflection-corpus.ts
|
|
601963
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
601964
|
+
function telegramReflectionMemoryDbPaths(repoRoot) {
|
|
601965
|
+
return omniusMemoryDbPaths(repoRoot);
|
|
601966
|
+
}
|
|
601967
|
+
function stableHash2(value2, length4 = 16) {
|
|
601968
|
+
return createHash22("sha1").update(value2).digest("hex").slice(0, length4);
|
|
601969
|
+
}
|
|
601970
|
+
function clean3(value2) {
|
|
601971
|
+
return String(value2 ?? "").replace(/\s+/g, " ").trim();
|
|
601972
|
+
}
|
|
601973
|
+
function compact(value2, max = 420) {
|
|
601974
|
+
const text = clean3(value2);
|
|
601975
|
+
return text.length > max ? `${text.slice(0, Math.max(0, max - 3)).trimEnd()}...` : text;
|
|
601976
|
+
}
|
|
601977
|
+
function senderLabel(entry) {
|
|
601978
|
+
if (entry.role === "assistant") return entry.speaker || "Assistant";
|
|
601979
|
+
if (entry.speaker) return entry.speaker;
|
|
601980
|
+
if (entry.username) return `@${entry.username}`;
|
|
601981
|
+
if (entry.firstName) return entry.firstName;
|
|
601982
|
+
if (entry.fromUserId) return `user:${entry.fromUserId}`;
|
|
601983
|
+
return "Telegram user";
|
|
601984
|
+
}
|
|
601985
|
+
function senderKey2(entry) {
|
|
601986
|
+
if (entry.role === "assistant") return entry.username || entry.speaker || "assistant";
|
|
601987
|
+
return String(entry.fromUserId || entry.username || entry.firstName || senderLabel(entry));
|
|
601988
|
+
}
|
|
601989
|
+
function scopeFor(entry, options2) {
|
|
601990
|
+
const chatType = entry.chatType || options2.chatType || "unknown";
|
|
601991
|
+
return {
|
|
601992
|
+
kind: `telegram-${chatType}`,
|
|
601993
|
+
id: String(entry.chatId ?? options2.chatId),
|
|
601994
|
+
title: entry.chatTitle || options2.chatTitle
|
|
601995
|
+
};
|
|
601996
|
+
}
|
|
601997
|
+
function senderFor(entry) {
|
|
601998
|
+
return {
|
|
601999
|
+
id: senderKey2(entry),
|
|
602000
|
+
username: entry.username,
|
|
602001
|
+
displayName: senderLabel(entry),
|
|
602002
|
+
isBot: entry.role === "assistant"
|
|
602003
|
+
};
|
|
602004
|
+
}
|
|
602005
|
+
function messageIdFor(entry, sessionKey) {
|
|
602006
|
+
if (typeof entry.messageId === "number" && Number.isFinite(entry.messageId)) return entry.messageId;
|
|
602007
|
+
return stableHash2(`${sessionKey}:${entry.role}:${entry.ts ?? ""}:${senderLabel(entry)}:${entry.text}`);
|
|
602008
|
+
}
|
|
602009
|
+
function messageRefFor(entry, sessionKey) {
|
|
602010
|
+
return {
|
|
602011
|
+
id: messageIdFor(entry, sessionKey),
|
|
602012
|
+
threadId: entry.messageThreadId,
|
|
602013
|
+
timestamp: entry.ts,
|
|
602014
|
+
text: entry.text
|
|
602015
|
+
};
|
|
602016
|
+
}
|
|
602017
|
+
function replyRefFor(entry) {
|
|
602018
|
+
const reply = entry.replyContext;
|
|
602019
|
+
const replyId = reply?.messageId ?? entry.replyToMessageId;
|
|
602020
|
+
if (replyId == null) return void 0;
|
|
602021
|
+
return {
|
|
602022
|
+
id: replyId,
|
|
602023
|
+
threadId: reply?.threadId,
|
|
602024
|
+
text: reply?.text || reply?.caption || reply?.mediaSummary,
|
|
602025
|
+
sender: reply?.sender ? {
|
|
602026
|
+
id: reply.sender.id == null ? void 0 : String(reply.sender.id),
|
|
602027
|
+
username: reply.sender.username,
|
|
602028
|
+
displayName: reply.sender.title || reply.sender.firstName || reply.sender.username,
|
|
602029
|
+
isBot: reply.sender.isBot
|
|
602030
|
+
} : void 0
|
|
602031
|
+
};
|
|
602032
|
+
}
|
|
602033
|
+
function contentFor(entry, sessionKey, options2) {
|
|
602034
|
+
const lines = [
|
|
602035
|
+
`Telegram ${entry.chatType || options2.chatType || "unknown"} ${entry.role} message`,
|
|
602036
|
+
`session: ${sessionKey}`,
|
|
602037
|
+
`chat: ${entry.chatTitle || options2.chatTitle || entry.chatId || options2.chatId}`,
|
|
602038
|
+
`message_id: ${messageIdFor(entry, sessionKey)}`,
|
|
602039
|
+
entry.messageThreadId != null ? `thread_id: ${entry.messageThreadId}` : "",
|
|
602040
|
+
entry.replyToMessageId != null ? `reply_to_message_id: ${entry.replyToMessageId}` : "",
|
|
602041
|
+
`speaker: ${senderLabel(entry)}`,
|
|
602042
|
+
entry.mode ? `mode: ${entry.mode}` : "",
|
|
602043
|
+
entry.mediaSummary ? `media: ${compact(entry.mediaSummary, 260)}` : "",
|
|
602044
|
+
"",
|
|
602045
|
+
entry.text
|
|
602046
|
+
].filter((line) => line !== "");
|
|
602047
|
+
return lines.join("\n");
|
|
602048
|
+
}
|
|
602049
|
+
function metadataFor(entry, sessionKey, options2) {
|
|
602050
|
+
return {
|
|
602051
|
+
sourceSurface: "telegram",
|
|
602052
|
+
sessionKey,
|
|
602053
|
+
telegram: {
|
|
602054
|
+
role: entry.role,
|
|
602055
|
+
mode: entry.mode,
|
|
602056
|
+
chatId: String(entry.chatId ?? options2.chatId),
|
|
602057
|
+
chatType: entry.chatType || options2.chatType,
|
|
602058
|
+
chatTitle: entry.chatTitle || options2.chatTitle,
|
|
602059
|
+
messageId: entry.messageId,
|
|
602060
|
+
messageThreadId: entry.messageThreadId,
|
|
602061
|
+
replyToMessageId: entry.replyToMessageId,
|
|
602062
|
+
username: entry.username,
|
|
602063
|
+
firstName: entry.firstName,
|
|
602064
|
+
fromUserId: entry.fromUserId,
|
|
602065
|
+
speaker: senderLabel(entry),
|
|
602066
|
+
mediaSummary: entry.mediaSummary
|
|
602067
|
+
}
|
|
602068
|
+
};
|
|
602069
|
+
}
|
|
602070
|
+
function graphTopicNode(graph, label) {
|
|
602071
|
+
return graph.upsertNode({ text: `topic:${label}`, nodeType: "concept" });
|
|
602072
|
+
}
|
|
602073
|
+
function addTextEdges(graph, result, entry) {
|
|
602074
|
+
const messageId = result.nodeIds.message;
|
|
602075
|
+
const senderId = result.nodeIds.sender;
|
|
602076
|
+
if (messageId && senderId) {
|
|
602077
|
+
graph.addEdge({
|
|
602078
|
+
srcId: messageId,
|
|
602079
|
+
dstId: senderId,
|
|
602080
|
+
relation: "said_by",
|
|
602081
|
+
fact: compact(entry.text, 260),
|
|
602082
|
+
sourceEpisodeId: result.episodeId,
|
|
602083
|
+
modality: entry.role === "user" ? "social" : "text",
|
|
602084
|
+
confidence: entry.role === "assistant" ? 0.92 : 0.96
|
|
602085
|
+
});
|
|
602086
|
+
}
|
|
602087
|
+
if (messageId) {
|
|
602088
|
+
const channelTopic = graphTopicNode(graph, "telegram-reflection-corpus");
|
|
602089
|
+
graph.addEdge({
|
|
602090
|
+
srcId: messageId,
|
|
602091
|
+
dstId: channelTopic,
|
|
602092
|
+
relation: "related_to",
|
|
602093
|
+
fact: compact(entry.text || entry.mediaSummary || "telegram message", 220),
|
|
602094
|
+
sourceEpisodeId: result.episodeId,
|
|
602095
|
+
modality: entry.role === "user" ? "social" : "text",
|
|
602096
|
+
confidence: 0.72
|
|
602097
|
+
});
|
|
602098
|
+
}
|
|
602099
|
+
}
|
|
602100
|
+
function upsertTelegramReflectionMessage(repoRoot, sessionKey, entry, options2) {
|
|
602101
|
+
const paths = telegramReflectionMemoryDbPaths(repoRoot);
|
|
602102
|
+
const graph = new TemporalGraph(paths.knowledge);
|
|
602103
|
+
const store2 = new EpisodeStore(paths.episodes, graph);
|
|
602104
|
+
try {
|
|
602105
|
+
const before = store2.count(sessionKey);
|
|
602106
|
+
const service = new MultimodalIdentityService({ episodeStore: store2, graph });
|
|
602107
|
+
const content = contentFor(entry, sessionKey, options2);
|
|
602108
|
+
const result = service.ingest({
|
|
602109
|
+
sourceSurface: "telegram",
|
|
602110
|
+
sessionId: sessionKey,
|
|
602111
|
+
metadata: metadataFor(entry, sessionKey, options2),
|
|
602112
|
+
scope: scopeFor(entry, options2),
|
|
602113
|
+
sender: senderFor(entry),
|
|
602114
|
+
message: messageRefFor(entry, sessionKey),
|
|
602115
|
+
replyTo: replyRefFor(entry),
|
|
602116
|
+
modality: entry.role === "user" ? "social" : "text",
|
|
602117
|
+
content,
|
|
602118
|
+
labels: [entry.mode, entry.mediaSummary, senderLabel(entry)].filter((value2) => Boolean(value2))
|
|
602119
|
+
});
|
|
602120
|
+
addTextEdges(graph, result, entry);
|
|
602121
|
+
const after = store2.count(sessionKey);
|
|
602122
|
+
return { episodeId: result.episodeId, reused: after === before };
|
|
602123
|
+
} finally {
|
|
602124
|
+
store2.close();
|
|
602125
|
+
graph.close();
|
|
602126
|
+
}
|
|
602127
|
+
}
|
|
602128
|
+
function queryFor(options2) {
|
|
602129
|
+
if (options2.query?.trim()) return options2.query.trim();
|
|
602130
|
+
const recent = options2.history.slice(-12).map((entry) => compact(`${senderLabel(entry)}: ${entry.text || entry.mediaSummary || ""}`, 180));
|
|
602131
|
+
return [
|
|
602132
|
+
`Telegram ${options2.chatType} ${options2.chatTitle || options2.chatId} reflection`,
|
|
602133
|
+
...recent
|
|
602134
|
+
].filter(Boolean).join("\n");
|
|
602135
|
+
}
|
|
602136
|
+
async function fillMissingEmbeddings(store2, graph, episodes, embeddingConfig) {
|
|
602137
|
+
if (embeddingConfig === false) return { embedded: 0, unavailable: true, queryEmbedding: null };
|
|
602138
|
+
const missing = episodes.filter((episode) => !episode.embedding && episode.content.trim());
|
|
602139
|
+
if (missing.length === 0) return { embedded: 0, unavailable: false, queryEmbedding: null };
|
|
602140
|
+
const results = await generateEmbeddingBatch(missing.map((episode) => episode.content.slice(0, 4e3)), embeddingConfig);
|
|
602141
|
+
let embedded = 0;
|
|
602142
|
+
for (let i2 = 0; i2 < missing.length; i2++) {
|
|
602143
|
+
const result = results[i2];
|
|
602144
|
+
const episode = missing[i2];
|
|
602145
|
+
if (!result || !episode) continue;
|
|
602146
|
+
store2.setEmbedding(episode.id, result.vector);
|
|
602147
|
+
const refreshed = store2.get(episode.id);
|
|
602148
|
+
if (refreshed) linkEpisode(refreshed, store2, graph);
|
|
602149
|
+
embedded++;
|
|
602150
|
+
}
|
|
602151
|
+
return { embedded, unavailable: embedded === 0 && missing.length > 0, queryEmbedding: null };
|
|
602152
|
+
}
|
|
602153
|
+
async function queryEmbeddingFor(query, embeddingConfig) {
|
|
602154
|
+
if (embeddingConfig === false) return null;
|
|
602155
|
+
const result = await generateEmbedding(query.slice(0, 4e3), embeddingConfig);
|
|
602156
|
+
return result?.vector ?? null;
|
|
602157
|
+
}
|
|
602158
|
+
async function buildTelegramReflectionCorpus(options2) {
|
|
602159
|
+
const paths = telegramReflectionMemoryDbPaths(options2.repoRoot);
|
|
602160
|
+
const graph = new TemporalGraph(paths.knowledge);
|
|
602161
|
+
const store2 = new EpisodeStore(paths.episodes, graph);
|
|
602162
|
+
const episodeIds = [];
|
|
602163
|
+
let reusedEpisodes = 0;
|
|
602164
|
+
const fallbacks = [];
|
|
602165
|
+
try {
|
|
602166
|
+
const service = new MultimodalIdentityService({ episodeStore: store2, graph });
|
|
602167
|
+
for (const entry of options2.history) {
|
|
602168
|
+
const before = store2.count(options2.sessionKey);
|
|
602169
|
+
const content = contentFor(entry, options2.sessionKey, options2);
|
|
602170
|
+
const result = service.ingest({
|
|
602171
|
+
sourceSurface: "telegram",
|
|
602172
|
+
sessionId: options2.sessionKey,
|
|
602173
|
+
metadata: metadataFor(entry, options2.sessionKey, options2),
|
|
602174
|
+
scope: scopeFor(entry, options2),
|
|
602175
|
+
sender: senderFor(entry),
|
|
602176
|
+
message: messageRefFor(entry, options2.sessionKey),
|
|
602177
|
+
replyTo: replyRefFor(entry),
|
|
602178
|
+
modality: entry.role === "user" ? "social" : "text",
|
|
602179
|
+
content,
|
|
602180
|
+
labels: [entry.mode, entry.mediaSummary, senderLabel(entry)].filter((value2) => Boolean(value2))
|
|
602181
|
+
});
|
|
602182
|
+
addTextEdges(graph, result, entry);
|
|
602183
|
+
const after = store2.count(options2.sessionKey);
|
|
602184
|
+
if (after === before) reusedEpisodes++;
|
|
602185
|
+
if (result.episodeId) episodeIds.push(result.episodeId);
|
|
602186
|
+
}
|
|
602187
|
+
const scopedEpisodes = store2.recent(500, options2.sessionKey).filter((episode) => {
|
|
602188
|
+
const meta = episode.metadata;
|
|
602189
|
+
return meta?.sourceSurface === "telegram" || meta?.telegram && typeof meta.telegram === "object";
|
|
602190
|
+
});
|
|
602191
|
+
const embeddingFill = await fillMissingEmbeddings(store2, graph, scopedEpisodes, options2.embeddingConfig);
|
|
602192
|
+
const query = queryFor(options2);
|
|
602193
|
+
const queryEmbedding = await queryEmbeddingFor(query, options2.embeddingConfig);
|
|
602194
|
+
if (embeddingFill.unavailable || !queryEmbedding) fallbacks.push("embedding unavailable or incomplete; lexical scoped search included");
|
|
602195
|
+
let graphWalk = null;
|
|
602196
|
+
let selectedEpisodes = [];
|
|
602197
|
+
let vectorSearchLimitUsed = 0;
|
|
602198
|
+
let candidateEpisodes = [];
|
|
602199
|
+
const limits = options2.candidateLimits ?? [48, 96, 192, 384, 500];
|
|
602200
|
+
for (const limit of limits) {
|
|
602201
|
+
vectorSearchLimitUsed = limit;
|
|
602202
|
+
candidateEpisodes = store2.search(
|
|
602203
|
+
{
|
|
602204
|
+
sessionId: options2.sessionKey,
|
|
602205
|
+
query,
|
|
602206
|
+
limit,
|
|
602207
|
+
metadataFilter: { sourceSurface: "telegram" }
|
|
602208
|
+
},
|
|
602209
|
+
{
|
|
602210
|
+
queryEmbedding,
|
|
602211
|
+
lexicalWeight: 1,
|
|
602212
|
+
embeddingWeight: queryEmbedding ? 1.8 : 0
|
|
602213
|
+
}
|
|
602214
|
+
);
|
|
602215
|
+
graphWalk = selectAndWalkGraphCandidate(
|
|
602216
|
+
graph,
|
|
602217
|
+
candidateEpisodes.map((episode, index) => ({ episode, score: limit - index })),
|
|
602218
|
+
{
|
|
602219
|
+
seed: `${options2.sessionKey}:${options2.generatedAtMs}:${limit}`,
|
|
602220
|
+
maxDepth: 2,
|
|
602221
|
+
maxVisitedNodes: 72,
|
|
602222
|
+
maxTraversedEdges: 180,
|
|
602223
|
+
maxSourceEpisodes: 100
|
|
602224
|
+
}
|
|
602225
|
+
);
|
|
602226
|
+
if (graphWalk.seed) {
|
|
602227
|
+
selectedEpisodes = graphWalk.sourceEpisodeIds.map((id) => store2.get(id)).filter((episode) => Boolean(episode));
|
|
602228
|
+
if (selectedEpisodes.length < (options2.minWalkEpisodes ?? 8)) {
|
|
602229
|
+
const deeper = selectAndWalkGraphCandidate(
|
|
602230
|
+
graph,
|
|
602231
|
+
candidateEpisodes.map((episode, index) => ({ episode, score: limit - index })),
|
|
602232
|
+
{
|
|
602233
|
+
seed: `${options2.sessionKey}:${options2.generatedAtMs}:${limit}:deep`,
|
|
602234
|
+
maxDepth: 3,
|
|
602235
|
+
maxVisitedNodes: 96,
|
|
602236
|
+
maxTraversedEdges: 240,
|
|
602237
|
+
maxSourceEpisodes: 120
|
|
602238
|
+
}
|
|
602239
|
+
);
|
|
602240
|
+
if (deeper.seed && deeper.sourceEpisodeIds.length >= graphWalk.sourceEpisodeIds.length) graphWalk = deeper;
|
|
602241
|
+
}
|
|
602242
|
+
selectedEpisodes = graphWalk.sourceEpisodeIds.map((id) => store2.get(id)).filter((episode) => Boolean(episode));
|
|
602243
|
+
break;
|
|
602244
|
+
}
|
|
602245
|
+
}
|
|
602246
|
+
if (!graphWalk) {
|
|
602247
|
+
graphWalk = selectAndWalkGraphCandidate(graph, [], { seed: `${options2.sessionKey}:${options2.generatedAtMs}:empty` });
|
|
602248
|
+
}
|
|
602249
|
+
if (!graphWalk.seed && graphWalk.fallbackReason) fallbacks.push(graphWalk.fallbackReason);
|
|
602250
|
+
if (selectedEpisodes.length === 0) {
|
|
602251
|
+
selectedEpisodes = candidateEpisodes.slice(0, Math.min(24, candidateEpisodes.length));
|
|
602252
|
+
if (selectedEpisodes.length > 0) fallbacks.push("selected recent scoped episodes because graph walk produced no source episode anchors");
|
|
602253
|
+
}
|
|
602254
|
+
return {
|
|
602255
|
+
stats: {
|
|
602256
|
+
retainedMessages: options2.history.length,
|
|
602257
|
+
upsertedEpisodes: episodeIds.length,
|
|
602258
|
+
reusedEpisodes,
|
|
602259
|
+
embeddedEpisodes: embeddingFill.embedded,
|
|
602260
|
+
candidateEpisodes: candidateEpisodes.length,
|
|
602261
|
+
selectedEpisodes: selectedEpisodes.length,
|
|
602262
|
+
graphNodesVisited: graphWalk.visitedNodes.length,
|
|
602263
|
+
graphEdgesTraversed: graphWalk.traversedEdges.length,
|
|
602264
|
+
vectorSearchLimitUsed,
|
|
602265
|
+
embeddingUnavailable: embeddingFill.unavailable || !queryEmbedding
|
|
602266
|
+
},
|
|
602267
|
+
episodeIds: [...new Set(episodeIds)],
|
|
602268
|
+
candidateEpisodeIds: candidateEpisodes.map((episode) => episode.id),
|
|
602269
|
+
selectedEpisodeIds: selectedEpisodes.map((episode) => episode.id),
|
|
602270
|
+
selectedEpisodes,
|
|
602271
|
+
graphWalk,
|
|
602272
|
+
selectionSeed: `${options2.sessionKey}:${options2.generatedAtMs}:${vectorSearchLimitUsed}`,
|
|
602273
|
+
query,
|
|
602274
|
+
fallbacks
|
|
602275
|
+
};
|
|
602276
|
+
} finally {
|
|
602277
|
+
store2.close();
|
|
602278
|
+
graph.close();
|
|
602279
|
+
}
|
|
602280
|
+
}
|
|
602281
|
+
var init_telegram_reflection_corpus = __esm({
|
|
602282
|
+
"packages/cli/src/tui/telegram-reflection-corpus.ts"() {
|
|
602283
|
+
"use strict";
|
|
602284
|
+
init_dist7();
|
|
602285
|
+
init_memory_paths();
|
|
602286
|
+
}
|
|
602287
|
+
});
|
|
602288
|
+
|
|
602289
|
+
// packages/cli/src/tui/telegram-reflection-extraction.ts
|
|
602290
|
+
function clean4(value2, max = 2e3) {
|
|
602291
|
+
const text = String(value2 ?? "").replace(/\s+/g, " ").trim();
|
|
602292
|
+
return text.length > max ? `${text.slice(0, Math.max(0, max - 3)).trimEnd()}...` : text;
|
|
602293
|
+
}
|
|
602294
|
+
function clampConfidence(value2, fallback = 0.5) {
|
|
602295
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return fallback;
|
|
602296
|
+
return Math.max(0, Math.min(1, value2));
|
|
602297
|
+
}
|
|
602298
|
+
function numberArray(value2) {
|
|
602299
|
+
if (!Array.isArray(value2)) return [];
|
|
602300
|
+
return [...new Set(value2.map((item) => Number(item)).filter((item) => Number.isFinite(item)).map((item) => Math.trunc(item)))];
|
|
602301
|
+
}
|
|
602302
|
+
function stringArray(value2) {
|
|
602303
|
+
if (!Array.isArray(value2)) return [];
|
|
602304
|
+
return [...new Set(value2.map((item) => clean4(item, 180)).filter(Boolean))];
|
|
602305
|
+
}
|
|
602306
|
+
function episodeLine(episode) {
|
|
602307
|
+
const meta = episode.metadata;
|
|
602308
|
+
const telegram = meta?.telegram;
|
|
602309
|
+
const speaker = clean4(telegram?.speaker || telegram?.username || "unknown", 80);
|
|
602310
|
+
const messageId = telegram?.messageId == null ? "unknown" : String(telegram.messageId);
|
|
602311
|
+
const replyTo = telegram?.replyToMessageId == null ? "" : ` reply_to=${telegram.replyToMessageId}`;
|
|
602312
|
+
return [
|
|
602313
|
+
`episode_id=${episode.id}`,
|
|
602314
|
+
`message_id=${messageId}${replyTo}`,
|
|
602315
|
+
`speaker=${speaker}`,
|
|
602316
|
+
`modality=${episode.modality}`,
|
|
602317
|
+
`content=${clean4(episode.content, 700)}`
|
|
602318
|
+
].join(" | ");
|
|
602319
|
+
}
|
|
602320
|
+
function buildTelegramReflectionExtractionPrompt(options2) {
|
|
602321
|
+
const corpus = options2.corpus;
|
|
602322
|
+
const walkNodes = corpus.graphWalk.visitedNodes.slice(0, 40).map((node) => `node_id=${node.id} type=${node.nodeType} mentions=${node.mentionCount} text=${clean4(node.text, 220)}`).join("\n");
|
|
602323
|
+
const walkEdges = corpus.graphWalk.traversedEdges.slice(0, 60).map((edge) => `edge_id=${edge.id} relation=${edge.relation} confidence=${edge.confidence.toFixed(2)} src=${edge.srcId} dst=${edge.dstId} source_episode=${edge.sourceEpisodeId || "none"} fact=${clean4(edge.fact, 220)}`).join("\n");
|
|
602324
|
+
const episodes = corpus.selectedEpisodes.slice(0, 36).map(episodeLine).join("\n");
|
|
602325
|
+
return [
|
|
602326
|
+
"You are extracting a reusable Telegram reflection artifact from a scoped chat corpus.",
|
|
602327
|
+
"Return strict JSON only. Do not include Markdown, prose, or comments.",
|
|
602328
|
+
"",
|
|
602329
|
+
"Required top-level JSON keys:",
|
|
602330
|
+
"artifact_title, tags, summaries, titles, extractions, links, followups",
|
|
602331
|
+
"",
|
|
602332
|
+
"Rules:",
|
|
602333
|
+
"- Use only the scoped Telegram corpus, graph nodes, graph edges, and source anchors below.",
|
|
602334
|
+
"- Preserve message_id and episode_id anchors on every item when possible.",
|
|
602335
|
+
"- Do not infer identity from a face, voice, or name unless the corpus explicitly says it.",
|
|
602336
|
+
"- Private DM followups may be proposed but must not be framed as already sent.",
|
|
602337
|
+
"- same_group followups must be concise, low-intrusion, and anchored to a source message id.",
|
|
602338
|
+
"- If a category has no evidence, return an empty array for that category.",
|
|
602339
|
+
"",
|
|
602340
|
+
"Schema:",
|
|
602341
|
+
JSON.stringify({
|
|
602342
|
+
artifact_title: "short title",
|
|
602343
|
+
tags: [{ label: "tag", kind: "topic|person|preference|task|media|tone", confidence: 0, source_message_ids: [1], target_episode_ids: ["episode-id"], target_node_ids: ["node-id"] }],
|
|
602344
|
+
summaries: [{ title: "summary title", scope: "channel|thread|participant|message_window", text: "summary text", confidence: 0, source_message_ids: [1], target_episode_ids: ["episode-id"] }],
|
|
602345
|
+
titles: [{ title: "usable title", target: "artifact|thread|memory_card|graph_node", confidence: 0, source_message_ids: [1], target_episode_ids: ["episode-id"] }],
|
|
602346
|
+
extractions: [{ kind: "fact|preference|open_question|decision|identity_candidate|media_reference|followup_need", text: "extracted item", confidence: 0, source_message_ids: [1], target_episode_ids: ["episode-id"], target_node_ids: ["node-id"] }],
|
|
602347
|
+
links: [{ relation: "related_to|contains|authored_by|replied_to|said_by|depicts|named_as|same_person_candidate", src_node_text: "node text", dst_node_text: "node text", confidence: 0, fact: "why linked", source_message_ids: [1], target_episode_ids: ["episode-id"] }],
|
|
602348
|
+
followups: [{ target: "same_group|private_dm|none", text: "candidate visible reply", reply_to_message_id: 1, rationale: "why", confidence: 0 }]
|
|
602349
|
+
}),
|
|
602350
|
+
"",
|
|
602351
|
+
`Chat: ${options2.chatTitle || options2.chatId} (${options2.chatType})`,
|
|
602352
|
+
`Session: ${options2.sessionKey}`,
|
|
602353
|
+
`Corpus query: ${clean4(corpus.query, 1e3)}`,
|
|
602354
|
+
`Corpus stats: ${JSON.stringify(corpus.stats)}`,
|
|
602355
|
+
`Selected seed: ${corpus.graphWalk.seed ? `${corpus.graphWalk.seed.node.text} degree=${corpus.graphWalk.seed.degree}` : "none"}`,
|
|
602356
|
+
corpus.fallbacks.length ? `Fallbacks: ${corpus.fallbacks.join("; ")}` : "Fallbacks: none",
|
|
602357
|
+
"",
|
|
602358
|
+
"Graph nodes:",
|
|
602359
|
+
walkNodes || "none",
|
|
602360
|
+
"",
|
|
602361
|
+
"Graph edges:",
|
|
602362
|
+
walkEdges || "none",
|
|
602363
|
+
"",
|
|
602364
|
+
"Source episodes:",
|
|
602365
|
+
episodes || "none"
|
|
602366
|
+
].join("\n");
|
|
602367
|
+
}
|
|
602368
|
+
function parseJsonObject(raw) {
|
|
602369
|
+
const text = raw.trim();
|
|
602370
|
+
if (!text) return null;
|
|
602371
|
+
const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1]?.trim();
|
|
602372
|
+
const candidate = fenced || text.slice(text.indexOf("{"), text.lastIndexOf("}") + 1);
|
|
602373
|
+
if (!candidate || !candidate.startsWith("{")) return null;
|
|
602374
|
+
try {
|
|
602375
|
+
const parsed = JSON.parse(candidate);
|
|
602376
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
602377
|
+
} catch {
|
|
602378
|
+
return null;
|
|
602379
|
+
}
|
|
602380
|
+
}
|
|
602381
|
+
function parseTelegramReflectionExtraction(raw) {
|
|
602382
|
+
const parsed = parseJsonObject(raw);
|
|
602383
|
+
if (!parsed) return null;
|
|
602384
|
+
const tags = Array.isArray(parsed.tags) ? parsed.tags.map((item) => {
|
|
602385
|
+
const obj = item;
|
|
602386
|
+
return {
|
|
602387
|
+
label: clean4(obj.label, 80),
|
|
602388
|
+
kind: clean4(obj.kind, 40) || "topic",
|
|
602389
|
+
confidence: clampConfidence(obj.confidence),
|
|
602390
|
+
sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
|
|
602391
|
+
targetEpisodeIds: stringArray(obj.target_episode_ids ?? obj.targetEpisodeIds),
|
|
602392
|
+
targetNodeIds: stringArray(obj.target_node_ids ?? obj.targetNodeIds)
|
|
602393
|
+
};
|
|
602394
|
+
}).filter((item) => item.label) : [];
|
|
602395
|
+
const summaries = Array.isArray(parsed.summaries) ? parsed.summaries.map((item) => {
|
|
602396
|
+
const obj = item;
|
|
602397
|
+
return {
|
|
602398
|
+
title: clean4(obj.title, 120),
|
|
602399
|
+
scope: clean4(obj.scope, 60) || "message_window",
|
|
602400
|
+
text: clean4(obj.text, 1200),
|
|
602401
|
+
confidence: clampConfidence(obj.confidence),
|
|
602402
|
+
sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
|
|
602403
|
+
targetEpisodeIds: stringArray(obj.target_episode_ids ?? obj.targetEpisodeIds)
|
|
602404
|
+
};
|
|
602405
|
+
}).filter((item) => item.title && item.text) : [];
|
|
602406
|
+
const titles = Array.isArray(parsed.titles) ? parsed.titles.map((item) => {
|
|
602407
|
+
const obj = item;
|
|
602408
|
+
return {
|
|
602409
|
+
title: clean4(obj.title, 120),
|
|
602410
|
+
target: clean4(obj.target, 60) || "artifact",
|
|
602411
|
+
confidence: clampConfidence(obj.confidence),
|
|
602412
|
+
sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
|
|
602413
|
+
targetEpisodeIds: stringArray(obj.target_episode_ids ?? obj.targetEpisodeIds)
|
|
602414
|
+
};
|
|
602415
|
+
}).filter((item) => item.title) : [];
|
|
602416
|
+
const extractions = Array.isArray(parsed.extractions) ? parsed.extractions.map((item) => {
|
|
602417
|
+
const obj = item;
|
|
602418
|
+
return {
|
|
602419
|
+
kind: clean4(obj.kind, 60) || "fact",
|
|
602420
|
+
text: clean4(obj.text, 1e3),
|
|
602421
|
+
confidence: clampConfidence(obj.confidence),
|
|
602422
|
+
sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
|
|
602423
|
+
targetEpisodeIds: stringArray(obj.target_episode_ids ?? obj.targetEpisodeIds),
|
|
602424
|
+
targetNodeIds: stringArray(obj.target_node_ids ?? obj.targetNodeIds)
|
|
602425
|
+
};
|
|
602426
|
+
}).filter((item) => item.text) : [];
|
|
602427
|
+
const links2 = Array.isArray(parsed.links) ? parsed.links.map((item) => {
|
|
602428
|
+
const obj = item;
|
|
602429
|
+
return {
|
|
602430
|
+
relation: clean4(obj.relation, 60) || "related_to",
|
|
602431
|
+
srcNodeText: clean4(obj.src_node_text ?? obj.srcNodeText, 180),
|
|
602432
|
+
dstNodeText: clean4(obj.dst_node_text ?? obj.dstNodeText, 180),
|
|
602433
|
+
confidence: clampConfidence(obj.confidence),
|
|
602434
|
+
fact: clean4(obj.fact, 500),
|
|
602435
|
+
sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
|
|
602436
|
+
targetEpisodeIds: stringArray(obj.target_episode_ids ?? obj.targetEpisodeIds)
|
|
602437
|
+
};
|
|
602438
|
+
}).filter((item) => item.srcNodeText && item.dstNodeText) : [];
|
|
602439
|
+
const followups = Array.isArray(parsed.followups) ? parsed.followups.map((item) => {
|
|
602440
|
+
const obj = item;
|
|
602441
|
+
const target = clean4(obj.target, 40);
|
|
602442
|
+
const replyTo = Number(obj.reply_to_message_id ?? obj.replyToMessageId);
|
|
602443
|
+
const normalizedTarget = target === "private_dm" ? "private_dm" : target === "same_group" ? "same_group" : "none";
|
|
602444
|
+
return {
|
|
602445
|
+
target: normalizedTarget,
|
|
602446
|
+
text: clean4(obj.text, 700),
|
|
602447
|
+
replyToMessageId: Number.isFinite(replyTo) ? Math.trunc(replyTo) : null,
|
|
602448
|
+
rationale: clean4(obj.rationale, 400),
|
|
602449
|
+
confidence: clampConfidence(obj.confidence)
|
|
602450
|
+
};
|
|
602451
|
+
}) : [];
|
|
602452
|
+
return {
|
|
602453
|
+
artifactTitle: clean4(parsed.artifact_title ?? parsed.artifactTitle, 140) || "Telegram reflection",
|
|
602454
|
+
tags,
|
|
602455
|
+
summaries,
|
|
602456
|
+
titles,
|
|
602457
|
+
extractions,
|
|
602458
|
+
links: links2,
|
|
602459
|
+
followups,
|
|
602460
|
+
raw
|
|
602461
|
+
};
|
|
602462
|
+
}
|
|
602463
|
+
async function runTelegramReflectionExtraction(options2) {
|
|
602464
|
+
const prompt = buildTelegramReflectionExtractionPrompt(options2);
|
|
602465
|
+
const result = await options2.backend.chatCompletion({
|
|
602466
|
+
messages: [
|
|
602467
|
+
{ role: "system", content: "You produce strict JSON for Telegram reflection memory extraction." },
|
|
602468
|
+
{ role: "user", content: prompt }
|
|
602469
|
+
],
|
|
602470
|
+
tools: [],
|
|
602471
|
+
temperature: 0.2,
|
|
602472
|
+
maxTokens: 1800,
|
|
602473
|
+
timeoutMs: options2.timeoutMs,
|
|
602474
|
+
think: false
|
|
602475
|
+
});
|
|
602476
|
+
return parseTelegramReflectionExtraction(result.choices[0]?.message?.content ?? "");
|
|
602477
|
+
}
|
|
602478
|
+
function memoryDbPaths(repoRoot) {
|
|
602479
|
+
return omniusMemoryDbPaths(repoRoot);
|
|
602480
|
+
}
|
|
602481
|
+
function allowedRelation(value2) {
|
|
602482
|
+
const relations = [
|
|
602483
|
+
"caused_by",
|
|
602484
|
+
"discovered_during",
|
|
602485
|
+
"fixed_by",
|
|
602486
|
+
"produced_by",
|
|
602487
|
+
"co_occurred_with",
|
|
602488
|
+
"requires",
|
|
602489
|
+
"is_instance_of",
|
|
602490
|
+
"related_to",
|
|
602491
|
+
"contains",
|
|
602492
|
+
"modified_by",
|
|
602493
|
+
"said_by",
|
|
602494
|
+
"appears_in",
|
|
602495
|
+
"alias_of",
|
|
602496
|
+
"authored_by",
|
|
602497
|
+
"uploaded_by",
|
|
602498
|
+
"replied_to",
|
|
602499
|
+
"depicts",
|
|
602500
|
+
"named_as",
|
|
602501
|
+
"face_match",
|
|
602502
|
+
"voice_sample_of",
|
|
602503
|
+
"speaker_candidate",
|
|
602504
|
+
"same_person_candidate"
|
|
602505
|
+
];
|
|
602506
|
+
return relations.includes(value2) ? value2 : "related_to";
|
|
602507
|
+
}
|
|
602508
|
+
function nodeText(prefix, value2) {
|
|
602509
|
+
return `${prefix}:${clean4(value2, 180).toLowerCase()}`;
|
|
602510
|
+
}
|
|
602511
|
+
function firstSourceEpisode(itemEpisodeIds, fallback) {
|
|
602512
|
+
return itemEpisodeIds[0] || fallback;
|
|
602513
|
+
}
|
|
602514
|
+
function commitTelegramReflectionExtraction(repoRoot, sessionKey, corpus, extraction) {
|
|
602515
|
+
const paths = memoryDbPaths(repoRoot);
|
|
602516
|
+
const graph = new TemporalGraph(paths.knowledge);
|
|
602517
|
+
const store2 = new EpisodeStore(paths.episodes, graph);
|
|
602518
|
+
try {
|
|
602519
|
+
const reflectionContent = [
|
|
602520
|
+
`Telegram reflection extraction: ${extraction.artifactTitle}`,
|
|
602521
|
+
`session: ${sessionKey}`,
|
|
602522
|
+
`seed: ${corpus.graphWalk.seed?.node.text || "none"}`,
|
|
602523
|
+
`tags: ${extraction.tags.map((tag) => tag.label).join(", ") || "none"}`,
|
|
602524
|
+
"",
|
|
602525
|
+
...extraction.summaries.map((summary) => `${summary.title}: ${summary.text}`),
|
|
602526
|
+
...extraction.extractions.map((item) => `${item.kind}: ${item.text}`)
|
|
602527
|
+
].join("\n");
|
|
602528
|
+
const reflectionEpisodeId = store2.insert({
|
|
602529
|
+
sessionId: sessionKey,
|
|
602530
|
+
modality: "reflection",
|
|
602531
|
+
toolName: "telegram_reflection_extraction",
|
|
602532
|
+
content: reflectionContent,
|
|
602533
|
+
metadata: {
|
|
602534
|
+
sourceSurface: "telegram_reflection",
|
|
602535
|
+
sessionKey,
|
|
602536
|
+
corpusStats: corpus.stats,
|
|
602537
|
+
selectedEpisodeIds: corpus.selectedEpisodeIds,
|
|
602538
|
+
extraction: {
|
|
602539
|
+
artifactTitle: extraction.artifactTitle,
|
|
602540
|
+
tags: extraction.tags,
|
|
602541
|
+
summaries: extraction.summaries,
|
|
602542
|
+
titles: extraction.titles,
|
|
602543
|
+
extractions: extraction.extractions,
|
|
602544
|
+
links: extraction.links,
|
|
602545
|
+
followups: extraction.followups
|
|
602546
|
+
}
|
|
602547
|
+
},
|
|
602548
|
+
importance: 8,
|
|
602549
|
+
decayClass: "procedural"
|
|
602550
|
+
});
|
|
602551
|
+
const artifactNode = graph.upsertNode({ text: nodeText("telegram_reflection", extraction.artifactTitle), nodeType: "concept" });
|
|
602552
|
+
let graphNodes = 1;
|
|
602553
|
+
let graphEdges = 0;
|
|
602554
|
+
const summaryEpisodeIds = [];
|
|
602555
|
+
const seedNodeId = corpus.graphWalk.seed?.node.id;
|
|
602556
|
+
if (seedNodeId) {
|
|
602557
|
+
graph.addEdge({
|
|
602558
|
+
srcId: artifactNode,
|
|
602559
|
+
dstId: seedNodeId,
|
|
602560
|
+
relation: "related_to",
|
|
602561
|
+
fact: `Reflection seed for ${extraction.artifactTitle}`,
|
|
602562
|
+
sourceEpisodeId: reflectionEpisodeId,
|
|
602563
|
+
modality: "reflection",
|
|
602564
|
+
confidence: 0.9
|
|
602565
|
+
});
|
|
602566
|
+
graphEdges++;
|
|
602567
|
+
}
|
|
602568
|
+
for (const tag of extraction.tags) {
|
|
602569
|
+
const tagNode = graph.upsertNode({ text: nodeText("tag", tag.label), nodeType: "concept" });
|
|
602570
|
+
graphNodes++;
|
|
602571
|
+
graph.addEdge({
|
|
602572
|
+
srcId: artifactNode,
|
|
602573
|
+
dstId: tagNode,
|
|
602574
|
+
relation: "contains",
|
|
602575
|
+
fact: `${tag.kind}: ${tag.label}`,
|
|
602576
|
+
sourceEpisodeId: firstSourceEpisode(tag.targetEpisodeIds, reflectionEpisodeId),
|
|
602577
|
+
modality: "reflection",
|
|
602578
|
+
confidence: tag.confidence
|
|
602579
|
+
});
|
|
602580
|
+
graphEdges++;
|
|
602581
|
+
}
|
|
602582
|
+
for (const summary of extraction.summaries) {
|
|
602583
|
+
const episodeId = store2.insert({
|
|
602584
|
+
sessionId: sessionKey,
|
|
602585
|
+
modality: "gist",
|
|
602586
|
+
toolName: "telegram_reflection_summary",
|
|
602587
|
+
content: `${summary.title}
|
|
602588
|
+
${summary.text}`,
|
|
602589
|
+
metadata: {
|
|
602590
|
+
sourceSurface: "telegram_reflection",
|
|
602591
|
+
sessionKey,
|
|
602592
|
+
scope: summary.scope,
|
|
602593
|
+
sourceMessageIds: summary.sourceMessageIds,
|
|
602594
|
+
targetEpisodeIds: summary.targetEpisodeIds
|
|
602595
|
+
},
|
|
602596
|
+
importance: Math.max(6, summary.confidence * 10),
|
|
602597
|
+
decayClass: "procedural",
|
|
602598
|
+
sourceEpisodeId: reflectionEpisodeId
|
|
602599
|
+
});
|
|
602600
|
+
summaryEpisodeIds.push(episodeId);
|
|
602601
|
+
const summaryNode = graph.upsertNode({ text: nodeText("summary", summary.title), nodeType: "concept" });
|
|
602602
|
+
graphNodes++;
|
|
602603
|
+
graph.addEdge({
|
|
602604
|
+
srcId: artifactNode,
|
|
602605
|
+
dstId: summaryNode,
|
|
602606
|
+
relation: "contains",
|
|
602607
|
+
fact: summary.text,
|
|
602608
|
+
sourceEpisodeId: episodeId,
|
|
602609
|
+
modality: "reflection",
|
|
602610
|
+
confidence: summary.confidence
|
|
602611
|
+
});
|
|
602612
|
+
graphEdges++;
|
|
602613
|
+
}
|
|
602614
|
+
for (const title of extraction.titles) {
|
|
602615
|
+
const titleNode = graph.upsertNode({ text: nodeText("title", title.title), nodeType: "concept" });
|
|
602616
|
+
graphNodes++;
|
|
602617
|
+
graph.addEdge({
|
|
602618
|
+
srcId: artifactNode,
|
|
602619
|
+
dstId: titleNode,
|
|
602620
|
+
relation: "contains",
|
|
602621
|
+
fact: `${title.target}: ${title.title}`,
|
|
602622
|
+
sourceEpisodeId: firstSourceEpisode(title.targetEpisodeIds, reflectionEpisodeId),
|
|
602623
|
+
modality: "reflection",
|
|
602624
|
+
confidence: title.confidence
|
|
602625
|
+
});
|
|
602626
|
+
graphEdges++;
|
|
602627
|
+
}
|
|
602628
|
+
for (const item of extraction.extractions) {
|
|
602629
|
+
const itemNode = graph.upsertNode({ text: nodeText(item.kind, item.text), nodeType: item.kind === "open_question" ? "event" : "concept" });
|
|
602630
|
+
graphNodes++;
|
|
602631
|
+
graph.addEdge({
|
|
602632
|
+
srcId: artifactNode,
|
|
602633
|
+
dstId: itemNode,
|
|
602634
|
+
relation: "contains",
|
|
602635
|
+
fact: item.text,
|
|
602636
|
+
sourceEpisodeId: firstSourceEpisode(item.targetEpisodeIds, reflectionEpisodeId),
|
|
602637
|
+
modality: "reflection",
|
|
602638
|
+
confidence: item.confidence
|
|
602639
|
+
});
|
|
602640
|
+
graphEdges++;
|
|
602641
|
+
}
|
|
602642
|
+
for (const link of extraction.links) {
|
|
602643
|
+
const src2 = graph.upsertNode({ text: clean4(link.srcNodeText, 180), nodeType: "concept" });
|
|
602644
|
+
const dst = graph.upsertNode({ text: clean4(link.dstNodeText, 180), nodeType: "concept" });
|
|
602645
|
+
graphNodes += 2;
|
|
602646
|
+
graph.addEdge({
|
|
602647
|
+
srcId: src2,
|
|
602648
|
+
dstId: dst,
|
|
602649
|
+
relation: allowedRelation(link.relation),
|
|
602650
|
+
fact: link.fact,
|
|
602651
|
+
sourceEpisodeId: firstSourceEpisode(link.targetEpisodeIds, reflectionEpisodeId),
|
|
602652
|
+
modality: "reflection",
|
|
602653
|
+
confidence: link.confidence
|
|
602654
|
+
});
|
|
602655
|
+
graphEdges++;
|
|
602656
|
+
}
|
|
602657
|
+
return { reflectionEpisodeId, summaryEpisodeIds, graphNodes, graphEdges };
|
|
602658
|
+
} finally {
|
|
602659
|
+
store2.close();
|
|
602660
|
+
graph.close();
|
|
602661
|
+
}
|
|
602662
|
+
}
|
|
602663
|
+
var init_telegram_reflection_extraction = __esm({
|
|
602664
|
+
"packages/cli/src/tui/telegram-reflection-extraction.ts"() {
|
|
602665
|
+
"use strict";
|
|
602666
|
+
init_dist7();
|
|
602667
|
+
init_memory_paths();
|
|
602668
|
+
}
|
|
602669
|
+
});
|
|
602670
|
+
|
|
601131
602671
|
// packages/cli/src/tui/vision-ingress.ts
|
|
601132
602672
|
var vision_ingress_exports = {};
|
|
601133
602673
|
__export(vision_ingress_exports, {
|
|
@@ -601283,9 +602823,9 @@ var init_vision_ingress = __esm({
|
|
|
601283
602823
|
|
|
601284
602824
|
// packages/cli/src/tui/telegram-bridge.ts
|
|
601285
602825
|
import { mkdirSync as mkdirSync63, existsSync as existsSync108, unlinkSync as unlinkSync21, readdirSync as readdirSync37, statSync as statSync36, statfsSync as statfsSync3, readFileSync as readFileSync88, writeFileSync as writeFileSync57 } from "node:fs";
|
|
601286
|
-
import { join as join123, resolve as resolve41, basename as
|
|
602826
|
+
import { join as join123, resolve as resolve41, basename as basename27, relative as relative13, isAbsolute as isAbsolute7, extname as extname16 } from "node:path";
|
|
601287
602827
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
601288
|
-
import { createHash as
|
|
602828
|
+
import { createHash as createHash23, randomInt } from "node:crypto";
|
|
601289
602829
|
function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
|
|
601290
602830
|
const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
|
|
601291
602831
|
const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
|
|
@@ -601321,6 +602861,29 @@ function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
|
|
|
601321
602861
|
return null;
|
|
601322
602862
|
}
|
|
601323
602863
|
}
|
|
602864
|
+
function parseTelegramReflectionFollowupDecision(text) {
|
|
602865
|
+
const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
|
|
602866
|
+
const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
|
|
602867
|
+
if (!jsonText) return null;
|
|
602868
|
+
try {
|
|
602869
|
+
const parsed = JSON.parse(jsonText);
|
|
602870
|
+
const shouldSendRaw = parsed["should_send"] ?? parsed["shouldSend"];
|
|
602871
|
+
const shouldSend = shouldSendRaw === true;
|
|
602872
|
+
const confidenceRaw = Number(parsed["confidence"]);
|
|
602873
|
+
const confidence2 = Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : 0;
|
|
602874
|
+
const replyRaw = Number(parsed["reply_to_message_id"] ?? parsed["replyToMessageId"]);
|
|
602875
|
+
const replyToMessageId = Number.isFinite(replyRaw) && replyRaw > 0 ? Math.trunc(replyRaw) : void 0;
|
|
602876
|
+
return {
|
|
602877
|
+
shouldSend,
|
|
602878
|
+
text: String(parsed["text"] ?? "").trim().slice(0, 900),
|
|
602879
|
+
reason: String(parsed["reason"] ?? (shouldSend ? "model selected a scoped follow-up" : "model chose silence")).trim().slice(0, 240),
|
|
602880
|
+
confidence: confidence2,
|
|
602881
|
+
replyToMessageId
|
|
602882
|
+
};
|
|
602883
|
+
} catch {
|
|
602884
|
+
return null;
|
|
602885
|
+
}
|
|
602886
|
+
}
|
|
601324
602887
|
function convertMarkdownToTelegramHTML(md) {
|
|
601325
602888
|
let html = md;
|
|
601326
602889
|
html = html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -601365,8 +602928,8 @@ function stripTelegramHiddenThinking(text) {
|
|
|
601365
602928
|
return withoutClosedThink.replace(/<think>[\s\S]*$/gi, "");
|
|
601366
602929
|
}
|
|
601367
602930
|
function sanitizeTelegramProgressText(text, maxLength) {
|
|
601368
|
-
const
|
|
601369
|
-
return
|
|
602931
|
+
const compact2 = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
|
|
602932
|
+
return compact2.length > maxLength ? compact2.slice(0, Math.max(0, maxLength - 3)) + "..." : compact2;
|
|
601370
602933
|
}
|
|
601371
602934
|
function isCodebaseMemoryStatus(text) {
|
|
601372
602935
|
return /^\s*\[CODEBASE MEMORY\]/i.test(stripTelegramHiddenThinking(text));
|
|
@@ -601408,40 +602971,40 @@ function isTelegramNoReplySentinel(text) {
|
|
|
601408
602971
|
return lower === "no_reply" || lower.startsWith("no_reply");
|
|
601409
602972
|
}
|
|
601410
602973
|
function isTelegramInternalStatusText(text) {
|
|
601411
|
-
const
|
|
601412
|
-
if (!
|
|
601413
|
-
const lower =
|
|
601414
|
-
if (isTelegramNoReplySentinel(
|
|
602974
|
+
const compact2 = compactTelegramVisibleText(text);
|
|
602975
|
+
if (!compact2) return false;
|
|
602976
|
+
const lower = compact2.toLowerCase();
|
|
602977
|
+
if (isTelegramNoReplySentinel(compact2)) return true;
|
|
601415
602978
|
if (lower === "complete" || lower === "completed") return true;
|
|
601416
|
-
if (/^memory stage:/i.test(
|
|
601417
|
-
if (/^\[ppr[-_\s]?skip\]/i.test(
|
|
601418
|
-
if (/^(casual|ambient|group)\b.{0,180}\b(skipping|skipped|not directed|no action needed|no reply)\b/i.test(
|
|
601419
|
-
if (/^no further action needed\b/i.test(
|
|
601420
|
-
if (/^no action needed\b.{0,120}\b(task|complete|completed|done)\b/i.test(
|
|
601421
|
-
if (/^(there'?s|there is) no active task\b/i.test(
|
|
601422
|
-
if (/^everything'?s (done|complete|completed|wrapped up)\b/i.test(
|
|
601423
|
-
if (/\balready (been )?(provided|answered|handled|delivered) above\b/i.test(
|
|
601424
|
-
if (/\b(no remaining work|nothing left to do|task is complete|task has been completed)\b/i.test(
|
|
602979
|
+
if (/^memory stage:/i.test(compact2)) return true;
|
|
602980
|
+
if (/^\[ppr[-_\s]?skip\]/i.test(compact2)) return true;
|
|
602981
|
+
if (/^(casual|ambient|group)\b.{0,180}\b(skipping|skipped|not directed|no action needed|no reply)\b/i.test(compact2)) return true;
|
|
602982
|
+
if (/^no further action needed\b/i.test(compact2)) return true;
|
|
602983
|
+
if (/^no action needed\b.{0,120}\b(task|complete|completed|done)\b/i.test(compact2)) return true;
|
|
602984
|
+
if (/^(there'?s|there is) no active task\b/i.test(compact2)) return true;
|
|
602985
|
+
if (/^everything'?s (done|complete|completed|wrapped up)\b/i.test(compact2)) return true;
|
|
602986
|
+
if (/\balready (been )?(provided|answered|handled|delivered) above\b/i.test(compact2)) return true;
|
|
602987
|
+
if (/\b(no remaining work|nothing left to do|task is complete|task has been completed)\b/i.test(compact2)) return true;
|
|
601425
602988
|
return false;
|
|
601426
602989
|
}
|
|
601427
602990
|
function cleanTelegramVisibleReply(text, options2 = {}) {
|
|
601428
|
-
const
|
|
601429
|
-
if (!
|
|
601430
|
-
if (options2.suppressPotentialNoReplyPrefix && isTelegramPotentialNoReplyPrefix(
|
|
601431
|
-
if (isTelegramInternalStatusText(
|
|
601432
|
-
return dedupeTelegramVisibleReply(
|
|
602991
|
+
const clean5 = stripTelegramHiddenThinking(text).trim();
|
|
602992
|
+
if (!clean5) return "";
|
|
602993
|
+
if (options2.suppressPotentialNoReplyPrefix && isTelegramPotentialNoReplyPrefix(clean5)) return "";
|
|
602994
|
+
if (isTelegramInternalStatusText(clean5)) return "";
|
|
602995
|
+
return dedupeTelegramVisibleReply(clean5);
|
|
601433
602996
|
}
|
|
601434
602997
|
function dedupeTelegramVisibleReply(text) {
|
|
601435
602998
|
const paragraphs = text.split(/\n{2,}/);
|
|
601436
602999
|
const seenParagraphs = /* @__PURE__ */ new Set();
|
|
601437
603000
|
const collapsedParagraphs = [];
|
|
601438
603001
|
for (const paragraph of paragraphs) {
|
|
601439
|
-
const
|
|
601440
|
-
if (!
|
|
601441
|
-
const key = compactTelegramVisibleText(
|
|
603002
|
+
const clean5 = paragraph.trim();
|
|
603003
|
+
if (!clean5) continue;
|
|
603004
|
+
const key = compactTelegramVisibleText(clean5).toLowerCase();
|
|
601442
603005
|
if (seenParagraphs.has(key)) continue;
|
|
601443
603006
|
seenParagraphs.add(key);
|
|
601444
|
-
collapsedParagraphs.push(
|
|
603007
|
+
collapsedParagraphs.push(clean5);
|
|
601445
603008
|
}
|
|
601446
603009
|
const paragraphCollapsed = collapsedParagraphs.join("\n\n");
|
|
601447
603010
|
const sentenceLike = paragraphCollapsed.match(/[^.!?]+[.!?]+|[^.!?]+$/g);
|
|
@@ -601471,9 +603034,9 @@ function truncateTelegramContext(text, maxLength) {
|
|
|
601471
603034
|
[Telegram context truncated; use tools for full detail.]`;
|
|
601472
603035
|
}
|
|
601473
603036
|
function truncateTelegramContextLine(text, maxLength = TELEGRAM_CONTEXT_LINE_LIMIT) {
|
|
601474
|
-
const
|
|
601475
|
-
if (
|
|
601476
|
-
return `${
|
|
603037
|
+
const compact2 = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
|
|
603038
|
+
if (compact2.length <= maxLength) return compact2;
|
|
603039
|
+
return `${compact2.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
|
|
601477
603040
|
}
|
|
601478
603041
|
function telegramSpeakerLabel(msg) {
|
|
601479
603042
|
if (msg.username && msg.username !== "unknown") return `@${msg.username}`;
|
|
@@ -601620,7 +603183,7 @@ function buildTelegramRuntimeContext(now = /* @__PURE__ */ new Date(), repoRoot)
|
|
|
601620
603183
|
].filter(Boolean).join("\n");
|
|
601621
603184
|
}
|
|
601622
603185
|
function telegramSessionIdFromKey(sessionKey) {
|
|
601623
|
-
return `telegram-${
|
|
603186
|
+
return `telegram-${createHash23("sha1").update(sessionKey).digest("hex").slice(0, 16)}`;
|
|
601624
603187
|
}
|
|
601625
603188
|
function selectTelegramFinalResponse(args) {
|
|
601626
603189
|
const committedVisibleReply = cleanTelegramVisibleReply(args.visibleReplyText || "");
|
|
@@ -601695,10 +603258,17 @@ function telegramSyntheticHelpSignatures() {
|
|
|
601695
603258
|
{ signature: "/help", description: "Show Telegram command help" },
|
|
601696
603259
|
{ signature: "/start", description: "Show Telegram bridge status and authentication instructions" },
|
|
601697
603260
|
{ signature: "/auth <code>", description: "Authenticate this Telegram user as bot admin using the TUI code" },
|
|
601698
|
-
{ signature: "/call", description: "Get the active voice call link when a call session is running" }
|
|
603261
|
+
{ signature: "/call", description: "Get the active voice call link when a call session is running" },
|
|
603262
|
+
{ signature: "/reflect", description: "Run scoped Telegram chat reflection over retained chat history" },
|
|
603263
|
+
{ signature: "/reflect status", description: "Show the latest scoped Telegram reflection artifact" },
|
|
603264
|
+
{ signature: "/reflect now", description: "Run reflection and let the model decide whether to post a public follow-up" },
|
|
603265
|
+
{ signature: "/reflect auto on|off", description: "Enable or disable model-gated idle follow-ups for this chat" },
|
|
603266
|
+
{ signature: "/reflection", description: "Alias for /reflect" },
|
|
603267
|
+
{ signature: "/daydream", description: "Alias for /reflect in Telegram chats" }
|
|
601699
603268
|
];
|
|
601700
603269
|
}
|
|
601701
603270
|
function telegramHelpCommandAllowed(cmd, scope) {
|
|
603271
|
+
if (cmd.name === "dream") return false;
|
|
601702
603272
|
if (scope === "admin") return cmd.implementationStatus === "implemented";
|
|
601703
603273
|
if (TELEGRAM_PUBLIC_HELP_COMMANDS.has(cmd.name)) return true;
|
|
601704
603274
|
return cmd.surfaces.agentTool && !cmd.safety.secretBearing && !cmd.safety.destructive && !cmd.safety.profileGated;
|
|
@@ -601729,6 +603299,65 @@ function buildTelegramHelpHTML(scope, maxPublicCommands = 24) {
|
|
|
601729
603299
|
}
|
|
601730
603300
|
return lines.join("\n");
|
|
601731
603301
|
}
|
|
603302
|
+
function formatTelegramReflectionSummaryHTML(artifact, opts = { autoFollowup: false }) {
|
|
603303
|
+
const topThreads = artifact.curiosityThreads.slice(0, 3);
|
|
603304
|
+
const topReplies = artifact.replyOpportunities.slice(0, 3);
|
|
603305
|
+
const groupPlans = artifact.outreachPlans.filter((plan) => plan.target === "same_group").slice(0, 2);
|
|
603306
|
+
const topTags = (artifact.tagging ?? []).slice(0, 6);
|
|
603307
|
+
const topSummaries = (artifact.summation ?? []).slice(0, 3);
|
|
603308
|
+
const topExtractions = (artifact.extraction ?? []).slice(0, 4);
|
|
603309
|
+
const topLinks = (artifact.linking ?? []).slice(0, 4);
|
|
603310
|
+
const lines = [
|
|
603311
|
+
`<b>Telegram reflection</b>`,
|
|
603312
|
+
`Scope: <code>${escapeTelegramHTML(artifact.chatTitle || artifact.chatId)}</code> (${escapeTelegramHTML(artifact.chatType)})`,
|
|
603313
|
+
`Window: ${artifact.messageWindow.totalRetained} retained messages`,
|
|
603314
|
+
artifact.corpus?.stats ? `Corpus: ${artifact.corpus.stats.selectedEpisodes} selected episodes, ${artifact.corpus.stats.graphNodesVisited} graph nodes, ${artifact.corpus.stats.graphEdgesTraversed} graph edges` : "",
|
|
603315
|
+
artifact.selectedSeed ? `Seed: <code>${escapeTelegramHTML(artifact.selectedSeed.nodeText)}</code>` : "",
|
|
603316
|
+
`Auto follow-up: <b>${opts.autoFollowup ? "on" : "off"}</b>`,
|
|
603317
|
+
opts.sentFollowup ? `Follow-up: <b>sent</b>` : opts.followupReason ? `Follow-up: ${escapeTelegramHTML(opts.followupReason)}` : "",
|
|
603318
|
+
"",
|
|
603319
|
+
topTags.length ? `<b>Tags</b>` : "",
|
|
603320
|
+
...topTags.map(
|
|
603321
|
+
(tag) => `- ${escapeTelegramHTML(tag.label)} (${escapeTelegramHTML(tag.kind)}, ${Math.round(tag.confidence * 100)}%)`
|
|
603322
|
+
),
|
|
603323
|
+
topSummaries.length ? "" : "",
|
|
603324
|
+
topSummaries.length ? `<b>Summaries</b>` : "",
|
|
603325
|
+
...topSummaries.map(
|
|
603326
|
+
(summary) => `- ${escapeTelegramHTML(summary.title)}: ${escapeTelegramHTML(summary.text)}`
|
|
603327
|
+
),
|
|
603328
|
+
topExtractions.length ? "" : "",
|
|
603329
|
+
topExtractions.length ? `<b>Extractions</b>` : "",
|
|
603330
|
+
...topExtractions.map(
|
|
603331
|
+
(item) => `- ${escapeTelegramHTML(item.kind)}: ${escapeTelegramHTML(item.text)}`
|
|
603332
|
+
),
|
|
603333
|
+
topLinks.length ? "" : "",
|
|
603334
|
+
topLinks.length ? `<b>Links</b>` : "",
|
|
603335
|
+
...topLinks.map(
|
|
603336
|
+
(link) => `- ${escapeTelegramHTML(link.srcNodeText)} -> ${escapeTelegramHTML(link.dstNodeText)} (${escapeTelegramHTML(link.relation)})`
|
|
603337
|
+
),
|
|
603338
|
+
artifact.corpus?.fallbacks?.length ? "" : "",
|
|
603339
|
+
artifact.corpus?.fallbacks?.length ? `<b>Fallbacks</b>` : "",
|
|
603340
|
+
...(artifact.corpus?.fallbacks ?? []).slice(0, 3).map((fallback) => `- ${escapeTelegramHTML(fallback)}`),
|
|
603341
|
+
"",
|
|
603342
|
+
topThreads.length ? `<b>Curiosity threads</b>` : "",
|
|
603343
|
+
...topThreads.map(
|
|
603344
|
+
(thread) => `- ${escapeTelegramHTML(thread.question)} (${Math.round(thread.intensity * 100)}%)`
|
|
603345
|
+
),
|
|
603346
|
+
topReplies.length ? "" : "",
|
|
603347
|
+
topReplies.length ? `<b>Reply opportunities</b>` : "",
|
|
603348
|
+
...topReplies.map(
|
|
603349
|
+
(item) => `- ${escapeTelegramHTML(item.trigger)} (${Math.round(item.confidence * 100)}%)`
|
|
603350
|
+
),
|
|
603351
|
+
groupPlans.length ? "" : "",
|
|
603352
|
+
groupPlans.length ? `<b>Same-group outreach plans</b>` : "",
|
|
603353
|
+
...groupPlans.map(
|
|
603354
|
+
(plan) => `- ${escapeTelegramHTML(plan.trigger)} (${Math.round(plan.confidence * 100)}%, ${escapeTelegramHTML(plan.gate)})`
|
|
603355
|
+
),
|
|
603356
|
+
"",
|
|
603357
|
+
"Saved as scoped Telegram context for future routing. It reflects chat history only, not the workspace filesystem."
|
|
603358
|
+
].filter((line) => line !== "");
|
|
603359
|
+
return lines.join("\n");
|
|
603360
|
+
}
|
|
601732
603361
|
function splitTelegramHTMLMessage(html, maxLength = 3600) {
|
|
601733
603362
|
const chunks = [];
|
|
601734
603363
|
let current = "";
|
|
@@ -602084,6 +603713,16 @@ function telegramImageMime(media) {
|
|
|
602084
603713
|
if (ext === ".tif" || ext === ".tiff") return "image/tiff";
|
|
602085
603714
|
return "image/jpeg";
|
|
602086
603715
|
}
|
|
603716
|
+
function appendMediaContextBlock(description, block) {
|
|
603717
|
+
const clean5 = block.trim();
|
|
603718
|
+
if (!clean5) return description;
|
|
603719
|
+
if (description.endsWith("]")) return `${description.slice(0, -1)}
|
|
603720
|
+
|
|
603721
|
+
${clean5}]`;
|
|
603722
|
+
return `${description}
|
|
603723
|
+
|
|
603724
|
+
${clean5}`;
|
|
603725
|
+
}
|
|
602087
603726
|
function telegramCachedMediaIsImage(entry) {
|
|
602088
603727
|
if (entry.mediaType === "photo") return true;
|
|
602089
603728
|
if (entry.mimeType?.toLowerCase().startsWith("image/")) return true;
|
|
@@ -602312,7 +603951,7 @@ function renderTelegramSubAgentError(username, error) {
|
|
|
602312
603951
|
process.stdout.write(` ${c3.dim("⎿")} ${c3.red("✘")} @${username}: ${c3.dim(preview)}
|
|
602313
603952
|
`);
|
|
602314
603953
|
}
|
|
602315
|
-
var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_PUBLIC_HELP_COMMANDS, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TelegramBridge;
|
|
603954
|
+
var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_PUBLIC_HELP_COMMANDS, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TelegramBridge;
|
|
602316
603955
|
var init_telegram_bridge = __esm({
|
|
602317
603956
|
"packages/cli/src/tui/telegram-bridge.ts"() {
|
|
602318
603957
|
"use strict";
|
|
@@ -602328,7 +603967,10 @@ var init_telegram_bridge = __esm({
|
|
|
602328
603967
|
init_omnius_directory();
|
|
602329
603968
|
init_stimulation();
|
|
602330
603969
|
init_identity_memory_tool();
|
|
603970
|
+
init_visual_identity_association();
|
|
602331
603971
|
init_telegram_channel_dmn();
|
|
603972
|
+
init_telegram_reflection_corpus();
|
|
603973
|
+
init_telegram_reflection_extraction();
|
|
602332
603974
|
TELEGRAM_SAFETY_PROMPT = `
|
|
602333
603975
|
CRITICAL SAFETY NOTICE — PUBLIC TELEGRAM CHANNEL
|
|
602334
603976
|
|
|
@@ -602512,6 +604154,7 @@ Telegram response contract:
|
|
|
602512
604154
|
]);
|
|
602513
604155
|
TELEGRAM_PUBLIC_HELP_COMMANDS = /* @__PURE__ */ new Set(["help", "start", "auth", "call"]);
|
|
602514
604156
|
TELEGRAM_REMINDER_SLASH_COMMANDS = /* @__PURE__ */ new Set(["remind", "reminder", "reminders"]);
|
|
604157
|
+
TELEGRAM_REFLECTION_SLASH_COMMANDS = /* @__PURE__ */ new Set(["reflect", "reflection", "daydream", "dream"]);
|
|
602515
604158
|
TELEGRAM_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", ".tif", ".svg"]);
|
|
602516
604159
|
MEDIA_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
602517
604160
|
TELEGRAM_CHANNEL_DMN_SWEEP_MS = 2 * 60 * 1e3;
|
|
@@ -602614,6 +604257,8 @@ Telegram response contract:
|
|
|
602614
604257
|
channelDmnRunning = /* @__PURE__ */ new Set();
|
|
602615
604258
|
/** Daydream artifact already used to force a live-router check. */
|
|
602616
604259
|
channelDmnPromptedArtifactAt = /* @__PURE__ */ new Map();
|
|
604260
|
+
/** Per-chat reflection settings for model-gated idle follow-ups. */
|
|
604261
|
+
channelReflectionState = /* @__PURE__ */ new Map();
|
|
602617
604262
|
/** Set admin user ID filter */
|
|
602618
604263
|
setAdmin(userId) {
|
|
602619
604264
|
this.adminUserId = userId;
|
|
@@ -602698,7 +604343,7 @@ Telegram response contract:
|
|
|
602698
604343
|
return !!this.adminAuthChallenge && this.adminAuthChallenge.expiresAtMs > Date.now();
|
|
602699
604344
|
}
|
|
602700
604345
|
hashAdminAuthCode(code8) {
|
|
602701
|
-
return
|
|
604346
|
+
return createHash23("sha256").update(`omnius-telegram-admin:${code8.trim()}`).digest("hex");
|
|
602702
604347
|
}
|
|
602703
604348
|
viewIdForMessage(msg) {
|
|
602704
604349
|
return `telegram-${this.sessionKeyForMessage(msg).replace(/[^A-Za-z0-9_-]/g, "-")}`;
|
|
@@ -602769,6 +604414,69 @@ Telegram response contract:
|
|
|
602769
604414
|
result.success ? result.output || "Reminder updated." : result.error || `/${cmd} failed`
|
|
602770
604415
|
);
|
|
602771
604416
|
}
|
|
604417
|
+
async handleTelegramReflectionSlash(msg, commandText) {
|
|
604418
|
+
if (!this.repoRoot) {
|
|
604419
|
+
await this.replyToTelegramMessage(msg, "Telegram reflection storage is not available yet.");
|
|
604420
|
+
return;
|
|
604421
|
+
}
|
|
604422
|
+
const sessionKey = this.sessionKeyForMessage(msg);
|
|
604423
|
+
this.ensureTelegramConversationLoaded(sessionKey);
|
|
604424
|
+
const first2 = commandText.trim().split(/\s+/)[0] ?? "";
|
|
604425
|
+
const commandName = first2.slice(1).split("@")[0]?.toLowerCase() || "reflect";
|
|
604426
|
+
const arg = commandText.trim().slice(first2.length).trim();
|
|
604427
|
+
const lower = arg.toLowerCase();
|
|
604428
|
+
const state = this.reflectionStateForSession(sessionKey);
|
|
604429
|
+
if (commandName === "dream" && (lower === "deep" || lower === "lucid" || lower === "consolidate")) {
|
|
604430
|
+
await this.replyToTelegramMessage(
|
|
604431
|
+
msg,
|
|
604432
|
+
"Telegram /dream is scoped to chat reflection and does not start filesystem dream mode. Use /reflect, /reflect now, or run /dream in the TUI terminal."
|
|
604433
|
+
);
|
|
604434
|
+
return;
|
|
604435
|
+
}
|
|
604436
|
+
if (lower === "auto on" || lower === "on") {
|
|
604437
|
+
state.autoFollowup = true;
|
|
604438
|
+
this.saveTelegramConversationState(sessionKey);
|
|
604439
|
+
await this.replyToTelegramMessage(msg, "Scoped Telegram reflection auto follow-up is on for this chat. Idle cycles remain model-gated and public-only.");
|
|
604440
|
+
return;
|
|
604441
|
+
}
|
|
604442
|
+
if (lower === "auto off" || lower === "off" || lower === "stop") {
|
|
604443
|
+
state.autoFollowup = false;
|
|
604444
|
+
this.saveTelegramConversationState(sessionKey);
|
|
604445
|
+
await this.replyToTelegramMessage(msg, "Scoped Telegram reflection auto follow-up is off for this chat.");
|
|
604446
|
+
return;
|
|
604447
|
+
}
|
|
604448
|
+
if (lower === "auto" || lower === "status" || lower === "show") {
|
|
604449
|
+
const latest = this.latestTelegramChannelDaydream(sessionKey);
|
|
604450
|
+
const html2 = latest ? formatTelegramReflectionSummaryHTML(latest, { autoFollowup: state.autoFollowup }) : `<b>Telegram reflection</b>
|
|
604451
|
+
No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code> to build one from retained Telegram history.`;
|
|
604452
|
+
await this.replyToTelegramMessage(msg, html2, {
|
|
604453
|
+
html: true,
|
|
604454
|
+
replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
|
|
604455
|
+
});
|
|
604456
|
+
return;
|
|
604457
|
+
}
|
|
604458
|
+
const artifact = await this.runTelegramChannelDmnForSession(sessionKey, "telegram-command", Date.now(), true);
|
|
604459
|
+
if (!artifact) {
|
|
604460
|
+
await this.replyToTelegramMessage(
|
|
604461
|
+
msg,
|
|
604462
|
+
"No retained Telegram chat history is available for scoped reflection yet. Send a few messages in this chat first, then run /reflect again."
|
|
604463
|
+
);
|
|
604464
|
+
return;
|
|
604465
|
+
}
|
|
604466
|
+
let followup;
|
|
604467
|
+
if (lower === "now" || lower === "reply" || lower === "send") {
|
|
604468
|
+
followup = await this.maybeSendTelegramReflectionFollowup(sessionKey, artifact, "telegram-command");
|
|
604469
|
+
}
|
|
604470
|
+
const html = formatTelegramReflectionSummaryHTML(artifact, {
|
|
604471
|
+
autoFollowup: state.autoFollowup,
|
|
604472
|
+
sentFollowup: followup?.sent,
|
|
604473
|
+
followupReason: followup?.reason
|
|
604474
|
+
});
|
|
604475
|
+
await this.replyToTelegramMessage(msg, html, {
|
|
604476
|
+
html: true,
|
|
604477
|
+
replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
|
|
604478
|
+
});
|
|
604479
|
+
}
|
|
602772
604480
|
/** Write to the scrollable TUI waterfall area (respects status bar scroll region) */
|
|
602773
604481
|
tuiWrite(fn) {
|
|
602774
604482
|
if (this.writeContent) {
|
|
@@ -602887,9 +604595,9 @@ Telegram response contract:
|
|
|
602887
604595
|
return reply;
|
|
602888
604596
|
}
|
|
602889
604597
|
quoteTelegramContextBlock(text, maxLength = 1800) {
|
|
602890
|
-
const
|
|
602891
|
-
const clipped =
|
|
602892
|
-
[reply context truncated]` :
|
|
604598
|
+
const clean5 = stripTelegramHiddenThinking(text).trim();
|
|
604599
|
+
const clipped = clean5.length > maxLength ? `${clean5.slice(0, Math.max(0, maxLength - 60)).trimEnd()}
|
|
604600
|
+
[reply context truncated]` : clean5;
|
|
602893
604601
|
return clipped.split(/\r?\n/).map((line) => `> ${line}`).join("\n");
|
|
602894
604602
|
}
|
|
602895
604603
|
buildTelegramCurrentReplyContext(sessionKey, msg) {
|
|
@@ -602995,6 +604703,7 @@ ${mediaContext}` : ""
|
|
|
602995
604703
|
const modality = media.type === "audio" || media.type === "voice" ? "audio" : telegramMediaIsImage(media) ? "visual" : "text";
|
|
602996
604704
|
const payload = {
|
|
602997
604705
|
sourceSurface: "telegram",
|
|
604706
|
+
sessionId: this.sessionKeyForMessage(msg),
|
|
602998
604707
|
scope: this.telegramMemoryScope(msg),
|
|
602999
604708
|
sender,
|
|
603000
604709
|
message: {
|
|
@@ -603036,7 +604745,7 @@ ${mediaContext}` : ""
|
|
|
603036
604745
|
return payload;
|
|
603037
604746
|
}
|
|
603038
604747
|
telegramConversationPath(sessionKey) {
|
|
603039
|
-
const safe =
|
|
604748
|
+
const safe = createHash23("sha1").update(sessionKey).digest("hex").slice(0, 20);
|
|
603040
604749
|
return join123(this.telegramConversationDir, `${safe}.json`);
|
|
603041
604750
|
}
|
|
603042
604751
|
telegramPersonalityScope(sessionKey, msg) {
|
|
@@ -603076,6 +604785,13 @@ ${mediaContext}` : ""
|
|
|
603076
604785
|
if (parsed.stimulation) {
|
|
603077
604786
|
this.stimulation.setState(sessionKey, parsed.stimulation);
|
|
603078
604787
|
}
|
|
604788
|
+
if (parsed.reflection) {
|
|
604789
|
+
this.channelReflectionState.set(sessionKey, {
|
|
604790
|
+
autoFollowup: parsed.reflection.autoFollowup === true,
|
|
604791
|
+
lastFollowupAt: typeof parsed.reflection.lastFollowupAt === "number" ? parsed.reflection.lastFollowupAt : void 0,
|
|
604792
|
+
lastFollowupArtifactAt: typeof parsed.reflection.lastFollowupArtifactAt === "string" ? parsed.reflection.lastFollowupArtifactAt : void 0
|
|
604793
|
+
});
|
|
604794
|
+
}
|
|
603079
604795
|
} catch {
|
|
603080
604796
|
}
|
|
603081
604797
|
}
|
|
@@ -603110,7 +604826,8 @@ ${mediaContext}` : ""
|
|
|
603110
604826
|
history: this.chatHistory.get(sessionKey) ?? [],
|
|
603111
604827
|
participants,
|
|
603112
604828
|
memoryCards: this.chatMemoryCards.get(sessionKey) ?? [],
|
|
603113
|
-
stimulation: this.stimulation.getState(sessionKey)
|
|
604829
|
+
stimulation: this.stimulation.getState(sessionKey),
|
|
604830
|
+
reflection: this.channelReflectionState.get(sessionKey) ?? { autoFollowup: false }
|
|
603114
604831
|
};
|
|
603115
604832
|
writeFileSync57(this.telegramConversationPath(sessionKey), JSON.stringify(payload, null, 2) + "\n", "utf8");
|
|
603116
604833
|
} catch {
|
|
@@ -603120,6 +604837,21 @@ ${mediaContext}` : ""
|
|
|
603120
604837
|
if (!this.repoRoot) return null;
|
|
603121
604838
|
return latestTelegramChannelDaydream(this.repoRoot, sessionKey);
|
|
603122
604839
|
}
|
|
604840
|
+
reflectionStateForSession(sessionKey) {
|
|
604841
|
+
const existing = this.channelReflectionState.get(sessionKey);
|
|
604842
|
+
if (existing) return existing;
|
|
604843
|
+
const created = { autoFollowup: false };
|
|
604844
|
+
this.channelReflectionState.set(sessionKey, created);
|
|
604845
|
+
return created;
|
|
604846
|
+
}
|
|
604847
|
+
telegramReflectionEmbeddingConfig() {
|
|
604848
|
+
if (!this.agentConfig || this.agentConfig.backendType !== "ollama") return false;
|
|
604849
|
+
return {
|
|
604850
|
+
baseUrl: this.agentConfig.backendUrl,
|
|
604851
|
+
model: process.env["OMNIUS_EMBEDDING_MODEL"] || "nomic-embed-text",
|
|
604852
|
+
timeoutMs: Math.min(Math.max(this.agentConfig.timeoutMs ?? 3e4, 5e3), 3e4)
|
|
604853
|
+
};
|
|
604854
|
+
}
|
|
603123
604855
|
buildTelegramChannelDaydreamInput(sessionKey, nowMs = Date.now()) {
|
|
603124
604856
|
const history = this.chatHistory.get(sessionKey) ?? [];
|
|
603125
604857
|
if (history.length === 0) return null;
|
|
@@ -603153,11 +604885,18 @@ ${mediaContext}` : ""
|
|
|
603153
604885
|
role: entry.role,
|
|
603154
604886
|
speaker: entry.speaker,
|
|
603155
604887
|
username: entry.username,
|
|
604888
|
+
firstName: entry.firstName,
|
|
604889
|
+
fromUserId: entry.fromUserId,
|
|
603156
604890
|
text: entry.text,
|
|
603157
604891
|
ts: entry.ts,
|
|
603158
604892
|
mode: entry.mode,
|
|
604893
|
+
chatId: entry.chatId,
|
|
604894
|
+
chatType: entry.chatType,
|
|
604895
|
+
chatTitle: entry.chatTitle,
|
|
603159
604896
|
messageId: entry.messageId,
|
|
604897
|
+
messageThreadId: entry.messageThreadId,
|
|
603160
604898
|
replyToMessageId: entry.replyToMessageId,
|
|
604899
|
+
replyContext: entry.replyContext,
|
|
603161
604900
|
mediaSummary: entry.mediaSummary
|
|
603162
604901
|
})),
|
|
603163
604902
|
participants,
|
|
@@ -603172,7 +604911,7 @@ ${mediaContext}` : ""
|
|
|
603172
604911
|
if (this.subAgents.has(sessionKey)) return null;
|
|
603173
604912
|
const input = this.buildTelegramChannelDaydreamInput(sessionKey, nowMs);
|
|
603174
604913
|
if (!input) return null;
|
|
603175
|
-
if (input.chatType === "private") return null;
|
|
604914
|
+
if (input.chatType === "private" && !force) return null;
|
|
603176
604915
|
const lastMessageAt = input.history.map((entry) => entry.ts).filter((ts) => typeof ts === "number").sort((a2, b) => b - a2)[0] ?? nowMs;
|
|
603177
604916
|
const lastRunAt = this.channelDmnLastRunAt.get(sessionKey) ?? 0;
|
|
603178
604917
|
if (!force) {
|
|
@@ -603182,9 +604921,51 @@ ${mediaContext}` : ""
|
|
|
603182
604921
|
}
|
|
603183
604922
|
this.channelDmnRunning.add(sessionKey);
|
|
603184
604923
|
try {
|
|
603185
|
-
const
|
|
604924
|
+
const corpus = await buildTelegramReflectionCorpus({
|
|
604925
|
+
repoRoot: this.repoRoot,
|
|
604926
|
+
sessionKey,
|
|
604927
|
+
chatId: input.chatId,
|
|
604928
|
+
chatType: input.chatType,
|
|
604929
|
+
chatTitle: input.chatTitle,
|
|
604930
|
+
generatedAtMs: nowMs,
|
|
604931
|
+
history: input.history,
|
|
604932
|
+
embeddingConfig: this.telegramReflectionEmbeddingConfig()
|
|
604933
|
+
});
|
|
604934
|
+
let extraction = null;
|
|
604935
|
+
let extractionCommit;
|
|
604936
|
+
if (this.agentConfig) {
|
|
604937
|
+
try {
|
|
604938
|
+
const backend = new OllamaAgenticBackend(
|
|
604939
|
+
this.agentConfig.backendUrl,
|
|
604940
|
+
this.agentConfig.model,
|
|
604941
|
+
this.agentConfig.apiKey
|
|
604942
|
+
);
|
|
604943
|
+
extraction = await runTelegramReflectionExtraction({
|
|
604944
|
+
backend: {
|
|
604945
|
+
chatCompletion: (args) => backend.chatCompletion(args)
|
|
604946
|
+
},
|
|
604947
|
+
corpus,
|
|
604948
|
+
sessionKey,
|
|
604949
|
+
chatId: input.chatId,
|
|
604950
|
+
chatType: input.chatType,
|
|
604951
|
+
chatTitle: input.chatTitle,
|
|
604952
|
+
timeoutMs: Math.min(Math.max(this.agentConfig.timeoutMs ?? 3e4, 5e3), 3e4)
|
|
604953
|
+
});
|
|
604954
|
+
if (extraction) {
|
|
604955
|
+
extractionCommit = commitTelegramReflectionExtraction(this.repoRoot, sessionKey, corpus, extraction);
|
|
604956
|
+
} else {
|
|
604957
|
+
corpus.fallbacks.push("structured extraction unavailable: model returned no valid JSON");
|
|
604958
|
+
}
|
|
604959
|
+
} catch (err) {
|
|
604960
|
+
corpus.fallbacks.push(`structured extraction unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
604961
|
+
}
|
|
604962
|
+
} else {
|
|
604963
|
+
corpus.fallbacks.push("structured extraction unavailable: backend unavailable");
|
|
604964
|
+
}
|
|
604965
|
+
const artifact = buildTelegramChannelDaydream(input, corpus, extraction, extractionCommit);
|
|
603186
604966
|
writeTelegramChannelDaydream(this.repoRoot, artifact);
|
|
603187
604967
|
this.channelDmnLastRunAt.set(sessionKey, nowMs);
|
|
604968
|
+
this.channelDmnPromptedArtifactAt.delete(sessionKey);
|
|
603188
604969
|
void reason;
|
|
603189
604970
|
return artifact;
|
|
603190
604971
|
} finally {
|
|
@@ -603196,7 +604977,123 @@ ${mediaContext}` : ""
|
|
|
603196
604977
|
this.ensureAllTelegramConversationsLoaded();
|
|
603197
604978
|
const now = Date.now();
|
|
603198
604979
|
for (const sessionKey of this.chatHistory.keys()) {
|
|
603199
|
-
await this.runTelegramChannelDmnForSession(sessionKey, reason, now).catch(() => null);
|
|
604980
|
+
const artifact = await this.runTelegramChannelDmnForSession(sessionKey, reason, now).catch(() => null);
|
|
604981
|
+
if (!artifact) continue;
|
|
604982
|
+
const reflection = this.reflectionStateForSession(sessionKey);
|
|
604983
|
+
if (reflection.autoFollowup) {
|
|
604984
|
+
await this.maybeSendTelegramReflectionFollowup(sessionKey, artifact, reason).catch(() => null);
|
|
604985
|
+
}
|
|
604986
|
+
}
|
|
604987
|
+
}
|
|
604988
|
+
telegramChatIdFromArtifact(artifact) {
|
|
604989
|
+
const numeric = Number(artifact.chatId);
|
|
604990
|
+
return Number.isFinite(numeric) && String(Math.trunc(numeric)) === artifact.chatId ? Math.trunc(numeric) : artifact.chatId;
|
|
604991
|
+
}
|
|
604992
|
+
async maybeSendTelegramReflectionFollowup(sessionKey, artifact, reason = "reflection") {
|
|
604993
|
+
if (!this.agentConfig) return { sent: false, reason: "backend unavailable" };
|
|
604994
|
+
if (artifact.chatType === "private") return { sent: false, reason: "private chat reflection stored without autonomous outreach" };
|
|
604995
|
+
const state = this.reflectionStateForSession(sessionKey);
|
|
604996
|
+
if (state.lastFollowupArtifactAt === artifact.generatedAt) {
|
|
604997
|
+
return { sent: false, reason: "follow-up already evaluated for this artifact" };
|
|
604998
|
+
}
|
|
604999
|
+
const now = Date.now();
|
|
605000
|
+
if (state.lastFollowupAt && now - state.lastFollowupAt < 60 * 6e4) {
|
|
605001
|
+
return { sent: false, reason: "rate limit held public follow-up" };
|
|
605002
|
+
}
|
|
605003
|
+
const candidateMessageIds = Array.from(new Set([
|
|
605004
|
+
...artifact.curiosityThreads.flatMap((thread) => thread.sourceMessages ?? []),
|
|
605005
|
+
...artifact.memoryProposals.flatMap((proposal) => proposal.sourceMessages ?? []),
|
|
605006
|
+
...(artifact.tagging ?? []).flatMap((item) => item.sourceMessageIds ?? []),
|
|
605007
|
+
...(artifact.summation ?? []).flatMap((item) => item.sourceMessageIds ?? []),
|
|
605008
|
+
...(artifact.titling ?? []).flatMap((item) => item.sourceMessageIds ?? []),
|
|
605009
|
+
...(artifact.extraction ?? []).flatMap((item) => item.sourceMessageIds ?? []),
|
|
605010
|
+
...(artifact.linking ?? []).flatMap((item) => item.sourceMessageIds ?? []),
|
|
605011
|
+
...(artifact.extractionFollowups ?? []).map((item) => item.replyToMessageId).filter((id) => typeof id === "number")
|
|
605012
|
+
].filter((id) => typeof id === "number" && Number.isFinite(id))));
|
|
605013
|
+
const context2 = this.buildTelegramConversationContextStream(sessionKey, {
|
|
605014
|
+
chatId: this.telegramChatIdFromArtifact(artifact),
|
|
605015
|
+
chatType: artifact.chatType,
|
|
605016
|
+
chatTitle: artifact.chatTitle,
|
|
605017
|
+
text: `[internal Telegram reflection cycle: ${reason}]`,
|
|
605018
|
+
username: this.state.botUsername || "omnius",
|
|
605019
|
+
firstName: "Omnius",
|
|
605020
|
+
fromUserId: 0,
|
|
605021
|
+
messageId: 0
|
|
605022
|
+
}, 40);
|
|
605023
|
+
const prompt = [
|
|
605024
|
+
"You are deciding whether an idle Telegram reflection cycle should post one public follow-up in the same group.",
|
|
605025
|
+
'Return JSON only: {"should_send":boolean,"text":"public message text","reply_to_message_id":number|null,"confidence":0.0-1.0,"reason":"short reason"}.',
|
|
605026
|
+
"",
|
|
605027
|
+
"Hard constraints:",
|
|
605028
|
+
"- Use only the Telegram chat context and reflection artifact below.",
|
|
605029
|
+
"- Do not inspect or reference the workspace filesystem.",
|
|
605030
|
+
"- Default should_send=false unless a concise public follow-up is timely, low-intrusion, and clearly useful.",
|
|
605031
|
+
"- Do not reveal hidden meta-analysis, local paths, internal tools, or that a private artifact exists.",
|
|
605032
|
+
"- If sending, write one short message under 700 characters.",
|
|
605033
|
+
"- Prefer replying to one of the candidate message IDs when the follow-up is anchored to old content.",
|
|
605034
|
+
"- Private DM outreach is admin-review only and must not be sent by this autonomous public follow-up path.",
|
|
605035
|
+
"",
|
|
605036
|
+
`Candidate reply message IDs: ${candidateMessageIds.length ? candidateMessageIds.join(", ") : "none"}`,
|
|
605037
|
+
"",
|
|
605038
|
+
formatTelegramChannelDaydreamContext(artifact),
|
|
605039
|
+
"",
|
|
605040
|
+
context2
|
|
605041
|
+
].join("\n");
|
|
605042
|
+
try {
|
|
605043
|
+
const backend = new OllamaAgenticBackend(
|
|
605044
|
+
this.agentConfig.backendUrl,
|
|
605045
|
+
this.agentConfig.model,
|
|
605046
|
+
this.agentConfig.apiKey
|
|
605047
|
+
);
|
|
605048
|
+
const result = await backend.chatCompletion({
|
|
605049
|
+
messages: [
|
|
605050
|
+
{ role: "system", content: "You are a Telegram public-follow-up discretion model. Output strict JSON only." },
|
|
605051
|
+
{ role: "user", content: prompt }
|
|
605052
|
+
],
|
|
605053
|
+
tools: [],
|
|
605054
|
+
temperature: 0.2,
|
|
605055
|
+
maxTokens: 300,
|
|
605056
|
+
timeoutMs: Math.min(Math.max(this.agentConfig.timeoutMs ?? 3e4, 5e3), 2e4),
|
|
605057
|
+
think: false
|
|
605058
|
+
});
|
|
605059
|
+
const decision = parseTelegramReflectionFollowupDecision(result.choices[0]?.message?.content ?? "");
|
|
605060
|
+
state.lastFollowupArtifactAt = artifact.generatedAt;
|
|
605061
|
+
if (!decision) {
|
|
605062
|
+
this.saveTelegramConversationState(sessionKey);
|
|
605063
|
+
return { sent: false, reason: "model returned no usable follow-up decision" };
|
|
605064
|
+
}
|
|
605065
|
+
if (!decision.shouldSend || !decision.text || decision.confidence < 0.66) {
|
|
605066
|
+
this.saveTelegramConversationState(sessionKey);
|
|
605067
|
+
return { sent: false, reason: decision.reason || "model chose silence" };
|
|
605068
|
+
}
|
|
605069
|
+
const replyTo = decision.replyToMessageId && candidateMessageIds.includes(decision.replyToMessageId) ? decision.replyToMessageId : void 0;
|
|
605070
|
+
const chatId = this.telegramChatIdFromArtifact(artifact);
|
|
605071
|
+
const sentMessageId = await this.sendMessageHTML(
|
|
605072
|
+
chatId,
|
|
605073
|
+
convertMarkdownToTelegramHTML(decision.text),
|
|
605074
|
+
replyTo
|
|
605075
|
+
);
|
|
605076
|
+
this.recordTelegramAssistantMessage({
|
|
605077
|
+
chatId,
|
|
605078
|
+
chatType: artifact.chatType,
|
|
605079
|
+
chatTitle: artifact.chatTitle,
|
|
605080
|
+
text: decision.text,
|
|
605081
|
+
username: this.state.botUsername || "omnius",
|
|
605082
|
+
firstName: "Omnius",
|
|
605083
|
+
fromUserId: 0,
|
|
605084
|
+
messageId: sentMessageId ?? 0
|
|
605085
|
+
}, decision.text, "chat", {
|
|
605086
|
+
messageId: sentMessageId,
|
|
605087
|
+
replyToMessageId: replyTo
|
|
605088
|
+
});
|
|
605089
|
+
state.lastFollowupAt = now;
|
|
605090
|
+
this.saveTelegramConversationState(sessionKey);
|
|
605091
|
+
this.tuiWrite(() => renderTelegramSubAgentEvent("reflection", `sent scoped Telegram follow-up (${decision.confidence.toFixed(2)}): ${decision.reason}`));
|
|
605092
|
+
return { sent: true, reason: decision.reason };
|
|
605093
|
+
} catch (err) {
|
|
605094
|
+
state.lastFollowupArtifactAt = artifact.generatedAt;
|
|
605095
|
+
this.saveTelegramConversationState(sessionKey);
|
|
605096
|
+
return { sent: false, reason: err instanceof Error ? err.message : String(err) };
|
|
603200
605097
|
}
|
|
603201
605098
|
}
|
|
603202
605099
|
formatLatestTelegramChannelDaydreamContext(sessionKey) {
|
|
@@ -603220,6 +605117,22 @@ ${mediaContext}` : ""
|
|
|
603220
605117
|
return "";
|
|
603221
605118
|
}
|
|
603222
605119
|
}
|
|
605120
|
+
upsertTelegramReflectionHistoryEntry(sessionKey, entry) {
|
|
605121
|
+
if (!this.repoRoot || entry.chatId === void 0) return;
|
|
605122
|
+
try {
|
|
605123
|
+
upsertTelegramReflectionMessage(
|
|
605124
|
+
this.repoRoot,
|
|
605125
|
+
sessionKey,
|
|
605126
|
+
entry,
|
|
605127
|
+
{
|
|
605128
|
+
chatId: String(entry.chatId),
|
|
605129
|
+
chatType: entry.chatType || "unknown",
|
|
605130
|
+
chatTitle: entry.chatTitle
|
|
605131
|
+
}
|
|
605132
|
+
);
|
|
605133
|
+
} catch {
|
|
605134
|
+
}
|
|
605135
|
+
}
|
|
603223
605136
|
recordTelegramUserMessage(msg, mode, textOverride) {
|
|
603224
605137
|
const sessionKey = this.sessionKeyForMessage(msg);
|
|
603225
605138
|
const mediaSummary = summarizeTelegramMessageAttachments(msg);
|
|
@@ -603242,6 +605155,7 @@ ${mediaContext}` : ""
|
|
|
603242
605155
|
mediaSummary
|
|
603243
605156
|
};
|
|
603244
605157
|
this.recordChatHistory(sessionKey, entry);
|
|
605158
|
+
this.upsertTelegramReflectionHistoryEntry(sessionKey, entry);
|
|
603245
605159
|
this.updateTelegramParticipantProfile(sessionKey, msg, text);
|
|
603246
605160
|
this.updateTelegramMemoryCards(sessionKey, entry);
|
|
603247
605161
|
try {
|
|
@@ -603261,12 +605175,12 @@ ${mediaContext}` : ""
|
|
|
603261
605175
|
this.saveTelegramConversationState(sessionKey);
|
|
603262
605176
|
}
|
|
603263
605177
|
recordTelegramAssistantMessage(msg, text, mode, options2 = {}) {
|
|
603264
|
-
const
|
|
603265
|
-
if (!
|
|
605178
|
+
const clean5 = stripTelegramHiddenThinking(text).trim();
|
|
605179
|
+
if (!clean5) return;
|
|
603266
605180
|
const sessionKey = this.sessionKeyForMessage(msg);
|
|
603267
605181
|
const entry = {
|
|
603268
605182
|
role: "assistant",
|
|
603269
|
-
text:
|
|
605183
|
+
text: clean5,
|
|
603270
605184
|
mode,
|
|
603271
605185
|
chatId: msg.chatId,
|
|
603272
605186
|
speaker: this.state.botUsername ? `@${this.state.botUsername}` : "Assistant",
|
|
@@ -603277,16 +605191,17 @@ ${mediaContext}` : ""
|
|
|
603277
605191
|
chatTitle: msg.chatTitle
|
|
603278
605192
|
};
|
|
603279
605193
|
this.recordChatHistory(sessionKey, entry);
|
|
605194
|
+
this.upsertTelegramReflectionHistoryEntry(sessionKey, entry);
|
|
603280
605195
|
this.stimulation.recordAgentOutput(sessionKey);
|
|
603281
605196
|
this.updateTelegramMemoryCards(sessionKey, entry);
|
|
603282
605197
|
try {
|
|
603283
605198
|
updateScopedPersonality(this.telegramPersonalityScope(sessionKey, msg), {
|
|
603284
605199
|
speaker: entry.speaker || "Assistant",
|
|
603285
|
-
text:
|
|
605200
|
+
text: clean5,
|
|
603286
605201
|
role: "assistant",
|
|
603287
605202
|
mode,
|
|
603288
605203
|
ts: entry.ts,
|
|
603289
|
-
toneTags: inferTelegramToneTags(
|
|
605204
|
+
toneTags: inferTelegramToneTags(clean5)
|
|
603290
605205
|
});
|
|
603291
605206
|
} catch {
|
|
603292
605207
|
}
|
|
@@ -603354,7 +605269,7 @@ ${mediaContext}` : ""
|
|
|
603354
605269
|
}
|
|
603355
605270
|
const matchingEntry = mediaEntries.find((entry) => {
|
|
603356
605271
|
if (resolve41(entry.localPath) === resolve41(raw)) return true;
|
|
603357
|
-
if (
|
|
605272
|
+
if (basename27(entry.localPath) === raw) return true;
|
|
603358
605273
|
if (entry.fileUniqueId === raw || entry.fileId === raw) return true;
|
|
603359
605274
|
if (entry.messageId && String(entry.messageId) === raw) return true;
|
|
603360
605275
|
return false;
|
|
@@ -603390,7 +605305,7 @@ ${mediaContext}` : ""
|
|
|
603390
605305
|
}
|
|
603391
605306
|
return entries.find((entry2) => {
|
|
603392
605307
|
if (resolve41(entry2.localPath) === resolve41(ref)) return true;
|
|
603393
|
-
if (
|
|
605308
|
+
if (basename27(entry2.localPath) === ref) return true;
|
|
603394
605309
|
if (entry2.fileUniqueId === ref || entry2.fileId === ref) return true;
|
|
603395
605310
|
if (entry2.messageId && String(entry2.messageId) === ref) return true;
|
|
603396
605311
|
return false;
|
|
@@ -603418,7 +605333,7 @@ ${mediaContext}` : ""
|
|
|
603418
605333
|
caption: entry.caption
|
|
603419
605334
|
},
|
|
603420
605335
|
modality,
|
|
603421
|
-
label: `Telegram message_id ${entry.messageId || "unknown"} ${
|
|
605336
|
+
label: `Telegram message_id ${entry.messageId || "unknown"} ${basename27(entry.localPath)}`,
|
|
603422
605337
|
extractedContent: entry.extractedContent
|
|
603423
605338
|
};
|
|
603424
605339
|
}
|
|
@@ -603493,7 +605408,7 @@ ${mediaContext}` : ""
|
|
|
603493
605408
|
const titleTags = tags.slice(0, 4);
|
|
603494
605409
|
const title = titleTags.length > 0 ? `${speaker} / ${titleTags.join(" ")}` : `${speaker} / conversation`;
|
|
603495
605410
|
const card = {
|
|
603496
|
-
id:
|
|
605411
|
+
id: createHash23("sha1").update(`${sessionKey}:${now}:${speaker}:${text}`).digest("hex").slice(0, 12),
|
|
603497
605412
|
title,
|
|
603498
605413
|
notes: [],
|
|
603499
605414
|
tags: [],
|
|
@@ -603624,7 +605539,7 @@ ${cardLines.join("\n")}`);
|
|
|
603624
605539
|
const caption = entry.caption ? ` caption:${truncateTelegramContextLine(entry.caption, 120)}` : "";
|
|
603625
605540
|
const extracted = entry.extractedContent ? `
|
|
603626
605541
|
${truncateTelegramContextLine(entry.extractedContent.replace(/\s+/g, " "), 220)}` : "";
|
|
603627
|
-
return `- message_id ${entry.messageId}${replyMark}: ${kind}; path ${entry.localPath}; file ${
|
|
605542
|
+
return `- message_id ${entry.messageId}${replyMark}: ${kind}; path ${entry.localPath}; file ${basename27(entry.localPath)}${caption}${extracted}`;
|
|
603628
605543
|
});
|
|
603629
605544
|
sections.push([
|
|
603630
605545
|
"### Recent Chat Media",
|
|
@@ -603965,7 +605880,7 @@ ${list}` : "No shared group target is currently known for this sender. Ask in th
|
|
|
603965
605880
|
}
|
|
603966
605881
|
telegramRunnerStateDir(sessionKey) {
|
|
603967
605882
|
if (!this.repoRoot) return void 0;
|
|
603968
|
-
const safe =
|
|
605883
|
+
const safe = createHash23("sha1").update(sessionKey).digest("hex").slice(0, 20);
|
|
603969
605884
|
return join123(this.repoRoot, ".omnius", "telegram-runner-state", safe);
|
|
603970
605885
|
}
|
|
603971
605886
|
buildTelegramAdminOverviewContext(currentSessionKey) {
|
|
@@ -604283,11 +606198,12 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
604283
606198
|
const chunks = splitTelegramMessageText(html, 3900);
|
|
604284
606199
|
if (chunks.length === 0) return null;
|
|
604285
606200
|
const replyToMessageId = msg.chatType !== "private" ? msg.messageId : void 0;
|
|
606201
|
+
const suppressMedia = this.deliveredArtifactMediaSuppressorForMessage(msg);
|
|
604286
606202
|
if (liveMessageId && !msg.guestQueryId) {
|
|
604287
606203
|
const edited = await this.editLiveMessage(msg.chatId, liveMessageId, chunks[0]);
|
|
604288
606204
|
if (edited) {
|
|
604289
606205
|
for (const chunk of chunks.slice(1)) {
|
|
604290
|
-
await this.sendMessageHTML(msg.chatId, chunk);
|
|
606206
|
+
await this.sendMessageHTML(msg.chatId, chunk, void 0, { suppressMedia });
|
|
604291
606207
|
}
|
|
604292
606208
|
return liveMessageId;
|
|
604293
606209
|
}
|
|
@@ -604298,7 +606214,12 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
604298
606214
|
}
|
|
604299
606215
|
let firstMessageId = null;
|
|
604300
606216
|
for (let idx = 0; idx < chunks.length; idx++) {
|
|
604301
|
-
const messageId = await this.sendMessageHTML(
|
|
606217
|
+
const messageId = await this.sendMessageHTML(
|
|
606218
|
+
msg.chatId,
|
|
606219
|
+
chunks[idx],
|
|
606220
|
+
idx === 0 ? replyToMessageId : void 0,
|
|
606221
|
+
{ suppressMedia }
|
|
606222
|
+
);
|
|
604302
606223
|
if (firstMessageId === null) firstMessageId = messageId;
|
|
604303
606224
|
}
|
|
604304
606225
|
return firstMessageId;
|
|
@@ -604325,6 +606246,11 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
604325
606246
|
await this.replyWithTelegramHelp(msg, isAdmin);
|
|
604326
606247
|
return;
|
|
604327
606248
|
}
|
|
606249
|
+
const telegramSlash = this.telegramSlashName(normalizedCommandText);
|
|
606250
|
+
if (msg.text.trim().startsWith("/") && TELEGRAM_REFLECTION_SLASH_COMMANDS.has(telegramSlash)) {
|
|
606251
|
+
await this.handleTelegramReflectionSlash(msg, normalizedCommandText);
|
|
606252
|
+
return;
|
|
606253
|
+
}
|
|
604328
606254
|
if (!this.agentConfig || !this.repoRoot) {
|
|
604329
606255
|
this.onMessage(msg);
|
|
604330
606256
|
return;
|
|
@@ -604332,7 +606258,6 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
604332
606258
|
const toolContext = this.resolveToolContext(msg, isAdmin);
|
|
604333
606259
|
const isAdminDM = toolContext === "telegram-admin-dm";
|
|
604334
606260
|
const sessionKey = this.sessionKeyForMessage(msg);
|
|
604335
|
-
const telegramSlash = this.telegramSlashName(normalizedCommandText);
|
|
604336
606261
|
if (msg.text.trim().startsWith("/") && TELEGRAM_REMINDER_SLASH_COMMANDS.has(telegramSlash)) {
|
|
604337
606262
|
await this.handleTelegramReminderSlash(msg, normalizedCommandText, toolContext);
|
|
604338
606263
|
return;
|
|
@@ -604494,6 +606419,7 @@ Join: ${newUrl}`);
|
|
|
604494
606419
|
creativeWorkspaceRoot: this.creativeWorkspaceRootForMessage(msg, toolContext),
|
|
604495
606420
|
generatedArtifacts: [],
|
|
604496
606421
|
deliveredArtifacts: [],
|
|
606422
|
+
deliveredFileSends: /* @__PURE__ */ new Set(),
|
|
604497
606423
|
surfacedToolCallFingerprints: /* @__PURE__ */ new Set()
|
|
604498
606424
|
};
|
|
604499
606425
|
this.subAgents.set(sessionKey, subAgent);
|
|
@@ -604606,6 +606532,7 @@ Join: ${newUrl}`);
|
|
|
604606
606532
|
creativeWorkspaceRoot: this.creativeWorkspaceRootForMessage(msg, toolContext),
|
|
604607
606533
|
generatedArtifacts: [],
|
|
604608
606534
|
deliveredArtifacts: [],
|
|
606535
|
+
deliveredFileSends: /* @__PURE__ */ new Set(),
|
|
604609
606536
|
surfacedToolCallFingerprints: /* @__PURE__ */ new Set()
|
|
604610
606537
|
};
|
|
604611
606538
|
this.subAgents.set(sessionKey, subAgent);
|
|
@@ -604897,12 +606824,12 @@ ${conversationStream}`
|
|
|
604897
606824
|
}
|
|
604898
606825
|
retainTelegramVisibleReplyDraft(subAgent, draft, streamToolNames = subAgent.currentStreamToolNames) {
|
|
604899
606826
|
if (subAgent.visibleReplyText) return;
|
|
604900
|
-
const
|
|
604901
|
-
if (!
|
|
606827
|
+
const clean5 = cleanTelegramVisibleReply(draft);
|
|
606828
|
+
if (!clean5) return;
|
|
604902
606829
|
const toolNames = [...streamToolNames];
|
|
604903
606830
|
const hasNonCompletionTool = toolNames.some((name10) => name10 !== "task_complete");
|
|
604904
606831
|
if (hasNonCompletionTool) return;
|
|
604905
|
-
subAgent.visibleReplyText =
|
|
606832
|
+
subAgent.visibleReplyText = clean5;
|
|
604906
606833
|
}
|
|
604907
606834
|
retainTelegramVisibleReplyFromCompletedStream(subAgent) {
|
|
604908
606835
|
this.retainTelegramVisibleReplyDraft(
|
|
@@ -605685,6 +607612,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
605685
607612
|
return new IdentityMemoryTool(repoRoot, {
|
|
605686
607613
|
sourceSurface: "telegram",
|
|
605687
607614
|
scope,
|
|
607615
|
+
sessionId: currentMsg ? this.sessionKeyForMessage(currentMsg) : chatId !== void 0 ? `chat:${String(chatId)}` : void 0,
|
|
605688
607616
|
sender: currentMsg ? this.telegramMemorySenderFromMessage(currentMsg) : void 0,
|
|
605689
607617
|
message: message2,
|
|
605690
607618
|
replyTo: currentMsg ? this.telegramMemoryReplyRef(currentMsg) : void 0,
|
|
@@ -605720,7 +607648,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
605720
607648
|
`${index + 1}. message_id ${entry.messageId || "unknown"}`,
|
|
605721
607649
|
currentMsg?.replyToMessageId === entry.messageId ? "replied-to" : "",
|
|
605722
607650
|
telegramCachedMediaIsImage(entry) ? "image" : telegramCachedMediaIsPdf(entry) ? "pdf" : telegramCachedMediaIsAudio(entry) ? "audio" : telegramCachedMediaIsVideo(entry) ? "video" : entry.mediaType,
|
|
605723
|
-
`file=${
|
|
607651
|
+
`file=${basename27(entry.localPath)}`,
|
|
605724
607652
|
`path=${entry.localPath}`,
|
|
605725
607653
|
entry.caption ? `caption=${truncateTelegramContextLine(entry.caption, 140)}` : ""
|
|
605726
607654
|
].filter(Boolean);
|
|
@@ -605823,17 +607751,37 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
605823
607751
|
const kind = normalizeTelegramSendKind(args["kind"], file.path);
|
|
605824
607752
|
const caption = typeof args["caption"] === "string" ? args["caption"].trim().slice(0, 1024) : void 0;
|
|
605825
607753
|
const replyTo = Number(args["reply_to_message_id"]);
|
|
607754
|
+
const replyToMessageId = Number.isFinite(replyTo) && replyTo > 0 ? Math.floor(replyTo) : void 0;
|
|
607755
|
+
const ledgerPath = file.logicalPath ?? file.path;
|
|
607756
|
+
const sendFingerprint = bridge.telegramFileSendFingerprint(
|
|
607757
|
+
target.chatId,
|
|
607758
|
+
ledgerPath,
|
|
607759
|
+
kind,
|
|
607760
|
+
caption,
|
|
607761
|
+
replyToMessageId
|
|
607762
|
+
);
|
|
607763
|
+
if (bridge.telegramFileSendAlreadyDeliveredForMessage(currentMsg, sendFingerprint)) {
|
|
607764
|
+
return {
|
|
607765
|
+
success: true,
|
|
607766
|
+
output: `Telegram file already sent in this turn: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}`,
|
|
607767
|
+
llmContent: `Already sent ${basename27(file.path)} to Telegram as ${kind}; do not send it again.`,
|
|
607768
|
+
durationMs: performance.now() - start2,
|
|
607769
|
+
mutated: false,
|
|
607770
|
+
mutatedFiles: []
|
|
607771
|
+
};
|
|
607772
|
+
}
|
|
605826
607773
|
try {
|
|
605827
607774
|
const messageId = await bridge.sendTelegramFileToChat(target.chatId, file.path, {
|
|
605828
607775
|
kind,
|
|
605829
607776
|
caption: caption || void 0,
|
|
605830
|
-
replyToMessageId
|
|
607777
|
+
replyToMessageId
|
|
605831
607778
|
});
|
|
605832
|
-
bridge.
|
|
607779
|
+
bridge.rememberTelegramFileSendForMessage(currentMsg, sendFingerprint);
|
|
607780
|
+
bridge.rememberTelegramDeliveredArtifactForMessage(currentMsg, ledgerPath);
|
|
605833
607781
|
return {
|
|
605834
607782
|
success: true,
|
|
605835
|
-
output: `Sent Telegram file: ${
|
|
605836
|
-
llmContent: `Sent ${
|
|
607783
|
+
output: `Sent Telegram file: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}${messageId ? ` (message_id ${messageId})` : ""}`,
|
|
607784
|
+
llmContent: `Sent ${basename27(file.path)} to Telegram as ${kind}.`,
|
|
605837
607785
|
durationMs: performance.now() - start2,
|
|
605838
607786
|
mutated: false,
|
|
605839
607787
|
mutatedFiles: []
|
|
@@ -605927,6 +607875,27 @@ ${knownList}` : "Private-user telegram_send_file target must be this DM or a kno
|
|
|
605927
607875
|
if (!subAgent) return;
|
|
605928
607876
|
this.rememberTelegramDeliveredArtifact(subAgent, path11);
|
|
605929
607877
|
}
|
|
607878
|
+
telegramFileSendFingerprint(chatId, path11, kind, caption, replyToMessageId) {
|
|
607879
|
+
return stableTelegramValueKey({
|
|
607880
|
+
chatId: String(chatId),
|
|
607881
|
+
path: resolve41(path11),
|
|
607882
|
+
kind,
|
|
607883
|
+
caption: caption ?? "",
|
|
607884
|
+
replyToMessageId: replyToMessageId ?? null
|
|
607885
|
+
});
|
|
607886
|
+
}
|
|
607887
|
+
telegramFileSendAlreadyDeliveredForMessage(msg, fingerprint) {
|
|
607888
|
+
if (!msg) return false;
|
|
607889
|
+
const subAgent = this.subAgents.get(this.sessionKeyForMessage(msg));
|
|
607890
|
+
return Boolean(subAgent?.deliveredFileSends?.has(fingerprint));
|
|
607891
|
+
}
|
|
607892
|
+
rememberTelegramFileSendForMessage(msg, fingerprint) {
|
|
607893
|
+
if (!msg) return;
|
|
607894
|
+
const subAgent = this.subAgents.get(this.sessionKeyForMessage(msg));
|
|
607895
|
+
if (!subAgent) return;
|
|
607896
|
+
subAgent.deliveredFileSends ??= /* @__PURE__ */ new Set();
|
|
607897
|
+
subAgent.deliveredFileSends.add(fingerprint);
|
|
607898
|
+
}
|
|
605930
607899
|
/** Check if a message is from the admin user (uses fromUserId, NOT chatId) */
|
|
605931
607900
|
isAdminUser(msg) {
|
|
605932
607901
|
if (!this.adminUserId) return false;
|
|
@@ -606039,15 +608008,43 @@ ${visionContext}]`;
|
|
|
606039
608008
|
} else {
|
|
606040
608009
|
description = `[${sourceLabel}image received and saved to ${localPath}${caption ? ` — caption: "${caption}"` : ""}. You can use image_read, ocr, or vision tools to analyze it.]`;
|
|
606041
608010
|
}
|
|
608011
|
+
const ingestPayload = this.telegramMemoryIngestPayload(msg, media, localPath, source, cacheEntry.extractedContent);
|
|
608012
|
+
let visualIdentityContext = "";
|
|
608013
|
+
let ingestReachedDaemon = false;
|
|
606042
608014
|
try {
|
|
606043
|
-
await fetch("http://127.0.0.1:11435/v1/memory/ingest", {
|
|
608015
|
+
const ingestResponse = await fetch("http://127.0.0.1:11435/v1/memory/ingest", {
|
|
606044
608016
|
method: "POST",
|
|
606045
608017
|
headers: { "Content-Type": "application/json" },
|
|
606046
|
-
body: JSON.stringify(
|
|
608018
|
+
body: JSON.stringify(ingestPayload),
|
|
606047
608019
|
signal: AbortSignal.timeout(2e3)
|
|
606048
608020
|
});
|
|
608021
|
+
ingestReachedDaemon = ingestResponse.ok;
|
|
608022
|
+
if (ingestResponse.ok) {
|
|
608023
|
+
const ingested = await ingestResponse.json().catch(() => null);
|
|
608024
|
+
const block = ingested?.visualIdentity?.contextBlock;
|
|
608025
|
+
if (typeof block === "string" && block.trim()) visualIdentityContext = block.trim();
|
|
608026
|
+
}
|
|
606049
608027
|
} catch {
|
|
606050
608028
|
}
|
|
608029
|
+
if (!ingestReachedDaemon && this.repoRoot) {
|
|
608030
|
+
try {
|
|
608031
|
+
const association = await associateVisualIdentityFromImage({
|
|
608032
|
+
repoRoot: this.repoRoot,
|
|
608033
|
+
imagePath: localPath,
|
|
608034
|
+
sourceSurface: "telegram",
|
|
608035
|
+
scope: ingestPayload["scope"],
|
|
608036
|
+
sender: ingestPayload["sender"],
|
|
608037
|
+
message: ingestPayload["message"],
|
|
608038
|
+
replyTo: ingestPayload["replyTo"],
|
|
608039
|
+
sessionId: typeof ingestPayload["sessionId"] === "string" ? ingestPayload["sessionId"] : this.sessionKeyForMessage(msg),
|
|
608040
|
+
media: ingestPayload["media"],
|
|
608041
|
+
extractedContent: cacheEntry.extractedContent
|
|
608042
|
+
});
|
|
608043
|
+
if (association.contextBlock) visualIdentityContext = association.contextBlock;
|
|
608044
|
+
} catch {
|
|
608045
|
+
}
|
|
608046
|
+
}
|
|
608047
|
+
description = appendMediaContextBlock(description, visualIdentityContext);
|
|
606051
608048
|
} else if (type === "audio" || type === "voice") {
|
|
606052
608049
|
let transcription = null;
|
|
606053
608050
|
try {
|
|
@@ -606115,23 +608112,25 @@ ${text}`.trim());
|
|
|
606115
608112
|
}
|
|
606116
608113
|
// ── Message sending ───────────────────────────────────────────────────
|
|
606117
608114
|
/** Send a response back to a Telegram chat (Markdown → HTML conversion) */
|
|
606118
|
-
async sendMessage(chatId, text, replyToMessageId) {
|
|
608115
|
+
async sendMessage(chatId, text, replyToMessageId, options2 = {}) {
|
|
606119
608116
|
const extracted = extractMediaReferences(text);
|
|
608117
|
+
const mediaRefs = this.filterTelegramMediaReferences(extracted.media, options2);
|
|
606120
608118
|
const html = convertMarkdownToTelegramHTML(extracted.text);
|
|
606121
|
-
const msgId = extracted.text.trim() ? await this.sendMessageHTML(chatId, html, replyToMessageId) : null;
|
|
606122
|
-
for (const media of
|
|
608119
|
+
const msgId = extracted.text.trim() ? await this.sendMessageHTML(chatId, html, replyToMessageId, options2) : null;
|
|
608120
|
+
for (const media of mediaRefs) {
|
|
606123
608121
|
await this.sendMediaReference(chatId, media, { replyToMessageId }).catch(() => null);
|
|
606124
608122
|
}
|
|
606125
608123
|
return msgId;
|
|
606126
608124
|
}
|
|
606127
608125
|
/** Send an HTML-formatted message to a Telegram chat */
|
|
606128
|
-
async sendMessageHTML(chatId, html, replyToMessageId) {
|
|
608126
|
+
async sendMessageHTML(chatId, html, replyToMessageId, options2 = {}) {
|
|
606129
608127
|
const extracted = extractMediaReferences(html);
|
|
608128
|
+
const mediaRefs = this.filterTelegramMediaReferences(extracted.media, options2);
|
|
606130
608129
|
const sendHtml = extracted.text || (extracted.media.length > 0 ? "" : html);
|
|
606131
608130
|
let sentId = null;
|
|
606132
608131
|
if (!sendHtml.trim()) {
|
|
606133
|
-
for (let idx = 0; idx <
|
|
606134
|
-
const media =
|
|
608132
|
+
for (let idx = 0; idx < mediaRefs.length; idx++) {
|
|
608133
|
+
const media = mediaRefs[idx];
|
|
606135
608134
|
const mediaId = await this.sendMediaReference(
|
|
606136
608135
|
chatId,
|
|
606137
608136
|
media,
|
|
@@ -606170,11 +608169,24 @@ ${text}`.trim());
|
|
|
606170
608169
|
}
|
|
606171
608170
|
}
|
|
606172
608171
|
}
|
|
606173
|
-
for (const media of
|
|
608172
|
+
for (const media of mediaRefs) {
|
|
606174
608173
|
await this.sendMediaReference(chatId, media).catch(() => null);
|
|
606175
608174
|
}
|
|
606176
608175
|
return sentId;
|
|
606177
608176
|
}
|
|
608177
|
+
filterTelegramMediaReferences(media, options2) {
|
|
608178
|
+
const suppress = options2.suppressMedia;
|
|
608179
|
+
if (!suppress) return media;
|
|
608180
|
+
return media.filter((ref) => !suppress(ref));
|
|
608181
|
+
}
|
|
608182
|
+
deliveredArtifactMediaSuppressorForMessage(msg) {
|
|
608183
|
+
const subAgent = this.subAgents.get(this.sessionKeyForMessage(msg));
|
|
608184
|
+
const delivered = new Set(
|
|
608185
|
+
(subAgent?.deliveredArtifacts ?? []).map((path11) => resolve41(path11))
|
|
608186
|
+
);
|
|
608187
|
+
if (delivered.size === 0) return void 0;
|
|
608188
|
+
return (media) => media.source === "file" && delivered.has(resolve41(media.value));
|
|
608189
|
+
}
|
|
606178
608190
|
async replyToTelegramMessage(msg, text, options2 = {}) {
|
|
606179
608191
|
if (msg.guestQueryId) {
|
|
606180
608192
|
return this.answerGuestQuery(msg.guestQueryId, text, {
|
|
@@ -606221,7 +608233,7 @@ ${text}`.trim());
|
|
|
606221
608233
|
if (!existsSync108(media.value)) throw new Error(`File does not exist: ${media.value}`);
|
|
606222
608234
|
const buffer2 = readFileSync88(media.value);
|
|
606223
608235
|
const boundary = `----omnius-media-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
606224
|
-
const filename =
|
|
608236
|
+
const filename = basename27(media.value);
|
|
606225
608237
|
const contentType = mimeForPath(media.value, media.kind);
|
|
606226
608238
|
const parts = [];
|
|
606227
608239
|
const addField = (name10, value2) => {
|
|
@@ -606326,7 +608338,7 @@ Content-Type: ${contentType}\r
|
|
|
606326
608338
|
continue;
|
|
606327
608339
|
}
|
|
606328
608340
|
const buffer2 = readFileSync88(pathOrFileId);
|
|
606329
|
-
const filename =
|
|
608341
|
+
const filename = basename27(pathOrFileId);
|
|
606330
608342
|
parts.push(Buffer.from(`--${boundary}\r
|
|
606331
608343
|
`));
|
|
606332
608344
|
parts.push(Buffer.from(
|
|
@@ -606356,11 +608368,11 @@ Content-Type: ${mimeForPath(pathOrFileId, field === "photo" ? "image" : "video")
|
|
|
606356
608368
|
* Telegram accepts @botusername in chat_id for the supported bot-to-bot subset.
|
|
606357
608369
|
*/
|
|
606358
608370
|
async sendMessageToBot(username, text) {
|
|
606359
|
-
const
|
|
606360
|
-
if (!/^[A-Za-z0-9_]{5,32}$/.test(
|
|
608371
|
+
const clean5 = username.trim().replace(/^@/, "");
|
|
608372
|
+
if (!/^[A-Za-z0-9_]{5,32}$/.test(clean5)) {
|
|
606361
608373
|
throw new Error("Expected a Telegram bot username (5-32 chars, letters/numbers/underscore).");
|
|
606362
608374
|
}
|
|
606363
|
-
return this.sendMessage(`@${
|
|
608375
|
+
return this.sendMessage(`@${clean5}`, text);
|
|
606364
608376
|
}
|
|
606365
608377
|
async setMyCommands(commands) {
|
|
606366
608378
|
const apiCommands = commands.map((cmd) => ({
|
|
@@ -607390,7 +609402,7 @@ __export(projects_exports, {
|
|
|
607390
609402
|
});
|
|
607391
609403
|
import { readFileSync as readFileSync90, writeFileSync as writeFileSync59, mkdirSync as mkdirSync65, existsSync as existsSync110, statSync as statSync37, renameSync as renameSync6 } from "node:fs";
|
|
607392
609404
|
import { homedir as homedir37 } from "node:os";
|
|
607393
|
-
import { basename as
|
|
609405
|
+
import { basename as basename28, join as join125, resolve as resolve42 } from "node:path";
|
|
607394
609406
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
607395
609407
|
function readAll2() {
|
|
607396
609408
|
try {
|
|
@@ -607438,7 +609450,7 @@ function registerProject(root, pid) {
|
|
|
607438
609450
|
} else {
|
|
607439
609451
|
entry = {
|
|
607440
609452
|
root: canonical,
|
|
607441
|
-
name:
|
|
609453
|
+
name: basename28(canonical) || canonical,
|
|
607442
609454
|
firstSeen: now,
|
|
607443
609455
|
lastSeen: now,
|
|
607444
609456
|
pid: pid ?? null,
|
|
@@ -608164,24 +610176,24 @@ function stripMappedPrefix(ip) {
|
|
|
608164
610176
|
}
|
|
608165
610177
|
function isLoopbackIP(ip) {
|
|
608166
610178
|
if (!ip) return false;
|
|
608167
|
-
const
|
|
608168
|
-
if (
|
|
608169
|
-
if (/^127\./.test(
|
|
610179
|
+
const clean5 = stripMappedPrefix(ip);
|
|
610180
|
+
if (clean5 === "::1") return true;
|
|
610181
|
+
if (/^127\./.test(clean5)) return true;
|
|
608170
610182
|
return false;
|
|
608171
610183
|
}
|
|
608172
610184
|
function isPrivateIP(ip) {
|
|
608173
610185
|
if (!ip) return false;
|
|
608174
|
-
const
|
|
608175
|
-
if (/^10\./.test(
|
|
608176
|
-
if (/^192\.168\./.test(
|
|
608177
|
-
const m2 = /^172\.(\d{1,3})\./.exec(
|
|
610186
|
+
const clean5 = stripMappedPrefix(ip);
|
|
610187
|
+
if (/^10\./.test(clean5)) return true;
|
|
610188
|
+
if (/^192\.168\./.test(clean5)) return true;
|
|
610189
|
+
const m2 = /^172\.(\d{1,3})\./.exec(clean5);
|
|
608178
610190
|
if (m2) {
|
|
608179
610191
|
const second3 = parseInt(m2[1], 10);
|
|
608180
610192
|
if (second3 >= 16 && second3 <= 31) return true;
|
|
608181
610193
|
}
|
|
608182
|
-
if (/^169\.254\./.test(
|
|
608183
|
-
if (/^f[cd][0-9a-f]{2}:/i.test(
|
|
608184
|
-
if (/^fe[89ab][0-9a-f]:/i.test(
|
|
610194
|
+
if (/^169\.254\./.test(clean5)) return true;
|
|
610195
|
+
if (/^f[cd][0-9a-f]{2}:/i.test(clean5)) return true;
|
|
610196
|
+
if (/^fe[89ab][0-9a-f]:/i.test(clean5)) return true;
|
|
608185
610197
|
return false;
|
|
608186
610198
|
}
|
|
608187
610199
|
function isAllowedIP(ip, mode) {
|
|
@@ -608207,14 +610219,14 @@ var init_access_policy = __esm({
|
|
|
608207
610219
|
});
|
|
608208
610220
|
|
|
608209
610221
|
// packages/cli/src/api/project-preferences.ts
|
|
608210
|
-
import { createHash as
|
|
610222
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
608211
610223
|
import { existsSync as existsSync111, mkdirSync as mkdirSync66, readFileSync as readFileSync91, renameSync as renameSync7, writeFileSync as writeFileSync60, unlinkSync as unlinkSync23 } from "node:fs";
|
|
608212
610224
|
import { homedir as homedir38 } from "node:os";
|
|
608213
610225
|
import { join as join126, resolve as resolve43 } from "node:path";
|
|
608214
610226
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
608215
610227
|
function projectKey(root) {
|
|
608216
610228
|
const canonical = resolve43(root);
|
|
608217
|
-
return
|
|
610229
|
+
return createHash24("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
608218
610230
|
}
|
|
608219
610231
|
function projectDir(root) {
|
|
608220
610232
|
return join126(PROJECTS_DIR, projectKey(root));
|
|
@@ -608306,7 +610318,7 @@ __export(voicechat_exports, {
|
|
|
608306
610318
|
VoiceChatSession: () => VoiceChatSession
|
|
608307
610319
|
});
|
|
608308
610320
|
import { EventEmitter as EventEmitter11 } from "node:events";
|
|
608309
|
-
function
|
|
610321
|
+
function clamp019(x) {
|
|
608310
610322
|
return x < 0 ? 0 : x > 1 ? 1 : x;
|
|
608311
610323
|
}
|
|
608312
610324
|
function alnumRatio(s2) {
|
|
@@ -608345,9 +610357,9 @@ function computeSignalFromText(text, confidence2) {
|
|
|
608345
610357
|
else score = 0.15;
|
|
608346
610358
|
score -= repeatingCharPenalty(t2) * 0.4;
|
|
608347
610359
|
if (typeof confidence2 === "number" && !Number.isNaN(confidence2)) {
|
|
608348
|
-
score = 0.7 * score + 0.3 *
|
|
610360
|
+
score = 0.7 * score + 0.3 * clamp019(confidence2);
|
|
608349
610361
|
}
|
|
608350
|
-
return
|
|
610362
|
+
return clamp019(score);
|
|
608351
610363
|
}
|
|
608352
610364
|
function truncateForLog(s2, n2) {
|
|
608353
610365
|
return s2.length <= n2 ? s2 : s2.slice(0, n2 - 1) + "…";
|
|
@@ -608617,7 +610629,7 @@ Rules:
|
|
|
608617
610629
|
}, MAX_SEGMENT_MS);
|
|
608618
610630
|
}
|
|
608619
610631
|
this.captureBuffer = text;
|
|
608620
|
-
this.lastSignalScore = typeof snr === "number" && !Number.isNaN(snr) ?
|
|
610632
|
+
this.lastSignalScore = typeof snr === "number" && !Number.isNaN(snr) ? clamp019(snr) : computeSignalFromText(text, confidence2);
|
|
608621
610633
|
this.emit("snr", { score: this.lastSignalScore });
|
|
608622
610634
|
this.onPartialTranscript(text);
|
|
608623
610635
|
if (this.silenceTimer) clearTimeout(this.silenceTimer);
|
|
@@ -609392,7 +611404,7 @@ var init_disk_task_output = __esm({
|
|
|
609392
611404
|
});
|
|
609393
611405
|
|
|
609394
611406
|
// packages/cli/src/api/http.ts
|
|
609395
|
-
import { createHash as
|
|
611407
|
+
import { createHash as createHash25 } from "node:crypto";
|
|
609396
611408
|
function problemDetails(opts) {
|
|
609397
611409
|
const p2 = {
|
|
609398
611410
|
type: opts.type ?? "about:blank",
|
|
@@ -609455,7 +611467,7 @@ function paginated(items, page2, total) {
|
|
|
609455
611467
|
}
|
|
609456
611468
|
function computeEtag(payload) {
|
|
609457
611469
|
const json = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
609458
|
-
const hash =
|
|
611470
|
+
const hash = createHash25("sha1").update(json).digest("hex").slice(0, 16);
|
|
609459
611471
|
return `W/"${hash}"`;
|
|
609460
611472
|
}
|
|
609461
611473
|
function checkNotModified(req2, res, etag) {
|
|
@@ -616604,13 +618616,20 @@ async function sendMessage() {
|
|
|
616604
618616
|
showStreamingIndicator(msgDiv, 'thinking');
|
|
616605
618617
|
|
|
616606
618618
|
try {
|
|
618619
|
+
const attachmentContextBlock = _attachments.length > 0
|
|
618620
|
+
? await uploadChatAttachments(chatSessionId)
|
|
618621
|
+
: '';
|
|
618622
|
+
|
|
616607
618623
|
// Prepend context files as a FILES block so the agent can read them
|
|
616608
618624
|
// without having to guess paths. The user picked these via right-click
|
|
616609
618625
|
// "Add to context" on the workspace tree.
|
|
616610
618626
|
let messageWithContext = sendText;
|
|
618627
|
+
if (attachmentContextBlock) {
|
|
618628
|
+
messageWithContext = attachmentContextBlock + '\\n\\n' + messageWithContext;
|
|
618629
|
+
}
|
|
616611
618630
|
if (contextFiles.length > 0) {
|
|
616612
618631
|
const filesBlock = 'FILES IN CONTEXT:\\n' + contextFiles.map(p => ' - ' + p).join('\\n') + '\\n\\n';
|
|
616613
|
-
messageWithContext = filesBlock +
|
|
618632
|
+
messageWithContext = filesBlock + messageWithContext;
|
|
616614
618633
|
}
|
|
616615
618634
|
|
|
616616
618635
|
// FRESH-SESSION: pull the one-shot fresh flag the newChatSession()
|
|
@@ -621863,6 +623882,51 @@ function _removeAttachment(i) {
|
|
|
621863
623882
|
_renderAttachChips();
|
|
621864
623883
|
}
|
|
621865
623884
|
|
|
623885
|
+
function _fileToBase64(file) {
|
|
623886
|
+
return new Promise((resolve, reject) => {
|
|
623887
|
+
const reader = new FileReader();
|
|
623888
|
+
reader.onload = () => {
|
|
623889
|
+
const raw = String(reader.result || '');
|
|
623890
|
+
const comma = raw.indexOf(',');
|
|
623891
|
+
resolve(comma >= 0 ? raw.slice(comma + 1) : raw);
|
|
623892
|
+
};
|
|
623893
|
+
reader.onerror = () => reject(reader.error || new Error('file_read_failed'));
|
|
623894
|
+
reader.readAsDataURL(file);
|
|
623895
|
+
});
|
|
623896
|
+
}
|
|
623897
|
+
|
|
623898
|
+
async function uploadChatAttachments(sessionId) {
|
|
623899
|
+
if (!_attachments.length) return '';
|
|
623900
|
+
const blocks = [];
|
|
623901
|
+
for (const attachment of _attachments) {
|
|
623902
|
+
try {
|
|
623903
|
+
const base64 = await _fileToBase64(attachment.file);
|
|
623904
|
+
const response = await fetch('/v1/chat/attachments', {
|
|
623905
|
+
method: 'POST',
|
|
623906
|
+
headers: headers(),
|
|
623907
|
+
body: JSON.stringify({
|
|
623908
|
+
session_id: sessionId || '',
|
|
623909
|
+
filename: attachment.name,
|
|
623910
|
+
mimeType: attachment.file && attachment.file.type ? attachment.file.type : '',
|
|
623911
|
+
base64,
|
|
623912
|
+
}),
|
|
623913
|
+
});
|
|
623914
|
+
if (!response.ok) {
|
|
623915
|
+
blocks.push('GUI attachment failed: ' + attachment.name);
|
|
623916
|
+
continue;
|
|
623917
|
+
}
|
|
623918
|
+
const data = await response.json();
|
|
623919
|
+
blocks.push(data.contextBlock || ('GUI attachment saved: ' + (data.path || attachment.name)));
|
|
623920
|
+
} catch (err) {
|
|
623921
|
+
blocks.push('GUI attachment failed: ' + attachment.name + ' (' + ((err && err.message) ? err.message : String(err)) + ')');
|
|
623922
|
+
}
|
|
623923
|
+
}
|
|
623924
|
+
_attachments = [];
|
|
623925
|
+
_renderAttachChips();
|
|
623926
|
+
if (!blocks.length) return '';
|
|
623927
|
+
return 'GUI ATTACHMENTS:\\n' + blocks.map((block) => String(block).split('\\n').map((line) => ' ' + line).join('\\n')).join('\\n\\n');
|
|
623928
|
+
}
|
|
623929
|
+
|
|
621866
623930
|
// Drag & drop on the input row
|
|
621867
623931
|
(function _wireDropZone() {
|
|
621868
623932
|
const row = document.getElementById('input-row');
|
|
@@ -623458,7 +625522,7 @@ __export(embedding_workers_exports, {
|
|
|
623458
625522
|
startEmbeddingWorkers: () => startEmbeddingWorkers,
|
|
623459
625523
|
stopEmbeddingWorkers: () => stopEmbeddingWorkers
|
|
623460
625524
|
});
|
|
623461
|
-
import { basename as
|
|
625525
|
+
import { basename as basename29, join as join136 } from "node:path";
|
|
623462
625526
|
function startEmbeddingWorkers(opts) {
|
|
623463
625527
|
if (_running) return;
|
|
623464
625528
|
_running = true;
|
|
@@ -623524,7 +625588,7 @@ async function runEmbeddingTask(modality, episodeId, taskId, opts) {
|
|
|
623524
625588
|
try {
|
|
623525
625589
|
if (!_aligner) {
|
|
623526
625590
|
const stateRoot = process.env.OMNIUS_DIR || process.cwd();
|
|
623527
|
-
const omniusDir =
|
|
625591
|
+
const omniusDir = basename29(stateRoot) === ".omnius" ? stateRoot : join136(stateRoot, ".omnius");
|
|
623528
625592
|
const memDir = join136(omniusDir, "memory");
|
|
623529
625593
|
_aligner = new EmbeddingAligner(
|
|
623530
625594
|
`${modality}-${emb.length}`,
|
|
@@ -623645,7 +625709,7 @@ import { homedir as homedir45 } from "node:os";
|
|
|
623645
625709
|
import { spawn as spawn29, execSync as execSync57 } from "node:child_process";
|
|
623646
625710
|
import { mkdirSync as mkdirSync74, writeFileSync as writeFileSync66, readFileSync as readFileSync99, readdirSync as readdirSync42, existsSync as existsSync122, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync25 } from "node:fs";
|
|
623647
625711
|
import { randomBytes as randomBytes24, randomUUID as randomUUID16 } from "node:crypto";
|
|
623648
|
-
import { createHash as
|
|
625712
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
623649
625713
|
function memoryDbPaths3(baseDir = process.cwd()) {
|
|
623650
625714
|
const dir = join137(baseDir, ".omnius");
|
|
623651
625715
|
return {
|
|
@@ -629518,7 +631582,7 @@ function listScheduledTasks() {
|
|
|
629518
631582
|
const schedule = String(t2?.schedule || t2?.cron || t2?.when || "");
|
|
629519
631583
|
const enabled2 = typeof t2?.enabled === "boolean" ? t2.enabled : true;
|
|
629520
631584
|
const realId = typeof t2?.id === "string" && t2.id ? t2.id : null;
|
|
629521
|
-
const fallbackId =
|
|
631585
|
+
const fallbackId = createHash27("sha1").update(`${file}#${i2}`).digest("hex").slice(0, 16);
|
|
629522
631586
|
const uid = realId || fallbackId;
|
|
629523
631587
|
const key = `${uid}`;
|
|
629524
631588
|
if (seen.has(key)) return;
|
|
@@ -629635,8 +631699,8 @@ function deleteScheduledById(id) {
|
|
|
629635
631699
|
if (id) candidates.push(id);
|
|
629636
631700
|
if (typeof entry?.id === "string" && entry.id && !candidates.includes(entry.id)) candidates.push(entry.id);
|
|
629637
631701
|
try {
|
|
629638
|
-
const { createHash:
|
|
629639
|
-
const fallback =
|
|
631702
|
+
const { createHash: createHash28 } = require4("node:crypto");
|
|
631703
|
+
const fallback = createHash28("sha1").update(`${target.file}#${target.index}`).digest("hex").slice(0, 16);
|
|
629640
631704
|
if (!candidates.includes(fallback)) candidates.push(fallback);
|
|
629641
631705
|
} catch {
|
|
629642
631706
|
}
|
|
@@ -630391,6 +632455,10 @@ function startApiServer(options2 = {}) {
|
|
|
630391
632455
|
handleMemoryIngest(req2, res, ollamaUrl);
|
|
630392
632456
|
return;
|
|
630393
632457
|
}
|
|
632458
|
+
if (req2.method === "POST" && url.pathname === "/v1/chat/attachments") {
|
|
632459
|
+
handleChatAttachmentUpload(req2, res);
|
|
632460
|
+
return;
|
|
632461
|
+
}
|
|
630394
632462
|
if (req2.method === "GET" && url.pathname === "/v1/memory/entities") {
|
|
630395
632463
|
handleEntitiesList(req2, res);
|
|
630396
632464
|
return;
|
|
@@ -630948,6 +633016,126 @@ async function handleAudioEmbed(req2, res) {
|
|
|
630948
633016
|
jsonResponse(res, 400, { error: "bad_request", message: err instanceof Error ? err.message : String(err) });
|
|
630949
633017
|
}
|
|
630950
633018
|
}
|
|
633019
|
+
async function handleChatAttachmentUpload(req2, res) {
|
|
633020
|
+
try {
|
|
633021
|
+
const body = await parseJsonBody(req2);
|
|
633022
|
+
if (!body || typeof body !== "object") {
|
|
633023
|
+
jsonResponse(res, 400, { error: "bad_request" });
|
|
633024
|
+
return;
|
|
633025
|
+
}
|
|
633026
|
+
const b = body;
|
|
633027
|
+
const filename = typeof b.filename === "string" && b.filename.trim() ? b.filename.trim() : `attachment-${Date.now()}.bin`;
|
|
633028
|
+
const base642 = typeof b.base64 === "string" ? b.base64 : "";
|
|
633029
|
+
if (!base642) {
|
|
633030
|
+
jsonResponse(res, 400, { error: "missing_base64" });
|
|
633031
|
+
return;
|
|
633032
|
+
}
|
|
633033
|
+
const safeName2 = filename.replace(/[^a-zA-Z0-9._-]/g, "-").slice(0, 180) || `attachment-${Date.now()}.bin`;
|
|
633034
|
+
const dir = join137(process.cwd(), ".omnius", "gui-attachments");
|
|
633035
|
+
mkdirSync74(dir, { recursive: true });
|
|
633036
|
+
const localPath = join137(dir, `${Date.now()}-${randomUUID16().slice(0, 8)}-${safeName2}`);
|
|
633037
|
+
writeFileSync66(localPath, Buffer.from(base642, "base64"));
|
|
633038
|
+
const mimeType = typeof b.mimeType === "string" ? b.mimeType : typeof b.mime_type === "string" ? b.mime_type : "";
|
|
633039
|
+
const isImage = mimeType.toLowerCase().startsWith("image/") || /\.(png|jpe?g|gif|webp|bmp|tiff?)$/i.test(safeName2);
|
|
633040
|
+
const sessionId = typeof b.sessionId === "string" ? b.sessionId : typeof b.session_id === "string" ? b.session_id : void 0;
|
|
633041
|
+
const scope = typeof b.scope === "object" && b.scope ? b.scope : { kind: "gui", id: sessionId || "web", title: "GUI session" };
|
|
633042
|
+
const sender = typeof b.sender === "object" && b.sender ? b.sender : { id: "gui-user", displayName: "GUI user" };
|
|
633043
|
+
const message2 = {
|
|
633044
|
+
id: typeof b.message_id === "string" || typeof b.message_id === "number" ? b.message_id : `attachment:${randomUUID16()}`,
|
|
633045
|
+
timestamp: Date.now(),
|
|
633046
|
+
text: typeof b.caption === "string" && b.caption.trim() ? b.caption.trim() : `GUI attachment: ${safeName2}`
|
|
633047
|
+
};
|
|
633048
|
+
const media = {
|
|
633049
|
+
path: localPath,
|
|
633050
|
+
mediaType: isImage ? "photo" : "document",
|
|
633051
|
+
mimeType: mimeType || void 0,
|
|
633052
|
+
caption: typeof b.caption === "string" ? b.caption : void 0
|
|
633053
|
+
};
|
|
633054
|
+
const modality = isImage ? "visual" : "text";
|
|
633055
|
+
const { EpisodeStore: EpisodeStore3, TemporalGraph: TemporalGraph3, MultimodalIdentityService: MultimodalIdentityService2 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
633056
|
+
const dbPaths = memoryDbPaths3(process.cwd());
|
|
633057
|
+
const graph = new TemporalGraph3(dbPaths.knowledge);
|
|
633058
|
+
const store2 = new EpisodeStore3(dbPaths.episodes, graph);
|
|
633059
|
+
let ingestId = "";
|
|
633060
|
+
try {
|
|
633061
|
+
const embeddings = {};
|
|
633062
|
+
if (isImage) {
|
|
633063
|
+
try {
|
|
633064
|
+
const provider = globalThis.__omniusVisionProvider;
|
|
633065
|
+
const emb = provider ? await provider({ path: localPath }) : null;
|
|
633066
|
+
if (emb) embeddings.imageClip = emb;
|
|
633067
|
+
} catch {
|
|
633068
|
+
}
|
|
633069
|
+
}
|
|
633070
|
+
const service = new MultimodalIdentityService2({ episodeStore: store2, graph });
|
|
633071
|
+
ingestId = service.ingest({
|
|
633072
|
+
sourceSurface: "gui",
|
|
633073
|
+
sessionId,
|
|
633074
|
+
scope,
|
|
633075
|
+
sender,
|
|
633076
|
+
message: message2,
|
|
633077
|
+
modality,
|
|
633078
|
+
content: `GUI attachment: ${safeName2}`,
|
|
633079
|
+
media,
|
|
633080
|
+
labels: [safeName2, typeof b.caption === "string" ? b.caption : ""].filter(Boolean),
|
|
633081
|
+
embeddings
|
|
633082
|
+
}).episodeId;
|
|
633083
|
+
} finally {
|
|
633084
|
+
store2.close();
|
|
633085
|
+
graph.close();
|
|
633086
|
+
}
|
|
633087
|
+
let visualIdentity = void 0;
|
|
633088
|
+
let contextBlock = [
|
|
633089
|
+
`GUI attachment saved: ${safeName2}`,
|
|
633090
|
+
`path: ${localPath}`,
|
|
633091
|
+
mimeType ? `mime_type: ${mimeType}` : ""
|
|
633092
|
+
].filter(Boolean).join("\n");
|
|
633093
|
+
if (isImage) {
|
|
633094
|
+
try {
|
|
633095
|
+
const { associateVisualIdentityFromImage: associateVisualIdentityFromImage2 } = await Promise.resolve().then(() => (init_visual_identity_association(), visual_identity_association_exports));
|
|
633096
|
+
const association = await associateVisualIdentityFromImage2({
|
|
633097
|
+
repoRoot: process.cwd(),
|
|
633098
|
+
imagePath: localPath,
|
|
633099
|
+
sourceSurface: "gui",
|
|
633100
|
+
scope,
|
|
633101
|
+
sender,
|
|
633102
|
+
message: message2,
|
|
633103
|
+
sessionId,
|
|
633104
|
+
media
|
|
633105
|
+
});
|
|
633106
|
+
visualIdentity = {
|
|
633107
|
+
matches: association.matches,
|
|
633108
|
+
recalledEpisodes: association.recalledEpisodes,
|
|
633109
|
+
committedEpisodeIds: association.committedEpisodeIds,
|
|
633110
|
+
contextBlock: association.contextBlock,
|
|
633111
|
+
degradedReason: association.degradedReason
|
|
633112
|
+
};
|
|
633113
|
+
if (association.contextBlock) contextBlock += `
|
|
633114
|
+
|
|
633115
|
+
${association.contextBlock}`;
|
|
633116
|
+
} catch (err) {
|
|
633117
|
+
visualIdentity = {
|
|
633118
|
+
matches: [],
|
|
633119
|
+
recalledEpisodes: [],
|
|
633120
|
+
committedEpisodeIds: [],
|
|
633121
|
+
contextBlock: "",
|
|
633122
|
+
degradedReason: err instanceof Error ? err.message : String(err)
|
|
633123
|
+
};
|
|
633124
|
+
}
|
|
633125
|
+
}
|
|
633126
|
+
jsonResponse(res, 200, {
|
|
633127
|
+
id: ingestId,
|
|
633128
|
+
path: localPath,
|
|
633129
|
+
filename: safeName2,
|
|
633130
|
+
mimeType,
|
|
633131
|
+
modality,
|
|
633132
|
+
contextBlock,
|
|
633133
|
+
visualIdentity
|
|
633134
|
+
});
|
|
633135
|
+
} catch (err) {
|
|
633136
|
+
jsonResponse(res, 400, { error: "bad_request", message: err instanceof Error ? err.message : String(err) });
|
|
633137
|
+
}
|
|
633138
|
+
}
|
|
630951
633139
|
async function handleMemoryIngest(req2, res, ollamaUrl) {
|
|
630952
633140
|
try {
|
|
630953
633141
|
const body = await parseJsonBody(req2);
|
|
@@ -630971,6 +633159,7 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
|
|
|
630971
633159
|
};
|
|
630972
633160
|
const media = Object.values(rawMedia).some((value2) => value2 != null && String(value2).trim() !== "") ? rawMedia : void 0;
|
|
630973
633161
|
const sourceSurface = String(b.sourceSurface || b.source_surface || "api");
|
|
633162
|
+
const sessionId = typeof b.sessionId === "string" ? b.sessionId : typeof b.session_id === "string" ? b.session_id : void 0;
|
|
630974
633163
|
const scope = typeof b.scope === "object" && b.scope ? b.scope : {
|
|
630975
633164
|
kind: b.scope_kind || (b.chat_type === "private" ? "private" : b.chat_id ? "group" : "global"),
|
|
630976
633165
|
id: String(b.scope_id || b.chat_id || sourceSurface),
|
|
@@ -631026,6 +633215,7 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
|
|
|
631026
633215
|
const service = new MultimodalIdentityService2({ episodeStore: epStore, graph: kg });
|
|
631027
633216
|
const result = service.ingest({
|
|
631028
633217
|
sourceSurface,
|
|
633218
|
+
sessionId,
|
|
631029
633219
|
scope,
|
|
631030
633220
|
sender,
|
|
631031
633221
|
message: message2,
|
|
@@ -631039,7 +633229,42 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
|
|
|
631039
633229
|
identityAssertions,
|
|
631040
633230
|
embeddings
|
|
631041
633231
|
});
|
|
631042
|
-
|
|
633232
|
+
let visualIdentity = void 0;
|
|
633233
|
+
if (modality === "visual" && mediaPath) {
|
|
633234
|
+
try {
|
|
633235
|
+
const { associateVisualIdentityFromImage: associateVisualIdentityFromImage2 } = await Promise.resolve().then(() => (init_visual_identity_association(), visual_identity_association_exports));
|
|
633236
|
+
const association = await associateVisualIdentityFromImage2({
|
|
633237
|
+
repoRoot: process.cwd(),
|
|
633238
|
+
imagePath: mediaPath,
|
|
633239
|
+
sourceSurface,
|
|
633240
|
+
scope,
|
|
633241
|
+
sender,
|
|
633242
|
+
message: message2,
|
|
633243
|
+
replyTo,
|
|
633244
|
+
sessionId,
|
|
633245
|
+
media,
|
|
633246
|
+
extractedContent: b.extracted_content || b.extractedContent,
|
|
633247
|
+
threshold: typeof b.threshold === "number" ? b.threshold : 0.5,
|
|
633248
|
+
limit: typeof b.limit === "number" ? b.limit : 5
|
|
633249
|
+
});
|
|
633250
|
+
visualIdentity = {
|
|
633251
|
+
matches: association.matches,
|
|
633252
|
+
recalledEpisodes: association.recalledEpisodes,
|
|
633253
|
+
committedEpisodeIds: association.committedEpisodeIds,
|
|
633254
|
+
contextBlock: association.contextBlock,
|
|
633255
|
+
degradedReason: association.degradedReason
|
|
633256
|
+
};
|
|
633257
|
+
} catch (err) {
|
|
633258
|
+
visualIdentity = {
|
|
633259
|
+
matches: [],
|
|
633260
|
+
recalledEpisodes: [],
|
|
633261
|
+
committedEpisodeIds: [],
|
|
633262
|
+
contextBlock: "",
|
|
633263
|
+
degradedReason: err instanceof Error ? err.message : String(err)
|
|
633264
|
+
};
|
|
633265
|
+
}
|
|
633266
|
+
}
|
|
633267
|
+
jsonResponse(res, 200, { id: result.episodeId, ...result, visualIdentity });
|
|
631043
633268
|
} catch (err) {
|
|
631044
633269
|
jsonResponse(res, 400, { error: "bad_request", message: err instanceof Error ? err.message : String(err) });
|
|
631045
633270
|
}
|
|
@@ -631690,6 +633915,7 @@ function buildSubAgentTools(repoRoot, config) {
|
|
|
631690
633915
|
id: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
631691
633916
|
title: "TUI session"
|
|
631692
633917
|
},
|
|
633918
|
+
sessionId: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
631693
633919
|
sender: { id: "local-user", displayName: "User" }
|
|
631694
633920
|
}),
|
|
631695
633921
|
new VideoUnderstandTool(repoRoot),
|
|
@@ -631842,6 +634068,7 @@ function buildTools(repoRoot, config, contextWindowSize, modelTier) {
|
|
|
631842
634068
|
id: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
631843
634069
|
title: "TUI session"
|
|
631844
634070
|
},
|
|
634071
|
+
sessionId: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
631845
634072
|
sender: { id: "local-user", displayName: "User" }
|
|
631846
634073
|
}),
|
|
631847
634074
|
new AsrListenTool(),
|
|
@@ -636637,8 +638864,28 @@ Log: ${nexusLogPath}`)
|
|
|
636637
638864
|
visionContext = formatImageContextPrefix2(ingressResult);
|
|
636638
638865
|
} catch {
|
|
636639
638866
|
}
|
|
638867
|
+
let visualIdentityContext = "";
|
|
638868
|
+
try {
|
|
638869
|
+
const association = await associateVisualIdentityFromImage({
|
|
638870
|
+
repoRoot,
|
|
638871
|
+
imagePath: pasted.path,
|
|
638872
|
+
sourceSurface: "tui",
|
|
638873
|
+
scope: {
|
|
638874
|
+
kind: "terminal",
|
|
638875
|
+
id: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
638876
|
+
title: "TUI session"
|
|
638877
|
+
},
|
|
638878
|
+
sender: { id: "local-user", displayName: "User" },
|
|
638879
|
+
message: { timestamp: Date.now(), text: "User pasted a clipboard image." },
|
|
638880
|
+
sessionId: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
638881
|
+
media: { path: pasted.path, mediaType: "photo", mimeType: pasted.mime },
|
|
638882
|
+
extractedContent: visionContext
|
|
638883
|
+
});
|
|
638884
|
+
visualIdentityContext = association.contextBlock;
|
|
638885
|
+
} catch {
|
|
638886
|
+
}
|
|
636640
638887
|
const asciiContext = await asciiContextPromise;
|
|
636641
|
-
const imageContext = [visionContext, asciiContext].filter(Boolean).join("\n\n");
|
|
638888
|
+
const imageContext = [visionContext, visualIdentityContext, asciiContext].filter(Boolean).join("\n\n");
|
|
636642
638889
|
if (activeTask) {
|
|
636643
638890
|
activeTask.runner.injectImage(
|
|
636644
638891
|
pasted.buffer.toString("base64"),
|
|
@@ -636966,6 +639213,17 @@ The user pasted a clipboard image saved at ${relPath}. Use the OCR, vision analy
|
|
|
636966
639213
|
},
|
|
636967
639214
|
// Telegram bridge
|
|
636968
639215
|
async telegramStart(token, adminId) {
|
|
639216
|
+
if (telegramBridge?.isActive) {
|
|
639217
|
+
writeContent(
|
|
639218
|
+
() => renderWarning("Telegram bridge already active. Use /telegram stop before restarting.")
|
|
639219
|
+
);
|
|
639220
|
+
showPrompt();
|
|
639221
|
+
return;
|
|
639222
|
+
}
|
|
639223
|
+
if (telegramBridge) {
|
|
639224
|
+
telegramBridge.stop();
|
|
639225
|
+
telegramBridge = null;
|
|
639226
|
+
}
|
|
636969
639227
|
telegramBridge = new TelegramBridge(
|
|
636970
639228
|
token,
|
|
636971
639229
|
(msg) => {
|
|
@@ -637094,9 +639352,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
637094
639352
|
return `Skill invoked: ${result.name}`;
|
|
637095
639353
|
}
|
|
637096
639354
|
const raw = captured.join("");
|
|
637097
|
-
const
|
|
637098
|
-
if (!
|
|
637099
|
-
return
|
|
639355
|
+
const clean5 = raw.replace(/\x1B\[[0-9;]*[A-Za-z]/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B[()][A-Z0-9]/g, "").replace(/\x1B\[?\??[0-9;]*[a-zA-Z]/g, "").replace(/\x1B/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐]/g, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
639356
|
+
if (!clean5) return null;
|
|
639357
|
+
return clean5.length > 3900 ? clean5.slice(0, 3900) + "\n..." : clean5;
|
|
637100
639358
|
} catch (err) {
|
|
637101
639359
|
process.stdout.write = origWrite;
|
|
637102
639360
|
throw err;
|
|
@@ -638806,12 +641064,32 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
638806
641064
|
"Shared image",
|
|
638807
641065
|
writeContent
|
|
638808
641066
|
);
|
|
641067
|
+
let visualIdentityContext = "";
|
|
641068
|
+
try {
|
|
641069
|
+
const association = await associateVisualIdentityFromImage({
|
|
641070
|
+
repoRoot,
|
|
641071
|
+
imagePath: imgPath,
|
|
641072
|
+
sourceSurface: "tui",
|
|
641073
|
+
scope: {
|
|
641074
|
+
kind: "terminal",
|
|
641075
|
+
id: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
641076
|
+
title: "TUI session"
|
|
641077
|
+
},
|
|
641078
|
+
sender: { id: "local-user", displayName: "User" },
|
|
641079
|
+
message: { timestamp: Date.now(), text: `User shared image: ${cleanPath}` },
|
|
641080
|
+
sessionId: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
641081
|
+
media: { path: imgPath, mediaType: "photo", mimeType: mime }
|
|
641082
|
+
});
|
|
641083
|
+
visualIdentityContext = association.contextBlock;
|
|
641084
|
+
} catch {
|
|
641085
|
+
}
|
|
641086
|
+
const combinedImageContext = [asciiContext, visualIdentityContext].filter(Boolean).join("\n\n");
|
|
638809
641087
|
activeTask.runner.injectImage(
|
|
638810
641088
|
base642,
|
|
638811
641089
|
mime,
|
|
638812
|
-
|
|
641090
|
+
combinedImageContext ? `User shared image: ${cleanPath}
|
|
638813
641091
|
|
|
638814
|
-
${
|
|
641092
|
+
${combinedImageContext}` : `User shared image: ${cleanPath}`
|
|
638815
641093
|
);
|
|
638816
641094
|
writeContent(() => renderUserInterrupt(`[Image: ${cleanPath}]`));
|
|
638817
641095
|
} catch {
|
|
@@ -638960,15 +641238,38 @@ ${result.text}`;
|
|
|
638960
641238
|
}
|
|
638961
641239
|
let fullInput = input;
|
|
638962
641240
|
if (isImage && fullInput === input) {
|
|
641241
|
+
const imgPath = resolve46(repoRoot, cleanPath);
|
|
638963
641242
|
const asciiContext = await renderAsciiPreviewForImage(
|
|
638964
|
-
|
|
641243
|
+
imgPath,
|
|
638965
641244
|
cleanPath,
|
|
638966
641245
|
"Image context",
|
|
638967
641246
|
writeContent
|
|
638968
641247
|
);
|
|
638969
|
-
|
|
641248
|
+
let visualIdentityContext = "";
|
|
641249
|
+
try {
|
|
641250
|
+
const ext = extname17(cleanPath).toLowerCase();
|
|
641251
|
+
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
641252
|
+
const association = await associateVisualIdentityFromImage({
|
|
641253
|
+
repoRoot,
|
|
641254
|
+
imagePath: imgPath,
|
|
641255
|
+
sourceSurface: "tui",
|
|
641256
|
+
scope: {
|
|
641257
|
+
kind: "terminal",
|
|
641258
|
+
id: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
641259
|
+
title: "TUI session"
|
|
641260
|
+
},
|
|
641261
|
+
sender: { id: "local-user", displayName: "User" },
|
|
641262
|
+
message: { timestamp: Date.now(), text: `User provided image file: ${cleanPath}` },
|
|
641263
|
+
sessionId: process.env["OMNIUS_SESSION_ID"] || "terminal",
|
|
641264
|
+
media: { path: imgPath, mediaType: "photo", mimeType: mime }
|
|
641265
|
+
});
|
|
641266
|
+
visualIdentityContext = association.contextBlock;
|
|
641267
|
+
} catch {
|
|
641268
|
+
}
|
|
641269
|
+
const imageContext = [asciiContext, visualIdentityContext].filter(Boolean).join("\n\n");
|
|
641270
|
+
fullInput = imageContext ? `The user has provided an image file: ${cleanPath}.
|
|
638970
641271
|
|
|
638971
|
-
${
|
|
641272
|
+
${imageContext}
|
|
638972
641273
|
|
|
638973
641274
|
Read it with image_read or vision if more detail is needed. Describe what you see and extract any text with OCR if relevant.` : `The user has provided an image file: ${cleanPath}. Read it with image_read and describe what you see. Extract any text with OCR if relevant.`;
|
|
638974
641275
|
}
|
|
@@ -639168,13 +641469,13 @@ NEW TASK: ${fullInput}`;
|
|
|
639168
641469
|
writeContent(() => renderError(errMsg));
|
|
639169
641470
|
if (failureStore) {
|
|
639170
641471
|
try {
|
|
639171
|
-
const { createHash:
|
|
641472
|
+
const { createHash: createHash28 } = await import("node:crypto");
|
|
639172
641473
|
failureStore.insert({
|
|
639173
641474
|
taskId: "",
|
|
639174
641475
|
sessionId: `${Date.now()}`,
|
|
639175
641476
|
repoRoot,
|
|
639176
641477
|
failureType: "runtime-error",
|
|
639177
|
-
fingerprint:
|
|
641478
|
+
fingerprint: createHash28("sha256").update(errMsg.slice(0, 200)).digest("hex").slice(0, 16),
|
|
639178
641479
|
filePath: null,
|
|
639179
641480
|
errorMessage: errMsg.slice(0, 500),
|
|
639180
641481
|
context: null,
|
|
@@ -639922,6 +642223,7 @@ var init_interactive = __esm({
|
|
|
639922
642223
|
init_model_picker();
|
|
639923
642224
|
init_project_context();
|
|
639924
642225
|
init_identity_memory_tool();
|
|
642226
|
+
init_visual_identity_association();
|
|
639925
642227
|
init_dist7();
|
|
639926
642228
|
init_omnius_directory();
|
|
639927
642229
|
init_render();
|