@agent-link/agent 0.1.272 → 0.1.273
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/action-draft-session.d.ts +7 -0
- package/dist/action-draft-session.js +11 -0
- package/dist/action-draft-session.js.map +1 -0
- package/dist/action-drafts.d.ts +36 -0
- package/dist/action-drafts.js +74 -0
- package/dist/action-drafts.js.map +1 -0
- package/dist/action.d.ts +1 -0
- package/dist/action.js.map +1 -1
- package/dist/braincore-cli.d.ts +2 -0
- package/dist/braincore-cli.js +57 -0
- package/dist/braincore-cli.js.map +1 -0
- package/dist/claude.d.ts +3 -0
- package/dist/claude.js +22 -0
- package/dist/claude.js.map +1 -1
- package/dist/connection.d.ts +1 -0
- package/dist/connection.js +147 -4
- package/dist/connection.js.map +1 -1
- package/dist/recap.js +8 -47
- package/dist/recap.js.map +1 -1
- package/package.json +1 -1
package/dist/connection.js
CHANGED
|
@@ -11,6 +11,8 @@ import { handleCreateLoop, handleUpdateLoop, handleDeleteLoop, handleListLoops,
|
|
|
11
11
|
import { loadSessionMetadata, loadAllSessionMetadata, deleteSessionMetadata } from './session-metadata.js';
|
|
12
12
|
import { listRecaps, listRecapsWithStatus, getRecapDetail, runActionItemsCli } from './recap.js';
|
|
13
13
|
import { listActions, getActionDetail } from './action.js';
|
|
14
|
+
import { bindActionDraftSession, commitActionDraft, createActionDraft, discardActionDraft, getActionDraft, listActionDrafts, validateActionDraftId, } from './action-drafts.js';
|
|
15
|
+
import { resolveNewActionDraftSessionDir } from './action-draft-session.js';
|
|
14
16
|
import { listIcms } from './playground-icm.js';
|
|
15
17
|
import { listBriefings, getBriefingDetail } from './briefing.js';
|
|
16
18
|
import { listDevops, getDevopsDetail } from './devops.js';
|
|
@@ -136,7 +138,7 @@ export function connect(config) {
|
|
|
136
138
|
}
|
|
137
139
|
catch { /* ignore */ }
|
|
138
140
|
}
|
|
139
|
-
unsubscribeSessionStarted = addOnSessionStarted(
|
|
141
|
+
unsubscribeSessionStarted = addOnSessionStarted(checkPendingSessionLinks);
|
|
140
142
|
// Initialize the tunnel handler for port proxy
|
|
141
143
|
tunnelHandler = createTunnelHandler(send);
|
|
142
144
|
// Initialize the terminal manager for web terminal
|
|
@@ -514,10 +516,12 @@ function scheduleReconnect(config) {
|
|
|
514
516
|
}, delay);
|
|
515
517
|
}
|
|
516
518
|
const BRAIN_DATA_DIR = getBrainDataDir();
|
|
519
|
+
const FOLLOW_THROUGH_SESSION_DIR = path.join(BRAIN_DATA_DIR, 'reports', 'follow-through');
|
|
517
520
|
const BRAIN_SERVER = 'http://localhost:8001';
|
|
518
521
|
// Pending action item IDs: conversationId → actionItemId
|
|
519
522
|
// Used to link a chat's Claude session to an action item for CLI start
|
|
520
523
|
const pendingActionItems = new Map();
|
|
524
|
+
const pendingActionDrafts = new Map();
|
|
521
525
|
function handleServerMessage(msg) {
|
|
522
526
|
console.log(`[AgentLink] ← ${msg.type}`);
|
|
523
527
|
switch (msg.type) {
|
|
@@ -556,9 +560,21 @@ function handleServerMessage(msg) {
|
|
|
556
560
|
const projectName = msg.projectName;
|
|
557
561
|
const icmId = msg.icmId;
|
|
558
562
|
const actionItemId = msg.actionItemId;
|
|
563
|
+
const actionDraftId = msg.actionDraftId;
|
|
559
564
|
const explicitWorkDir = msg.workDir;
|
|
565
|
+
if (actionDraftId) {
|
|
566
|
+
try {
|
|
567
|
+
validateActionDraftId(actionDraftId);
|
|
568
|
+
}
|
|
569
|
+
catch (err) {
|
|
570
|
+
send({ type: 'error', message: String(err), conversationId: chatConvId });
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
560
574
|
// Backward compat: brainMode: true without providerId → "brain"
|
|
561
|
-
const effectiveProviderId =
|
|
575
|
+
const effectiveProviderId = actionDraftId
|
|
576
|
+
? 'brain'
|
|
577
|
+
: (msgProviderId || (isBrainMode ? 'brain' : undefined));
|
|
562
578
|
console.log(`[AgentLink] chat: conversationId=${chatConvId}, existingConv.planMode=${existingConv?.planMode}, providerId=${effectiveProviderId || '(default)'}`);
|
|
563
579
|
const chatOptions = {
|
|
564
580
|
resumeSessionId: msg.resumeSessionId,
|
|
@@ -587,13 +603,19 @@ function handleServerMessage(msg) {
|
|
|
587
603
|
if (icmId) {
|
|
588
604
|
chatOptions.icmId = String(icmId);
|
|
589
605
|
}
|
|
606
|
+
if (actionDraftId) {
|
|
607
|
+
chatOptions.actionDraftId = actionDraftId;
|
|
608
|
+
}
|
|
590
609
|
// Determine the working directory for this chat. For resumed sessions
|
|
591
610
|
// the JSONL may live in a different cwd than the agent's current workDir
|
|
592
611
|
// (e.g. action-item sessions spawned by BrainCore live in $HOME). When
|
|
593
612
|
// no existingConv is found (agent restarted, or cache-hit skipped
|
|
594
613
|
// resume_conversation), probe the filesystem to find the right directory.
|
|
595
|
-
|
|
596
|
-
|
|
614
|
+
const newActionDraftSessionDir = resolveNewActionDraftSessionDir(BRAIN_DATA_DIR, actionDraftId, explicitWorkDir, chatOptions.resumeSessionId, existingConv);
|
|
615
|
+
let chatDir = newActionDraftSessionDir ?? explicitWorkDir ?? existingConv?.workDir;
|
|
616
|
+
if (newActionDraftSessionDir)
|
|
617
|
+
mkdirSync(FOLLOW_THROUGH_SESSION_DIR, { recursive: true });
|
|
618
|
+
if (!chatDir && (recapId || briefingDate || devopsEntityType || projectName || icmId || actionDraftId)) {
|
|
597
619
|
// Brain-mode session: try BRAIN_DATA_DIR first, then homedir fallback
|
|
598
620
|
const probeSessionId = chatOptions.resumeSessionId
|
|
599
621
|
|| existingConv?.claudeSessionId;
|
|
@@ -617,6 +639,9 @@ function handleServerMessage(msg) {
|
|
|
617
639
|
if (actionItemId && chatConvId) {
|
|
618
640
|
pendingActionItems.set(chatConvId, actionItemId);
|
|
619
641
|
}
|
|
642
|
+
if (actionDraftId && chatConvId) {
|
|
643
|
+
pendingActionDrafts.set(chatConvId, { draftId: actionDraftId, sessionCwd: chatDir });
|
|
644
|
+
}
|
|
620
645
|
// Auto-switch backend if chat message's providerId requires a different backend
|
|
621
646
|
if (effectiveProviderId) {
|
|
622
647
|
const requiredBt = getBackendTypeForProvider(effectiveProviderId);
|
|
@@ -1612,6 +1637,21 @@ function handleServerMessage(msg) {
|
|
|
1612
1637
|
case 'complete_action_item':
|
|
1613
1638
|
handleCompleteActionItem(msg);
|
|
1614
1639
|
break;
|
|
1640
|
+
case 'create_action_draft':
|
|
1641
|
+
handleCreateActionDraft(msg);
|
|
1642
|
+
break;
|
|
1643
|
+
case 'list_action_drafts':
|
|
1644
|
+
handleListActionDrafts(msg);
|
|
1645
|
+
break;
|
|
1646
|
+
case 'get_action_draft':
|
|
1647
|
+
handleGetActionDraft(msg);
|
|
1648
|
+
break;
|
|
1649
|
+
case 'commit_action_draft':
|
|
1650
|
+
handleCommitActionDraft(msg);
|
|
1651
|
+
break;
|
|
1652
|
+
case 'discard_action_draft':
|
|
1653
|
+
handleDiscardActionDraft(msg);
|
|
1654
|
+
break;
|
|
1615
1655
|
case 'list_briefings':
|
|
1616
1656
|
handleListBriefings();
|
|
1617
1657
|
break;
|
|
@@ -2381,6 +2421,78 @@ async function handleCompleteActionItem(msg) {
|
|
|
2381
2421
|
send({ type: 'action_item_completed', actionItemId: msg.actionItemId, error: String(err) });
|
|
2382
2422
|
}
|
|
2383
2423
|
}
|
|
2424
|
+
async function handleCreateActionDraft(msg) {
|
|
2425
|
+
try {
|
|
2426
|
+
const draft = await createActionDraft();
|
|
2427
|
+
send({ type: 'action_draft_created', requestId: msg.requestId, draft });
|
|
2428
|
+
}
|
|
2429
|
+
catch (err) {
|
|
2430
|
+
console.error('[AgentLink] createActionDraft failed:', err);
|
|
2431
|
+
send({
|
|
2432
|
+
type: 'action_draft_created',
|
|
2433
|
+
requestId: msg.requestId,
|
|
2434
|
+
draft: null,
|
|
2435
|
+
error: String(err),
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
async function handleListActionDrafts(msg) {
|
|
2440
|
+
try {
|
|
2441
|
+
const drafts = await listActionDrafts(msg.status);
|
|
2442
|
+
send({ type: 'action_drafts_list', drafts });
|
|
2443
|
+
}
|
|
2444
|
+
catch (err) {
|
|
2445
|
+
console.error('[AgentLink] listActionDrafts failed:', err);
|
|
2446
|
+
send({ type: 'action_drafts_list', drafts: [], error: String(err) });
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
async function handleGetActionDraft(msg) {
|
|
2450
|
+
try {
|
|
2451
|
+
const draft = await getActionDraft(msg.draftId);
|
|
2452
|
+
send({ type: 'action_draft', draftId: msg.draftId, draft });
|
|
2453
|
+
}
|
|
2454
|
+
catch (err) {
|
|
2455
|
+
console.error(`[AgentLink] getActionDraft failed for ${msg.draftId}:`, err);
|
|
2456
|
+
send({ type: 'action_draft', draftId: msg.draftId, draft: null, error: String(err) });
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
async function handleCommitActionDraft(msg) {
|
|
2460
|
+
try {
|
|
2461
|
+
const result = await commitActionDraft(msg.draftId, msg.expectedRevision);
|
|
2462
|
+
const actionItemId = String(result.action.action_item_id || result.draft.action_item_id || '');
|
|
2463
|
+
send({
|
|
2464
|
+
type: 'action_draft_committed',
|
|
2465
|
+
draftId: msg.draftId,
|
|
2466
|
+
actionItemId,
|
|
2467
|
+
draft: result.draft,
|
|
2468
|
+
action: result.action,
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
2471
|
+
catch (err) {
|
|
2472
|
+
console.error(`[AgentLink] commitActionDraft failed for ${msg.draftId}:`, err);
|
|
2473
|
+
send({
|
|
2474
|
+
type: 'action_draft_committed',
|
|
2475
|
+
draftId: msg.draftId,
|
|
2476
|
+
actionItemId: null,
|
|
2477
|
+
error: String(err),
|
|
2478
|
+
});
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
async function handleDiscardActionDraft(msg) {
|
|
2482
|
+
try {
|
|
2483
|
+
const draft = await discardActionDraft(msg.draftId);
|
|
2484
|
+
send({ type: 'action_draft_discarded', draftId: msg.draftId, draft });
|
|
2485
|
+
}
|
|
2486
|
+
catch (err) {
|
|
2487
|
+
console.error(`[AgentLink] discardActionDraft failed for ${msg.draftId}:`, err);
|
|
2488
|
+
send({
|
|
2489
|
+
type: 'action_draft_discarded',
|
|
2490
|
+
draftId: msg.draftId,
|
|
2491
|
+
draft: null,
|
|
2492
|
+
error: String(err),
|
|
2493
|
+
});
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2384
2496
|
/**
|
|
2385
2497
|
* Called when a recap chat session starts to check if it's linked to an action item.
|
|
2386
2498
|
* If so, calls CLI `start` to transition the action item to 'running' status.
|
|
@@ -2400,4 +2512,35 @@ export function checkPendingActionItem(conversationId, claudeSessionId) {
|
|
|
2400
2512
|
send({ type: 'action_item_started', actionItemId, sessionId: claudeSessionId, error: String(err) });
|
|
2401
2513
|
});
|
|
2402
2514
|
}
|
|
2515
|
+
function checkPendingActionDraft(conversationId, claudeSessionId) {
|
|
2516
|
+
const pending = pendingActionDrafts.get(conversationId);
|
|
2517
|
+
if (!pending)
|
|
2518
|
+
return;
|
|
2519
|
+
pendingActionDrafts.delete(conversationId);
|
|
2520
|
+
const bind = (attempt) => {
|
|
2521
|
+
console.log(`[AgentLink] Binding action draft ${pending.draftId} to session ${claudeSessionId} (attempt ${attempt + 1})`);
|
|
2522
|
+
bindActionDraftSession(pending.draftId, claudeSessionId, pending.sessionCwd)
|
|
2523
|
+
.then((draft) => {
|
|
2524
|
+
send({ type: 'action_draft', draftId: pending.draftId, draft });
|
|
2525
|
+
})
|
|
2526
|
+
.catch((err) => {
|
|
2527
|
+
if (attempt < 2) {
|
|
2528
|
+
setTimeout(() => bind(attempt + 1), 500 * (attempt + 1));
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
console.error('[AgentLink] bind action draft session failed:', err);
|
|
2532
|
+
send({
|
|
2533
|
+
type: 'action_draft',
|
|
2534
|
+
draftId: pending.draftId,
|
|
2535
|
+
draft: null,
|
|
2536
|
+
error: String(err),
|
|
2537
|
+
});
|
|
2538
|
+
});
|
|
2539
|
+
};
|
|
2540
|
+
bind(0);
|
|
2541
|
+
}
|
|
2542
|
+
export function checkPendingSessionLinks(conversationId, claudeSessionId) {
|
|
2543
|
+
checkPendingActionItem(conversationId, claudeSessionId);
|
|
2544
|
+
checkPendingActionDraft(conversationId, claudeSessionId);
|
|
2545
|
+
}
|
|
2403
2546
|
//# sourceMappingURL=connection.js.map
|