@chrryai/waffles 2.4.41 → 2.4.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,6 +3,9 @@
3
3
  var dotenv = require('dotenv');
4
4
  var test = require('@playwright/test');
5
5
  var faker = require('@faker-js/faker');
6
+ var child_process = require('child_process');
7
+ var crypto = require('crypto');
8
+ var effect = require('effect');
6
9
 
7
10
  function _interopNamespace(e) {
8
11
  if (e && e.__esModule) return e;
@@ -24,7 +27,12 @@ function _interopNamespace(e) {
24
27
 
25
28
  var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
26
29
 
27
- // src/index.ts
30
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
31
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
32
+ }) : x)(function(x) {
33
+ if (typeof require !== "undefined") return require.apply(this, arguments);
34
+ throw Error('Dynamic require of "' + x + '" is not supported');
35
+ });
28
36
  var APIClient = class {
29
37
  context = null;
30
38
  baseURL;
@@ -140,6 +148,703 @@ var scheduledJobFactory = {
140
148
  return Array.from({ length: count }, () => this.build(overrides));
141
149
  }
142
150
  };
151
+ var BRANCH_STORAGE_KEY = "chrry-branch-agents";
152
+ function getStorage() {
153
+ if (typeof globalThis === "undefined") return {};
154
+ try {
155
+ const raw = globalThis[BRANCH_STORAGE_KEY];
156
+ if (raw) return JSON.parse(raw);
157
+ } catch {
158
+ }
159
+ return {};
160
+ }
161
+ function setStorage(data) {
162
+ if (typeof globalThis !== "undefined") {
163
+ globalThis[BRANCH_STORAGE_KEY] = JSON.stringify(data);
164
+ }
165
+ }
166
+ function fileStoragePath() {
167
+ try {
168
+ const cwd = process.cwd();
169
+ return `${cwd}/.chrry/branch-agents.json`;
170
+ } catch {
171
+ return void 0;
172
+ }
173
+ }
174
+ function loadFileStorage() {
175
+ const path = fileStoragePath();
176
+ if (!path) return {};
177
+ try {
178
+ const fs = __require("fs");
179
+ if (fs.existsSync(path)) {
180
+ return JSON.parse(fs.readFileSync(path, "utf-8"));
181
+ }
182
+ } catch {
183
+ }
184
+ return {};
185
+ }
186
+ function saveFileStorage(data) {
187
+ const path = fileStoragePath();
188
+ if (!path) return;
189
+ try {
190
+ const fs = __require("fs");
191
+ const dir = path.replace("/branch-agents.json", "");
192
+ if (!fs.existsSync(dir)) {
193
+ fs.mkdirSync(dir, { recursive: true });
194
+ }
195
+ fs.writeFileSync(path, JSON.stringify(data, null, 2));
196
+ } catch {
197
+ }
198
+ }
199
+ function getAllWorkspaces() {
200
+ const mem = getStorage();
201
+ const file = loadFileStorage();
202
+ return { ...file, ...mem };
203
+ }
204
+ function setAllWorkspaces(data) {
205
+ setStorage(data);
206
+ saveFileStorage(data);
207
+ }
208
+ function getCurrentBranch() {
209
+ const envBranch = process.env.CHRRY_BRANCH || process.env.GIT_BRANCH || process.env.GITHUB_HEAD_REF || process.env.CF_PAGES_BRANCH;
210
+ if (envBranch) return envBranch;
211
+ try {
212
+ const branch = child_process.execSync("git branch --show-current", {
213
+ encoding: "utf-8",
214
+ stdio: ["pipe", "pipe", "ignore"]
215
+ }).trim();
216
+ if (branch) return branch;
217
+ } catch {
218
+ }
219
+ try {
220
+ const desc = child_process.execSync("git describe --all --contains HEAD", {
221
+ encoding: "utf-8",
222
+ stdio: ["pipe", "pipe", "ignore"]
223
+ }).trim();
224
+ if (desc) return desc.replace(/^heads\//, "");
225
+ } catch {
226
+ }
227
+ return void 0;
228
+ }
229
+ function parseBranchName(fullBranch) {
230
+ const parts = fullBranch.split("/");
231
+ if (parts.length >= 2) {
232
+ return {
233
+ namespace: parts.slice(0, -1).join("/"),
234
+ branchName: parts[parts.length - 1]
235
+ };
236
+ }
237
+ return {
238
+ namespace: "default",
239
+ branchName: fullBranch
240
+ };
241
+ }
242
+ function generateAgentId(namespace, branchName) {
243
+ return `agent-${namespace}-${branchName}-${crypto.randomUUID().slice(0, 8)}`;
244
+ }
245
+ function createBranchWorkspace(fullBranchName, overrides) {
246
+ const { namespace, branchName } = parseBranchName(fullBranchName);
247
+ const now = (/* @__PURE__ */ new Date()).toISOString();
248
+ return {
249
+ id: crypto.randomUUID(),
250
+ namespace,
251
+ branchName,
252
+ fullBranchName,
253
+ agentId: overrides?.agentId || generateAgentId(namespace, branchName),
254
+ systemPrompt: overrides?.systemPrompt || defaultSystemPrompt(namespace, branchName),
255
+ instructions: overrides?.instructions || [],
256
+ memories: overrides?.memories || [],
257
+ characterProfile: overrides?.characterProfile,
258
+ evolutionScore: overrides?.evolutionScore ?? 0,
259
+ lastCommitSha: overrides?.lastCommitSha,
260
+ metadata: overrides?.metadata || {
261
+ createdBy: "branch-agent-system",
262
+ version: "1.0"
263
+ },
264
+ createdOn: overrides?.createdOn || now,
265
+ updatedOn: now
266
+ };
267
+ }
268
+ function defaultSystemPrompt(namespace, branchName) {
269
+ return `You are the AI agent for the branch "${namespace}/${branchName}".
270
+ Your knowledge, memories, and behavior are isolated to this branch.
271
+ When switching branches, save your current context and load the new one.
272
+ Collaborate with other branch agents via @namespace/branch mentions.`;
273
+ }
274
+ function loadBranchWorkspace(fullBranchName) {
275
+ const workspaces = getAllWorkspaces();
276
+ return workspaces[fullBranchName];
277
+ }
278
+ function saveBranchWorkspace(workspace) {
279
+ const workspaces = getAllWorkspaces();
280
+ workspace.updatedOn = (/* @__PURE__ */ new Date()).toISOString();
281
+ workspaces[workspace.fullBranchName] = workspace;
282
+ setAllWorkspaces(workspaces);
283
+ return workspace;
284
+ }
285
+ function getOrCreateBranchWorkspace(fullBranchName) {
286
+ const existing = loadBranchWorkspace(fullBranchName);
287
+ if (existing) return existing;
288
+ const created = createBranchWorkspace(fullBranchName);
289
+ return saveBranchWorkspace(created);
290
+ }
291
+ function switchBranchContext(newBranch, previousBranch) {
292
+ const { namespace, branchName } = parseBranchName(newBranch);
293
+ if (previousBranch) {
294
+ const prevWorkspace = loadBranchWorkspace(previousBranch);
295
+ if (prevWorkspace) {
296
+ saveBranchWorkspace(prevWorkspace);
297
+ }
298
+ }
299
+ const workspace = getOrCreateBranchWorkspace(newBranch);
300
+ return {
301
+ currentBranch: newBranch,
302
+ namespace,
303
+ branchName,
304
+ workspace,
305
+ previousBranch
306
+ };
307
+ }
308
+ function autoDetectAndSwitch(previousBranch) {
309
+ const current = getCurrentBranch();
310
+ if (!current) return void 0;
311
+ if (current === previousBranch) {
312
+ return {
313
+ currentBranch: current,
314
+ ...parseBranchName(current),
315
+ workspace: loadBranchWorkspace(current),
316
+ previousBranch
317
+ };
318
+ }
319
+ return switchBranchContext(current, previousBranch);
320
+ }
321
+ function deleteBranchWorkspace(fullBranchName) {
322
+ const workspaces = getAllWorkspaces();
323
+ if (!workspaces[fullBranchName]) return false;
324
+ delete workspaces[fullBranchName];
325
+ setAllWorkspaces(workspaces);
326
+ return true;
327
+ }
328
+ function recordMutation(fullBranchName, mutation) {
329
+ const workspace = loadBranchWorkspace(fullBranchName);
330
+ if (!workspace) return void 0;
331
+ const mutations = workspace.metadata.mutations || [];
332
+ mutations.push({
333
+ ...mutation,
334
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
335
+ });
336
+ const successCount = mutations.filter((m) => m.success).length;
337
+ workspace.evolutionScore = mutations.length > 0 ? successCount / mutations.length : 0;
338
+ workspace.metadata.mutations = mutations.slice(-100);
339
+ return saveBranchWorkspace(workspace);
340
+ }
341
+ function getCurrentBranchSafe() {
342
+ return effect.Effect.sync(() => getCurrentBranch()).pipe(
343
+ effect.Effect.catchAll((e) => effect.Effect.succeed(void 0))
344
+ );
345
+ }
346
+ function switchBranchContextSafe(newBranch, previousBranch) {
347
+ return effect.Effect.sync(() => switchBranchContext(newBranch, previousBranch)).pipe(
348
+ effect.Effect.catchAll((e) => effect.Effect.fail(String(e)))
349
+ );
350
+ }
351
+ function autoDetectAndSwitchSafe(previousBranch) {
352
+ return effect.Effect.sync(() => autoDetectAndSwitch(previousBranch)).pipe(
353
+ effect.Effect.catchAll((e) => effect.Effect.fail(String(e)))
354
+ );
355
+ }
356
+
357
+ // src/agent/chopstickExpert.ts
358
+ var modelPricing = {
359
+ "deepseek/deepseek-v3.2": {
360
+ input: 0.28,
361
+ output: 0.4,
362
+ tools: true,
363
+ analyze: false
364
+ },
365
+ "deepseek/deepseek-chat": {
366
+ input: 0.15,
367
+ output: 0.45,
368
+ tools: true,
369
+ analyze: false
370
+ },
371
+ "anthropic/claude-sonnet-4-6": {
372
+ input: 3,
373
+ output: 15,
374
+ tools: true,
375
+ analyze: true
376
+ },
377
+ "google/gemini-3.1-pro-preview": {
378
+ input: 0.35,
379
+ output: 1.05,
380
+ tools: true,
381
+ analyze: true
382
+ },
383
+ "deepseek/deepseek-v3.2-thinking": {
384
+ input: 0.28,
385
+ output: 0.4,
386
+ tools: true,
387
+ analyze: false
388
+ },
389
+ "qwen/qwen3.6-plus": { input: 0.3, output: 0.8, tools: true, analyze: true },
390
+ "minimax/minimax-m2.5": {
391
+ input: 0.3,
392
+ output: 1.1,
393
+ tools: true,
394
+ analyze: false
395
+ },
396
+ "minimax/minimax-m2.7": {
397
+ input: 0.3,
398
+ output: 1.2,
399
+ tools: true,
400
+ analyze: false
401
+ },
402
+ "x-ai/grok-4.1-fast": { input: 0.5, output: 2, tools: true, analyze: true },
403
+ "perplexity/sonar-pro": {
404
+ input: 2,
405
+ output: 8,
406
+ tools: false,
407
+ analyze: false
408
+ },
409
+ "openrouter/free": { input: 0, output: 0, tools: false, analyze: false },
410
+ "openai/gpt-oss-120b:free": {
411
+ input: 0,
412
+ output: 0.073,
413
+ tools: false,
414
+ analyze: true
415
+ },
416
+ "nvidia/nemotron-3-super-120b-a12b:free": {
417
+ input: 0,
418
+ output: 0,
419
+ tools: true,
420
+ analyze: false
421
+ },
422
+ "gpt-4o": { input: 2.5, output: 10, tools: true, analyze: true },
423
+ "gpt-4o-mini": { input: 0.15, output: 0.6, tools: true, analyze: true },
424
+ "openai/gpt-5.4": { input: 2.5, output: 15, tools: true, analyze: true }
425
+ };
426
+ var presets = {
427
+ minimal: {
428
+ join: {
429
+ memories: { user: 1, app: 1, dna: 0, thread: 1 },
430
+ instructions: { user: 1, app: 1, dna: 0, thread: 1 },
431
+ characterProfile: { user: 0, app: 0, dna: 0, thread: 0 },
432
+ placeholders: { user: 1, app: 1, dna: 0, thread: 1 }
433
+ },
434
+ depth: 0,
435
+ model: {
436
+ modelId: "nvidia/nemotron-3-super-120b-a12b:free",
437
+ inputPrice: 0,
438
+ outputPrice: 0,
439
+ hasTools: true,
440
+ canAnalyze: false,
441
+ reason: "Free model, minimal context"
442
+ },
443
+ reasoning: ["Minimal preset"]
444
+ },
445
+ balanced: {
446
+ join: {
447
+ memories: { user: 3, app: 2, dna: 1, thread: 3 },
448
+ instructions: { user: 2, app: 2, dna: 1, thread: 2 },
449
+ characterProfile: { user: 1, app: 1, dna: 0, thread: 1 },
450
+ placeholders: { user: 2, app: 2, dna: 1, thread: 2 }
451
+ },
452
+ depth: 1,
453
+ model: {
454
+ modelId: "deepseek/deepseek-chat",
455
+ inputPrice: 0.15,
456
+ outputPrice: 0.45,
457
+ hasTools: true,
458
+ canAnalyze: false,
459
+ reason: "Balanced cost/performance"
460
+ },
461
+ reasoning: ["Balanced preset"]
462
+ },
463
+ rich: {
464
+ join: {
465
+ memories: { user: 8, app: 5, dna: 3, thread: 6 },
466
+ instructions: { user: 5, app: 4, dna: 2, thread: 4 },
467
+ characterProfile: { user: 2, app: 2, dna: 1, thread: 2 },
468
+ placeholders: { user: 3, app: 3, dna: 2, thread: 3 }
469
+ },
470
+ depth: 2,
471
+ model: {
472
+ modelId: "deepseek/deepseek-v3.2",
473
+ inputPrice: 0.28,
474
+ outputPrice: 0.4,
475
+ hasTools: true,
476
+ canAnalyze: false,
477
+ reason: "Rich context"
478
+ },
479
+ reasoning: ["Rich preset"]
480
+ },
481
+ /** Admin/Sato mode - maximum user context */
482
+ admin: {
483
+ join: {
484
+ memories: { user: 15, app: 5, dna: 3, thread: 8 },
485
+ instructions: { user: 10, app: 4, dna: 2, thread: 5 },
486
+ characterProfile: { user: 3, app: 2, dna: 1, thread: 2 },
487
+ placeholders: { user: 5, app: 3, dna: 2, thread: 4 }
488
+ },
489
+ depth: 2,
490
+ model: {
491
+ modelId: "anthropic/claude-sonnet-4-6",
492
+ inputPrice: 3,
493
+ outputPrice: 15,
494
+ hasTools: true,
495
+ canAnalyze: true,
496
+ reason: "Admin mode: maximum context for Sato reports"
497
+ },
498
+ reasoning: ["Admin preset: Sato mode activated"]
499
+ },
500
+ kanban: {
501
+ join: {
502
+ memories: { user: 4, app: 6, dna: 2, thread: 3 },
503
+ instructions: { user: 3, app: 6, dna: 1, thread: 3 },
504
+ characterProfile: { user: 1, app: 2, dna: 1, thread: 1 },
505
+ placeholders: { user: 2, app: 4, dna: 1, thread: 2 }
506
+ },
507
+ depth: 1,
508
+ model: {
509
+ modelId: "deepseek/deepseek-chat",
510
+ inputPrice: 0.15,
511
+ outputPrice: 0.45,
512
+ hasTools: true,
513
+ canAnalyze: false,
514
+ reason: "Kanban needs tools"
515
+ },
516
+ reasoning: ["Kanban preset"]
517
+ },
518
+ tribe: {
519
+ join: {
520
+ memories: { user: 5, app: 3, dna: 2, thread: 8 },
521
+ instructions: { user: 4, app: 3, dna: 1, thread: 6 },
522
+ characterProfile: { user: 2, app: 2, dna: 1, thread: 2 },
523
+ placeholders: { user: 3, app: 3, dna: 1, thread: 4 }
524
+ },
525
+ depth: 2,
526
+ model: {
527
+ modelId: "deepseek/deepseek-v3.2",
528
+ inputPrice: 0.28,
529
+ outputPrice: 0.4,
530
+ hasTools: true,
531
+ canAnalyze: false,
532
+ reason: "Tribe needs thread context"
533
+ },
534
+ reasoning: ["Tribe preset"]
535
+ },
536
+ retro: {
537
+ join: {
538
+ memories: { user: 8, app: 2, dna: 1, thread: 5 },
539
+ instructions: { user: 6, app: 2, dna: 1, thread: 4 },
540
+ characterProfile: { user: 3, app: 1, dna: 0, thread: 2 },
541
+ placeholders: { user: 4, app: 2, dna: 1, thread: 3 }
542
+ },
543
+ depth: 1,
544
+ model: {
545
+ modelId: "anthropic/claude-sonnet-4-6",
546
+ inputPrice: 3,
547
+ outputPrice: 15,
548
+ hasTools: true,
549
+ canAnalyze: true,
550
+ reason: "Retro benefits from quality"
551
+ },
552
+ reasoning: ["Retro preset"]
553
+ },
554
+ background: {
555
+ join: {
556
+ memories: { user: 8, app: 5, dna: 3, thread: 6 },
557
+ instructions: { user: 5, app: 4, dna: 2, thread: 4 },
558
+ characterProfile: { user: 2, app: 2, dna: 1, thread: 2 },
559
+ placeholders: { user: 3, app: 3, dna: 2, thread: 3 }
560
+ },
561
+ depth: 2,
562
+ model: {
563
+ modelId: "deepseek/deepseek-v3.2",
564
+ inputPrice: 0.28,
565
+ outputPrice: 0.4,
566
+ hasTools: true,
567
+ canAnalyze: false,
568
+ reason: "Background job: more context"
569
+ },
570
+ reasoning: ["Background preset"]
571
+ },
572
+ free: {
573
+ join: {
574
+ memories: { user: 2, app: 1, dna: 0, thread: 2 },
575
+ instructions: { user: 1, app: 1, dna: 0, thread: 1 },
576
+ characterProfile: { user: 0, app: 0, dna: 0, thread: 0 },
577
+ placeholders: { user: 1, app: 1, dna: 0, thread: 1 }
578
+ },
579
+ depth: 0,
580
+ model: {
581
+ modelId: "nvidia/nemotron-3-super-120b-a12b:free",
582
+ inputPrice: 0,
583
+ outputPrice: 0,
584
+ hasTools: true,
585
+ canAnalyze: false,
586
+ reason: "Zero cost"
587
+ },
588
+ reasoning: ["Free preset"]
589
+ }
590
+ };
591
+ function swapModel(modelId, preferFree) {
592
+ return { modelId, swapped: false };
593
+ }
594
+ function optimizeChopStick(ctx) {
595
+ const reasoning = [];
596
+ let base = presets.balanced;
597
+ if (ctx.isAdmin || ctx.isSatoMode) {
598
+ base = presets.admin;
599
+ reasoning.push("Admin/Sato mode: maximum user context");
600
+ } else if (ctx.isBackgroundJob) {
601
+ base = presets.background;
602
+ } else if (ctx.hasRetro) {
603
+ base = presets.retro;
604
+ } else if (ctx.appType === "kanban" || ctx.hasKanban) {
605
+ base = presets.kanban;
606
+ } else if (ctx.appType === "tribe") {
607
+ base = presets.tribe;
608
+ }
609
+ if ((ctx.creditsLeft ?? 10) < 3) {
610
+ base = presets.free;
611
+ reasoning.push(`Low credits: ${ctx.creditsLeft}`);
612
+ }
613
+ let depth = base.depth;
614
+ if ((ctx.messageCount ?? 0) > 50) {
615
+ depth = 2;
616
+ reasoning.push(`Deep thread: ${ctx.messageCount}`);
617
+ }
618
+ const join = { ...base.join };
619
+ if (ctx.hasDNA) {
620
+ join.memories.dna = Math.min(5, join.memories.dna + 2);
621
+ join.instructions.dna = Math.min(3, join.instructions.dna + 1);
622
+ reasoning.push("DNA boost");
623
+ }
624
+ if (ctx.hasTimer) {
625
+ join.memories.app = Math.min(10, join.memories.app + 1);
626
+ reasoning.push("Timer boost");
627
+ }
628
+ let modelId = ctx.defaultModelId || base.model.modelId;
629
+ if (ctx.needsTools && !modelPricing[modelId]?.tools) {
630
+ modelId = "deepseek/deepseek-chat";
631
+ reasoning.push("Tool requirement");
632
+ }
633
+ if (ctx.needsAnalysis && !modelPricing[modelId]?.analyze) {
634
+ modelId = "anthropic/claude-sonnet-4-6";
635
+ reasoning.push("Analysis requirement");
636
+ }
637
+ if (ctx.allowsModelSwap) {
638
+ swapModel(
639
+ modelId,
640
+ ctx.preferFree || (ctx.creditsLeft ?? 10) < 5
641
+ );
642
+ }
643
+ const pricing = modelPricing[modelId];
644
+ return {
645
+ join,
646
+ depth,
647
+ model: {
648
+ modelId,
649
+ inputPrice: pricing?.input ?? 1,
650
+ outputPrice: pricing?.output ?? 2,
651
+ hasTools: pricing?.tools ?? true,
652
+ canAnalyze: pricing?.analyze ?? false,
653
+ reason: reasoning.join(", ") || "Default"
654
+ },
655
+ reasoning: [...base.reasoning, ...reasoning]
656
+ };
657
+ }
658
+ function buildStoreKnowledgeBase(ctx) {
659
+ const reasoning = [];
660
+ const mainConfig = optimizeChopStick({
661
+ appType: ctx.appType,
662
+ hasDNA: ctx.hasDNA,
663
+ hasTimer: ctx.hasTimer,
664
+ hasKanban: ctx.hasKanban,
665
+ messageCount: ctx.messageCount,
666
+ isBackgroundJob: ctx.isBackgroundJob
667
+ });
668
+ const contextConfig = optimizeChopStick({
669
+ appType: "default",
670
+ isBackgroundJob: true
671
+ // lighter
672
+ });
673
+ const apps = ctx.storeAppIds.map((id, index) => {
674
+ const isMain = id === ctx.mainAppId;
675
+ const config2 = isMain ? mainConfig : contextConfig;
676
+ const limits = isMain ? { memories: 15, instructions: 10, messages: 10 } : { memories: 5, instructions: 3, messages: 3 };
677
+ return {
678
+ app: {
679
+ id,
680
+ name: `App-${index + 1}`,
681
+ // Caller doldurur
682
+ slug: `app-${id.slice(0, 6)}`
683
+ },
684
+ context: {
685
+ join: config2.join,
686
+ depth: config2.depth,
687
+ isMainApp: isMain
688
+ },
689
+ limits
690
+ };
691
+ });
692
+ const mainApp = apps.find((a) => a.app.id === ctx.mainAppId) || apps[0];
693
+ const contextApps = apps.filter((a) => a.app.id !== ctx.mainAppId);
694
+ const estimatedTokens = apps.reduce((sum, app) => {
695
+ const memTokens = app.limits.memories * 100;
696
+ const instTokens = app.limits.instructions * 200;
697
+ const msgTokens = app.limits.messages * 150;
698
+ return sum + memTokens + instTokens + msgTokens;
699
+ }, 0);
700
+ if (ctx.hasDNA) reasoning.push("DNA context included");
701
+ if (ctx.hasTimer) reasoning.push("Timer context included");
702
+ if (ctx.hasKanban) reasoning.push("Kanban context included");
703
+ return {
704
+ apps,
705
+ mainApp,
706
+ contextApps,
707
+ estimatedTokens,
708
+ meta: {
709
+ totalApps: apps.length,
710
+ reasoning,
711
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
712
+ }
713
+ };
714
+ }
715
+ function getPreset(name) {
716
+ return presets[name] ?? presets.balanced;
717
+ }
718
+ function getJoinWeights(ctx) {
719
+ return optimizeChopStick(ctx).join;
720
+ }
721
+ function buildRamenPayload(base, ctx) {
722
+ const opt = optimizeChopStick(ctx);
723
+ const estimatedCost = 2 * (opt.model.inputPrice + opt.model.outputPrice);
724
+ return {
725
+ ...base,
726
+ join: opt.join,
727
+ depth: opt.depth,
728
+ _meta: {
729
+ modelId: opt.model.modelId,
730
+ estimatedCost: Math.round(estimatedCost * 1e3) / 1e3,
731
+ reasoning: opt.reasoning
732
+ }
733
+ };
734
+ }
735
+
736
+ // src/agent/goldenRatio.ts
737
+ var FIBONACCI = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144];
738
+ var DEFAULT_TRIGGERS = [
739
+ {
740
+ feature: "memory",
741
+ homeApp: "hippo",
742
+ threadThreshold: 3,
743
+ messageThreshold: 2
744
+ },
745
+ {
746
+ feature: "kanban",
747
+ homeApp: "focus",
748
+ threadThreshold: 5,
749
+ messageThreshold: 3
750
+ },
751
+ {
752
+ feature: "characterProfile",
753
+ homeApp: "hippo",
754
+ threadThreshold: 5,
755
+ messageThreshold: 5
756
+ },
757
+ {
758
+ feature: "placeholders",
759
+ homeApp: "hippo",
760
+ threadThreshold: 8,
761
+ messageThreshold: 5
762
+ },
763
+ {
764
+ feature: "instructions",
765
+ homeApp: "sushi",
766
+ threadThreshold: 8,
767
+ messageThreshold: 8
768
+ },
769
+ {
770
+ feature: "vectorEmbed",
771
+ homeApp: "grape",
772
+ threadThreshold: 13,
773
+ messageThreshold: 8
774
+ }
775
+ ];
776
+ function getDefaultTriggers() {
777
+ return DEFAULT_TRIGGERS.map((t) => ({ ...t }));
778
+ }
779
+ function getUserGoldenRatioConfig(userConfig) {
780
+ const defaults = Object.fromEntries(
781
+ DEFAULT_TRIGGERS.map((t) => [
782
+ t.feature,
783
+ {
784
+ threadThreshold: t.threadThreshold,
785
+ messageThreshold: t.messageThreshold,
786
+ enabled: true
787
+ }
788
+ ])
789
+ );
790
+ if (!userConfig) return defaults;
791
+ for (const key of Object.keys(userConfig)) {
792
+ const cfg = userConfig[key];
793
+ if (!cfg) continue;
794
+ defaults[key] = {
795
+ threadThreshold: cfg.threadThreshold ?? defaults[key].threadThreshold,
796
+ messageThreshold: cfg.messageThreshold ?? defaults[key].messageThreshold,
797
+ enabled: cfg.enabled ?? true
798
+ };
799
+ }
800
+ return defaults;
801
+ }
802
+ function evaluateGoldenRatio(userThreadCount, threadMessageCount, lastTriggeredFeatures, userConfig) {
803
+ const config2 = getUserGoldenRatioConfig(userConfig);
804
+ const triggeredSet = new Set(lastTriggeredFeatures);
805
+ return DEFAULT_TRIGGERS.map((trigger) => {
806
+ const cfg = config2[trigger.feature];
807
+ const isTriggered = cfg.enabled && userThreadCount >= cfg.threadThreshold && threadMessageCount >= cfg.messageThreshold;
808
+ return {
809
+ feature: trigger.feature,
810
+ homeApp: trigger.homeApp,
811
+ triggered: isTriggered,
812
+ alreadyTriggered: triggeredSet.has(trigger.feature),
813
+ threadThreshold: cfg.threadThreshold,
814
+ messageThreshold: cfg.messageThreshold,
815
+ userThreadCount,
816
+ threadMessageCount
817
+ };
818
+ });
819
+ }
820
+ function getNewlyTriggeredFeatures(userThreadCount, threadMessageCount, lastTriggeredFeatures, userConfig) {
821
+ return evaluateGoldenRatio(
822
+ userThreadCount,
823
+ threadMessageCount,
824
+ lastTriggeredFeatures,
825
+ userConfig
826
+ ).filter((e) => e.triggered && !e.alreadyTriggered);
827
+ }
828
+ function getNextFibonacciThreshold(value) {
829
+ const next = FIBONACCI.find((f) => f > value);
830
+ return next ?? FIBONACCI[FIBONACCI.length - 1];
831
+ }
832
+ function formatFibonacciPreview(userThreadCount, threadMessageCount, userConfig) {
833
+ const config2 = getUserGoldenRatioConfig(userConfig);
834
+ return DEFAULT_TRIGGERS.map((trigger) => {
835
+ const cfg = config2[trigger.feature];
836
+ const ready = cfg.enabled && userThreadCount >= cfg.threadThreshold && threadMessageCount >= cfg.messageThreshold;
837
+ return {
838
+ feature: trigger.feature,
839
+ homeApp: trigger.homeApp,
840
+ progressThread: Math.min(1, userThreadCount / cfg.threadThreshold),
841
+ progressMessage: Math.min(1, threadMessageCount / cfg.messageThreshold),
842
+ ready,
843
+ nextThresholdThread: cfg.threadThreshold,
844
+ nextThresholdMessage: cfg.messageThreshold
845
+ };
846
+ });
847
+ }
143
848
 
144
849
  // src/index.ts
145
850
  dotenv__namespace.config();
@@ -253,6 +958,8 @@ var log = ({ page }) => {
253
958
  };
254
959
 
255
960
  exports.APIClient = APIClient;
961
+ exports.DEFAULT_TRIGGERS = DEFAULT_TRIGGERS;
962
+ exports.FIBONACCI = FIBONACCI;
256
963
  exports.TEST_GUEST_FINGERPRINTS = TEST_GUEST_FINGERPRINTS;
257
964
  exports.TEST_MEMBER_EMAILS = TEST_MEMBER_EMAILS;
258
965
  exports.TEST_MEMBER_FINGERPRINTS = TEST_MEMBER_FINGERPRINTS;
@@ -273,15 +980,42 @@ exports.VEX_TEST_PASSWORD = VEX_TEST_PASSWORD;
273
980
  exports.VEX_TEST_PASSWORD_2 = VEX_TEST_PASSWORD_2;
274
981
  exports.VEX_TEST_PASSWORD_3 = VEX_TEST_PASSWORD_3;
275
982
  exports.VEX_TEST_PASSWORD_4 = VEX_TEST_PASSWORD_4;
983
+ exports.autoDetectAndSwitch = autoDetectAndSwitch;
984
+ exports.autoDetectAndSwitchSafe = autoDetectAndSwitchSafe;
985
+ exports.buildRamenPayload = buildRamenPayload;
986
+ exports.buildStoreKnowledgeBase = buildStoreKnowledgeBase;
276
987
  exports.capitalizeFirstLetter = capitalizeFirstLetter;
988
+ exports.createBranchWorkspace = createBranchWorkspace;
989
+ exports.deleteBranchWorkspace = deleteBranchWorkspace;
990
+ exports.evaluateGoldenRatio = evaluateGoldenRatio;
991
+ exports.formatFibonacciPreview = formatFibonacciPreview;
992
+ exports.generateAgentId = generateAgentId;
993
+ exports.getCurrentBranch = getCurrentBranch;
994
+ exports.getCurrentBranchSafe = getCurrentBranchSafe;
995
+ exports.getDefaultTriggers = getDefaultTriggers;
996
+ exports.getJoinWeights = getJoinWeights;
277
997
  exports.getModelCredits = getModelCredits;
998
+ exports.getNewlyTriggeredFeatures = getNewlyTriggeredFeatures;
999
+ exports.getNextFibonacciThreshold = getNextFibonacciThreshold;
1000
+ exports.getOrCreateBranchWorkspace = getOrCreateBranchWorkspace;
1001
+ exports.getPreset = getPreset;
278
1002
  exports.getURL = getURL;
1003
+ exports.getUserGoldenRatioConfig = getUserGoldenRatioConfig;
279
1004
  exports.isCI = isCI;
1005
+ exports.loadBranchWorkspace = loadBranchWorkspace;
280
1006
  exports.log = log;
1007
+ exports.modelPricing = modelPricing;
1008
+ exports.optimizeChopStick = optimizeChopStick;
1009
+ exports.parseBranchName = parseBranchName;
1010
+ exports.presets = presets;
1011
+ exports.recordMutation = recordMutation;
1012
+ exports.saveBranchWorkspace = saveBranchWorkspace;
281
1013
  exports.scheduledJobFactory = scheduledJobFactory;
282
1014
  exports.simulateInputPaste = simulateInputPaste;
283
1015
  exports.simulatePaste = simulatePaste;
284
1016
  exports.storeApps = storeApps;
1017
+ exports.switchBranchContext = switchBranchContext;
1018
+ exports.switchBranchContextSafe = switchBranchContextSafe;
285
1019
  exports.wait = wait;
286
1020
  //# sourceMappingURL=index.js.map
287
1021
  //# sourceMappingURL=index.js.map