pi-firecode 0.8.1 → 1.0.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/README.md +35 -15
- package/activity.ts +92 -0
- package/busy.ts +188 -0
- package/config.example.jsonc +38 -47
- package/config.ts +198 -172
- package/deliver.ts +100 -13
- package/flame.ts +149 -0
- package/format.ts +84 -31
- package/header.ts +208 -82
- package/index.ts +17 -11
- package/master/actions.ts +293 -0
- package/master/activity-list.ts +281 -0
- package/master/event-card.ts +18 -37
- package/master/event-format.ts +71 -40
- package/master/guard.ts +46 -0
- package/master/index.ts +88 -1036
- package/master/list-view.ts +129 -0
- package/master/outbox.ts +188 -0
- package/master/prompts/master.zh.md +17 -12
- package/master/prompts/worker.zh.md +1 -1
- package/master/role.ts +6 -1
- package/master/run.ts +315 -0
- package/master/runtime.ts +259 -0
- package/master/spawn.ts +79 -38
- package/master/state.ts +30 -6
- package/master/worker-view.ts +517 -0
- package/package.json +1 -1
- package/provider/claude-sub.ts +35 -13
- package/provider/openai-native/src/compact-client.ts +2 -14
- package/provider/openai-native/src/options.ts +4 -2
- package/review/advisor.ts +0 -2
- package/review/card.ts +36 -23
- package/review/checkpoint.ts +2 -8
- package/review/evidence.ts +42 -44
- package/review/index.ts +271 -525
- package/review/occupancy.ts +25 -0
- package/review/outcome.ts +31 -7
- package/review/prompt.ts +7 -8
- package/review/prompts/review.en.md +7 -6
- package/review/prompts/review.zh.md +7 -6
- package/review/reviewer.ts +2 -5
- package/review/session.ts +11 -30
- package/review/state.ts +32 -60
- package/review/ui.ts +30 -469
- package/round-recorder.ts +18 -0
- package/session/herdr-display.ts +1 -1
- package/session/presets.ts +130 -87
- package/session/quota.ts +123 -0
- package/session/stats.ts +4 -1
- package/statusbar/index.ts +242 -104
- package/statusbar/render.ts +95 -163
- package/theme.ts +2 -41
- package/tools/actions.ts +53 -0
- package/tools/assistant-view.ts +64 -0
- package/tools/click-anchor.ts +56 -0
- package/tools/group-view.ts +420 -0
- package/tools/grouping.ts +146 -221
- package/tools/host.ts +369 -0
- package/tools/index.ts +108 -105
- package/tools/line.ts +95 -58
- package/tools/machine.ts +78 -0
- package/tools/parts.ts +2 -2
- package/tools/round.ts +95 -0
- package/tools/turn-clock.ts +41 -0
- package/tools/turn-summary.ts +109 -0
- package/truncated-write.ts +18 -0
- package/watcher/card.ts +28 -22
- package/watcher/index.ts +16 -44
- package/watcher/observer.ts +3 -3
- package/watcher/prompts/watch.zh.md +1 -1
- package/watcher/transcript.ts +4 -12
- package/flame-frames.ts +0 -460
- package/review/progress.ts +0 -324
- package/session/bark.ts +0 -157
- package/session/working-flame.ts +0 -116
- package/statusbar/quota-cache.ts +0 -60
- package/statusbar/quota-parse.ts +0 -85
- package/statusbar/quota.ts +0 -203
- package/statusbar/tps.ts +0 -87
package/tools/grouping.ts
CHANGED
|
@@ -1,233 +1,158 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function getTheme(): Theme {
|
|
16
|
-
const globalTheme = (globalThis as any)[THEME_KEY];
|
|
17
|
-
if (globalTheme && typeof globalTheme.fg === "function") return globalTheme;
|
|
18
|
-
return {
|
|
19
|
-
fg: (_color: string, text: string) => text,
|
|
20
|
-
bg: (_color: string, text: string) => text,
|
|
21
|
-
bold: (text: string) => text,
|
|
22
|
-
} as unknown as Theme;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type RenderFunction = (width: number) => string[];
|
|
26
|
-
type RequestRenderFunction = (force?: boolean) => unknown;
|
|
27
|
-
type ToolRow = { toolName: unknown; setExpanded: unknown; render: RenderFunction };
|
|
28
|
-
type ToolRowPatch = { original: RenderFunction; patched: RenderFunction };
|
|
29
|
-
type ToolRowPrototype = ToolRow & { [GROUP_PATCH]?: ToolRowPatch };
|
|
30
|
-
type RequestRenderPatch = { original: RequestRenderFunction; patched: RequestRenderFunction };
|
|
31
|
-
type ContainerLike = { children: unknown[] };
|
|
32
|
-
type TuiLike = {
|
|
33
|
-
requestRender: RequestRenderFunction;
|
|
34
|
-
children?: unknown[];
|
|
35
|
-
[REQUEST_RENDER_PATCH]?: RequestRenderPatch;
|
|
36
|
-
};
|
|
37
|
-
type GlobalState = {
|
|
38
|
-
tui?: TuiLike;
|
|
39
|
-
chat?: ContainerLike;
|
|
40
|
-
indexedChildren?: unknown[];
|
|
41
|
-
indexedLength?: number;
|
|
42
|
-
joinedRows?: WeakSet<object>;
|
|
43
|
-
patchedPrototype?: ToolRowPrototype;
|
|
44
|
-
patchErrorReported?: boolean;
|
|
45
|
-
decorated: Set<string>;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// 扩展热重载会重新执行模块,patch 状态必须挂在全局才能正确卸载。
|
|
49
|
-
const runtimeGlobal = globalThis as typeof globalThis & { [GLOBAL_STATE]?: GlobalState };
|
|
50
|
-
const globalState = (runtimeGlobal[GLOBAL_STATE] ??= { decorated: new Set<string>() });
|
|
51
|
-
|
|
52
|
-
function isToolRow(value: unknown): value is ToolRow {
|
|
53
|
-
if (!value || typeof value !== "object") return false;
|
|
54
|
-
const row = value as ToolRow;
|
|
55
|
-
return typeof row.render === "function" && typeof row.setExpanded === "function" && "toolName" in row;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function isDecoratedToolRow(value: unknown): value is ToolRow {
|
|
59
|
-
return isToolRow(value);
|
|
1
|
+
/** 过程分组的安装:原始聊天树不变,渲染与鼠标命中共用同一份投影;宿主私有细节全部经 host.ts。 */
|
|
2
|
+
import { AssistantMessageComponent, CustomMessageComponent, ToolExecutionComponent, UserMessageComponent, type ExtensionUIContext } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { Container, type Component, type TUI } from "@earendil-works/pi-tui";
|
|
4
|
+
import { onFrame } from "../flame.js";
|
|
5
|
+
import { ClickAnchor } from "./click-anchor.js";
|
|
6
|
+
import { isMachineMessage, projectProcessGroups, toggleToolDetails, type ProjectionEnv } from "./group-view.js";
|
|
7
|
+
import { assistantFacts, captureTui, findChat, HostShapeError, isCardOpened, patchMethod, rowUiOf, scrollContentHeight, scrollViewOf, toolFacts } from "./host.js";
|
|
8
|
+
import type { TurnClock } from "./turn-clock.js";
|
|
9
|
+
|
|
10
|
+
const OWNER = Symbol.for("pi.firecode.tool-groups");
|
|
11
|
+
const runtime = globalThis as typeof globalThis & { [OWNER]?: () => void };
|
|
12
|
+
|
|
13
|
+
export interface GroupOptions {
|
|
14
|
+
clock: TurnClock;
|
|
60
15
|
}
|
|
61
16
|
|
|
62
|
-
export function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const toolLine = new ToolLine({
|
|
68
|
-
label: toolName,
|
|
69
|
-
value: genericArgsParts(row.args),
|
|
70
|
-
clip: "end",
|
|
71
|
-
theme: activeTheme,
|
|
72
|
-
ctx: {
|
|
73
|
-
state: row.rendererState ?? {},
|
|
74
|
-
cwd: row.cwd ?? process.cwd(),
|
|
75
|
-
toolCallId: row.toolCallId ?? "",
|
|
76
|
-
isPartial,
|
|
77
|
-
isError,
|
|
78
|
-
expanded: row.expanded ?? false,
|
|
79
|
-
},
|
|
17
|
+
export function installGroupPatch(ui: ExtensionUIContext, options: GroupOptions): () => void {
|
|
18
|
+
runtime[OWNER]?.();
|
|
19
|
+
let detach = () => {};
|
|
20
|
+
captureTui(ui, (tui) => {
|
|
21
|
+
detach = attach(tui, ui, options);
|
|
80
22
|
});
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
: "";
|
|
89
|
-
if (textContent) {
|
|
90
|
-
const outputLines = textContent.split("\n").map((l: string) => activeTheme.fg("toolOutput", l));
|
|
91
|
-
lines.push("", ...outputLines);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return lines;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function findChatContainer(value: unknown, seen = new Set<unknown>()): ContainerLike | undefined {
|
|
98
|
-
if (!value || typeof value !== "object" || seen.has(value)) return undefined;
|
|
99
|
-
seen.add(value);
|
|
100
|
-
const children = (value as ContainerLike).children;
|
|
101
|
-
if (!Array.isArray(children)) return undefined;
|
|
102
|
-
if (children.some(isToolRow)) return value as ContainerLike;
|
|
103
|
-
for (const child of children) {
|
|
104
|
-
const found = findChatContainer(child, seen);
|
|
105
|
-
if (found) return found;
|
|
106
|
-
}
|
|
107
|
-
return undefined;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** 增量标记"紧跟另一条装饰行"的行,聊天记录只增不改,可以从上次位置续算。 */
|
|
111
|
-
function indexJoinedRows(children: unknown[]): void {
|
|
112
|
-
const canAppend =
|
|
113
|
-
globalState.indexedChildren === children &&
|
|
114
|
-
globalState.indexedLength !== undefined &&
|
|
115
|
-
globalState.indexedLength <= children.length &&
|
|
116
|
-
globalState.joinedRows !== undefined;
|
|
117
|
-
const joinedRows =
|
|
118
|
-
canAppend && globalState.joinedRows ? globalState.joinedRows : new WeakSet<object>();
|
|
119
|
-
const start = canAppend ? Math.max(1, globalState.indexedLength ?? 1) : 1;
|
|
120
|
-
for (let index = start; index < children.length; index++) {
|
|
121
|
-
const current = children[index];
|
|
122
|
-
if (isDecoratedToolRow(current) && isDecoratedToolRow(children[index - 1]))
|
|
123
|
-
joinedRows.add(current);
|
|
124
|
-
}
|
|
125
|
-
globalState.indexedChildren = children;
|
|
126
|
-
globalState.indexedLength = children.length;
|
|
127
|
-
globalState.joinedRows = joinedRows;
|
|
23
|
+
const dispose = () => {
|
|
24
|
+
if (runtime[OWNER] !== dispose) return;
|
|
25
|
+
detach();
|
|
26
|
+
delete runtime[OWNER];
|
|
27
|
+
};
|
|
28
|
+
runtime[OWNER] = dispose;
|
|
29
|
+
return dispose;
|
|
128
30
|
}
|
|
129
31
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (
|
|
134
|
-
if (globalState.indexedChildren !== children || globalState.indexedLength !== children.length)
|
|
135
|
-
indexJoinedRows(children);
|
|
136
|
-
return globalState.joinedRows?.has(row) ?? false;
|
|
32
|
+
/** 首个真实实例的形状自检:私有字段改名或换型就不安装。 */
|
|
33
|
+
function checkShape(child: Component): void {
|
|
34
|
+
if (child instanceof ToolExecutionComponent) toolFacts(child);
|
|
35
|
+
if (child instanceof AssistantMessageComponent) assistantFacts(child);
|
|
137
36
|
}
|
|
138
37
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const prototype = Object.getPrototypeOf(row) as ToolRowPrototype;
|
|
151
|
-
if (prototype[GROUP_PATCH]) {
|
|
152
|
-
globalState.patchedPrototype = prototype;
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const original = prototype.render;
|
|
156
|
-
const patched: RenderFunction = function (this: ToolRow, width: number): string[] {
|
|
157
|
-
const toolName = typeof this.toolName === "string" ? this.toolName : "";
|
|
158
|
-
const isFirecodeTool = FIRECODE_TOOLS.has(toolName);
|
|
159
|
-
const isExpanded = Boolean((this as any).expanded);
|
|
160
|
-
const lines = isFirecodeTool || isExpanded
|
|
161
|
-
? original.call(this, width)
|
|
162
|
-
: renderFallbackToolRow(this, width);
|
|
163
|
-
return followsToolRow(this) && lines[0] === "" ? lines.slice(1) : lines;
|
|
38
|
+
function attach(tui: TUI, ui: ExtensionUIContext, options: GroupOptions): () => void {
|
|
39
|
+
const originalExpand = ToolExecutionComponent.prototype.setExpanded;
|
|
40
|
+
const originalMessageExpand = CustomMessageComponent.prototype.setExpanded;
|
|
41
|
+
const originalAdd = Container.prototype.addChild;
|
|
42
|
+
const restores: (() => void)[] = [];
|
|
43
|
+
let stopFrames: (() => void) | undefined;
|
|
44
|
+
let attached = false;
|
|
45
|
+
const detach = () => {
|
|
46
|
+
stopFrames?.();
|
|
47
|
+
stopFrames = undefined;
|
|
48
|
+
for (const restore of restores.splice(0).reverse()) restore();
|
|
164
49
|
};
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
globalState.indexedChildren = undefined;
|
|
182
|
-
globalState.joinedRows = undefined;
|
|
183
|
-
if (!patchableTui[REQUEST_RENDER_PATCH]) {
|
|
184
|
-
const original = patchableTui.requestRender;
|
|
185
|
-
const patched: RequestRenderFunction = (force) => {
|
|
186
|
-
try {
|
|
187
|
-
patchToolRows();
|
|
188
|
-
} catch (error) {
|
|
189
|
-
if (!globalState.patchErrorReported) {
|
|
190
|
-
globalState.patchErrorReported = true;
|
|
191
|
-
ui.notify(
|
|
192
|
-
`工具轨道连接失败:${error instanceof Error ? error.message : String(error)}`,
|
|
193
|
-
"warning",
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return original.call(patchableTui, force);
|
|
198
|
-
};
|
|
199
|
-
Object.defineProperty(patchableTui, REQUEST_RENDER_PATCH, {
|
|
200
|
-
configurable: true,
|
|
201
|
-
value: { original, patched } satisfies RequestRenderPatch,
|
|
202
|
-
});
|
|
203
|
-
patchableTui.requestRender = patched;
|
|
50
|
+
let abandoned = false;
|
|
51
|
+
/** 自检、渲染、点击或全局展开时发现宿主形状不符:整体退回原生显示并明确提示一次,不悄悄画错。 */
|
|
52
|
+
const abandon = (error: HostShapeError) => {
|
|
53
|
+
detach();
|
|
54
|
+
if (abandoned) return;
|
|
55
|
+
abandoned = true;
|
|
56
|
+
ui.notify(error.message, "warning");
|
|
57
|
+
};
|
|
58
|
+
/** 宿主调进来的每个入口都经这里:形状不符就退回原生,再按原生行为完成这次调用。 */
|
|
59
|
+
const guarded = <T>(run: () => T, native: () => T): T => {
|
|
60
|
+
try {
|
|
61
|
+
return run();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (!(error instanceof HostShapeError)) throw error;
|
|
64
|
+
abandon(error);
|
|
65
|
+
return native();
|
|
204
66
|
}
|
|
205
|
-
|
|
206
|
-
|
|
67
|
+
};
|
|
68
|
+
// 归属只比对 TUI 引用,不校验别的 TUI 的工具行形状。
|
|
69
|
+
const belongsHere = (row: ToolExecutionComponent) => rowUiOf(row) === tui;
|
|
70
|
+
// 全局展开只控制组摘要/列表;单工具正文通过下方独立的鼠标入口调用原方法。
|
|
71
|
+
restores.push(patchMethod(ToolExecutionComponent.prototype, "setExpanded", function (this: ToolExecutionComponent, value) {
|
|
72
|
+
originalExpand.call(this, belongsHere(this) ? false : value);
|
|
73
|
+
}));
|
|
74
|
+
// 机器消息的原生卡片只由投影点开(host.ts 的 openCard);全局展开不平铺它(其余 CustomMessage 照旧跟随全局)。
|
|
75
|
+
restores.push(patchMethod(CustomMessageComponent.prototype, "setExpanded", function (this: CustomMessageComponent, value) {
|
|
76
|
+
const target = guarded(() => (isMachineMessage(this) && !isCardOpened(this) ? false : value), () => value);
|
|
77
|
+
originalMessageExpand.call(this, target);
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
const install = (chat: Container) => {
|
|
81
|
+
const render = chat.render;
|
|
82
|
+
const mouse = chat.handleMouse;
|
|
83
|
+
const projection = new Container();
|
|
84
|
+
const overrides = new Set<object>();
|
|
85
|
+
let lastExpanded = ui.getToolsExpanded();
|
|
86
|
+
const anchor = new ClickAnchor(() => {
|
|
87
|
+
const view = scrollViewOf(tui, chat);
|
|
88
|
+
return view && {
|
|
89
|
+
top: view.scrollTop,
|
|
90
|
+
following: view.isFollowingEnd,
|
|
91
|
+
viewport: view.viewportHeight,
|
|
92
|
+
contentHeight: scrollContentHeight(view),
|
|
93
|
+
holdAt: (top: number) => view.scrollTo(top, { disableFollow: true }),
|
|
94
|
+
follow: () => view.scrollToEnd(),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
const env: ProjectionEnv = {
|
|
98
|
+
ui, clock: options.clock, headless: {},
|
|
99
|
+
toggleRow: (row) => {
|
|
100
|
+
toggleToolDetails(row, originalExpand);
|
|
101
|
+
tui.requestRender();
|
|
102
|
+
},
|
|
103
|
+
isOpen: (key) => overrides.has(key),
|
|
104
|
+
toggleOpen: (key) => {
|
|
105
|
+
if (!overrides.delete(key)) overrides.add(key);
|
|
106
|
+
tui.requestRender();
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
chat.render = (width) => {
|
|
110
|
+
// ctrl+o 永远是全部展开/全部折叠:全局档位一变,逐轮覆盖(含被点开的机器消息卡)一并复位。
|
|
111
|
+
if (ui.getToolsExpanded() !== lastExpanded) {
|
|
112
|
+
lastExpanded = ui.getToolsExpanded();
|
|
113
|
+
overrides.clear();
|
|
114
|
+
}
|
|
115
|
+
return guarded(() => {
|
|
116
|
+
const { nodes, animating } = projectProcessGroups(chat.children, env);
|
|
117
|
+
projection.children = nodes;
|
|
118
|
+
// 动效只经全局时钟:有活的摘要才订阅,静止即取消。
|
|
119
|
+
if (animating && !stopFrames) stopFrames = onFrame(() => tui.requestRender());
|
|
120
|
+
else if (!animating && stopFrames) { stopFrames(); stopFrames = undefined; }
|
|
121
|
+
const lines = projection.render(width);
|
|
122
|
+
anchor.layout(lines.length);
|
|
123
|
+
return lines;
|
|
124
|
+
}, () => render.call(chat, width));
|
|
125
|
+
};
|
|
126
|
+
chat.handleMouse = (event) => guarded(() => {
|
|
127
|
+
const result = projection.handleMouse(event);
|
|
128
|
+
if (result && event.type === "click") anchor.click(event.y);
|
|
129
|
+
return result;
|
|
130
|
+
}, () => mouse.call(chat, event));
|
|
131
|
+
restores.push(() => {
|
|
132
|
+
chat.render = render;
|
|
133
|
+
chat.handleMouse = mouse;
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
const discover = (trigger?: Component) => {
|
|
137
|
+
if (attached) return;
|
|
138
|
+
const chat = findChat(tui);
|
|
139
|
+
if (!chat) return;
|
|
140
|
+
attached = true;
|
|
141
|
+
removeHook();
|
|
142
|
+
const healthy = guarded(() => {
|
|
143
|
+
for (const child of trigger ? [trigger, ...chat.children] : chat.children) checkShape(child);
|
|
144
|
+
return true;
|
|
145
|
+
}, () => false);
|
|
146
|
+
if (healthy) install(chat);
|
|
147
|
+
};
|
|
148
|
+
// 宿主没有聊天容器句柄;首条用户消息、助手或工具插入时定位(首条用户消息一出现就带竖条),随后立即卸掉发现钩子。
|
|
149
|
+
const removeHook = patchMethod(Container.prototype, "addChild", function (this: Container, child: Component) {
|
|
150
|
+
originalAdd.call(this, child);
|
|
151
|
+
if (child instanceof AssistantMessageComponent || child instanceof UserMessageComponent
|
|
152
|
+
|| (child instanceof ToolExecutionComponent && rowUiOf(child) === tui)) discover(child);
|
|
207
153
|
});
|
|
208
|
-
|
|
154
|
+
restores.push(removeHook);
|
|
155
|
+
discover();
|
|
156
|
+
return detach;
|
|
209
157
|
}
|
|
210
158
|
|
|
211
|
-
export function uninstallGroupPatch(): void {
|
|
212
|
-
const tui = globalState.tui;
|
|
213
|
-
const requestPatch = tui?.[REQUEST_RENDER_PATCH];
|
|
214
|
-
if (tui && requestPatch && tui.requestRender === requestPatch.patched) {
|
|
215
|
-
tui.requestRender = requestPatch.original;
|
|
216
|
-
delete tui[REQUEST_RENDER_PATCH];
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const prototype = globalState.patchedPrototype;
|
|
220
|
-
const rowPatch = prototype?.[GROUP_PATCH];
|
|
221
|
-
if (prototype && rowPatch && prototype.render === rowPatch.patched) {
|
|
222
|
-
prototype.render = rowPatch.original;
|
|
223
|
-
delete prototype[GROUP_PATCH];
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
globalState.tui = undefined;
|
|
227
|
-
globalState.chat = undefined;
|
|
228
|
-
globalState.indexedChildren = undefined;
|
|
229
|
-
globalState.indexedLength = undefined;
|
|
230
|
-
globalState.joinedRows = undefined;
|
|
231
|
-
globalState.patchedPrototype = undefined;
|
|
232
|
-
globalState.patchErrorReported = false;
|
|
233
|
-
}
|