@chatpanel/events 0.102.0 → 0.103.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/adapters.js +1 -83
- package/adaptive-tool-policy.js +1 -45
- package/agent.js +2 -255
- package/attribution.js +1 -132
- package/backup-envelope.js +1 -221
- package/board-tool.js +2 -165
- package/budget.js +1 -116
- package/capability.js +1 -126
- package/citations.js +5 -127
- package/client-prefs.js +1 -148
- package/context-attachments.js +8 -144
- package/cowriter-router.js +1 -83
- package/cowriter-writer.js +19 -193
- package/cowriter.js +1 -190
- package/curate.js +3 -509
- package/distance.js +1 -124
- package/engine.js +1 -131
- package/entitlement.js +1 -332
- package/entity.js +1 -354
- package/event.js +1 -175
- package/extraction.js +4 -293
- package/failover.js +1 -93
- package/find-tool.js +1 -66
- package/flowchart.js +2 -644
- package/gate.js +1 -74
- package/harness.js +4 -101
- package/index.js +1 -345
- package/invariants.js +1 -174
- package/job.js +3 -147
- package/kernel.js +1 -255
- package/knowledge-derive.js +1 -267
- package/knowledge.js +3 -230
- package/library.js +11 -280
- package/loop.js +1 -132
- package/manifest.js +1 -107
- package/markdown-authoring.js +11 -288
- package/markdown-render.js +0 -0
- package/mcp-client.js +8 -358
- package/mcp-dispatch.js +1 -52
- package/mcp-errors.js +1 -106
- package/mcp-manager.js +1 -127
- package/media-transcript.js +8 -531
- package/meeting-analyzers.js +1 -83
- package/meeting-insights.js +7 -164
- package/meeting-shape.js +1 -282
- package/meeting-text.js +5 -94
- package/memory.js +2 -638
- package/model-candidates.js +1 -358
- package/model-health.js +1 -182
- package/model-ledger.js +1 -228
- package/model-picker.js +1 -188
- package/note-actions.js +15 -246
- package/note-graph.js +1 -158
- package/note-links.js +1 -68
- package/note-mentions.js +8 -114
- package/note-plan.js +9 -107
- package/note-research.js +1 -135
- package/observability.js +1 -119
- package/omni.js +1 -125
- package/order.js +1 -78
- package/package.json +1 -4
- package/pdf-layout.js +7 -253
- package/project-run.js +20 -444
- package/project.js +1 -170
- package/promotion.js +1 -171
- package/queue.js +1 -98
- package/reach.js +1 -23
- package/recipe-tool.js +2 -161
- package/recipe.js +1 -264
- package/record-list.js +2 -110
- package/recruit.js +3 -456
- package/redaction-tokens.js +1 -61
- package/ref.js +1 -55
- package/registry.js +1 -240
- package/route-graph.js +1 -115
- package/route-strategies.js +2 -232
- package/router.js +2 -880
- package/rrf.js +1 -89
- package/rules.js +1 -142
- package/schedule.js +1 -663
- package/scm-connection.js +1 -180
- package/scopes.js +1 -12
- package/scorecard.js +1 -335
- package/search-engines.js +1 -81
- package/skill-manifest.js +1 -330
- package/skill-scan.js +3 -209
- package/skill-sources.js +1 -162
- package/skill-vars.js +2 -252
- package/slash-commands.js +1 -158
- package/source-gate.js +1 -92
- package/sources-retrieval.js +5 -186
- package/sources.js +1 -273
- package/store.js +1 -171
- package/structured.js +4 -901
- package/subject-kinds.js +1 -5
- package/subject-name.js +1 -96
- package/sync-plan.js +1 -213
- package/synthesis.js +3 -123
- package/tags.js +1 -203
- package/team-board.js +6 -337
- package/team-cache.js +2 -63
- package/team-observe.js +1 -118
- package/team-org.js +1 -442
- package/team-plan.js +4 -131
- package/team-record.js +1 -225
- package/team-run.js +9 -652
- package/team-subtask.js +2 -191
- package/team-task.js +2 -124
- package/team-tool.js +2 -196
- package/team-trail.js +2 -73
- package/team-worklog.js +2 -149
- package/team.js +1 -302
- package/text-search.js +1 -155
- package/theme.js +17 -154
- package/titles.js +4 -285
- package/tool-discovery.js +1 -87
- package/tool-dispatch.js +5 -230
- package/tool-groups.js +1 -81
- package/tool-hints.js +10 -185
- package/tool-loop-guard.js +4 -182
- package/tool-need.js +2 -124
- package/tool-result.js +2 -438
- package/tool-round.js +0 -0
- package/tool-schema.js +1 -155
- package/tool-traits.js +1 -182
- package/toolset.js +2 -88
- package/trajectory.js +1 -530
- package/turn-loop.js +4 -440
- package/upcast.js +1 -37
- package/vault.js +2 -250
- package/view.js +1 -88
- package/voice-intents.js +2 -1488
- package/voice-speaker.js +1 -98
- package/weather-tool.js +1 -65
- package/weather.js +2 -211
- package/web-search-tool.js +14 -102
- package/web-search.js +1 -160
- package/widget.js +1 -153
package/gate.js
CHANGED
|
@@ -1,74 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// ChatPanel's own gate is the strictest setting; an organisation that trusts its pool more
|
|
4
|
-
// flips a flag. Nothing in the runner changes: project-run.js reads the gate at every step
|
|
5
|
-
// where it would otherwise ask, and `gateAllows` is the one question it asks. Lives in
|
|
6
|
-
// `.chatpanel/gate.json` in the org repo (pillars §14.3), optionally overridden per project.
|
|
7
|
-
|
|
8
|
-
export const AUTONOMY = Object.freeze(['propose', 'push', 'merge']);
|
|
9
|
-
export const HUMAN_FLAGS = Object.freeze(['merge', 'push', 'publish', 'budgetRaise', 'newAgent', 'newTool', 'writeBack', 'recruit']);
|
|
10
|
-
export const CHECKS = Object.freeze(['guard', 'review', 'tester', 'scan']);
|
|
11
|
-
|
|
12
|
-
/** ChatPanel's own: a branch push is not a release; everything else waits for a person. */
|
|
13
|
-
export const DEFAULT_GATE = Object.freeze({
|
|
14
|
-
autonomy: 'push',
|
|
15
|
-
human: Object.freeze({ merge: true, push: false, publish: true, budgetRaise: true, newAgent: true, newTool: true, writeBack: true, recruit: false }),
|
|
16
|
-
requiredBeforeMerge: Object.freeze(['guard', 'review', 'tester']),
|
|
17
|
-
branches: Object.freeze({ base: 'main', protected: Object.freeze(['main']) }),
|
|
18
|
-
budget: Object.freeze({ perProjectCap: null, perJobCap: null }),
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const isRecord = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
22
|
-
|
|
23
|
-
export function validateGate(g, { partial = false } = {}) {
|
|
24
|
-
const errors = [];
|
|
25
|
-
if (!isRecord(g)) return { ok: false, errors: ['gate must be an object'] };
|
|
26
|
-
if (g.autonomy !== undefined && !AUTONOMY.includes(g.autonomy)) errors.push(`autonomy: one of ${AUTONOMY.join(', ')}`);
|
|
27
|
-
if (g.human !== undefined) {
|
|
28
|
-
if (!isRecord(g.human)) errors.push('human: an object of flags');
|
|
29
|
-
else for (const [k, v] of Object.entries(g.human)) { if (!HUMAN_FLAGS.includes(k)) errors.push(`human.${k}: unknown flag`); else if (typeof v !== 'boolean') errors.push(`human.${k}: true or false`); }
|
|
30
|
-
}
|
|
31
|
-
if (g.requiredBeforeMerge !== undefined && (!Array.isArray(g.requiredBeforeMerge) || g.requiredBeforeMerge.some((c) => !CHECKS.includes(c)))) errors.push(`requiredBeforeMerge: a list of ${CHECKS.join(', ')}`);
|
|
32
|
-
if (g.branches !== undefined && (!isRecord(g.branches) || (g.branches.protected !== undefined && !Array.isArray(g.branches.protected)))) errors.push('branches: { base, protected[] }');
|
|
33
|
-
if (g.budget !== undefined && !isRecord(g.budget)) errors.push('budget: { perProjectCap, perJobCap }');
|
|
34
|
-
if (!partial && g.autonomy === undefined) errors.push('autonomy: required');
|
|
35
|
-
return { ok: errors.length === 0, errors };
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** A gate over the default: a partial gate fills in from ChatPanel's own; a full one stands alone. */
|
|
39
|
-
export function normalizeGate(g, { partial = false, base = DEFAULT_GATE } = {}) {
|
|
40
|
-
const v = validateGate(g || {}, { partial: true });
|
|
41
|
-
if (!v.ok) throw new Error(`gate: ${v.errors.join('; ')}`);
|
|
42
|
-
const src = g || {};
|
|
43
|
-
const b = partial ? base : DEFAULT_GATE;
|
|
44
|
-
return {
|
|
45
|
-
autonomy: AUTONOMY.includes(src.autonomy) ? src.autonomy : b.autonomy,
|
|
46
|
-
human: { ...b.human, ...(isRecord(src.human) ? src.human : {}) },
|
|
47
|
-
requiredBeforeMerge: Array.isArray(src.requiredBeforeMerge) ? [...new Set(src.requiredBeforeMerge)] : [...b.requiredBeforeMerge],
|
|
48
|
-
branches: { base: String(src.branches?.base || b.branches.base), protected: Array.isArray(src.branches?.protected) ? [...new Set(src.branches.protected.map(String))] : [...b.branches.protected] },
|
|
49
|
-
budget: { perProjectCap: src.budget?.perProjectCap ?? b.budget.perProjectCap, perJobCap: src.budget?.perJobCap ?? b.budget.perJobCap },
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** The org's gate with a project's partial one over it. */
|
|
54
|
-
export function effectiveGate(orgGate = null, projectGate = null) {
|
|
55
|
-
const org = normalizeGate(orgGate || {}, { partial: true });
|
|
56
|
-
return projectGate ? normalizeGate(projectGate, { partial: true, base: org }) : org;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* The one question the executive loop asks: may a team do `action` on its own?
|
|
61
|
-
* push · merge · publish · budgetRaise · newAgent · newTool · writeBack · recruit
|
|
62
|
-
* Returns `{ allowed, reason }`; a false answer is where the loop asks a person instead.
|
|
63
|
-
*/
|
|
64
|
-
export function gateAllows(gate, action, { branch = null } = {}) {
|
|
65
|
-
const g = normalizeGate(gate || {}, { partial: true });
|
|
66
|
-
if (action === 'push' || action === 'merge') {
|
|
67
|
-
if (branch && g.branches.protected.includes(branch)) return { allowed: false, reason: `${branch} is protected — a person merges` };
|
|
68
|
-
const far = AUTONOMY.indexOf(g.autonomy);
|
|
69
|
-
if (action === 'push' && far < AUTONOMY.indexOf('push')) return { allowed: false, reason: 'the gate allows proposing only' };
|
|
70
|
-
if (action === 'merge' && far < AUTONOMY.indexOf('merge')) return { allowed: false, reason: `the gate allows up to ${g.autonomy}` };
|
|
71
|
-
}
|
|
72
|
-
if (HUMAN_FLAGS.includes(action) && g.human[action]) return { allowed: false, reason: `a person decides ${action}` };
|
|
73
|
-
return { allowed: true, reason: `the gate allows ${action}` };
|
|
74
|
-
}
|
|
1
|
+
const u=Object.freeze(["propose","push","merge"]),f=Object.freeze(["merge","push","publish","budgetRaise","newAgent","newTool","writeBack","recruit"]),p=Object.freeze(["guard","review","tester","scan"]),d=Object.freeze({autonomy:"push",human:Object.freeze({merge:!0,push:!1,publish:!0,budgetRaise:!0,newAgent:!0,newTool:!0,writeBack:!0,recruit:!1}),requiredBeforeMerge:Object.freeze(["guard","review","tester"]),branches:Object.freeze({base:"main",protected:Object.freeze(["main"])}),budget:Object.freeze({perProjectCap:null,perJobCap:null})}),s=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);function l(e,{partial:o=!1}={}){const r=[];if(!s(e))return{ok:!1,errors:["gate must be an object"]};if(e.autonomy!==void 0&&!u.includes(e.autonomy)&&r.push(`autonomy: one of ${u.join(", ")}`),e.human!==void 0)if(!s(e.human))r.push("human: an object of flags");else for(const[n,t]of Object.entries(e.human))f.includes(n)?typeof t!="boolean"&&r.push(`human.${n}: true or false`):r.push(`human.${n}: unknown flag`);return e.requiredBeforeMerge!==void 0&&(!Array.isArray(e.requiredBeforeMerge)||e.requiredBeforeMerge.some(n=>!p.includes(n)))&&r.push(`requiredBeforeMerge: a list of ${p.join(", ")}`),e.branches!==void 0&&(!s(e.branches)||e.branches.protected!==void 0&&!Array.isArray(e.branches.protected))&&r.push("branches: { base, protected[] }"),e.budget!==void 0&&!s(e.budget)&&r.push("budget: { perProjectCap, perJobCap }"),!o&&e.autonomy===void 0&&r.push("autonomy: required"),{ok:r.length===0,errors:r}}function i(e,{partial:o=!1,base:r=d}={}){const n=l(e||{},{partial:!0});if(!n.ok)throw new Error(`gate: ${n.errors.join("; ")}`);const t=e||{},a=o?r:d;return{autonomy:u.includes(t.autonomy)?t.autonomy:a.autonomy,human:{...a.human,...s(t.human)?t.human:{}},requiredBeforeMerge:Array.isArray(t.requiredBeforeMerge)?[...new Set(t.requiredBeforeMerge)]:[...a.requiredBeforeMerge],branches:{base:String(t.branches?.base||a.branches.base),protected:Array.isArray(t.branches?.protected)?[...new Set(t.branches.protected.map(String))]:[...a.branches.protected]},budget:{perProjectCap:t.budget?.perProjectCap??a.budget.perProjectCap,perJobCap:t.budget?.perJobCap??a.budget.perJobCap}}}function c(e=null,o=null){const r=i(e||{},{partial:!0});return o?i(o,{partial:!0,base:r}):r}function b(e,o,{branch:r=null}={}){const n=i(e||{},{partial:!0});if(o==="push"||o==="merge"){if(r&&n.branches.protected.includes(r))return{allowed:!1,reason:`${r} is protected — a person merges`};const t=u.indexOf(n.autonomy);if(o==="push"&&t<u.indexOf("push"))return{allowed:!1,reason:"the gate allows proposing only"};if(o==="merge"&&t<u.indexOf("merge"))return{allowed:!1,reason:`the gate allows up to ${n.autonomy}`}}return f.includes(o)&&n.human[o]?{allowed:!1,reason:`a person decides ${o}`}:{allowed:!0,reason:`the gate allows ${o}`}}export{u as AUTONOMY,p as CHECKS,d as DEFAULT_GATE,f as HUMAN_FLAGS,c as effectiveGate,b as gateAllows,i as normalizeGate,l as validateGate};
|
package/harness.js
CHANGED
|
@@ -1,101 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// recorded logs and fails the build when reconstruction drifts — the same discipline as
|
|
6
|
-
// the `sync:pii --check` drift guard and the CSP assertion in build-editor.mjs.
|
|
7
|
-
//
|
|
8
|
-
// What it verifies, and what it deliberately does not:
|
|
9
|
-
// • ORDER is reproduced exactly, from (host, seq) and causes, never from a clock.
|
|
10
|
-
// • MODEL-VISIBLE INPUT is reconstructable: every resident Ref resolves by hash.
|
|
11
|
-
// • A Ref whose blob is gone reports VERIFIED-BUT-UNAVAILABLE. That is a PASS, not a
|
|
12
|
-
// failure — crypto-shredding is a feature, and the log still proves what was sent.
|
|
13
|
-
// • A Ref whose source CHANGED reports DRIFTED, and that IS a failure, because the
|
|
14
|
-
// alternative is replay quietly substituting today's note for the one actually sent.
|
|
15
|
-
|
|
16
|
-
import { upcastAll } from './upcast.js';
|
|
17
|
-
import { linearize } from './order.js';
|
|
18
|
-
import { checkInvariants } from './invariants.js';
|
|
19
|
-
import { resolveRef, RESOLUTION } from './ref.js';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param stored events as persisted (any schema version)
|
|
23
|
-
* @param blobs { lookup(ref) } — omit to skip content reconstruction
|
|
24
|
-
* @returns a report; `ok` is the CI signal.
|
|
25
|
-
*/
|
|
26
|
-
export function replay(stored, { blobs = null, invariantOptions = {} } = {}) {
|
|
27
|
-
const events = upcastAll(stored);
|
|
28
|
-
const ordered = linearize(events);
|
|
29
|
-
|
|
30
|
-
// Determinism: linearize is a function of the SET. Feed it back reversed; if the order
|
|
31
|
-
// changes, replay depends on how the log happened to be read off disk.
|
|
32
|
-
const stable = linearize([...events].reverse()).map((e) => e.id).join(',')
|
|
33
|
-
=== ordered.map((e) => e.id).join(',');
|
|
34
|
-
|
|
35
|
-
const violations = checkInvariants(ordered, invariantOptions);
|
|
36
|
-
|
|
37
|
-
const refs = { exact: 0, unavailable: 0, drifted: [] };
|
|
38
|
-
const turns = [];
|
|
39
|
-
if (blobs) {
|
|
40
|
-
for (const e of ordered) {
|
|
41
|
-
// What the model was SHOWN and what it SAID are refs too, and they are the half a
|
|
42
|
-
// reader most wants replayed. Checking only `resident` verified the toolset while
|
|
43
|
-
// leaving the conversation unverified — the part that actually reconstructs a turn.
|
|
44
|
-
if (String(e.type).startsWith('assistant.')) {
|
|
45
|
-
const r = resolveRef(e.payload.ref, (x) => blobs.lookup(x));
|
|
46
|
-
if (r.resolution === RESOLUTION.EXACT) refs.exact++;
|
|
47
|
-
else if (r.resolution === RESOLUTION.UNAVAILABLE) refs.unavailable++;
|
|
48
|
-
else refs.drifted.push({ eventId: e.id, ref: r.ref, actualHash: r.actualHash });
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (e.type !== 'context.assembled') continue;
|
|
52
|
-
const resolved = e.payload.resident.map((ref) => resolveRef(ref, (r) => blobs.lookup(r)));
|
|
53
|
-
for (const r of resolved) {
|
|
54
|
-
if (r.resolution === RESOLUTION.EXACT) refs.exact++;
|
|
55
|
-
else if (r.resolution === RESOLUTION.UNAVAILABLE) refs.unavailable++;
|
|
56
|
-
else refs.drifted.push({ eventId: e.id, ref: r.ref, actualHash: r.actualHash });
|
|
57
|
-
}
|
|
58
|
-
turns.push({
|
|
59
|
-
turnId: e.payload.turnId,
|
|
60
|
-
budget: e.payload.budget,
|
|
61
|
-
used: e.payload.used,
|
|
62
|
-
parts: e.payload.parts,
|
|
63
|
-
reconstructable: resolved.every((r) => r.resolution !== RESOLUTION.DRIFTED),
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
ok: stable && violations.length === 0 && refs.drifted.length === 0,
|
|
70
|
-
events: ordered.length,
|
|
71
|
-
stable,
|
|
72
|
-
violations,
|
|
73
|
-
refs,
|
|
74
|
-
turns,
|
|
75
|
-
order: ordered.map((e) => e.id),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** One-line CI summary. */
|
|
80
|
-
export function formatReport(report) {
|
|
81
|
-
const lines = [
|
|
82
|
-
`${report.ok ? 'PASS' : 'FAIL'} — ${report.events} events`,
|
|
83
|
-
` order stable ${report.stable ? 'yes' : 'NO — replay is order-dependent'}`,
|
|
84
|
-
` invariants ${report.violations.length === 0 ? 'I1-I6 hold' : `${report.violations.length} violation(s)`}`,
|
|
85
|
-
];
|
|
86
|
-
for (const v of report.violations) lines.push(` ${v.invariant} ${v.eventId || ''} ${v.message}`);
|
|
87
|
-
if (report.refs.exact || report.refs.unavailable || report.refs.drifted.length) {
|
|
88
|
-
lines.push(` refs ${report.refs.exact} exact · ${report.refs.unavailable} shredded/evicted · ${report.refs.drifted.length} DRIFTED`);
|
|
89
|
-
}
|
|
90
|
-
for (const d of report.refs.drifted) lines.push(` drifted ${d.ref.kind}:${d.ref.id} — the source changed since capture`);
|
|
91
|
-
return lines.join('\n');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** Parse a JSONL log. Blank lines ignored so a truncated export still loads. */
|
|
95
|
-
export function parseJsonl(text) {
|
|
96
|
-
return String(text).split('\n').map((l) => l.trim()).filter(Boolean).map((l) => JSON.parse(l));
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function toJsonl(events) {
|
|
100
|
-
return events.map((e) => JSON.stringify(e)).join('\n');
|
|
101
|
-
}
|
|
1
|
+
import{upcastAll as m}from"./upcast.js";import{linearize as v}from"./order.js";import{checkInvariants as g}from"./invariants.js";import{resolveRef as h,RESOLUTION as r}from"./ref.js";function A(e,{blobs:n=null,invariantOptions:a={}}={}){const d=m(e),o=v(d),f=v([...d].reverse()).map(t=>t.id).join(",")===o.map(t=>t.id).join(","),u=g(o,a),i={exact:0,unavailable:0,drifted:[]},c=[];if(n)for(const t of o){if(String(t.type).startsWith("assistant.")){const s=h(t.payload.ref,l=>n.lookup(l));s.resolution===r.EXACT?i.exact++:s.resolution===r.UNAVAILABLE?i.unavailable++:i.drifted.push({eventId:t.id,ref:s.ref,actualHash:s.actualHash});continue}if(t.type!=="context.assembled")continue;const p=t.payload.resident.map(s=>h(s,l=>n.lookup(l)));for(const s of p)s.resolution===r.EXACT?i.exact++:s.resolution===r.UNAVAILABLE?i.unavailable++:i.drifted.push({eventId:t.id,ref:s.ref,actualHash:s.actualHash});c.push({turnId:t.payload.turnId,budget:t.payload.budget,used:t.payload.used,parts:t.payload.parts,reconstructable:p.every(s=>s.resolution!==r.DRIFTED)})}return{ok:f&&u.length===0&&i.drifted.length===0,events:o.length,stable:f,violations:u,refs:i,turns:c,order:o.map(t=>t.id)}}function b(e){const n=[`${e.ok?"PASS":"FAIL"} — ${e.events} events`,` order stable ${e.stable?"yes":"NO — replay is order-dependent"}`,` invariants ${e.violations.length===0?"I1-I6 hold":`${e.violations.length} violation(s)`}`];for(const a of e.violations)n.push(` ${a.invariant} ${a.eventId||""} ${a.message}`);(e.refs.exact||e.refs.unavailable||e.refs.drifted.length)&&n.push(` refs ${e.refs.exact} exact · ${e.refs.unavailable} shredded/evicted · ${e.refs.drifted.length} DRIFTED`);for(const a of e.refs.drifted)n.push(` drifted ${a.ref.kind}:${a.ref.id} — the source changed since capture`);return n.join(`
|
|
2
|
+
`)}function E(e){return String(e).split(`
|
|
3
|
+
`).map(n=>n.trim()).filter(Boolean).map(n=>JSON.parse(n))}function S(e){return e.map(n=>JSON.stringify(n)).join(`
|
|
4
|
+
`)}export{b as formatReport,E as parseJsonl,A as replay,S as toJsonl};
|