@staix/agent-hub 0.12.23 → 0.12.25
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/CHANGELOG.md +109 -1
- package/README.md +8 -3
- package/docs/addons/claude-mem.md +24 -0
- package/docs/addons/codex-plugin.md +8 -0
- package/docs/addons/dot-admit.md +8 -0
- package/docs/addons/open-code-review.md +8 -0
- package/docs/addons/ponytail.md +23 -0
- package/docs/addons/ripwire.md +22 -0
- package/docs/agent-notes/README.md +5 -0
- package/docs/agent-notes/adapters.md +10 -1
- package/docs/agent-notes/bus.md +3 -1
- package/docs/agent-notes/daemon.md +7 -1
- package/docs/agent-notes/local-worker.md +4 -2
- package/docs/agent-notes/tasks.md +8 -0
- package/docs/agent-notes/tests.md +5 -1
- package/docs/bench.md +28 -3
- package/docs/cooperbench.md +4 -0
- package/docs/data-policy.md +36 -0
- package/docs/events.md +3 -0
- package/docs/gsd-collaboration-analysis.md +48 -0
- package/docs/memory.md +231 -0
- package/docs/operations.md +666 -19
- package/docs/plans/2026-10-11-issues-109-sequential.md +81 -0
- package/docs/plans/2026-10-11-routing-evaluation-proposal.md +30 -0
- package/docs/profiles.md +57 -0
- package/docs/quickstart.md +2 -2
- package/docs/research.md +31 -1
- package/docs/roles.md +85 -0
- package/docs/sdlc.md +170 -0
- package/docs/security.md +111 -4
- package/docs/smoke.md +288 -0
- package/docs/specs/2026-09-19-agent-hub-design.md +633 -7
- package/docs/specs/2026-10-12-backlog-implementation-plan.md +186 -0
- package/docs/specs/2026-10-12-office-view-design.md +212 -0
- package/docs/text-projection.md +19 -0
- package/docs/verification/2026-10-11-acp-watch-t0.md +33 -0
- package/docs/verification/2026-10-11-agent-config-inventory.md +20 -0
- package/docs/verification/2026-10-11-jcode-peer-contract.md +27 -0
- package/docs/verification/2026-10-13-0.12.24.md +94 -0
- package/docs/verification/2026-10-13-board-phone.md +31 -0
- package/docs/verification/2026-10-13-fsmonitor-fixture-attribution.md +19 -0
- package/docs/verification/2026-10-14-0.12.24-audit.md +123 -0
- package/docs/verification/2026-10-14-0.12.25.md +27 -0
- package/docs/verified.json +22 -13
- package/package.json +2 -1
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/ROLE-NOTICE.md +26 -0
- package/plugins/agent-hub/server.js +1175 -339
- package/scripts/check-docs.mjs +129 -0
- package/src/adapters/acp.ts +112 -13
- package/src/adapters/claude-channel.ts +48 -11
- package/src/adapters/codex-appserver.ts +11 -0
- package/src/adapters/jcode.ts +110 -0
- package/src/adapters/local-worker.ts +10 -7
- package/src/adapters/pi.ts +171 -23
- package/src/cli/attention.ts +60 -0
- package/src/cli/bench.ts +24 -5
- package/src/cli/board-read.ts +12 -0
- package/src/cli/console-state.ts +103 -17
- package/src/cli/console.ts +54 -8
- package/src/cli/facts-hook.ts +12 -4
- package/src/cli/help.ts +35 -9
- package/src/cli/identity.ts +18 -7
- package/src/cli/init.ts +48 -10
- package/src/cli/jcode-mcp.ts +58 -0
- package/src/cli/kimi-mcp.ts +53 -0
- package/src/cli/launch.ts +16 -1
- package/src/cli/main.ts +392 -57
- package/src/cli/memory.ts +193 -0
- package/src/cli/output.ts +45 -4
- package/src/cli/pet-config.ts +1 -0
- package/src/cli/pet.ts +83 -0
- package/src/cli/preview.ts +38 -5
- package/src/cli/status-lines.ts +1 -1
- package/src/cli/tail-render.ts +1 -0
- package/src/cli/upgrade-runtime.ts +32 -3
- package/src/cli/watch.ts +31 -0
- package/src/hub/activity.ts +53 -0
- package/src/hub/ask.ts +10 -5
- package/src/hub/bench.ts +10 -3
- package/src/hub/board.ts +222 -16
- package/src/hub/bus.ts +48 -9
- package/src/hub/citations.ts +7 -0
- package/src/hub/conductor.ts +12 -7
- package/src/hub/config-trust.ts +4 -2
- package/src/hub/crash.ts +9 -0
- package/src/hub/daemon.ts +914 -120
- package/src/hub/delivery-journal.ts +5 -0
- package/src/hub/envelope.ts +1 -1
- package/src/hub/events.ts +12 -2
- package/src/hub/facts.ts +26 -7
- package/src/hub/git.ts +8 -2
- package/src/hub/github-import.ts +28 -0
- package/src/hub/hub-tools.ts +49 -10
- package/src/hub/inference.ts +1 -1
- package/src/hub/lifecycle-schema.ts +17 -0
- package/src/hub/listen.ts +15 -0
- package/src/hub/manager.ts +12 -5
- package/src/hub/path-policy.ts +115 -0
- package/src/hub/peer-catalog.ts +28 -0
- package/src/hub/permission-mode.ts +19 -5
- package/src/hub/planning.ts +70 -0
- package/src/hub/profiles.ts +74 -0
- package/src/hub/projected-diff.ts +73 -0
- package/src/hub/projection-exec.ts +24 -0
- package/src/hub/research.ts +144 -21
- package/src/hub/roles.ts +123 -0
- package/src/hub/roster.ts +23 -0
- package/src/hub/routing.ts +18 -5
- package/src/hub/sdlc-queue.ts +112 -0
- package/src/hub/sdlc-release.ts +125 -0
- package/src/hub/sdlc.ts +250 -0
- package/src/hub/settings.ts +34 -15
- package/src/hub/shipped-roles.ts +25 -0
- package/src/hub/snapshots.ts +89 -15
- package/src/hub/start-mode.ts +7 -5
- package/src/hub/supervision.ts +1 -0
- package/src/hub/task-sweep.ts +1 -1
- package/src/hub/tasks.ts +905 -89
- package/src/hub/text-projection.ts +151 -0
- package/src/hub/tooling.ts +170 -0
- package/src/hub/ui.ts +16 -2
- package/src/hub/workflow.ts +71 -0
- package/src/local/sandbox.ts +6 -4
- package/src/local/tools.ts +11 -6
- package/src/memory/brief.ts +28 -14
- package/src/memory/import.ts +55 -0
- package/src/memory/recall.ts +84 -0
- package/src/memory/store.ts +757 -0
- package/src/memory/sync.ts +145 -0
- package/src/pet/NOTICE.md +10 -0
- package/src/pet/characters.ts +1438 -0
- package/src/pet/config.ts +31 -0
- package/src/pet/frame.ts +17 -0
- package/src/pet/pixels.ts +28 -0
- package/src/pi/extension.ts +40 -5
- package/src/role-text.d.ts +1 -0
- package/src/ui/index.html +843 -46
- package/src/ui/needs.ts +58 -0
- package/src/ui/office-model.ts +440 -0
- package/src/ui/peer-palette.ts +16 -0
- package/src/ui/task-board.ts +49 -0
- package/src/ui/task-progress.ts +5 -1
- package/templates/AGENTS.block.md +3 -2
- package/templates/config.json +5 -1
- package/templates/profiles/dev.json +22 -0
- package/templates/profiles/general.json +26 -0
- package/templates/profiles/research.json +57 -0
- package/templates/profiles/writing.json +28 -0
- package/templates/roles/NOTICE.md +26 -0
- package/templates/roles/dev/backend-engineer.md +26 -0
- package/templates/roles/dev/code-reviewer.md +26 -0
- package/templates/roles/dev/frontend-engineer.md +26 -0
- package/templates/roles/dev/security-reviewer.md +26 -0
- package/templates/roles/dev/software-architect.md +26 -0
- package/templates/roles/dev/test-engineer.md +26 -0
- package/templates/roles/research/analyst.md +26 -0
- package/templates/roles/research/fact-checker.md +26 -0
- package/templates/roles/research/research-lead.md +26 -0
- package/templates/roles/research/researcher.md +26 -0
- package/templates/roles/research/statistician.md +26 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { characterId, type CharacterId, type PetSize, type PetGlyphs } from "./frame.ts";
|
|
4
|
+
|
|
5
|
+
export interface PetConfig { enabled: boolean; blink: boolean; bell: boolean; character?: CharacterId; size?: PetSize; glyphs?: PetGlyphs; notice?: string }
|
|
6
|
+
/** Console-local presentation only; this reader never writes config or grants authority. */
|
|
7
|
+
export function loadPetConfig(cwd: string): PetConfig {
|
|
8
|
+
let value: unknown;
|
|
9
|
+
for (const name of ["config.json", "config.local.json"]) {
|
|
10
|
+
try {
|
|
11
|
+
const file = JSON.parse(readFileSync(join(cwd, ".agenthub", name), "utf8"));
|
|
12
|
+
if (file.pet !== undefined) value = value && typeof value === "object" && file.pet && typeof file.pet === "object" ? { ...value, ...file.pet } : file.pet;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (value === false) return { enabled: false, blink: true, bell: false };
|
|
18
|
+
const defaults = { enabled: true, blink: true, bell: false };
|
|
19
|
+
if (value === undefined) return defaults;
|
|
20
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { ...defaults, notice: "Unknown pet configuration; using stai line defaults." };
|
|
21
|
+
const row = value as Record<string, unknown>;
|
|
22
|
+
const invalid = Object.keys(row).some(key => !["character", "size", "glyphs", "blink", "bell"].includes(key)) ||
|
|
23
|
+
row.character !== undefined && !characterId(row.character) || row.size !== undefined && !["line", "mini", "full"].includes(row.size as string) ||
|
|
24
|
+
row.glyphs !== undefined && (typeof row.glyphs !== "string" || !["auto", "ascii", "blocks"].includes(row.glyphs)) ||
|
|
25
|
+
row.blink !== undefined && typeof row.blink !== "boolean" || row.bell !== undefined && typeof row.bell !== "boolean";
|
|
26
|
+
return { enabled: true, blink: typeof row.blink === "boolean" ? row.blink : true, bell: typeof row.bell === "boolean" ? row.bell : false,
|
|
27
|
+
...(characterId(row.character) && row.character !== "stai" ? { character: row.character } : {}),
|
|
28
|
+
...(row.size === "mini" || row.size === "full" ? { size: row.size } : {}),
|
|
29
|
+
...(row.glyphs === "ascii" || row.glyphs === "blocks" ? { glyphs: row.glyphs } : {}),
|
|
30
|
+
...(invalid ? { notice: "Unknown pet option; using stai line defaults for that option." } : {}) };
|
|
31
|
+
}
|
package/src/pet/frame.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CHARACTERS, CHARACTER_IDS, type CharacterId, type PetGlyphs, type PetPose, type PetSize } from "./characters.ts";
|
|
2
|
+
export { CHARACTERS, CHARACTER_IDS };
|
|
3
|
+
export type { CharacterId, PetGlyphs, PetPose, PetSize };
|
|
4
|
+
export function characterId(value: unknown): value is CharacterId { return typeof value === "string" && (CHARACTER_IDS as readonly string[]).includes(value); }
|
|
5
|
+
export function petSize(requested: PetSize = "line", columns: number, rows: number): PetSize {
|
|
6
|
+
if (requested === "full" && columns >= 100 && rows >= 40) return "full";
|
|
7
|
+
return requested !== "line" && columns >= 100 ? "mini" : "line";
|
|
8
|
+
}
|
|
9
|
+
export function petGlyphs(requested: PetGlyphs = "auto", env: Record<string, string | undefined> = process.env): "ascii" | "blocks" {
|
|
10
|
+
const locale = env.LC_ALL || env.LC_CTYPE || env.LANG || "";
|
|
11
|
+
return requested !== "ascii" && /utf-?8/i.test(locale) && !!env.TERM && !["dumb", "linux"].includes(env.TERM) ? "blocks" : "ascii";
|
|
12
|
+
}
|
|
13
|
+
export function petFrame(character: CharacterId = "stai", pose: PetPose, size: PetSize = "line", glyphs: "ascii" | "blocks" = "ascii"): readonly string[] {
|
|
14
|
+
return CHARACTERS[character].frames[glyphs][pose][size];
|
|
15
|
+
}
|
|
16
|
+
/** A full footer reserves the catalog maximum, independent of state and session character cycling. */
|
|
17
|
+
export function petFooterRows(size: PetSize): number { return size === "full" ? 9 : 4; }
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Self-contained glyph pixels for the shared literal frame data; browser injection needs no font/image decoder. */
|
|
2
|
+
export function petPixels(frame: readonly string[]): { width: number; height: number; pixels: [number, number][] } {
|
|
3
|
+
const font: Record<string, string[]> = {
|
|
4
|
+
O:["01110","10001","10001","10001","10001","10001","01110"],
|
|
5
|
+
o:["00000","00000","01110","10001","10001","01110","00000"],
|
|
6
|
+
X:["10001","10001","01010","00100","01010","10001","10001"],
|
|
7
|
+
S:["01111","10000","10000","01110","00001","00001","11110"],
|
|
8
|
+
T:["11111","00100","00100","00100","00100","00100","00100"],
|
|
9
|
+
A:["01110","10001","10001","11111","10001","10001","10001"],
|
|
10
|
+
I:["11111","00100","00100","00100","00100","00100","11111"],
|
|
11
|
+
">": ["10000","01000","00100","00010","00100","01000","10000"],
|
|
12
|
+
"<": ["00001","00010","00100","01000","00100","00010","00001"],
|
|
13
|
+
"^": ["00100","01010","10001"],
|
|
14
|
+
"~": ["00000","01001","10110"],
|
|
15
|
+
"/": ["00001","00001","00010","00100","01000","10000","10000"],
|
|
16
|
+
"\\": ["10000","10000","01000","00100","00010","00001","00001"],
|
|
17
|
+
"-": ["00000","00000","00000","11111"],
|
|
18
|
+
"'": ["00100","00100"],
|
|
19
|
+
};
|
|
20
|
+
const pixels: [number, number][] = [];
|
|
21
|
+
for (const [row, text] of frame.entries()) for (const [column, glyph] of [...text].entries()) {
|
|
22
|
+
for (let y=0;y<8;y++) for (let x=0;x<5;x++) {
|
|
23
|
+
const on = glyph === "█" || glyph === "▀" && y<4 || glyph === "▄" && y>=4 || glyph === "▟" && (y>=4 || x>=2) || glyph === "▙" && (y>=4 || x<3) || font[glyph]?.[y]?.[x] === "1";
|
|
24
|
+
if (on) pixels.push([column*5+x,row*8+y]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return { width: Math.max(0,...frame.map(row=>[...row].length))*5, height: frame.length*8, pixels };
|
|
28
|
+
}
|
package/src/pi/extension.ts
CHANGED
|
@@ -23,6 +23,9 @@ let shellSeq = 0;
|
|
|
23
23
|
let forcedFailure = "";
|
|
24
24
|
let turnGeneration = 0;
|
|
25
25
|
let sessionId = "";
|
|
26
|
+
let pendingPromptId: string | undefined;
|
|
27
|
+
let activePromptId: string | undefined;
|
|
28
|
+
let settlement: Promise<void> | undefined;
|
|
26
29
|
const maxSteps = Number(process.env.AGENTHUB_PI_MAX_STEPS ?? 30);
|
|
27
30
|
let shutdown: (() => void) | undefined;
|
|
28
31
|
let runtimeCtx: any;
|
|
@@ -66,7 +69,30 @@ async function poll(pi: ExtensionAPI): Promise<void> {
|
|
|
66
69
|
if (!command) continue;
|
|
67
70
|
try {
|
|
68
71
|
if (command.type === "prompt" || command.type === "steer") {
|
|
72
|
+
if (command.type === "prompt") {
|
|
73
|
+
// Let our settled callback return to native Pi before the normal queued successor starts.
|
|
74
|
+
if (settlement) {
|
|
75
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
76
|
+
try { await Promise.race([settlement, new Promise<void>(resolve => { timer = setTimeout(resolve, 5_000); })]); }
|
|
77
|
+
finally { clearTimeout(timer); }
|
|
78
|
+
}
|
|
79
|
+
if (settlement || runtimeCtx?.isIdle?.() !== true || (command.sessionId !== undefined && command.sessionId !== sessionId) || (command.generation !== undefined && command.generation !== turnGeneration)) {
|
|
80
|
+
await post("/ack", { id: command.id, ok: false, error: "Pi prompt was not inserted because its native session is no longer idle at the expected generation", refusal: { kind: "prompt_not_started", promptId: command.id, sessionId, generation: turnGeneration } });
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Pinned Pi 1.0.1 starts _runAgentPrompt synchronously before its first await.
|
|
84
|
+
// Keep this check and insertion in one JS turn; snapshots cannot reserve native idleness.
|
|
85
|
+
pendingPromptId = command.id;
|
|
86
|
+
}
|
|
69
87
|
pi.sendMessage({ customType: "agent-hub", content: String(command.message ?? ""), display: true }, { triggerTurn: command.type === "prompt", deliverAs: command.type === "steer" ? "steer" : "followUp" });
|
|
88
|
+
if (command.type === "prompt" && runtimeCtx?.isIdle?.() !== false) {
|
|
89
|
+
// Another extension's async settled hook can make native Pi defer this insertion.
|
|
90
|
+
// Our callback barrier is not an atomic native reservation: keep that effect uncertain.
|
|
91
|
+
if (pendingPromptId === command.id) pendingPromptId = undefined;
|
|
92
|
+
if (activePromptId === command.id) activePromptId = undefined;
|
|
93
|
+
await post("/ack", { id: command.id, ok: false, error: "Pi prompt insertion did not synchronously claim a native turn", refusal: { kind: "prompt_uncertain", promptId: command.id, sessionId, generation: turnGeneration } });
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
70
96
|
} else if (command.type === "get_session_state") {
|
|
71
97
|
const entries = runtimeCtx.sessionManager.getEntries();
|
|
72
98
|
await post("/ack", { id: command.id, ok: true, result: {
|
|
@@ -94,7 +120,7 @@ async function poll(pi: ExtensionAPI): Promise<void> {
|
|
|
94
120
|
}
|
|
95
121
|
}
|
|
96
122
|
await post("/ack", { id: command.id, ok: true });
|
|
97
|
-
} catch (error) { await post("/ack", { id: command.id, ok: false, error: (error as Error).message }); }
|
|
123
|
+
} catch (error) { if (pendingPromptId === command.id) pendingPromptId = undefined; await post("/ack", { id: command.id, ok: false, error: (error as Error).message }); }
|
|
98
124
|
} catch { await new Promise((resolve) => setTimeout(resolve, 250)); }
|
|
99
125
|
}
|
|
100
126
|
}
|
|
@@ -117,7 +143,7 @@ export default function(pi: ExtensionAPI): void {
|
|
|
117
143
|
const state = ctx.sessionManager.getHeader();
|
|
118
144
|
sessionId = String(state?.id ?? "");
|
|
119
145
|
try {
|
|
120
|
-
const claimed = await post("/event", { type: "session_start", ownerToken, pid: process.pid, signature: processSignature(process.pid), sessionId: state?.id, sessionFile: ctx.sessionManager.getSessionFile(), approvalTurnAbort: typeof ctx.abort === "function" });
|
|
146
|
+
const claimed = await post("/event", { type: "session_start", ownerToken, pid: process.pid, signature: processSignature(process.pid), sessionId: state?.id, sessionFile: ctx.sessionManager.getSessionFile(), approvalTurnAbort: typeof ctx.abort === "function", fencedPrompt: true });
|
|
121
147
|
if (claimed?.ok === false) { ctx.shutdown?.(); return; }
|
|
122
148
|
} catch (error) { ctx.shutdown?.(); throw error; }
|
|
123
149
|
if (!pollStarted) { pollStarted = true; void poll(pi); }
|
|
@@ -127,7 +153,7 @@ export default function(pi: ExtensionAPI): void {
|
|
|
127
153
|
const text = message?.content?.filter((c: any) => c?.type === "text").map((c: any) => c.text).join("")?.trim();
|
|
128
154
|
const failed = !!forcedFailure || message?.stopReason === "error";
|
|
129
155
|
const cancelled = !forcedFailure && message?.stopReason === "aborted";
|
|
130
|
-
await post("/event", { type: "agent_end", generation: turnGeneration, text: text ?? "", failed, cancelled, ...(failed ? { error: forcedFailure || message?.errorMessage || message?.stopReason } : {}) });
|
|
156
|
+
await post("/event", { type: "agent_end", generation: turnGeneration, ...(activePromptId ? { promptId: activePromptId } : {}), text: text ?? "", failed, cancelled, ...(failed ? { error: forcedFailure || message?.errorMessage || message?.stopReason } : {}) });
|
|
131
157
|
});
|
|
132
158
|
pi.on("message_end", async (event: any) => {
|
|
133
159
|
const tokens = assistantTokens(event.message);
|
|
@@ -142,7 +168,8 @@ export default function(pi: ExtensionAPI): void {
|
|
|
142
168
|
lastActivity = now;
|
|
143
169
|
try { await post("/event", { type: "activity" }); } catch { /* shutdown owns bridge cleanup */ }
|
|
144
170
|
});
|
|
145
|
-
|
|
171
|
+
// Native retries/continuations emit more starts before the one logical agent_settled.
|
|
172
|
+
pi.on("agent_start", async () => { toolSteps = 0; forcedFailure = ""; turnGeneration++; activePromptId = pendingPromptId ?? activePromptId; pendingPromptId = undefined; await post("/event", { type: "agent_start", generation: turnGeneration, ...(activePromptId ? { promptId: activePromptId } : {}) }); });
|
|
146
173
|
pi.on("model_select", async (_event: any, ctx: any) => { if (ctx.model?.provider && ctx.model.provider !== "agent-hub-local") ctx.shutdown?.(); });
|
|
147
174
|
pi.on("before_agent_start", async (event: any, ctx: any) => {
|
|
148
175
|
if (ctx.model?.provider && ctx.model.provider !== "agent-hub-local") { ctx.abort?.(); return { systemPrompt: event.systemPrompt }; }
|
|
@@ -157,10 +184,18 @@ export default function(pi: ExtensionAPI): void {
|
|
|
157
184
|
return undefined;
|
|
158
185
|
});
|
|
159
186
|
pi.on("agent_settled", async (_event: any, ctx: any) => {
|
|
187
|
+
let release!: () => void;
|
|
188
|
+
const current = new Promise<void>(resolve => { release = resolve; });
|
|
189
|
+
settlement = current;
|
|
160
190
|
const entries = ctx.sessionManager?.getEntries?.() ?? [];
|
|
161
191
|
const message = entries.slice().reverse().find((entry: any) => entry.type === "message" && entry.message?.role === "assistant")?.message;
|
|
162
192
|
const text = message?.content?.filter((c: any) => c?.type === "text").map((c: any) => c.text).join("")?.trim();
|
|
163
|
-
await post("/event", { type: "agent_settled", generation: turnGeneration, ...(text ? { text } : {}) });
|
|
193
|
+
try { await post("/event", { type: "agent_settled", generation: turnGeneration, ...(activePromptId ? { promptId: activePromptId } : {}), ...(text ? { text } : {}) }); }
|
|
194
|
+
finally {
|
|
195
|
+
activePromptId = undefined;
|
|
196
|
+
// Release after this callback returns, not inside its awaited POST continuation.
|
|
197
|
+
setTimeout(() => { if (settlement === current) settlement = undefined; release(); }, 0);
|
|
198
|
+
}
|
|
164
199
|
});
|
|
165
200
|
pi.on("user_bash", async (event: any) => {
|
|
166
201
|
const generation = turnGeneration, callSessionId = sessionId;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "*.md" { const text: string; export default text; }
|