@bendyline/gezel-service 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/gezeld.js +781 -251
- package/dist/handboek-content/whats-new/1.26226.md +89 -0
- package/dist/index.d.ts +64 -11
- package/dist/index.js +781 -251
- package/dist/memory/embed-worker.js +22 -3
- package/dist/ui/assets/{TerminalCodeEditor-CXspNipu.js → TerminalCodeEditor-C_Mvaxqz.js} +2 -2
- package/dist/ui/assets/{_.contribution-Bi8h5rS7.js → _.contribution-fOcpgyNy.js} +1 -1
- package/dist/ui/assets/{chunk-6N2J7C2B-Du7clJkV.js → chunk-6N2J7C2B-BNHR_rFP.js} +1 -1
- package/dist/ui/assets/chunk-ILCJ3WFD-CUnKgI_I.js +4 -0
- package/dist/ui/assets/chunk-S5PCVMKU-i2wfHmvU.js +6 -0
- package/dist/ui/assets/{chunk-WATAOG4Y-BnCgSncI.js → chunk-WATAOG4Y-BbL-tDgQ.js} +1 -1
- package/dist/ui/assets/{cpp.contribution-CIgWElWw.js → cpp.contribution-Cx5HvoW7.js} +1 -1
- package/dist/ui/assets/{csharp.contribution-DDiJzXzB.js → csharp.contribution-DMuCSvzf.js} +1 -1
- package/dist/ui/assets/{css.contribution-Dc5E_mNx.js → css.contribution-BPXcRoVK.js} +1 -1
- package/dist/ui/assets/{cssMode-BN_VZB6O.js → cssMode-BHAnHChA.js} +1 -1
- package/dist/ui/assets/{dist-D4PZf1Q3.js → dist-DRDFuw7G.js} +2 -2
- package/dist/ui/assets/dist-DYn91eSO.js +2 -0
- package/dist/ui/assets/{dockerfile.contribution-BQsaSuAJ.js → dockerfile.contribution-DQAHazBI.js} +1 -1
- package/dist/ui/assets/docx-BEJpkI6I.js +2 -0
- package/dist/ui/assets/extract-UTAOG7LV-BY3SCkzz.js +1 -0
- package/dist/ui/assets/{go.contribution-CPvqBST7.js → go.contribution-Jq5pYI7r.js} +1 -1
- package/dist/ui/assets/{handlebars-DJvRMy-I.js → handlebars-BWC7ZXbe.js} +1 -1
- package/dist/ui/assets/handlebars.contribution-BSmxDPeT.js +2 -0
- package/dist/ui/assets/{html-Becff5XU.js → html-BzC9B_Os.js} +1 -1
- package/dist/ui/assets/html.contribution-CEvtdKHG.js +2 -0
- package/dist/ui/assets/{htmlMode-BFmyC6t-.js → htmlMode-1qtmM5J4.js} +1 -1
- package/dist/ui/assets/{index-w_CaRVtV.js → index-JGn32C5f.js} +177 -172
- package/dist/ui/assets/infer-D6e75m-s.js +2 -0
- package/dist/ui/assets/{ini.contribution-DFSSA0eY.js → ini.contribution-BQpzdQzE.js} +1 -1
- package/dist/ui/assets/{java.contribution-Bdvvskrf.js → java.contribution-r3T-8LYE.js} +1 -1
- package/dist/ui/assets/{javascript-DByfaclN.js → javascript-DlipM3VT.js} +1 -1
- package/dist/ui/assets/javascript.contribution-D4MU3K0o.js +2 -0
- package/dist/ui/assets/{jsonMode-CxkV6dJT.js → jsonMode-DSXTaEG9.js} +1 -1
- package/dist/ui/assets/{kotlin.contribution-D8eqi2Fi.js → kotlin.contribution-NI_YvQPr.js} +1 -1
- package/dist/ui/assets/layouts-2A7QNF6Y-CWQp8HDd.js +1 -0
- package/dist/ui/assets/{less.contribution-DFRb86Ld.js → less.contribution-BDz7g6GS.js} +1 -1
- package/dist/ui/assets/{lua.contribution-BgktkcsF.js → lua.contribution-Cr_f17YF.js} +1 -1
- package/dist/ui/assets/{markdown.contribution-BKqBKD_g.js → markdown.contribution-CeJFrLN_.js} +1 -1
- package/dist/ui/assets/{monaco-CyhM025v.js → monaco-Bv9TxWl_.js} +3 -3
- package/dist/ui/assets/{monaco-base-hW9ht_BG.js → monaco-base-DD1Wr24S.js} +1 -1
- package/dist/ui/assets/{monaco-setup-Cquhh1OE.js → monaco-setup-CSa3_fbr.js} +1 -1
- package/dist/ui/assets/{monaco.contribution-Cle0Lbgx.js → monaco.contribution-DKCJArGP.js} +2 -2
- package/dist/ui/assets/{monaco.contribution-BVrZ1Anc.js → monaco.contribution-QFH9z5g8.js} +2 -2
- package/dist/ui/assets/{monaco.contribution-D9-bPyBf.js → monaco.contribution-ZD-wInG3.js} +2 -2
- package/dist/ui/assets/{monaco.contribution-Dl8lHLi5.js → monaco.contribution-tTvEzZ5l.js} +2 -2
- package/dist/ui/assets/{php.contribution-CcYxMawn.js → php.contribution-B310cs3S.js} +1 -1
- package/dist/ui/assets/pptx-DZdEoDP9.js +6 -0
- package/dist/ui/assets/{python-DivQov6J.js → python-CcCNDnkj.js} +1 -1
- package/dist/ui/assets/python.contribution-ZHL594qQ.js +2 -0
- package/dist/ui/assets/{ruby.contribution-DNudSRrU.js → ruby.contribution-CRsX2xPw.js} +1 -1
- package/dist/ui/assets/{rust.contribution-BqG2lQpP.js → rust.contribution-CfwWiQxD.js} +1 -1
- package/dist/ui/assets/{scss.contribution-DDxPnF-K.js → scss.contribution-CJaLNKeq.js} +1 -1
- package/dist/ui/assets/{shell.contribution-Q7wVL7zv.js → shell.contribution-DLPinQHD.js} +1 -1
- package/dist/ui/assets/{sql.contribution-B9ndj3QH.js → sql.contribution-DsZSLfVg.js} +1 -1
- package/dist/ui/assets/{swift.contribution-D_FDdL6S.js → swift.contribution-DFBOOFKs.js} +1 -1
- package/dist/ui/assets/{terminal-monaco-setup-BdF0mUfG.js → terminal-monaco-setup-B8Xv2NV9.js} +1 -1
- package/dist/ui/assets/{tsMode-JVR2Jo5q.js → tsMode-DqT2Dz4k.js} +1 -1
- package/dist/ui/assets/{typescript-1ZOjdUnd.js → typescript-_R5MS0Lp.js} +1 -1
- package/dist/ui/assets/typescript.contribution-CHnXQvfG.js +2 -0
- package/dist/ui/assets/xlsx-DDBRN-IU.js +4 -0
- package/dist/ui/assets/{xml-DrdFGpo2.js → xml-CQVIKNxb.js} +1 -1
- package/dist/ui/assets/xml.contribution-HY4GvlWC.js +2 -0
- package/dist/ui/assets/{yaml-DYQPB5Mj.js → yaml-Nt3uLkWC.js} +1 -1
- package/dist/ui/assets/yaml.contribution-C7dllTyY.js +2 -0
- package/dist/ui/index.html +10 -10
- package/package.json +12 -11
- package/dist/ui/assets/chunk-ILCJ3WFD-fHFoZ9wm.js +0 -4
- package/dist/ui/assets/chunk-S5PCVMKU-DopU3Q9j.js +0 -6
- package/dist/ui/assets/dist-BwDZUtiH.js +0 -2
- package/dist/ui/assets/docx-IZY6hX8A.js +0 -2
- package/dist/ui/assets/extract-UTAOG7LV-BZ_L7lLL.js +0 -1
- package/dist/ui/assets/handlebars.contribution-BNbstxN6.js +0 -2
- package/dist/ui/assets/html.contribution-CPDzzJ0M.js +0 -2
- package/dist/ui/assets/infer-v-bCXeT9.js +0 -2
- package/dist/ui/assets/javascript.contribution-CPCuprn0.js +0 -2
- package/dist/ui/assets/layouts-2A7QNF6Y-D94iKLLQ.js +0 -1
- package/dist/ui/assets/pptx-CsdVR0xn.js +0 -6
- package/dist/ui/assets/python.contribution-CiRaN0sm.js +0 -2
- package/dist/ui/assets/typescript.contribution-_s-8TvIE.js +0 -2
- package/dist/ui/assets/xlsx-CdLmEC42.js +0 -4
- package/dist/ui/assets/xml.contribution-DUPYAKAC.js +0 -2
- package/dist/ui/assets/yaml.contribution-CRBo99nF.js +0 -2
package/dist/index.js
CHANGED
|
@@ -320,6 +320,13 @@ function queryInstruction() {
|
|
|
320
320
|
if (/bge-/i.test(model)) return "Represent this sentence for searching relevant passages: ";
|
|
321
321
|
return "";
|
|
322
322
|
}
|
|
323
|
+
function isRetryablePipelineLoadFailure(error) {
|
|
324
|
+
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
325
|
+
const code = error?.code ?? "";
|
|
326
|
+
return /(?:ECONNRESET|ECONNREFUSED|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|UND_ERR_|fetch failed|network(?: request)? failed|socket hang up|timed?\s*out|HTTP\s+(?:408|425|429|5\d\d)|TLS|SSL|certificate)/i.test(
|
|
327
|
+
`${code} ${message}`
|
|
328
|
+
);
|
|
329
|
+
}
|
|
323
330
|
async function loadPipeline() {
|
|
324
331
|
if (!pipelinePromise) {
|
|
325
332
|
pipelinePromise = (async () => {
|
|
@@ -333,7 +340,11 @@ async function loadPipeline() {
|
|
|
333
340
|
} catch (err) {
|
|
334
341
|
const missing = isMissingModule(err, TRANSFORMERS_MODULE);
|
|
335
342
|
const message = missing ? "Local memory embeddings are an optional npm feature. Install @huggingface/transformers@^3.8.1 alongside @bendyline/gezel-service (see the service README)." : err instanceof Error ? err.message : String(err);
|
|
336
|
-
throw new PipelineLoadError(
|
|
343
|
+
throw new PipelineLoadError(
|
|
344
|
+
message,
|
|
345
|
+
missing,
|
|
346
|
+
!missing && isRetryablePipelineLoadFailure(err)
|
|
347
|
+
);
|
|
337
348
|
}
|
|
338
349
|
})();
|
|
339
350
|
pipelinePromise.catch(() => {
|
|
@@ -374,10 +385,17 @@ var init_embed_core = __esm({
|
|
|
374
385
|
* damaged runtime.
|
|
375
386
|
*/
|
|
376
387
|
optionalPeerMissing;
|
|
377
|
-
|
|
388
|
+
/**
|
|
389
|
+
* Network/model-registry failures can clear without a process restart. The
|
|
390
|
+
* host uses this bit to apply a short retry cooldown instead of permanently
|
|
391
|
+
* disabling embeddings after one failed first-use download.
|
|
392
|
+
*/
|
|
393
|
+
retryable;
|
|
394
|
+
constructor(message, optionalPeerMissing = false, retryable = false) {
|
|
378
395
|
super(message);
|
|
379
396
|
this.name = "PipelineLoadError";
|
|
380
397
|
this.optionalPeerMissing = optionalPeerMissing;
|
|
398
|
+
this.retryable = retryable;
|
|
381
399
|
}
|
|
382
400
|
};
|
|
383
401
|
pipelinePromise = null;
|
|
@@ -388,6 +406,7 @@ var init_embed_core = __esm({
|
|
|
388
406
|
var embeddings_exports = {};
|
|
389
407
|
__export(embeddings_exports, {
|
|
390
408
|
EmbeddingsDisabledError: () => EmbeddingsDisabledError,
|
|
409
|
+
EmbeddingsUnavailableError: () => EmbeddingsUnavailableError,
|
|
391
410
|
embed: () => embed,
|
|
392
411
|
embedBatch: () => embedBatch,
|
|
393
412
|
embedQuery: () => embedQuery,
|
|
@@ -400,7 +419,7 @@ function disabledByEnv() {
|
|
|
400
419
|
return raw === "1" || raw?.toLowerCase() === "true";
|
|
401
420
|
}
|
|
402
421
|
function embeddingsDisabledReason() {
|
|
403
|
-
return disabledByEnv() ? ENV_DISABLED_REASON : disabledReason;
|
|
422
|
+
return disabledByEnv() ? ENV_DISABLED_REASON : disabledReason ?? currentUnavailableReason();
|
|
404
423
|
}
|
|
405
424
|
function workerEntry() {
|
|
406
425
|
if (process.env.VITEST) return null;
|
|
@@ -436,7 +455,12 @@ function onMessage(msg) {
|
|
|
436
455
|
pending.delete(msg.id);
|
|
437
456
|
if (msg.error) {
|
|
438
457
|
if (msg.fatal) markDisabled(msg.error, msg.optionalPeerMissing ?? false);
|
|
439
|
-
|
|
458
|
+
if (msg.retryable) {
|
|
459
|
+
markTemporarilyUnavailable(msg.error);
|
|
460
|
+
p.reject(new EmbeddingsUnavailableError(unavailableReason ?? msg.error));
|
|
461
|
+
} else {
|
|
462
|
+
p.reject(new Error(msg.error));
|
|
463
|
+
}
|
|
440
464
|
return;
|
|
441
465
|
}
|
|
442
466
|
p.resolve(msg.vectors ?? []);
|
|
@@ -469,12 +493,31 @@ async function embedInProcess(texts) {
|
|
|
469
493
|
return await runEmbed(texts);
|
|
470
494
|
} catch (err) {
|
|
471
495
|
if (err instanceof PipelineLoadError) {
|
|
496
|
+
if (err.retryable) {
|
|
497
|
+
markTemporarilyUnavailable(err.message);
|
|
498
|
+
throw new EmbeddingsUnavailableError(unavailableReason ?? err.message);
|
|
499
|
+
}
|
|
472
500
|
markDisabled(err.message, err.optionalPeerMissing);
|
|
473
501
|
throw new EmbeddingsDisabledError(disabledReason ?? err.message);
|
|
474
502
|
}
|
|
475
503
|
throw err;
|
|
476
504
|
}
|
|
477
505
|
}
|
|
506
|
+
function currentUnavailableReason() {
|
|
507
|
+
if (!unavailableReason) return null;
|
|
508
|
+
if (Date.now() < unavailableUntil) return unavailableReason;
|
|
509
|
+
unavailableReason = null;
|
|
510
|
+
unavailableUntil = 0;
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
function markTemporarilyUnavailable(message) {
|
|
514
|
+
unavailableReason = firstLine(message);
|
|
515
|
+
unavailableUntil = Date.now() + EMBEDDING_RETRY_COOLDOWN_MS;
|
|
516
|
+
log10.warn(
|
|
517
|
+
`[memory] embedding model load failed; semantic search will retry after ${Math.ceil(EMBEDDING_RETRY_COOLDOWN_MS / 1e3)}s.`
|
|
518
|
+
);
|
|
519
|
+
log10.warn("[memory] underlying transient error:", message);
|
|
520
|
+
}
|
|
478
521
|
function markDisabled(message, optionalPeerMissing = false) {
|
|
479
522
|
if (disabledReason) return;
|
|
480
523
|
disabledReason = firstLine(message);
|
|
@@ -490,11 +533,14 @@ function markDisabled(message, optionalPeerMissing = false) {
|
|
|
490
533
|
async function embedMany(texts) {
|
|
491
534
|
if (disabledByEnv()) throw new EmbeddingsDisabledError(ENV_DISABLED_REASON);
|
|
492
535
|
if (disabledReason) throw new EmbeddingsDisabledError(disabledReason);
|
|
536
|
+
const temporaryReason = currentUnavailableReason();
|
|
537
|
+
if (temporaryReason) throw new EmbeddingsUnavailableError(temporaryReason);
|
|
493
538
|
const w = ensureWorker();
|
|
494
539
|
if (w) {
|
|
495
540
|
try {
|
|
496
541
|
return await sendToWorker(w, texts);
|
|
497
542
|
} catch (err) {
|
|
543
|
+
if (err instanceof EmbeddingsUnavailableError) throw err;
|
|
498
544
|
if (disabledReason) throw new EmbeddingsDisabledError(disabledReason);
|
|
499
545
|
log10.warn(`[memory] embed via worker failed; retrying in-process: ${describe(err)}`);
|
|
500
546
|
}
|
|
@@ -519,7 +565,7 @@ async function embedBatch(texts) {
|
|
|
519
565
|
if (texts.length === 0) return [];
|
|
520
566
|
return embedMany(texts);
|
|
521
567
|
}
|
|
522
|
-
var log10, EmbeddingsDisabledError, disabledReason, ENV_DISABLED_REASON, worker, workerUsable, crashCount, nextId, pending;
|
|
568
|
+
var log10, EmbeddingsDisabledError, EmbeddingsUnavailableError, disabledReason, unavailableReason, unavailableUntil, EMBEDDING_RETRY_COOLDOWN_MS, ENV_DISABLED_REASON, worker, workerUsable, crashCount, nextId, pending;
|
|
523
569
|
var init_embeddings = __esm({
|
|
524
570
|
"src/memory/embeddings.ts"() {
|
|
525
571
|
"use strict";
|
|
@@ -528,12 +574,25 @@ var init_embeddings = __esm({
|
|
|
528
574
|
log10 = createLogger10("memory");
|
|
529
575
|
EmbeddingsDisabledError = class extends Error {
|
|
530
576
|
code = "EMBEDDINGS_DISABLED";
|
|
577
|
+
retryable = false;
|
|
531
578
|
constructor(reason) {
|
|
532
579
|
super(`memory embeddings disabled: ${reason}`);
|
|
533
580
|
this.name = "EmbeddingsDisabledError";
|
|
534
581
|
}
|
|
535
582
|
};
|
|
583
|
+
EmbeddingsUnavailableError = class extends EmbeddingsDisabledError {
|
|
584
|
+
code = "EMBEDDINGS_UNAVAILABLE";
|
|
585
|
+
retryable = true;
|
|
586
|
+
constructor(reason) {
|
|
587
|
+
super(reason);
|
|
588
|
+
this.name = "EmbeddingsUnavailableError";
|
|
589
|
+
this.message = `memory embeddings temporarily unavailable: ${reason}`;
|
|
590
|
+
}
|
|
591
|
+
};
|
|
536
592
|
disabledReason = null;
|
|
593
|
+
unavailableReason = null;
|
|
594
|
+
unavailableUntil = 0;
|
|
595
|
+
EMBEDDING_RETRY_COOLDOWN_MS = 6e4;
|
|
537
596
|
ENV_DISABLED_REASON = "disabled by GEZEL_DISABLE_EMBEDDINGS";
|
|
538
597
|
worker = null;
|
|
539
598
|
workerUsable = true;
|
|
@@ -9500,7 +9559,7 @@ __export(bootstrap_exports, {
|
|
|
9500
9559
|
reconcileSystemToolsetFromDisk: () => reconcileSystemToolsetFromDisk,
|
|
9501
9560
|
runSystemBootstrap: () => runSystemBootstrap
|
|
9502
9561
|
});
|
|
9503
|
-
import { createHash as
|
|
9562
|
+
import { createHash as createHash39, randomUUID as randomUUID25 } from "crypto";
|
|
9504
9563
|
import { existsSync as existsSync23 } from "fs";
|
|
9505
9564
|
import { mkdir as mkdir51, open as open5, readFile as readFile62, rm as rm34, writeFile as writeFile23 } from "fs/promises";
|
|
9506
9565
|
import { join as join85 } from "path";
|
|
@@ -9896,7 +9955,7 @@ async function downloadWithIntegrity(url, dest, integrity, opts = {}) {
|
|
|
9896
9955
|
if (!["sha256", "sha384", "sha512"].includes(algo)) {
|
|
9897
9956
|
throw new Error(`unsupported integrity algorithm: ${algo}`);
|
|
9898
9957
|
}
|
|
9899
|
-
const hash =
|
|
9958
|
+
const hash = createHash39(algo);
|
|
9900
9959
|
const request = await fetchBounded(url, DOWNLOAD_TIMEOUT_MS, opts.signal);
|
|
9901
9960
|
const handle = await open5(dest, "wx", 384);
|
|
9902
9961
|
try {
|
|
@@ -11690,7 +11749,7 @@ var ChatEventBus = class {
|
|
|
11690
11749
|
};
|
|
11691
11750
|
|
|
11692
11751
|
// src/chat/manager.ts
|
|
11693
|
-
import { randomUUID as randomUUID7 } from "crypto";
|
|
11752
|
+
import { createHash as createHash12, randomUUID as randomUUID7 } from "crypto";
|
|
11694
11753
|
import { createRequire } from "module";
|
|
11695
11754
|
import { join as join28 } from "path";
|
|
11696
11755
|
import {
|
|
@@ -14085,15 +14144,13 @@ import { createLogger as createLogger4 } from "@bendyline/gezel";
|
|
|
14085
14144
|
// src/model-profile/behaviors/fabrication-detect-claim-without-tool.ts
|
|
14086
14145
|
var PROJECT_CREATION_VERBS = [
|
|
14087
14146
|
"created",
|
|
14088
|
-
"initiated",
|
|
14089
14147
|
"initialized",
|
|
14090
14148
|
"set\\s+up",
|
|
14091
14149
|
"spun\\s+up",
|
|
14092
|
-
"started",
|
|
14093
14150
|
"made",
|
|
14094
|
-
"bootstrapped"
|
|
14095
|
-
"kicked\\s+off"
|
|
14151
|
+
"bootstrapped"
|
|
14096
14152
|
].join("|");
|
|
14153
|
+
var PROJECT_WORK_START_VERBS = ["initiated", "started", "kicked\\s+off"].join("|");
|
|
14097
14154
|
var TASK_CREATION_VERBS = ["created", "added", "queued", "set\\s+up"].join("|");
|
|
14098
14155
|
var GEZEL_CREATION_VERBS = [
|
|
14099
14156
|
"created",
|
|
@@ -14154,6 +14211,18 @@ var CLAIM_RULES = [
|
|
|
14154
14211
|
claim: "recruited a voorman",
|
|
14155
14212
|
nudge: "You told the user you recruited a voorman, but you did not call `create_gezel`, `ensure_gezel`, or `start_project` this turn. Call the right one now, and only report recruitment after it succeeds."
|
|
14156
14213
|
},
|
|
14214
|
+
{
|
|
14215
|
+
// Ambiguous kickoff verbs only become a container-creation claim when
|
|
14216
|
+
// the prose explicitly says this is a new/separate project. Otherwise
|
|
14217
|
+
// the next rule treats them as starting work in the current project.
|
|
14218
|
+
pattern: new RegExp(
|
|
14219
|
+
String.raw`\bI(?:'ve|\s+have|\s+just|\s+already)?\s+(?:` + PROJECT_WORK_START_VERBS + String.raw`)\s+(?:the|a|an)\s+(?:new|fresh|separate|another|dedicated)\s+project\b`,
|
|
14220
|
+
"i"
|
|
14221
|
+
),
|
|
14222
|
+
requiredTools: ["start_project"],
|
|
14223
|
+
claim: "created a project",
|
|
14224
|
+
nudge: "You told the user you started a new project, but you did not call `start_project` this turn. Call it now with the user-intended name and project brief, or correct the claim."
|
|
14225
|
+
},
|
|
14157
14226
|
{
|
|
14158
14227
|
pattern: new RegExp(
|
|
14159
14228
|
String.raw`\bI(?:'ve|\s+have|\s+just|\s+already)?\s+(?:` + PROJECT_CREATION_VERBS + String.raw`)\s+(?:the|a|an)\s+` + // Optional name placed between "the" and "project". Forms
|
|
@@ -14175,6 +14244,15 @@ var CLAIM_RULES = [
|
|
|
14175
14244
|
claim: "created a project",
|
|
14176
14245
|
nudge: "You told the user you created the project, but you did not call `start_project` this turn. Call it now with the user-intended name and a real `about` + `missionObjectives` derived from their request."
|
|
14177
14246
|
},
|
|
14247
|
+
{
|
|
14248
|
+
pattern: new RegExp(
|
|
14249
|
+
String.raw`\bI(?:'ve|\s+have|\s+just|\s+already)?\s+(?:` + PROJECT_WORK_START_VERBS + String.raw`)\s+(?:(?:work|the\s+work)\s+(?:on|for)\s+)?(?:the|this|that|our|your|a|an)\s+project\b`,
|
|
14250
|
+
"i"
|
|
14251
|
+
),
|
|
14252
|
+
requiredTools: ["invoke_craftbook", "create_task", "start_project"],
|
|
14253
|
+
claim: "started work in the current project",
|
|
14254
|
+
nudge: "You told the user project work started, but no project-local action succeeded this turn. Use `invoke_craftbook` for a selected procedure, `create_task` for an ad-hoc task, or `start_project` only when the user explicitly requested a separate project. Do not repeat the kickoff claim until the action returns successfully."
|
|
14255
|
+
},
|
|
14178
14256
|
{
|
|
14179
14257
|
pattern: new RegExp(
|
|
14180
14258
|
String.raw`\bI(?:'ve|\s+have|\s+just|\s+already)?\s+(?:` + GEZEL_CREATION_VERBS + String.raw`)\s+(?:the|a|an)\s+(?:new\s+)?gezel\b`,
|
|
@@ -15097,13 +15175,26 @@ var BUILD_REQUEST_RE = new RegExp(
|
|
|
15097
15175
|
function looksLikeNewBuildRequest(text) {
|
|
15098
15176
|
return BUILD_REQUEST_RE.test(text);
|
|
15099
15177
|
}
|
|
15178
|
+
function explicitlyRequestsSeparateProject(text) {
|
|
15179
|
+
return /\b(?:new|fresh|separate|another|dedicated)\s+(?:(?:standalone|independent)\s+)?(?:project|workspace)\b/i.test(
|
|
15180
|
+
text
|
|
15181
|
+
) || /\b(?:as|in|into|under|for)\s+(?:a|an)\s+(?:new|fresh|separate|another|dedicated)\s+(?:project|workspace)\b/i.test(
|
|
15182
|
+
text
|
|
15183
|
+
);
|
|
15184
|
+
}
|
|
15100
15185
|
var MEESTER_BUILD_PRELUDE = '(System note for this turn: the user is asking for a new substantive build. Make ONE tool call:\n \u2022 `start_project({ name, about, missionObjectives, taskDescription })`. Creates a fresh project, selects an appropriate lead/team for the effective execution mode, creates the kickoff task, and hands it off (the work starts in a task-scoped session). Use this for every "build me a website / game / app / dashboard" request, from a single-file prototype through multimodal work. `taskDescription` must ask the lead to ship the actual requested deliverable, not to create a plan. For browser games/sites, name `index.html` and the acceptance criteria (workspace-relative path; do not prefix `workspace/`).\nAfter the macro returns, your turn is done \u2014 tell the user the lead is on it. Do NOT call `create_gezel`, `update_project`, `create_task`, or `message_gezel` separately \u2014 the macro handles them. Do NOT reuse the existing "Default" project; the macro creates a fresh dedicated one.)';
|
|
15101
15186
|
var PromptMeesterBuildPrelude = {
|
|
15102
15187
|
id: "prompt.meester-build-prelude",
|
|
15103
15188
|
description: 'Prepends a system note to the user prompt when the active gezel is the Meester and the message looks like a "build me X" request, anchoring the first-call expectation on `start_project`.',
|
|
15104
15189
|
userPromptPrelude(ctx) {
|
|
15105
15190
|
if (!ctx.isMeester) return null;
|
|
15191
|
+
if (ctx.messageOrigin !== "direct-user") return null;
|
|
15192
|
+
if (/^\s*\[Answer to:/i.test(ctx.userText)) return null;
|
|
15106
15193
|
if (!looksLikeNewBuildRequest(ctx.userText)) return null;
|
|
15194
|
+
if (ctx.projectId !== "default" && !explicitlyRequestsSeparateProject(ctx.userText)) {
|
|
15195
|
+
return null;
|
|
15196
|
+
}
|
|
15197
|
+
if (!ctx.availableToolNames.includes("start_project")) return null;
|
|
15107
15198
|
return MEESTER_BUILD_PRELUDE;
|
|
15108
15199
|
}
|
|
15109
15200
|
};
|
|
@@ -18152,6 +18243,12 @@ var AnthropicCliSession = class extends StreamingSessionBase {
|
|
|
18152
18243
|
providerState() {
|
|
18153
18244
|
return this.claudeSessionIdCache ? { claudeCliSessionId: this.claudeSessionIdCache } : {};
|
|
18154
18245
|
}
|
|
18246
|
+
getRegisteredToolNames() {
|
|
18247
|
+
const context = this.deps.context;
|
|
18248
|
+
return [
|
|
18249
|
+
.../* @__PURE__ */ new Set([...context.allowedBuiltinTools ?? [], ...context.allowedMcpTools ?? []])
|
|
18250
|
+
];
|
|
18251
|
+
}
|
|
18155
18252
|
async disconnect() {
|
|
18156
18253
|
this.aborted = true;
|
|
18157
18254
|
try {
|
|
@@ -19700,6 +19797,10 @@ var AnthropicSession = class extends StreamingSessionBase {
|
|
|
19700
19797
|
* resolves and persisted on `ChatMessage.reasoning`.
|
|
19701
19798
|
*/
|
|
19702
19799
|
lastTurnReasoning = "";
|
|
19800
|
+
getRegisteredToolNames() {
|
|
19801
|
+
const bridgeNames = this.deps.bridges.isEmpty() ? [] : this.deps.bridges.getAnthropicTools().map((tool) => tool.name);
|
|
19802
|
+
return [.../* @__PURE__ */ new Set([...bridgeNames, ...this.externalToolNames])];
|
|
19803
|
+
}
|
|
19703
19804
|
capturedToolCalls() {
|
|
19704
19805
|
return [...this.capturedCalls];
|
|
19705
19806
|
}
|
|
@@ -26964,7 +27065,12 @@ var LlamaCppSession = class extends StreamingSessionBase {
|
|
|
26964
27065
|
if (toolCalls.length > 0) {
|
|
26965
27066
|
const normalized2 = normalizeMalformedStructuredToolCalls(
|
|
26966
27067
|
toolCalls,
|
|
26967
|
-
collectKnownToolNames()
|
|
27068
|
+
collectKnownToolNames(),
|
|
27069
|
+
// A malformed write at the output ceiling is not repairable: the
|
|
27070
|
+
// missing JSON tail may also be missing file bytes. Executing the
|
|
27071
|
+
// loose prefix can silently replace a complete file with a
|
|
27072
|
+
// truncated one. Valid, fully parseable calls remain eligible.
|
|
27073
|
+
finishReason !== "length"
|
|
26968
27074
|
);
|
|
26969
27075
|
toolCalls = normalized2.toolCalls;
|
|
26970
27076
|
malformedStructuredCallIds = new Set(normalized2.sanitizedIds);
|
|
@@ -27841,7 +27947,7 @@ var ToolCallAccumulator = class {
|
|
|
27841
27947
|
}));
|
|
27842
27948
|
}
|
|
27843
27949
|
};
|
|
27844
|
-
function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
|
|
27950
|
+
function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames, allowMalformedWriteRepair = true) {
|
|
27845
27951
|
const repaired = [];
|
|
27846
27952
|
const sanitized = [];
|
|
27847
27953
|
const sanitizedIds = [];
|
|
@@ -27852,11 +27958,7 @@ function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
|
|
|
27852
27958
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return call;
|
|
27853
27959
|
} catch {
|
|
27854
27960
|
}
|
|
27855
|
-
const repairedArgs = tryRepairMalformedWriteToolArguments(
|
|
27856
|
-
call.function.name,
|
|
27857
|
-
raw,
|
|
27858
|
-
knownToolNames
|
|
27859
|
-
);
|
|
27961
|
+
const repairedArgs = allowMalformedWriteRepair ? tryRepairMalformedWriteToolArguments(call.function.name, raw, knownToolNames) : null;
|
|
27860
27962
|
if (repairedArgs) {
|
|
27861
27963
|
repaired.push({
|
|
27862
27964
|
name: call.function.name,
|
|
@@ -32018,6 +32120,7 @@ function buildLlamaCppEngineArgs(input) {
|
|
|
32018
32120
|
ggufHasMtp,
|
|
32019
32121
|
installedDraftModelPath,
|
|
32020
32122
|
reasoningFormat,
|
|
32123
|
+
reasoningPreserve,
|
|
32021
32124
|
architecture,
|
|
32022
32125
|
modelId,
|
|
32023
32126
|
swaFullAutoFits
|
|
@@ -32065,6 +32168,7 @@ function buildLlamaCppEngineArgs(input) {
|
|
|
32065
32168
|
if (typeof nMax === "number") args.push("--spec-draft-n-max", String(nMax));
|
|
32066
32169
|
}
|
|
32067
32170
|
if (reasoningFormat) args.push("--reasoning-format", reasoningFormat);
|
|
32171
|
+
if (reasoningPreserve) args.push("--reasoning-preserve");
|
|
32068
32172
|
if (config.llamaCppExtraArgs) {
|
|
32069
32173
|
for (const [rawKey, value] of Object.entries(config.llamaCppExtraArgs)) {
|
|
32070
32174
|
if (value === false) continue;
|
|
@@ -32385,6 +32489,31 @@ function fitsSwaFullInFastMemory(input) {
|
|
|
32385
32489
|
return Number.isFinite(required) && Number.isFinite(available) && required <= available;
|
|
32386
32490
|
}
|
|
32387
32491
|
|
|
32492
|
+
// src/providers/llama-cpp/reasoning-launch.ts
|
|
32493
|
+
var POSITIVE_INTEGER = /^[1-9]\d*$/;
|
|
32494
|
+
function parseReasoningPreserveEnv(raw) {
|
|
32495
|
+
const normalized2 = raw?.trim().toLowerCase();
|
|
32496
|
+
return normalized2 === "1" || normalized2 === "true";
|
|
32497
|
+
}
|
|
32498
|
+
function parseReasoningBudgetEnv(raw) {
|
|
32499
|
+
const normalized2 = raw?.trim();
|
|
32500
|
+
if (!normalized2) return void 0;
|
|
32501
|
+
if (!POSITIVE_INTEGER.test(normalized2)) {
|
|
32502
|
+
throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS must be a positive integer");
|
|
32503
|
+
}
|
|
32504
|
+
const parsed = Number(normalized2);
|
|
32505
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
32506
|
+
throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS exceeds the safe integer range");
|
|
32507
|
+
}
|
|
32508
|
+
return parsed;
|
|
32509
|
+
}
|
|
32510
|
+
function reasoningLaunchOverridesFromEnv(env = process.env) {
|
|
32511
|
+
return {
|
|
32512
|
+
preserve: parseReasoningPreserveEnv(env.GEZEL_LLAMA_REASONING_PRESERVE),
|
|
32513
|
+
budgetTokens: parseReasoningBudgetEnv(env.GEZEL_LLAMA_REASONING_BUDGET_TOKENS)
|
|
32514
|
+
};
|
|
32515
|
+
}
|
|
32516
|
+
|
|
32388
32517
|
// src/providers/llama-cpp/spec-draft.ts
|
|
32389
32518
|
async function resolveSpecDraft(input) {
|
|
32390
32519
|
const { perModel, configSpecType, configDraftModelPath, resolveDraftPath } = input;
|
|
@@ -32443,6 +32572,8 @@ async function buildLlamaCppProvider(opts) {
|
|
|
32443
32572
|
const { config, affinity, home } = opts;
|
|
32444
32573
|
const externalBaseUrl = opts.modelOverride ? void 0 : process.env.GEZEL_LLAMA_SERVER_URL ?? config.llamaCppBaseUrl;
|
|
32445
32574
|
const binary = process.env.GEZEL_LLAMA_SERVER_BIN;
|
|
32575
|
+
const reasoningLaunchOverrides = reasoningLaunchOverridesFromEnv();
|
|
32576
|
+
const reasoningPreserve = reasoningLaunchOverrides.preserve;
|
|
32446
32577
|
const defaultModelId = opts.modelOverride?.modelId ?? config.defaultModel?.["llama-cpp"];
|
|
32447
32578
|
const configuredSlots = config.providerConcurrency?.["llama-cpp"];
|
|
32448
32579
|
const envNumCtx = (() => {
|
|
@@ -32465,6 +32596,7 @@ async function buildLlamaCppProvider(opts) {
|
|
|
32465
32596
|
// rate for its own default engine — throughput was reachable only by
|
|
32466
32597
|
// scraping stdout from the eval harness.
|
|
32467
32598
|
includeUsageInStream: true,
|
|
32599
|
+
replayReasoningContent: reasoningPreserve,
|
|
32468
32600
|
// External-baseUrl default; the supervised path overrides this with the
|
|
32469
32601
|
// auto-sized `slots` computed below (after the model resolves).
|
|
32470
32602
|
concurrency: configuredSlots ?? 2,
|
|
@@ -32655,10 +32787,12 @@ async function buildLlamaCppProvider(opts) {
|
|
|
32655
32787
|
const slotSavePath = replicaSuffix ? join18(llamaCacheRoot, llamaFingerprint, replicaSuffix) : join18(llamaCacheRoot, llamaFingerprint);
|
|
32656
32788
|
await mkdirAsync(slotSavePath, { recursive: true }).catch(() => {
|
|
32657
32789
|
});
|
|
32658
|
-
const
|
|
32790
|
+
const catalogReasoningBudgetTokens = opts.catalog ? await resolveCatalogReasoningBudget(
|
|
32659
32791
|
opts.catalog,
|
|
32660
32792
|
opts.modelOverride?.modelId ?? defaultModelId
|
|
32661
32793
|
) : void 0;
|
|
32794
|
+
const reasoningBudgetTokens = reasoningLaunchOverrides.budgetTokens ?? catalogReasoningBudgetTokens;
|
|
32795
|
+
const reasoningBudgetSource = reasoningLaunchOverrides.budgetTokens !== void 0 ? "env" : catalogReasoningBudgetTokens !== void 0 ? "catalog" : "unbounded";
|
|
32662
32796
|
const specDraft = await resolveSpecDraft({
|
|
32663
32797
|
perModel: manifestEngineConfig,
|
|
32664
32798
|
configSpecType: config.llamaCppSpecType,
|
|
@@ -33048,6 +33182,7 @@ async function buildLlamaCppProvider(opts) {
|
|
|
33048
33182
|
// disables llama-server's chat-template output parsing so mangled
|
|
33049
33183
|
// model output reaches `delta.content` for provider-side salvage.
|
|
33050
33184
|
reasoningFormat: process.env.GEZEL_LLAMA_REASONING_FORMAT?.trim() || void 0,
|
|
33185
|
+
reasoningPreserve,
|
|
33051
33186
|
architecture: modelCatalogInfo?.architecture,
|
|
33052
33187
|
modelId: defaultModelId ?? void 0,
|
|
33053
33188
|
swaFullAutoFits
|
|
@@ -33156,6 +33291,9 @@ async function buildLlamaCppProvider(opts) {
|
|
|
33156
33291
|
batchSize: lastArgValue(resolvedAdvancedArgs, "--batch-size") ?? "default",
|
|
33157
33292
|
ubatchSize: lastArgValue(resolvedAdvancedArgs, "--ubatch-size") ?? "default",
|
|
33158
33293
|
flashAttention: lastArgValue(resolvedAdvancedArgs, "--flash-attn") ?? "default",
|
|
33294
|
+
reasoningBudgetTokens: reasoningBudgetTokens ?? "unbounded",
|
|
33295
|
+
reasoningBudgetSource,
|
|
33296
|
+
reasoningPreserve,
|
|
33159
33297
|
cudaGraphs: process.env.GGML_CUDA_DISABLE_GRAPHS ? "disabled-by-env" : "default"
|
|
33160
33298
|
},
|
|
33161
33299
|
env: {
|
|
@@ -33321,7 +33459,7 @@ var PROJECT_MACRO_INTERCEPT_CAP = 2;
|
|
|
33321
33459
|
var PROJECT_MACRO_FAILURE_CAP = 2;
|
|
33322
33460
|
function deriveProjectMacroClosing(firstResult) {
|
|
33323
33461
|
const projectMatch = firstResult.match(/Started (?:project|job) "([^"]+)"/);
|
|
33324
|
-
const leadMatch = firstResult.match(/Recruited (\S+) as (voorman|
|
|
33462
|
+
const leadMatch = firstResult.match(/Recruited (\S+) as (voorman|builder|lead)/i);
|
|
33325
33463
|
const projectName = projectMatch?.[1];
|
|
33326
33464
|
const leadName = leadMatch?.[1];
|
|
33327
33465
|
const leadRole = leadMatch?.[2];
|
|
@@ -35944,14 +36082,14 @@ async function buildMlxProvider(opts) {
|
|
|
35944
36082
|
const cacheBudgetMb = Math.min(config.cacheBudgetMb?.mlx ?? ramAwareDefaultMb, mlxKvHeadroomMb);
|
|
35945
36083
|
const mlxReplicaSuffix = opts.modelOverride && opts.modelOverride.replicaIdx > 0 ? `replica-${opts.modelOverride.replicaIdx}` : "";
|
|
35946
36084
|
const cacheRoot = mlxReplicaSuffix ? join21(store.homePath, "engines", "mlx", "cache", mlxReplicaSuffix) : join21(store.homePath, "engines", "mlx", "cache");
|
|
35947
|
-
const { createHash:
|
|
36085
|
+
const { createHash: createHash48 } = await import("crypto");
|
|
35948
36086
|
const fingerprintInput = [
|
|
35949
36087
|
modelCatalogInfo?.id ?? defaultModelId ?? modelDir,
|
|
35950
36088
|
modelCatalogInfo?.catalogVersion ?? "",
|
|
35951
36089
|
modelCatalogInfo?.installedAt ?? "",
|
|
35952
36090
|
modelDir
|
|
35953
36091
|
].join("::");
|
|
35954
|
-
const modelFingerprint =
|
|
36092
|
+
const modelFingerprint = createHash48("sha256").update(fingerprintInput, "utf8").digest("hex").slice(0, 24);
|
|
35955
36093
|
const diskCacheBudgetMb = config.mlxDiskCacheBudgetMb ?? 8192;
|
|
35956
36094
|
const mlxIdleMs = config.localEngineIdleTimeoutMs ?? DEFAULT_LOCAL_ENGINE_IDLE_TIMEOUT_MS3;
|
|
35957
36095
|
const mlxFreezeMs = Math.floor(mlxIdleMs / 2);
|
|
@@ -37273,6 +37411,10 @@ var OpenAISession = class extends StreamingSessionBase {
|
|
|
37273
37411
|
capturedToolCalls() {
|
|
37274
37412
|
return [...this.capturedCalls];
|
|
37275
37413
|
}
|
|
37414
|
+
getRegisteredToolNames() {
|
|
37415
|
+
const bridgeNames = this.deps.bridges.isEmpty() ? [] : this.deps.bridges.getOpenAITools().map((tool) => tool.name);
|
|
37416
|
+
return [.../* @__PURE__ */ new Set([...bridgeNames, ...this.externalToolNames])];
|
|
37417
|
+
}
|
|
37276
37418
|
async sendAndWait(prompt, opts) {
|
|
37277
37419
|
return runInQueue(this.deps.queue, opts?.queue, () => this.sendAndWaitInner(prompt, opts));
|
|
37278
37420
|
}
|
|
@@ -40190,14 +40332,15 @@ async function evalCheck(c, ws, deps) {
|
|
|
40190
40332
|
}
|
|
40191
40333
|
async function evalCheckInner(c, ws, deps) {
|
|
40192
40334
|
const usesArtifact = c.artifact === true;
|
|
40193
|
-
const
|
|
40335
|
+
const artifactReader = {
|
|
40194
40336
|
read: ws.readArtifact ?? (async () => null),
|
|
40195
40337
|
list: ws.listArtifacts ?? (async () => []),
|
|
40196
40338
|
// Carry the byte reader across the artifact swap; without it a
|
|
40197
40339
|
// `verifyImageBytes` check on an artifact deliverable would report
|
|
40198
40340
|
// "no binary reads" even though the surface supports them.
|
|
40199
40341
|
...ws.readArtifactBytes ? { readBytes: ws.readArtifactBytes.bind(ws) } : {}
|
|
40200
|
-
}
|
|
40342
|
+
};
|
|
40343
|
+
const reader = usesArtifact ? artifactReader : ws;
|
|
40201
40344
|
switch (c.kind) {
|
|
40202
40345
|
case "minBytes": {
|
|
40203
40346
|
const r = await fileMinBytes(reader, c.file, c.bytes);
|
|
@@ -40625,7 +40768,12 @@ ${hint}` : ""}`,
|
|
|
40625
40768
|
};
|
|
40626
40769
|
}
|
|
40627
40770
|
case "markdownHeadingsMatch": {
|
|
40628
|
-
const result = await markdownHeadingsMatch(
|
|
40771
|
+
const result = await markdownHeadingsMatch(
|
|
40772
|
+
reader,
|
|
40773
|
+
c.file,
|
|
40774
|
+
c.outlineFile,
|
|
40775
|
+
c.outlineArtifact ? artifactReader : ws
|
|
40776
|
+
);
|
|
40629
40777
|
return {
|
|
40630
40778
|
ok: result.ok,
|
|
40631
40779
|
detail: result.detail,
|
|
@@ -42540,6 +42688,11 @@ function filterPromptToolDirectives(args) {
|
|
|
42540
42688
|
if (rejectedLines.size === 0) return args.prompt;
|
|
42541
42689
|
return args.prompt.split("\n").filter((_, index) => !rejectedLines.has(index + 1)).join("\n").replace(/\n{4,}/g, "\n\n\n");
|
|
42542
42690
|
}
|
|
42691
|
+
function capabilitySafeCorrectivePrompt(args) {
|
|
42692
|
+
const filtered = filterPromptToolDirectives(args).trim();
|
|
42693
|
+
if (filtered) return filtered;
|
|
42694
|
+
return "Your previous reply claimed an action succeeded without live evidence. Use only an appropriate action tool visible in your current roster, or explain that the action cannot be performed here. Do not repeat the success claim until an available action returns successfully.";
|
|
42695
|
+
}
|
|
42543
42696
|
|
|
42544
42697
|
// src/chat/provider-capabilities.ts
|
|
42545
42698
|
function providerUsesManagedMcpBridge(name) {
|
|
@@ -46378,6 +46531,21 @@ function sameFromBucket(a, b) {
|
|
|
46378
46531
|
if (!a || !b) return false;
|
|
46379
46532
|
return a.gezelId === b.gezelId;
|
|
46380
46533
|
}
|
|
46534
|
+
function resolveTurnMessageOrigin(opts) {
|
|
46535
|
+
if (opts?.messageOrigin) return opts.messageOrigin;
|
|
46536
|
+
if (opts?.from) return "cross-gezel";
|
|
46537
|
+
if (opts?.ambient || opts?.nudge || opts?.lane === "background") return "background-nudge";
|
|
46538
|
+
return "direct-user";
|
|
46539
|
+
}
|
|
46540
|
+
function liveTurnToolNames(session) {
|
|
46541
|
+
const names = /* @__PURE__ */ new Set();
|
|
46542
|
+
for (const name of session?.getRegisteredToolNames?.() ?? []) {
|
|
46543
|
+
names.add(name);
|
|
46544
|
+
const qualified = name.match(/^mcp__.+?__(.+)$/)?.[1];
|
|
46545
|
+
if (qualified && qualified !== "*") names.add(qualified);
|
|
46546
|
+
}
|
|
46547
|
+
return [...names];
|
|
46548
|
+
}
|
|
46381
46549
|
async function resolveCatalogParameterSize(catalog, catalogId) {
|
|
46382
46550
|
if (!catalogId) return void 0;
|
|
46383
46551
|
try {
|
|
@@ -46519,10 +46687,12 @@ var ChatManager = class {
|
|
|
46519
46687
|
*/
|
|
46520
46688
|
afterSessionIdle = /* @__PURE__ */ new Map();
|
|
46521
46689
|
/**
|
|
46522
|
-
* One live async file handoff per sender/target/project/path. Models can
|
|
46690
|
+
* One live async file handoff per sender/target/project/path/intent. Models can
|
|
46523
46691
|
* emit the same `message_gezel` call several times while the sender turn
|
|
46524
46692
|
* is still active; joining that work prevents a parked-send burst from
|
|
46525
|
-
* replaying the same assignment into the recipient session.
|
|
46693
|
+
* replaying the same assignment into the recipient session. A later
|
|
46694
|
+
* validator repair for a file that was originally missing is distinct work
|
|
46695
|
+
* and must never join the older create request.
|
|
46526
46696
|
*/
|
|
46527
46697
|
inflightFileHandoffs = /* @__PURE__ */ new Map();
|
|
46528
46698
|
/** Set once {@link shutdown} starts so deferred watchdogs don't fire into a tearing-down manager. */
|
|
@@ -47779,6 +47949,7 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
47779
47949
|
coalescable: false,
|
|
47780
47950
|
lane: void 0,
|
|
47781
47951
|
ambient: false,
|
|
47952
|
+
messageOrigin: "direct-user",
|
|
47782
47953
|
continuationMaxTokens: void 0,
|
|
47783
47954
|
hidden: false,
|
|
47784
47955
|
nudge: false,
|
|
@@ -48084,11 +48255,14 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
48084
48255
|
const full = await this.store.getSession(args.gezelId, active.id);
|
|
48085
48256
|
if (full) return full;
|
|
48086
48257
|
}
|
|
48258
|
+
const parsedTaskRef = parseTaskRef2(args.taskRef);
|
|
48259
|
+
const task = parsedTaskRef ? await this.store.readTask(parsedTaskRef.projectId, parsedTaskRef.num).catch(() => null) : null;
|
|
48087
48260
|
return this.createSession({
|
|
48088
48261
|
gezelId: args.gezelId,
|
|
48089
48262
|
projectId: args.projectId,
|
|
48090
48263
|
taskRef: args.taskRef,
|
|
48091
|
-
...args.stepId ? { stepId: args.stepId } : {}
|
|
48264
|
+
...args.stepId ? { stepId: args.stepId } : {},
|
|
48265
|
+
...task?.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: task.roleBasedNameOnlyMode } : {}
|
|
48092
48266
|
});
|
|
48093
48267
|
}
|
|
48094
48268
|
/** Late-bind the fitness manager (see the field's docblock). */
|
|
@@ -48215,6 +48389,7 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
48215
48389
|
*/
|
|
48216
48390
|
async startHandoffSession(args) {
|
|
48217
48391
|
const dispatchConfig = await this.store.readConfig();
|
|
48392
|
+
const roleBasedNameOnlyMode = args.roleBasedNameOnlyMode ?? dispatchConfig.roleBasedNameOnlyMode ?? false;
|
|
48218
48393
|
const dispatchGezel = await this.store.getGezel(args.gezelId);
|
|
48219
48394
|
const dispatchProviderName = await this.resolveProviderName(
|
|
48220
48395
|
args.gezelId,
|
|
@@ -48263,6 +48438,7 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
48263
48438
|
projectId: args.projectId,
|
|
48264
48439
|
taskRef: args.taskRef,
|
|
48265
48440
|
stepId: dispatchStepId,
|
|
48441
|
+
roleBasedNameOnlyMode,
|
|
48266
48442
|
...args.nightShift ? { nightShift: true } : {},
|
|
48267
48443
|
...routed && args.capabilityFloor ? {
|
|
48268
48444
|
routedModel: {
|
|
@@ -48319,9 +48495,15 @@ ${stepArc}
|
|
|
48319
48495
|
}
|
|
48320
48496
|
}
|
|
48321
48497
|
const selfHandoff = args.fromGezelId !== void 0 && args.fromGezelId === args.gezelId;
|
|
48322
|
-
const
|
|
48498
|
+
const previousGezel = !selfHandoff && args.fromGezelId ? await this.store.getGezel(args.fromGezelId).catch(() => null) : null;
|
|
48499
|
+
const fromGezelDisplayName = previousGezel ? displayName2(
|
|
48500
|
+
{ name: previousGezel.name, roleBasedName: previousGezel.roleBasedName },
|
|
48501
|
+
roleBasedNameOnlyMode
|
|
48502
|
+
) : roleBasedNameOnlyMode ? void 0 : args.fromGezelName;
|
|
48503
|
+
const seed = args.kind === "entry" ? `${entryPreface}You've been assigned task ${args.taskRef} (step \`${dispatchStepId}\`). Follow the step instructions already in your prompt \u2014 make the first tool call they name this turn. Append focused notes with \`write_task_note\` as you go. When the step is done, call \`advance_task_step\` to hand off to whoever's next.` : selfHandoff ? `Task ${args.taskRef} has advanced to the next step \u2014 \`${dispatchStepId}\`, which is yours as well. Please continue: follow the step instructions already in your prompt \u2014 make the first tool call they name this turn. Append focused notes with \`write_task_note\` as you go so the next gezel can pick up where you left off. When the step is done, call \`advance_task_step\` to hand off to whoever's next.` : `${fromGezelDisplayName ? `${fromGezelDisplayName} has` : "The previous step has been completed and"} handed step \`${dispatchStepId}\` of task ${args.taskRef} to you. Follow the step instructions already in your prompt \u2014 make the first tool call they name this turn. Append focused notes with \`write_task_note\` as you go so the next gezel can pick up where you left off. When the step is done, call \`advance_task_step\` to hand off to whoever's next.`;
|
|
48323
48504
|
this.trackBackground(
|
|
48324
48505
|
this.sendWithBusyRetry(session.id, seed, {
|
|
48506
|
+
messageOrigin: "system",
|
|
48325
48507
|
...args.lane ? { lane: args.lane } : {},
|
|
48326
48508
|
...args.ambient ? { ambient: true } : {}
|
|
48327
48509
|
}).catch((err) => {
|
|
@@ -48390,7 +48572,8 @@ ${stepArc}
|
|
|
48390
48572
|
args.fromSessionId ?? args.fromGezelId,
|
|
48391
48573
|
target.id,
|
|
48392
48574
|
projectId,
|
|
48393
|
-
normalizeExpectedDeliverablePath(requestedFilePath)
|
|
48575
|
+
normalizeExpectedDeliverablePath(requestedFilePath),
|
|
48576
|
+
fileHandoffIntentKey(args.text)
|
|
48394
48577
|
].join("\0") : null;
|
|
48395
48578
|
const pendingHandoff = fileHandoffKey ? this.inflightFileHandoffs.get(fileHandoffKey) : void 0;
|
|
48396
48579
|
if (pendingHandoff) return { ...pendingHandoff, deduplicated: true };
|
|
@@ -48431,7 +48614,7 @@ ${stepArc}
|
|
|
48431
48614
|
const seed = `[Message from ${fromName}]: ${args.text}${deliverableAnnotation}`;
|
|
48432
48615
|
const failureNotice = { sent: false };
|
|
48433
48616
|
const resolvedFromSessionId = args.fromSessionId ?? (target.id === args.fromGezelId ? null : await this.ensureOrCreateSession({ gezelId: args.fromGezelId, projectId }).then((s) => s.id).catch(() => null));
|
|
48434
|
-
if (resolvedFromSessionId && resolvedFromSessionId !== session.id) {
|
|
48617
|
+
if (!args.suppressReply && resolvedFromSessionId && resolvedFromSessionId !== session.id) {
|
|
48435
48618
|
this.attachReplyListener({
|
|
48436
48619
|
targetSessionId: session.id,
|
|
48437
48620
|
fromSessionId: resolvedFromSessionId,
|
|
@@ -49167,11 +49350,10 @@ ${stepArc}
|
|
|
49167
49350
|
log52.info(
|
|
49168
49351
|
`[questions] delivering answer to session ${args.sessionId.slice(0, 8)} (gezel ${session.gezelId}, project ${session.projectId})`
|
|
49169
49352
|
);
|
|
49170
|
-
await this.sendWithBusyRetry(
|
|
49171
|
-
|
|
49172
|
-
args.
|
|
49173
|
-
|
|
49174
|
-
);
|
|
49353
|
+
await this.sendWithBusyRetry(args.sessionId, args.seed, {
|
|
49354
|
+
messageOrigin: "question-answer",
|
|
49355
|
+
...args.coalescable ? { coalescable: true } : {}
|
|
49356
|
+
});
|
|
49175
49357
|
}
|
|
49176
49358
|
/**
|
|
49177
49359
|
* System-authored reaction seed into a gezel's live (gezel, project)
|
|
@@ -49197,6 +49379,7 @@ ${stepArc}
|
|
|
49197
49379
|
this.send(session.id, args.seed, {
|
|
49198
49380
|
coalescable: true,
|
|
49199
49381
|
lane: "background",
|
|
49382
|
+
messageOrigin: "system",
|
|
49200
49383
|
...leanReactionCap ? { continuationMaxTokens: leanReactionCap } : {},
|
|
49201
49384
|
...args.hidden ? { hidden: true } : {}
|
|
49202
49385
|
}).catch((err) => {
|
|
@@ -49671,12 +49854,13 @@ ${stepArc}
|
|
|
49671
49854
|
throw new Error("engagement-off: AI is disabled in settings; re-enable to send");
|
|
49672
49855
|
}
|
|
49673
49856
|
const existingQueue = this.pendingSends.get(sessionId2);
|
|
49857
|
+
const messageOrigin = resolveTurnMessageOrigin(opts);
|
|
49674
49858
|
const shouldQueue = this.inflight.has(sessionId2) || existingQueue !== void 0 && existingQueue.length > 0;
|
|
49675
49859
|
if (shouldQueue) {
|
|
49676
49860
|
return new Promise((resolve18, reject) => {
|
|
49677
49861
|
const q2 = this.pendingSends.get(sessionId2) ?? [];
|
|
49678
49862
|
const tail = q2.length > 0 ? q2[q2.length - 1] : void 0;
|
|
49679
|
-
const canMerge = opts?.coalescable === true && opts?.nudge !== true && tail?.coalescable === true && tail.nudge !== true && sameFromBucket(tail.from, opts.from);
|
|
49863
|
+
const canMerge = opts?.coalescable === true && opts?.nudge !== true && tail?.coalescable === true && tail.nudge !== true && tail.messageOrigin === messageOrigin && sameFromBucket(tail.from, opts.from);
|
|
49680
49864
|
if (canMerge && tail) {
|
|
49681
49865
|
tail.userText = `${tail.userText}
|
|
49682
49866
|
|
|
@@ -49703,6 +49887,7 @@ ${userText}`;
|
|
|
49703
49887
|
coalescable: opts?.coalescable === true,
|
|
49704
49888
|
lane: opts?.lane,
|
|
49705
49889
|
ambient: opts?.ambient === true,
|
|
49890
|
+
messageOrigin,
|
|
49706
49891
|
continuationMaxTokens: opts?.continuationMaxTokens,
|
|
49707
49892
|
hidden: opts?.hidden === true,
|
|
49708
49893
|
nudge: opts?.nudge === true,
|
|
@@ -49719,7 +49904,7 @@ ${userText}`;
|
|
|
49719
49904
|
return this.runSendAndDrain(
|
|
49720
49905
|
sessionId2,
|
|
49721
49906
|
userText,
|
|
49722
|
-
opts?.nudge ? { ...opts, nudge: false } : opts
|
|
49907
|
+
opts?.nudge ? { ...opts, nudge: false, messageOrigin } : { ...opts, messageOrigin }
|
|
49723
49908
|
);
|
|
49724
49909
|
}
|
|
49725
49910
|
/**
|
|
@@ -49818,7 +50003,7 @@ ${userText}`;
|
|
|
49818
50003
|
if (next.nudge) {
|
|
49819
50004
|
while (q2.length > 0) {
|
|
49820
50005
|
const peek = q2[0];
|
|
49821
|
-
if (!peek.nudge || peek.hidden !== next.hidden || !sameFromBucket(peek.from, next.from)) {
|
|
50006
|
+
if (!peek.nudge || peek.hidden !== next.hidden || peek.messageOrigin !== next.messageOrigin || !sameFromBucket(peek.from, next.from)) {
|
|
49822
50007
|
break;
|
|
49823
50008
|
}
|
|
49824
50009
|
q2.shift();
|
|
@@ -49841,6 +50026,7 @@ ${peek.userText}`;
|
|
|
49841
50026
|
if (next.continuationMaxTokens) runOpts.continuationMaxTokens = next.continuationMaxTokens;
|
|
49842
50027
|
if (next.hidden) runOpts.hidden = true;
|
|
49843
50028
|
if (next.nudge) runOpts.nudge = true;
|
|
50029
|
+
runOpts.messageOrigin = next.messageOrigin;
|
|
49844
50030
|
void this.runSendAndDrain(sessionId2, next.userText, runOpts).then((msg) => {
|
|
49845
50031
|
for (const w of next.waiters) {
|
|
49846
50032
|
try {
|
|
@@ -49871,20 +50057,36 @@ ${peek.userText}`;
|
|
|
49871
50057
|
return this.runFixedFunctionSend(sessionId2, userText, opts);
|
|
49872
50058
|
}
|
|
49873
50059
|
}
|
|
50060
|
+
const preflightScope = ffRecord ? {
|
|
50061
|
+
sessionId: sessionId2,
|
|
50062
|
+
gezelId: ffRecord.gezelId,
|
|
50063
|
+
projectId: ffRecord.projectId
|
|
50064
|
+
} : void 0;
|
|
50065
|
+
const coldStartPending = preflightScope && !this.states.get(sessionId2)?.session;
|
|
50066
|
+
if (preflightScope && coldStartPending) {
|
|
50067
|
+
this.events.publish(preflightScope, {
|
|
50068
|
+
type: "user_message_pending",
|
|
50069
|
+
preview: userText.length > 160 ? `${userText.slice(0, 157)}\u2026` : userText
|
|
50070
|
+
});
|
|
50071
|
+
}
|
|
49874
50072
|
const fail2 = (err) => {
|
|
49875
50073
|
const message = err instanceof Error ? err.message : String(err);
|
|
49876
50074
|
log52.error("error:", message);
|
|
50075
|
+
const publish = (event) => {
|
|
50076
|
+
if (preflightScope) this.events.publish(preflightScope, event);
|
|
50077
|
+
else this.events.publishSessionOnly(sessionId2, event);
|
|
50078
|
+
};
|
|
49877
50079
|
if (inflightTurn.cancelled) {
|
|
49878
|
-
|
|
50080
|
+
publish({ type: "cancelled" });
|
|
49879
50081
|
} else {
|
|
49880
50082
|
const detail = describeTurnError(err);
|
|
49881
|
-
|
|
50083
|
+
publish({
|
|
49882
50084
|
type: "error",
|
|
49883
50085
|
error: redactCredentials4(message),
|
|
49884
50086
|
...detail ? { errorDetail: detail } : {}
|
|
49885
50087
|
});
|
|
49886
50088
|
}
|
|
49887
|
-
|
|
50089
|
+
publish({ type: "done" });
|
|
49888
50090
|
throw err;
|
|
49889
50091
|
};
|
|
49890
50092
|
if (ffRecord) {
|
|
@@ -50171,6 +50373,18 @@ ${peek.userText}`;
|
|
|
50171
50373
|
try {
|
|
50172
50374
|
let lastAssistantMessage = null;
|
|
50173
50375
|
let promptForTurn = spliceIntoText(userText, pendingDigests);
|
|
50376
|
+
const correctivePromptForLiveRoster = (prompt, source) => {
|
|
50377
|
+
const safe = capabilitySafeCorrectivePrompt({
|
|
50378
|
+
prompt,
|
|
50379
|
+
availableTools: liveTurnToolNames(liveSession)
|
|
50380
|
+
});
|
|
50381
|
+
if (safe !== prompt.trim()) {
|
|
50382
|
+
log52.warn(
|
|
50383
|
+
`session ${sessionId2}: filtered ${source} corrective against the live tool roster`
|
|
50384
|
+
);
|
|
50385
|
+
}
|
|
50386
|
+
return safe;
|
|
50387
|
+
};
|
|
50174
50388
|
const freshGameState = await this.refreshLeanGameState(state.record, userText);
|
|
50175
50389
|
if (freshGameState) {
|
|
50176
50390
|
promptForTurn = `${freshGameState}
|
|
@@ -50181,7 +50395,8 @@ ${promptForTurn}`;
|
|
|
50181
50395
|
this.taskBudget.reset(state.record.taskRef);
|
|
50182
50396
|
this.pendingBudgetNudge.delete(state.record.taskRef);
|
|
50183
50397
|
}
|
|
50184
|
-
const
|
|
50398
|
+
const messageOrigin = resolveTurnMessageOrigin(opts);
|
|
50399
|
+
const preludeForTurn = await this.resolveUserPromptPrelude(state, userText, messageOrigin);
|
|
50185
50400
|
if (preludeForTurn) {
|
|
50186
50401
|
promptForTurn = `${preludeForTurn.text}
|
|
50187
50402
|
|
|
@@ -50204,7 +50419,7 @@ ${promptForTurn}`;
|
|
|
50204
50419
|
}
|
|
50205
50420
|
if (state.record.taskRef && this.pendingBudgetNudge.has(state.record.taskRef)) {
|
|
50206
50421
|
this.pendingBudgetNudge.delete(state.record.taskRef);
|
|
50207
|
-
promptForTurn = `${TASK_BUDGET_NUDGE}
|
|
50422
|
+
promptForTurn = `${correctivePromptForLiveRoster(TASK_BUDGET_NUDGE, "task-budget")}
|
|
50208
50423
|
|
|
50209
50424
|
${promptForTurn}`;
|
|
50210
50425
|
log52.info(
|
|
@@ -50213,6 +50428,7 @@ ${promptForTurn}`;
|
|
|
50213
50428
|
}
|
|
50214
50429
|
let continuations = 0;
|
|
50215
50430
|
const maxContinuations = resolveContinuationBudget(state);
|
|
50431
|
+
let voormanIdleNudged = false;
|
|
50216
50432
|
const toolsAcrossContinuations = [];
|
|
50217
50433
|
let compactionsThisSend = 0;
|
|
50218
50434
|
let keurmeesterConsultedThisSend = false;
|
|
@@ -50476,6 +50692,7 @@ ${state.aboutSnapshot}`);
|
|
|
50476
50692
|
const detectorVerdict = runPostTurnDetectors(state, {
|
|
50477
50693
|
sessionId: sessionId2,
|
|
50478
50694
|
isMeester: cfgForDetector?.meesterGezelId === state.record.gezelId,
|
|
50695
|
+
messageOrigin,
|
|
50479
50696
|
userText,
|
|
50480
50697
|
drained: toolsAcrossContinuations,
|
|
50481
50698
|
assistantContent: assistantMessage.content,
|
|
@@ -50489,7 +50706,10 @@ ${state.aboutSnapshot}`);
|
|
|
50489
50706
|
this.events.publish(scope, { type: "warning", message: warningMessage });
|
|
50490
50707
|
}
|
|
50491
50708
|
if (detectorVerdict?.promptForNextTurn) {
|
|
50492
|
-
detectorReprompt =
|
|
50709
|
+
detectorReprompt = correctivePromptForLiveRoster(
|
|
50710
|
+
detectorVerdict.promptForNextTurn,
|
|
50711
|
+
"post-turn detector"
|
|
50712
|
+
);
|
|
50493
50713
|
}
|
|
50494
50714
|
const advanceOutcome = await this.maybeAutoAdvanceOnObservableProgress(
|
|
50495
50715
|
state,
|
|
@@ -50640,7 +50860,10 @@ ${state.aboutSnapshot}`);
|
|
|
50640
50860
|
log52.info(
|
|
50641
50861
|
`session ${sessionId2}: keurmeester intervention applied (case ${consult.caseId}) \u2014 granting one recovery continuation`
|
|
50642
50862
|
);
|
|
50643
|
-
promptForTurn =
|
|
50863
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50864
|
+
consult.correctivePrompt,
|
|
50865
|
+
"keurmeester"
|
|
50866
|
+
);
|
|
50644
50867
|
continue;
|
|
50645
50868
|
}
|
|
50646
50869
|
}
|
|
@@ -50658,7 +50881,10 @@ ${state.aboutSnapshot}`);
|
|
|
50658
50881
|
log52.info(
|
|
50659
50882
|
`session ${sessionId2}: ${detectorVerdict?.reason ?? "detector"} \u2014 re-prompting`
|
|
50660
50883
|
);
|
|
50661
|
-
promptForTurn =
|
|
50884
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50885
|
+
detectorReprompt,
|
|
50886
|
+
detectorVerdict ? "post-turn detector" : "deliverable salvage"
|
|
50887
|
+
);
|
|
50662
50888
|
continue;
|
|
50663
50889
|
}
|
|
50664
50890
|
if (advanceOutcome.gateRejected && !advanceOutcome.gateRejected.paused && advanceOutcome.gateRejected.fingerprint !== state.lastGateNudgeFingerprint && !drained.some((d) => d.name === "ask_user_question" && d.success)) {
|
|
@@ -50668,7 +50894,10 @@ ${state.aboutSnapshot}`);
|
|
|
50668
50894
|
log52.info(
|
|
50669
50895
|
`session ${sessionId2}: ${advanceOutcome.gateRejected.taskRef} step "${advanceOutcome.gateRejected.stepId}" gate rejected \u2014 re-prompting with the verdict${stage > 0 ? ` (escalation stage ${stage})` : ""}`
|
|
50670
50896
|
);
|
|
50671
|
-
promptForTurn =
|
|
50897
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50898
|
+
stage >= 1 ? advanceOutcome.gateRejected.message : buildGateRejectionNudge(advanceOutcome.gateRejected.message),
|
|
50899
|
+
"task-gate"
|
|
50900
|
+
);
|
|
50672
50901
|
continue;
|
|
50673
50902
|
}
|
|
50674
50903
|
if (deliverableOutcome.deliverableRejected?.stopRetrying) {
|
|
@@ -50719,7 +50948,10 @@ ${state.aboutSnapshot}`);
|
|
|
50719
50948
|
log52.info(
|
|
50720
50949
|
`session ${sessionId2}: keurmeester intervention applied on deliverable plateau (case ${consult.caseId}) \u2014 granting one recovery continuation`
|
|
50721
50950
|
);
|
|
50722
|
-
promptForTurn =
|
|
50951
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50952
|
+
consult.correctivePrompt,
|
|
50953
|
+
"keurmeester deliverable-plateau"
|
|
50954
|
+
);
|
|
50723
50955
|
continue;
|
|
50724
50956
|
}
|
|
50725
50957
|
}
|
|
@@ -50743,7 +50975,10 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50743
50975
|
...dRej.filePath ? { filePath: dRej.filePath } : {},
|
|
50744
50976
|
failingVerdict: dRej.message
|
|
50745
50977
|
});
|
|
50746
|
-
promptForTurn =
|
|
50978
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50979
|
+
clampNudge ?? (dStage >= 1 ? dRej.message : buildGateRejectionNudge(dRej.message)),
|
|
50980
|
+
"deliverable-gate"
|
|
50981
|
+
);
|
|
50747
50982
|
continue;
|
|
50748
50983
|
}
|
|
50749
50984
|
if (advanceOutcome.unmetEditGate && (looksStalled(finalContent) || claimsCompletion(finalContent)) && !drained.some((d) => d.name === "ask_user_question" && d.success)) {
|
|
@@ -50751,7 +50986,10 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50751
50986
|
log52.info(
|
|
50752
50987
|
`session ${sessionId2}: ${advanceOutcome.unmetEditGate.taskRef} edit gate unmet (${advanceOutcome.unmetEditGate.file} not written) but reply claims progress \u2014 nudging to edit`
|
|
50753
50988
|
);
|
|
50754
|
-
promptForTurn =
|
|
50989
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50990
|
+
buildDeliverableEditNudge(advanceOutcome.unmetEditGate.file),
|
|
50991
|
+
"deliverable-edit"
|
|
50992
|
+
);
|
|
50755
50993
|
continue;
|
|
50756
50994
|
}
|
|
50757
50995
|
const unresolvedToolFailures = unresolvedFailedToolCalls(drained);
|
|
@@ -50795,7 +51033,7 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50795
51033
|
// the hot path synchronous for the common non-voorman case.
|
|
50796
51034
|
// Also requires `proactive` — voorman idle nudges advance
|
|
50797
51035
|
// project work past what the user asked for.
|
|
50798
|
-
isProactiveAllowed(nudgeConfig) && state.record.providerName !== "copilot"
|
|
51036
|
+
isProactiveAllowed(nudgeConfig) && state.record.providerName !== "copilot" && !voormanIdleNudged
|
|
50799
51037
|
) {
|
|
50800
51038
|
voormanIdleVerdict = await this.didVoormanIdleStall(state.record, drained, sessionId2);
|
|
50801
51039
|
if (voormanIdleVerdict !== null) {
|
|
@@ -50813,15 +51051,19 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50813
51051
|
);
|
|
50814
51052
|
break;
|
|
50815
51053
|
}
|
|
51054
|
+
if (stallReason === "voorman-idle") voormanIdleNudged = true;
|
|
50816
51055
|
continuations++;
|
|
50817
51056
|
log52.info(
|
|
50818
|
-
`session ${sessionId2}: response looks stalled (${stallReason}) \u2014
|
|
51057
|
+
`session ${sessionId2}: response looks stalled (${stallReason}) \u2014 requesting one recovery pass`
|
|
51058
|
+
);
|
|
51059
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
51060
|
+
stallReason === "voorman-idle" ? buildContinuationNudge(
|
|
51061
|
+
finalContent,
|
|
51062
|
+
state.record.messages,
|
|
51063
|
+
voormanIdleVerdict === "nothing-built" ? VOORMAN_NOT_DONE_NUDGE : VOORMAN_IDLE_NUDGE
|
|
51064
|
+
) : stallReason === "tool-only" ? CLOSING_SUMMARY_NUDGE : stallReason === "tool-read-only" ? READ_ONLY_PROGRESS_NUDGE : stallReason === "tool-failed" ? buildFailedToolRecoveryNudge(unresolvedToolFailures) : buildContinuationNudge(finalContent, state.record.messages),
|
|
51065
|
+
`stall-${stallReason}`
|
|
50819
51066
|
);
|
|
50820
|
-
promptForTurn = stallReason === "voorman-idle" ? buildContinuationNudge(
|
|
50821
|
-
finalContent,
|
|
50822
|
-
state.record.messages,
|
|
50823
|
-
voormanIdleVerdict === "nothing-built" ? VOORMAN_NOT_DONE_NUDGE : VOORMAN_IDLE_NUDGE
|
|
50824
|
-
) : stallReason === "tool-only" ? CLOSING_SUMMARY_NUDGE : stallReason === "tool-read-only" ? READ_ONLY_PROGRESS_NUDGE : stallReason === "tool-failed" ? buildFailedToolRecoveryNudge(unresolvedToolFailures) : buildContinuationNudge(finalContent, state.record.messages);
|
|
50825
51067
|
continue;
|
|
50826
51068
|
}
|
|
50827
51069
|
}
|
|
@@ -51387,7 +51629,7 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
51387
51629
|
return null;
|
|
51388
51630
|
}
|
|
51389
51631
|
const tasks = await this.store.listProjectTasks(record.projectId).catch(() => []);
|
|
51390
|
-
if (tasks.length
|
|
51632
|
+
if (tasks.length === 0 || !tasks.some((t) => t.status === "active")) {
|
|
51391
51633
|
return null;
|
|
51392
51634
|
}
|
|
51393
51635
|
const workspaceFiles = await this.store.listProjectWorkspaceRecursive(record.projectId).catch(() => []);
|
|
@@ -54138,7 +54380,7 @@ ${baseSystem}` : baseSystem;
|
|
|
54138
54380
|
return { modelId };
|
|
54139
54381
|
}
|
|
54140
54382
|
}
|
|
54141
|
-
async resolveUserPromptPrelude(state, userText) {
|
|
54383
|
+
async resolveUserPromptPrelude(state, userText, messageOrigin) {
|
|
54142
54384
|
const profile = state.profile;
|
|
54143
54385
|
if (!profile) return null;
|
|
54144
54386
|
const cfg = await this.store.readConfig().catch(() => null);
|
|
@@ -54147,6 +54389,9 @@ ${baseSystem}` : baseSystem;
|
|
|
54147
54389
|
...modelCtxFromProfile(profile, state),
|
|
54148
54390
|
sessionId: state.record.id,
|
|
54149
54391
|
isMeester,
|
|
54392
|
+
projectId: state.record.projectId,
|
|
54393
|
+
messageOrigin,
|
|
54394
|
+
availableToolNames: liveTurnToolNames(state.session),
|
|
54150
54395
|
userText,
|
|
54151
54396
|
drained: [],
|
|
54152
54397
|
assistantContent: "",
|
|
@@ -55467,6 +55712,7 @@ Allow **${info.toolName}** this time?`,
|
|
|
55467
55712
|
GEZEL_SESSION_ID: record.id,
|
|
55468
55713
|
GEZEL_HOME: this.home,
|
|
55469
55714
|
GEZEL_EXECUTION_DENSITY: executionDensity,
|
|
55715
|
+
GEZEL_ROLE_BASED_NAME_ONLY_MODE: record.roleBasedNameOnlyMode ?? globalConfig.roleBasedNameOnlyMode ?? false ? "1" : "0",
|
|
55470
55716
|
...record.expectedDeliverable ? { GEZEL_EXPECTED_DELIVERABLE: JSON.stringify(record.expectedDeliverable) } : {},
|
|
55471
55717
|
...record.stepId ? { GEZEL_STEP_ID: record.stepId } : {},
|
|
55472
55718
|
// Scope task: lets the MCP task tools default to / recover toward
|
|
@@ -55906,6 +56152,9 @@ function runPostTurnDetectors(state, args) {
|
|
|
55906
56152
|
...modelCtxFromProfile(profile, state),
|
|
55907
56153
|
sessionId: args.sessionId,
|
|
55908
56154
|
isMeester: args.isMeester,
|
|
56155
|
+
projectId: state.record.projectId,
|
|
56156
|
+
messageOrigin: args.messageOrigin,
|
|
56157
|
+
availableToolNames: liveTurnToolNames(state.session),
|
|
55909
56158
|
userText: args.userText,
|
|
55910
56159
|
drained: args.drained,
|
|
55911
56160
|
assistantContent: args.assistantContent,
|
|
@@ -56154,6 +56403,14 @@ function messageExpressesModifyIntent(text) {
|
|
|
56154
56403
|
)
|
|
56155
56404
|
);
|
|
56156
56405
|
}
|
|
56406
|
+
function fileHandoffIntentKey(text) {
|
|
56407
|
+
const repair = messageExpressesModifyIntent(text) || /\[scenario check\]|\b(?:specific failure|signals? that (?:didn't|did not) fire|success criteria (?:aren't|are not) met|repeat miss|gate_full_rewrite|rejected)\b/i.test(
|
|
56408
|
+
text
|
|
56409
|
+
);
|
|
56410
|
+
if (!repair) return "create";
|
|
56411
|
+
const normalized2 = text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
56412
|
+
return `repair:${createHash12("sha256").update(normalized2).digest("hex").slice(0, 16)}`;
|
|
56413
|
+
}
|
|
56157
56414
|
function isSubstantiveExistingWorkspaceFile(filePath2, content) {
|
|
56158
56415
|
const trimmed = content.trim();
|
|
56159
56416
|
if (!trimmed) return false;
|
|
@@ -56438,13 +56695,18 @@ Drop conversational filler, pleasantries, and verbatim tool outputs (just note "
|
|
|
56438
56695
|
Earlier conversation:
|
|
56439
56696
|
|
|
56440
56697
|
`;
|
|
56441
|
-
var VOORMAN_IDLE_NUDGE =
|
|
56698
|
+
var VOORMAN_IDLE_NUDGE = "Before you finish, make one quick project check: is there concrete work already in flight that this turn should move? If yes, take the natural next action with the most relevant available tool \u2014 advance a ready step, message or assign the right gezel, or surface a real blocker. If no \u2014 because the project is complete, stable, or waiting on the user \u2014 say that once in one short sentence and end the turn. Do not invent work or call a tool merely to satisfy this check. Do not re-verify or promise future action.";
|
|
56442
56699
|
var BOOTSTRAP_WORKSPACE_FILES = /* @__PURE__ */ new Set([
|
|
56443
56700
|
"package.json",
|
|
56701
|
+
"package-lock.json",
|
|
56702
|
+
"pnpm-lock.yaml",
|
|
56703
|
+
"yarn.lock",
|
|
56704
|
+
"bun.lock",
|
|
56705
|
+
"bun.lockb",
|
|
56444
56706
|
"tsconfig.json",
|
|
56445
56707
|
".gitignore"
|
|
56446
56708
|
]);
|
|
56447
|
-
var VOORMAN_NOT_DONE_NUDGE = "
|
|
56709
|
+
var VOORMAN_NOT_DONE_NUDGE = "One project-state check before you finish: an active task remains, but the workspace still contains only setup files, so no deliverable has been built yet. If the user only asked for status or conversation, answer accurately and stop; a tool is not required. If this turn is supposed to move the active work, take one natural next action: message or assign the specialist who owns the deliverable, advance a genuinely ready step, or surface a real blocker with `ask_user_question`. Do not invent work or call a tool merely to appear busy, and do not describe an active empty project as done or stable.";
|
|
56448
56710
|
var READ_ONLY_MCP_TOOLS = /* @__PURE__ */ new Set([
|
|
56449
56711
|
"search_memory",
|
|
56450
56712
|
"list_memories",
|
|
@@ -56645,7 +56907,7 @@ function growthSignature(gezel) {
|
|
|
56645
56907
|
|
|
56646
56908
|
// src/codex-setup/manager.ts
|
|
56647
56909
|
init_atomic();
|
|
56648
|
-
import { createHash as
|
|
56910
|
+
import { createHash as createHash13 } from "crypto";
|
|
56649
56911
|
import { realpathSync as realpathSync2 } from "fs";
|
|
56650
56912
|
import { chmod as chmod4, mkdir as mkdir15, readFile as readFile16, rm as rm6 } from "fs/promises";
|
|
56651
56913
|
import { homedir as homedir3 } from "os";
|
|
@@ -57396,7 +57658,7 @@ function canonicalPath(path2) {
|
|
|
57396
57658
|
}
|
|
57397
57659
|
}
|
|
57398
57660
|
function sha256(value) {
|
|
57399
|
-
return
|
|
57661
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
57400
57662
|
}
|
|
57401
57663
|
function catalogModelFor(model) {
|
|
57402
57664
|
const contextWindow = model.contextWindow ?? 32768;
|
|
@@ -57821,7 +58083,7 @@ init_mcp_bridge();
|
|
|
57821
58083
|
|
|
57822
58084
|
// src/connectors/writer.ts
|
|
57823
58085
|
init_atomic();
|
|
57824
|
-
import { createHash as
|
|
58086
|
+
import { createHash as createHash14 } from "crypto";
|
|
57825
58087
|
import { mkdir as mkdir16, readFile as readFile17, readdir as readdir9, rm as rm7, stat as stat11 } from "fs/promises";
|
|
57826
58088
|
import { basename as basename7, join as join30 } from "path";
|
|
57827
58089
|
import { projectLocalQuarantineDir } from "@bendyline/gezel/paths";
|
|
@@ -58094,7 +58356,7 @@ var StaticContentScanner = class {
|
|
|
58094
58356
|
var contentScanner = new StaticContentScanner();
|
|
58095
58357
|
|
|
58096
58358
|
// src/connectors/writer.ts
|
|
58097
|
-
var sha8 = (s) =>
|
|
58359
|
+
var sha8 = (s) => createHash14("sha256").update(s).digest("hex").slice(0, 8);
|
|
58098
58360
|
function slug(input, max = 48) {
|
|
58099
58361
|
const s = input.normalize("NFKD").replace(/[^\x20-\x7E]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max).replace(/-+$/g, "");
|
|
58100
58362
|
return s || "x";
|
|
@@ -58111,7 +58373,7 @@ function contentHash(record) {
|
|
|
58111
58373
|
const attachments = (record.attachments ?? []).map((attachment) => ({
|
|
58112
58374
|
filename: attachment.filename,
|
|
58113
58375
|
size: attachment.size ?? attachment.content?.byteLength ?? 0,
|
|
58114
|
-
sha256: attachment.sha256 ??
|
|
58376
|
+
sha256: attachment.sha256 ?? createHash14("sha256").update(attachment.content).digest("hex")
|
|
58115
58377
|
}));
|
|
58116
58378
|
return sha8(
|
|
58117
58379
|
`${JSON.stringify(sortedFrontmatter)}
|
|
@@ -59182,10 +59444,10 @@ var SpectralConnectorAdapter = class {
|
|
|
59182
59444
|
};
|
|
59183
59445
|
|
|
59184
59446
|
// src/connectors/oauth.ts
|
|
59185
|
-
import { createHash as
|
|
59447
|
+
import { createHash as createHash15, randomBytes as randomBytes3 } from "crypto";
|
|
59186
59448
|
function createPkce() {
|
|
59187
59449
|
const verifier = randomBytes3(32).toString("base64url");
|
|
59188
|
-
const challenge =
|
|
59450
|
+
const challenge = createHash15("sha256").update(verifier).digest("base64url");
|
|
59189
59451
|
return { verifier, challenge };
|
|
59190
59452
|
}
|
|
59191
59453
|
function randomState() {
|
|
@@ -63870,7 +64132,7 @@ function registerGitHubPullsAdapters(runtime) {
|
|
|
63870
64132
|
}
|
|
63871
64133
|
|
|
63872
64134
|
// src/connectors/natives/github-releases.ts
|
|
63873
|
-
import { createHash as
|
|
64135
|
+
import { createHash as createHash16 } from "crypto";
|
|
63874
64136
|
import { mkdir as mkdir21, mkdtemp as mkdtemp3, open as open2, rm as rm13 } from "fs/promises";
|
|
63875
64137
|
import { tmpdir as tmpdir3 } from "os";
|
|
63876
64138
|
import { basename as basename8, join as join35 } from "path";
|
|
@@ -64063,7 +64325,7 @@ var GitHubReleasesAdapter = class {
|
|
|
64063
64325
|
}
|
|
64064
64326
|
}
|
|
64065
64327
|
this.releases = releases;
|
|
64066
|
-
this.fingerprint =
|
|
64328
|
+
this.fingerprint = createHash16("sha256").update(JSON.stringify(releases)).digest("hex");
|
|
64067
64329
|
}
|
|
64068
64330
|
apiHeaders(accept) {
|
|
64069
64331
|
return {
|
|
@@ -64126,7 +64388,7 @@ var GitHubReleasesAdapter = class {
|
|
|
64126
64388
|
};
|
|
64127
64389
|
async function streamResponseToFile(response, path2) {
|
|
64128
64390
|
const handle = await open2(path2, "wx");
|
|
64129
|
-
const hash =
|
|
64391
|
+
const hash = createHash16("sha256");
|
|
64130
64392
|
let size = 0;
|
|
64131
64393
|
try {
|
|
64132
64394
|
for await (const raw of response.body) {
|
|
@@ -66506,7 +66768,7 @@ var DebugFlag = class {
|
|
|
66506
66768
|
|
|
66507
66769
|
// src/digest/generator.ts
|
|
66508
66770
|
init_atomic();
|
|
66509
|
-
import { createHash as
|
|
66771
|
+
import { createHash as createHash17 } from "crypto";
|
|
66510
66772
|
import { readFile as readFile25 } from "fs/promises";
|
|
66511
66773
|
import { join as join40 } from "path";
|
|
66512
66774
|
import {
|
|
@@ -69655,7 +69917,7 @@ var ProjectDigestGenerator = class {
|
|
|
69655
69917
|
if (commits.length === 0 && sessions.length === 0 && events.length < MIN_EVENTS_FOR_DIGEST) {
|
|
69656
69918
|
return false;
|
|
69657
69919
|
}
|
|
69658
|
-
const inputHash =
|
|
69920
|
+
const inputHash = createHash17("sha256").update(
|
|
69659
69921
|
[
|
|
69660
69922
|
week,
|
|
69661
69923
|
...commits,
|
|
@@ -69812,7 +70074,7 @@ function describe4(err) {
|
|
|
69812
70074
|
}
|
|
69813
70075
|
|
|
69814
70076
|
// src/engines/electron-native-reuse.ts
|
|
69815
|
-
import { createHash as
|
|
70077
|
+
import { createHash as createHash18 } from "crypto";
|
|
69816
70078
|
import { createReadStream as createReadStream3 } from "fs";
|
|
69817
70079
|
import { lstat as lstat2, readdir as readdir13, readlink } from "fs/promises";
|
|
69818
70080
|
import { basename as basename11, join as join41, posix, relative as relative5, resolve as resolve8, sep as sep5 } from "path";
|
|
@@ -71432,7 +71694,7 @@ function enclosingMacApp(path2) {
|
|
|
71432
71694
|
var HASH_READ_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
71433
71695
|
function sha256File2(path2) {
|
|
71434
71696
|
return new Promise((resolveHash, reject) => {
|
|
71435
|
-
const hash =
|
|
71697
|
+
const hash = createHash18("sha256");
|
|
71436
71698
|
const stream = createReadStream3(path2, { highWaterMark: HASH_READ_BUFFER_BYTES });
|
|
71437
71699
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
71438
71700
|
stream.on("error", reject);
|
|
@@ -71444,7 +71706,7 @@ function sha256File2(path2) {
|
|
|
71444
71706
|
import { createLogger as createLogger69 } from "@bendyline/gezel";
|
|
71445
71707
|
|
|
71446
71708
|
// src/engines/resolver.ts
|
|
71447
|
-
import { createHash as
|
|
71709
|
+
import { createHash as createHash19 } from "crypto";
|
|
71448
71710
|
import { createReadStream as createReadStream4, existsSync as existsSync7 } from "fs";
|
|
71449
71711
|
import { chmod as chmod5, mkdir as mkdir24, readFile as readFile26, rename as rename7, rm as rm16, writeFile as writeFile9 } from "fs/promises";
|
|
71450
71712
|
import { join as join42 } from "path";
|
|
@@ -71568,7 +71830,7 @@ async function* resolveEngine(opts) {
|
|
|
71568
71830
|
);
|
|
71569
71831
|
}
|
|
71570
71832
|
const sumsBytes = await ghBytes(sumsAsset.url, baseFetch, token);
|
|
71571
|
-
const sumsDigest =
|
|
71833
|
+
const sumsDigest = createHash19("sha256").update(sumsBytes).digest("hex");
|
|
71572
71834
|
if (!unpinned && sumsDigest !== expectedDigest) {
|
|
71573
71835
|
yield* fail(
|
|
71574
71836
|
`SHA256SUMS digest mismatch for ${tag}: this build pins ${expectedDigest.slice(0, 16)}\u2026 but the release served ${sumsDigest.slice(0, 16)}\u2026. Refusing \u2014 the release may have been tampered with or re-cut.`
|
|
@@ -71818,7 +72080,7 @@ function parseSums(text) {
|
|
|
71818
72080
|
}
|
|
71819
72081
|
var HASH_READ_BUFFER_BYTES2 = 16 * 1024 * 1024;
|
|
71820
72082
|
async function sha256File3(path2) {
|
|
71821
|
-
const hash =
|
|
72083
|
+
const hash = createHash19("sha256");
|
|
71822
72084
|
await new Promise((resolve18, reject) => {
|
|
71823
72085
|
const stream = createReadStream4(path2, { highWaterMark: HASH_READ_BUFFER_BYTES2 });
|
|
71824
72086
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
@@ -72701,7 +72963,7 @@ function safeBasename(name) {
|
|
|
72701
72963
|
}
|
|
72702
72964
|
|
|
72703
72965
|
// src/fs/store.ts
|
|
72704
|
-
import { createHash as
|
|
72966
|
+
import { createHash as createHash21, randomUUID as randomUUID10 } from "crypto";
|
|
72705
72967
|
import {
|
|
72706
72968
|
appendFile as appendFile4,
|
|
72707
72969
|
chmod as chmod7,
|
|
@@ -73110,7 +73372,7 @@ function countDiffLines(diff) {
|
|
|
73110
73372
|
}
|
|
73111
73373
|
|
|
73112
73374
|
// src/workspace/journal.ts
|
|
73113
|
-
import { createHash as
|
|
73375
|
+
import { createHash as createHash20 } from "crypto";
|
|
73114
73376
|
import { appendFile as appendFile2, mkdir as mkdir27, readFile as readFile29 } from "fs/promises";
|
|
73115
73377
|
import { dirname as dirname26, join as join43 } from "path";
|
|
73116
73378
|
import { projectPrivateDir as projectPrivateDir2 } from "@bendyline/gezel/paths";
|
|
@@ -73153,7 +73415,7 @@ async function readJournalTail(home, projectId, limit = 100) {
|
|
|
73153
73415
|
}
|
|
73154
73416
|
}
|
|
73155
73417
|
function sha2562(content) {
|
|
73156
|
-
return
|
|
73418
|
+
return createHash20("sha256").update(content).digest("hex");
|
|
73157
73419
|
}
|
|
73158
73420
|
|
|
73159
73421
|
// src/workspace/template.ts
|
|
@@ -74020,7 +74282,7 @@ function boekwachterIssueFingerprint(path2, issue) {
|
|
|
74020
74282
|
issue.category.trim().toLocaleLowerCase(),
|
|
74021
74283
|
issue.message.trim().toLocaleLowerCase().replace(/\s+/g, " ")
|
|
74022
74284
|
].join("\0");
|
|
74023
|
-
return
|
|
74285
|
+
return createHash21("sha256").update(normalized2).digest("hex");
|
|
74024
74286
|
}
|
|
74025
74287
|
var ConfigCorruptionError = class extends Error {
|
|
74026
74288
|
code = "CONFIG_CORRUPT";
|
|
@@ -75768,6 +76030,7 @@ ${p.content.trim()}`).join("\n\n---\n\n");
|
|
|
75768
76030
|
async createProject(input, opts) {
|
|
75769
76031
|
const release2 = await this.acquireProjectCreationLock();
|
|
75770
76032
|
try {
|
|
76033
|
+
if (input.workingDir) this.assertSafeWorkingDir(input.workingDir);
|
|
75771
76034
|
const id = opts?.id ?? await this.uniqueProjectId(slugify(input.name) || randomUUID10().slice(0, 8));
|
|
75772
76035
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(id)) {
|
|
75773
76036
|
throw new Error(`invalid project id "${id}"`);
|
|
@@ -75791,14 +76054,22 @@ ${p.content.trim()}`).join("\n\n---\n\n");
|
|
|
75791
76054
|
projectName: input.name
|
|
75792
76055
|
});
|
|
75793
76056
|
}
|
|
76057
|
+
let github = input.github?.url ? { url: input.github.url } : void 0;
|
|
76058
|
+
if (input.workingDir) {
|
|
76059
|
+
github = await autoDetectGitHubLink(input.workingDir, github) ?? github;
|
|
76060
|
+
}
|
|
75794
76061
|
const project = {
|
|
75795
76062
|
id,
|
|
75796
76063
|
name: input.name,
|
|
75797
76064
|
description: input.description,
|
|
75798
76065
|
...input.workingDir ? { workingDir: input.workingDir } : {},
|
|
76066
|
+
// Opening an existing folder is an intake action, not a declaration
|
|
76067
|
+
// that its objectives are ready for active supervision. Keep the
|
|
76068
|
+
// Meester quiet until the user explicitly opts this project back in.
|
|
76069
|
+
...input.workingDir ? { nudgeConfig: { enabled: false } } : {},
|
|
75799
76070
|
...input.mode && input.mode !== "crew" ? { mode: input.mode } : {},
|
|
75800
76071
|
...input.indexingEnabled !== void 0 ? { indexingEnabled: input.indexingEnabled } : {},
|
|
75801
|
-
...
|
|
76072
|
+
...github ? { github } : {},
|
|
75802
76073
|
createdAt: nowIso5(),
|
|
75803
76074
|
updatedAt: nowIso5()
|
|
75804
76075
|
};
|
|
@@ -79473,7 +79744,7 @@ import { projectCodeReviewsFile } from "@bendyline/gezel/paths";
|
|
|
79473
79744
|
import { createLogger as createLogger77, projectAllowsAmbientWork } from "@bendyline/gezel";
|
|
79474
79745
|
|
|
79475
79746
|
// src/tasks/manager.ts
|
|
79476
|
-
import { createHash as
|
|
79747
|
+
import { createHash as createHash22, randomUUID as randomUUID12 } from "crypto";
|
|
79477
79748
|
import {
|
|
79478
79749
|
DEFAULT_NIGHT_SHIFT_WINDOW,
|
|
79479
79750
|
MANAGED_WORKSPACE_WRITE_SETTING_LABEL as MANAGED_WORKSPACE_WRITE_SETTING_LABEL4,
|
|
@@ -80250,6 +80521,7 @@ var TaskManager = class {
|
|
|
80250
80521
|
...cron ? { cron } : {},
|
|
80251
80522
|
...nightShift ? { nightShift } : {},
|
|
80252
80523
|
...fanout ? { fanout } : {},
|
|
80524
|
+
...input.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: input.roleBasedNameOnlyMode } : {},
|
|
80253
80525
|
createdAt: now,
|
|
80254
80526
|
updatedAt: now,
|
|
80255
80527
|
createdBy: input.createdBy ?? { kind: "user" }
|
|
@@ -81324,7 +81596,7 @@ ${paramLines}` : ""}`,
|
|
|
81324
81596
|
if (step.advanceWhen?.file) {
|
|
81325
81597
|
const content = await (step.advanceWhen.artifact ? this.store.readProjectArtifact(projectId, step.advanceWhen.file) : this.store.readProjectWorkspaceFile(projectId, step.advanceWhen.file)).catch(() => null);
|
|
81326
81598
|
if (content !== null) {
|
|
81327
|
-
contentHash2 =
|
|
81599
|
+
contentHash2 = createHash22("sha256").update(content).digest("hex");
|
|
81328
81600
|
}
|
|
81329
81601
|
}
|
|
81330
81602
|
if (contentHash2 !== void 0 && step.lastGateReject?.contentHash !== void 0 && step.lastGateReject.contentHash === contentHash2) {
|
|
@@ -82244,6 +82516,7 @@ Fix one of these, then set the task active again:
|
|
|
82244
82516
|
...parent.nightShift?.enabled ? { nightShift: { enabled: true } } : {},
|
|
82245
82517
|
activeStepId,
|
|
82246
82518
|
parentTaskRef: parent.ref,
|
|
82519
|
+
...parent.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: parent.roleBasedNameOnlyMode } : {},
|
|
82247
82520
|
createdAt: now,
|
|
82248
82521
|
updatedAt: now,
|
|
82249
82522
|
createdBy: parent.createdBy
|
|
@@ -82990,7 +83263,7 @@ function sumStat(s, key) {
|
|
|
82990
83263
|
}
|
|
82991
83264
|
|
|
82992
83265
|
// src/grants/manager.ts
|
|
82993
|
-
import { createHash as
|
|
83266
|
+
import { createHash as createHash23, randomBytes as randomBytes5, randomUUID as randomUUID13, timingSafeEqual } from "crypto";
|
|
82994
83267
|
import { chmod as chmod8 } from "fs/promises";
|
|
82995
83268
|
import { pendingGrantsFile as defaultPendingGrantsFile } from "@bendyline/gezel/paths";
|
|
82996
83269
|
var PENDING_GRANT_TTL_MS = 10 * 6e4;
|
|
@@ -83062,7 +83335,7 @@ function generateVerificationCode() {
|
|
|
83062
83335
|
return `${raw.slice(0, 3)}-${raw.slice(3)}`;
|
|
83063
83336
|
}
|
|
83064
83337
|
function hashVerificationCode(salt, normalizedCode) {
|
|
83065
|
-
return
|
|
83338
|
+
return createHash23("sha256").update(salt, "base64url").update("\0").update(normalizedCode, "ascii").digest();
|
|
83066
83339
|
}
|
|
83067
83340
|
function codeMatches(grant, suppliedCode) {
|
|
83068
83341
|
const normalized2 = normalizeVerificationCode(suppliedCode);
|
|
@@ -84982,7 +85255,7 @@ function tokenize2(question) {
|
|
|
84982
85255
|
}
|
|
84983
85256
|
|
|
84984
85257
|
// src/http/cert.ts
|
|
84985
|
-
import { createHash as
|
|
85258
|
+
import { createHash as createHash24 } from "crypto";
|
|
84986
85259
|
import { generate as selfsignedGenerate } from "selfsigned";
|
|
84987
85260
|
var CERT_VALIDITY_DAYS = 90;
|
|
84988
85261
|
async function generateLoopbackCert() {
|
|
@@ -85019,7 +85292,7 @@ async function generateLoopbackCert() {
|
|
|
85019
85292
|
]
|
|
85020
85293
|
});
|
|
85021
85294
|
const der = pemToDer(pems.cert);
|
|
85022
|
-
const digest =
|
|
85295
|
+
const digest = createHash24("sha256").update(der).digest();
|
|
85023
85296
|
return {
|
|
85024
85297
|
certPem: pems.cert,
|
|
85025
85298
|
keyPem: pems.private,
|
|
@@ -85033,14 +85306,14 @@ function pemToDer(pem) {
|
|
|
85033
85306
|
}
|
|
85034
85307
|
|
|
85035
85308
|
// src/http/codex-bridge-port.ts
|
|
85036
|
-
import { createHash as
|
|
85309
|
+
import { createHash as createHash25 } from "crypto";
|
|
85037
85310
|
import { realpathSync as realpathSync3 } from "fs";
|
|
85038
85311
|
import { resolve as resolve10 } from "path";
|
|
85039
85312
|
var CODEX_BRIDGE_PORT_RANGE_START = 2e4;
|
|
85040
85313
|
var CODEX_BRIDGE_PORT_RANGE_END = 49151;
|
|
85041
85314
|
var CODEX_BRIDGE_PORT_RANGE_SIZE = CODEX_BRIDGE_PORT_RANGE_END - CODEX_BRIDGE_PORT_RANGE_START + 1;
|
|
85042
85315
|
function codexBridgePortForHome(home) {
|
|
85043
|
-
const digest =
|
|
85316
|
+
const digest = createHash25("sha256").update(canonicalPath2(home)).digest();
|
|
85044
85317
|
const bucket = digest.readUInt32BE(0) % CODEX_BRIDGE_PORT_RANGE_SIZE;
|
|
85045
85318
|
return CODEX_BRIDGE_PORT_RANGE_START + bucket;
|
|
85046
85319
|
}
|
|
@@ -85266,7 +85539,7 @@ async function loadGezelByRef(ref, ctx) {
|
|
|
85266
85539
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
85267
85540
|
|
|
85268
85541
|
// src/http/openai-compat/responses-translate.ts
|
|
85269
|
-
import { createHash as
|
|
85542
|
+
import { createHash as createHash26 } from "crypto";
|
|
85270
85543
|
import { z as z11 } from "zod";
|
|
85271
85544
|
|
|
85272
85545
|
// src/http/openai-compat/translate.ts
|
|
@@ -85705,7 +85978,7 @@ var CUSTOM_TOOL_INPUT_KEY = "input";
|
|
|
85705
85978
|
function flattenResponsesNamespaceToolName(namespace, name) {
|
|
85706
85979
|
const joined = `${namespace}__${name}`;
|
|
85707
85980
|
if (joined.length <= MAX_LOCAL_TOOL_NAME_LENGTH) return joined;
|
|
85708
|
-
const digest =
|
|
85981
|
+
const digest = createHash26("sha256").update(namespace).update("\0").update(name).digest("hex").slice(0, 12);
|
|
85709
85982
|
const prefixLength = MAX_LOCAL_TOOL_NAME_LENGTH - digest.length - 2;
|
|
85710
85983
|
return `${joined.slice(0, prefixLength)}__${digest}`;
|
|
85711
85984
|
}
|
|
@@ -86935,7 +87208,7 @@ function mountMachineEngineHints(app) {
|
|
|
86935
87208
|
}
|
|
86936
87209
|
|
|
86937
87210
|
// src/http/preview-capability.ts
|
|
86938
|
-
import { createHash as
|
|
87211
|
+
import { createHash as createHash27, randomBytes as randomBytes6 } from "crypto";
|
|
86939
87212
|
import { posix as posix3 } from "path";
|
|
86940
87213
|
var DEFAULT_PREVIEW_CAPABILITY_TTL_MS = 10 * 60 * 1e3;
|
|
86941
87214
|
var DEFAULT_PREVIEW_CAPABILITY_ABSOLUTE_TTL_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -87079,7 +87352,7 @@ function pathIsInScope(path2, scopePath) {
|
|
|
87079
87352
|
return scopePath === "" || path2 === scopePath || path2.startsWith(`${scopePath}/`);
|
|
87080
87353
|
}
|
|
87081
87354
|
function tokenDigest(token) {
|
|
87082
|
-
return
|
|
87355
|
+
return createHash27("sha256").update(token).digest("base64url");
|
|
87083
87356
|
}
|
|
87084
87357
|
|
|
87085
87358
|
// src/http/routes/ai.ts
|
|
@@ -87448,6 +87721,15 @@ var KOKORO_HF_REPO = "onnx-community/Kokoro-82M-v1.0-ONNX";
|
|
|
87448
87721
|
var KOKORO_APPROX_BYTES_BY_ID = {
|
|
87449
87722
|
[KOKORO_DEFAULT_MODEL_ID]: 95e6
|
|
87450
87723
|
};
|
|
87724
|
+
function isKokoroRuntimeAvailable(resolveModule = (specifier) => import.meta.resolve(specifier)) {
|
|
87725
|
+
try {
|
|
87726
|
+
resolveModule("kokoro-js");
|
|
87727
|
+
resolveModule("@huggingface/transformers");
|
|
87728
|
+
return true;
|
|
87729
|
+
} catch {
|
|
87730
|
+
return false;
|
|
87731
|
+
}
|
|
87732
|
+
}
|
|
87451
87733
|
var KOKORO_DEFAULT_VOICES = [
|
|
87452
87734
|
{
|
|
87453
87735
|
id: "af_heart",
|
|
@@ -87777,7 +88059,7 @@ function parseGender(s) {
|
|
|
87777
88059
|
}
|
|
87778
88060
|
|
|
87779
88061
|
// src/providers/audio/whisper-cpp.ts
|
|
87780
|
-
import { createHash as
|
|
88062
|
+
import { createHash as createHash28 } from "crypto";
|
|
87781
88063
|
import { createReadStream as createReadStream5 } from "fs";
|
|
87782
88064
|
import { mkdir as mkdir37, readFile as readFile39, rename as rename11, rm as rm25, writeFile as writeFile14 } from "fs/promises";
|
|
87783
88065
|
import { basename as basename12, join as join52 } from "path";
|
|
@@ -88072,7 +88354,7 @@ async function* downloadWithSha256(fetchImpl, opts) {
|
|
|
88072
88354
|
yield { type: "progress", bytesWritten: writtenAll, totalBytes: totalAllBytes };
|
|
88073
88355
|
}
|
|
88074
88356
|
}
|
|
88075
|
-
const hasher =
|
|
88357
|
+
const hasher = createHash28("sha256");
|
|
88076
88358
|
await new Promise((resolve18, reject) => {
|
|
88077
88359
|
const stream = createReadStream5(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
88078
88360
|
stream.on("data", (chunk2) => hasher.update(chunk2));
|
|
@@ -88123,6 +88405,41 @@ function machineEngineProxy(ctx, sourcePrefix, targetPrefix, localPaths = [], sh
|
|
|
88123
88405
|
|
|
88124
88406
|
// src/http/routes/audio.ts
|
|
88125
88407
|
var log85 = createLogger88("audio");
|
|
88408
|
+
function buildAudioCatalog(options = {}) {
|
|
88409
|
+
const kokoroRuntimeAvailable = options.kokoroRuntimeAvailable ?? isKokoroRuntimeAvailable();
|
|
88410
|
+
return {
|
|
88411
|
+
// All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
|
|
88412
|
+
// Kokoro under Apache 2.0. Both are permissive → "Free, open".
|
|
88413
|
+
stt: WHISPER_MODEL_CATALOG.map((m) => ({
|
|
88414
|
+
id: m.id,
|
|
88415
|
+
name: m.name,
|
|
88416
|
+
description: m.description,
|
|
88417
|
+
approxSizeBytes: m.approxSizeBytes,
|
|
88418
|
+
kind: "stt",
|
|
88419
|
+
license: "MIT",
|
|
88420
|
+
licenseClass: "open",
|
|
88421
|
+
licenseShortName: "MIT",
|
|
88422
|
+
licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
|
|
88423
|
+
// The Base (English) variant is the recommended STT default: ~140 MB,
|
|
88424
|
+
// realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
|
|
88425
|
+
...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
|
|
88426
|
+
})),
|
|
88427
|
+
tts: kokoroRuntimeAvailable ? [
|
|
88428
|
+
{
|
|
88429
|
+
id: KOKORO_DEFAULT_MODEL_ID,
|
|
88430
|
+
name: "Kokoro 82M v1.0",
|
|
88431
|
+
description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
|
|
88432
|
+
approxSizeBytes: 95e6,
|
|
88433
|
+
kind: "tts",
|
|
88434
|
+
license: "Apache 2.0",
|
|
88435
|
+
licenseClass: "open",
|
|
88436
|
+
licenseShortName: "Apache 2.0",
|
|
88437
|
+
licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
|
|
88438
|
+
recoScore: 20
|
|
88439
|
+
}
|
|
88440
|
+
] : []
|
|
88441
|
+
};
|
|
88442
|
+
}
|
|
88126
88443
|
function audioRoutes(ctx) {
|
|
88127
88444
|
const app = new Hono4();
|
|
88128
88445
|
app.use(
|
|
@@ -88244,38 +88561,7 @@ function audioRoutes(ctx) {
|
|
|
88244
88561
|
});
|
|
88245
88562
|
});
|
|
88246
88563
|
app.get("/catalog", (c) => {
|
|
88247
|
-
return c.json(
|
|
88248
|
-
// All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
|
|
88249
|
-
// Kokoro under Apache 2.0. Both are permissive → "Free, open".
|
|
88250
|
-
stt: WHISPER_MODEL_CATALOG.map((m) => ({
|
|
88251
|
-
id: m.id,
|
|
88252
|
-
name: m.name,
|
|
88253
|
-
description: m.description,
|
|
88254
|
-
approxSizeBytes: m.approxSizeBytes,
|
|
88255
|
-
kind: "stt",
|
|
88256
|
-
license: "MIT",
|
|
88257
|
-
licenseClass: "open",
|
|
88258
|
-
licenseShortName: "MIT",
|
|
88259
|
-
licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
|
|
88260
|
-
// The Base (English) variant is the recommended STT default: ~140 MB,
|
|
88261
|
-
// realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
|
|
88262
|
-
...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
|
|
88263
|
-
})),
|
|
88264
|
-
tts: [
|
|
88265
|
-
{
|
|
88266
|
-
id: KOKORO_DEFAULT_MODEL_ID,
|
|
88267
|
-
name: "Kokoro 82M v1.0",
|
|
88268
|
-
description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
|
|
88269
|
-
approxSizeBytes: 95e6,
|
|
88270
|
-
kind: "tts",
|
|
88271
|
-
license: "Apache 2.0",
|
|
88272
|
-
licenseClass: "open",
|
|
88273
|
-
licenseShortName: "Apache 2.0",
|
|
88274
|
-
licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
|
|
88275
|
-
recoScore: 20
|
|
88276
|
-
}
|
|
88277
|
-
]
|
|
88278
|
-
});
|
|
88564
|
+
return c.json(buildAudioCatalog());
|
|
88279
88565
|
});
|
|
88280
88566
|
app.get("/stt/models", async (c) => {
|
|
88281
88567
|
const provider = await ctx.stt.current();
|
|
@@ -90247,6 +90533,8 @@ function configRoutes(ctx) {
|
|
|
90247
90533
|
autoUpdateChecks: config.autoUpdateChecks !== false,
|
|
90248
90534
|
quitOnClose: config.quitOnClose === true,
|
|
90249
90535
|
themePref: config.themePref,
|
|
90536
|
+
cliShowThinking: config.cliShowThinking !== false,
|
|
90537
|
+
cliShowWrites: config.cliShowWrites === true,
|
|
90250
90538
|
documentExportOptions: config.documentExportOptions,
|
|
90251
90539
|
sidebarSide: config.sidebarSide,
|
|
90252
90540
|
homeGreetingCollapsed: config.homeGreetingCollapsed === true,
|
|
@@ -90593,6 +90881,8 @@ function configRoutes(ctx) {
|
|
|
90593
90881
|
autoUpdateChecks: updated.autoUpdateChecks !== false,
|
|
90594
90882
|
quitOnClose: updated.quitOnClose === true,
|
|
90595
90883
|
themePref: updated.themePref,
|
|
90884
|
+
cliShowThinking: updated.cliShowThinking !== false,
|
|
90885
|
+
cliShowWrites: updated.cliShowWrites === true,
|
|
90596
90886
|
documentExportOptions: updated.documentExportOptions,
|
|
90597
90887
|
sidebarSide: updated.sidebarSide,
|
|
90598
90888
|
homeGreetingCollapsed: updated.homeGreetingCollapsed === true,
|
|
@@ -91982,7 +92272,11 @@ function ds4Routes(ctx) {
|
|
|
91982
92272
|
const catalogId = c.req.param("catalogId");
|
|
91983
92273
|
const skipShaRaw = c.req.query("skipSha");
|
|
91984
92274
|
const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
|
|
91985
|
-
ctx.chatInstalls.ds4.start(catalogId, {
|
|
92275
|
+
ctx.chatInstalls.ds4.start(catalogId, {
|
|
92276
|
+
skipSha,
|
|
92277
|
+
includeMmproj: false,
|
|
92278
|
+
installCompanion: false
|
|
92279
|
+
});
|
|
91986
92280
|
return streamSSE5(c, (stream) => subscribeToInstallSse(ctx.chatInstalls.ds4, catalogId, stream));
|
|
91987
92281
|
});
|
|
91988
92282
|
app.delete("/models/:catalogId/install", (c) => {
|
|
@@ -93670,6 +93964,7 @@ function gezelRoutes(ctx) {
|
|
|
93670
93964
|
toGezelIdOrName: toId,
|
|
93671
93965
|
projectId: body.projectId,
|
|
93672
93966
|
text: body.text,
|
|
93967
|
+
...body.suppressReply ? { suppressReply: true } : {},
|
|
93673
93968
|
...body.expectedDeliverable ? { expectedDeliverable: body.expectedDeliverable } : {}
|
|
93674
93969
|
});
|
|
93675
93970
|
return c.json({
|
|
@@ -94611,7 +94906,7 @@ import { HandboekRenderModeSchema } from "@bendyline/gezel";
|
|
|
94611
94906
|
import { Hono as Hono29 } from "hono";
|
|
94612
94907
|
|
|
94613
94908
|
// src/handboek/narration.ts
|
|
94614
|
-
import { createHash as
|
|
94909
|
+
import { createHash as createHash29 } from "crypto";
|
|
94615
94910
|
import { existsSync as existsSync14 } from "fs";
|
|
94616
94911
|
import { mkdir as mkdir42, readFile as readFile43, writeFile as writeFile16 } from "fs/promises";
|
|
94617
94912
|
import { join as join65 } from "path";
|
|
@@ -94627,7 +94922,7 @@ function createHandboekNarrator(deps) {
|
|
|
94627
94922
|
const pathFor = (hash) => join65(dir, `${hash}.wav`);
|
|
94628
94923
|
const metaPathFor = (hash) => join65(dir, `${hash}.json`);
|
|
94629
94924
|
async function ensureSegment(key, synthesize) {
|
|
94630
|
-
const hash =
|
|
94925
|
+
const hash = createHash29("sha256").update(key).digest("hex");
|
|
94631
94926
|
const metaPath = metaPathFor(hash);
|
|
94632
94927
|
if (existsSync14(pathFor(hash)) && existsSync14(metaPath)) {
|
|
94633
94928
|
try {
|
|
@@ -95627,9 +95922,15 @@ function llamaCppRoutes(ctx) {
|
|
|
95627
95922
|
const catalogId = c.req.param("catalogId");
|
|
95628
95923
|
const skipShaRaw = c.req.query("skipSha");
|
|
95629
95924
|
const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
|
|
95925
|
+
const skipCompanionRaw = c.req.query("skipCompanion");
|
|
95926
|
+
const skipCompanion = skipCompanionRaw != null && skipCompanionRaw !== "" && skipCompanionRaw !== "0" && skipCompanionRaw !== "false";
|
|
95630
95927
|
const config = await ctx.store.readConfig().catch(() => null);
|
|
95631
95928
|
const includeMmproj = config?.nativeVision?.[catalogId] === true;
|
|
95632
|
-
ctx.chatInstalls.llamaCpp.start(catalogId, {
|
|
95929
|
+
ctx.chatInstalls.llamaCpp.start(catalogId, {
|
|
95930
|
+
skipSha,
|
|
95931
|
+
includeMmproj,
|
|
95932
|
+
installCompanion: !skipCompanion
|
|
95933
|
+
});
|
|
95633
95934
|
return streamSSE9(
|
|
95634
95935
|
c,
|
|
95635
95936
|
(stream) => subscribeToInstallSse(ctx.chatInstalls.llamaCpp, catalogId, stream)
|
|
@@ -95720,7 +96021,7 @@ function mcpToolRoutes(ctx) {
|
|
|
95720
96021
|
import { Hono as Hono36 } from "hono";
|
|
95721
96022
|
|
|
95722
96023
|
// src/meester/status-generator.ts
|
|
95723
|
-
import { createHash as
|
|
96024
|
+
import { createHash as createHash30 } from "crypto";
|
|
95724
96025
|
import {
|
|
95725
96026
|
MEESTER_STATUS_HEADLINE_MAX,
|
|
95726
96027
|
MeesterStatusModelOutputSchema,
|
|
@@ -96032,7 +96333,7 @@ function localDay4(date) {
|
|
|
96032
96333
|
return `${y}-${m}-${d}`;
|
|
96033
96334
|
}
|
|
96034
96335
|
function actionKey(projectId, title) {
|
|
96035
|
-
return
|
|
96336
|
+
return createHash30("sha256").update(`${projectId}
|
|
96036
96337
|
${normalizeTitle(title)}`).digest("hex");
|
|
96037
96338
|
}
|
|
96038
96339
|
function normalizeTitle(title) {
|
|
@@ -96044,7 +96345,7 @@ function hashInput(candidates) {
|
|
|
96044
96345
|
...c.openTasks.map((t) => `${t.ref}:${t.status}`),
|
|
96045
96346
|
...c.events.map((e) => e.id)
|
|
96046
96347
|
]);
|
|
96047
|
-
return
|
|
96348
|
+
return createHash30("sha256").update(lines.join("\n")).digest("hex");
|
|
96048
96349
|
}
|
|
96049
96350
|
function parseModelOutput(raw) {
|
|
96050
96351
|
const fence = raw.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/);
|
|
@@ -96144,19 +96445,19 @@ function memoryRoutes(ctx) {
|
|
|
96144
96445
|
const app = new Hono37();
|
|
96145
96446
|
app.post("/search", async (c) => {
|
|
96146
96447
|
const body = await c.req.json();
|
|
96147
|
-
const
|
|
96448
|
+
const outcome = await ctx.memory.searchAllDetailed(
|
|
96148
96449
|
body.gezelId,
|
|
96149
96450
|
body.projectId,
|
|
96150
96451
|
body.query,
|
|
96151
96452
|
body.topK ?? 10
|
|
96152
96453
|
);
|
|
96153
|
-
return c.json(
|
|
96454
|
+
return c.json(outcome);
|
|
96154
96455
|
});
|
|
96155
96456
|
app.post("/save", async (c) => {
|
|
96156
96457
|
const body = await c.req.json();
|
|
96157
96458
|
const kind = isMemoryKind(body.kind) ? body.kind : "fact";
|
|
96158
96459
|
const outcome = await ctx.memory.save(body.scope, body.id, body.text, kind);
|
|
96159
|
-
return c.json({ ok: true,
|
|
96460
|
+
return c.json({ ok: true, ...outcome });
|
|
96160
96461
|
});
|
|
96161
96462
|
app.get("/recent", async (c) => {
|
|
96162
96463
|
const scope = c.req.query("scope") ?? "gezel";
|
|
@@ -96337,7 +96638,7 @@ import { Hono as Hono39 } from "hono";
|
|
|
96337
96638
|
import { z as z20 } from "zod";
|
|
96338
96639
|
|
|
96339
96640
|
// src/models/gezmodel.ts
|
|
96340
|
-
import { createHash as
|
|
96641
|
+
import { createHash as createHash31, randomUUID as randomUUID19 } from "crypto";
|
|
96341
96642
|
import { createReadStream as createReadStream6, createWriteStream as createWriteStream5 } from "fs";
|
|
96342
96643
|
import { mkdir as mkdir43, open as open3, readFile as readFile45, readdir as readdir26, rm as rm29, stat as stat26, writeFile as writeFile17 } from "fs/promises";
|
|
96343
96644
|
import { basename as basename14, dirname as dirname35, extname as extname5, join as join66 } from "path";
|
|
@@ -96439,7 +96740,7 @@ var GezmodelManager = class {
|
|
|
96439
96740
|
files.push({
|
|
96440
96741
|
path: path2,
|
|
96441
96742
|
sizeBytes: content.byteLength,
|
|
96442
|
-
sha256:
|
|
96743
|
+
sha256: createHash31("sha256").update(content).digest("hex"),
|
|
96443
96744
|
role: path2 === "manifests/installed.json" ? "installed-manifest" : path2 === "manifests/catalog.json" ? "catalog-manifest" : "catalog-file"
|
|
96444
96745
|
});
|
|
96445
96746
|
}
|
|
@@ -96645,7 +96946,7 @@ var GezmodelManager = class {
|
|
|
96645
96946
|
}
|
|
96646
96947
|
};
|
|
96647
96948
|
async function hashFile(path2) {
|
|
96648
|
-
const hash =
|
|
96949
|
+
const hash = createHash31("sha256");
|
|
96649
96950
|
const stream = createReadStream6(path2, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
96650
96951
|
for await (const chunk2 of stream) hash.update(chunk2);
|
|
96651
96952
|
return hash.digest("hex");
|
|
@@ -96843,7 +97144,7 @@ function extractOne(archivePath, wanted, dest, expected) {
|
|
|
96843
97144
|
zip.openReadStream(entry, (streamErr, stream) => {
|
|
96844
97145
|
if (streamErr || !stream)
|
|
96845
97146
|
return fail2(streamErr ?? new Error("could not read ZIP entry"));
|
|
96846
|
-
const hash =
|
|
97147
|
+
const hash = createHash31("sha256");
|
|
96847
97148
|
let bytes = 0;
|
|
96848
97149
|
const verifier = new Transform({
|
|
96849
97150
|
transform(chunk2, _encoding, callback) {
|
|
@@ -97077,7 +97378,7 @@ import {
|
|
|
97077
97378
|
} from "@bendyline/gezel";
|
|
97078
97379
|
|
|
97079
97380
|
// src/providers/mlx/models.ts
|
|
97080
|
-
import { createHash as
|
|
97381
|
+
import { createHash as createHash32 } from "crypto";
|
|
97081
97382
|
import { createReadStream as createReadStream7 } from "fs";
|
|
97082
97383
|
import { mkdir as mkdir44, readFile as readFile47, rename as rename12, rm as rm30, stat as stat27, writeFile as writeFile18 } from "fs/promises";
|
|
97083
97384
|
import { join as join68, resolve as resolvePath2 } from "path";
|
|
@@ -97639,7 +97940,7 @@ var MlxModelManager = class {
|
|
|
97639
97940
|
}
|
|
97640
97941
|
}
|
|
97641
97942
|
push({ type: "verifying", file: file.name });
|
|
97642
|
-
const hasher =
|
|
97943
|
+
const hasher = createHash32("sha256");
|
|
97643
97944
|
await new Promise((resolve18, reject) => {
|
|
97644
97945
|
const stream = createReadStream7(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
97645
97946
|
stream.on("data", (chunk2) => hasher.update(chunk2));
|
|
@@ -99479,7 +99780,7 @@ function describeHostCadence(args) {
|
|
|
99479
99780
|
}
|
|
99480
99781
|
|
|
99481
99782
|
// src/project-type/craftbooks.ts
|
|
99482
|
-
import { createHash as
|
|
99783
|
+
import { createHash as createHash33 } from "crypto";
|
|
99483
99784
|
import {
|
|
99484
99785
|
craftbookFromDoc as craftbookFromDoc3,
|
|
99485
99786
|
createLogger as createLogger109,
|
|
@@ -99503,7 +99804,7 @@ function craftbookContentHash(book) {
|
|
|
99503
99804
|
command: book.command ?? null,
|
|
99504
99805
|
requirements: book.requirements ?? null
|
|
99505
99806
|
};
|
|
99506
|
-
return `sha256:${
|
|
99807
|
+
return `sha256:${createHash33("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
|
|
99507
99808
|
}
|
|
99508
99809
|
async function resolveTypeCraftbook(catalog, input, id, now) {
|
|
99509
99810
|
const embedded = await catalog.readItemFile(
|
|
@@ -100211,7 +100512,7 @@ function pageInvokeRoutes(ctx) {
|
|
|
100211
100512
|
}
|
|
100212
100513
|
|
|
100213
100514
|
// src/http/routes/page-read.ts
|
|
100214
|
-
import { createHash as
|
|
100515
|
+
import { createHash as createHash34 } from "crypto";
|
|
100215
100516
|
import { readFile as readFile50, readdir as readdir29, stat as stat28 } from "fs/promises";
|
|
100216
100517
|
import { PageReadRequestSchema, createLogger as createLogger113 } from "@bendyline/gezel";
|
|
100217
100518
|
import { Hono as Hono48 } from "hono";
|
|
@@ -100220,7 +100521,7 @@ var PAGE_READ_MAX_BYTES = 2 * 1024 * 1024;
|
|
|
100220
100521
|
var RATE_WINDOW_MS3 = 6e4;
|
|
100221
100522
|
var RATE_MAX_READS = 600;
|
|
100222
100523
|
function etagOf(size, mtimeMs) {
|
|
100223
|
-
return
|
|
100524
|
+
return createHash34("sha256").update(`${size}:${Math.trunc(mtimeMs)}`).digest("base64url").slice(0, 16);
|
|
100224
100525
|
}
|
|
100225
100526
|
function pageReadRoutes(ctx) {
|
|
100226
100527
|
const app = new Hono48();
|
|
@@ -100270,7 +100571,7 @@ function pageReadRoutes(ctx) {
|
|
|
100270
100571
|
return `${entry.name}:${entry.isDirectory() ? "dir" : "file"}:${Math.trunc(child?.mtimeMs ?? 0)}`;
|
|
100271
100572
|
})
|
|
100272
100573
|
);
|
|
100273
|
-
const digest =
|
|
100574
|
+
const digest = createHash34("sha256").update(listed.sort().join("\n")).digest("base64url").slice(0, 16);
|
|
100274
100575
|
return c.json({ op: "stat", etag: digest, mtime: stats.mtimeMs });
|
|
100275
100576
|
}
|
|
100276
100577
|
return c.json({
|
|
@@ -100295,7 +100596,7 @@ function pageReadRoutes(ctx) {
|
|
|
100295
100596
|
};
|
|
100296
100597
|
})
|
|
100297
100598
|
)).filter((entry) => entry !== null);
|
|
100298
|
-
const digest =
|
|
100599
|
+
const digest = createHash34("sha256").update(
|
|
100299
100600
|
listed.map((e) => `${e.name}:${e.kind}:${Math.trunc(e.mtime)}`).sort().join("\n")
|
|
100300
100601
|
).digest("base64url").slice(0, 16);
|
|
100301
100602
|
return c.json({ op: "list", entries: listed, etag: digest, mtime: stats.mtimeMs });
|
|
@@ -101005,10 +101306,11 @@ import {
|
|
|
101005
101306
|
projectGezelId as projectGezelId2,
|
|
101006
101307
|
skillToCraftbookDoc
|
|
101007
101308
|
} from "@bendyline/gezel";
|
|
101309
|
+
init_ensure();
|
|
101008
101310
|
init_install();
|
|
101009
101311
|
|
|
101010
101312
|
// src/workspace/instruction-scanner.ts
|
|
101011
|
-
import { createHash as
|
|
101313
|
+
import { createHash as createHash35 } from "crypto";
|
|
101012
101314
|
import { readFile as readFile52, stat as stat30 } from "fs/promises";
|
|
101013
101315
|
import { join as join73 } from "path";
|
|
101014
101316
|
var MAX_CONTENT_CHARS = 64e3;
|
|
@@ -101053,7 +101355,7 @@ ${i.content.trim()}`).join("\n\n---\n\n");
|
|
|
101053
101355
|
return { content: chosen.content, sourceFile: chosen.source, hash: chosen.hash };
|
|
101054
101356
|
}
|
|
101055
101357
|
function sha2563(s) {
|
|
101056
|
-
return
|
|
101358
|
+
return createHash35("sha256").update(s).digest("hex");
|
|
101057
101359
|
}
|
|
101058
101360
|
|
|
101059
101361
|
// src/workspace/skill-script-translator.ts
|
|
@@ -101187,6 +101489,30 @@ async function translateShellBlock(chat, skillName, scriptName, code) {
|
|
|
101187
101489
|
// src/workspace/import-sync.ts
|
|
101188
101490
|
var log110 = createLogger114("import-sync");
|
|
101189
101491
|
var VOORMAN_TEMPLATE_ID = "voorman";
|
|
101492
|
+
var BUILDER_TEMPLATE_ID = "builder";
|
|
101493
|
+
async function ensureFolderProjectBuilder(deps, projectId) {
|
|
101494
|
+
const { store, catalog } = deps;
|
|
101495
|
+
if (!projectId || projectId === "default") return {};
|
|
101496
|
+
const project = await store.getProject(projectId).catch(() => null);
|
|
101497
|
+
if (!project || project.mode !== "solo" || !project.workingDir) return {};
|
|
101498
|
+
if (project.voormanGezelId) return {};
|
|
101499
|
+
const gezels = await store.listGezels().catch(() => []);
|
|
101500
|
+
const existing = gezels.find(
|
|
101501
|
+
(gezel) => gezel.templateId === BUILDER_TEMPLATE_ID || gezel.role?.trim().toLowerCase() === BUILDER_TEMPLATE_ID
|
|
101502
|
+
);
|
|
101503
|
+
const recruited = existing ? null : await recruitFromTemplate(store, catalog, BUILDER_TEMPLATE_ID).catch((err) => {
|
|
101504
|
+
log110.warn(`[import-sync] ${projectId}: Builder recruit failed: ${describe6(err)}`);
|
|
101505
|
+
return null;
|
|
101506
|
+
});
|
|
101507
|
+
const builder = existing ?? recruited;
|
|
101508
|
+
if (!builder) return {};
|
|
101509
|
+
await store.updateProject(projectId, {
|
|
101510
|
+
voormanGezelId: builder.id,
|
|
101511
|
+
voormanAutoAssignedAt: nowIso12()
|
|
101512
|
+
});
|
|
101513
|
+
log110.info(`[import-sync] ${projectId}: assigned ${builder.id} as Builder`);
|
|
101514
|
+
return recruited ? { createdGezel: recruited } : {};
|
|
101515
|
+
}
|
|
101190
101516
|
async function syncProjectImports(deps, projectId, instructions, skills) {
|
|
101191
101517
|
const { store } = deps;
|
|
101192
101518
|
const gate = await store.assertWorkspaceWritable(projectId).catch(() => null);
|
|
@@ -101315,16 +101641,20 @@ async function findExistingVoorman(store) {
|
|
|
101315
101641
|
return match?.id ?? null;
|
|
101316
101642
|
}
|
|
101317
101643
|
async function recruitVoorman(store, catalog) {
|
|
101318
|
-
|
|
101319
|
-
|
|
101644
|
+
return recruitFromTemplate(store, catalog, VOORMAN_TEMPLATE_ID);
|
|
101645
|
+
}
|
|
101646
|
+
async function recruitFromTemplate(store, catalog, templateId) {
|
|
101647
|
+
const template = await resolveGildeTemplateForRole(catalog, templateId).catch(() => null);
|
|
101648
|
+
if (!template || template.templateId !== templateId) return null;
|
|
101320
101649
|
const { name, gender } = pickRandomNameWithGender4();
|
|
101321
101650
|
const created = await store.createGezel({
|
|
101322
101651
|
name,
|
|
101323
|
-
role:
|
|
101652
|
+
role: template.role,
|
|
101324
101653
|
gender,
|
|
101325
|
-
about:
|
|
101326
|
-
templateId
|
|
101327
|
-
templateVersion:
|
|
101654
|
+
about: template.about,
|
|
101655
|
+
templateId,
|
|
101656
|
+
templateVersion: template.templateVersion,
|
|
101657
|
+
...template.frontmatter ? { frontmatter: template.frontmatter } : {}
|
|
101328
101658
|
});
|
|
101329
101659
|
return { id: created.id, name: created.name };
|
|
101330
101660
|
}
|
|
@@ -101799,6 +102129,7 @@ async function resolveActor(ctx, gezelIdHeader) {
|
|
|
101799
102129
|
}
|
|
101800
102130
|
function projectTaskRoutes(ctx) {
|
|
101801
102131
|
const app = new Hono55();
|
|
102132
|
+
const inflightCraftbookInvocations = /* @__PURE__ */ new Map();
|
|
101802
102133
|
app.get("/:projectId/tasks", async (c) => {
|
|
101803
102134
|
const projectId = c.req.param("projectId");
|
|
101804
102135
|
const filter = ListFilterSchema.parse({
|
|
@@ -101814,10 +102145,31 @@ function projectTaskRoutes(ctx) {
|
|
|
101814
102145
|
});
|
|
101815
102146
|
app.post("/:projectId/tasks", async (c) => {
|
|
101816
102147
|
const projectId = c.req.param("projectId");
|
|
101817
|
-
const { dispatchEntry, ...body } = CreateTaskRequestSchema.parse(
|
|
102148
|
+
const { dispatchEntry, craftbookInvocationKey, ...body } = CreateTaskRequestSchema.parse(
|
|
102149
|
+
await c.req.json()
|
|
102150
|
+
);
|
|
101818
102151
|
let task;
|
|
101819
102152
|
try {
|
|
101820
|
-
|
|
102153
|
+
if (craftbookInvocationKey) {
|
|
102154
|
+
const existing = (await ctx.tasks.list({ projectId })).find(
|
|
102155
|
+
(candidate) => candidate.origin?.kind === "craftbook-invocation" && candidate.origin.key === craftbookInvocationKey && (candidate.status === "draft" || candidate.status === "active" || candidate.status === "paused")
|
|
102156
|
+
);
|
|
102157
|
+
if (existing) return c.json(existing);
|
|
102158
|
+
const inflightKey = `${projectId}:${craftbookInvocationKey}`;
|
|
102159
|
+
const pending5 = inflightCraftbookInvocations.get(inflightKey);
|
|
102160
|
+
if (pending5) return c.json(await pending5);
|
|
102161
|
+
const create = ctx.tasks.create(projectId, body, {
|
|
102162
|
+
origin: { kind: "craftbook-invocation", key: craftbookInvocationKey }
|
|
102163
|
+
});
|
|
102164
|
+
inflightCraftbookInvocations.set(inflightKey, create);
|
|
102165
|
+
try {
|
|
102166
|
+
task = await create;
|
|
102167
|
+
} finally {
|
|
102168
|
+
inflightCraftbookInvocations.delete(inflightKey);
|
|
102169
|
+
}
|
|
102170
|
+
} else {
|
|
102171
|
+
task = await ctx.tasks.create(projectId, body);
|
|
102172
|
+
}
|
|
101821
102173
|
} catch (err) {
|
|
101822
102174
|
if (err instanceof CraftbookSetupRequiredError) {
|
|
101823
102175
|
return c.json(
|
|
@@ -102888,7 +103240,7 @@ async function recoverTypedProjectCreations(store) {
|
|
|
102888
103240
|
}
|
|
102889
103241
|
|
|
102890
103242
|
// src/project-type/gzl.ts
|
|
102891
|
-
import { createHash as
|
|
103243
|
+
import { createHash as createHash36 } from "crypto";
|
|
102892
103244
|
import { mkdir as mkdir48, writeFile as writeFile21 } from "fs/promises";
|
|
102893
103245
|
import { dirname as dirname40 } from "path";
|
|
102894
103246
|
import {
|
|
@@ -102906,7 +103258,7 @@ function shard(id) {
|
|
|
102906
103258
|
return id.slice(0, 2).toLowerCase();
|
|
102907
103259
|
}
|
|
102908
103260
|
function hashItemFiles(files) {
|
|
102909
|
-
const hash =
|
|
103261
|
+
const hash = createHash36("sha256");
|
|
102910
103262
|
for (const { rel, content } of [...files].sort((a, b) => a.rel < b.rel ? -1 : 1)) {
|
|
102911
103263
|
hash.update(rel);
|
|
102912
103264
|
hash.update("\0");
|
|
@@ -103054,7 +103406,7 @@ async function importGzlBundle(deps, buffer, opts = {}) {
|
|
|
103054
103406
|
|
|
103055
103407
|
// src/workspace/command-approvals.ts
|
|
103056
103408
|
init_atomic();
|
|
103057
|
-
import { createHash as
|
|
103409
|
+
import { createHash as createHash37 } from "crypto";
|
|
103058
103410
|
import { existsSync as existsSync18 } from "fs";
|
|
103059
103411
|
import { mkdir as mkdir49, readFile as readFile57 } from "fs/promises";
|
|
103060
103412
|
import { dirname as dirname41, join as join79 } from "path";
|
|
@@ -103062,7 +103414,7 @@ import { projectPrivateDir as projectPrivateDir5 } from "@bendyline/gezel/paths"
|
|
|
103062
103414
|
function hashCommandInvocation(body, args, inputFiles = []) {
|
|
103063
103415
|
const files = [...inputFiles].map(({ path: path2, sha256: sha2565 }) => ({ path: path2, sha256: sha2565 })).sort((a, b) => a.path.localeCompare(b.path) || a.sha256.localeCompare(b.sha256));
|
|
103064
103416
|
const payload = JSON.stringify({ version: 2, body: body ?? null, args, files });
|
|
103065
|
-
return
|
|
103417
|
+
return createHash37("sha256").update("gezel-command-invocation\0").update(payload).digest("hex");
|
|
103066
103418
|
}
|
|
103067
103419
|
function approvalsPath(home, projectId) {
|
|
103068
103420
|
return join79(projectPrivateDir5(home, projectId), "command-approvals.json");
|
|
@@ -103288,20 +103640,20 @@ import {
|
|
|
103288
103640
|
} from "@bendyline/gezel";
|
|
103289
103641
|
import { projectPrivateDir as projectPrivateDir6 } from "@bendyline/gezel/paths";
|
|
103290
103642
|
var SHIPPED_ALLOWLIST = [
|
|
103291
|
-
{ package: "zod", allowedVersions: ["^3", "^4"] },
|
|
103292
|
-
{ package: "chalk", allowedVersions: ["^5"] },
|
|
103293
|
-
{ package: "commander", allowedVersions: ["^12", "^13"] },
|
|
103294
|
-
{ package: "date-fns", allowedVersions: ["^3", "^4"] },
|
|
103295
|
-
{ package: "yaml", allowedVersions: ["^2"] },
|
|
103296
|
-
{ package: "cheerio", allowedVersions: ["^1"] },
|
|
103297
|
-
{ package: "mime-types", allowedVersions: ["^2", "^3"] },
|
|
103298
|
-
{ package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"] },
|
|
103299
|
-
{ package: "nanoid", allowedVersions: ["^5"] },
|
|
103300
|
-
{ package: "pino", allowedVersions: ["^9"] },
|
|
103301
|
-
{ package: "playwright-core", allowedVersions: ["^1"] },
|
|
103302
|
-
{ package: "tsx", allowedVersions: ["^4"] },
|
|
103303
|
-
{ package: "typescript", allowedVersions: ["^5"] },
|
|
103304
|
-
{ package: "undici", allowedVersions: ["^6", "^7"] }
|
|
103643
|
+
{ package: "zod", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
|
|
103644
|
+
{ package: "chalk", allowedVersions: ["^5"], defaultVersion: "^5" },
|
|
103645
|
+
{ package: "commander", allowedVersions: ["^12", "^13"], defaultVersion: "^13" },
|
|
103646
|
+
{ package: "date-fns", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
|
|
103647
|
+
{ package: "yaml", allowedVersions: ["^2"], defaultVersion: "^2" },
|
|
103648
|
+
{ package: "cheerio", allowedVersions: ["^1"], defaultVersion: "^1" },
|
|
103649
|
+
{ package: "mime-types", allowedVersions: ["^2", "^3"], defaultVersion: "^3" },
|
|
103650
|
+
{ package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"], defaultVersion: "^15" },
|
|
103651
|
+
{ package: "nanoid", allowedVersions: ["^5"], defaultVersion: "^5" },
|
|
103652
|
+
{ package: "pino", allowedVersions: ["^9"], defaultVersion: "^9" },
|
|
103653
|
+
{ package: "playwright-core", allowedVersions: ["^1"], defaultVersion: "^1" },
|
|
103654
|
+
{ package: "tsx", allowedVersions: ["^4"], defaultVersion: "^4" },
|
|
103655
|
+
{ package: "typescript", allowedVersions: ["^5"], defaultVersion: "^5" },
|
|
103656
|
+
{ package: "undici", allowedVersions: ["^6", "^7"], defaultVersion: "^7" }
|
|
103305
103657
|
];
|
|
103306
103658
|
function projectAllowlistPath(home, projectId) {
|
|
103307
103659
|
return join81(projectPrivateDir6(home, projectId), "npm-allowlist.json");
|
|
@@ -103332,6 +103684,9 @@ function matchesAllowlist(pkg, version) {
|
|
|
103332
103684
|
}
|
|
103333
103685
|
return false;
|
|
103334
103686
|
}
|
|
103687
|
+
function shippedDefaultVersion(pkg) {
|
|
103688
|
+
return SHIPPED_ALLOWLIST.find((entry) => entry.package === pkg)?.defaultVersion;
|
|
103689
|
+
}
|
|
103335
103690
|
function matchesProjectApproval(allowlist, pkg, version) {
|
|
103336
103691
|
return allowlist.approved.some((e) => e.package === pkg && e.version === version);
|
|
103337
103692
|
}
|
|
@@ -103461,7 +103816,9 @@ function dedupRequests(raw) {
|
|
|
103461
103816
|
const out = [];
|
|
103462
103817
|
for (const r of raw) {
|
|
103463
103818
|
const pkg = NpmPackageNameSchema.parse(r.package);
|
|
103464
|
-
const version = NpmRegistryVersionSchema.parse(
|
|
103819
|
+
const version = NpmRegistryVersionSchema.parse(
|
|
103820
|
+
r.version ?? shippedDefaultVersion(pkg) ?? "latest"
|
|
103821
|
+
);
|
|
103465
103822
|
const key = keyOf(pkg, version);
|
|
103466
103823
|
if (seen.has(key)) continue;
|
|
103467
103824
|
seen.add(key);
|
|
@@ -103631,7 +103988,7 @@ import { join as join82 } from "path";
|
|
|
103631
103988
|
import { nowIso as nowIso14 } from "@bendyline/gezel";
|
|
103632
103989
|
|
|
103633
103990
|
// src/workspace/command-inputs.ts
|
|
103634
|
-
import { createHash as
|
|
103991
|
+
import { createHash as createHash38 } from "crypto";
|
|
103635
103992
|
import { createReadStream as createReadStream8 } from "fs";
|
|
103636
103993
|
import { readFile as readFile59, realpath as realpath7, stat as stat35 } from "fs/promises";
|
|
103637
103994
|
import { dirname as dirname43, extname as extname6, isAbsolute as isAbsolute10, relative as relative10, resolve as resolve13, sep as sep9 } from "path";
|
|
@@ -103704,7 +104061,7 @@ function portableRelative(root, file) {
|
|
|
103704
104061
|
return relative10(root, file).split(sep9).join("/");
|
|
103705
104062
|
}
|
|
103706
104063
|
async function sha256File4(file) {
|
|
103707
|
-
const hash =
|
|
104064
|
+
const hash = createHash38("sha256");
|
|
103708
104065
|
await new Promise((resolveStream, reject) => {
|
|
103709
104066
|
const stream = createReadStream8(file);
|
|
103710
104067
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
@@ -104263,12 +104620,13 @@ function projectRoutes(ctx) {
|
|
|
104263
104620
|
app.post("/", async (c) => {
|
|
104264
104621
|
const body = CreateProjectRequestSchema.parse(await c.req.json());
|
|
104265
104622
|
const created = await ctx.store.createProject(body);
|
|
104266
|
-
const
|
|
104623
|
+
const ensureLead = body.workingDir && body.mode === "solo" ? ensureFolderProjectBuilder : ensureProjectVoorman;
|
|
104624
|
+
const ensured2 = await ensureLead(
|
|
104267
104625
|
{ store: ctx.store, chat: ctx.chat, home: ctx.home, catalog: ctx.catalog },
|
|
104268
104626
|
created.id
|
|
104269
104627
|
).catch((err) => {
|
|
104270
104628
|
const message = err instanceof Error ? err.message : String(err);
|
|
104271
|
-
log114.warn(`[projects] ensure-
|
|
104629
|
+
log114.warn(`[projects] ensure-lead failed for ${created.id}: ${message}`);
|
|
104272
104630
|
return {};
|
|
104273
104631
|
});
|
|
104274
104632
|
if (ensured2.createdGezel) {
|
|
@@ -104791,6 +105149,31 @@ function projectRoutes(ctx) {
|
|
|
104791
105149
|
return c.json({ error: "not found" }, 404);
|
|
104792
105150
|
}
|
|
104793
105151
|
});
|
|
105152
|
+
app.post("/:id/reveal-reference", async (c) => {
|
|
105153
|
+
const id = c.req.param("id");
|
|
105154
|
+
const request = ReferenceFileLocationRequestSchema.parse({
|
|
105155
|
+
kind: c.req.query("kind"),
|
|
105156
|
+
path: c.req.query("path")
|
|
105157
|
+
});
|
|
105158
|
+
const base = request.kind === "artifact" ? ctx.store.projectArtifactsDir(id) : request.kind === "workspace" ? await ctx.store.projectWorkspaceDir(id) : ctx.store.documentsDir();
|
|
105159
|
+
const joined = safeJoin(base, request.path);
|
|
105160
|
+
if (!joined || !await realpathContained(base, joined)) {
|
|
105161
|
+
return c.json({ error: "path traversal" }, 400);
|
|
105162
|
+
}
|
|
105163
|
+
let path2;
|
|
105164
|
+
try {
|
|
105165
|
+
const file = await stat36(joined);
|
|
105166
|
+
if (!file.isFile()) return c.json({ error: "not found" }, 404);
|
|
105167
|
+
path2 = await realpath8(joined);
|
|
105168
|
+
} catch {
|
|
105169
|
+
return c.json({ error: "not found" }, 404);
|
|
105170
|
+
}
|
|
105171
|
+
const { execFile: execFile8 } = await import("child_process");
|
|
105172
|
+
const launcher = process.platform === "darwin" ? { cmd: "open", args: ["-R", path2] } : process.platform === "win32" ? { cmd: "explorer", args: ["/select,", path2] } : { cmd: "xdg-open", args: [dirname44(path2)] };
|
|
105173
|
+
execFile8(launcher.cmd, launcher.args, { windowsHide: true }, () => {
|
|
105174
|
+
});
|
|
105175
|
+
return c.json(ReferenceFileLocationResponseSchema.parse({ path: path2 }));
|
|
105176
|
+
});
|
|
104794
105177
|
app.get("/:id/artifacts", async (c) => {
|
|
104795
105178
|
const id = c.req.param("id");
|
|
104796
105179
|
const subpath = c.req.query("path") ?? "";
|
|
@@ -107583,7 +107966,7 @@ async function readProjectScriptRun(home, projectId, runId) {
|
|
|
107583
107966
|
}
|
|
107584
107967
|
|
|
107585
107968
|
// src/scripts/sdk.ts
|
|
107586
|
-
import { createHash as
|
|
107969
|
+
import { createHash as createHash40 } from "crypto";
|
|
107587
107970
|
import { readFile as readFile67 } from "fs/promises";
|
|
107588
107971
|
import { dirname as dirname45, join as join87, relative as relative11 } from "path";
|
|
107589
107972
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
@@ -107649,7 +108032,7 @@ async function readSdkTypes() {
|
|
|
107649
108032
|
});
|
|
107650
108033
|
} catch {
|
|
107651
108034
|
}
|
|
107652
|
-
const hash =
|
|
108035
|
+
const hash = createHash40("sha256");
|
|
107653
108036
|
for (const f of files) hash.update(f.name).update("\0").update(f.content);
|
|
107654
108037
|
cachedTypes = { version: hash.digest("hex"), files };
|
|
107655
108038
|
return cachedTypes;
|
|
@@ -110463,9 +110846,13 @@ async function grepWorkspace(opts) {
|
|
|
110463
110846
|
const plan = normalizePlan(opts);
|
|
110464
110847
|
const target = await resolveSearchTarget(opts.workspaceDir, opts.path);
|
|
110465
110848
|
const requestedEngine = opts.engine ?? "auto";
|
|
110466
|
-
const ripgrepPath = requestedEngine === "javascript" ? null : await
|
|
110849
|
+
const ripgrepPath = requestedEngine === "javascript" ? null : await resolveRipgrepExecutable(target.workspaceDir, Math.min(plan.timeoutMs, 2e3));
|
|
110467
110850
|
if (requestedEngine === "ripgrep" && !ripgrepPath) {
|
|
110468
|
-
throw new WorkspaceGrepError(
|
|
110851
|
+
throw new WorkspaceGrepError(
|
|
110852
|
+
"ripgrep is unavailable (the bundled platform package is missing and rg is not on PATH)",
|
|
110853
|
+
500,
|
|
110854
|
+
"rg-unavailable"
|
|
110855
|
+
);
|
|
110469
110856
|
}
|
|
110470
110857
|
let raw;
|
|
110471
110858
|
let engine;
|
|
@@ -110969,6 +111356,16 @@ async function resolveExecutableOnPath(command, forbiddenRoot, timeoutMs) {
|
|
|
110969
111356
|
if (timer) clearTimeout(timer);
|
|
110970
111357
|
}
|
|
110971
111358
|
}
|
|
111359
|
+
async function resolveRipgrepExecutable(forbiddenRoot, timeoutMs) {
|
|
111360
|
+
const onPath = await resolveExecutableOnPath("rg", forbiddenRoot, timeoutMs);
|
|
111361
|
+
if (onPath) return onPath;
|
|
111362
|
+
try {
|
|
111363
|
+
const { rgPath } = await import("@vscode/ripgrep");
|
|
111364
|
+
return await validateExecutable(rgPath, forbiddenRoot);
|
|
111365
|
+
} catch {
|
|
111366
|
+
return null;
|
|
111367
|
+
}
|
|
111368
|
+
}
|
|
110972
111369
|
async function findExecutableOnPath(command, forbiddenRoot) {
|
|
110973
111370
|
const pathValue = process.env.PATH;
|
|
110974
111371
|
if (!pathValue) return null;
|
|
@@ -110977,22 +111374,28 @@ async function findExecutableOnPath(command, forbiddenRoot) {
|
|
|
110977
111374
|
const entry = rawEntry.replace(/^"|"$/g, "");
|
|
110978
111375
|
if (!entry || !isAbsolute11(entry)) continue;
|
|
110979
111376
|
for (const suffix of suffixes) {
|
|
110980
|
-
|
|
110981
|
-
|
|
110982
|
-
|
|
110983
|
-
|
|
110984
|
-
|
|
110985
|
-
await access3(
|
|
110986
|
-
executable,
|
|
110987
|
-
process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK
|
|
110988
|
-
);
|
|
110989
|
-
return executable;
|
|
110990
|
-
} catch {
|
|
110991
|
-
}
|
|
111377
|
+
const executable = await validateExecutable(
|
|
111378
|
+
join89(entry, `${command}${suffix}`),
|
|
111379
|
+
forbiddenRoot
|
|
111380
|
+
);
|
|
111381
|
+
if (executable) return executable;
|
|
110992
111382
|
}
|
|
110993
111383
|
}
|
|
110994
111384
|
return null;
|
|
110995
111385
|
}
|
|
111386
|
+
async function validateExecutable(candidate, forbiddenRoot) {
|
|
111387
|
+
if (!isAbsolute11(candidate)) return null;
|
|
111388
|
+
try {
|
|
111389
|
+
const executable = await realpath10(candidate);
|
|
111390
|
+
if (pathIsInside(forbiddenRoot, executable)) return null;
|
|
111391
|
+
const executableStat = await stat39(executable);
|
|
111392
|
+
if (!executableStat.isFile()) return null;
|
|
111393
|
+
await access3(executable, process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK);
|
|
111394
|
+
return executable;
|
|
111395
|
+
} catch {
|
|
111396
|
+
return null;
|
|
111397
|
+
}
|
|
111398
|
+
}
|
|
110996
111399
|
function pathIsInside(root, candidate) {
|
|
110997
111400
|
const rel = relative12(root, candidate);
|
|
110998
111401
|
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep10}`) && !isAbsolute11(rel);
|
|
@@ -116245,7 +116648,10 @@ function opaqueServerErrors(log189, onUnexpectedHttpError) {
|
|
|
116245
116648
|
const raw = await prior.clone().text().catch(() => "");
|
|
116246
116649
|
try {
|
|
116247
116650
|
const parsed = JSON.parse(raw);
|
|
116248
|
-
if (parsed.error === "internal_error" && typeof parsed.requestId === "string")
|
|
116651
|
+
if (parsed.error === "internal_error" && typeof parsed.requestId === "string") {
|
|
116652
|
+
c.header("x-request-id", parsed.requestId);
|
|
116653
|
+
return;
|
|
116654
|
+
}
|
|
116249
116655
|
if ((parsed.error === "machine_engine_unavailable" || parsed.error === "capacity_denied") && Object.keys(parsed).length === 1) {
|
|
116250
116656
|
return;
|
|
116251
116657
|
}
|
|
@@ -118594,7 +119000,7 @@ function indexShadowBody(store, file, body) {
|
|
|
118594
119000
|
}
|
|
118595
119001
|
|
|
118596
119002
|
// src/index-store/area-pass.ts
|
|
118597
|
-
import { createHash as
|
|
119003
|
+
import { createHash as createHash41 } from "crypto";
|
|
118598
119004
|
var ARCHITECTURE_KEY = "::project";
|
|
118599
119005
|
var MIN_AREA_FILES = 2;
|
|
118600
119006
|
var AREA_INPUT_CAP = 6e3;
|
|
@@ -118656,7 +119062,7 @@ async function runAreaPass(index, deps) {
|
|
|
118656
119062
|
return result;
|
|
118657
119063
|
}
|
|
118658
119064
|
function hashLines(lines) {
|
|
118659
|
-
return
|
|
119065
|
+
return createHash41("sha256").update([...lines].sort().join("\n")).digest("hex");
|
|
118660
119066
|
}
|
|
118661
119067
|
function buildAreaPrompt(area, entries) {
|
|
118662
119068
|
let body = "";
|
|
@@ -118846,9 +119252,9 @@ function triv(kind) {
|
|
|
118846
119252
|
}
|
|
118847
119253
|
|
|
118848
119254
|
// src/index-store/hash.ts
|
|
118849
|
-
import { createHash as
|
|
119255
|
+
import { createHash as createHash42 } from "crypto";
|
|
118850
119256
|
function sha2564(data) {
|
|
118851
|
-
return
|
|
119257
|
+
return createHash42("sha256").update(data).digest("hex");
|
|
118852
119258
|
}
|
|
118853
119259
|
|
|
118854
119260
|
// src/index-store/artifacts-indexer.ts
|
|
@@ -123759,7 +124165,7 @@ ${body}\r
|
|
|
123759
124165
|
}
|
|
123760
124166
|
|
|
123761
124167
|
// src/mail/mime.ts
|
|
123762
|
-
import { createHash as
|
|
124168
|
+
import { createHash as createHash43 } from "crypto";
|
|
123763
124169
|
import { simpleParser } from "mailparser";
|
|
123764
124170
|
|
|
123765
124171
|
// src/mail/html.ts
|
|
@@ -123874,7 +124280,7 @@ function normalizeReferences(refs) {
|
|
|
123874
124280
|
}
|
|
123875
124281
|
function synthesizeMessageId(parsed, ctx) {
|
|
123876
124282
|
const basis = `${addressText(parsed.from)}|${parsed.subject ?? ""}|${parsed.date?.toISOString() ?? ctx.fallbackDate ?? ""}|${ctx.id}`;
|
|
123877
|
-
return `<${
|
|
124283
|
+
return `<${createHash43("sha256").update(basis).digest("hex").slice(0, 32)}@gezel.local>`;
|
|
123878
124284
|
}
|
|
123879
124285
|
async function parseRawMessage(raw, ctx) {
|
|
123880
124286
|
const parsed = await simpleParser(raw);
|
|
@@ -124497,7 +124903,7 @@ async function migrateOversightTask(store, num) {
|
|
|
124497
124903
|
|
|
124498
124904
|
// src/memory/compaction.ts
|
|
124499
124905
|
init_atomic();
|
|
124500
|
-
import { createHash as
|
|
124906
|
+
import { createHash as createHash44 } from "crypto";
|
|
124501
124907
|
import { readFile as readFile77 } from "fs/promises";
|
|
124502
124908
|
import { join as join101 } from "path";
|
|
124503
124909
|
import { createLogger as createLogger160, isProactiveAllowed as isProactiveAllowed5 } from "@bendyline/gezel";
|
|
@@ -124709,7 +125115,7 @@ var MemoryCompactor = class {
|
|
|
124709
125115
|
}
|
|
124710
125116
|
}
|
|
124711
125117
|
if (entries.length < minEntries) return false;
|
|
124712
|
-
const inputHash =
|
|
125118
|
+
const inputHash = createHash44("sha256").update(eligibleDays.map((d) => `${d}
|
|
124713
125119
|
${dayContents.get(d)}`).join("\n")).digest("hex");
|
|
124714
125120
|
const state = await this.readState(scope, id);
|
|
124715
125121
|
if (state.inputHash === inputHash) return false;
|
|
@@ -124815,7 +125221,7 @@ ${dayContents.get(d)}`).join("\n")).digest("hex");
|
|
|
124815
125221
|
const notes = await this.memory.getRecent("gezel", gezelId, lookbackDays);
|
|
124816
125222
|
if (!notes.trim()) return;
|
|
124817
125223
|
const current = await this.store.readMemoryLessons(gezelId);
|
|
124818
|
-
const lessonsInputHash =
|
|
125224
|
+
const lessonsInputHash = createHash44("sha256").update(`${notes}
|
|
124819
125225
|
---
|
|
124820
125226
|
${current}`).digest("hex");
|
|
124821
125227
|
const state = await this.readState("gezel", gezelId);
|
|
@@ -125156,8 +125562,8 @@ var MemoryManager = class {
|
|
|
125156
125562
|
* that text dedups, so we accept the race rather than lock.
|
|
125157
125563
|
*
|
|
125158
125564
|
* Degraded mode (embeddings disabled): markdown is still appended (it is
|
|
125159
|
-
* the source of truth and the
|
|
125160
|
-
*
|
|
125565
|
+
* the source of truth) and the outcome reports deferred indexing. The health
|
|
125566
|
+
* monitor self-heals the derived index once embeddings recover.
|
|
125161
125567
|
*/
|
|
125162
125568
|
async save(scope, id, text, kind = DEFAULT_MEMORY_KIND) {
|
|
125163
125569
|
const trimmed = text.trim();
|
|
@@ -125172,9 +125578,19 @@ var MemoryManager = class {
|
|
|
125172
125578
|
vector = await embed(trimmed);
|
|
125173
125579
|
} catch (err) {
|
|
125174
125580
|
await this.store.appendMemory(scope, id, trimmed, kind);
|
|
125175
|
-
|
|
125581
|
+
log155.warn(
|
|
125582
|
+
`[memory] saved ${scope}/${id} to Markdown; semantic indexing deferred: ${describeError3(err)}`
|
|
125583
|
+
);
|
|
125584
|
+
return deferredIndexOutcome();
|
|
125585
|
+
}
|
|
125586
|
+
let top;
|
|
125587
|
+
try {
|
|
125588
|
+
top = (await searchByVector(indexDir, vector, 1))[0];
|
|
125589
|
+
} catch (error) {
|
|
125590
|
+
log155.warn(
|
|
125591
|
+
`[memory] vector dedup unavailable for ${scope}/${id}; continuing save: ${describeError3(error)}`
|
|
125592
|
+
);
|
|
125176
125593
|
}
|
|
125177
|
-
const top = (await searchByVector(indexDir, vector, 1))[0];
|
|
125178
125594
|
if (top && top.score >= this.dedupThreshold) {
|
|
125179
125595
|
log155.info(
|
|
125180
125596
|
`[memory] dup-skip (${top.score.toFixed(2)} vs "${top.text.slice(0, 40)}") ${scope}/${id}: ${trimmed.slice(0, 60)}`
|
|
@@ -125182,20 +125598,27 @@ var MemoryManager = class {
|
|
|
125182
125598
|
return { status: "duplicate", match: { text: top.text, score: top.score, via: "vector" } };
|
|
125183
125599
|
}
|
|
125184
125600
|
await this.store.appendMemory(scope, id, trimmed, kind);
|
|
125185
|
-
|
|
125186
|
-
|
|
125187
|
-
|
|
125188
|
-
|
|
125189
|
-
|
|
125190
|
-
|
|
125191
|
-
|
|
125192
|
-
|
|
125193
|
-
|
|
125194
|
-
|
|
125195
|
-
|
|
125196
|
-
|
|
125601
|
+
try {
|
|
125602
|
+
await addToIndex(
|
|
125603
|
+
indexDir,
|
|
125604
|
+
{
|
|
125605
|
+
text: trimmed,
|
|
125606
|
+
scope,
|
|
125607
|
+
id,
|
|
125608
|
+
day: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
125609
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
125610
|
+
kind
|
|
125611
|
+
},
|
|
125612
|
+
vector
|
|
125613
|
+
);
|
|
125614
|
+
} catch (error) {
|
|
125615
|
+
log155.warn(
|
|
125616
|
+
`[memory] saved ${scope}/${id} to Markdown; semantic index write deferred: ${describeError3(error)}`
|
|
125617
|
+
);
|
|
125618
|
+
return deferredIndexOutcome();
|
|
125619
|
+
}
|
|
125197
125620
|
log155.info(`[memory] saved ${scope}/${id} [${kind}]: ${trimmed.slice(0, 60)}`);
|
|
125198
|
-
return { status: "saved" };
|
|
125621
|
+
return { status: "saved", indexed: true };
|
|
125199
125622
|
}
|
|
125200
125623
|
/**
|
|
125201
125624
|
* Exact-text match against today's and yesterday's daily files. Two days
|
|
@@ -125217,7 +125640,15 @@ var MemoryManager = class {
|
|
|
125217
125640
|
}
|
|
125218
125641
|
async search(scope, id, query, topK = 10) {
|
|
125219
125642
|
const indexDir = this.store.memoryIndexDir(scope, id);
|
|
125220
|
-
return
|
|
125643
|
+
if (!this.hasIndex(scope, id)) return this.searchLexical(scope, id, query, topK);
|
|
125644
|
+
try {
|
|
125645
|
+
return await searchIndex(indexDir, query, topK);
|
|
125646
|
+
} catch (error) {
|
|
125647
|
+
log155.warn(
|
|
125648
|
+
`[memory] semantic search failed for ${scope}/${id}; using lexical fallback: ${describeError3(error)}`
|
|
125649
|
+
);
|
|
125650
|
+
return this.searchLexical(scope, id, query, topK);
|
|
125651
|
+
}
|
|
125221
125652
|
}
|
|
125222
125653
|
/**
|
|
125223
125654
|
* Like {@link search} but with a precomputed query embedding — lets the
|
|
@@ -125246,11 +125677,64 @@ var MemoryManager = class {
|
|
|
125246
125677
|
return existsSync28(join103(this.store.memoryIndexDir(scope, id), "mem.db"));
|
|
125247
125678
|
}
|
|
125248
125679
|
async searchAll(gezelId, projectId, query, topK = 10) {
|
|
125249
|
-
|
|
125250
|
-
|
|
125251
|
-
|
|
125680
|
+
return (await this.searchAllDetailed(gezelId, projectId, query, topK)).results;
|
|
125681
|
+
}
|
|
125682
|
+
/**
|
|
125683
|
+
* Search both scopes with one query embedding. Missing indexes fall back to
|
|
125684
|
+
* the daily Markdown source; an unavailable/corrupt semantic cache does the
|
|
125685
|
+
* same and reports a degraded mode instead of turning an optional feature
|
|
125686
|
+
* into an HTTP 500.
|
|
125687
|
+
*/
|
|
125688
|
+
async searchAllDetailed(gezelId, projectId, query, topK = 10) {
|
|
125689
|
+
const gezelIndexed = this.hasIndex("gezel", gezelId);
|
|
125690
|
+
const projectIndexed = this.hasIndex("project", projectId);
|
|
125691
|
+
if (!gezelIndexed && !projectIndexed) {
|
|
125692
|
+
return {
|
|
125693
|
+
results: await this.searchAllLexical(gezelId, projectId, query, topK),
|
|
125694
|
+
mode: "lexical"
|
|
125695
|
+
};
|
|
125696
|
+
}
|
|
125697
|
+
try {
|
|
125698
|
+
const vector = await embedQuery(query);
|
|
125699
|
+
const [gezelResults, projectResults] = await Promise.all([
|
|
125700
|
+
gezelIndexed ? this.searchVector("gezel", gezelId, vector, topK) : this.searchLexical("gezel", gezelId, query, topK),
|
|
125701
|
+
projectIndexed ? this.searchVector("project", projectId, vector, topK) : this.searchLexical("project", projectId, query, topK)
|
|
125702
|
+
]);
|
|
125703
|
+
return {
|
|
125704
|
+
results: rankSearchResults([...gezelResults, ...projectResults], topK),
|
|
125705
|
+
mode: gezelIndexed && projectIndexed ? "semantic" : "hybrid"
|
|
125706
|
+
};
|
|
125707
|
+
} catch (error) {
|
|
125708
|
+
log155.warn(
|
|
125709
|
+
`[memory] semantic search unavailable; using daily-memory lexical fallback: ${describeError3(error)}`
|
|
125710
|
+
);
|
|
125711
|
+
return {
|
|
125712
|
+
results: await this.searchAllLexical(gezelId, projectId, query, topK),
|
|
125713
|
+
mode: "lexical",
|
|
125714
|
+
degraded: {
|
|
125715
|
+
code: "semantic_search_unavailable",
|
|
125716
|
+
message: "Semantic memory search is temporarily unavailable; searched saved memory text directly instead."
|
|
125717
|
+
}
|
|
125718
|
+
};
|
|
125719
|
+
}
|
|
125720
|
+
}
|
|
125721
|
+
async searchAllLexical(gezelId, projectId, query, topK) {
|
|
125722
|
+
const [gezelResults, projectResults] = await Promise.all([
|
|
125723
|
+
this.searchLexical("gezel", gezelId, query, topK),
|
|
125724
|
+
this.searchLexical("project", projectId, query, topK)
|
|
125252
125725
|
]);
|
|
125253
|
-
return [...
|
|
125726
|
+
return rankSearchResults([...gezelResults, ...projectResults], topK);
|
|
125727
|
+
}
|
|
125728
|
+
async searchLexical(scope, id, query, topK) {
|
|
125729
|
+
const entries = await this.allEntries(scope, id);
|
|
125730
|
+
return entries.map((entry) => ({ entry, score: lexicalScore(query, entry.text) })).filter((candidate) => candidate.score > 0).sort((a, b) => b.score - a.score || b.entry.at.localeCompare(a.entry.at)).slice(0, topK).map(({ entry, score }) => ({
|
|
125731
|
+
text: entry.text,
|
|
125732
|
+
score,
|
|
125733
|
+
day: entry.day,
|
|
125734
|
+
scope: entry.scope,
|
|
125735
|
+
id: entry.id,
|
|
125736
|
+
kind: entry.kind ?? DEFAULT_MEMORY_KIND
|
|
125737
|
+
}));
|
|
125254
125738
|
}
|
|
125255
125739
|
async listDays(scope, id) {
|
|
125256
125740
|
return this.store.listMemoryDays(scope, id);
|
|
@@ -125315,6 +125799,36 @@ var MemoryManager = class {
|
|
|
125315
125799
|
return entries.length;
|
|
125316
125800
|
}
|
|
125317
125801
|
};
|
|
125802
|
+
function rankSearchResults(results, topK) {
|
|
125803
|
+
return results.sort((a, b) => b.score - a.score).slice(0, topK);
|
|
125804
|
+
}
|
|
125805
|
+
function deferredIndexOutcome() {
|
|
125806
|
+
return {
|
|
125807
|
+
status: "saved",
|
|
125808
|
+
indexed: false,
|
|
125809
|
+
degraded: {
|
|
125810
|
+
code: "semantic_index_unavailable",
|
|
125811
|
+
message: "Memory was saved, but semantic indexing is temporarily unavailable."
|
|
125812
|
+
}
|
|
125813
|
+
};
|
|
125814
|
+
}
|
|
125815
|
+
function lexicalScore(query, text) {
|
|
125816
|
+
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
125817
|
+
const normalizedText = text.toLocaleLowerCase();
|
|
125818
|
+
if (!normalizedQuery || !normalizedText) return 0;
|
|
125819
|
+
if (normalizedText.includes(normalizedQuery)) return 1;
|
|
125820
|
+
const queryTokens = new Set(normalizedQuery.match(/[\p{L}\p{N}_-]+/gu) ?? []);
|
|
125821
|
+
if (queryTokens.size === 0) return 0;
|
|
125822
|
+
const textTokens = new Set(normalizedText.match(/[\p{L}\p{N}_-]+/gu) ?? []);
|
|
125823
|
+
let matches = 0;
|
|
125824
|
+
for (const token of queryTokens) {
|
|
125825
|
+
if (textTokens.has(token)) matches++;
|
|
125826
|
+
}
|
|
125827
|
+
return matches / queryTokens.size;
|
|
125828
|
+
}
|
|
125829
|
+
function describeError3(error) {
|
|
125830
|
+
return error instanceof Error ? error.message : String(error);
|
|
125831
|
+
}
|
|
125318
125832
|
|
|
125319
125833
|
// src/models/install-jobs.ts
|
|
125320
125834
|
import { createLogger as createLogger166 } from "@bendyline/gezel";
|
|
@@ -125477,6 +125991,7 @@ var LlamaVisionProvider = class {
|
|
|
125477
125991
|
await mkdir57(itemDir, { recursive: true });
|
|
125478
125992
|
const totalAllBytes = spec.files.reduce((n, f) => n + f.approxSizeBytes, 0);
|
|
125479
125993
|
let writtenAll = 0;
|
|
125994
|
+
const verifiedDigests = {};
|
|
125480
125995
|
for (const file of spec.files) {
|
|
125481
125996
|
const result = yield* downloadWithSha256(this.fetchImpl, {
|
|
125482
125997
|
url: file.downloadUrl,
|
|
@@ -125492,8 +126007,9 @@ var LlamaVisionProvider = class {
|
|
|
125492
126007
|
return;
|
|
125493
126008
|
}
|
|
125494
126009
|
writtenAll = result.writtenAll;
|
|
126010
|
+
verifiedDigests[file.filename] = file.sha256.toLowerCase();
|
|
125495
126011
|
}
|
|
125496
|
-
const fileSha256 = await hashModelPayloadFiles(itemDir);
|
|
126012
|
+
const fileSha256 = await hashModelPayloadFiles(itemDir, verifiedDigests);
|
|
125497
126013
|
await writeFile26(
|
|
125498
126014
|
join104(itemDir, "manifest.json"),
|
|
125499
126015
|
`${JSON.stringify(
|
|
@@ -125913,7 +126429,7 @@ async function* runGgufInstallWithCompanion(catalogId, o, deps) {
|
|
|
125913
126429
|
yield event;
|
|
125914
126430
|
}
|
|
125915
126431
|
if (!finished) return;
|
|
125916
|
-
yield* companionRecognitionEvents(catalogId, deps);
|
|
126432
|
+
if (o.installCompanion) yield* companionRecognitionEvents(catalogId, deps);
|
|
125917
126433
|
yield finished;
|
|
125918
126434
|
}
|
|
125919
126435
|
async function* companionRecognitionEvents(catalogId, deps) {
|
|
@@ -127221,7 +127737,7 @@ function makeActionable(message) {
|
|
|
127221
127737
|
}
|
|
127222
127738
|
|
|
127223
127739
|
// src/providers/image/sd-cpp.ts
|
|
127224
|
-
import { createHash as
|
|
127740
|
+
import { createHash as createHash45 } from "crypto";
|
|
127225
127741
|
import { createReadStream as createReadStream10 } from "fs";
|
|
127226
127742
|
import { mkdir as mkdir60, readFile as readFile81, rename as rename15, rm as rm41, writeFile as writeFile29 } from "fs/promises";
|
|
127227
127743
|
import { join as join110 } from "path";
|
|
@@ -127560,7 +128076,7 @@ var StableDiffusionCppProvider = class {
|
|
|
127560
128076
|
}
|
|
127561
128077
|
}
|
|
127562
128078
|
const partialPath = `${destPath}.partial`;
|
|
127563
|
-
const hasher =
|
|
128079
|
+
const hasher = createHash45("sha256");
|
|
127564
128080
|
await new Promise((resolve18, reject) => {
|
|
127565
128081
|
const stream = createReadStream10(partialPath, {
|
|
127566
128082
|
highWaterMark: MODEL_HASH_READ_BUFFER_BYTES
|
|
@@ -128079,7 +128595,7 @@ function isMachineImageProvider(config, env) {
|
|
|
128079
128595
|
}
|
|
128080
128596
|
|
|
128081
128597
|
// src/providers/recognition/store.ts
|
|
128082
|
-
import { createHash as
|
|
128598
|
+
import { createHash as createHash46 } from "crypto";
|
|
128083
128599
|
import { mkdir as mkdir61, readFile as readFile82, rename as rename16, rm as rm42, writeFile as writeFile30 } from "fs/promises";
|
|
128084
128600
|
import { join as join112 } from "path";
|
|
128085
128601
|
import { ImageRecognitionSchema, createLogger as createLogger172 } from "@bendyline/gezel";
|
|
@@ -128091,8 +128607,8 @@ var RecognitionCache = class {
|
|
|
128091
128607
|
this.root = join112(opts.home, "recognition");
|
|
128092
128608
|
}
|
|
128093
128609
|
keyFor(input) {
|
|
128094
|
-
const imageHash =
|
|
128095
|
-
return
|
|
128610
|
+
const imageHash = createHash46("sha256").update(input.bytes).digest("hex");
|
|
128611
|
+
return createHash46("sha256").update(`${imageHash}\0${input.mode}\0${input.modelId}\0v${PROMPT_VERSION}`).digest("hex");
|
|
128096
128612
|
}
|
|
128097
128613
|
pathFor(key) {
|
|
128098
128614
|
return join112(this.root, key.slice(0, 2), `${key}.json`);
|
|
@@ -128537,7 +129053,7 @@ var MockVideoProvider = class {
|
|
|
128537
129053
|
};
|
|
128538
129054
|
|
|
128539
129055
|
// src/providers/video/models.ts
|
|
128540
|
-
import { createHash as
|
|
129056
|
+
import { createHash as createHash47 } from "crypto";
|
|
128541
129057
|
import { createReadStream as createReadStream11 } from "fs";
|
|
128542
129058
|
import { mkdir as mkdir62, readFile as readFile83, rename as rename17, rm as rm43, writeFile as writeFile31 } from "fs/promises";
|
|
128543
129059
|
import { dirname as dirname50, join as join113 } from "path";
|
|
@@ -128723,7 +129239,7 @@ var VideoModelManager = class {
|
|
|
128723
129239
|
await rm43(finalPath, { force: true });
|
|
128724
129240
|
await rename17(partialPath, finalPath);
|
|
128725
129241
|
} catch (err) {
|
|
128726
|
-
yield { type: "error", error: `rename failed for ${file.name}: ${
|
|
129242
|
+
yield { type: "error", error: `rename failed for ${file.name}: ${describeError4(err)}` };
|
|
128727
129243
|
return;
|
|
128728
129244
|
}
|
|
128729
129245
|
}
|
|
@@ -128810,7 +129326,7 @@ var VideoModelManager = class {
|
|
|
128810
129326
|
}
|
|
128811
129327
|
}
|
|
128812
129328
|
push({ type: "verifying", file: file.name });
|
|
128813
|
-
const hasher =
|
|
129329
|
+
const hasher = createHash47("sha256");
|
|
128814
129330
|
await new Promise((resolve18, reject) => {
|
|
128815
129331
|
const stream = createReadStream11(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
128816
129332
|
stream.on("data", (chunk2) => hasher.update(chunk2));
|
|
@@ -128882,7 +129398,7 @@ var VideoModelSelector = class {
|
|
|
128882
129398
|
return (id ? await this.models.resolveModel(id) : null) ?? await this.models.resolveDefaultModel();
|
|
128883
129399
|
}
|
|
128884
129400
|
};
|
|
128885
|
-
function
|
|
129401
|
+
function describeError4(err) {
|
|
128886
129402
|
return err instanceof Error ? err.message : String(err);
|
|
128887
129403
|
}
|
|
128888
129404
|
function isSafeId3(id) {
|
|
@@ -133083,11 +133599,18 @@ var TaskRunner = class {
|
|
|
133083
133599
|
/** Run one serialized dispatch pass now, sharing the interval's overlap guard. */
|
|
133084
133600
|
async wake() {
|
|
133085
133601
|
if (this.tickInFlight) return this.tickInFlight;
|
|
133086
|
-
this.tickInFlight = this.
|
|
133602
|
+
this.tickInFlight = this.tickOnce().finally(() => {
|
|
133087
133603
|
this.tickInFlight = null;
|
|
133088
133604
|
});
|
|
133089
133605
|
return this.tickInFlight;
|
|
133090
133606
|
}
|
|
133607
|
+
/**
|
|
133608
|
+
* Public test/operator entry point. Keep it serialized with the interval:
|
|
133609
|
+
* callers may drive a real, already-started service whose ticker is active.
|
|
133610
|
+
*/
|
|
133611
|
+
async tick() {
|
|
133612
|
+
return this.wake();
|
|
133613
|
+
}
|
|
133091
133614
|
/**
|
|
133092
133615
|
* Scan every `active` task and enqueue a handoff for any whose
|
|
133093
133616
|
* current step has an effective gezel owner. Call on service boot and
|
|
@@ -133134,9 +133657,9 @@ var TaskRunner = class {
|
|
|
133134
133657
|
/**
|
|
133135
133658
|
* One dispatch pass. Walks pending in FIFO order; dispatches any
|
|
133136
133659
|
* whose target provider has a free slot; skips items for tasks
|
|
133137
|
-
* that are no longer active.
|
|
133660
|
+
* that are no longer active.
|
|
133138
133661
|
*/
|
|
133139
|
-
async
|
|
133662
|
+
async tickOnce() {
|
|
133140
133663
|
await this.pruneActiveDispatches();
|
|
133141
133664
|
if (this.pending.length === 0) {
|
|
133142
133665
|
this.holdReason = void 0;
|
|
@@ -133148,6 +133671,7 @@ var TaskRunner = class {
|
|
|
133148
133671
|
return;
|
|
133149
133672
|
}
|
|
133150
133673
|
const snapshot = this.pending.slice();
|
|
133674
|
+
const snapshotIds = new Set(snapshot.map((handoff) => handoff.id));
|
|
133151
133675
|
const keep = [];
|
|
133152
133676
|
const inTickDispatches = /* @__PURE__ */ new Map();
|
|
133153
133677
|
const nightShiftOn = this.isNightShiftActive();
|
|
@@ -133213,6 +133737,7 @@ var TaskRunner = class {
|
|
|
133213
133737
|
...handoff.fromGezelName ? { fromGezelName: handoff.fromGezelName } : {},
|
|
133214
133738
|
...handoff.fromGezelId ? { fromGezelId: handoff.fromGezelId } : {},
|
|
133215
133739
|
...handoff.kind ? { kind: handoff.kind } : {},
|
|
133740
|
+
...task.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: task.roleBasedNameOnlyMode } : {},
|
|
133216
133741
|
lane,
|
|
133217
133742
|
...isNight ? { ambient: true } : {},
|
|
133218
133743
|
...isNight ? { nightShift: true } : {},
|
|
@@ -133235,8 +133760,9 @@ var TaskRunner = class {
|
|
|
133235
133760
|
);
|
|
133236
133761
|
}
|
|
133237
133762
|
}
|
|
133763
|
+
const enqueuedDuringTick = this.pending.filter((handoff) => !snapshotIds.has(handoff.id));
|
|
133238
133764
|
this.pending.length = 0;
|
|
133239
|
-
this.pending.push(...keep);
|
|
133765
|
+
this.pending.push(...keep, ...enqueuedDuringTick);
|
|
133240
133766
|
this.holdReason = keep.some((handoff) => handoff.heldFor === "provider-busy") ? "provider-busy" : void 0;
|
|
133241
133767
|
}
|
|
133242
133768
|
async pruneActiveDispatches() {
|
|
@@ -133726,6 +134252,10 @@ Step "${step.name}" (\`${step.id}\`) was re-driven ${maxRedrives}\xD7 without pr
|
|
|
133726
134252
|
} catch {
|
|
133727
134253
|
}
|
|
133728
134254
|
const activeTasks = projectTasks.filter((t) => t.status === "active");
|
|
134255
|
+
if (projectTasks.length === 0) {
|
|
134256
|
+
trace("skip \u2014 project has no tasks to advance");
|
|
134257
|
+
return;
|
|
134258
|
+
}
|
|
133729
134259
|
if (projectTasks.length > 0 && activeTasks.length === 0) {
|
|
133730
134260
|
if (projectTasks.some((t) => t.status === "draft")) {
|
|
133731
134261
|
trace("skip \u2014 only draft task(s) await activation; not nudging or stabilizing");
|
|
@@ -137467,7 +137997,7 @@ Address these, then the gate re-checks automatically.`,
|
|
|
137467
137997
|
try {
|
|
137468
137998
|
const existing = await tasks.listChildren(task.ref).catch(() => []);
|
|
137469
137999
|
if (existing.length === 0) {
|
|
137470
|
-
const raw = await store.readProjectWorkspaceFile(projectId, spawn14.overFile).catch(() => null);
|
|
138000
|
+
const raw = await (spawn14.overArtifact ? store.readProjectArtifact(projectId, spawn14.overFile) : store.readProjectWorkspaceFile(projectId, spawn14.overFile)).catch(() => null);
|
|
137471
138001
|
const items = raw ? extractSpawnItems(raw, spawn14.itemsPath) : [];
|
|
137472
138002
|
if (items.length === 0) {
|
|
137473
138003
|
log188.warn(
|
|
@@ -137496,7 +138026,7 @@ Address these, then the gate re-checks automatically.`,
|
|
|
137496
138026
|
|
|
137497
138027
|
${kids.map((k) => `- ${k.ref}: ${k.title}`).join("\n")}
|
|
137498
138028
|
`;
|
|
137499
|
-
await store.writeProjectWorkspaceFile(projectId, advanceFile, manifest).catch((err) => log188.warn(`[fanout] ${task.ref}: could not write ${advanceFile}:`, err));
|
|
138029
|
+
await (newStep.advanceWhen?.artifact ? store.writeProjectArtifact(projectId, advanceFile, manifest) : store.writeProjectWorkspaceFile(projectId, advanceFile, manifest)).catch((err) => log188.warn(`[fanout] ${task.ref}: could not write ${advanceFile}:`, err));
|
|
137500
138030
|
}
|
|
137501
138031
|
const nextStep = newStep.advanceWhen?.goto ?? newStep.next;
|
|
137502
138032
|
if (nextStep) {
|