@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/bin/gezeld.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 {
|
|
@@ -11699,7 +11758,7 @@ var ChatEventBus = class {
|
|
|
11699
11758
|
};
|
|
11700
11759
|
|
|
11701
11760
|
// src/chat/manager.ts
|
|
11702
|
-
import { randomUUID as randomUUID7 } from "crypto";
|
|
11761
|
+
import { createHash as createHash12, randomUUID as randomUUID7 } from "crypto";
|
|
11703
11762
|
import { createRequire } from "module";
|
|
11704
11763
|
import { join as join28 } from "path";
|
|
11705
11764
|
import {
|
|
@@ -14094,15 +14153,13 @@ import { createLogger as createLogger4 } from "@bendyline/gezel";
|
|
|
14094
14153
|
// src/model-profile/behaviors/fabrication-detect-claim-without-tool.ts
|
|
14095
14154
|
var PROJECT_CREATION_VERBS = [
|
|
14096
14155
|
"created",
|
|
14097
|
-
"initiated",
|
|
14098
14156
|
"initialized",
|
|
14099
14157
|
"set\\s+up",
|
|
14100
14158
|
"spun\\s+up",
|
|
14101
|
-
"started",
|
|
14102
14159
|
"made",
|
|
14103
|
-
"bootstrapped"
|
|
14104
|
-
"kicked\\s+off"
|
|
14160
|
+
"bootstrapped"
|
|
14105
14161
|
].join("|");
|
|
14162
|
+
var PROJECT_WORK_START_VERBS = ["initiated", "started", "kicked\\s+off"].join("|");
|
|
14106
14163
|
var TASK_CREATION_VERBS = ["created", "added", "queued", "set\\s+up"].join("|");
|
|
14107
14164
|
var GEZEL_CREATION_VERBS = [
|
|
14108
14165
|
"created",
|
|
@@ -14163,6 +14220,18 @@ var CLAIM_RULES = [
|
|
|
14163
14220
|
claim: "recruited a voorman",
|
|
14164
14221
|
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."
|
|
14165
14222
|
},
|
|
14223
|
+
{
|
|
14224
|
+
// Ambiguous kickoff verbs only become a container-creation claim when
|
|
14225
|
+
// the prose explicitly says this is a new/separate project. Otherwise
|
|
14226
|
+
// the next rule treats them as starting work in the current project.
|
|
14227
|
+
pattern: new RegExp(
|
|
14228
|
+
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`,
|
|
14229
|
+
"i"
|
|
14230
|
+
),
|
|
14231
|
+
requiredTools: ["start_project"],
|
|
14232
|
+
claim: "created a project",
|
|
14233
|
+
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."
|
|
14234
|
+
},
|
|
14166
14235
|
{
|
|
14167
14236
|
pattern: new RegExp(
|
|
14168
14237
|
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
|
|
@@ -14184,6 +14253,15 @@ var CLAIM_RULES = [
|
|
|
14184
14253
|
claim: "created a project",
|
|
14185
14254
|
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."
|
|
14186
14255
|
},
|
|
14256
|
+
{
|
|
14257
|
+
pattern: new RegExp(
|
|
14258
|
+
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`,
|
|
14259
|
+
"i"
|
|
14260
|
+
),
|
|
14261
|
+
requiredTools: ["invoke_craftbook", "create_task", "start_project"],
|
|
14262
|
+
claim: "started work in the current project",
|
|
14263
|
+
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."
|
|
14264
|
+
},
|
|
14187
14265
|
{
|
|
14188
14266
|
pattern: new RegExp(
|
|
14189
14267
|
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`,
|
|
@@ -15106,13 +15184,26 @@ var BUILD_REQUEST_RE = new RegExp(
|
|
|
15106
15184
|
function looksLikeNewBuildRequest(text) {
|
|
15107
15185
|
return BUILD_REQUEST_RE.test(text);
|
|
15108
15186
|
}
|
|
15187
|
+
function explicitlyRequestsSeparateProject(text) {
|
|
15188
|
+
return /\b(?:new|fresh|separate|another|dedicated)\s+(?:(?:standalone|independent)\s+)?(?:project|workspace)\b/i.test(
|
|
15189
|
+
text
|
|
15190
|
+
) || /\b(?:as|in|into|under|for)\s+(?:a|an)\s+(?:new|fresh|separate|another|dedicated)\s+(?:project|workspace)\b/i.test(
|
|
15191
|
+
text
|
|
15192
|
+
);
|
|
15193
|
+
}
|
|
15109
15194
|
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.)';
|
|
15110
15195
|
var PromptMeesterBuildPrelude = {
|
|
15111
15196
|
id: "prompt.meester-build-prelude",
|
|
15112
15197
|
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`.',
|
|
15113
15198
|
userPromptPrelude(ctx) {
|
|
15114
15199
|
if (!ctx.isMeester) return null;
|
|
15200
|
+
if (ctx.messageOrigin !== "direct-user") return null;
|
|
15201
|
+
if (/^\s*\[Answer to:/i.test(ctx.userText)) return null;
|
|
15115
15202
|
if (!looksLikeNewBuildRequest(ctx.userText)) return null;
|
|
15203
|
+
if (ctx.projectId !== "default" && !explicitlyRequestsSeparateProject(ctx.userText)) {
|
|
15204
|
+
return null;
|
|
15205
|
+
}
|
|
15206
|
+
if (!ctx.availableToolNames.includes("start_project")) return null;
|
|
15116
15207
|
return MEESTER_BUILD_PRELUDE;
|
|
15117
15208
|
}
|
|
15118
15209
|
};
|
|
@@ -18161,6 +18252,12 @@ var AnthropicCliSession = class extends StreamingSessionBase {
|
|
|
18161
18252
|
providerState() {
|
|
18162
18253
|
return this.claudeSessionIdCache ? { claudeCliSessionId: this.claudeSessionIdCache } : {};
|
|
18163
18254
|
}
|
|
18255
|
+
getRegisteredToolNames() {
|
|
18256
|
+
const context = this.deps.context;
|
|
18257
|
+
return [
|
|
18258
|
+
.../* @__PURE__ */ new Set([...context.allowedBuiltinTools ?? [], ...context.allowedMcpTools ?? []])
|
|
18259
|
+
];
|
|
18260
|
+
}
|
|
18164
18261
|
async disconnect() {
|
|
18165
18262
|
this.aborted = true;
|
|
18166
18263
|
try {
|
|
@@ -19709,6 +19806,10 @@ var AnthropicSession = class extends StreamingSessionBase {
|
|
|
19709
19806
|
* resolves and persisted on `ChatMessage.reasoning`.
|
|
19710
19807
|
*/
|
|
19711
19808
|
lastTurnReasoning = "";
|
|
19809
|
+
getRegisteredToolNames() {
|
|
19810
|
+
const bridgeNames = this.deps.bridges.isEmpty() ? [] : this.deps.bridges.getAnthropicTools().map((tool) => tool.name);
|
|
19811
|
+
return [.../* @__PURE__ */ new Set([...bridgeNames, ...this.externalToolNames])];
|
|
19812
|
+
}
|
|
19712
19813
|
capturedToolCalls() {
|
|
19713
19814
|
return [...this.capturedCalls];
|
|
19714
19815
|
}
|
|
@@ -26973,7 +27074,12 @@ var LlamaCppSession = class extends StreamingSessionBase {
|
|
|
26973
27074
|
if (toolCalls.length > 0) {
|
|
26974
27075
|
const normalized2 = normalizeMalformedStructuredToolCalls(
|
|
26975
27076
|
toolCalls,
|
|
26976
|
-
collectKnownToolNames()
|
|
27077
|
+
collectKnownToolNames(),
|
|
27078
|
+
// A malformed write at the output ceiling is not repairable: the
|
|
27079
|
+
// missing JSON tail may also be missing file bytes. Executing the
|
|
27080
|
+
// loose prefix can silently replace a complete file with a
|
|
27081
|
+
// truncated one. Valid, fully parseable calls remain eligible.
|
|
27082
|
+
finishReason !== "length"
|
|
26977
27083
|
);
|
|
26978
27084
|
toolCalls = normalized2.toolCalls;
|
|
26979
27085
|
malformedStructuredCallIds = new Set(normalized2.sanitizedIds);
|
|
@@ -27850,7 +27956,7 @@ var ToolCallAccumulator = class {
|
|
|
27850
27956
|
}));
|
|
27851
27957
|
}
|
|
27852
27958
|
};
|
|
27853
|
-
function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
|
|
27959
|
+
function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames, allowMalformedWriteRepair = true) {
|
|
27854
27960
|
const repaired = [];
|
|
27855
27961
|
const sanitized = [];
|
|
27856
27962
|
const sanitizedIds = [];
|
|
@@ -27861,11 +27967,7 @@ function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
|
|
|
27861
27967
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return call;
|
|
27862
27968
|
} catch {
|
|
27863
27969
|
}
|
|
27864
|
-
const repairedArgs = tryRepairMalformedWriteToolArguments(
|
|
27865
|
-
call.function.name,
|
|
27866
|
-
raw,
|
|
27867
|
-
knownToolNames
|
|
27868
|
-
);
|
|
27970
|
+
const repairedArgs = allowMalformedWriteRepair ? tryRepairMalformedWriteToolArguments(call.function.name, raw, knownToolNames) : null;
|
|
27869
27971
|
if (repairedArgs) {
|
|
27870
27972
|
repaired.push({
|
|
27871
27973
|
name: call.function.name,
|
|
@@ -32027,6 +32129,7 @@ function buildLlamaCppEngineArgs(input) {
|
|
|
32027
32129
|
ggufHasMtp,
|
|
32028
32130
|
installedDraftModelPath,
|
|
32029
32131
|
reasoningFormat,
|
|
32132
|
+
reasoningPreserve,
|
|
32030
32133
|
architecture,
|
|
32031
32134
|
modelId,
|
|
32032
32135
|
swaFullAutoFits
|
|
@@ -32074,6 +32177,7 @@ function buildLlamaCppEngineArgs(input) {
|
|
|
32074
32177
|
if (typeof nMax === "number") args.push("--spec-draft-n-max", String(nMax));
|
|
32075
32178
|
}
|
|
32076
32179
|
if (reasoningFormat) args.push("--reasoning-format", reasoningFormat);
|
|
32180
|
+
if (reasoningPreserve) args.push("--reasoning-preserve");
|
|
32077
32181
|
if (config.llamaCppExtraArgs) {
|
|
32078
32182
|
for (const [rawKey, value] of Object.entries(config.llamaCppExtraArgs)) {
|
|
32079
32183
|
if (value === false) continue;
|
|
@@ -32394,6 +32498,31 @@ function fitsSwaFullInFastMemory(input) {
|
|
|
32394
32498
|
return Number.isFinite(required) && Number.isFinite(available) && required <= available;
|
|
32395
32499
|
}
|
|
32396
32500
|
|
|
32501
|
+
// src/providers/llama-cpp/reasoning-launch.ts
|
|
32502
|
+
var POSITIVE_INTEGER = /^[1-9]\d*$/;
|
|
32503
|
+
function parseReasoningPreserveEnv(raw) {
|
|
32504
|
+
const normalized2 = raw?.trim().toLowerCase();
|
|
32505
|
+
return normalized2 === "1" || normalized2 === "true";
|
|
32506
|
+
}
|
|
32507
|
+
function parseReasoningBudgetEnv(raw) {
|
|
32508
|
+
const normalized2 = raw?.trim();
|
|
32509
|
+
if (!normalized2) return void 0;
|
|
32510
|
+
if (!POSITIVE_INTEGER.test(normalized2)) {
|
|
32511
|
+
throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS must be a positive integer");
|
|
32512
|
+
}
|
|
32513
|
+
const parsed = Number(normalized2);
|
|
32514
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
32515
|
+
throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS exceeds the safe integer range");
|
|
32516
|
+
}
|
|
32517
|
+
return parsed;
|
|
32518
|
+
}
|
|
32519
|
+
function reasoningLaunchOverridesFromEnv(env = process.env) {
|
|
32520
|
+
return {
|
|
32521
|
+
preserve: parseReasoningPreserveEnv(env.GEZEL_LLAMA_REASONING_PRESERVE),
|
|
32522
|
+
budgetTokens: parseReasoningBudgetEnv(env.GEZEL_LLAMA_REASONING_BUDGET_TOKENS)
|
|
32523
|
+
};
|
|
32524
|
+
}
|
|
32525
|
+
|
|
32397
32526
|
// src/providers/llama-cpp/spec-draft.ts
|
|
32398
32527
|
async function resolveSpecDraft(input) {
|
|
32399
32528
|
const { perModel, configSpecType, configDraftModelPath, resolveDraftPath } = input;
|
|
@@ -32452,6 +32581,8 @@ async function buildLlamaCppProvider(opts) {
|
|
|
32452
32581
|
const { config, affinity, home } = opts;
|
|
32453
32582
|
const externalBaseUrl = opts.modelOverride ? void 0 : process.env.GEZEL_LLAMA_SERVER_URL ?? config.llamaCppBaseUrl;
|
|
32454
32583
|
const binary = process.env.GEZEL_LLAMA_SERVER_BIN;
|
|
32584
|
+
const reasoningLaunchOverrides = reasoningLaunchOverridesFromEnv();
|
|
32585
|
+
const reasoningPreserve = reasoningLaunchOverrides.preserve;
|
|
32455
32586
|
const defaultModelId = opts.modelOverride?.modelId ?? config.defaultModel?.["llama-cpp"];
|
|
32456
32587
|
const configuredSlots = config.providerConcurrency?.["llama-cpp"];
|
|
32457
32588
|
const envNumCtx = (() => {
|
|
@@ -32474,6 +32605,7 @@ async function buildLlamaCppProvider(opts) {
|
|
|
32474
32605
|
// rate for its own default engine — throughput was reachable only by
|
|
32475
32606
|
// scraping stdout from the eval harness.
|
|
32476
32607
|
includeUsageInStream: true,
|
|
32608
|
+
replayReasoningContent: reasoningPreserve,
|
|
32477
32609
|
// External-baseUrl default; the supervised path overrides this with the
|
|
32478
32610
|
// auto-sized `slots` computed below (after the model resolves).
|
|
32479
32611
|
concurrency: configuredSlots ?? 2,
|
|
@@ -32664,10 +32796,12 @@ async function buildLlamaCppProvider(opts) {
|
|
|
32664
32796
|
const slotSavePath = replicaSuffix ? join18(llamaCacheRoot, llamaFingerprint, replicaSuffix) : join18(llamaCacheRoot, llamaFingerprint);
|
|
32665
32797
|
await mkdirAsync(slotSavePath, { recursive: true }).catch(() => {
|
|
32666
32798
|
});
|
|
32667
|
-
const
|
|
32799
|
+
const catalogReasoningBudgetTokens = opts.catalog ? await resolveCatalogReasoningBudget(
|
|
32668
32800
|
opts.catalog,
|
|
32669
32801
|
opts.modelOverride?.modelId ?? defaultModelId
|
|
32670
32802
|
) : void 0;
|
|
32803
|
+
const reasoningBudgetTokens = reasoningLaunchOverrides.budgetTokens ?? catalogReasoningBudgetTokens;
|
|
32804
|
+
const reasoningBudgetSource = reasoningLaunchOverrides.budgetTokens !== void 0 ? "env" : catalogReasoningBudgetTokens !== void 0 ? "catalog" : "unbounded";
|
|
32671
32805
|
const specDraft = await resolveSpecDraft({
|
|
32672
32806
|
perModel: manifestEngineConfig,
|
|
32673
32807
|
configSpecType: config.llamaCppSpecType,
|
|
@@ -33057,6 +33191,7 @@ async function buildLlamaCppProvider(opts) {
|
|
|
33057
33191
|
// disables llama-server's chat-template output parsing so mangled
|
|
33058
33192
|
// model output reaches `delta.content` for provider-side salvage.
|
|
33059
33193
|
reasoningFormat: process.env.GEZEL_LLAMA_REASONING_FORMAT?.trim() || void 0,
|
|
33194
|
+
reasoningPreserve,
|
|
33060
33195
|
architecture: modelCatalogInfo?.architecture,
|
|
33061
33196
|
modelId: defaultModelId ?? void 0,
|
|
33062
33197
|
swaFullAutoFits
|
|
@@ -33165,6 +33300,9 @@ async function buildLlamaCppProvider(opts) {
|
|
|
33165
33300
|
batchSize: lastArgValue(resolvedAdvancedArgs, "--batch-size") ?? "default",
|
|
33166
33301
|
ubatchSize: lastArgValue(resolvedAdvancedArgs, "--ubatch-size") ?? "default",
|
|
33167
33302
|
flashAttention: lastArgValue(resolvedAdvancedArgs, "--flash-attn") ?? "default",
|
|
33303
|
+
reasoningBudgetTokens: reasoningBudgetTokens ?? "unbounded",
|
|
33304
|
+
reasoningBudgetSource,
|
|
33305
|
+
reasoningPreserve,
|
|
33168
33306
|
cudaGraphs: process.env.GGML_CUDA_DISABLE_GRAPHS ? "disabled-by-env" : "default"
|
|
33169
33307
|
},
|
|
33170
33308
|
env: {
|
|
@@ -33330,7 +33468,7 @@ var PROJECT_MACRO_INTERCEPT_CAP = 2;
|
|
|
33330
33468
|
var PROJECT_MACRO_FAILURE_CAP = 2;
|
|
33331
33469
|
function deriveProjectMacroClosing(firstResult) {
|
|
33332
33470
|
const projectMatch = firstResult.match(/Started (?:project|job) "([^"]+)"/);
|
|
33333
|
-
const leadMatch = firstResult.match(/Recruited (\S+) as (voorman|
|
|
33471
|
+
const leadMatch = firstResult.match(/Recruited (\S+) as (voorman|builder|lead)/i);
|
|
33334
33472
|
const projectName = projectMatch?.[1];
|
|
33335
33473
|
const leadName = leadMatch?.[1];
|
|
33336
33474
|
const leadRole = leadMatch?.[2];
|
|
@@ -35953,14 +36091,14 @@ async function buildMlxProvider(opts) {
|
|
|
35953
36091
|
const cacheBudgetMb = Math.min(config.cacheBudgetMb?.mlx ?? ramAwareDefaultMb, mlxKvHeadroomMb);
|
|
35954
36092
|
const mlxReplicaSuffix = opts.modelOverride && opts.modelOverride.replicaIdx > 0 ? `replica-${opts.modelOverride.replicaIdx}` : "";
|
|
35955
36093
|
const cacheRoot = mlxReplicaSuffix ? join21(store.homePath, "engines", "mlx", "cache", mlxReplicaSuffix) : join21(store.homePath, "engines", "mlx", "cache");
|
|
35956
|
-
const { createHash:
|
|
36094
|
+
const { createHash: createHash48 } = await import("crypto");
|
|
35957
36095
|
const fingerprintInput = [
|
|
35958
36096
|
modelCatalogInfo?.id ?? defaultModelId ?? modelDir,
|
|
35959
36097
|
modelCatalogInfo?.catalogVersion ?? "",
|
|
35960
36098
|
modelCatalogInfo?.installedAt ?? "",
|
|
35961
36099
|
modelDir
|
|
35962
36100
|
].join("::");
|
|
35963
|
-
const modelFingerprint =
|
|
36101
|
+
const modelFingerprint = createHash48("sha256").update(fingerprintInput, "utf8").digest("hex").slice(0, 24);
|
|
35964
36102
|
const diskCacheBudgetMb = config.mlxDiskCacheBudgetMb ?? 8192;
|
|
35965
36103
|
const mlxIdleMs = config.localEngineIdleTimeoutMs ?? DEFAULT_LOCAL_ENGINE_IDLE_TIMEOUT_MS3;
|
|
35966
36104
|
const mlxFreezeMs = Math.floor(mlxIdleMs / 2);
|
|
@@ -37282,6 +37420,10 @@ var OpenAISession = class extends StreamingSessionBase {
|
|
|
37282
37420
|
capturedToolCalls() {
|
|
37283
37421
|
return [...this.capturedCalls];
|
|
37284
37422
|
}
|
|
37423
|
+
getRegisteredToolNames() {
|
|
37424
|
+
const bridgeNames = this.deps.bridges.isEmpty() ? [] : this.deps.bridges.getOpenAITools().map((tool) => tool.name);
|
|
37425
|
+
return [.../* @__PURE__ */ new Set([...bridgeNames, ...this.externalToolNames])];
|
|
37426
|
+
}
|
|
37285
37427
|
async sendAndWait(prompt, opts) {
|
|
37286
37428
|
return runInQueue(this.deps.queue, opts?.queue, () => this.sendAndWaitInner(prompt, opts));
|
|
37287
37429
|
}
|
|
@@ -40199,14 +40341,15 @@ async function evalCheck(c, ws, deps) {
|
|
|
40199
40341
|
}
|
|
40200
40342
|
async function evalCheckInner(c, ws, deps) {
|
|
40201
40343
|
const usesArtifact = c.artifact === true;
|
|
40202
|
-
const
|
|
40344
|
+
const artifactReader = {
|
|
40203
40345
|
read: ws.readArtifact ?? (async () => null),
|
|
40204
40346
|
list: ws.listArtifacts ?? (async () => []),
|
|
40205
40347
|
// Carry the byte reader across the artifact swap; without it a
|
|
40206
40348
|
// `verifyImageBytes` check on an artifact deliverable would report
|
|
40207
40349
|
// "no binary reads" even though the surface supports them.
|
|
40208
40350
|
...ws.readArtifactBytes ? { readBytes: ws.readArtifactBytes.bind(ws) } : {}
|
|
40209
|
-
}
|
|
40351
|
+
};
|
|
40352
|
+
const reader = usesArtifact ? artifactReader : ws;
|
|
40210
40353
|
switch (c.kind) {
|
|
40211
40354
|
case "minBytes": {
|
|
40212
40355
|
const r = await fileMinBytes(reader, c.file, c.bytes);
|
|
@@ -40634,7 +40777,12 @@ ${hint}` : ""}`,
|
|
|
40634
40777
|
};
|
|
40635
40778
|
}
|
|
40636
40779
|
case "markdownHeadingsMatch": {
|
|
40637
|
-
const result = await markdownHeadingsMatch(
|
|
40780
|
+
const result = await markdownHeadingsMatch(
|
|
40781
|
+
reader,
|
|
40782
|
+
c.file,
|
|
40783
|
+
c.outlineFile,
|
|
40784
|
+
c.outlineArtifact ? artifactReader : ws
|
|
40785
|
+
);
|
|
40638
40786
|
return {
|
|
40639
40787
|
ok: result.ok,
|
|
40640
40788
|
detail: result.detail,
|
|
@@ -42549,6 +42697,11 @@ function filterPromptToolDirectives(args) {
|
|
|
42549
42697
|
if (rejectedLines.size === 0) return args.prompt;
|
|
42550
42698
|
return args.prompt.split("\n").filter((_, index) => !rejectedLines.has(index + 1)).join("\n").replace(/\n{4,}/g, "\n\n\n");
|
|
42551
42699
|
}
|
|
42700
|
+
function capabilitySafeCorrectivePrompt(args) {
|
|
42701
|
+
const filtered = filterPromptToolDirectives(args).trim();
|
|
42702
|
+
if (filtered) return filtered;
|
|
42703
|
+
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.";
|
|
42704
|
+
}
|
|
42552
42705
|
|
|
42553
42706
|
// src/chat/provider-capabilities.ts
|
|
42554
42707
|
function providerUsesManagedMcpBridge(name) {
|
|
@@ -46387,6 +46540,21 @@ function sameFromBucket(a, b) {
|
|
|
46387
46540
|
if (!a || !b) return false;
|
|
46388
46541
|
return a.gezelId === b.gezelId;
|
|
46389
46542
|
}
|
|
46543
|
+
function resolveTurnMessageOrigin(opts) {
|
|
46544
|
+
if (opts?.messageOrigin) return opts.messageOrigin;
|
|
46545
|
+
if (opts?.from) return "cross-gezel";
|
|
46546
|
+
if (opts?.ambient || opts?.nudge || opts?.lane === "background") return "background-nudge";
|
|
46547
|
+
return "direct-user";
|
|
46548
|
+
}
|
|
46549
|
+
function liveTurnToolNames(session) {
|
|
46550
|
+
const names = /* @__PURE__ */ new Set();
|
|
46551
|
+
for (const name of session?.getRegisteredToolNames?.() ?? []) {
|
|
46552
|
+
names.add(name);
|
|
46553
|
+
const qualified = name.match(/^mcp__.+?__(.+)$/)?.[1];
|
|
46554
|
+
if (qualified && qualified !== "*") names.add(qualified);
|
|
46555
|
+
}
|
|
46556
|
+
return [...names];
|
|
46557
|
+
}
|
|
46390
46558
|
async function resolveCatalogParameterSize(catalog, catalogId) {
|
|
46391
46559
|
if (!catalogId) return void 0;
|
|
46392
46560
|
try {
|
|
@@ -46528,10 +46696,12 @@ var ChatManager = class {
|
|
|
46528
46696
|
*/
|
|
46529
46697
|
afterSessionIdle = /* @__PURE__ */ new Map();
|
|
46530
46698
|
/**
|
|
46531
|
-
* One live async file handoff per sender/target/project/path. Models can
|
|
46699
|
+
* One live async file handoff per sender/target/project/path/intent. Models can
|
|
46532
46700
|
* emit the same `message_gezel` call several times while the sender turn
|
|
46533
46701
|
* is still active; joining that work prevents a parked-send burst from
|
|
46534
|
-
* replaying the same assignment into the recipient session.
|
|
46702
|
+
* replaying the same assignment into the recipient session. A later
|
|
46703
|
+
* validator repair for a file that was originally missing is distinct work
|
|
46704
|
+
* and must never join the older create request.
|
|
46535
46705
|
*/
|
|
46536
46706
|
inflightFileHandoffs = /* @__PURE__ */ new Map();
|
|
46537
46707
|
/** Set once {@link shutdown} starts so deferred watchdogs don't fire into a tearing-down manager. */
|
|
@@ -47788,6 +47958,7 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
47788
47958
|
coalescable: false,
|
|
47789
47959
|
lane: void 0,
|
|
47790
47960
|
ambient: false,
|
|
47961
|
+
messageOrigin: "direct-user",
|
|
47791
47962
|
continuationMaxTokens: void 0,
|
|
47792
47963
|
hidden: false,
|
|
47793
47964
|
nudge: false,
|
|
@@ -48093,11 +48264,14 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
48093
48264
|
const full = await this.store.getSession(args.gezelId, active.id);
|
|
48094
48265
|
if (full) return full;
|
|
48095
48266
|
}
|
|
48267
|
+
const parsedTaskRef = parseTaskRef2(args.taskRef);
|
|
48268
|
+
const task = parsedTaskRef ? await this.store.readTask(parsedTaskRef.projectId, parsedTaskRef.num).catch(() => null) : null;
|
|
48096
48269
|
return this.createSession({
|
|
48097
48270
|
gezelId: args.gezelId,
|
|
48098
48271
|
projectId: args.projectId,
|
|
48099
48272
|
taskRef: args.taskRef,
|
|
48100
|
-
...args.stepId ? { stepId: args.stepId } : {}
|
|
48273
|
+
...args.stepId ? { stepId: args.stepId } : {},
|
|
48274
|
+
...task?.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: task.roleBasedNameOnlyMode } : {}
|
|
48101
48275
|
});
|
|
48102
48276
|
}
|
|
48103
48277
|
/** Late-bind the fitness manager (see the field's docblock). */
|
|
@@ -48224,6 +48398,7 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
48224
48398
|
*/
|
|
48225
48399
|
async startHandoffSession(args) {
|
|
48226
48400
|
const dispatchConfig = await this.store.readConfig();
|
|
48401
|
+
const roleBasedNameOnlyMode = args.roleBasedNameOnlyMode ?? dispatchConfig.roleBasedNameOnlyMode ?? false;
|
|
48227
48402
|
const dispatchGezel = await this.store.getGezel(args.gezelId);
|
|
48228
48403
|
const dispatchProviderName = await this.resolveProviderName(
|
|
48229
48404
|
args.gezelId,
|
|
@@ -48272,6 +48447,7 @@ ${JSON.stringify(run.output, null, 2)}`;
|
|
|
48272
48447
|
projectId: args.projectId,
|
|
48273
48448
|
taskRef: args.taskRef,
|
|
48274
48449
|
stepId: dispatchStepId,
|
|
48450
|
+
roleBasedNameOnlyMode,
|
|
48275
48451
|
...args.nightShift ? { nightShift: true } : {},
|
|
48276
48452
|
...routed && args.capabilityFloor ? {
|
|
48277
48453
|
routedModel: {
|
|
@@ -48328,9 +48504,15 @@ ${stepArc}
|
|
|
48328
48504
|
}
|
|
48329
48505
|
}
|
|
48330
48506
|
const selfHandoff = args.fromGezelId !== void 0 && args.fromGezelId === args.gezelId;
|
|
48331
|
-
const
|
|
48507
|
+
const previousGezel = !selfHandoff && args.fromGezelId ? await this.store.getGezel(args.fromGezelId).catch(() => null) : null;
|
|
48508
|
+
const fromGezelDisplayName = previousGezel ? displayName2(
|
|
48509
|
+
{ name: previousGezel.name, roleBasedName: previousGezel.roleBasedName },
|
|
48510
|
+
roleBasedNameOnlyMode
|
|
48511
|
+
) : roleBasedNameOnlyMode ? void 0 : args.fromGezelName;
|
|
48512
|
+
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.`;
|
|
48332
48513
|
this.trackBackground(
|
|
48333
48514
|
this.sendWithBusyRetry(session.id, seed, {
|
|
48515
|
+
messageOrigin: "system",
|
|
48334
48516
|
...args.lane ? { lane: args.lane } : {},
|
|
48335
48517
|
...args.ambient ? { ambient: true } : {}
|
|
48336
48518
|
}).catch((err) => {
|
|
@@ -48399,7 +48581,8 @@ ${stepArc}
|
|
|
48399
48581
|
args.fromSessionId ?? args.fromGezelId,
|
|
48400
48582
|
target.id,
|
|
48401
48583
|
projectId,
|
|
48402
|
-
normalizeExpectedDeliverablePath(requestedFilePath)
|
|
48584
|
+
normalizeExpectedDeliverablePath(requestedFilePath),
|
|
48585
|
+
fileHandoffIntentKey(args.text)
|
|
48403
48586
|
].join("\0") : null;
|
|
48404
48587
|
const pendingHandoff = fileHandoffKey ? this.inflightFileHandoffs.get(fileHandoffKey) : void 0;
|
|
48405
48588
|
if (pendingHandoff) return { ...pendingHandoff, deduplicated: true };
|
|
@@ -48440,7 +48623,7 @@ ${stepArc}
|
|
|
48440
48623
|
const seed = `[Message from ${fromName}]: ${args.text}${deliverableAnnotation}`;
|
|
48441
48624
|
const failureNotice = { sent: false };
|
|
48442
48625
|
const resolvedFromSessionId = args.fromSessionId ?? (target.id === args.fromGezelId ? null : await this.ensureOrCreateSession({ gezelId: args.fromGezelId, projectId }).then((s) => s.id).catch(() => null));
|
|
48443
|
-
if (resolvedFromSessionId && resolvedFromSessionId !== session.id) {
|
|
48626
|
+
if (!args.suppressReply && resolvedFromSessionId && resolvedFromSessionId !== session.id) {
|
|
48444
48627
|
this.attachReplyListener({
|
|
48445
48628
|
targetSessionId: session.id,
|
|
48446
48629
|
fromSessionId: resolvedFromSessionId,
|
|
@@ -49176,11 +49359,10 @@ ${stepArc}
|
|
|
49176
49359
|
log52.info(
|
|
49177
49360
|
`[questions] delivering answer to session ${args.sessionId.slice(0, 8)} (gezel ${session.gezelId}, project ${session.projectId})`
|
|
49178
49361
|
);
|
|
49179
|
-
await this.sendWithBusyRetry(
|
|
49180
|
-
|
|
49181
|
-
args.
|
|
49182
|
-
|
|
49183
|
-
);
|
|
49362
|
+
await this.sendWithBusyRetry(args.sessionId, args.seed, {
|
|
49363
|
+
messageOrigin: "question-answer",
|
|
49364
|
+
...args.coalescable ? { coalescable: true } : {}
|
|
49365
|
+
});
|
|
49184
49366
|
}
|
|
49185
49367
|
/**
|
|
49186
49368
|
* System-authored reaction seed into a gezel's live (gezel, project)
|
|
@@ -49206,6 +49388,7 @@ ${stepArc}
|
|
|
49206
49388
|
this.send(session.id, args.seed, {
|
|
49207
49389
|
coalescable: true,
|
|
49208
49390
|
lane: "background",
|
|
49391
|
+
messageOrigin: "system",
|
|
49209
49392
|
...leanReactionCap ? { continuationMaxTokens: leanReactionCap } : {},
|
|
49210
49393
|
...args.hidden ? { hidden: true } : {}
|
|
49211
49394
|
}).catch((err) => {
|
|
@@ -49680,12 +49863,13 @@ ${stepArc}
|
|
|
49680
49863
|
throw new Error("engagement-off: AI is disabled in settings; re-enable to send");
|
|
49681
49864
|
}
|
|
49682
49865
|
const existingQueue = this.pendingSends.get(sessionId2);
|
|
49866
|
+
const messageOrigin = resolveTurnMessageOrigin(opts);
|
|
49683
49867
|
const shouldQueue = this.inflight.has(sessionId2) || existingQueue !== void 0 && existingQueue.length > 0;
|
|
49684
49868
|
if (shouldQueue) {
|
|
49685
49869
|
return new Promise((resolve19, reject) => {
|
|
49686
49870
|
const q2 = this.pendingSends.get(sessionId2) ?? [];
|
|
49687
49871
|
const tail = q2.length > 0 ? q2[q2.length - 1] : void 0;
|
|
49688
|
-
const canMerge = opts?.coalescable === true && opts?.nudge !== true && tail?.coalescable === true && tail.nudge !== true && sameFromBucket(tail.from, opts.from);
|
|
49872
|
+
const canMerge = opts?.coalescable === true && opts?.nudge !== true && tail?.coalescable === true && tail.nudge !== true && tail.messageOrigin === messageOrigin && sameFromBucket(tail.from, opts.from);
|
|
49689
49873
|
if (canMerge && tail) {
|
|
49690
49874
|
tail.userText = `${tail.userText}
|
|
49691
49875
|
|
|
@@ -49712,6 +49896,7 @@ ${userText}`;
|
|
|
49712
49896
|
coalescable: opts?.coalescable === true,
|
|
49713
49897
|
lane: opts?.lane,
|
|
49714
49898
|
ambient: opts?.ambient === true,
|
|
49899
|
+
messageOrigin,
|
|
49715
49900
|
continuationMaxTokens: opts?.continuationMaxTokens,
|
|
49716
49901
|
hidden: opts?.hidden === true,
|
|
49717
49902
|
nudge: opts?.nudge === true,
|
|
@@ -49728,7 +49913,7 @@ ${userText}`;
|
|
|
49728
49913
|
return this.runSendAndDrain(
|
|
49729
49914
|
sessionId2,
|
|
49730
49915
|
userText,
|
|
49731
|
-
opts?.nudge ? { ...opts, nudge: false } : opts
|
|
49916
|
+
opts?.nudge ? { ...opts, nudge: false, messageOrigin } : { ...opts, messageOrigin }
|
|
49732
49917
|
);
|
|
49733
49918
|
}
|
|
49734
49919
|
/**
|
|
@@ -49827,7 +50012,7 @@ ${userText}`;
|
|
|
49827
50012
|
if (next.nudge) {
|
|
49828
50013
|
while (q2.length > 0) {
|
|
49829
50014
|
const peek = q2[0];
|
|
49830
|
-
if (!peek.nudge || peek.hidden !== next.hidden || !sameFromBucket(peek.from, next.from)) {
|
|
50015
|
+
if (!peek.nudge || peek.hidden !== next.hidden || peek.messageOrigin !== next.messageOrigin || !sameFromBucket(peek.from, next.from)) {
|
|
49831
50016
|
break;
|
|
49832
50017
|
}
|
|
49833
50018
|
q2.shift();
|
|
@@ -49850,6 +50035,7 @@ ${peek.userText}`;
|
|
|
49850
50035
|
if (next.continuationMaxTokens) runOpts.continuationMaxTokens = next.continuationMaxTokens;
|
|
49851
50036
|
if (next.hidden) runOpts.hidden = true;
|
|
49852
50037
|
if (next.nudge) runOpts.nudge = true;
|
|
50038
|
+
runOpts.messageOrigin = next.messageOrigin;
|
|
49853
50039
|
void this.runSendAndDrain(sessionId2, next.userText, runOpts).then((msg) => {
|
|
49854
50040
|
for (const w of next.waiters) {
|
|
49855
50041
|
try {
|
|
@@ -49880,20 +50066,36 @@ ${peek.userText}`;
|
|
|
49880
50066
|
return this.runFixedFunctionSend(sessionId2, userText, opts);
|
|
49881
50067
|
}
|
|
49882
50068
|
}
|
|
50069
|
+
const preflightScope = ffRecord ? {
|
|
50070
|
+
sessionId: sessionId2,
|
|
50071
|
+
gezelId: ffRecord.gezelId,
|
|
50072
|
+
projectId: ffRecord.projectId
|
|
50073
|
+
} : void 0;
|
|
50074
|
+
const coldStartPending = preflightScope && !this.states.get(sessionId2)?.session;
|
|
50075
|
+
if (preflightScope && coldStartPending) {
|
|
50076
|
+
this.events.publish(preflightScope, {
|
|
50077
|
+
type: "user_message_pending",
|
|
50078
|
+
preview: userText.length > 160 ? `${userText.slice(0, 157)}\u2026` : userText
|
|
50079
|
+
});
|
|
50080
|
+
}
|
|
49883
50081
|
const fail2 = (err) => {
|
|
49884
50082
|
const message = err instanceof Error ? err.message : String(err);
|
|
49885
50083
|
log52.error("error:", message);
|
|
50084
|
+
const publish = (event) => {
|
|
50085
|
+
if (preflightScope) this.events.publish(preflightScope, event);
|
|
50086
|
+
else this.events.publishSessionOnly(sessionId2, event);
|
|
50087
|
+
};
|
|
49886
50088
|
if (inflightTurn.cancelled) {
|
|
49887
|
-
|
|
50089
|
+
publish({ type: "cancelled" });
|
|
49888
50090
|
} else {
|
|
49889
50091
|
const detail = describeTurnError(err);
|
|
49890
|
-
|
|
50092
|
+
publish({
|
|
49891
50093
|
type: "error",
|
|
49892
50094
|
error: redactCredentials4(message),
|
|
49893
50095
|
...detail ? { errorDetail: detail } : {}
|
|
49894
50096
|
});
|
|
49895
50097
|
}
|
|
49896
|
-
|
|
50098
|
+
publish({ type: "done" });
|
|
49897
50099
|
throw err;
|
|
49898
50100
|
};
|
|
49899
50101
|
if (ffRecord) {
|
|
@@ -50180,6 +50382,18 @@ ${peek.userText}`;
|
|
|
50180
50382
|
try {
|
|
50181
50383
|
let lastAssistantMessage = null;
|
|
50182
50384
|
let promptForTurn = spliceIntoText(userText, pendingDigests);
|
|
50385
|
+
const correctivePromptForLiveRoster = (prompt, source) => {
|
|
50386
|
+
const safe = capabilitySafeCorrectivePrompt({
|
|
50387
|
+
prompt,
|
|
50388
|
+
availableTools: liveTurnToolNames(liveSession)
|
|
50389
|
+
});
|
|
50390
|
+
if (safe !== prompt.trim()) {
|
|
50391
|
+
log52.warn(
|
|
50392
|
+
`session ${sessionId2}: filtered ${source} corrective against the live tool roster`
|
|
50393
|
+
);
|
|
50394
|
+
}
|
|
50395
|
+
return safe;
|
|
50396
|
+
};
|
|
50183
50397
|
const freshGameState = await this.refreshLeanGameState(state.record, userText);
|
|
50184
50398
|
if (freshGameState) {
|
|
50185
50399
|
promptForTurn = `${freshGameState}
|
|
@@ -50190,7 +50404,8 @@ ${promptForTurn}`;
|
|
|
50190
50404
|
this.taskBudget.reset(state.record.taskRef);
|
|
50191
50405
|
this.pendingBudgetNudge.delete(state.record.taskRef);
|
|
50192
50406
|
}
|
|
50193
|
-
const
|
|
50407
|
+
const messageOrigin = resolveTurnMessageOrigin(opts);
|
|
50408
|
+
const preludeForTurn = await this.resolveUserPromptPrelude(state, userText, messageOrigin);
|
|
50194
50409
|
if (preludeForTurn) {
|
|
50195
50410
|
promptForTurn = `${preludeForTurn.text}
|
|
50196
50411
|
|
|
@@ -50213,7 +50428,7 @@ ${promptForTurn}`;
|
|
|
50213
50428
|
}
|
|
50214
50429
|
if (state.record.taskRef && this.pendingBudgetNudge.has(state.record.taskRef)) {
|
|
50215
50430
|
this.pendingBudgetNudge.delete(state.record.taskRef);
|
|
50216
|
-
promptForTurn = `${TASK_BUDGET_NUDGE}
|
|
50431
|
+
promptForTurn = `${correctivePromptForLiveRoster(TASK_BUDGET_NUDGE, "task-budget")}
|
|
50217
50432
|
|
|
50218
50433
|
${promptForTurn}`;
|
|
50219
50434
|
log52.info(
|
|
@@ -50222,6 +50437,7 @@ ${promptForTurn}`;
|
|
|
50222
50437
|
}
|
|
50223
50438
|
let continuations = 0;
|
|
50224
50439
|
const maxContinuations = resolveContinuationBudget(state);
|
|
50440
|
+
let voormanIdleNudged = false;
|
|
50225
50441
|
const toolsAcrossContinuations = [];
|
|
50226
50442
|
let compactionsThisSend = 0;
|
|
50227
50443
|
let keurmeesterConsultedThisSend = false;
|
|
@@ -50485,6 +50701,7 @@ ${state.aboutSnapshot}`);
|
|
|
50485
50701
|
const detectorVerdict = runPostTurnDetectors(state, {
|
|
50486
50702
|
sessionId: sessionId2,
|
|
50487
50703
|
isMeester: cfgForDetector?.meesterGezelId === state.record.gezelId,
|
|
50704
|
+
messageOrigin,
|
|
50488
50705
|
userText,
|
|
50489
50706
|
drained: toolsAcrossContinuations,
|
|
50490
50707
|
assistantContent: assistantMessage.content,
|
|
@@ -50498,7 +50715,10 @@ ${state.aboutSnapshot}`);
|
|
|
50498
50715
|
this.events.publish(scope, { type: "warning", message: warningMessage });
|
|
50499
50716
|
}
|
|
50500
50717
|
if (detectorVerdict?.promptForNextTurn) {
|
|
50501
|
-
detectorReprompt =
|
|
50718
|
+
detectorReprompt = correctivePromptForLiveRoster(
|
|
50719
|
+
detectorVerdict.promptForNextTurn,
|
|
50720
|
+
"post-turn detector"
|
|
50721
|
+
);
|
|
50502
50722
|
}
|
|
50503
50723
|
const advanceOutcome = await this.maybeAutoAdvanceOnObservableProgress(
|
|
50504
50724
|
state,
|
|
@@ -50649,7 +50869,10 @@ ${state.aboutSnapshot}`);
|
|
|
50649
50869
|
log52.info(
|
|
50650
50870
|
`session ${sessionId2}: keurmeester intervention applied (case ${consult.caseId}) \u2014 granting one recovery continuation`
|
|
50651
50871
|
);
|
|
50652
|
-
promptForTurn =
|
|
50872
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50873
|
+
consult.correctivePrompt,
|
|
50874
|
+
"keurmeester"
|
|
50875
|
+
);
|
|
50653
50876
|
continue;
|
|
50654
50877
|
}
|
|
50655
50878
|
}
|
|
@@ -50667,7 +50890,10 @@ ${state.aboutSnapshot}`);
|
|
|
50667
50890
|
log52.info(
|
|
50668
50891
|
`session ${sessionId2}: ${detectorVerdict?.reason ?? "detector"} \u2014 re-prompting`
|
|
50669
50892
|
);
|
|
50670
|
-
promptForTurn =
|
|
50893
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50894
|
+
detectorReprompt,
|
|
50895
|
+
detectorVerdict ? "post-turn detector" : "deliverable salvage"
|
|
50896
|
+
);
|
|
50671
50897
|
continue;
|
|
50672
50898
|
}
|
|
50673
50899
|
if (advanceOutcome.gateRejected && !advanceOutcome.gateRejected.paused && advanceOutcome.gateRejected.fingerprint !== state.lastGateNudgeFingerprint && !drained.some((d) => d.name === "ask_user_question" && d.success)) {
|
|
@@ -50677,7 +50903,10 @@ ${state.aboutSnapshot}`);
|
|
|
50677
50903
|
log52.info(
|
|
50678
50904
|
`session ${sessionId2}: ${advanceOutcome.gateRejected.taskRef} step "${advanceOutcome.gateRejected.stepId}" gate rejected \u2014 re-prompting with the verdict${stage > 0 ? ` (escalation stage ${stage})` : ""}`
|
|
50679
50905
|
);
|
|
50680
|
-
promptForTurn =
|
|
50906
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50907
|
+
stage >= 1 ? advanceOutcome.gateRejected.message : buildGateRejectionNudge(advanceOutcome.gateRejected.message),
|
|
50908
|
+
"task-gate"
|
|
50909
|
+
);
|
|
50681
50910
|
continue;
|
|
50682
50911
|
}
|
|
50683
50912
|
if (deliverableOutcome.deliverableRejected?.stopRetrying) {
|
|
@@ -50728,7 +50957,10 @@ ${state.aboutSnapshot}`);
|
|
|
50728
50957
|
log52.info(
|
|
50729
50958
|
`session ${sessionId2}: keurmeester intervention applied on deliverable plateau (case ${consult.caseId}) \u2014 granting one recovery continuation`
|
|
50730
50959
|
);
|
|
50731
|
-
promptForTurn =
|
|
50960
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50961
|
+
consult.correctivePrompt,
|
|
50962
|
+
"keurmeester deliverable-plateau"
|
|
50963
|
+
);
|
|
50732
50964
|
continue;
|
|
50733
50965
|
}
|
|
50734
50966
|
}
|
|
@@ -50752,7 +50984,10 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50752
50984
|
...dRej.filePath ? { filePath: dRej.filePath } : {},
|
|
50753
50985
|
failingVerdict: dRej.message
|
|
50754
50986
|
});
|
|
50755
|
-
promptForTurn =
|
|
50987
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50988
|
+
clampNudge ?? (dStage >= 1 ? dRej.message : buildGateRejectionNudge(dRej.message)),
|
|
50989
|
+
"deliverable-gate"
|
|
50990
|
+
);
|
|
50756
50991
|
continue;
|
|
50757
50992
|
}
|
|
50758
50993
|
if (advanceOutcome.unmetEditGate && (looksStalled(finalContent) || claimsCompletion(finalContent)) && !drained.some((d) => d.name === "ask_user_question" && d.success)) {
|
|
@@ -50760,7 +50995,10 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50760
50995
|
log52.info(
|
|
50761
50996
|
`session ${sessionId2}: ${advanceOutcome.unmetEditGate.taskRef} edit gate unmet (${advanceOutcome.unmetEditGate.file} not written) but reply claims progress \u2014 nudging to edit`
|
|
50762
50997
|
);
|
|
50763
|
-
promptForTurn =
|
|
50998
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
50999
|
+
buildDeliverableEditNudge(advanceOutcome.unmetEditGate.file),
|
|
51000
|
+
"deliverable-edit"
|
|
51001
|
+
);
|
|
50764
51002
|
continue;
|
|
50765
51003
|
}
|
|
50766
51004
|
const unresolvedToolFailures = unresolvedFailedToolCalls(drained);
|
|
@@ -50804,7 +51042,7 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50804
51042
|
// the hot path synchronous for the common non-voorman case.
|
|
50805
51043
|
// Also requires `proactive` — voorman idle nudges advance
|
|
50806
51044
|
// project work past what the user asked for.
|
|
50807
|
-
isProactiveAllowed(nudgeConfig) && state.record.providerName !== "copilot"
|
|
51045
|
+
isProactiveAllowed(nudgeConfig) && state.record.providerName !== "copilot" && !voormanIdleNudged
|
|
50808
51046
|
) {
|
|
50809
51047
|
voormanIdleVerdict = await this.didVoormanIdleStall(state.record, drained, sessionId2);
|
|
50810
51048
|
if (voormanIdleVerdict !== null) {
|
|
@@ -50822,15 +51060,19 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
50822
51060
|
);
|
|
50823
51061
|
break;
|
|
50824
51062
|
}
|
|
51063
|
+
if (stallReason === "voorman-idle") voormanIdleNudged = true;
|
|
50825
51064
|
continuations++;
|
|
50826
51065
|
log52.info(
|
|
50827
|
-
`session ${sessionId2}: response looks stalled (${stallReason}) \u2014
|
|
51066
|
+
`session ${sessionId2}: response looks stalled (${stallReason}) \u2014 requesting one recovery pass`
|
|
51067
|
+
);
|
|
51068
|
+
promptForTurn = correctivePromptForLiveRoster(
|
|
51069
|
+
stallReason === "voorman-idle" ? buildContinuationNudge(
|
|
51070
|
+
finalContent,
|
|
51071
|
+
state.record.messages,
|
|
51072
|
+
voormanIdleVerdict === "nothing-built" ? VOORMAN_NOT_DONE_NUDGE : VOORMAN_IDLE_NUDGE
|
|
51073
|
+
) : stallReason === "tool-only" ? CLOSING_SUMMARY_NUDGE : stallReason === "tool-read-only" ? READ_ONLY_PROGRESS_NUDGE : stallReason === "tool-failed" ? buildFailedToolRecoveryNudge(unresolvedToolFailures) : buildContinuationNudge(finalContent, state.record.messages),
|
|
51074
|
+
`stall-${stallReason}`
|
|
50828
51075
|
);
|
|
50829
|
-
promptForTurn = stallReason === "voorman-idle" ? buildContinuationNudge(
|
|
50830
|
-
finalContent,
|
|
50831
|
-
state.record.messages,
|
|
50832
|
-
voormanIdleVerdict === "nothing-built" ? VOORMAN_NOT_DONE_NUDGE : VOORMAN_IDLE_NUDGE
|
|
50833
|
-
) : stallReason === "tool-only" ? CLOSING_SUMMARY_NUDGE : stallReason === "tool-read-only" ? READ_ONLY_PROGRESS_NUDGE : stallReason === "tool-failed" ? buildFailedToolRecoveryNudge(unresolvedToolFailures) : buildContinuationNudge(finalContent, state.record.messages);
|
|
50834
51076
|
continue;
|
|
50835
51077
|
}
|
|
50836
51078
|
}
|
|
@@ -51396,7 +51638,7 @@ ${rej.message.split("\n").slice(0, 4).join("\n")}`;
|
|
|
51396
51638
|
return null;
|
|
51397
51639
|
}
|
|
51398
51640
|
const tasks = await this.store.listProjectTasks(record.projectId).catch(() => []);
|
|
51399
|
-
if (tasks.length
|
|
51641
|
+
if (tasks.length === 0 || !tasks.some((t) => t.status === "active")) {
|
|
51400
51642
|
return null;
|
|
51401
51643
|
}
|
|
51402
51644
|
const workspaceFiles = await this.store.listProjectWorkspaceRecursive(record.projectId).catch(() => []);
|
|
@@ -54147,7 +54389,7 @@ ${baseSystem}` : baseSystem;
|
|
|
54147
54389
|
return { modelId };
|
|
54148
54390
|
}
|
|
54149
54391
|
}
|
|
54150
|
-
async resolveUserPromptPrelude(state, userText) {
|
|
54392
|
+
async resolveUserPromptPrelude(state, userText, messageOrigin) {
|
|
54151
54393
|
const profile = state.profile;
|
|
54152
54394
|
if (!profile) return null;
|
|
54153
54395
|
const cfg = await this.store.readConfig().catch(() => null);
|
|
@@ -54156,6 +54398,9 @@ ${baseSystem}` : baseSystem;
|
|
|
54156
54398
|
...modelCtxFromProfile(profile, state),
|
|
54157
54399
|
sessionId: state.record.id,
|
|
54158
54400
|
isMeester,
|
|
54401
|
+
projectId: state.record.projectId,
|
|
54402
|
+
messageOrigin,
|
|
54403
|
+
availableToolNames: liveTurnToolNames(state.session),
|
|
54159
54404
|
userText,
|
|
54160
54405
|
drained: [],
|
|
54161
54406
|
assistantContent: "",
|
|
@@ -55476,6 +55721,7 @@ Allow **${info.toolName}** this time?`,
|
|
|
55476
55721
|
GEZEL_SESSION_ID: record.id,
|
|
55477
55722
|
GEZEL_HOME: this.home,
|
|
55478
55723
|
GEZEL_EXECUTION_DENSITY: executionDensity,
|
|
55724
|
+
GEZEL_ROLE_BASED_NAME_ONLY_MODE: record.roleBasedNameOnlyMode ?? globalConfig.roleBasedNameOnlyMode ?? false ? "1" : "0",
|
|
55479
55725
|
...record.expectedDeliverable ? { GEZEL_EXPECTED_DELIVERABLE: JSON.stringify(record.expectedDeliverable) } : {},
|
|
55480
55726
|
...record.stepId ? { GEZEL_STEP_ID: record.stepId } : {},
|
|
55481
55727
|
// Scope task: lets the MCP task tools default to / recover toward
|
|
@@ -55915,6 +56161,9 @@ function runPostTurnDetectors(state, args) {
|
|
|
55915
56161
|
...modelCtxFromProfile(profile, state),
|
|
55916
56162
|
sessionId: args.sessionId,
|
|
55917
56163
|
isMeester: args.isMeester,
|
|
56164
|
+
projectId: state.record.projectId,
|
|
56165
|
+
messageOrigin: args.messageOrigin,
|
|
56166
|
+
availableToolNames: liveTurnToolNames(state.session),
|
|
55918
56167
|
userText: args.userText,
|
|
55919
56168
|
drained: args.drained,
|
|
55920
56169
|
assistantContent: args.assistantContent,
|
|
@@ -56163,6 +56412,14 @@ function messageExpressesModifyIntent(text) {
|
|
|
56163
56412
|
)
|
|
56164
56413
|
);
|
|
56165
56414
|
}
|
|
56415
|
+
function fileHandoffIntentKey(text) {
|
|
56416
|
+
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(
|
|
56417
|
+
text
|
|
56418
|
+
);
|
|
56419
|
+
if (!repair) return "create";
|
|
56420
|
+
const normalized2 = text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
56421
|
+
return `repair:${createHash12("sha256").update(normalized2).digest("hex").slice(0, 16)}`;
|
|
56422
|
+
}
|
|
56166
56423
|
function isSubstantiveExistingWorkspaceFile(filePath2, content) {
|
|
56167
56424
|
const trimmed = content.trim();
|
|
56168
56425
|
if (!trimmed) return false;
|
|
@@ -56447,13 +56704,18 @@ Drop conversational filler, pleasantries, and verbatim tool outputs (just note "
|
|
|
56447
56704
|
Earlier conversation:
|
|
56448
56705
|
|
|
56449
56706
|
`;
|
|
56450
|
-
var VOORMAN_IDLE_NUDGE =
|
|
56707
|
+
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.";
|
|
56451
56708
|
var BOOTSTRAP_WORKSPACE_FILES = /* @__PURE__ */ new Set([
|
|
56452
56709
|
"package.json",
|
|
56710
|
+
"package-lock.json",
|
|
56711
|
+
"pnpm-lock.yaml",
|
|
56712
|
+
"yarn.lock",
|
|
56713
|
+
"bun.lock",
|
|
56714
|
+
"bun.lockb",
|
|
56453
56715
|
"tsconfig.json",
|
|
56454
56716
|
".gitignore"
|
|
56455
56717
|
]);
|
|
56456
|
-
var VOORMAN_NOT_DONE_NUDGE = "
|
|
56718
|
+
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.";
|
|
56457
56719
|
var READ_ONLY_MCP_TOOLS = /* @__PURE__ */ new Set([
|
|
56458
56720
|
"search_memory",
|
|
56459
56721
|
"list_memories",
|
|
@@ -56654,7 +56916,7 @@ function growthSignature(gezel) {
|
|
|
56654
56916
|
|
|
56655
56917
|
// src/codex-setup/manager.ts
|
|
56656
56918
|
init_atomic();
|
|
56657
|
-
import { createHash as
|
|
56919
|
+
import { createHash as createHash13 } from "crypto";
|
|
56658
56920
|
import { realpathSync as realpathSync2 } from "fs";
|
|
56659
56921
|
import { chmod as chmod4, mkdir as mkdir15, readFile as readFile16, rm as rm6 } from "fs/promises";
|
|
56660
56922
|
import { homedir as homedir3 } from "os";
|
|
@@ -57405,7 +57667,7 @@ function canonicalPath(path2) {
|
|
|
57405
57667
|
}
|
|
57406
57668
|
}
|
|
57407
57669
|
function sha256(value) {
|
|
57408
|
-
return
|
|
57670
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
57409
57671
|
}
|
|
57410
57672
|
function catalogModelFor(model) {
|
|
57411
57673
|
const contextWindow = model.contextWindow ?? 32768;
|
|
@@ -57830,7 +58092,7 @@ init_mcp_bridge();
|
|
|
57830
58092
|
|
|
57831
58093
|
// src/connectors/writer.ts
|
|
57832
58094
|
init_atomic();
|
|
57833
|
-
import { createHash as
|
|
58095
|
+
import { createHash as createHash14 } from "crypto";
|
|
57834
58096
|
import { mkdir as mkdir16, readFile as readFile17, readdir as readdir9, rm as rm7, stat as stat11 } from "fs/promises";
|
|
57835
58097
|
import { basename as basename7, join as join30 } from "path";
|
|
57836
58098
|
import { projectLocalQuarantineDir } from "@bendyline/gezel/paths";
|
|
@@ -58103,7 +58365,7 @@ var StaticContentScanner = class {
|
|
|
58103
58365
|
var contentScanner = new StaticContentScanner();
|
|
58104
58366
|
|
|
58105
58367
|
// src/connectors/writer.ts
|
|
58106
|
-
var sha8 = (s) =>
|
|
58368
|
+
var sha8 = (s) => createHash14("sha256").update(s).digest("hex").slice(0, 8);
|
|
58107
58369
|
function slug(input, max = 48) {
|
|
58108
58370
|
const s = input.normalize("NFKD").replace(/[^\x20-\x7E]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max).replace(/-+$/g, "");
|
|
58109
58371
|
return s || "x";
|
|
@@ -58120,7 +58382,7 @@ function contentHash(record) {
|
|
|
58120
58382
|
const attachments = (record.attachments ?? []).map((attachment) => ({
|
|
58121
58383
|
filename: attachment.filename,
|
|
58122
58384
|
size: attachment.size ?? attachment.content?.byteLength ?? 0,
|
|
58123
|
-
sha256: attachment.sha256 ??
|
|
58385
|
+
sha256: attachment.sha256 ?? createHash14("sha256").update(attachment.content).digest("hex")
|
|
58124
58386
|
}));
|
|
58125
58387
|
return sha8(
|
|
58126
58388
|
`${JSON.stringify(sortedFrontmatter)}
|
|
@@ -59191,10 +59453,10 @@ var SpectralConnectorAdapter = class {
|
|
|
59191
59453
|
};
|
|
59192
59454
|
|
|
59193
59455
|
// src/connectors/oauth.ts
|
|
59194
|
-
import { createHash as
|
|
59456
|
+
import { createHash as createHash15, randomBytes as randomBytes3 } from "crypto";
|
|
59195
59457
|
function createPkce() {
|
|
59196
59458
|
const verifier = randomBytes3(32).toString("base64url");
|
|
59197
|
-
const challenge =
|
|
59459
|
+
const challenge = createHash15("sha256").update(verifier).digest("base64url");
|
|
59198
59460
|
return { verifier, challenge };
|
|
59199
59461
|
}
|
|
59200
59462
|
function randomState() {
|
|
@@ -63879,7 +64141,7 @@ function registerGitHubPullsAdapters(runtime) {
|
|
|
63879
64141
|
}
|
|
63880
64142
|
|
|
63881
64143
|
// src/connectors/natives/github-releases.ts
|
|
63882
|
-
import { createHash as
|
|
64144
|
+
import { createHash as createHash16 } from "crypto";
|
|
63883
64145
|
import { mkdir as mkdir21, mkdtemp as mkdtemp3, open as open2, rm as rm13 } from "fs/promises";
|
|
63884
64146
|
import { tmpdir as tmpdir3 } from "os";
|
|
63885
64147
|
import { basename as basename8, join as join35 } from "path";
|
|
@@ -64072,7 +64334,7 @@ var GitHubReleasesAdapter = class {
|
|
|
64072
64334
|
}
|
|
64073
64335
|
}
|
|
64074
64336
|
this.releases = releases;
|
|
64075
|
-
this.fingerprint =
|
|
64337
|
+
this.fingerprint = createHash16("sha256").update(JSON.stringify(releases)).digest("hex");
|
|
64076
64338
|
}
|
|
64077
64339
|
apiHeaders(accept) {
|
|
64078
64340
|
return {
|
|
@@ -64135,7 +64397,7 @@ var GitHubReleasesAdapter = class {
|
|
|
64135
64397
|
};
|
|
64136
64398
|
async function streamResponseToFile(response, path2) {
|
|
64137
64399
|
const handle = await open2(path2, "wx");
|
|
64138
|
-
const hash =
|
|
64400
|
+
const hash = createHash16("sha256");
|
|
64139
64401
|
let size = 0;
|
|
64140
64402
|
try {
|
|
64141
64403
|
for await (const raw of response.body) {
|
|
@@ -66515,7 +66777,7 @@ var DebugFlag = class {
|
|
|
66515
66777
|
|
|
66516
66778
|
// src/digest/generator.ts
|
|
66517
66779
|
init_atomic();
|
|
66518
|
-
import { createHash as
|
|
66780
|
+
import { createHash as createHash17 } from "crypto";
|
|
66519
66781
|
import { readFile as readFile25 } from "fs/promises";
|
|
66520
66782
|
import { join as join40 } from "path";
|
|
66521
66783
|
import {
|
|
@@ -69664,7 +69926,7 @@ var ProjectDigestGenerator = class {
|
|
|
69664
69926
|
if (commits.length === 0 && sessions.length === 0 && events.length < MIN_EVENTS_FOR_DIGEST) {
|
|
69665
69927
|
return false;
|
|
69666
69928
|
}
|
|
69667
|
-
const inputHash =
|
|
69929
|
+
const inputHash = createHash17("sha256").update(
|
|
69668
69930
|
[
|
|
69669
69931
|
week,
|
|
69670
69932
|
...commits,
|
|
@@ -69821,7 +70083,7 @@ function describe4(err) {
|
|
|
69821
70083
|
}
|
|
69822
70084
|
|
|
69823
70085
|
// src/engines/electron-native-reuse.ts
|
|
69824
|
-
import { createHash as
|
|
70086
|
+
import { createHash as createHash18 } from "crypto";
|
|
69825
70087
|
import { createReadStream as createReadStream3 } from "fs";
|
|
69826
70088
|
import { lstat as lstat2, readdir as readdir13, readlink } from "fs/promises";
|
|
69827
70089
|
import { basename as basename11, join as join41, posix, relative as relative5, resolve as resolve8, sep as sep5 } from "path";
|
|
@@ -71441,7 +71703,7 @@ function enclosingMacApp(path2) {
|
|
|
71441
71703
|
var HASH_READ_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
71442
71704
|
function sha256File2(path2) {
|
|
71443
71705
|
return new Promise((resolveHash, reject) => {
|
|
71444
|
-
const hash =
|
|
71706
|
+
const hash = createHash18("sha256");
|
|
71445
71707
|
const stream = createReadStream3(path2, { highWaterMark: HASH_READ_BUFFER_BYTES });
|
|
71446
71708
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
71447
71709
|
stream.on("error", reject);
|
|
@@ -71453,7 +71715,7 @@ function sha256File2(path2) {
|
|
|
71453
71715
|
import { createLogger as createLogger69 } from "@bendyline/gezel";
|
|
71454
71716
|
|
|
71455
71717
|
// src/engines/resolver.ts
|
|
71456
|
-
import { createHash as
|
|
71718
|
+
import { createHash as createHash19 } from "crypto";
|
|
71457
71719
|
import { createReadStream as createReadStream4, existsSync as existsSync7 } from "fs";
|
|
71458
71720
|
import { chmod as chmod5, mkdir as mkdir24, readFile as readFile26, rename as rename7, rm as rm16, writeFile as writeFile9 } from "fs/promises";
|
|
71459
71721
|
import { join as join42 } from "path";
|
|
@@ -71577,7 +71839,7 @@ async function* resolveEngine(opts) {
|
|
|
71577
71839
|
);
|
|
71578
71840
|
}
|
|
71579
71841
|
const sumsBytes = await ghBytes(sumsAsset.url, baseFetch, token);
|
|
71580
|
-
const sumsDigest =
|
|
71842
|
+
const sumsDigest = createHash19("sha256").update(sumsBytes).digest("hex");
|
|
71581
71843
|
if (!unpinned && sumsDigest !== expectedDigest) {
|
|
71582
71844
|
yield* fail(
|
|
71583
71845
|
`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.`
|
|
@@ -71827,7 +72089,7 @@ function parseSums(text) {
|
|
|
71827
72089
|
}
|
|
71828
72090
|
var HASH_READ_BUFFER_BYTES2 = 16 * 1024 * 1024;
|
|
71829
72091
|
async function sha256File3(path2) {
|
|
71830
|
-
const hash =
|
|
72092
|
+
const hash = createHash19("sha256");
|
|
71831
72093
|
await new Promise((resolve19, reject) => {
|
|
71832
72094
|
const stream = createReadStream4(path2, { highWaterMark: HASH_READ_BUFFER_BYTES2 });
|
|
71833
72095
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
@@ -72710,7 +72972,7 @@ function safeBasename(name) {
|
|
|
72710
72972
|
}
|
|
72711
72973
|
|
|
72712
72974
|
// src/fs/store.ts
|
|
72713
|
-
import { createHash as
|
|
72975
|
+
import { createHash as createHash21, randomUUID as randomUUID10 } from "crypto";
|
|
72714
72976
|
import {
|
|
72715
72977
|
appendFile as appendFile4,
|
|
72716
72978
|
chmod as chmod7,
|
|
@@ -73119,7 +73381,7 @@ function countDiffLines(diff) {
|
|
|
73119
73381
|
}
|
|
73120
73382
|
|
|
73121
73383
|
// src/workspace/journal.ts
|
|
73122
|
-
import { createHash as
|
|
73384
|
+
import { createHash as createHash20 } from "crypto";
|
|
73123
73385
|
import { appendFile as appendFile2, mkdir as mkdir27, readFile as readFile29 } from "fs/promises";
|
|
73124
73386
|
import { dirname as dirname26, join as join43 } from "path";
|
|
73125
73387
|
import { projectPrivateDir as projectPrivateDir2 } from "@bendyline/gezel/paths";
|
|
@@ -73162,7 +73424,7 @@ async function readJournalTail(home, projectId, limit = 100) {
|
|
|
73162
73424
|
}
|
|
73163
73425
|
}
|
|
73164
73426
|
function sha2562(content) {
|
|
73165
|
-
return
|
|
73427
|
+
return createHash20("sha256").update(content).digest("hex");
|
|
73166
73428
|
}
|
|
73167
73429
|
|
|
73168
73430
|
// src/workspace/template.ts
|
|
@@ -74029,7 +74291,7 @@ function boekwachterIssueFingerprint(path2, issue) {
|
|
|
74029
74291
|
issue.category.trim().toLocaleLowerCase(),
|
|
74030
74292
|
issue.message.trim().toLocaleLowerCase().replace(/\s+/g, " ")
|
|
74031
74293
|
].join("\0");
|
|
74032
|
-
return
|
|
74294
|
+
return createHash21("sha256").update(normalized2).digest("hex");
|
|
74033
74295
|
}
|
|
74034
74296
|
var ConfigCorruptionError = class extends Error {
|
|
74035
74297
|
code = "CONFIG_CORRUPT";
|
|
@@ -75777,6 +76039,7 @@ ${p.content.trim()}`).join("\n\n---\n\n");
|
|
|
75777
76039
|
async createProject(input, opts) {
|
|
75778
76040
|
const release2 = await this.acquireProjectCreationLock();
|
|
75779
76041
|
try {
|
|
76042
|
+
if (input.workingDir) this.assertSafeWorkingDir(input.workingDir);
|
|
75780
76043
|
const id = opts?.id ?? await this.uniqueProjectId(slugify(input.name) || randomUUID10().slice(0, 8));
|
|
75781
76044
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(id)) {
|
|
75782
76045
|
throw new Error(`invalid project id "${id}"`);
|
|
@@ -75800,14 +76063,22 @@ ${p.content.trim()}`).join("\n\n---\n\n");
|
|
|
75800
76063
|
projectName: input.name
|
|
75801
76064
|
});
|
|
75802
76065
|
}
|
|
76066
|
+
let github = input.github?.url ? { url: input.github.url } : void 0;
|
|
76067
|
+
if (input.workingDir) {
|
|
76068
|
+
github = await autoDetectGitHubLink(input.workingDir, github) ?? github;
|
|
76069
|
+
}
|
|
75803
76070
|
const project = {
|
|
75804
76071
|
id,
|
|
75805
76072
|
name: input.name,
|
|
75806
76073
|
description: input.description,
|
|
75807
76074
|
...input.workingDir ? { workingDir: input.workingDir } : {},
|
|
76075
|
+
// Opening an existing folder is an intake action, not a declaration
|
|
76076
|
+
// that its objectives are ready for active supervision. Keep the
|
|
76077
|
+
// Meester quiet until the user explicitly opts this project back in.
|
|
76078
|
+
...input.workingDir ? { nudgeConfig: { enabled: false } } : {},
|
|
75808
76079
|
...input.mode && input.mode !== "crew" ? { mode: input.mode } : {},
|
|
75809
76080
|
...input.indexingEnabled !== void 0 ? { indexingEnabled: input.indexingEnabled } : {},
|
|
75810
|
-
...
|
|
76081
|
+
...github ? { github } : {},
|
|
75811
76082
|
createdAt: nowIso5(),
|
|
75812
76083
|
updatedAt: nowIso5()
|
|
75813
76084
|
};
|
|
@@ -79482,7 +79753,7 @@ import { projectCodeReviewsFile } from "@bendyline/gezel/paths";
|
|
|
79482
79753
|
import { createLogger as createLogger77, projectAllowsAmbientWork } from "@bendyline/gezel";
|
|
79483
79754
|
|
|
79484
79755
|
// src/tasks/manager.ts
|
|
79485
|
-
import { createHash as
|
|
79756
|
+
import { createHash as createHash22, randomUUID as randomUUID12 } from "crypto";
|
|
79486
79757
|
import {
|
|
79487
79758
|
DEFAULT_NIGHT_SHIFT_WINDOW,
|
|
79488
79759
|
MANAGED_WORKSPACE_WRITE_SETTING_LABEL as MANAGED_WORKSPACE_WRITE_SETTING_LABEL4,
|
|
@@ -80259,6 +80530,7 @@ var TaskManager = class {
|
|
|
80259
80530
|
...cron ? { cron } : {},
|
|
80260
80531
|
...nightShift ? { nightShift } : {},
|
|
80261
80532
|
...fanout ? { fanout } : {},
|
|
80533
|
+
...input.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: input.roleBasedNameOnlyMode } : {},
|
|
80262
80534
|
createdAt: now,
|
|
80263
80535
|
updatedAt: now,
|
|
80264
80536
|
createdBy: input.createdBy ?? { kind: "user" }
|
|
@@ -81333,7 +81605,7 @@ ${paramLines}` : ""}`,
|
|
|
81333
81605
|
if (step.advanceWhen?.file) {
|
|
81334
81606
|
const content = await (step.advanceWhen.artifact ? this.store.readProjectArtifact(projectId, step.advanceWhen.file) : this.store.readProjectWorkspaceFile(projectId, step.advanceWhen.file)).catch(() => null);
|
|
81335
81607
|
if (content !== null) {
|
|
81336
|
-
contentHash2 =
|
|
81608
|
+
contentHash2 = createHash22("sha256").update(content).digest("hex");
|
|
81337
81609
|
}
|
|
81338
81610
|
}
|
|
81339
81611
|
if (contentHash2 !== void 0 && step.lastGateReject?.contentHash !== void 0 && step.lastGateReject.contentHash === contentHash2) {
|
|
@@ -82253,6 +82525,7 @@ Fix one of these, then set the task active again:
|
|
|
82253
82525
|
...parent.nightShift?.enabled ? { nightShift: { enabled: true } } : {},
|
|
82254
82526
|
activeStepId,
|
|
82255
82527
|
parentTaskRef: parent.ref,
|
|
82528
|
+
...parent.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: parent.roleBasedNameOnlyMode } : {},
|
|
82256
82529
|
createdAt: now,
|
|
82257
82530
|
updatedAt: now,
|
|
82258
82531
|
createdBy: parent.createdBy
|
|
@@ -82999,7 +83272,7 @@ function sumStat(s, key) {
|
|
|
82999
83272
|
}
|
|
83000
83273
|
|
|
83001
83274
|
// src/grants/manager.ts
|
|
83002
|
-
import { createHash as
|
|
83275
|
+
import { createHash as createHash23, randomBytes as randomBytes5, randomUUID as randomUUID13, timingSafeEqual } from "crypto";
|
|
83003
83276
|
import { chmod as chmod8 } from "fs/promises";
|
|
83004
83277
|
import { pendingGrantsFile as defaultPendingGrantsFile } from "@bendyline/gezel/paths";
|
|
83005
83278
|
var PENDING_GRANT_TTL_MS = 10 * 6e4;
|
|
@@ -83071,7 +83344,7 @@ function generateVerificationCode() {
|
|
|
83071
83344
|
return `${raw.slice(0, 3)}-${raw.slice(3)}`;
|
|
83072
83345
|
}
|
|
83073
83346
|
function hashVerificationCode(salt, normalizedCode) {
|
|
83074
|
-
return
|
|
83347
|
+
return createHash23("sha256").update(salt, "base64url").update("\0").update(normalizedCode, "ascii").digest();
|
|
83075
83348
|
}
|
|
83076
83349
|
function codeMatches(grant, suppliedCode) {
|
|
83077
83350
|
const normalized2 = normalizeVerificationCode(suppliedCode);
|
|
@@ -84991,7 +85264,7 @@ function tokenize2(question) {
|
|
|
84991
85264
|
}
|
|
84992
85265
|
|
|
84993
85266
|
// src/http/cert.ts
|
|
84994
|
-
import { createHash as
|
|
85267
|
+
import { createHash as createHash24 } from "crypto";
|
|
84995
85268
|
import { generate as selfsignedGenerate } from "selfsigned";
|
|
84996
85269
|
var CERT_VALIDITY_DAYS = 90;
|
|
84997
85270
|
async function generateLoopbackCert() {
|
|
@@ -85028,7 +85301,7 @@ async function generateLoopbackCert() {
|
|
|
85028
85301
|
]
|
|
85029
85302
|
});
|
|
85030
85303
|
const der = pemToDer(pems.cert);
|
|
85031
|
-
const digest =
|
|
85304
|
+
const digest = createHash24("sha256").update(der).digest();
|
|
85032
85305
|
return {
|
|
85033
85306
|
certPem: pems.cert,
|
|
85034
85307
|
keyPem: pems.private,
|
|
@@ -85042,14 +85315,14 @@ function pemToDer(pem) {
|
|
|
85042
85315
|
}
|
|
85043
85316
|
|
|
85044
85317
|
// src/http/codex-bridge-port.ts
|
|
85045
|
-
import { createHash as
|
|
85318
|
+
import { createHash as createHash25 } from "crypto";
|
|
85046
85319
|
import { realpathSync as realpathSync3 } from "fs";
|
|
85047
85320
|
import { resolve as resolve10 } from "path";
|
|
85048
85321
|
var CODEX_BRIDGE_PORT_RANGE_START = 2e4;
|
|
85049
85322
|
var CODEX_BRIDGE_PORT_RANGE_END = 49151;
|
|
85050
85323
|
var CODEX_BRIDGE_PORT_RANGE_SIZE = CODEX_BRIDGE_PORT_RANGE_END - CODEX_BRIDGE_PORT_RANGE_START + 1;
|
|
85051
85324
|
function codexBridgePortForHome(home) {
|
|
85052
|
-
const digest =
|
|
85325
|
+
const digest = createHash25("sha256").update(canonicalPath2(home)).digest();
|
|
85053
85326
|
const bucket = digest.readUInt32BE(0) % CODEX_BRIDGE_PORT_RANGE_SIZE;
|
|
85054
85327
|
return CODEX_BRIDGE_PORT_RANGE_START + bucket;
|
|
85055
85328
|
}
|
|
@@ -85275,7 +85548,7 @@ async function loadGezelByRef(ref, ctx) {
|
|
|
85275
85548
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
85276
85549
|
|
|
85277
85550
|
// src/http/openai-compat/responses-translate.ts
|
|
85278
|
-
import { createHash as
|
|
85551
|
+
import { createHash as createHash26 } from "crypto";
|
|
85279
85552
|
import { z as z11 } from "zod";
|
|
85280
85553
|
|
|
85281
85554
|
// src/http/openai-compat/translate.ts
|
|
@@ -85714,7 +85987,7 @@ var CUSTOM_TOOL_INPUT_KEY = "input";
|
|
|
85714
85987
|
function flattenResponsesNamespaceToolName(namespace, name) {
|
|
85715
85988
|
const joined = `${namespace}__${name}`;
|
|
85716
85989
|
if (joined.length <= MAX_LOCAL_TOOL_NAME_LENGTH) return joined;
|
|
85717
|
-
const digest =
|
|
85990
|
+
const digest = createHash26("sha256").update(namespace).update("\0").update(name).digest("hex").slice(0, 12);
|
|
85718
85991
|
const prefixLength = MAX_LOCAL_TOOL_NAME_LENGTH - digest.length - 2;
|
|
85719
85992
|
return `${joined.slice(0, prefixLength)}__${digest}`;
|
|
85720
85993
|
}
|
|
@@ -86944,7 +87217,7 @@ function mountMachineEngineHints(app) {
|
|
|
86944
87217
|
}
|
|
86945
87218
|
|
|
86946
87219
|
// src/http/preview-capability.ts
|
|
86947
|
-
import { createHash as
|
|
87220
|
+
import { createHash as createHash27, randomBytes as randomBytes6 } from "crypto";
|
|
86948
87221
|
import { posix as posix3 } from "path";
|
|
86949
87222
|
var DEFAULT_PREVIEW_CAPABILITY_TTL_MS = 10 * 60 * 1e3;
|
|
86950
87223
|
var DEFAULT_PREVIEW_CAPABILITY_ABSOLUTE_TTL_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -87088,7 +87361,7 @@ function pathIsInScope(path2, scopePath) {
|
|
|
87088
87361
|
return scopePath === "" || path2 === scopePath || path2.startsWith(`${scopePath}/`);
|
|
87089
87362
|
}
|
|
87090
87363
|
function tokenDigest(token) {
|
|
87091
|
-
return
|
|
87364
|
+
return createHash27("sha256").update(token).digest("base64url");
|
|
87092
87365
|
}
|
|
87093
87366
|
|
|
87094
87367
|
// src/http/routes/ai.ts
|
|
@@ -87457,6 +87730,15 @@ var KOKORO_HF_REPO = "onnx-community/Kokoro-82M-v1.0-ONNX";
|
|
|
87457
87730
|
var KOKORO_APPROX_BYTES_BY_ID = {
|
|
87458
87731
|
[KOKORO_DEFAULT_MODEL_ID]: 95e6
|
|
87459
87732
|
};
|
|
87733
|
+
function isKokoroRuntimeAvailable(resolveModule = (specifier) => import.meta.resolve(specifier)) {
|
|
87734
|
+
try {
|
|
87735
|
+
resolveModule("kokoro-js");
|
|
87736
|
+
resolveModule("@huggingface/transformers");
|
|
87737
|
+
return true;
|
|
87738
|
+
} catch {
|
|
87739
|
+
return false;
|
|
87740
|
+
}
|
|
87741
|
+
}
|
|
87460
87742
|
var KOKORO_DEFAULT_VOICES = [
|
|
87461
87743
|
{
|
|
87462
87744
|
id: "af_heart",
|
|
@@ -87786,7 +88068,7 @@ function parseGender(s) {
|
|
|
87786
88068
|
}
|
|
87787
88069
|
|
|
87788
88070
|
// src/providers/audio/whisper-cpp.ts
|
|
87789
|
-
import { createHash as
|
|
88071
|
+
import { createHash as createHash28 } from "crypto";
|
|
87790
88072
|
import { createReadStream as createReadStream5 } from "fs";
|
|
87791
88073
|
import { mkdir as mkdir37, readFile as readFile39, rename as rename11, rm as rm25, writeFile as writeFile14 } from "fs/promises";
|
|
87792
88074
|
import { basename as basename12, join as join52 } from "path";
|
|
@@ -88081,7 +88363,7 @@ async function* downloadWithSha256(fetchImpl, opts) {
|
|
|
88081
88363
|
yield { type: "progress", bytesWritten: writtenAll, totalBytes: totalAllBytes };
|
|
88082
88364
|
}
|
|
88083
88365
|
}
|
|
88084
|
-
const hasher =
|
|
88366
|
+
const hasher = createHash28("sha256");
|
|
88085
88367
|
await new Promise((resolve19, reject) => {
|
|
88086
88368
|
const stream = createReadStream5(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
88087
88369
|
stream.on("data", (chunk2) => hasher.update(chunk2));
|
|
@@ -88132,6 +88414,41 @@ function machineEngineProxy(ctx, sourcePrefix, targetPrefix, localPaths = [], sh
|
|
|
88132
88414
|
|
|
88133
88415
|
// src/http/routes/audio.ts
|
|
88134
88416
|
var log85 = createLogger88("audio");
|
|
88417
|
+
function buildAudioCatalog(options = {}) {
|
|
88418
|
+
const kokoroRuntimeAvailable = options.kokoroRuntimeAvailable ?? isKokoroRuntimeAvailable();
|
|
88419
|
+
return {
|
|
88420
|
+
// All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
|
|
88421
|
+
// Kokoro under Apache 2.0. Both are permissive → "Free, open".
|
|
88422
|
+
stt: WHISPER_MODEL_CATALOG.map((m) => ({
|
|
88423
|
+
id: m.id,
|
|
88424
|
+
name: m.name,
|
|
88425
|
+
description: m.description,
|
|
88426
|
+
approxSizeBytes: m.approxSizeBytes,
|
|
88427
|
+
kind: "stt",
|
|
88428
|
+
license: "MIT",
|
|
88429
|
+
licenseClass: "open",
|
|
88430
|
+
licenseShortName: "MIT",
|
|
88431
|
+
licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
|
|
88432
|
+
// The Base (English) variant is the recommended STT default: ~140 MB,
|
|
88433
|
+
// realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
|
|
88434
|
+
...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
|
|
88435
|
+
})),
|
|
88436
|
+
tts: kokoroRuntimeAvailable ? [
|
|
88437
|
+
{
|
|
88438
|
+
id: KOKORO_DEFAULT_MODEL_ID,
|
|
88439
|
+
name: "Kokoro 82M v1.0",
|
|
88440
|
+
description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
|
|
88441
|
+
approxSizeBytes: 95e6,
|
|
88442
|
+
kind: "tts",
|
|
88443
|
+
license: "Apache 2.0",
|
|
88444
|
+
licenseClass: "open",
|
|
88445
|
+
licenseShortName: "Apache 2.0",
|
|
88446
|
+
licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
|
|
88447
|
+
recoScore: 20
|
|
88448
|
+
}
|
|
88449
|
+
] : []
|
|
88450
|
+
};
|
|
88451
|
+
}
|
|
88135
88452
|
function audioRoutes(ctx) {
|
|
88136
88453
|
const app = new Hono4();
|
|
88137
88454
|
app.use(
|
|
@@ -88253,38 +88570,7 @@ function audioRoutes(ctx) {
|
|
|
88253
88570
|
});
|
|
88254
88571
|
});
|
|
88255
88572
|
app.get("/catalog", (c) => {
|
|
88256
|
-
return c.json(
|
|
88257
|
-
// All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
|
|
88258
|
-
// Kokoro under Apache 2.0. Both are permissive → "Free, open".
|
|
88259
|
-
stt: WHISPER_MODEL_CATALOG.map((m) => ({
|
|
88260
|
-
id: m.id,
|
|
88261
|
-
name: m.name,
|
|
88262
|
-
description: m.description,
|
|
88263
|
-
approxSizeBytes: m.approxSizeBytes,
|
|
88264
|
-
kind: "stt",
|
|
88265
|
-
license: "MIT",
|
|
88266
|
-
licenseClass: "open",
|
|
88267
|
-
licenseShortName: "MIT",
|
|
88268
|
-
licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
|
|
88269
|
-
// The Base (English) variant is the recommended STT default: ~140 MB,
|
|
88270
|
-
// realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
|
|
88271
|
-
...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
|
|
88272
|
-
})),
|
|
88273
|
-
tts: [
|
|
88274
|
-
{
|
|
88275
|
-
id: KOKORO_DEFAULT_MODEL_ID,
|
|
88276
|
-
name: "Kokoro 82M v1.0",
|
|
88277
|
-
description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
|
|
88278
|
-
approxSizeBytes: 95e6,
|
|
88279
|
-
kind: "tts",
|
|
88280
|
-
license: "Apache 2.0",
|
|
88281
|
-
licenseClass: "open",
|
|
88282
|
-
licenseShortName: "Apache 2.0",
|
|
88283
|
-
licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
|
|
88284
|
-
recoScore: 20
|
|
88285
|
-
}
|
|
88286
|
-
]
|
|
88287
|
-
});
|
|
88573
|
+
return c.json(buildAudioCatalog());
|
|
88288
88574
|
});
|
|
88289
88575
|
app.get("/stt/models", async (c) => {
|
|
88290
88576
|
const provider = await ctx.stt.current();
|
|
@@ -90256,6 +90542,8 @@ function configRoutes(ctx) {
|
|
|
90256
90542
|
autoUpdateChecks: config.autoUpdateChecks !== false,
|
|
90257
90543
|
quitOnClose: config.quitOnClose === true,
|
|
90258
90544
|
themePref: config.themePref,
|
|
90545
|
+
cliShowThinking: config.cliShowThinking !== false,
|
|
90546
|
+
cliShowWrites: config.cliShowWrites === true,
|
|
90259
90547
|
documentExportOptions: config.documentExportOptions,
|
|
90260
90548
|
sidebarSide: config.sidebarSide,
|
|
90261
90549
|
homeGreetingCollapsed: config.homeGreetingCollapsed === true,
|
|
@@ -90602,6 +90890,8 @@ function configRoutes(ctx) {
|
|
|
90602
90890
|
autoUpdateChecks: updated.autoUpdateChecks !== false,
|
|
90603
90891
|
quitOnClose: updated.quitOnClose === true,
|
|
90604
90892
|
themePref: updated.themePref,
|
|
90893
|
+
cliShowThinking: updated.cliShowThinking !== false,
|
|
90894
|
+
cliShowWrites: updated.cliShowWrites === true,
|
|
90605
90895
|
documentExportOptions: updated.documentExportOptions,
|
|
90606
90896
|
sidebarSide: updated.sidebarSide,
|
|
90607
90897
|
homeGreetingCollapsed: updated.homeGreetingCollapsed === true,
|
|
@@ -91991,7 +92281,11 @@ function ds4Routes(ctx) {
|
|
|
91991
92281
|
const catalogId = c.req.param("catalogId");
|
|
91992
92282
|
const skipShaRaw = c.req.query("skipSha");
|
|
91993
92283
|
const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
|
|
91994
|
-
ctx.chatInstalls.ds4.start(catalogId, {
|
|
92284
|
+
ctx.chatInstalls.ds4.start(catalogId, {
|
|
92285
|
+
skipSha,
|
|
92286
|
+
includeMmproj: false,
|
|
92287
|
+
installCompanion: false
|
|
92288
|
+
});
|
|
91995
92289
|
return streamSSE5(c, (stream) => subscribeToInstallSse(ctx.chatInstalls.ds4, catalogId, stream));
|
|
91996
92290
|
});
|
|
91997
92291
|
app.delete("/models/:catalogId/install", (c) => {
|
|
@@ -93679,6 +93973,7 @@ function gezelRoutes(ctx) {
|
|
|
93679
93973
|
toGezelIdOrName: toId,
|
|
93680
93974
|
projectId: body.projectId,
|
|
93681
93975
|
text: body.text,
|
|
93976
|
+
...body.suppressReply ? { suppressReply: true } : {},
|
|
93682
93977
|
...body.expectedDeliverable ? { expectedDeliverable: body.expectedDeliverable } : {}
|
|
93683
93978
|
});
|
|
93684
93979
|
return c.json({
|
|
@@ -94620,7 +94915,7 @@ import { HandboekRenderModeSchema } from "@bendyline/gezel";
|
|
|
94620
94915
|
import { Hono as Hono29 } from "hono";
|
|
94621
94916
|
|
|
94622
94917
|
// src/handboek/narration.ts
|
|
94623
|
-
import { createHash as
|
|
94918
|
+
import { createHash as createHash29 } from "crypto";
|
|
94624
94919
|
import { existsSync as existsSync14 } from "fs";
|
|
94625
94920
|
import { mkdir as mkdir42, readFile as readFile43, writeFile as writeFile16 } from "fs/promises";
|
|
94626
94921
|
import { join as join65 } from "path";
|
|
@@ -94636,7 +94931,7 @@ function createHandboekNarrator(deps) {
|
|
|
94636
94931
|
const pathFor = (hash) => join65(dir, `${hash}.wav`);
|
|
94637
94932
|
const metaPathFor = (hash) => join65(dir, `${hash}.json`);
|
|
94638
94933
|
async function ensureSegment(key, synthesize) {
|
|
94639
|
-
const hash =
|
|
94934
|
+
const hash = createHash29("sha256").update(key).digest("hex");
|
|
94640
94935
|
const metaPath = metaPathFor(hash);
|
|
94641
94936
|
if (existsSync14(pathFor(hash)) && existsSync14(metaPath)) {
|
|
94642
94937
|
try {
|
|
@@ -95636,9 +95931,15 @@ function llamaCppRoutes(ctx) {
|
|
|
95636
95931
|
const catalogId = c.req.param("catalogId");
|
|
95637
95932
|
const skipShaRaw = c.req.query("skipSha");
|
|
95638
95933
|
const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
|
|
95934
|
+
const skipCompanionRaw = c.req.query("skipCompanion");
|
|
95935
|
+
const skipCompanion = skipCompanionRaw != null && skipCompanionRaw !== "" && skipCompanionRaw !== "0" && skipCompanionRaw !== "false";
|
|
95639
95936
|
const config = await ctx.store.readConfig().catch(() => null);
|
|
95640
95937
|
const includeMmproj = config?.nativeVision?.[catalogId] === true;
|
|
95641
|
-
ctx.chatInstalls.llamaCpp.start(catalogId, {
|
|
95938
|
+
ctx.chatInstalls.llamaCpp.start(catalogId, {
|
|
95939
|
+
skipSha,
|
|
95940
|
+
includeMmproj,
|
|
95941
|
+
installCompanion: !skipCompanion
|
|
95942
|
+
});
|
|
95642
95943
|
return streamSSE9(
|
|
95643
95944
|
c,
|
|
95644
95945
|
(stream) => subscribeToInstallSse(ctx.chatInstalls.llamaCpp, catalogId, stream)
|
|
@@ -95729,7 +96030,7 @@ function mcpToolRoutes(ctx) {
|
|
|
95729
96030
|
import { Hono as Hono36 } from "hono";
|
|
95730
96031
|
|
|
95731
96032
|
// src/meester/status-generator.ts
|
|
95732
|
-
import { createHash as
|
|
96033
|
+
import { createHash as createHash30 } from "crypto";
|
|
95733
96034
|
import {
|
|
95734
96035
|
MEESTER_STATUS_HEADLINE_MAX,
|
|
95735
96036
|
MeesterStatusModelOutputSchema,
|
|
@@ -96041,7 +96342,7 @@ function localDay4(date) {
|
|
|
96041
96342
|
return `${y}-${m}-${d}`;
|
|
96042
96343
|
}
|
|
96043
96344
|
function actionKey(projectId, title) {
|
|
96044
|
-
return
|
|
96345
|
+
return createHash30("sha256").update(`${projectId}
|
|
96045
96346
|
${normalizeTitle(title)}`).digest("hex");
|
|
96046
96347
|
}
|
|
96047
96348
|
function normalizeTitle(title) {
|
|
@@ -96053,7 +96354,7 @@ function hashInput(candidates) {
|
|
|
96053
96354
|
...c.openTasks.map((t) => `${t.ref}:${t.status}`),
|
|
96054
96355
|
...c.events.map((e) => e.id)
|
|
96055
96356
|
]);
|
|
96056
|
-
return
|
|
96357
|
+
return createHash30("sha256").update(lines.join("\n")).digest("hex");
|
|
96057
96358
|
}
|
|
96058
96359
|
function parseModelOutput(raw) {
|
|
96059
96360
|
const fence = raw.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/);
|
|
@@ -96153,19 +96454,19 @@ function memoryRoutes(ctx) {
|
|
|
96153
96454
|
const app = new Hono37();
|
|
96154
96455
|
app.post("/search", async (c) => {
|
|
96155
96456
|
const body = await c.req.json();
|
|
96156
|
-
const
|
|
96457
|
+
const outcome = await ctx.memory.searchAllDetailed(
|
|
96157
96458
|
body.gezelId,
|
|
96158
96459
|
body.projectId,
|
|
96159
96460
|
body.query,
|
|
96160
96461
|
body.topK ?? 10
|
|
96161
96462
|
);
|
|
96162
|
-
return c.json(
|
|
96463
|
+
return c.json(outcome);
|
|
96163
96464
|
});
|
|
96164
96465
|
app.post("/save", async (c) => {
|
|
96165
96466
|
const body = await c.req.json();
|
|
96166
96467
|
const kind = isMemoryKind(body.kind) ? body.kind : "fact";
|
|
96167
96468
|
const outcome = await ctx.memory.save(body.scope, body.id, body.text, kind);
|
|
96168
|
-
return c.json({ ok: true,
|
|
96469
|
+
return c.json({ ok: true, ...outcome });
|
|
96169
96470
|
});
|
|
96170
96471
|
app.get("/recent", async (c) => {
|
|
96171
96472
|
const scope = c.req.query("scope") ?? "gezel";
|
|
@@ -96346,7 +96647,7 @@ import { Hono as Hono39 } from "hono";
|
|
|
96346
96647
|
import { z as z20 } from "zod";
|
|
96347
96648
|
|
|
96348
96649
|
// src/models/gezmodel.ts
|
|
96349
|
-
import { createHash as
|
|
96650
|
+
import { createHash as createHash31, randomUUID as randomUUID19 } from "crypto";
|
|
96350
96651
|
import { createReadStream as createReadStream6, createWriteStream as createWriteStream5 } from "fs";
|
|
96351
96652
|
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";
|
|
96352
96653
|
import { basename as basename14, dirname as dirname35, extname as extname5, join as join66 } from "path";
|
|
@@ -96448,7 +96749,7 @@ var GezmodelManager = class {
|
|
|
96448
96749
|
files.push({
|
|
96449
96750
|
path: path2,
|
|
96450
96751
|
sizeBytes: content.byteLength,
|
|
96451
|
-
sha256:
|
|
96752
|
+
sha256: createHash31("sha256").update(content).digest("hex"),
|
|
96452
96753
|
role: path2 === "manifests/installed.json" ? "installed-manifest" : path2 === "manifests/catalog.json" ? "catalog-manifest" : "catalog-file"
|
|
96453
96754
|
});
|
|
96454
96755
|
}
|
|
@@ -96654,7 +96955,7 @@ var GezmodelManager = class {
|
|
|
96654
96955
|
}
|
|
96655
96956
|
};
|
|
96656
96957
|
async function hashFile(path2) {
|
|
96657
|
-
const hash =
|
|
96958
|
+
const hash = createHash31("sha256");
|
|
96658
96959
|
const stream = createReadStream6(path2, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
96659
96960
|
for await (const chunk2 of stream) hash.update(chunk2);
|
|
96660
96961
|
return hash.digest("hex");
|
|
@@ -96852,7 +97153,7 @@ function extractOne(archivePath, wanted, dest, expected) {
|
|
|
96852
97153
|
zip.openReadStream(entry, (streamErr, stream) => {
|
|
96853
97154
|
if (streamErr || !stream)
|
|
96854
97155
|
return fail2(streamErr ?? new Error("could not read ZIP entry"));
|
|
96855
|
-
const hash =
|
|
97156
|
+
const hash = createHash31("sha256");
|
|
96856
97157
|
let bytes = 0;
|
|
96857
97158
|
const verifier = new Transform({
|
|
96858
97159
|
transform(chunk2, _encoding, callback) {
|
|
@@ -97086,7 +97387,7 @@ import {
|
|
|
97086
97387
|
} from "@bendyline/gezel";
|
|
97087
97388
|
|
|
97088
97389
|
// src/providers/mlx/models.ts
|
|
97089
|
-
import { createHash as
|
|
97390
|
+
import { createHash as createHash32 } from "crypto";
|
|
97090
97391
|
import { createReadStream as createReadStream7 } from "fs";
|
|
97091
97392
|
import { mkdir as mkdir44, readFile as readFile47, rename as rename12, rm as rm30, stat as stat27, writeFile as writeFile18 } from "fs/promises";
|
|
97092
97393
|
import { join as join68, resolve as resolvePath2 } from "path";
|
|
@@ -97648,7 +97949,7 @@ var MlxModelManager = class {
|
|
|
97648
97949
|
}
|
|
97649
97950
|
}
|
|
97650
97951
|
push({ type: "verifying", file: file.name });
|
|
97651
|
-
const hasher =
|
|
97952
|
+
const hasher = createHash32("sha256");
|
|
97652
97953
|
await new Promise((resolve19, reject) => {
|
|
97653
97954
|
const stream = createReadStream7(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
97654
97955
|
stream.on("data", (chunk2) => hasher.update(chunk2));
|
|
@@ -99488,7 +99789,7 @@ function describeHostCadence(args) {
|
|
|
99488
99789
|
}
|
|
99489
99790
|
|
|
99490
99791
|
// src/project-type/craftbooks.ts
|
|
99491
|
-
import { createHash as
|
|
99792
|
+
import { createHash as createHash33 } from "crypto";
|
|
99492
99793
|
import {
|
|
99493
99794
|
craftbookFromDoc as craftbookFromDoc3,
|
|
99494
99795
|
createLogger as createLogger109,
|
|
@@ -99512,7 +99813,7 @@ function craftbookContentHash(book) {
|
|
|
99512
99813
|
command: book.command ?? null,
|
|
99513
99814
|
requirements: book.requirements ?? null
|
|
99514
99815
|
};
|
|
99515
|
-
return `sha256:${
|
|
99816
|
+
return `sha256:${createHash33("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
|
|
99516
99817
|
}
|
|
99517
99818
|
async function resolveTypeCraftbook(catalog, input, id, now) {
|
|
99518
99819
|
const embedded = await catalog.readItemFile(
|
|
@@ -100220,7 +100521,7 @@ function pageInvokeRoutes(ctx) {
|
|
|
100220
100521
|
}
|
|
100221
100522
|
|
|
100222
100523
|
// src/http/routes/page-read.ts
|
|
100223
|
-
import { createHash as
|
|
100524
|
+
import { createHash as createHash34 } from "crypto";
|
|
100224
100525
|
import { readFile as readFile50, readdir as readdir29, stat as stat28 } from "fs/promises";
|
|
100225
100526
|
import { PageReadRequestSchema, createLogger as createLogger113 } from "@bendyline/gezel";
|
|
100226
100527
|
import { Hono as Hono48 } from "hono";
|
|
@@ -100229,7 +100530,7 @@ var PAGE_READ_MAX_BYTES = 2 * 1024 * 1024;
|
|
|
100229
100530
|
var RATE_WINDOW_MS3 = 6e4;
|
|
100230
100531
|
var RATE_MAX_READS = 600;
|
|
100231
100532
|
function etagOf(size, mtimeMs) {
|
|
100232
|
-
return
|
|
100533
|
+
return createHash34("sha256").update(`${size}:${Math.trunc(mtimeMs)}`).digest("base64url").slice(0, 16);
|
|
100233
100534
|
}
|
|
100234
100535
|
function pageReadRoutes(ctx) {
|
|
100235
100536
|
const app = new Hono48();
|
|
@@ -100279,7 +100580,7 @@ function pageReadRoutes(ctx) {
|
|
|
100279
100580
|
return `${entry.name}:${entry.isDirectory() ? "dir" : "file"}:${Math.trunc(child?.mtimeMs ?? 0)}`;
|
|
100280
100581
|
})
|
|
100281
100582
|
);
|
|
100282
|
-
const digest =
|
|
100583
|
+
const digest = createHash34("sha256").update(listed.sort().join("\n")).digest("base64url").slice(0, 16);
|
|
100283
100584
|
return c.json({ op: "stat", etag: digest, mtime: stats.mtimeMs });
|
|
100284
100585
|
}
|
|
100285
100586
|
return c.json({
|
|
@@ -100304,7 +100605,7 @@ function pageReadRoutes(ctx) {
|
|
|
100304
100605
|
};
|
|
100305
100606
|
})
|
|
100306
100607
|
)).filter((entry) => entry !== null);
|
|
100307
|
-
const digest =
|
|
100608
|
+
const digest = createHash34("sha256").update(
|
|
100308
100609
|
listed.map((e) => `${e.name}:${e.kind}:${Math.trunc(e.mtime)}`).sort().join("\n")
|
|
100309
100610
|
).digest("base64url").slice(0, 16);
|
|
100310
100611
|
return c.json({ op: "list", entries: listed, etag: digest, mtime: stats.mtimeMs });
|
|
@@ -101014,10 +101315,11 @@ import {
|
|
|
101014
101315
|
projectGezelId as projectGezelId2,
|
|
101015
101316
|
skillToCraftbookDoc
|
|
101016
101317
|
} from "@bendyline/gezel";
|
|
101318
|
+
init_ensure();
|
|
101017
101319
|
init_install();
|
|
101018
101320
|
|
|
101019
101321
|
// src/workspace/instruction-scanner.ts
|
|
101020
|
-
import { createHash as
|
|
101322
|
+
import { createHash as createHash35 } from "crypto";
|
|
101021
101323
|
import { readFile as readFile52, stat as stat30 } from "fs/promises";
|
|
101022
101324
|
import { join as join73 } from "path";
|
|
101023
101325
|
var MAX_CONTENT_CHARS = 64e3;
|
|
@@ -101062,7 +101364,7 @@ ${i.content.trim()}`).join("\n\n---\n\n");
|
|
|
101062
101364
|
return { content: chosen.content, sourceFile: chosen.source, hash: chosen.hash };
|
|
101063
101365
|
}
|
|
101064
101366
|
function sha2563(s) {
|
|
101065
|
-
return
|
|
101367
|
+
return createHash35("sha256").update(s).digest("hex");
|
|
101066
101368
|
}
|
|
101067
101369
|
|
|
101068
101370
|
// src/workspace/skill-script-translator.ts
|
|
@@ -101196,6 +101498,30 @@ async function translateShellBlock(chat, skillName, scriptName, code) {
|
|
|
101196
101498
|
// src/workspace/import-sync.ts
|
|
101197
101499
|
var log110 = createLogger114("import-sync");
|
|
101198
101500
|
var VOORMAN_TEMPLATE_ID = "voorman";
|
|
101501
|
+
var BUILDER_TEMPLATE_ID = "builder";
|
|
101502
|
+
async function ensureFolderProjectBuilder(deps, projectId) {
|
|
101503
|
+
const { store, catalog } = deps;
|
|
101504
|
+
if (!projectId || projectId === "default") return {};
|
|
101505
|
+
const project = await store.getProject(projectId).catch(() => null);
|
|
101506
|
+
if (!project || project.mode !== "solo" || !project.workingDir) return {};
|
|
101507
|
+
if (project.voormanGezelId) return {};
|
|
101508
|
+
const gezels = await store.listGezels().catch(() => []);
|
|
101509
|
+
const existing = gezels.find(
|
|
101510
|
+
(gezel) => gezel.templateId === BUILDER_TEMPLATE_ID || gezel.role?.trim().toLowerCase() === BUILDER_TEMPLATE_ID
|
|
101511
|
+
);
|
|
101512
|
+
const recruited = existing ? null : await recruitFromTemplate(store, catalog, BUILDER_TEMPLATE_ID).catch((err) => {
|
|
101513
|
+
log110.warn(`[import-sync] ${projectId}: Builder recruit failed: ${describe6(err)}`);
|
|
101514
|
+
return null;
|
|
101515
|
+
});
|
|
101516
|
+
const builder = existing ?? recruited;
|
|
101517
|
+
if (!builder) return {};
|
|
101518
|
+
await store.updateProject(projectId, {
|
|
101519
|
+
voormanGezelId: builder.id,
|
|
101520
|
+
voormanAutoAssignedAt: nowIso12()
|
|
101521
|
+
});
|
|
101522
|
+
log110.info(`[import-sync] ${projectId}: assigned ${builder.id} as Builder`);
|
|
101523
|
+
return recruited ? { createdGezel: recruited } : {};
|
|
101524
|
+
}
|
|
101199
101525
|
async function syncProjectImports(deps, projectId, instructions, skills) {
|
|
101200
101526
|
const { store } = deps;
|
|
101201
101527
|
const gate = await store.assertWorkspaceWritable(projectId).catch(() => null);
|
|
@@ -101324,16 +101650,20 @@ async function findExistingVoorman(store) {
|
|
|
101324
101650
|
return match?.id ?? null;
|
|
101325
101651
|
}
|
|
101326
101652
|
async function recruitVoorman(store, catalog) {
|
|
101327
|
-
|
|
101328
|
-
|
|
101653
|
+
return recruitFromTemplate(store, catalog, VOORMAN_TEMPLATE_ID);
|
|
101654
|
+
}
|
|
101655
|
+
async function recruitFromTemplate(store, catalog, templateId) {
|
|
101656
|
+
const template = await resolveGildeTemplateForRole(catalog, templateId).catch(() => null);
|
|
101657
|
+
if (!template || template.templateId !== templateId) return null;
|
|
101329
101658
|
const { name, gender } = pickRandomNameWithGender4();
|
|
101330
101659
|
const created = await store.createGezel({
|
|
101331
101660
|
name,
|
|
101332
|
-
role:
|
|
101661
|
+
role: template.role,
|
|
101333
101662
|
gender,
|
|
101334
|
-
about:
|
|
101335
|
-
templateId
|
|
101336
|
-
templateVersion:
|
|
101663
|
+
about: template.about,
|
|
101664
|
+
templateId,
|
|
101665
|
+
templateVersion: template.templateVersion,
|
|
101666
|
+
...template.frontmatter ? { frontmatter: template.frontmatter } : {}
|
|
101337
101667
|
});
|
|
101338
101668
|
return { id: created.id, name: created.name };
|
|
101339
101669
|
}
|
|
@@ -101808,6 +102138,7 @@ async function resolveActor(ctx, gezelIdHeader) {
|
|
|
101808
102138
|
}
|
|
101809
102139
|
function projectTaskRoutes(ctx) {
|
|
101810
102140
|
const app = new Hono55();
|
|
102141
|
+
const inflightCraftbookInvocations = /* @__PURE__ */ new Map();
|
|
101811
102142
|
app.get("/:projectId/tasks", async (c) => {
|
|
101812
102143
|
const projectId = c.req.param("projectId");
|
|
101813
102144
|
const filter = ListFilterSchema.parse({
|
|
@@ -101823,10 +102154,31 @@ function projectTaskRoutes(ctx) {
|
|
|
101823
102154
|
});
|
|
101824
102155
|
app.post("/:projectId/tasks", async (c) => {
|
|
101825
102156
|
const projectId = c.req.param("projectId");
|
|
101826
|
-
const { dispatchEntry, ...body } = CreateTaskRequestSchema.parse(
|
|
102157
|
+
const { dispatchEntry, craftbookInvocationKey, ...body } = CreateTaskRequestSchema.parse(
|
|
102158
|
+
await c.req.json()
|
|
102159
|
+
);
|
|
101827
102160
|
let task;
|
|
101828
102161
|
try {
|
|
101829
|
-
|
|
102162
|
+
if (craftbookInvocationKey) {
|
|
102163
|
+
const existing = (await ctx.tasks.list({ projectId })).find(
|
|
102164
|
+
(candidate) => candidate.origin?.kind === "craftbook-invocation" && candidate.origin.key === craftbookInvocationKey && (candidate.status === "draft" || candidate.status === "active" || candidate.status === "paused")
|
|
102165
|
+
);
|
|
102166
|
+
if (existing) return c.json(existing);
|
|
102167
|
+
const inflightKey = `${projectId}:${craftbookInvocationKey}`;
|
|
102168
|
+
const pending5 = inflightCraftbookInvocations.get(inflightKey);
|
|
102169
|
+
if (pending5) return c.json(await pending5);
|
|
102170
|
+
const create = ctx.tasks.create(projectId, body, {
|
|
102171
|
+
origin: { kind: "craftbook-invocation", key: craftbookInvocationKey }
|
|
102172
|
+
});
|
|
102173
|
+
inflightCraftbookInvocations.set(inflightKey, create);
|
|
102174
|
+
try {
|
|
102175
|
+
task = await create;
|
|
102176
|
+
} finally {
|
|
102177
|
+
inflightCraftbookInvocations.delete(inflightKey);
|
|
102178
|
+
}
|
|
102179
|
+
} else {
|
|
102180
|
+
task = await ctx.tasks.create(projectId, body);
|
|
102181
|
+
}
|
|
101830
102182
|
} catch (err) {
|
|
101831
102183
|
if (err instanceof CraftbookSetupRequiredError) {
|
|
101832
102184
|
return c.json(
|
|
@@ -102897,7 +103249,7 @@ async function recoverTypedProjectCreations(store) {
|
|
|
102897
103249
|
}
|
|
102898
103250
|
|
|
102899
103251
|
// src/project-type/gzl.ts
|
|
102900
|
-
import { createHash as
|
|
103252
|
+
import { createHash as createHash36 } from "crypto";
|
|
102901
103253
|
import { mkdir as mkdir48, writeFile as writeFile21 } from "fs/promises";
|
|
102902
103254
|
import { dirname as dirname40 } from "path";
|
|
102903
103255
|
import {
|
|
@@ -102915,7 +103267,7 @@ function shard(id) {
|
|
|
102915
103267
|
return id.slice(0, 2).toLowerCase();
|
|
102916
103268
|
}
|
|
102917
103269
|
function hashItemFiles(files) {
|
|
102918
|
-
const hash =
|
|
103270
|
+
const hash = createHash36("sha256");
|
|
102919
103271
|
for (const { rel, content } of [...files].sort((a, b) => a.rel < b.rel ? -1 : 1)) {
|
|
102920
103272
|
hash.update(rel);
|
|
102921
103273
|
hash.update("\0");
|
|
@@ -103063,7 +103415,7 @@ async function importGzlBundle(deps, buffer, opts = {}) {
|
|
|
103063
103415
|
|
|
103064
103416
|
// src/workspace/command-approvals.ts
|
|
103065
103417
|
init_atomic();
|
|
103066
|
-
import { createHash as
|
|
103418
|
+
import { createHash as createHash37 } from "crypto";
|
|
103067
103419
|
import { existsSync as existsSync18 } from "fs";
|
|
103068
103420
|
import { mkdir as mkdir49, readFile as readFile57 } from "fs/promises";
|
|
103069
103421
|
import { dirname as dirname41, join as join79 } from "path";
|
|
@@ -103071,7 +103423,7 @@ import { projectPrivateDir as projectPrivateDir5 } from "@bendyline/gezel/paths"
|
|
|
103071
103423
|
function hashCommandInvocation(body, args, inputFiles = []) {
|
|
103072
103424
|
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));
|
|
103073
103425
|
const payload = JSON.stringify({ version: 2, body: body ?? null, args, files });
|
|
103074
|
-
return
|
|
103426
|
+
return createHash37("sha256").update("gezel-command-invocation\0").update(payload).digest("hex");
|
|
103075
103427
|
}
|
|
103076
103428
|
function approvalsPath(home, projectId) {
|
|
103077
103429
|
return join79(projectPrivateDir5(home, projectId), "command-approvals.json");
|
|
@@ -103297,20 +103649,20 @@ import {
|
|
|
103297
103649
|
} from "@bendyline/gezel";
|
|
103298
103650
|
import { projectPrivateDir as projectPrivateDir6 } from "@bendyline/gezel/paths";
|
|
103299
103651
|
var SHIPPED_ALLOWLIST = [
|
|
103300
|
-
{ package: "zod", allowedVersions: ["^3", "^4"] },
|
|
103301
|
-
{ package: "chalk", allowedVersions: ["^5"] },
|
|
103302
|
-
{ package: "commander", allowedVersions: ["^12", "^13"] },
|
|
103303
|
-
{ package: "date-fns", allowedVersions: ["^3", "^4"] },
|
|
103304
|
-
{ package: "yaml", allowedVersions: ["^2"] },
|
|
103305
|
-
{ package: "cheerio", allowedVersions: ["^1"] },
|
|
103306
|
-
{ package: "mime-types", allowedVersions: ["^2", "^3"] },
|
|
103307
|
-
{ package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"] },
|
|
103308
|
-
{ package: "nanoid", allowedVersions: ["^5"] },
|
|
103309
|
-
{ package: "pino", allowedVersions: ["^9"] },
|
|
103310
|
-
{ package: "playwright-core", allowedVersions: ["^1"] },
|
|
103311
|
-
{ package: "tsx", allowedVersions: ["^4"] },
|
|
103312
|
-
{ package: "typescript", allowedVersions: ["^5"] },
|
|
103313
|
-
{ package: "undici", allowedVersions: ["^6", "^7"] }
|
|
103652
|
+
{ package: "zod", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
|
|
103653
|
+
{ package: "chalk", allowedVersions: ["^5"], defaultVersion: "^5" },
|
|
103654
|
+
{ package: "commander", allowedVersions: ["^12", "^13"], defaultVersion: "^13" },
|
|
103655
|
+
{ package: "date-fns", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
|
|
103656
|
+
{ package: "yaml", allowedVersions: ["^2"], defaultVersion: "^2" },
|
|
103657
|
+
{ package: "cheerio", allowedVersions: ["^1"], defaultVersion: "^1" },
|
|
103658
|
+
{ package: "mime-types", allowedVersions: ["^2", "^3"], defaultVersion: "^3" },
|
|
103659
|
+
{ package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"], defaultVersion: "^15" },
|
|
103660
|
+
{ package: "nanoid", allowedVersions: ["^5"], defaultVersion: "^5" },
|
|
103661
|
+
{ package: "pino", allowedVersions: ["^9"], defaultVersion: "^9" },
|
|
103662
|
+
{ package: "playwright-core", allowedVersions: ["^1"], defaultVersion: "^1" },
|
|
103663
|
+
{ package: "tsx", allowedVersions: ["^4"], defaultVersion: "^4" },
|
|
103664
|
+
{ package: "typescript", allowedVersions: ["^5"], defaultVersion: "^5" },
|
|
103665
|
+
{ package: "undici", allowedVersions: ["^6", "^7"], defaultVersion: "^7" }
|
|
103314
103666
|
];
|
|
103315
103667
|
function projectAllowlistPath(home, projectId) {
|
|
103316
103668
|
return join81(projectPrivateDir6(home, projectId), "npm-allowlist.json");
|
|
@@ -103341,6 +103693,9 @@ function matchesAllowlist(pkg, version) {
|
|
|
103341
103693
|
}
|
|
103342
103694
|
return false;
|
|
103343
103695
|
}
|
|
103696
|
+
function shippedDefaultVersion(pkg) {
|
|
103697
|
+
return SHIPPED_ALLOWLIST.find((entry) => entry.package === pkg)?.defaultVersion;
|
|
103698
|
+
}
|
|
103344
103699
|
function matchesProjectApproval(allowlist, pkg, version) {
|
|
103345
103700
|
return allowlist.approved.some((e) => e.package === pkg && e.version === version);
|
|
103346
103701
|
}
|
|
@@ -103470,7 +103825,9 @@ function dedupRequests(raw) {
|
|
|
103470
103825
|
const out = [];
|
|
103471
103826
|
for (const r of raw) {
|
|
103472
103827
|
const pkg = NpmPackageNameSchema.parse(r.package);
|
|
103473
|
-
const version = NpmRegistryVersionSchema.parse(
|
|
103828
|
+
const version = NpmRegistryVersionSchema.parse(
|
|
103829
|
+
r.version ?? shippedDefaultVersion(pkg) ?? "latest"
|
|
103830
|
+
);
|
|
103474
103831
|
const key = keyOf(pkg, version);
|
|
103475
103832
|
if (seen.has(key)) continue;
|
|
103476
103833
|
seen.add(key);
|
|
@@ -103640,7 +103997,7 @@ import { join as join82 } from "path";
|
|
|
103640
103997
|
import { nowIso as nowIso14 } from "@bendyline/gezel";
|
|
103641
103998
|
|
|
103642
103999
|
// src/workspace/command-inputs.ts
|
|
103643
|
-
import { createHash as
|
|
104000
|
+
import { createHash as createHash38 } from "crypto";
|
|
103644
104001
|
import { createReadStream as createReadStream8 } from "fs";
|
|
103645
104002
|
import { readFile as readFile59, realpath as realpath7, stat as stat35 } from "fs/promises";
|
|
103646
104003
|
import { dirname as dirname43, extname as extname6, isAbsolute as isAbsolute10, relative as relative10, resolve as resolve13, sep as sep9 } from "path";
|
|
@@ -103713,7 +104070,7 @@ function portableRelative(root, file) {
|
|
|
103713
104070
|
return relative10(root, file).split(sep9).join("/");
|
|
103714
104071
|
}
|
|
103715
104072
|
async function sha256File4(file) {
|
|
103716
|
-
const hash =
|
|
104073
|
+
const hash = createHash38("sha256");
|
|
103717
104074
|
await new Promise((resolveStream, reject) => {
|
|
103718
104075
|
const stream = createReadStream8(file);
|
|
103719
104076
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
@@ -104272,12 +104629,13 @@ function projectRoutes(ctx) {
|
|
|
104272
104629
|
app.post("/", async (c) => {
|
|
104273
104630
|
const body = CreateProjectRequestSchema.parse(await c.req.json());
|
|
104274
104631
|
const created = await ctx.store.createProject(body);
|
|
104275
|
-
const
|
|
104632
|
+
const ensureLead = body.workingDir && body.mode === "solo" ? ensureFolderProjectBuilder : ensureProjectVoorman;
|
|
104633
|
+
const ensured2 = await ensureLead(
|
|
104276
104634
|
{ store: ctx.store, chat: ctx.chat, home: ctx.home, catalog: ctx.catalog },
|
|
104277
104635
|
created.id
|
|
104278
104636
|
).catch((err) => {
|
|
104279
104637
|
const message = err instanceof Error ? err.message : String(err);
|
|
104280
|
-
log114.warn(`[projects] ensure-
|
|
104638
|
+
log114.warn(`[projects] ensure-lead failed for ${created.id}: ${message}`);
|
|
104281
104639
|
return {};
|
|
104282
104640
|
});
|
|
104283
104641
|
if (ensured2.createdGezel) {
|
|
@@ -104800,6 +105158,31 @@ function projectRoutes(ctx) {
|
|
|
104800
105158
|
return c.json({ error: "not found" }, 404);
|
|
104801
105159
|
}
|
|
104802
105160
|
});
|
|
105161
|
+
app.post("/:id/reveal-reference", async (c) => {
|
|
105162
|
+
const id = c.req.param("id");
|
|
105163
|
+
const request = ReferenceFileLocationRequestSchema.parse({
|
|
105164
|
+
kind: c.req.query("kind"),
|
|
105165
|
+
path: c.req.query("path")
|
|
105166
|
+
});
|
|
105167
|
+
const base = request.kind === "artifact" ? ctx.store.projectArtifactsDir(id) : request.kind === "workspace" ? await ctx.store.projectWorkspaceDir(id) : ctx.store.documentsDir();
|
|
105168
|
+
const joined = safeJoin(base, request.path);
|
|
105169
|
+
if (!joined || !await realpathContained(base, joined)) {
|
|
105170
|
+
return c.json({ error: "path traversal" }, 400);
|
|
105171
|
+
}
|
|
105172
|
+
let path2;
|
|
105173
|
+
try {
|
|
105174
|
+
const file = await stat36(joined);
|
|
105175
|
+
if (!file.isFile()) return c.json({ error: "not found" }, 404);
|
|
105176
|
+
path2 = await realpath8(joined);
|
|
105177
|
+
} catch {
|
|
105178
|
+
return c.json({ error: "not found" }, 404);
|
|
105179
|
+
}
|
|
105180
|
+
const { execFile: execFile8 } = await import("child_process");
|
|
105181
|
+
const launcher = process.platform === "darwin" ? { cmd: "open", args: ["-R", path2] } : process.platform === "win32" ? { cmd: "explorer", args: ["/select,", path2] } : { cmd: "xdg-open", args: [dirname44(path2)] };
|
|
105182
|
+
execFile8(launcher.cmd, launcher.args, { windowsHide: true }, () => {
|
|
105183
|
+
});
|
|
105184
|
+
return c.json(ReferenceFileLocationResponseSchema.parse({ path: path2 }));
|
|
105185
|
+
});
|
|
104803
105186
|
app.get("/:id/artifacts", async (c) => {
|
|
104804
105187
|
const id = c.req.param("id");
|
|
104805
105188
|
const subpath = c.req.query("path") ?? "";
|
|
@@ -107592,7 +107975,7 @@ async function readProjectScriptRun(home, projectId, runId) {
|
|
|
107592
107975
|
}
|
|
107593
107976
|
|
|
107594
107977
|
// src/scripts/sdk.ts
|
|
107595
|
-
import { createHash as
|
|
107978
|
+
import { createHash as createHash40 } from "crypto";
|
|
107596
107979
|
import { readFile as readFile67 } from "fs/promises";
|
|
107597
107980
|
import { dirname as dirname45, join as join87, relative as relative11 } from "path";
|
|
107598
107981
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
@@ -107658,7 +108041,7 @@ async function readSdkTypes() {
|
|
|
107658
108041
|
});
|
|
107659
108042
|
} catch {
|
|
107660
108043
|
}
|
|
107661
|
-
const hash =
|
|
108044
|
+
const hash = createHash40("sha256");
|
|
107662
108045
|
for (const f of files) hash.update(f.name).update("\0").update(f.content);
|
|
107663
108046
|
cachedTypes = { version: hash.digest("hex"), files };
|
|
107664
108047
|
return cachedTypes;
|
|
@@ -110472,9 +110855,13 @@ async function grepWorkspace(opts) {
|
|
|
110472
110855
|
const plan = normalizePlan(opts);
|
|
110473
110856
|
const target = await resolveSearchTarget(opts.workspaceDir, opts.path);
|
|
110474
110857
|
const requestedEngine = opts.engine ?? "auto";
|
|
110475
|
-
const ripgrepPath = requestedEngine === "javascript" ? null : await
|
|
110858
|
+
const ripgrepPath = requestedEngine === "javascript" ? null : await resolveRipgrepExecutable(target.workspaceDir, Math.min(plan.timeoutMs, 2e3));
|
|
110476
110859
|
if (requestedEngine === "ripgrep" && !ripgrepPath) {
|
|
110477
|
-
throw new WorkspaceGrepError(
|
|
110860
|
+
throw new WorkspaceGrepError(
|
|
110861
|
+
"ripgrep is unavailable (the bundled platform package is missing and rg is not on PATH)",
|
|
110862
|
+
500,
|
|
110863
|
+
"rg-unavailable"
|
|
110864
|
+
);
|
|
110478
110865
|
}
|
|
110479
110866
|
let raw;
|
|
110480
110867
|
let engine;
|
|
@@ -110978,6 +111365,16 @@ async function resolveExecutableOnPath(command, forbiddenRoot, timeoutMs) {
|
|
|
110978
111365
|
if (timer) clearTimeout(timer);
|
|
110979
111366
|
}
|
|
110980
111367
|
}
|
|
111368
|
+
async function resolveRipgrepExecutable(forbiddenRoot, timeoutMs) {
|
|
111369
|
+
const onPath = await resolveExecutableOnPath("rg", forbiddenRoot, timeoutMs);
|
|
111370
|
+
if (onPath) return onPath;
|
|
111371
|
+
try {
|
|
111372
|
+
const { rgPath } = await import("@vscode/ripgrep");
|
|
111373
|
+
return await validateExecutable(rgPath, forbiddenRoot);
|
|
111374
|
+
} catch {
|
|
111375
|
+
return null;
|
|
111376
|
+
}
|
|
111377
|
+
}
|
|
110981
111378
|
async function findExecutableOnPath(command, forbiddenRoot) {
|
|
110982
111379
|
const pathValue = process.env.PATH;
|
|
110983
111380
|
if (!pathValue) return null;
|
|
@@ -110986,22 +111383,28 @@ async function findExecutableOnPath(command, forbiddenRoot) {
|
|
|
110986
111383
|
const entry = rawEntry.replace(/^"|"$/g, "");
|
|
110987
111384
|
if (!entry || !isAbsolute11(entry)) continue;
|
|
110988
111385
|
for (const suffix of suffixes) {
|
|
110989
|
-
|
|
110990
|
-
|
|
110991
|
-
|
|
110992
|
-
|
|
110993
|
-
|
|
110994
|
-
await access3(
|
|
110995
|
-
executable,
|
|
110996
|
-
process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK
|
|
110997
|
-
);
|
|
110998
|
-
return executable;
|
|
110999
|
-
} catch {
|
|
111000
|
-
}
|
|
111386
|
+
const executable = await validateExecutable(
|
|
111387
|
+
join89(entry, `${command}${suffix}`),
|
|
111388
|
+
forbiddenRoot
|
|
111389
|
+
);
|
|
111390
|
+
if (executable) return executable;
|
|
111001
111391
|
}
|
|
111002
111392
|
}
|
|
111003
111393
|
return null;
|
|
111004
111394
|
}
|
|
111395
|
+
async function validateExecutable(candidate, forbiddenRoot) {
|
|
111396
|
+
if (!isAbsolute11(candidate)) return null;
|
|
111397
|
+
try {
|
|
111398
|
+
const executable = await realpath10(candidate);
|
|
111399
|
+
if (pathIsInside(forbiddenRoot, executable)) return null;
|
|
111400
|
+
const executableStat = await stat39(executable);
|
|
111401
|
+
if (!executableStat.isFile()) return null;
|
|
111402
|
+
await access3(executable, process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK);
|
|
111403
|
+
return executable;
|
|
111404
|
+
} catch {
|
|
111405
|
+
return null;
|
|
111406
|
+
}
|
|
111407
|
+
}
|
|
111005
111408
|
function pathIsInside(root, candidate) {
|
|
111006
111409
|
const rel = relative12(root, candidate);
|
|
111007
111410
|
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep10}`) && !isAbsolute11(rel);
|
|
@@ -116254,7 +116657,10 @@ function opaqueServerErrors(log189, onUnexpectedHttpError) {
|
|
|
116254
116657
|
const raw = await prior.clone().text().catch(() => "");
|
|
116255
116658
|
try {
|
|
116256
116659
|
const parsed = JSON.parse(raw);
|
|
116257
|
-
if (parsed.error === "internal_error" && typeof parsed.requestId === "string")
|
|
116660
|
+
if (parsed.error === "internal_error" && typeof parsed.requestId === "string") {
|
|
116661
|
+
c.header("x-request-id", parsed.requestId);
|
|
116662
|
+
return;
|
|
116663
|
+
}
|
|
116258
116664
|
if ((parsed.error === "machine_engine_unavailable" || parsed.error === "capacity_denied") && Object.keys(parsed).length === 1) {
|
|
116259
116665
|
return;
|
|
116260
116666
|
}
|
|
@@ -118603,7 +119009,7 @@ function indexShadowBody(store, file, body) {
|
|
|
118603
119009
|
}
|
|
118604
119010
|
|
|
118605
119011
|
// src/index-store/area-pass.ts
|
|
118606
|
-
import { createHash as
|
|
119012
|
+
import { createHash as createHash41 } from "crypto";
|
|
118607
119013
|
var ARCHITECTURE_KEY = "::project";
|
|
118608
119014
|
var MIN_AREA_FILES = 2;
|
|
118609
119015
|
var AREA_INPUT_CAP = 6e3;
|
|
@@ -118665,7 +119071,7 @@ async function runAreaPass(index, deps) {
|
|
|
118665
119071
|
return result;
|
|
118666
119072
|
}
|
|
118667
119073
|
function hashLines(lines) {
|
|
118668
|
-
return
|
|
119074
|
+
return createHash41("sha256").update([...lines].sort().join("\n")).digest("hex");
|
|
118669
119075
|
}
|
|
118670
119076
|
function buildAreaPrompt(area, entries) {
|
|
118671
119077
|
let body = "";
|
|
@@ -118855,9 +119261,9 @@ function triv(kind) {
|
|
|
118855
119261
|
}
|
|
118856
119262
|
|
|
118857
119263
|
// src/index-store/hash.ts
|
|
118858
|
-
import { createHash as
|
|
119264
|
+
import { createHash as createHash42 } from "crypto";
|
|
118859
119265
|
function sha2564(data) {
|
|
118860
|
-
return
|
|
119266
|
+
return createHash42("sha256").update(data).digest("hex");
|
|
118861
119267
|
}
|
|
118862
119268
|
|
|
118863
119269
|
// src/index-store/artifacts-indexer.ts
|
|
@@ -123768,7 +124174,7 @@ ${body}\r
|
|
|
123768
124174
|
}
|
|
123769
124175
|
|
|
123770
124176
|
// src/mail/mime.ts
|
|
123771
|
-
import { createHash as
|
|
124177
|
+
import { createHash as createHash43 } from "crypto";
|
|
123772
124178
|
import { simpleParser } from "mailparser";
|
|
123773
124179
|
|
|
123774
124180
|
// src/mail/html.ts
|
|
@@ -123883,7 +124289,7 @@ function normalizeReferences(refs) {
|
|
|
123883
124289
|
}
|
|
123884
124290
|
function synthesizeMessageId(parsed, ctx) {
|
|
123885
124291
|
const basis = `${addressText(parsed.from)}|${parsed.subject ?? ""}|${parsed.date?.toISOString() ?? ctx.fallbackDate ?? ""}|${ctx.id}`;
|
|
123886
|
-
return `<${
|
|
124292
|
+
return `<${createHash43("sha256").update(basis).digest("hex").slice(0, 32)}@gezel.local>`;
|
|
123887
124293
|
}
|
|
123888
124294
|
async function parseRawMessage(raw, ctx) {
|
|
123889
124295
|
const parsed = await simpleParser(raw);
|
|
@@ -124506,7 +124912,7 @@ async function migrateOversightTask(store, num) {
|
|
|
124506
124912
|
|
|
124507
124913
|
// src/memory/compaction.ts
|
|
124508
124914
|
init_atomic();
|
|
124509
|
-
import { createHash as
|
|
124915
|
+
import { createHash as createHash44 } from "crypto";
|
|
124510
124916
|
import { readFile as readFile77 } from "fs/promises";
|
|
124511
124917
|
import { join as join101 } from "path";
|
|
124512
124918
|
import { createLogger as createLogger160, isProactiveAllowed as isProactiveAllowed5 } from "@bendyline/gezel";
|
|
@@ -124718,7 +125124,7 @@ var MemoryCompactor = class {
|
|
|
124718
125124
|
}
|
|
124719
125125
|
}
|
|
124720
125126
|
if (entries.length < minEntries) return false;
|
|
124721
|
-
const inputHash =
|
|
125127
|
+
const inputHash = createHash44("sha256").update(eligibleDays.map((d) => `${d}
|
|
124722
125128
|
${dayContents.get(d)}`).join("\n")).digest("hex");
|
|
124723
125129
|
const state = await this.readState(scope, id);
|
|
124724
125130
|
if (state.inputHash === inputHash) return false;
|
|
@@ -124824,7 +125230,7 @@ ${dayContents.get(d)}`).join("\n")).digest("hex");
|
|
|
124824
125230
|
const notes = await this.memory.getRecent("gezel", gezelId, lookbackDays);
|
|
124825
125231
|
if (!notes.trim()) return;
|
|
124826
125232
|
const current = await this.store.readMemoryLessons(gezelId);
|
|
124827
|
-
const lessonsInputHash =
|
|
125233
|
+
const lessonsInputHash = createHash44("sha256").update(`${notes}
|
|
124828
125234
|
---
|
|
124829
125235
|
${current}`).digest("hex");
|
|
124830
125236
|
const state = await this.readState("gezel", gezelId);
|
|
@@ -125165,8 +125571,8 @@ var MemoryManager = class {
|
|
|
125165
125571
|
* that text dedups, so we accept the race rather than lock.
|
|
125166
125572
|
*
|
|
125167
125573
|
* Degraded mode (embeddings disabled): markdown is still appended (it is
|
|
125168
|
-
* the source of truth and the
|
|
125169
|
-
*
|
|
125574
|
+
* the source of truth) and the outcome reports deferred indexing. The health
|
|
125575
|
+
* monitor self-heals the derived index once embeddings recover.
|
|
125170
125576
|
*/
|
|
125171
125577
|
async save(scope, id, text, kind = DEFAULT_MEMORY_KIND) {
|
|
125172
125578
|
const trimmed = text.trim();
|
|
@@ -125181,9 +125587,19 @@ var MemoryManager = class {
|
|
|
125181
125587
|
vector = await embed(trimmed);
|
|
125182
125588
|
} catch (err) {
|
|
125183
125589
|
await this.store.appendMemory(scope, id, trimmed, kind);
|
|
125184
|
-
|
|
125590
|
+
log155.warn(
|
|
125591
|
+
`[memory] saved ${scope}/${id} to Markdown; semantic indexing deferred: ${describeError3(err)}`
|
|
125592
|
+
);
|
|
125593
|
+
return deferredIndexOutcome();
|
|
125594
|
+
}
|
|
125595
|
+
let top;
|
|
125596
|
+
try {
|
|
125597
|
+
top = (await searchByVector(indexDir, vector, 1))[0];
|
|
125598
|
+
} catch (error) {
|
|
125599
|
+
log155.warn(
|
|
125600
|
+
`[memory] vector dedup unavailable for ${scope}/${id}; continuing save: ${describeError3(error)}`
|
|
125601
|
+
);
|
|
125185
125602
|
}
|
|
125186
|
-
const top = (await searchByVector(indexDir, vector, 1))[0];
|
|
125187
125603
|
if (top && top.score >= this.dedupThreshold) {
|
|
125188
125604
|
log155.info(
|
|
125189
125605
|
`[memory] dup-skip (${top.score.toFixed(2)} vs "${top.text.slice(0, 40)}") ${scope}/${id}: ${trimmed.slice(0, 60)}`
|
|
@@ -125191,20 +125607,27 @@ var MemoryManager = class {
|
|
|
125191
125607
|
return { status: "duplicate", match: { text: top.text, score: top.score, via: "vector" } };
|
|
125192
125608
|
}
|
|
125193
125609
|
await this.store.appendMemory(scope, id, trimmed, kind);
|
|
125194
|
-
|
|
125195
|
-
|
|
125196
|
-
|
|
125197
|
-
|
|
125198
|
-
|
|
125199
|
-
|
|
125200
|
-
|
|
125201
|
-
|
|
125202
|
-
|
|
125203
|
-
|
|
125204
|
-
|
|
125205
|
-
|
|
125610
|
+
try {
|
|
125611
|
+
await addToIndex(
|
|
125612
|
+
indexDir,
|
|
125613
|
+
{
|
|
125614
|
+
text: trimmed,
|
|
125615
|
+
scope,
|
|
125616
|
+
id,
|
|
125617
|
+
day: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
125618
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
125619
|
+
kind
|
|
125620
|
+
},
|
|
125621
|
+
vector
|
|
125622
|
+
);
|
|
125623
|
+
} catch (error) {
|
|
125624
|
+
log155.warn(
|
|
125625
|
+
`[memory] saved ${scope}/${id} to Markdown; semantic index write deferred: ${describeError3(error)}`
|
|
125626
|
+
);
|
|
125627
|
+
return deferredIndexOutcome();
|
|
125628
|
+
}
|
|
125206
125629
|
log155.info(`[memory] saved ${scope}/${id} [${kind}]: ${trimmed.slice(0, 60)}`);
|
|
125207
|
-
return { status: "saved" };
|
|
125630
|
+
return { status: "saved", indexed: true };
|
|
125208
125631
|
}
|
|
125209
125632
|
/**
|
|
125210
125633
|
* Exact-text match against today's and yesterday's daily files. Two days
|
|
@@ -125226,7 +125649,15 @@ var MemoryManager = class {
|
|
|
125226
125649
|
}
|
|
125227
125650
|
async search(scope, id, query, topK = 10) {
|
|
125228
125651
|
const indexDir = this.store.memoryIndexDir(scope, id);
|
|
125229
|
-
return
|
|
125652
|
+
if (!this.hasIndex(scope, id)) return this.searchLexical(scope, id, query, topK);
|
|
125653
|
+
try {
|
|
125654
|
+
return await searchIndex(indexDir, query, topK);
|
|
125655
|
+
} catch (error) {
|
|
125656
|
+
log155.warn(
|
|
125657
|
+
`[memory] semantic search failed for ${scope}/${id}; using lexical fallback: ${describeError3(error)}`
|
|
125658
|
+
);
|
|
125659
|
+
return this.searchLexical(scope, id, query, topK);
|
|
125660
|
+
}
|
|
125230
125661
|
}
|
|
125231
125662
|
/**
|
|
125232
125663
|
* Like {@link search} but with a precomputed query embedding — lets the
|
|
@@ -125255,11 +125686,64 @@ var MemoryManager = class {
|
|
|
125255
125686
|
return existsSync28(join103(this.store.memoryIndexDir(scope, id), "mem.db"));
|
|
125256
125687
|
}
|
|
125257
125688
|
async searchAll(gezelId, projectId, query, topK = 10) {
|
|
125258
|
-
|
|
125259
|
-
|
|
125260
|
-
|
|
125689
|
+
return (await this.searchAllDetailed(gezelId, projectId, query, topK)).results;
|
|
125690
|
+
}
|
|
125691
|
+
/**
|
|
125692
|
+
* Search both scopes with one query embedding. Missing indexes fall back to
|
|
125693
|
+
* the daily Markdown source; an unavailable/corrupt semantic cache does the
|
|
125694
|
+
* same and reports a degraded mode instead of turning an optional feature
|
|
125695
|
+
* into an HTTP 500.
|
|
125696
|
+
*/
|
|
125697
|
+
async searchAllDetailed(gezelId, projectId, query, topK = 10) {
|
|
125698
|
+
const gezelIndexed = this.hasIndex("gezel", gezelId);
|
|
125699
|
+
const projectIndexed = this.hasIndex("project", projectId);
|
|
125700
|
+
if (!gezelIndexed && !projectIndexed) {
|
|
125701
|
+
return {
|
|
125702
|
+
results: await this.searchAllLexical(gezelId, projectId, query, topK),
|
|
125703
|
+
mode: "lexical"
|
|
125704
|
+
};
|
|
125705
|
+
}
|
|
125706
|
+
try {
|
|
125707
|
+
const vector = await embedQuery(query);
|
|
125708
|
+
const [gezelResults, projectResults] = await Promise.all([
|
|
125709
|
+
gezelIndexed ? this.searchVector("gezel", gezelId, vector, topK) : this.searchLexical("gezel", gezelId, query, topK),
|
|
125710
|
+
projectIndexed ? this.searchVector("project", projectId, vector, topK) : this.searchLexical("project", projectId, query, topK)
|
|
125711
|
+
]);
|
|
125712
|
+
return {
|
|
125713
|
+
results: rankSearchResults([...gezelResults, ...projectResults], topK),
|
|
125714
|
+
mode: gezelIndexed && projectIndexed ? "semantic" : "hybrid"
|
|
125715
|
+
};
|
|
125716
|
+
} catch (error) {
|
|
125717
|
+
log155.warn(
|
|
125718
|
+
`[memory] semantic search unavailable; using daily-memory lexical fallback: ${describeError3(error)}`
|
|
125719
|
+
);
|
|
125720
|
+
return {
|
|
125721
|
+
results: await this.searchAllLexical(gezelId, projectId, query, topK),
|
|
125722
|
+
mode: "lexical",
|
|
125723
|
+
degraded: {
|
|
125724
|
+
code: "semantic_search_unavailable",
|
|
125725
|
+
message: "Semantic memory search is temporarily unavailable; searched saved memory text directly instead."
|
|
125726
|
+
}
|
|
125727
|
+
};
|
|
125728
|
+
}
|
|
125729
|
+
}
|
|
125730
|
+
async searchAllLexical(gezelId, projectId, query, topK) {
|
|
125731
|
+
const [gezelResults, projectResults] = await Promise.all([
|
|
125732
|
+
this.searchLexical("gezel", gezelId, query, topK),
|
|
125733
|
+
this.searchLexical("project", projectId, query, topK)
|
|
125261
125734
|
]);
|
|
125262
|
-
return [...
|
|
125735
|
+
return rankSearchResults([...gezelResults, ...projectResults], topK);
|
|
125736
|
+
}
|
|
125737
|
+
async searchLexical(scope, id, query, topK) {
|
|
125738
|
+
const entries = await this.allEntries(scope, id);
|
|
125739
|
+
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 }) => ({
|
|
125740
|
+
text: entry.text,
|
|
125741
|
+
score,
|
|
125742
|
+
day: entry.day,
|
|
125743
|
+
scope: entry.scope,
|
|
125744
|
+
id: entry.id,
|
|
125745
|
+
kind: entry.kind ?? DEFAULT_MEMORY_KIND
|
|
125746
|
+
}));
|
|
125263
125747
|
}
|
|
125264
125748
|
async listDays(scope, id) {
|
|
125265
125749
|
return this.store.listMemoryDays(scope, id);
|
|
@@ -125324,6 +125808,36 @@ var MemoryManager = class {
|
|
|
125324
125808
|
return entries.length;
|
|
125325
125809
|
}
|
|
125326
125810
|
};
|
|
125811
|
+
function rankSearchResults(results, topK) {
|
|
125812
|
+
return results.sort((a, b) => b.score - a.score).slice(0, topK);
|
|
125813
|
+
}
|
|
125814
|
+
function deferredIndexOutcome() {
|
|
125815
|
+
return {
|
|
125816
|
+
status: "saved",
|
|
125817
|
+
indexed: false,
|
|
125818
|
+
degraded: {
|
|
125819
|
+
code: "semantic_index_unavailable",
|
|
125820
|
+
message: "Memory was saved, but semantic indexing is temporarily unavailable."
|
|
125821
|
+
}
|
|
125822
|
+
};
|
|
125823
|
+
}
|
|
125824
|
+
function lexicalScore(query, text) {
|
|
125825
|
+
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
125826
|
+
const normalizedText = text.toLocaleLowerCase();
|
|
125827
|
+
if (!normalizedQuery || !normalizedText) return 0;
|
|
125828
|
+
if (normalizedText.includes(normalizedQuery)) return 1;
|
|
125829
|
+
const queryTokens = new Set(normalizedQuery.match(/[\p{L}\p{N}_-]+/gu) ?? []);
|
|
125830
|
+
if (queryTokens.size === 0) return 0;
|
|
125831
|
+
const textTokens = new Set(normalizedText.match(/[\p{L}\p{N}_-]+/gu) ?? []);
|
|
125832
|
+
let matches = 0;
|
|
125833
|
+
for (const token of queryTokens) {
|
|
125834
|
+
if (textTokens.has(token)) matches++;
|
|
125835
|
+
}
|
|
125836
|
+
return matches / queryTokens.size;
|
|
125837
|
+
}
|
|
125838
|
+
function describeError3(error) {
|
|
125839
|
+
return error instanceof Error ? error.message : String(error);
|
|
125840
|
+
}
|
|
125327
125841
|
|
|
125328
125842
|
// src/models/install-jobs.ts
|
|
125329
125843
|
import { createLogger as createLogger166 } from "@bendyline/gezel";
|
|
@@ -125486,6 +126000,7 @@ var LlamaVisionProvider = class {
|
|
|
125486
126000
|
await mkdir57(itemDir, { recursive: true });
|
|
125487
126001
|
const totalAllBytes = spec.files.reduce((n, f) => n + f.approxSizeBytes, 0);
|
|
125488
126002
|
let writtenAll = 0;
|
|
126003
|
+
const verifiedDigests = {};
|
|
125489
126004
|
for (const file of spec.files) {
|
|
125490
126005
|
const result = yield* downloadWithSha256(this.fetchImpl, {
|
|
125491
126006
|
url: file.downloadUrl,
|
|
@@ -125501,8 +126016,9 @@ var LlamaVisionProvider = class {
|
|
|
125501
126016
|
return;
|
|
125502
126017
|
}
|
|
125503
126018
|
writtenAll = result.writtenAll;
|
|
126019
|
+
verifiedDigests[file.filename] = file.sha256.toLowerCase();
|
|
125504
126020
|
}
|
|
125505
|
-
const fileSha256 = await hashModelPayloadFiles(itemDir);
|
|
126021
|
+
const fileSha256 = await hashModelPayloadFiles(itemDir, verifiedDigests);
|
|
125506
126022
|
await writeFile26(
|
|
125507
126023
|
join104(itemDir, "manifest.json"),
|
|
125508
126024
|
`${JSON.stringify(
|
|
@@ -125922,7 +126438,7 @@ async function* runGgufInstallWithCompanion(catalogId, o, deps) {
|
|
|
125922
126438
|
yield event;
|
|
125923
126439
|
}
|
|
125924
126440
|
if (!finished) return;
|
|
125925
|
-
yield* companionRecognitionEvents(catalogId, deps);
|
|
126441
|
+
if (o.installCompanion) yield* companionRecognitionEvents(catalogId, deps);
|
|
125926
126442
|
yield finished;
|
|
125927
126443
|
}
|
|
125928
126444
|
async function* companionRecognitionEvents(catalogId, deps) {
|
|
@@ -127230,7 +127746,7 @@ function makeActionable(message) {
|
|
|
127230
127746
|
}
|
|
127231
127747
|
|
|
127232
127748
|
// src/providers/image/sd-cpp.ts
|
|
127233
|
-
import { createHash as
|
|
127749
|
+
import { createHash as createHash45 } from "crypto";
|
|
127234
127750
|
import { createReadStream as createReadStream10 } from "fs";
|
|
127235
127751
|
import { mkdir as mkdir60, readFile as readFile81, rename as rename15, rm as rm41, writeFile as writeFile29 } from "fs/promises";
|
|
127236
127752
|
import { join as join110 } from "path";
|
|
@@ -127569,7 +128085,7 @@ var StableDiffusionCppProvider = class {
|
|
|
127569
128085
|
}
|
|
127570
128086
|
}
|
|
127571
128087
|
const partialPath = `${destPath}.partial`;
|
|
127572
|
-
const hasher =
|
|
128088
|
+
const hasher = createHash45("sha256");
|
|
127573
128089
|
await new Promise((resolve19, reject) => {
|
|
127574
128090
|
const stream = createReadStream10(partialPath, {
|
|
127575
128091
|
highWaterMark: MODEL_HASH_READ_BUFFER_BYTES
|
|
@@ -128088,7 +128604,7 @@ function isMachineImageProvider(config, env) {
|
|
|
128088
128604
|
}
|
|
128089
128605
|
|
|
128090
128606
|
// src/providers/recognition/store.ts
|
|
128091
|
-
import { createHash as
|
|
128607
|
+
import { createHash as createHash46 } from "crypto";
|
|
128092
128608
|
import { mkdir as mkdir61, readFile as readFile82, rename as rename16, rm as rm42, writeFile as writeFile30 } from "fs/promises";
|
|
128093
128609
|
import { join as join112 } from "path";
|
|
128094
128610
|
import { ImageRecognitionSchema, createLogger as createLogger172 } from "@bendyline/gezel";
|
|
@@ -128100,8 +128616,8 @@ var RecognitionCache = class {
|
|
|
128100
128616
|
this.root = join112(opts.home, "recognition");
|
|
128101
128617
|
}
|
|
128102
128618
|
keyFor(input) {
|
|
128103
|
-
const imageHash =
|
|
128104
|
-
return
|
|
128619
|
+
const imageHash = createHash46("sha256").update(input.bytes).digest("hex");
|
|
128620
|
+
return createHash46("sha256").update(`${imageHash}\0${input.mode}\0${input.modelId}\0v${PROMPT_VERSION}`).digest("hex");
|
|
128105
128621
|
}
|
|
128106
128622
|
pathFor(key) {
|
|
128107
128623
|
return join112(this.root, key.slice(0, 2), `${key}.json`);
|
|
@@ -128546,7 +129062,7 @@ var MockVideoProvider = class {
|
|
|
128546
129062
|
};
|
|
128547
129063
|
|
|
128548
129064
|
// src/providers/video/models.ts
|
|
128549
|
-
import { createHash as
|
|
129065
|
+
import { createHash as createHash47 } from "crypto";
|
|
128550
129066
|
import { createReadStream as createReadStream11 } from "fs";
|
|
128551
129067
|
import { mkdir as mkdir62, readFile as readFile83, rename as rename17, rm as rm43, writeFile as writeFile31 } from "fs/promises";
|
|
128552
129068
|
import { dirname as dirname50, join as join113 } from "path";
|
|
@@ -128732,7 +129248,7 @@ var VideoModelManager = class {
|
|
|
128732
129248
|
await rm43(finalPath, { force: true });
|
|
128733
129249
|
await rename17(partialPath, finalPath);
|
|
128734
129250
|
} catch (err) {
|
|
128735
|
-
yield { type: "error", error: `rename failed for ${file.name}: ${
|
|
129251
|
+
yield { type: "error", error: `rename failed for ${file.name}: ${describeError4(err)}` };
|
|
128736
129252
|
return;
|
|
128737
129253
|
}
|
|
128738
129254
|
}
|
|
@@ -128819,7 +129335,7 @@ var VideoModelManager = class {
|
|
|
128819
129335
|
}
|
|
128820
129336
|
}
|
|
128821
129337
|
push({ type: "verifying", file: file.name });
|
|
128822
|
-
const hasher =
|
|
129338
|
+
const hasher = createHash47("sha256");
|
|
128823
129339
|
await new Promise((resolve19, reject) => {
|
|
128824
129340
|
const stream = createReadStream11(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
|
|
128825
129341
|
stream.on("data", (chunk2) => hasher.update(chunk2));
|
|
@@ -128891,7 +129407,7 @@ var VideoModelSelector = class {
|
|
|
128891
129407
|
return (id ? await this.models.resolveModel(id) : null) ?? await this.models.resolveDefaultModel();
|
|
128892
129408
|
}
|
|
128893
129409
|
};
|
|
128894
|
-
function
|
|
129410
|
+
function describeError4(err) {
|
|
128895
129411
|
return err instanceof Error ? err.message : String(err);
|
|
128896
129412
|
}
|
|
128897
129413
|
function isSafeId3(id) {
|
|
@@ -133092,11 +133608,18 @@ var TaskRunner = class {
|
|
|
133092
133608
|
/** Run one serialized dispatch pass now, sharing the interval's overlap guard. */
|
|
133093
133609
|
async wake() {
|
|
133094
133610
|
if (this.tickInFlight) return this.tickInFlight;
|
|
133095
|
-
this.tickInFlight = this.
|
|
133611
|
+
this.tickInFlight = this.tickOnce().finally(() => {
|
|
133096
133612
|
this.tickInFlight = null;
|
|
133097
133613
|
});
|
|
133098
133614
|
return this.tickInFlight;
|
|
133099
133615
|
}
|
|
133616
|
+
/**
|
|
133617
|
+
* Public test/operator entry point. Keep it serialized with the interval:
|
|
133618
|
+
* callers may drive a real, already-started service whose ticker is active.
|
|
133619
|
+
*/
|
|
133620
|
+
async tick() {
|
|
133621
|
+
return this.wake();
|
|
133622
|
+
}
|
|
133100
133623
|
/**
|
|
133101
133624
|
* Scan every `active` task and enqueue a handoff for any whose
|
|
133102
133625
|
* current step has an effective gezel owner. Call on service boot and
|
|
@@ -133143,9 +133666,9 @@ var TaskRunner = class {
|
|
|
133143
133666
|
/**
|
|
133144
133667
|
* One dispatch pass. Walks pending in FIFO order; dispatches any
|
|
133145
133668
|
* whose target provider has a free slot; skips items for tasks
|
|
133146
|
-
* that are no longer active.
|
|
133669
|
+
* that are no longer active.
|
|
133147
133670
|
*/
|
|
133148
|
-
async
|
|
133671
|
+
async tickOnce() {
|
|
133149
133672
|
await this.pruneActiveDispatches();
|
|
133150
133673
|
if (this.pending.length === 0) {
|
|
133151
133674
|
this.holdReason = void 0;
|
|
@@ -133157,6 +133680,7 @@ var TaskRunner = class {
|
|
|
133157
133680
|
return;
|
|
133158
133681
|
}
|
|
133159
133682
|
const snapshot = this.pending.slice();
|
|
133683
|
+
const snapshotIds = new Set(snapshot.map((handoff) => handoff.id));
|
|
133160
133684
|
const keep = [];
|
|
133161
133685
|
const inTickDispatches = /* @__PURE__ */ new Map();
|
|
133162
133686
|
const nightShiftOn = this.isNightShiftActive();
|
|
@@ -133222,6 +133746,7 @@ var TaskRunner = class {
|
|
|
133222
133746
|
...handoff.fromGezelName ? { fromGezelName: handoff.fromGezelName } : {},
|
|
133223
133747
|
...handoff.fromGezelId ? { fromGezelId: handoff.fromGezelId } : {},
|
|
133224
133748
|
...handoff.kind ? { kind: handoff.kind } : {},
|
|
133749
|
+
...task.roleBasedNameOnlyMode !== void 0 ? { roleBasedNameOnlyMode: task.roleBasedNameOnlyMode } : {},
|
|
133225
133750
|
lane,
|
|
133226
133751
|
...isNight ? { ambient: true } : {},
|
|
133227
133752
|
...isNight ? { nightShift: true } : {},
|
|
@@ -133244,8 +133769,9 @@ var TaskRunner = class {
|
|
|
133244
133769
|
);
|
|
133245
133770
|
}
|
|
133246
133771
|
}
|
|
133772
|
+
const enqueuedDuringTick = this.pending.filter((handoff) => !snapshotIds.has(handoff.id));
|
|
133247
133773
|
this.pending.length = 0;
|
|
133248
|
-
this.pending.push(...keep);
|
|
133774
|
+
this.pending.push(...keep, ...enqueuedDuringTick);
|
|
133249
133775
|
this.holdReason = keep.some((handoff) => handoff.heldFor === "provider-busy") ? "provider-busy" : void 0;
|
|
133250
133776
|
}
|
|
133251
133777
|
async pruneActiveDispatches() {
|
|
@@ -133735,6 +134261,10 @@ Step "${step.name}" (\`${step.id}\`) was re-driven ${maxRedrives}\xD7 without pr
|
|
|
133735
134261
|
} catch {
|
|
133736
134262
|
}
|
|
133737
134263
|
const activeTasks = projectTasks.filter((t) => t.status === "active");
|
|
134264
|
+
if (projectTasks.length === 0) {
|
|
134265
|
+
trace("skip \u2014 project has no tasks to advance");
|
|
134266
|
+
return;
|
|
134267
|
+
}
|
|
133738
134268
|
if (projectTasks.length > 0 && activeTasks.length === 0) {
|
|
133739
134269
|
if (projectTasks.some((t) => t.status === "draft")) {
|
|
133740
134270
|
trace("skip \u2014 only draft task(s) await activation; not nudging or stabilizing");
|
|
@@ -137476,7 +138006,7 @@ Address these, then the gate re-checks automatically.`,
|
|
|
137476
138006
|
try {
|
|
137477
138007
|
const existing = await tasks.listChildren(task.ref).catch(() => []);
|
|
137478
138008
|
if (existing.length === 0) {
|
|
137479
|
-
const raw = await store.readProjectWorkspaceFile(projectId, spawn14.overFile).catch(() => null);
|
|
138009
|
+
const raw = await (spawn14.overArtifact ? store.readProjectArtifact(projectId, spawn14.overFile) : store.readProjectWorkspaceFile(projectId, spawn14.overFile)).catch(() => null);
|
|
137480
138010
|
const items = raw ? extractSpawnItems(raw, spawn14.itemsPath) : [];
|
|
137481
138011
|
if (items.length === 0) {
|
|
137482
138012
|
log188.warn(
|
|
@@ -137505,7 +138035,7 @@ Address these, then the gate re-checks automatically.`,
|
|
|
137505
138035
|
|
|
137506
138036
|
${kids.map((k) => `- ${k.ref}: ${k.title}`).join("\n")}
|
|
137507
138037
|
`;
|
|
137508
|
-
await store.writeProjectWorkspaceFile(projectId, advanceFile, manifest).catch((err) => log188.warn(`[fanout] ${task.ref}: could not write ${advanceFile}:`, err));
|
|
138038
|
+
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));
|
|
137509
138039
|
}
|
|
137510
138040
|
const nextStep = newStep.advanceWhen?.goto ?? newStep.next;
|
|
137511
138041
|
if (nextStep) {
|