a2acalling 0.6.47 → 0.6.49
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/bin/cli.js +78 -9
- package/docs/plans/2026-02-16-auto-updater.md +1284 -0
- package/docs/plans/2026-02-16-e2e-test-prompt-sequence.md +3085 -0
- package/docs/plans/2026-02-17-claude-code-codex-skills.md +770 -0
- package/docs/prompts/e2e-test-agent.md +368 -0
- package/docs/protocol.md +79 -0
- package/package.json +1 -1
- package/src/dashboard/public/app.js +108 -1
- package/src/dashboard/public/index.html +9 -0
- package/src/dashboard/public/style.css +27 -0
- package/src/lib/config.js +41 -0
- package/src/lib/conversation-driver.js +62 -21
- package/src/lib/openclaw-integration.js +22 -66
- package/src/lib/summary-formatter.js +168 -0
- package/src/lib/summary-prompt.js +203 -0
- package/src/lib/update-checker.js +93 -0
- package/src/lib/update-manager.js +313 -0
- package/src/routes/a2a.js +8 -1
- package/src/routes/dashboard.js +103 -1
- package/src/server.js +126 -25
package/src/server.js
CHANGED
|
@@ -22,6 +22,11 @@ const {
|
|
|
22
22
|
} = require('./lib/prompt-template');
|
|
23
23
|
const { findAvailablePort } = require('./lib/port-scanner');
|
|
24
24
|
const { createLogger } = require('./lib/logger');
|
|
25
|
+
const { writePidFile, removePidFile } = require('./lib/pid-file');
|
|
26
|
+
const { buildUnifiedSummaryPrompt } = require('./lib/summary-prompt');
|
|
27
|
+
const { A2AConfig } = require('./lib/config');
|
|
28
|
+
const { UpdateManager } = require('./lib/update-manager');
|
|
29
|
+
const { spawn } = require('child_process');
|
|
25
30
|
|
|
26
31
|
const DEFAULT_PORTS = [80, 3001, 8080, 8443, 9001];
|
|
27
32
|
const requestedPort = process.env.PORT ? parseInt(process.env.PORT, 10)
|
|
@@ -60,6 +65,7 @@ function loadAgentContext() {
|
|
|
60
65
|
|
|
61
66
|
const agentContext = loadAgentContext();
|
|
62
67
|
const tokenStore = new TokenStore();
|
|
68
|
+
const config = new A2AConfig();
|
|
63
69
|
const runtime = createRuntimeAdapter({
|
|
64
70
|
workspaceDir,
|
|
65
71
|
agentContext,
|
|
@@ -690,30 +696,61 @@ async function callAgent(message, a2aContext) {
|
|
|
690
696
|
* Generate strategic summary via sub-agent
|
|
691
697
|
*/
|
|
692
698
|
async function generateSummary(messages, callerInfo) {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
**Collaboration Potential:** Rate HIGH/MEDIUM/LOW. List specific opportunities identified.
|
|
710
|
-
**What We Learned vs Shared:** Brief information exchange audit — what did we get, what did we give.
|
|
711
|
-
**Recommended Follow-Up:**
|
|
712
|
-
- [ ] Actionable item 1
|
|
713
|
-
- [ ] Actionable item 2
|
|
714
|
-
**Assessment:** One-sentence strategic value judgment.
|
|
699
|
+
// Look up collaboration state if we have a conversation_id
|
|
700
|
+
const conversationId = callerInfo?.conversation_id || callerInfo?.conversationId;
|
|
701
|
+
let collaborationState = null;
|
|
702
|
+
if (conversationId) {
|
|
703
|
+
const collabSession = collaborationSessions.get(conversationId);
|
|
704
|
+
if (collabSession) {
|
|
705
|
+
collaborationState = {
|
|
706
|
+
phase: collabSession.phase,
|
|
707
|
+
overlapScore: collabSession.overlapScore,
|
|
708
|
+
turnCount: collabSession.turnCount,
|
|
709
|
+
activeThreads: collabSession.activeThreads,
|
|
710
|
+
candidateCollaborations: collabSession.candidateCollaborations,
|
|
711
|
+
closeSignal: collabSession.closeSignal
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
715
|
|
|
716
|
-
|
|
716
|
+
// Load disclosure manifest for the caller's tier
|
|
717
|
+
const tier = callerInfo?.tier || 'public';
|
|
718
|
+
let disclosure = null;
|
|
719
|
+
try {
|
|
720
|
+
const tierTopics = getTopicsForTier(tier);
|
|
721
|
+
if (tierTopics) {
|
|
722
|
+
disclosure = {
|
|
723
|
+
topics: tierTopics.topics || [],
|
|
724
|
+
objectives: tierTopics.objectives || [],
|
|
725
|
+
doNotDiscuss: tierTopics.do_not_discuss || [],
|
|
726
|
+
neverDisclose: tierTopics.never_disclose || []
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
} catch (e) {
|
|
730
|
+
// Disclosure is optional — continue without it
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// Build transcript in unified format
|
|
734
|
+
const transcript = messages.map(m => ({
|
|
735
|
+
direction: m.direction,
|
|
736
|
+
content: m.content
|
|
737
|
+
}));
|
|
738
|
+
|
|
739
|
+
const prompt = buildUnifiedSummaryPrompt({
|
|
740
|
+
transcript,
|
|
741
|
+
callerInfo: {
|
|
742
|
+
name: callerInfo?.name || null,
|
|
743
|
+
owner: callerInfo?.owner || null,
|
|
744
|
+
context: callerInfo?.context || null
|
|
745
|
+
},
|
|
746
|
+
disclosure,
|
|
747
|
+
collaborationState,
|
|
748
|
+
ownerContext: {
|
|
749
|
+
agentName: agentContext.name,
|
|
750
|
+
ownerName: agentContext.owner,
|
|
751
|
+
goals: []
|
|
752
|
+
}
|
|
753
|
+
});
|
|
717
754
|
|
|
718
755
|
try {
|
|
719
756
|
return await runtime.summarize({
|
|
@@ -722,13 +759,13 @@ Be concise but specific. No filler.`;
|
|
|
722
759
|
messages,
|
|
723
760
|
callerInfo,
|
|
724
761
|
traceId: callerInfo?.trace_id || callerInfo?.traceId,
|
|
725
|
-
conversationId
|
|
762
|
+
conversationId
|
|
726
763
|
});
|
|
727
764
|
} catch (err) {
|
|
728
765
|
logger.error('Summary generation failed', {
|
|
729
766
|
event: 'summary_generation_failed',
|
|
730
767
|
traceId: callerInfo?.trace_id || callerInfo?.traceId,
|
|
731
|
-
conversationId
|
|
768
|
+
conversationId,
|
|
732
769
|
error_code: 'SUMMARY_GENERATION_FAILED',
|
|
733
770
|
hint: 'Check summarizer runtime and command configuration for summary stage.',
|
|
734
771
|
error: err,
|
|
@@ -772,17 +809,23 @@ async function notifyOwner({ level, token, caller, message, conversation_id, tra
|
|
|
772
809
|
|
|
773
810
|
const app = express();
|
|
774
811
|
app.use(express.json());
|
|
812
|
+
let activeCallMonitor = null;
|
|
813
|
+
let updateManager = null;
|
|
775
814
|
|
|
776
815
|
// Minimal owner dashboard (local by default unless A2A_ADMIN_TOKEN is provided)
|
|
777
816
|
// All routes under /api/a2a/* so reverse proxy config stays simple.
|
|
778
817
|
app.use('/api/a2a/dashboard', createDashboardApiRouter({
|
|
779
818
|
tokenStore,
|
|
780
819
|
agentContext,
|
|
820
|
+
config,
|
|
821
|
+
getUpdateManager: () => updateManager,
|
|
781
822
|
logger: logger.child({ component: 'a2a.dashboard' })
|
|
782
823
|
}));
|
|
783
824
|
app.use('/api/a2a/dashboard', createDashboardUiRouter({
|
|
784
825
|
tokenStore,
|
|
785
826
|
agentContext,
|
|
827
|
+
config,
|
|
828
|
+
getUpdateManager: () => updateManager,
|
|
786
829
|
logger: logger.child({ component: 'a2a.dashboard' })
|
|
787
830
|
}));
|
|
788
831
|
|
|
@@ -801,6 +844,9 @@ app.use('/callbook', createCallbookRouter());
|
|
|
801
844
|
app.use('/api/a2a', createRoutes({
|
|
802
845
|
tokenStore,
|
|
803
846
|
logger: logger.child({ component: 'a2a.routes' }),
|
|
847
|
+
onCallMonitor: (monitor) => {
|
|
848
|
+
activeCallMonitor = monitor;
|
|
849
|
+
},
|
|
804
850
|
|
|
805
851
|
async handleMessage(message, context, options) {
|
|
806
852
|
const traceId = context.trace_id || null;
|
|
@@ -903,6 +949,51 @@ async function startServer() {
|
|
|
903
949
|
features: ['adaptive collaboration', 'auto-contacts', 'summaries', 'dashboard']
|
|
904
950
|
}
|
|
905
951
|
});
|
|
952
|
+
writePidFile(process.pid);
|
|
953
|
+
|
|
954
|
+
if (!updateManager) {
|
|
955
|
+
const pkg = require('../package.json');
|
|
956
|
+
const restartFn = async () => {
|
|
957
|
+
const cliPath = path.join(__dirname, '..', 'bin', 'cli.js');
|
|
958
|
+
const helperScript = `
|
|
959
|
+
const { spawn } = require('child_process');
|
|
960
|
+
const startNext = () => {
|
|
961
|
+
const child = spawn(process.execPath, [${JSON.stringify(cliPath)}, 'server', '--port', ${JSON.stringify(String(port))}], {
|
|
962
|
+
detached: true,
|
|
963
|
+
stdio: 'ignore',
|
|
964
|
+
env: process.env
|
|
965
|
+
});
|
|
966
|
+
child.unref();
|
|
967
|
+
process.exit(0);
|
|
968
|
+
};
|
|
969
|
+
setTimeout(startNext, 1500);
|
|
970
|
+
`;
|
|
971
|
+
const helper = spawn(process.execPath, ['-e', helperScript], {
|
|
972
|
+
detached: true,
|
|
973
|
+
stdio: 'ignore',
|
|
974
|
+
env: process.env
|
|
975
|
+
});
|
|
976
|
+
helper.unref();
|
|
977
|
+
setTimeout(() => {
|
|
978
|
+
process.kill(process.pid, 'SIGTERM');
|
|
979
|
+
}, 150);
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
updateManager = new UpdateManager({
|
|
983
|
+
currentVersion: pkg.version,
|
|
984
|
+
config,
|
|
985
|
+
logger: logger.child({ component: 'a2a.updater' }),
|
|
986
|
+
getCallMonitor: () => activeCallMonitor,
|
|
987
|
+
restartFn
|
|
988
|
+
});
|
|
989
|
+
updateManager.start();
|
|
990
|
+
updateManager.triggerCheck({ reason: 'startup' }).catch((err) => {
|
|
991
|
+
logger.warn('Initial auto-update check failed', {
|
|
992
|
+
event: 'updater_startup_check_failed',
|
|
993
|
+
error: err
|
|
994
|
+
});
|
|
995
|
+
});
|
|
996
|
+
}
|
|
906
997
|
});
|
|
907
998
|
|
|
908
999
|
server.on('error', (err) => {
|
|
@@ -917,6 +1008,16 @@ async function startServer() {
|
|
|
917
1008
|
}
|
|
918
1009
|
throw err;
|
|
919
1010
|
});
|
|
1011
|
+
|
|
1012
|
+
function shutdown() {
|
|
1013
|
+
if (updateManager) updateManager.stop();
|
|
1014
|
+
removePidFile();
|
|
1015
|
+
server.close(() => process.exit(0));
|
|
1016
|
+
// Force exit after 5s if connections won't close
|
|
1017
|
+
setTimeout(() => process.exit(0), 5000).unref();
|
|
1018
|
+
}
|
|
1019
|
+
process.on('SIGTERM', shutdown);
|
|
1020
|
+
process.on('SIGINT', shutdown);
|
|
920
1021
|
}
|
|
921
1022
|
|
|
922
1023
|
startServer();
|