a2acalling 0.6.48 → 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 +23 -0
- 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 +115 -26
package/src/server.js
CHANGED
|
@@ -23,6 +23,10 @@ const {
|
|
|
23
23
|
const { findAvailablePort } = require('./lib/port-scanner');
|
|
24
24
|
const { createLogger } = require('./lib/logger');
|
|
25
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');
|
|
26
30
|
|
|
27
31
|
const DEFAULT_PORTS = [80, 3001, 8080, 8443, 9001];
|
|
28
32
|
const requestedPort = process.env.PORT ? parseInt(process.env.PORT, 10)
|
|
@@ -61,6 +65,7 @@ function loadAgentContext() {
|
|
|
61
65
|
|
|
62
66
|
const agentContext = loadAgentContext();
|
|
63
67
|
const tokenStore = new TokenStore();
|
|
68
|
+
const config = new A2AConfig();
|
|
64
69
|
const runtime = createRuntimeAdapter({
|
|
65
70
|
workspaceDir,
|
|
66
71
|
agentContext,
|
|
@@ -691,30 +696,61 @@ async function callAgent(message, a2aContext) {
|
|
|
691
696
|
* Generate strategic summary via sub-agent
|
|
692
697
|
*/
|
|
693
698
|
async function generateSummary(messages, callerInfo) {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
**Collaboration Potential:** Rate HIGH/MEDIUM/LOW. List specific opportunities identified.
|
|
711
|
-
**What We Learned vs Shared:** Brief information exchange audit — what did we get, what did we give.
|
|
712
|
-
**Recommended Follow-Up:**
|
|
713
|
-
- [ ] Actionable item 1
|
|
714
|
-
- [ ] Actionable item 2
|
|
715
|
-
**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
|
+
}
|
|
716
715
|
|
|
717
|
-
|
|
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
|
+
});
|
|
718
754
|
|
|
719
755
|
try {
|
|
720
756
|
return await runtime.summarize({
|
|
@@ -723,13 +759,13 @@ Be concise but specific. No filler.`;
|
|
|
723
759
|
messages,
|
|
724
760
|
callerInfo,
|
|
725
761
|
traceId: callerInfo?.trace_id || callerInfo?.traceId,
|
|
726
|
-
conversationId
|
|
762
|
+
conversationId
|
|
727
763
|
});
|
|
728
764
|
} catch (err) {
|
|
729
765
|
logger.error('Summary generation failed', {
|
|
730
766
|
event: 'summary_generation_failed',
|
|
731
767
|
traceId: callerInfo?.trace_id || callerInfo?.traceId,
|
|
732
|
-
conversationId
|
|
768
|
+
conversationId,
|
|
733
769
|
error_code: 'SUMMARY_GENERATION_FAILED',
|
|
734
770
|
hint: 'Check summarizer runtime and command configuration for summary stage.',
|
|
735
771
|
error: err,
|
|
@@ -773,17 +809,23 @@ async function notifyOwner({ level, token, caller, message, conversation_id, tra
|
|
|
773
809
|
|
|
774
810
|
const app = express();
|
|
775
811
|
app.use(express.json());
|
|
812
|
+
let activeCallMonitor = null;
|
|
813
|
+
let updateManager = null;
|
|
776
814
|
|
|
777
815
|
// Minimal owner dashboard (local by default unless A2A_ADMIN_TOKEN is provided)
|
|
778
816
|
// All routes under /api/a2a/* so reverse proxy config stays simple.
|
|
779
817
|
app.use('/api/a2a/dashboard', createDashboardApiRouter({
|
|
780
818
|
tokenStore,
|
|
781
819
|
agentContext,
|
|
820
|
+
config,
|
|
821
|
+
getUpdateManager: () => updateManager,
|
|
782
822
|
logger: logger.child({ component: 'a2a.dashboard' })
|
|
783
823
|
}));
|
|
784
824
|
app.use('/api/a2a/dashboard', createDashboardUiRouter({
|
|
785
825
|
tokenStore,
|
|
786
826
|
agentContext,
|
|
827
|
+
config,
|
|
828
|
+
getUpdateManager: () => updateManager,
|
|
787
829
|
logger: logger.child({ component: 'a2a.dashboard' })
|
|
788
830
|
}));
|
|
789
831
|
|
|
@@ -802,6 +844,9 @@ app.use('/callbook', createCallbookRouter());
|
|
|
802
844
|
app.use('/api/a2a', createRoutes({
|
|
803
845
|
tokenStore,
|
|
804
846
|
logger: logger.child({ component: 'a2a.routes' }),
|
|
847
|
+
onCallMonitor: (monitor) => {
|
|
848
|
+
activeCallMonitor = monitor;
|
|
849
|
+
},
|
|
805
850
|
|
|
806
851
|
async handleMessage(message, context, options) {
|
|
807
852
|
const traceId = context.trace_id || null;
|
|
@@ -905,6 +950,50 @@ async function startServer() {
|
|
|
905
950
|
}
|
|
906
951
|
});
|
|
907
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
|
+
}
|
|
908
997
|
});
|
|
909
998
|
|
|
910
999
|
server.on('error', (err) => {
|
|
@@ -920,8 +1009,8 @@ async function startServer() {
|
|
|
920
1009
|
throw err;
|
|
921
1010
|
});
|
|
922
1011
|
|
|
923
|
-
// Graceful shutdown: clean up PID file
|
|
924
1012
|
function shutdown() {
|
|
1013
|
+
if (updateManager) updateManager.stop();
|
|
925
1014
|
removePidFile();
|
|
926
1015
|
server.close(() => process.exit(0));
|
|
927
1016
|
// Force exit after 5s if connections won't close
|