@onepointfour-packs/flaredeck-agent 0.2.171 → 0.2.173

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
@@ -40,9 +40,11 @@ import { updateSidecarSdk } from './updater-python.js';
40
40
  import { managedPython, usingManagedPython } from './engine-antigravity.js';
41
41
  import { appendFileSync, existsSync, mkdirSync, renameSync, statSync, writeFileSync } from 'node:fs';
42
42
  import { dirname, join } from 'node:path';
43
- import { configDir, loadGitHub, saveConfig, slug } from './config.js';
43
+ import { configDir, loadConfig, 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,22 @@ 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
+ // Read from the file each turn, so turning helpers on or off needs no restart.
3437
+ const helpersOn = !isAssistant && ((loadConfig(config.repo)?.helpers ?? config.helpers) === true || process.env['FLAREDECK_AGENT_HELPERS'] === '1');
3438
+ let thisRun = null;
3439
+ const deliverHelper = async (text) => {
3440
+ if (thisRun && liveRun === thisRun && await thisRun.steer(text).catch(() => false))
3441
+ return;
3442
+ if (!event.cardKey) {
3443
+ log('warn', `a helper finished after the turn ended, with no card to bring it back to: ${text.split('\n')[0]}`);
3444
+ return;
3445
+ }
3446
+ 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)}` }))
3447
+ void drain();
3448
+ };
3431
3449
  if (engine.name === 'antigravity') {
3432
3450
  const spend = await geminiSpend?.status().catch(() => null);
3433
3451
  if (spend?.over) {
@@ -3458,6 +3476,29 @@ export async function serve(opts) {
3458
3476
  geminiOver = false;
3459
3477
  }
3460
3478
  }
3479
+ const helperSet = helpersOn && turnEngine.name === 'claude' ? helperTools({
3480
+ cwd: () => tree?.path ?? cwd,
3481
+ ...(claudePlan?.use === 'token' ? { claudeToken: claudePlan.token } : {}),
3482
+ // Its own browser, on the same environment the agent's points at.
3483
+ browser: () => browserTools({
3484
+ repo: config.repo,
3485
+ endpoints: () => env.endpoints,
3486
+ ...(web ? { defaultPart: () => web } : {}),
3487
+ sites: () => declaredSites,
3488
+ contract: () => env.contract,
3489
+ cwd,
3490
+ onNote: (t) => log('tool', t),
3491
+ }),
3492
+ jam: async (url) => {
3493
+ const tokens = loadJamTokens();
3494
+ if (!tokens)
3495
+ return null;
3496
+ const e = await jamEvidenceFor(url, tokens, (t) => log('tool', t));
3497
+ return e.ok ? e.text : null;
3498
+ },
3499
+ deliver: deliverHelper,
3500
+ log: (t) => log('tool', t),
3501
+ }) : null;
3461
3502
  const engineContext = {
3462
3503
  ...(leadGoal ? { goal: leadGoal } : {}),
3463
3504
  config: { ...config, repo: cwd, ...(isAssistant ? { assistantMode: true } : {}) },
@@ -3495,7 +3536,9 @@ export async function serve(opts) {
3495
3536
  ...(prepared?.model ? { model: prepared.model } : {}),
3496
3537
  ...(prepared?.size ? { size: prepared.size } : {}),
3497
3538
  ...(claudePlan?.use === 'token' ? { claudeToken: claudePlan.token } : {}),
3539
+ ...(helpersOn && turnEngine.name === 'antigravity' ? { subagents: true } : {}),
3498
3540
  tools: {
3541
+ ...(helperSet ? { helpers: helperSet } : {}),
3499
3542
  ...(job ? { git: { server: gitServer, toolNames: GIT_TOOL_NAMES } } : {}),
3500
3543
  // The project's file storage, when a person has set one up for these boards.
3501
3544
  ...(await turnFileTools(cwd, forACard, event.environment) ?? {}),
@@ -3545,8 +3588,9 @@ export async function serve(opts) {
3545
3588
  `the card, tell whoever owns the board that ${START_SCRIPT_NAME} does not survive parallel ` +
3546
3589
  `worktrees — it must take a free port AND pass that port to the parts that call it — and stop.`
3547
3590
  : '');
3548
- const run = turnEngine.run(brief, engineContext);
3591
+ const run = turnEngine.run(brief + (helpersOn ? (turnEngine.name === 'antigravity' ? AGY_HELPERS_BRIEF : HELPERS_BRIEF) : ''), engineContext);
3549
3592
  liveRun = run;
3593
+ thisRun = run;
3550
3594
  if (isAssistant)
3551
3595
  liveFeed?.start(String(event.message ?? event.line ?? '').split('\n').filter(Boolean).pop() ?? '');
3552
3596
  // Connected MCP servers' tokens, kept current for as long as the session runs. FlareDeck hands