@chatpanel/events 0.75.0 โ 0.77.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/index.js +2 -1
- package/package.json +3 -1
- package/slash-commands.js +23 -1
- package/team-run.js +6 -2
- package/team-tool.js +1 -1
- package/team-trail.js +37 -0
package/index.js
CHANGED
|
@@ -197,6 +197,7 @@ export { fixedPlan, parsePlan, plannerPrompt, waves, breakCycles, TEAM_PLAN_SCHE
|
|
|
197
197
|
export { createBoard, parseFindings, boardText, findingsInstruction, toBriefClaims, FINDINGS_SCHEMA, FINDING_KINDS } from './team-board.js';
|
|
198
198
|
export { runTeam, dryRunTeam, TeamRunError, RUN_STATUSES } from './team-run.js';
|
|
199
199
|
export { teamToolProvider, teamToolSpec, describeTeamForApproval, TEAM_TOOL_NAME } from './team-tool.js';
|
|
200
|
+
export { teamLine, teamLanes } from './team-trail.js';
|
|
200
201
|
export { mcpDispatchProvider, MCP_TOOL_NAME } from './mcp-dispatch.js';
|
|
201
202
|
export { createManifest, ManifestError, SOURCES } from './manifest.js';
|
|
202
203
|
export { createKernel, meetDecisions, KernelError, REQUIRED_PLUGINS, ALLOW_ALL } from './kernel.js';
|
|
@@ -213,7 +214,7 @@ export { SOURCE_TRUST, SkillSourceError, defineSkillSource, createSkillSourceReg
|
|
|
213
214
|
export { SKILL_MANIFEST_VERSION, SKILL_CONTEXTS, SKILL_HISTORY_SCOPES, SKILL_MCP_MODES, SKILL_TRUST, SKILL_FILE_KINDS, SKILL_UPCASTERS, SkillManifestError, isSafeSkillPath, originOf, trustOf, skillFiles, needsBridge, declaredAccess, originLabel, sameSkillOrigin, skillIsStale, validateSkill, upcastSkill, upcastSkills, normalizeSkill } from './skill-manifest.js';
|
|
214
215
|
export { SKILL_VARS, SKILL_VAR_NAMES, skillVar, skillVarPattern, parseSkillVars, lintSkillPrompt, suggestSkillVar, substituteSkillVars, expandSkillPrompt, skillVarGuidance, SkillVarError } from './skill-vars.js';
|
|
215
216
|
export { lineAt, writerAffordance, INSTRUCTION_RE, instructionOnLine, GOAL_MIN_NEW, goalDraftAllowed, createSpendMeter, writerTail, draftSeparator, groundingBlock, writerRequest, AUTOCOMPLETE_SYSTEM, AUTOCOMPLETE_MAX_TOKENS, AUTOCOMPLETE_TEMPERATURE, clipCompletion, GEARS, WRITER_PREFS, WRITER_PREF_DEFAULTS, normalizeWriterPrefs, normalizeIntent } from './cowriter-writer.js';
|
|
216
|
-
export { SLASH_TYPING_RE, enabledSkills, slashCommandItems, matchSlashSkill, matchSlashRecipe, recipeInvocationText, slashCommandInsert, skillInvocationOf, skillInvocationLabel } from './slash-commands.js';
|
|
217
|
+
export { SLASH_TYPING_RE, enabledSkills, slashCommandItems, matchSlashSkill, matchSlashRecipe, recipeInvocationText, matchSlashTeam, teamInvocationText, slashCommandInsert, skillInvocationOf, skillInvocationLabel } from './slash-commands.js';
|
|
217
218
|
export { outlineOf, parseListItem, continueList, indentSelection, toggleWrap, toggleLinePrefix, toggleTask, toggleLink, docStats, selectionStats } from './markdown-authoring.js';
|
|
218
219
|
export {
|
|
219
220
|
MAX_TAG_LENGTH, MAX_TAGS, normalizeTag, normalizeTags, hasTag, addTag, removeTag, toggleTag,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/events",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.77.0",
|
|
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",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"./team-plan.js": "./team-plan.js",
|
|
94
94
|
"./team-run.js": "./team-run.js",
|
|
95
95
|
"./team-tool.js": "./team-tool.js",
|
|
96
|
+
"./team-trail.js": "./team-trail.js",
|
|
96
97
|
"./team.js": "./team.js",
|
|
97
98
|
"./text-search.js": "./text-search.js",
|
|
98
99
|
"./theme.js": "./theme.js",
|
|
@@ -207,6 +208,7 @@
|
|
|
207
208
|
"team-plan.js",
|
|
208
209
|
"team-run.js",
|
|
209
210
|
"team-tool.js",
|
|
211
|
+
"team-trail.js",
|
|
210
212
|
"team.js",
|
|
211
213
|
"text-search.js",
|
|
212
214
|
"theme.js",
|
package/slash-commands.js
CHANGED
|
@@ -37,6 +37,12 @@ function recipeItem(recipe) {
|
|
|
37
37
|
return { type: 'recipe', command: recipe.name || '', icon: '๐งฉ', description: recipe.description || 'Saved recipe', recipe };
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// A saved TEAM answers to a slash the same way: `/research <request>` is a request to run
|
|
41
|
+
// it, and the `team` tool does the rest.
|
|
42
|
+
function teamItem(team) {
|
|
43
|
+
return { type: 'team', command: team.name || '', icon: '๐งโ๐คโ๐ง', description: team.description || 'Agent team', team };
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
/** Skills that are switched on. Absence of the flag means enabled (older records have none). */
|
|
41
47
|
export function enabledSkills(skills) {
|
|
42
48
|
return (Array.isArray(skills) ? skills : []).filter((s) => !!s && s.enabled !== false);
|
|
@@ -58,6 +64,7 @@ export function slashCommandItems({
|
|
|
58
64
|
builtins = [],
|
|
59
65
|
skills = [],
|
|
60
66
|
recipes = [],
|
|
67
|
+
teams = [],
|
|
61
68
|
prefix = '',
|
|
62
69
|
skillsAllowed = false,
|
|
63
70
|
features = {},
|
|
@@ -70,7 +77,8 @@ export function slashCommandItems({
|
|
|
70
77
|
}));
|
|
71
78
|
const skillItems = skillsAllowed ? enabledSkills(skills).map(skillItem) : [];
|
|
72
79
|
const recipeItems = (recipes || []).filter((r) => r && r.enabled !== false && r.name).map(recipeItem);
|
|
73
|
-
|
|
80
|
+
const teamItems = (teams || []).filter((t) => t && t.enabled !== false && t.name).map(teamItem);
|
|
81
|
+
return [...own, ...skillItems, ...recipeItems, ...teamItems]
|
|
74
82
|
.filter((item) => item.command && item.command.toLowerCase().startsWith(normalized))
|
|
75
83
|
.slice(0, 12);
|
|
76
84
|
}
|
|
@@ -100,6 +108,20 @@ export function recipeInvocationText(recipe, args = '') {
|
|
|
100
108
|
return `Run the saved recipe "${recipe.name}"${a ? ` with this input: ${a}` : ''}. Use the recipe tool; if a parameter is missing, ask for it.`;
|
|
101
109
|
}
|
|
102
110
|
|
|
111
|
+
/** "/research compare A and B" โ the team, and the rest of the line as its request. */
|
|
112
|
+
export function matchSlashTeam(text, teams = []) {
|
|
113
|
+
const m = /^\/([a-z0-9_-]+)\s*([\s\S]*)$/i.exec(String(text || ''));
|
|
114
|
+
if (!m) return null;
|
|
115
|
+
const team = (teams || []).find((t) => t && t.enabled !== false && String(t.name || '').toLowerCase() === m[1].toLowerCase());
|
|
116
|
+
return team ? { team, args: m[2].trim() } : null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** What the model receives for a team command: a request to run it, never a prompt expansion. */
|
|
120
|
+
export function teamInvocationText(team, args = '') {
|
|
121
|
+
const a = String(args || '').trim();
|
|
122
|
+
return `Run the saved team "${team.name}"${a ? ` on this request: ${a}` : ''}. Use the team tool; if the request is unclear, ask first.`;
|
|
123
|
+
}
|
|
124
|
+
|
|
103
125
|
export function slashCommandInsert(item) {
|
|
104
126
|
return item?.command ? `/${item.command} ` : '/';
|
|
105
127
|
}
|
package/team-run.js
CHANGED
|
@@ -48,7 +48,9 @@ export function dryRunTeam(team, request, { appoint = null } = {}) {
|
|
|
48
48
|
const t = normalizeTeam(team);
|
|
49
49
|
const roles = t.roles.map((r) => {
|
|
50
50
|
const a = appoint ? appoint(r) : null;
|
|
51
|
-
|
|
51
|
+
// `model` is what callModel will be handed (a target id in a client that resolves ids);
|
|
52
|
+
// `label` is what a person should read โ the appointer says which, when it knows.
|
|
53
|
+
return { id: r.id, name: r.name, mode: r.mode, prefer: r.prefer, model: a?.model || r.model || null, label: a?.label || a?.model || r.model || null, appointed: !!(a?.model || r.model), grants: r.grants, ...(r.recipe ? { recipe: r.recipe } : {}) };
|
|
52
54
|
});
|
|
53
55
|
const missing = roles.filter((r) => r.mode !== 'recipe' && !r.appointed).map((r) => r.id);
|
|
54
56
|
return {
|
|
@@ -137,9 +139,11 @@ export async function runTeam({
|
|
|
137
139
|
if (!budget.canAfford({ tokens: 0 })) { overBudget = true; throw new Error('over budget'); }
|
|
138
140
|
const prior = boardText(board.all(), { taskIds: task.dependsOn?.length ? task.dependsOn : null });
|
|
139
141
|
const prompt = [task.prompt, prior, findingsInstruction()].filter(Boolean).join('\n\n');
|
|
142
|
+
// A host may build a toolset asynchronously (connecting MCP servers takes time).
|
|
143
|
+
const tools = await toolsFor(role);
|
|
140
144
|
const res = await callModel({
|
|
141
145
|
runId: id, taskId: task.id, role: role.id, model: m.model, mode: m.mode || role.mode,
|
|
142
|
-
system: role.prompt, prompt, tools
|
|
146
|
+
system: role.prompt, prompt, tools, signal,
|
|
143
147
|
onDelta: (delta, full) => say('task.delta', { taskId: task.id, role: role.id, delta, text: full }),
|
|
144
148
|
});
|
|
145
149
|
usage = res?.usage || null;
|
package/team-tool.js
CHANGED
|
@@ -49,7 +49,7 @@ export function teamToolSpec(teams) {
|
|
|
49
49
|
/** The card a person approves a new team on. */
|
|
50
50
|
export function describeTeamForApproval(team, dry) {
|
|
51
51
|
const lines = [`${team.name}${team.description ? ` โ ${team.description}` : ''}`, `Plan: ${team.plan || 'fixed'} ยท merge: ${team.merge || 'concat'}${team.judge ? ` (judge: ${team.judge})` : ''}`];
|
|
52
|
-
for (const r of dry?.roles || team.roles || []) lines.push(`โข ${describeRole({ ...r, model: r.model || undefined })}${r.appointed === false ? ' โ NO MODEL AVAILABLE' : ''}`);
|
|
52
|
+
for (const r of dry?.roles || team.roles || []) lines.push(`โข ${describeRole({ ...r, model: r.label || r.model || undefined })}${r.appointed === false ? ' โ NO MODEL AVAILABLE' : ''}`);
|
|
53
53
|
const b = team.budget || {};
|
|
54
54
|
lines.push(`Budget: ${Object.entries(b).map(([k, v]) => `${k} ${v}`).join(' ยท ')}`);
|
|
55
55
|
lines.push('Runs go through your own models and tools; a team may not act on a page. Nothing a team produces lands without you.');
|
package/team-trail.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// A team run as a trail reads it: one line per event in the trail's own vocabulary, and
|
|
2
|
+
// the run's lanes โ one per task โ folded from the same events. Both clients draw a run
|
|
3
|
+
// from these; neither decides for itself what "task.done" means in words. The event
|
|
4
|
+
// vocabulary is team-run.js's `emit`; the lanes are what a pane, a card or a phone renders.
|
|
5
|
+
|
|
6
|
+
/** One trail line per team event, in the trail's own vocabulary. */
|
|
7
|
+
export function teamLine(ev) {
|
|
8
|
+
const role = ev.role ? `${ev.role}` : 'team';
|
|
9
|
+
switch (ev.type) {
|
|
10
|
+
case 'run.started': return { type: 'status', text: `team ${ev.team}: ${(ev.roles || []).join(', ')}` };
|
|
11
|
+
case 'plan.ready': return { type: 'status', text: `plan: ${(ev.tasks || []).length} task${(ev.tasks || []).length === 1 ? '' : 's'} (${ev.by})` };
|
|
12
|
+
case 'task.started': return { type: 'tool', name: role, text: `${role} ยท ${ev.title || ev.taskId}` };
|
|
13
|
+
case 'task.tool': return { type: 'tool', name: ev.name, text: `${role} ran ${ev.name}${ev.text ? ` โ ${ev.text}` : ''}` };
|
|
14
|
+
case 'task.finding': return { type: 'status', text: `${role}: ${String(ev.finding?.text || '').slice(0, 140)}` };
|
|
15
|
+
case 'task.done': return { type: 'status', text: `${role} done ยท ${ev.findings || 0} finding${ev.findings === 1 ? '' : 's'}` };
|
|
16
|
+
case 'task.failed': return { type: 'error', text: `${role} ${ev.status || 'failed'}${ev.error ? ` โ ${ev.error}` : ''}` };
|
|
17
|
+
case 'run.merging': return { type: 'status', text: `merging (${ev.policy})` };
|
|
18
|
+
case 'run.done': return { type: 'status', text: `team ${ev.status}${ev.usage?.spent?.tokens ? ` ยท ${ev.usage.spent.tokens} tokens` : ''}` };
|
|
19
|
+
default: return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The run's lanes โ one per task โ folded from its events, for the pane. */
|
|
24
|
+
export function teamLanes(prev, ev) {
|
|
25
|
+
const lanes = prev ? { ...prev, tasks: { ...prev.tasks } } : { runId: ev.runId, team: '', status: 'running', tasks: {}, findings: 0 };
|
|
26
|
+
switch (ev.type) {
|
|
27
|
+
case 'run.started': lanes.team = ev.team; lanes.roles = ev.roles; break;
|
|
28
|
+
case 'plan.ready': for (const t of ev.tasks || []) lanes.tasks[t.id] = { id: t.id, role: t.role, title: t.title, status: 'pending', findings: 0 }; break;
|
|
29
|
+
case 'task.started': lanes.tasks[ev.taskId] = { ...(lanes.tasks[ev.taskId] || { id: ev.taskId, role: ev.role, title: ev.title }), status: 'running' }; break;
|
|
30
|
+
case 'task.delta': if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], text: ev.text }; break;
|
|
31
|
+
case 'task.finding': lanes.findings += 1; if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], findings: (lanes.tasks[ev.taskId].findings || 0) + 1 }; break;
|
|
32
|
+
case 'task.done': case 'task.failed': if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], status: ev.status || 'ok', ms: ev.ms }; break;
|
|
33
|
+
case 'run.done': lanes.status = ev.status; lanes.usage = ev.usage; break;
|
|
34
|
+
default: break;
|
|
35
|
+
}
|
|
36
|
+
return lanes;
|
|
37
|
+
}
|