a2acalling 0.6.43 → 0.6.45
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/README.md +27 -5
- package/bin/cli.js +48 -2
- package/docs/plans/2026-02-16-a2a-callbook-macos-app.md +1660 -0
- package/docs/plans/2026-02-16-e2e-test-prompt-sequence.md +1812 -0
- package/native/macos/index.html +172 -0
- package/native/macos/package.json +8 -0
- package/native/macos/src-tauri/Cargo.toml +23 -0
- package/native/macos/src-tauri/build.rs +3 -0
- package/native/macos/src-tauri/capabilities/default.json +16 -0
- package/native/macos/src-tauri/icons/128x128.png +0 -0
- package/native/macos/src-tauri/icons/128x128@2x.png +0 -0
- package/native/macos/src-tauri/icons/32x32.png +0 -0
- package/native/macos/src-tauri/icons/icon.icns +0 -0
- package/native/macos/src-tauri/icons/tray-connected.png +0 -0
- package/native/macos/src-tauri/icons/tray-disconnected.png +0 -0
- package/native/macos/src-tauri/src/discovery.rs +86 -0
- package/native/macos/src-tauri/src/health.rs +64 -0
- package/native/macos/src-tauri/src/lib.rs +185 -0
- package/native/macos/src-tauri/src/main.rs +6 -0
- package/native/macos/src-tauri/src/notifications.rs +101 -0
- package/native/macos/src-tauri/src/server.rs +67 -0
- package/native/macos/src-tauri/tauri.conf.json +48 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +49 -0
- package/src/lib/claude-subagent.js +485 -0
- package/src/lib/conversation-driver.js +80 -29
- package/src/lib/disclosure.js +5 -6
- package/src/lib/runtime-adapter.js +221 -437
- package/src/routes/dashboard.js +5 -5
- package/src/server.js +5 -10
|
@@ -56,7 +56,7 @@ function detectRemoteTermination(text) {
|
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* Infer collaboration state progression when the runtime doesn't emit
|
|
59
|
-
* <collab_state> tags (
|
|
59
|
+
* <collab_state> tags (e.g. OpenClaw without adaptive mode). Advances phase based on
|
|
60
60
|
* turn count and estimates overlap from remote text analysis.
|
|
61
61
|
*/
|
|
62
62
|
function inferStateProgression(collabState, remoteText, turn) {
|
|
@@ -128,8 +128,11 @@ class ConversationDriver {
|
|
|
128
128
|
this.tier = options.tier || 'public';
|
|
129
129
|
this.summarizer = options.summarizer || null;
|
|
130
130
|
this.ownerContext = options.ownerContext || {};
|
|
131
|
+
this.claudeMode = options.runtime?.mode === 'claude';
|
|
132
|
+
this.claudeTimeoutMs = options.claudeTimeoutMs || 180000;
|
|
131
133
|
|
|
132
|
-
|
|
134
|
+
const clientTimeout = this.claudeMode ? 200000 : 65000;
|
|
135
|
+
this.client = new A2AClient({ caller: this.caller, timeout: clientTimeout });
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
/**
|
|
@@ -351,18 +354,30 @@ Be concise but specific. No filler.`;
|
|
|
351
354
|
// 5. Call runtime.runTurn() to generate next message
|
|
352
355
|
const sessionId = `a2a-${conversationId}`;
|
|
353
356
|
let rawResponse;
|
|
357
|
+
const contextPayload = {
|
|
358
|
+
conversationId,
|
|
359
|
+
tier: this.tier,
|
|
360
|
+
ownerName: this.agentContext.owner,
|
|
361
|
+
agentName: this.agentContext.name,
|
|
362
|
+
roleContext: 'You initiated this call.'
|
|
363
|
+
};
|
|
364
|
+
if (this.claudeMode) {
|
|
365
|
+
contextPayload.turnCount = turn + 1;
|
|
366
|
+
contextPayload.maxTurns = this.maxTurns;
|
|
367
|
+
contextPayload.phase = collabState.phase;
|
|
368
|
+
contextPayload.overlapScore = collabState.overlapScore;
|
|
369
|
+
contextPayload.activeThreads = collabState.activeThreads;
|
|
370
|
+
contextPayload.candidateCollaborations = collabState.candidateCollaborations;
|
|
371
|
+
contextPayload.closeSignal = collabState.closeSignal;
|
|
372
|
+
}
|
|
354
373
|
try {
|
|
355
374
|
rawResponse = await this.runtime.runTurn({
|
|
356
375
|
sessionId,
|
|
357
376
|
prompt,
|
|
358
377
|
message: remoteText,
|
|
359
378
|
caller: this.caller,
|
|
360
|
-
timeoutMs: 65000,
|
|
361
|
-
context:
|
|
362
|
-
conversationId,
|
|
363
|
-
tier: this.tier,
|
|
364
|
-
ownerName: this.agentContext.owner
|
|
365
|
-
}
|
|
379
|
+
timeoutMs: this.claudeMode ? this.claudeTimeoutMs : 65000,
|
|
380
|
+
context: contextPayload
|
|
366
381
|
});
|
|
367
382
|
} catch (err) {
|
|
368
383
|
logger.error('Runtime turn failed', {
|
|
@@ -374,33 +389,59 @@ Be concise but specific. No filler.`;
|
|
|
374
389
|
}
|
|
375
390
|
|
|
376
391
|
// 6. Extract collab state from response
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
if (
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
392
|
+
// In claude mode, use the side channel (getLastTurnMeta) for state/flags
|
|
393
|
+
const turnMeta = this.claudeMode ? this.runtime.getLastTurnMeta?.(sessionId) : null;
|
|
394
|
+
|
|
395
|
+
if (turnMeta?.statePatch) {
|
|
396
|
+
// Claude subagent returned structured state — apply it directly
|
|
397
|
+
nextMessage = rawResponse;
|
|
398
|
+
const sp = turnMeta.statePatch;
|
|
399
|
+
if (sp.phase) collabState.phase = sp.phase;
|
|
400
|
+
if (sp.overlapScore != null) {
|
|
401
|
+
collabState.overlapScore = Math.max(0, Math.min(1, sp.overlapScore));
|
|
384
402
|
}
|
|
385
|
-
if (Array.isArray(
|
|
386
|
-
collabState.activeThreads =
|
|
403
|
+
if (Array.isArray(sp.activeThreads)) {
|
|
404
|
+
collabState.activeThreads = sp.activeThreads.slice(0, 4);
|
|
387
405
|
}
|
|
388
|
-
if (Array.isArray(
|
|
389
|
-
collabState.candidateCollaborations =
|
|
406
|
+
if (Array.isArray(sp.candidateCollaborations)) {
|
|
407
|
+
collabState.candidateCollaborations = sp.candidateCollaborations.slice(0, 4);
|
|
390
408
|
}
|
|
391
|
-
if (
|
|
392
|
-
collabState.closeSignal = Boolean(
|
|
409
|
+
if (sp.closeSignal != null) {
|
|
410
|
+
collabState.closeSignal = Boolean(sp.closeSignal);
|
|
393
411
|
}
|
|
394
|
-
if (
|
|
395
|
-
collabState.confidence = Math.max(0, Math.min(1,
|
|
412
|
+
if (sp.confidence != null) {
|
|
413
|
+
collabState.confidence = Math.max(0, Math.min(1, sp.confidence));
|
|
396
414
|
}
|
|
397
415
|
} else {
|
|
398
|
-
//
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (
|
|
403
|
-
|
|
416
|
+
// Non-claude path: extract from <collab_state> tags in response text
|
|
417
|
+
const parsed = extractCollaborationState(rawResponse);
|
|
418
|
+
nextMessage = parsed.cleanText || rawResponse;
|
|
419
|
+
|
|
420
|
+
if (parsed.hasState && parsed.statePatch) {
|
|
421
|
+
if (parsed.statePatch.phase) collabState.phase = parsed.statePatch.phase;
|
|
422
|
+
if (parsed.statePatch.overlapScore != null) {
|
|
423
|
+
collabState.overlapScore = Math.max(0, Math.min(1, parsed.statePatch.overlapScore));
|
|
424
|
+
}
|
|
425
|
+
if (Array.isArray(parsed.statePatch.activeThreads)) {
|
|
426
|
+
collabState.activeThreads = parsed.statePatch.activeThreads.slice(0, 4);
|
|
427
|
+
}
|
|
428
|
+
if (Array.isArray(parsed.statePatch.candidateCollaborations)) {
|
|
429
|
+
collabState.candidateCollaborations = parsed.statePatch.candidateCollaborations.slice(0, 4);
|
|
430
|
+
}
|
|
431
|
+
if (parsed.statePatch.closeSignal != null) {
|
|
432
|
+
collabState.closeSignal = Boolean(parsed.statePatch.closeSignal);
|
|
433
|
+
}
|
|
434
|
+
if (parsed.statePatch.confidence != null) {
|
|
435
|
+
collabState.confidence = Math.max(0, Math.min(1, parsed.statePatch.confidence));
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
// No <collab_state> in response (generic/fallback runtime) — infer progression
|
|
439
|
+
const inferred = inferStateProgression(collabState, remoteText, turn + 1);
|
|
440
|
+
if (inferred.phase) collabState.phase = inferred.phase;
|
|
441
|
+
if (inferred.overlapScore != null) collabState.overlapScore = inferred.overlapScore;
|
|
442
|
+
if (inferred.confidence != null) collabState.confidence = inferred.confidence;
|
|
443
|
+
if (inferred.closeSignal != null) collabState.closeSignal = inferred.closeSignal;
|
|
444
|
+
}
|
|
404
445
|
}
|
|
405
446
|
|
|
406
447
|
// 6b. Overlap flatline detection — if overlap hasn't changed significantly
|
|
@@ -426,6 +467,16 @@ Be concise but specific. No filler.`;
|
|
|
426
467
|
}
|
|
427
468
|
}
|
|
428
469
|
|
|
470
|
+
// 7b. Store flags from claude subagent responses
|
|
471
|
+
if (turnMeta?.flags?.length > 0 && this.convStore && dbConversationStarted) {
|
|
472
|
+
this.convStore.addMessage(conversationId, {
|
|
473
|
+
direction: 'outbound',
|
|
474
|
+
role: 'system',
|
|
475
|
+
content: `[flags] ${turnMeta.flags.map(f => f.content || f.type).join('; ')}`,
|
|
476
|
+
metadata: JSON.stringify({ flags: turnMeta.flags, turn: turn + 1 })
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
429
480
|
// onTurn callback for progress output
|
|
430
481
|
if (this.onTurn) {
|
|
431
482
|
try {
|
package/src/lib/disclosure.js
CHANGED
|
@@ -32,7 +32,7 @@ function dedupeByTopic(items) {
|
|
|
32
32
|
seen.add(topic.toLowerCase());
|
|
33
33
|
out.push({
|
|
34
34
|
topic,
|
|
35
|
-
description: normalizeTopic(item &&
|
|
35
|
+
description: normalizeTopic(item && item.description)
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
return out;
|
|
@@ -152,7 +152,7 @@ function saveManifest(manifest) {
|
|
|
152
152
|
*/
|
|
153
153
|
function getTopicsForTier(tier) {
|
|
154
154
|
const manifest = loadManifest();
|
|
155
|
-
const tiers = manifest.tiers ||
|
|
155
|
+
const tiers = manifest.tiers || {};
|
|
156
156
|
|
|
157
157
|
const tierIndex = TIER_HIERARCHY.indexOf(tier);
|
|
158
158
|
if (tierIndex === -1) {
|
|
@@ -195,7 +195,7 @@ function getTopicsForTier(tier) {
|
|
|
195
195
|
function formatTopicsForPrompt(tierTopics) {
|
|
196
196
|
const formatTopicList = (items) => {
|
|
197
197
|
if (!items || items.length === 0) return ' (none specified)';
|
|
198
|
-
return items.map(item => ` - ${item.topic}: ${item.description ||
|
|
198
|
+
return items.map(item => ` - ${item.topic}: ${item.description || ''}`).join('\n');
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
const formatObjectiveList = (items) => {
|
|
@@ -363,10 +363,9 @@ function validateDisclosureSubmission(data) {
|
|
|
363
363
|
return { valid: false, manifest: null, errors: ['Submission must be a non-null object'] };
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
|
|
367
|
-
const tiersData = data.tiers || data.topics;
|
|
366
|
+
const tiersData = data.tiers;
|
|
368
367
|
if (!tiersData || typeof tiersData !== 'object' || Array.isArray(tiersData)) {
|
|
369
|
-
errors.push('Submission must include a "tiers" object
|
|
368
|
+
errors.push('Submission must include a "tiers" object');
|
|
370
369
|
return { valid: false, manifest: null, errors };
|
|
371
370
|
}
|
|
372
371
|
|