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