@1presence/bridge 0.30.0 → 0.32.0
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/claude.js +41 -2
- package/dist/index.js +15 -11
- package/package.json +1 -1
package/dist/claude.js
CHANGED
|
@@ -76,6 +76,33 @@ function debugBlock(label, colorCode, body) {
|
|
|
76
76
|
const rule = `── ${label} `.padEnd(64, '─');
|
|
77
77
|
process.stderr.write(`\n${paint(colorCode, rule)}\n${body.trimEnd()}\n`);
|
|
78
78
|
}
|
|
79
|
+
// Render one replayed-history content block as a single readable line for the
|
|
80
|
+
// debug transcript. Tool calls and results are inlined so a history turn shows
|
|
81
|
+
// exactly what the model received — text, the tools it ran, and what they
|
|
82
|
+
// returned (including error flags) — not just an opaque "(replaying N turns)".
|
|
83
|
+
function summariseHistoryBlock(block) {
|
|
84
|
+
if (block.type === 'text')
|
|
85
|
+
return block.text.trimEnd();
|
|
86
|
+
if (block.type === 'tool_use') {
|
|
87
|
+
return `→ ${block.name} ${formatPayload(block.input)}`;
|
|
88
|
+
}
|
|
89
|
+
// tool_result
|
|
90
|
+
const body = typeof block.content === 'string'
|
|
91
|
+
? block.content
|
|
92
|
+
: block.content.map((c) => c.text).join('');
|
|
93
|
+
const errFlag = block.is_error ? ' [error]' : '';
|
|
94
|
+
return `← ${block.tool_use_id}${errFlag} ${body}`;
|
|
95
|
+
}
|
|
96
|
+
// Render a full replayed-history message with its role colour so the operator
|
|
97
|
+
// can tell user turns from assistant turns at a glance — the missing
|
|
98
|
+
// distinction that made replayed context unreadable in --debug.
|
|
99
|
+
function renderHistoryMessage(msg) {
|
|
100
|
+
const color = msg.role === 'user' ? DEBUG_COLORS.user : DEBUG_COLORS.assistant;
|
|
101
|
+
const body = typeof msg.content === 'string'
|
|
102
|
+
? msg.content
|
|
103
|
+
: msg.content.map(summariseHistoryBlock).join('\n');
|
|
104
|
+
debugBlock(`${msg.role} · history`, color, body);
|
|
105
|
+
}
|
|
79
106
|
// ─── Active processes ─────────────────────────────────────────────────────────
|
|
80
107
|
const active = new Map();
|
|
81
108
|
// ─── Spawn ────────────────────────────────────────────────────────────────────
|
|
@@ -97,8 +124,20 @@ function spawnClaude(params) {
|
|
|
97
124
|
// id (correlates with the chat URL / Firestore session doc) and a hint at
|
|
98
125
|
// how much prior context is being replayed.
|
|
99
126
|
if (debug) {
|
|
100
|
-
|
|
101
|
-
|
|
127
|
+
process.stderr.write(`\n${paint('1', `══ session ${presenceSessionId} ══`)}\n`);
|
|
128
|
+
// `history` already ends with the new user prompt (gateway-appended). Render
|
|
129
|
+
// every PRIOR message with its role colour so what the model saw as context
|
|
130
|
+
// is auditable — then the live turn is shown via the clean `text` below and
|
|
131
|
+
// streams in beneath it. Defensive: if the tail isn't the current user turn
|
|
132
|
+
// (unexpected), render the whole history rather than dropping a message.
|
|
133
|
+
const tail = history[history.length - 1];
|
|
134
|
+
const prior = tail?.role === 'user' ? history.slice(0, -1) : history;
|
|
135
|
+
if (prior.length > 0) {
|
|
136
|
+
process.stderr.write(paint('90', ` replaying ${prior.length} prior message${prior.length === 1 ? '' : 's'}:\n`));
|
|
137
|
+
for (const msg of prior)
|
|
138
|
+
renderHistoryMessage(msg);
|
|
139
|
+
}
|
|
140
|
+
debugBlock('user · this turn', DEBUG_COLORS.user, text);
|
|
102
141
|
}
|
|
103
142
|
else if (!verbose) {
|
|
104
143
|
// Default mode is quiet, but always surface the session id once per turn so
|
package/dist/index.js
CHANGED
|
@@ -52,9 +52,13 @@ let currentWs = null;
|
|
|
52
52
|
// must surface the error, not silently degrade to a different prompt source
|
|
53
53
|
// (which historically caused the "Skills section authoritative" rule to
|
|
54
54
|
// vanish and the agent to vault-hunt for skills).
|
|
55
|
-
async function fetchSystemPrompt(token) {
|
|
55
|
+
async function fetchSystemPrompt(token, agentSlug) {
|
|
56
56
|
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
57
|
-
|
|
57
|
+
// Pass the selected agent slug so agent-api resolves THIS agent (identity,
|
|
58
|
+
// granted connectors, scoped memory) rather than always falling back to the
|
|
59
|
+
// default 1Presence. Without it, every Local Mode turn was the generalist.
|
|
60
|
+
const agentParam = agentSlug ? `&agent=${encodeURIComponent(agentSlug)}` : '';
|
|
61
|
+
const url = `${GATEWAY_HTTP}/system-prompt-for-bridge?timezone=${encodeURIComponent(tz)}${agentParam}`;
|
|
58
62
|
let res;
|
|
59
63
|
try {
|
|
60
64
|
res = await fetch(url, {
|
|
@@ -89,9 +93,9 @@ function tmpFile(name) {
|
|
|
89
93
|
// connector status, palace, onboarding phase, skills) — call this per turn in
|
|
90
94
|
// the bridge too, otherwise newly shipped skills and mid-session vault writes
|
|
91
95
|
// never reach a long-running bridge. Throws on failure; caller must handle.
|
|
92
|
-
async function writeSystemPrompt(auth) {
|
|
96
|
+
async function writeSystemPrompt(auth, agentSlug) {
|
|
93
97
|
const { uid, token } = auth;
|
|
94
|
-
const systemPrompt = await fetchSystemPrompt(token);
|
|
98
|
+
const systemPrompt = await fetchSystemPrompt(token, agentSlug);
|
|
95
99
|
writeRestricted(tmpFile(`agent-${uid}.md`), systemPrompt);
|
|
96
100
|
if (VERBOSE) {
|
|
97
101
|
console.log('\n[bridge:verbose] ─── system prompt ───────────────────────');
|
|
@@ -112,8 +116,8 @@ function writeMcpConfig(auth) {
|
|
|
112
116
|
};
|
|
113
117
|
writeRestricted(tmpFile(`mcp-${uid}.json`), JSON.stringify(mcpConfig, null, 2));
|
|
114
118
|
}
|
|
115
|
-
async function writeSetupFiles(auth) {
|
|
116
|
-
await writeSystemPrompt(auth);
|
|
119
|
+
async function writeSetupFiles(auth, agentSlug) {
|
|
120
|
+
await writeSystemPrompt(auth, agentSlug);
|
|
117
121
|
writeMcpConfig(auth);
|
|
118
122
|
}
|
|
119
123
|
// The MCP config embeds a Bearer JWT and the system prompt may contain vault
|
|
@@ -129,7 +133,7 @@ function isUuid(value) {
|
|
|
129
133
|
return UUID_RE.test(value);
|
|
130
134
|
}
|
|
131
135
|
// ─── Handle a single incoming message (token refresh + spawn) ─────────────────
|
|
132
|
-
async function handleMessage(conversationId, text, sessionId, history, auth, vaultFileOpen, clientCapabilities, syncedFolders) {
|
|
136
|
+
async function handleMessage(conversationId, text, sessionId, history, auth, vaultFileOpen, clientCapabilities, syncedFolders, agentSlug) {
|
|
133
137
|
// Refresh JWT if <10 min remaining before spawning Claude
|
|
134
138
|
let activeAuth = auth;
|
|
135
139
|
try {
|
|
@@ -137,7 +141,7 @@ async function handleMessage(conversationId, text, sessionId, history, auth, vau
|
|
|
137
141
|
if (freshAuth.token !== auth.token) {
|
|
138
142
|
currentAuth = freshAuth;
|
|
139
143
|
activeAuth = freshAuth;
|
|
140
|
-
await writeSetupFiles(freshAuth);
|
|
144
|
+
await writeSetupFiles(freshAuth, agentSlug);
|
|
141
145
|
}
|
|
142
146
|
}
|
|
143
147
|
catch (err) {
|
|
@@ -161,7 +165,7 @@ async function handleMessage(conversationId, text, sessionId, history, auth, vau
|
|
|
161
165
|
// (e.g. agent vault-hunting for skills because the Skills authoritative
|
|
162
166
|
// rule was missing from the previous snapshot).
|
|
163
167
|
try {
|
|
164
|
-
await writeSystemPrompt(activeAuth);
|
|
168
|
+
await writeSystemPrompt(activeAuth, agentSlug);
|
|
165
169
|
}
|
|
166
170
|
catch (err) {
|
|
167
171
|
const message = `System prompt refresh failed: ${err.message}`;
|
|
@@ -376,11 +380,11 @@ function connect(auth, retryDelay = 1000) {
|
|
|
376
380
|
}
|
|
377
381
|
if (msg.type !== 'message' || !msg.conversationId || !msg.text)
|
|
378
382
|
return;
|
|
379
|
-
const { conversationId, text, sessionId, history, vaultFileOpen, clientCapabilities, syncedFolders } = msg;
|
|
383
|
+
const { conversationId, text, sessionId, history, vaultFileOpen, clientCapabilities, syncedFolders, agentSlug } = msg;
|
|
380
384
|
const ts = new Date().toLocaleTimeString();
|
|
381
385
|
const hist = Array.isArray(history) ? history : [];
|
|
382
386
|
console.log(`[${ts}] ▶ ${text}${hist.length ? ` (history: ${hist.length} turn${hist.length === 1 ? '' : 's'})` : ''}`);
|
|
383
|
-
handleMessage(conversationId, text, sessionId ?? null, hist, auth, vaultFileOpen, clientCapabilities, syncedFolders).catch((err) => {
|
|
387
|
+
handleMessage(conversationId, text, sessionId ?? null, hist, auth, vaultFileOpen, clientCapabilities, syncedFolders, agentSlug).catch((err) => {
|
|
384
388
|
console.error(`[bridge] handleMessage error: ${err.message}`);
|
|
385
389
|
});
|
|
386
390
|
});
|