@chatpanel/events 0.92.0 → 0.92.1
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/package.json +1 -1
- package/team-worklog.js +15 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/events",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.1",
|
|
4
4
|
"description": "The canonical ChatPanel event-log and capability contracts \u2014 typed durable facts, clock-free deterministic linearization, schema upcasting, and the invariants the replay harness asserts. Pure, dependency-free ESM shared by the ChatPanel extension, gateway and bridge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
package/team-worklog.js
CHANGED
|
@@ -34,10 +34,13 @@ export function describeCall(call) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* The timeline of one task: `[{ kind, at, by, attempt, ... }]`, oldest first. Every entry has
|
|
37
|
+
* The timeline of one task: `[{ id, kind, at, by, attempt, ... }]`, oldest first. Every entry has
|
|
38
38
|
* an `at`; a step recorded without one (an older build) inherits its attempt's, so the order
|
|
39
39
|
* still holds. `by` is the role for what the member did, `runner` for the runner's lines, and
|
|
40
|
-
* whoever posted for a post.
|
|
40
|
+
* whoever posted for a post. `id` is STABLE across polls — the step's index on the record, the
|
|
41
|
+
* post's id, the attempt's number — so a board can keep the row a person opened while the
|
|
42
|
+
* log grows underneath it (a row keyed by its position remounted on every new step, and the
|
|
43
|
+
* fold a reader had opened snapped shut every four seconds).
|
|
41
44
|
*/
|
|
42
45
|
export function workLogFor(run, taskId) {
|
|
43
46
|
const task = (run?.tasks || []).find((t) => t.id === taskId);
|
|
@@ -46,7 +49,7 @@ export function workLogFor(run, taskId) {
|
|
|
46
49
|
const out = [];
|
|
47
50
|
const attempts = Array.isArray(task.attempts) ? task.attempts : [];
|
|
48
51
|
const baseAt = num(task.startedAt, num(attempts[0]?.at, num(run?.startedAt, 0)));
|
|
49
|
-
attempts.forEach((a, i) => out.push({ kind: 'attempt', at: num(a.at, baseAt + i), by: 'runner', attempt: i + 1, model: a.model || '', engine: a.engine || null, continued: !!a.continued, status: a.status || null, error: a.error || null }));
|
|
52
|
+
attempts.forEach((a, i) => out.push({ id: `attempt:${i + 1}`, kind: 'attempt', at: num(a.at, baseAt + i), by: 'runner', attempt: i + 1, model: a.model || '', engine: a.engine || null, continued: !!a.continued, status: a.status || null, error: a.error || null }));
|
|
50
53
|
|
|
51
54
|
// Steps: stamped ones sort by their time; unstamped ones follow their attempt in order.
|
|
52
55
|
const steps = Array.isArray(task.transcript) ? task.transcript : [];
|
|
@@ -62,37 +65,37 @@ export function workLogFor(run, taskId) {
|
|
|
62
65
|
lastAt = Math.max(lastAt, at);
|
|
63
66
|
const attempt = attemptOf;
|
|
64
67
|
if (m.role === 'user') {
|
|
65
|
-
out.push({ kind: i === 0 ? 'prompt' : 'note', at, by: 'runner', attempt, text: str(m.content) });
|
|
68
|
+
out.push({ id: `step:${i}`, kind: i === 0 ? 'prompt' : 'note', at, by: 'runner', attempt, text: str(m.content) });
|
|
66
69
|
} else if (m.role === 'assistant') {
|
|
67
|
-
if (isThought(m)) { out.push({ kind: 'thought', at, by, attempt, text: m.thought }); return; }
|
|
68
|
-
if (typeof m.content === 'string' && m.content.trim()) out.push({ kind: 'text', at, by, attempt, text: m.content });
|
|
70
|
+
if (isThought(m)) { out.push({ id: `step:${i}`, kind: 'thought', at, by, attempt, text: m.thought }); return; }
|
|
71
|
+
if (typeof m.content === 'string' && m.content.trim()) out.push({ id: `step:${i}`, kind: 'text', at, by, attempt, text: m.content });
|
|
69
72
|
for (const c of Array.isArray(m.tool_calls) ? m.tool_calls : []) {
|
|
70
73
|
const id = c.id || `c${i}`;
|
|
71
74
|
calls.set(id, c);
|
|
72
|
-
out.push({ kind: 'call', at, by, attempt, callId: id, name: c.function?.name || 'tool', args: parseArgs(c.function?.arguments), text: describeCall(c) });
|
|
75
|
+
out.push({ id: `call:${id}`, kind: 'call', at, by, attempt, callId: id, name: c.function?.name || 'tool', args: parseArgs(c.function?.arguments), text: describeCall(c) });
|
|
73
76
|
}
|
|
74
77
|
} else if (m.role === 'tool') {
|
|
75
78
|
const c = m.tool_call_id ? calls.get(m.tool_call_id) : null;
|
|
76
|
-
out.push({ kind: 'result', at, by: 'tool', attempt, callId: m.tool_call_id || null, name: c?.function?.name || m.name || 'tool', text: str(m.content), error: /^error[:\s]/i.test(str(m.content)) });
|
|
79
|
+
out.push({ id: `step:${i}`, kind: 'result', at, by: 'tool', attempt, callId: m.tool_call_id || null, name: c?.function?.name || m.name || 'tool', text: str(m.content), error: /^error[:\s]/i.test(str(m.content)) });
|
|
77
80
|
}
|
|
78
81
|
});
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
(Array.isArray(task.handoffs) ? task.handoffs : []).forEach((h, i) => out.push({ id: `handoff:${i}`, kind: 'handoff', at: num(h.at, lastAt), by: h.by || 'person', from: h.from || '', to: h.to || '', text: h.reason || '' }));
|
|
81
84
|
|
|
82
85
|
// The thread's posts — a member's findings, a question, an answer, a decision, the runner's notes.
|
|
83
86
|
const thread = (run?.threads?.threads || []).find((t) => t.taskId === taskId && t.kind === 'task');
|
|
84
|
-
if (thread) for (const p of (run.threads.posts || []).filter((x) => x.threadId === thread.id)) out.push({ kind: 'post', at: num(p.at, lastAt), by: p.by || '', post: p, text: p.text || '' });
|
|
87
|
+
if (thread) for (const p of (run.threads.posts || []).filter((x) => x.threadId === thread.id)) out.push({ id: `post:${p.id}`, kind: 'post', at: num(p.at, lastAt), by: p.by || '', post: p, text: p.text || '' });
|
|
85
88
|
|
|
86
89
|
// What the member is saying right now — the attempt's text before it is a step.
|
|
87
90
|
const lastText = [...out].reverse().find((e) => e.kind === 'text');
|
|
88
|
-
if (task.status === 'running' && task.text && task.text !== lastText?.text) out.push({ kind: 'text', at: num(run?.lastEventAt, lastAt + 1), by, attempt: attemptOf, text: task.text, live: true });
|
|
91
|
+
if (task.status === 'running' && task.text && task.text !== lastText?.text) out.push({ id: 'live', kind: 'text', at: num(run?.lastEventAt, lastAt + 1), by, attempt: attemptOf, text: task.text, live: true });
|
|
89
92
|
|
|
90
93
|
if (task.endedAt || ['ok', 'failed', 'over-budget', 'stopped', 'waiting'].includes(task.status)) {
|
|
91
94
|
// Findings: the task's count, or the finding posts in its thread — a member's board posts
|
|
92
95
|
// count as its answer (team-run.js), and a record folded from an older run has only those.
|
|
93
96
|
const findings = Math.max(num(task.findings, 0), out.filter((e) => e.kind === 'post' && e.post?.kind === 'finding').length);
|
|
94
97
|
const tools = Math.max(num(task.tools, 0), out.filter((e) => e.kind === 'call').length);
|
|
95
|
-
out.push({ kind: 'end', at: num(task.endedAt, num(run?.lastEventAt, lastAt + 2)), by: 'runner', status: task.status, error: task.error || null, ms: num(task.ms, 0), findings, tools, text: endText({ ...task, findings, tools }, attempts) });
|
|
98
|
+
out.push({ id: 'end', kind: 'end', at: num(task.endedAt, num(run?.lastEventAt, lastAt + 2)), by: 'runner', status: task.status, error: task.error || null, ms: num(task.ms, 0), findings, tools, text: endText({ ...task, findings, tools }, attempts) });
|
|
96
99
|
}
|
|
97
100
|
return out.sort((a, b) => a.at - b.at || WORKLOG_KINDS.indexOf(a.kind) - WORKLOG_KINDS.indexOf(b.kind));
|
|
98
101
|
}
|