@onepointfour-packs/flaredeck-agent 0.2.171 → 0.2.172

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/serve.js CHANGED
@@ -43,6 +43,8 @@ import { dirname, join } from 'node:path';
43
43
  import { configDir, loadGitHub, saveConfig, slug } from './config.js';
44
44
  import { boardArg, onMyBoards, outstandingCards } from './boards.js';
45
45
  import { browserTools, ensureBrowser } from './browser.js';
46
+ import { AGY_HELPERS_BRIEF, HELPERS_BRIEF, helperTools } from './helpers.js';
47
+ import { jamEvidence as jamEvidenceFor, loadJam as loadJamTokens } from './jam.js';
46
48
  import { environmentTools } from './envtools.js';
47
49
  import { watchForDesperation } from './desperation.js';
48
50
  import { note, recallWorktree, rememberWorktree, resumeBrief } from './journal.js';
@@ -3428,6 +3430,21 @@ export async function serve(opts) {
3428
3430
  * the card waits for the reset, as it would for a spent plan.
3429
3431
  */
3430
3432
  let turnEngine = engine;
3433
+ /* Helpers (helpers.ts): on for this agent while they are measured. The result of one running
3434
+ in the background is typed into THIS turn; if the turn has ended by then, it starts the
3435
+ next one on the card, so it is never lost and never polled for. */
3436
+ const helpersOn = !isAssistant && (config.helpers === true || process.env['FLAREDECK_AGENT_HELPERS'] === '1');
3437
+ let thisRun = null;
3438
+ const deliverHelper = async (text) => {
3439
+ if (thisRun && liveRun === thisRun && await thisRun.steer(text).catch(() => false))
3440
+ return;
3441
+ if (!event.cardKey) {
3442
+ log('warn', `a helper finished after the turn ended, with no card to bring it back to: ${text.split('\n')[0]}`);
3443
+ return;
3444
+ }
3445
+ if (enqueue({ id: `helper-${Date.now()}`, event: 'assigned', cardKey: event.cardKey, cardCode: event.cardCode, ...(event.boardKey ? { boardKey: event.boardKey } : {}), line: `A helper you started on this card finished after your last turn ended:\n${text.slice(0, 6000)}` }))
3446
+ void drain();
3447
+ };
3431
3448
  if (engine.name === 'antigravity') {
3432
3449
  const spend = await geminiSpend?.status().catch(() => null);
3433
3450
  if (spend?.over) {
@@ -3458,6 +3475,29 @@ export async function serve(opts) {
3458
3475
  geminiOver = false;
3459
3476
  }
3460
3477
  }
3478
+ const helperSet = helpersOn && turnEngine.name === 'claude' ? helperTools({
3479
+ cwd: () => tree?.path ?? cwd,
3480
+ ...(claudePlan?.use === 'token' ? { claudeToken: claudePlan.token } : {}),
3481
+ // Its own browser, on the same environment the agent's points at.
3482
+ browser: () => browserTools({
3483
+ repo: config.repo,
3484
+ endpoints: () => env.endpoints,
3485
+ ...(web ? { defaultPart: () => web } : {}),
3486
+ sites: () => declaredSites,
3487
+ contract: () => env.contract,
3488
+ cwd,
3489
+ onNote: (t) => log('tool', t),
3490
+ }),
3491
+ jam: async (url) => {
3492
+ const tokens = loadJamTokens();
3493
+ if (!tokens)
3494
+ return null;
3495
+ const e = await jamEvidenceFor(url, tokens, (t) => log('tool', t));
3496
+ return e.ok ? e.text : null;
3497
+ },
3498
+ deliver: deliverHelper,
3499
+ log: (t) => log('tool', t),
3500
+ }) : null;
3461
3501
  const engineContext = {
3462
3502
  ...(leadGoal ? { goal: leadGoal } : {}),
3463
3503
  config: { ...config, repo: cwd, ...(isAssistant ? { assistantMode: true } : {}) },
@@ -3495,7 +3535,9 @@ export async function serve(opts) {
3495
3535
  ...(prepared?.model ? { model: prepared.model } : {}),
3496
3536
  ...(prepared?.size ? { size: prepared.size } : {}),
3497
3537
  ...(claudePlan?.use === 'token' ? { claudeToken: claudePlan.token } : {}),
3538
+ ...(helpersOn && turnEngine.name === 'antigravity' ? { subagents: true } : {}),
3498
3539
  tools: {
3540
+ ...(helperSet ? { helpers: helperSet } : {}),
3499
3541
  ...(job ? { git: { server: gitServer, toolNames: GIT_TOOL_NAMES } } : {}),
3500
3542
  // The project's file storage, when a person has set one up for these boards.
3501
3543
  ...(await turnFileTools(cwd, forACard, event.environment) ?? {}),
@@ -3545,8 +3587,9 @@ export async function serve(opts) {
3545
3587
  `the card, tell whoever owns the board that ${START_SCRIPT_NAME} does not survive parallel ` +
3546
3588
  `worktrees — it must take a free port AND pass that port to the parts that call it — and stop.`
3547
3589
  : '');
3548
- const run = turnEngine.run(brief, engineContext);
3590
+ const run = turnEngine.run(brief + (helpersOn ? (turnEngine.name === 'antigravity' ? AGY_HELPERS_BRIEF : HELPERS_BRIEF) : ''), engineContext);
3549
3591
  liveRun = run;
3592
+ thisRun = run;
3550
3593
  if (isAssistant)
3551
3594
  liveFeed?.start(String(event.message ?? event.line ?? '').split('\n').filter(Boolean).pop() ?? '');
3552
3595
  // Connected MCP servers' tokens, kept current for as long as the session runs. FlareDeck hands