@fitchmultz/pi-subagents 0.44.6 → 0.44.7
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
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.44.7] - 2026-10-09
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Keep newer Agents history, including consumed human answers, from being overwritten by an older in-flight page. Recheck the owning session, index, selected attempt, source and published page before applying async history or saved-result reads; preserve requested paging and reading anchors when reloading an invalidated snapshot.
|
|
7
|
+
- Consume refresh notifications received while the latest conversation page is loading, without pulling scrolled readers forward or automatically retrying history errors.
|
|
8
|
+
- Emit the Intercom bridge `session_closed` audit record after broker disconnect completes and the closing session is removed; cancellation still rejects pending and new requests for that identity immediately.
|
|
9
|
+
|
|
3
10
|
## [0.44.6] - 2026-10-09
|
|
4
11
|
|
|
5
12
|
### Fixed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const EXTENSION_BUILD = Object.freeze({"version":"0.44.
|
|
1
|
+
export const EXTENSION_BUILD = Object.freeze({"version":"0.44.7","sha256":"86c62961d20949874e872f49d9044371c4ae3d0b1b18b9d3b1186c29d1522bb0"});
|
|
@@ -295,8 +295,8 @@ class Session {
|
|
|
295
295
|
await this.disconnect();
|
|
296
296
|
if (this.bridge.sessions.get(this.identity.fingerprint256) === this)
|
|
297
297
|
this.bridge.sessions.delete(this.identity.fingerprint256);
|
|
298
|
+
log("session_closed", { ...this.fields(), result: error.code });
|
|
298
299
|
})();
|
|
299
|
-
log("session_closed", { ...this.fields(), result: error.code });
|
|
300
300
|
}
|
|
301
301
|
receive(from, message) {
|
|
302
302
|
if (this.closed)
|
package/dist/tui/agent-view.js
CHANGED
|
@@ -315,7 +315,7 @@ export class AgentViewController {
|
|
|
315
315
|
activity: { ...prior.child.activity, ...child.activity } } : child;
|
|
316
316
|
return { key, label: child.identityUnavailable ? "Saved assignment unavailable" : sameAttempt ? agentTaskLabel(child) : prior?.label ?? agentTaskLabel(child), run: view, child: displayChild,
|
|
317
317
|
model: agentModel(displayChild, child.nativeConfiguration ?? (canonical && sameAttempt && child.sessionFile === prior.child.sessionFile ? prior.page?.configuration : undefined)), history: sameAttempt ? prior.history : [], historyIds: sameAttempt ? prior.historyIds : [],
|
|
318
|
-
page: sameAttempt ? prior.page : undefined, metadataAt: observed ? prior.metadataAt : undefined, historyLoading: sameAttempt ? prior.historyLoading : false, finalId: sameAttempt ? prior.finalId : undefined, unavailable: child.missingSession && child.state !== "live" ? "Saved conversation unavailable." : view.diagnosis,
|
|
318
|
+
page: sameAttempt ? prior.page : undefined, historySource: sameAttempt ? prior.historySource : undefined, metadataAt: observed ? prior.metadataAt : undefined, historyLoading: sameAttempt ? prior.historyLoading : false, finalId: sameAttempt ? prior.finalId : undefined, unavailable: child.missingSession && child.state !== "live" ? "Saved conversation unavailable." : view.diagnosis,
|
|
319
319
|
question: child.identityUnavailable ? undefined : questions.findLast((question) => question.index === child.index && ["awaiting_input", "answer_pending"].includes(question.state)),
|
|
320
320
|
unread: observed ? prior.unread : Boolean(visit && (child.activity?.lastActivityAt ?? view.updatedAt) > (visit.seenActivityAt ?? 0)), replied: sameAttempt ? prior.replied : false };
|
|
321
321
|
});
|
|
@@ -485,7 +485,19 @@ export class AgentViewController {
|
|
|
485
485
|
const task = this.task(key), generation = this.generation;
|
|
486
486
|
if (!task || !this.live() || task.child.identityUnavailable)
|
|
487
487
|
return;
|
|
488
|
+
const published = task.page, source = task.historySource, sessionFile = task.child.sessionFile, childState = task.child.state;
|
|
488
489
|
const input = this.historyInput(task), index = await runHistoryIndex(this.state);
|
|
490
|
+
// Versions can reset on index reopen. Fence the actual owner/read baseline,
|
|
491
|
+
// including metadata-only source transitions, rather than ordering unrelated versions.
|
|
492
|
+
const isCurrent = () => {
|
|
493
|
+
const current = this.task(key);
|
|
494
|
+
if (!this.live(generation) || this.state.historyIndex !== index || index.failure || !current || current.child.identityUnavailable
|
|
495
|
+
|| current.page !== published || current.historySource !== source || current.child.sessionFile !== sessionFile || current.child.state !== childState)
|
|
496
|
+
return false;
|
|
497
|
+
const boundary = this.historyInput(current);
|
|
498
|
+
return boundary.runId === input.runId && boundary.index === input.index && boundary.leaf === input.leaf
|
|
499
|
+
&& boundary.terminalEntryId === input.terminalEntryId && boundary.endedAt === input.endedAt;
|
|
500
|
+
};
|
|
489
501
|
const boundary = { runId: task.run.runId, index: task.child.index, terminalEntryId: input.terminalEntryId, endedAt: input.endedAt };
|
|
490
502
|
const marker = typeof input.readThrough === "string" && !input.readThrough.startsWith("result:")
|
|
491
503
|
? await index.entry({ ...boundary, entryId: input.readThrough.replace(/:(?:\d+|error)$/, "") }) : undefined;
|
|
@@ -499,7 +511,7 @@ export class AgentViewController {
|
|
|
499
511
|
const result = await indexedHistory(index, { ...input, limit: 100, ...paging });
|
|
500
512
|
if (!this.live(generation) || this.task(key)?.run.runId !== task.run.runId)
|
|
501
513
|
return;
|
|
502
|
-
return { ...result, latestPage: paging.after !== undefined ? !result.page.hasMore : paging.before === undefined && paging.cursor === undefined,
|
|
514
|
+
return { ...result, isCurrent, latestPage: paging.after !== undefined ? !result.page.hasMore : paging.before === undefined && paging.cursor === undefined,
|
|
503
515
|
readThroughSequence: marker?.sequence ?? (input.readThrough == null ? -1 : undefined) };
|
|
504
516
|
}
|
|
505
517
|
async savedResult(key, id) {
|
|
@@ -522,6 +534,7 @@ export class AgentViewController {
|
|
|
522
534
|
}
|
|
523
535
|
applyMetadata(task, page) {
|
|
524
536
|
const visit = this.visits.get(task.key), delivered = new Map(page.deliveredMessages);
|
|
537
|
+
task.historySource = JSON.stringify([page.sourceId, page.generation, page.sessionId]);
|
|
525
538
|
if (page.freshness.state !== "catching-up")
|
|
526
539
|
task.metadataAt = task.run.updatedAt;
|
|
527
540
|
task.model = agentModel(task.child, page.configuration);
|
|
@@ -1009,6 +1022,7 @@ export class AgentConversation extends Container {
|
|
|
1009
1022
|
pageRequest = 0;
|
|
1010
1023
|
detailRequest = 0;
|
|
1011
1024
|
loadingPage = false;
|
|
1025
|
+
refreshPending = false;
|
|
1012
1026
|
pageError;
|
|
1013
1027
|
latestPage = true;
|
|
1014
1028
|
readSequence = -1;
|
|
@@ -1108,6 +1122,7 @@ export class AgentConversation extends Container {
|
|
|
1108
1122
|
if (this.closed)
|
|
1109
1123
|
return;
|
|
1110
1124
|
const request = ++this.pageRequest;
|
|
1125
|
+
this.refreshPending = false;
|
|
1111
1126
|
this.loadingPage = true;
|
|
1112
1127
|
this.pageError = undefined;
|
|
1113
1128
|
if (this.task)
|
|
@@ -1126,11 +1141,8 @@ export class AgentConversation extends Container {
|
|
|
1126
1141
|
result = reportPage;
|
|
1127
1142
|
}
|
|
1128
1143
|
let task = this.task;
|
|
1129
|
-
if (result.readThroughSequence !== undefined)
|
|
1130
|
-
this.readSequence = result.readThroughSequence;
|
|
1131
|
-
this.latestPage = result.latestPage;
|
|
1132
1144
|
let history = result.history;
|
|
1133
|
-
if ((this.initialPosition ||
|
|
1145
|
+
if ((this.initialPosition || result.latestPage || history.finalId && history.entryIds.includes(history.finalId)) && task.child.state !== "live" && task.child.result && getSingleResultOutput(task.child.result)) {
|
|
1134
1146
|
const report = await this.controller.savedResult(this.key, `result:${task.run.runId}`);
|
|
1135
1147
|
const currentTask = this.task;
|
|
1136
1148
|
if (this.closed || request !== this.pageRequest || !currentTask || currentTask.run.runId !== task.run.runId)
|
|
@@ -1138,6 +1150,13 @@ export class AgentConversation extends Container {
|
|
|
1138
1150
|
task = currentTask;
|
|
1139
1151
|
history = withFinalResult(history, report.text, task.run.runId, task.run.updatedAt);
|
|
1140
1152
|
}
|
|
1153
|
+
if (!result.isCurrent()) {
|
|
1154
|
+
void this.loadPage(paging, anchor);
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
if (result.readThroughSequence !== undefined)
|
|
1158
|
+
this.readSequence = result.readThroughSequence;
|
|
1159
|
+
this.latestPage = result.latestPage;
|
|
1141
1160
|
task.history = history.items;
|
|
1142
1161
|
task.historyIds = history.entryIds;
|
|
1143
1162
|
task.finalId = history.finalId;
|
|
@@ -1159,6 +1178,10 @@ export class AgentConversation extends Container {
|
|
|
1159
1178
|
this.loadingPage = false;
|
|
1160
1179
|
if (this.task)
|
|
1161
1180
|
this.task.historyLoading = false;
|
|
1181
|
+
if (this.refreshPending && !this.pageError) {
|
|
1182
|
+
this.refreshPending = false;
|
|
1183
|
+
this.refresh();
|
|
1184
|
+
}
|
|
1162
1185
|
this.tui.requestRender();
|
|
1163
1186
|
}
|
|
1164
1187
|
}
|
|
@@ -1178,8 +1201,12 @@ export class AgentConversation extends Container {
|
|
|
1178
1201
|
this.detail = this.assignment();
|
|
1179
1202
|
if (!this.initialPosition && !this.scroll.isFollowingEnd)
|
|
1180
1203
|
this.restoreAnchor = this.anchor();
|
|
1181
|
-
if (
|
|
1182
|
-
|
|
1204
|
+
if (this.latestPage && this.scroll.isFollowingEnd && !this.detail && !this.pageError) {
|
|
1205
|
+
if (this.loadingPage)
|
|
1206
|
+
this.refreshPending = true;
|
|
1207
|
+
else
|
|
1208
|
+
void this.loadPage();
|
|
1209
|
+
}
|
|
1183
1210
|
this.tui.requestRender();
|
|
1184
1211
|
}
|
|
1185
1212
|
syncDraft() { if (!this.closed && this.editor.getExpandedText() !== this.visit.draft)
|
package/docs/intercom-bridge.md
CHANGED
|
@@ -14,7 +14,7 @@ Optional HTTPS messaging proxy for a remote agent such as **Grok Bot**. Pi-inter
|
|
|
14
14
|
|
|
15
15
|
**Delivery/lifecycle:** one broker peer per authorized certificate, registered lazily on the first API call, with a five-minute inactivity lease. Poll inbox to maintain presence. Send returns broker acceptance, not proof a model consumed it. Ask steers the recipient and waits at most two minutes for both the exact recipient ID and exact `replyTo`. One outgoing ask per identity. Revocation/expiry/shutdown/client disconnect terminate waits. Inbox is bounded and volatile; overflow is reported, not silently described as successful receipt. Restarting the helper loses inbox contents and pending replies. Upgrade to a durable inbox journal if restart recovery is required; existing Pi recipients still save their own messages normally.
|
|
16
16
|
|
|
17
|
-
**Audit:** JSONL metadata on stdout: request/connection identity, certificate fingerprint, operation, peer/message IDs and outcome. Message/attachment bodies and keys are not logged. Protect logs (0700 directory, 0600 files); rotate them with your normal log tooling. Never publish private config/keys or raw inbox/list output as smoke evidence.
|
|
17
|
+
**Audit:** JSONL metadata on stdout: request/connection identity, certificate fingerprint, operation, peer/message IDs and outcome. `session_closed` confirms broker disconnection and removal of the retiring session; cancellation still rejects requests immediately. Message/attachment bodies and keys are not logged. Protect logs (0700 directory, 0600 files); rotate them with your normal log tooling. Never publish private config/keys or raw inbox/list output as smoke evidence.
|
|
18
18
|
|
|
19
19
|
## Mac setup
|
|
20
20
|
|
package/package.json
CHANGED
|
@@ -287,8 +287,8 @@ class Session {
|
|
|
287
287
|
try { await this.connecting; } catch { /* The original request receives the connect failure. */ }
|
|
288
288
|
await this.disconnect();
|
|
289
289
|
if (this.bridge.sessions.get(this.identity.fingerprint256) === this) this.bridge.sessions.delete(this.identity.fingerprint256);
|
|
290
|
+
log("session_closed", { ...this.fields(), result: error.code });
|
|
290
291
|
})();
|
|
291
|
-
log("session_closed", { ...this.fields(), result: error.code });
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
private receive(from: SessionInfo, message: Message): void {
|
package/src/tui/agent-view.ts
CHANGED
|
@@ -70,6 +70,7 @@ export interface AgentTask {
|
|
|
70
70
|
replied: boolean;
|
|
71
71
|
page?: HistoryPage;
|
|
72
72
|
historyLoading?: boolean;
|
|
73
|
+
historySource?: string;
|
|
73
74
|
metadataAt?: number;
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -332,7 +333,7 @@ export class AgentViewController {
|
|
|
332
333
|
activity: { ...prior.child.activity, ...child.activity } } : child;
|
|
333
334
|
return { key, label: child.identityUnavailable ? "Saved assignment unavailable" : sameAttempt ? agentTaskLabel(child) : prior?.label ?? agentTaskLabel(child), run: view, child: displayChild,
|
|
334
335
|
model: agentModel(displayChild, child.nativeConfiguration ?? (canonical && sameAttempt && child.sessionFile === prior.child.sessionFile ? prior.page?.configuration : undefined)), history: sameAttempt ? prior.history : [], historyIds: sameAttempt ? prior.historyIds : [],
|
|
335
|
-
page: sameAttempt ? prior.page : undefined, metadataAt: observed ? prior.metadataAt : undefined, historyLoading: sameAttempt ? prior.historyLoading : false, finalId: sameAttempt ? prior.finalId : undefined, unavailable: child.missingSession && child.state !== "live" ? "Saved conversation unavailable." : view.diagnosis,
|
|
336
|
+
page: sameAttempt ? prior.page : undefined, historySource: sameAttempt ? prior.historySource : undefined, metadataAt: observed ? prior.metadataAt : undefined, historyLoading: sameAttempt ? prior.historyLoading : false, finalId: sameAttempt ? prior.finalId : undefined, unavailable: child.missingSession && child.state !== "live" ? "Saved conversation unavailable." : view.diagnosis,
|
|
336
337
|
question: child.identityUnavailable ? undefined : questions.findLast((question) => question.index === child.index && ["awaiting_input", "answer_pending"].includes(question.state)),
|
|
337
338
|
unread: observed ? prior.unread : Boolean(visit && (child.activity?.lastActivityAt ?? view.updatedAt) > (visit.seenActivityAt ?? 0)), replied: sameAttempt ? prior.replied : false };
|
|
338
339
|
});
|
|
@@ -457,10 +458,21 @@ export class AgentViewController {
|
|
|
457
458
|
if (this.live(generation)) await this.refresh();
|
|
458
459
|
}
|
|
459
460
|
|
|
460
|
-
async historyPage(key: string, paging: Pick<HistoryPageInput, "before" | "after" | "cursor"> = {}, anchor?: string | null): Promise<{ history: AgentHistory; page: HistoryPage; latestPage: boolean; readThroughSequence?: number } | undefined> {
|
|
461
|
+
async historyPage(key: string, paging: Pick<HistoryPageInput, "before" | "after" | "cursor"> = {}, anchor?: string | null): Promise<{ history: AgentHistory; page: HistoryPage; latestPage: boolean; readThroughSequence?: number; isCurrent: () => boolean } | undefined> {
|
|
461
462
|
const task = this.task(key), generation = this.generation;
|
|
462
463
|
if (!task || !this.live() || task.child.identityUnavailable) return;
|
|
464
|
+
const published = task.page, source = task.historySource, sessionFile = task.child.sessionFile, childState = task.child.state;
|
|
463
465
|
const input = this.historyInput(task), index = await runHistoryIndex(this.state);
|
|
466
|
+
// Versions can reset on index reopen. Fence the actual owner/read baseline,
|
|
467
|
+
// including metadata-only source transitions, rather than ordering unrelated versions.
|
|
468
|
+
const isCurrent = () => {
|
|
469
|
+
const current = this.task(key);
|
|
470
|
+
if (!this.live(generation) || this.state.historyIndex !== index || index.failure || !current || current.child.identityUnavailable
|
|
471
|
+
|| current.page !== published || current.historySource !== source || current.child.sessionFile !== sessionFile || current.child.state !== childState) return false;
|
|
472
|
+
const boundary = this.historyInput(current);
|
|
473
|
+
return boundary.runId === input.runId && boundary.index === input.index && boundary.leaf === input.leaf
|
|
474
|
+
&& boundary.terminalEntryId === input.terminalEntryId && boundary.endedAt === input.endedAt;
|
|
475
|
+
};
|
|
464
476
|
const boundary = { runId: task.run.runId, index: task.child.index, terminalEntryId: input.terminalEntryId, endedAt: input.endedAt };
|
|
465
477
|
const marker = typeof input.readThrough === "string" && !input.readThrough.startsWith("result:")
|
|
466
478
|
? await index.entry({ ...boundary, entryId: input.readThrough.replace(/:(?:\d+|error)$/, "") }) : undefined;
|
|
@@ -471,7 +483,7 @@ export class AgentViewController {
|
|
|
471
483
|
}
|
|
472
484
|
const result = await indexedHistory(index, { ...input, limit: 100, ...paging });
|
|
473
485
|
if (!this.live(generation) || this.task(key)?.run.runId !== task.run.runId) return;
|
|
474
|
-
return { ...result, latestPage: paging.after !== undefined ? !result.page.hasMore : paging.before === undefined && paging.cursor === undefined,
|
|
486
|
+
return { ...result, isCurrent, latestPage: paging.after !== undefined ? !result.page.hasMore : paging.before === undefined && paging.cursor === undefined,
|
|
475
487
|
readThroughSequence: marker?.sequence ?? (input.readThrough == null ? -1 : undefined) };
|
|
476
488
|
}
|
|
477
489
|
|
|
@@ -494,6 +506,7 @@ export class AgentViewController {
|
|
|
494
506
|
|
|
495
507
|
applyMetadata(task: AgentTask, page: HistoryPage): void {
|
|
496
508
|
const visit = this.visits.get(task.key), delivered = new Map(page.deliveredMessages);
|
|
509
|
+
task.historySource = JSON.stringify([page.sourceId, page.generation, page.sessionId]);
|
|
497
510
|
if (page.freshness.state !== "catching-up") task.metadataAt = task.run.updatedAt;
|
|
498
511
|
task.model = agentModel(task.child, page.configuration);
|
|
499
512
|
task.unread = Boolean(page.unreadAfter || visit && (task.child.activity?.lastActivityAt ?? 0) > (visit.seenActivityAt ?? 0));
|
|
@@ -865,6 +878,7 @@ export class AgentConversation extends Container {
|
|
|
865
878
|
private pageRequest = 0;
|
|
866
879
|
private detailRequest = 0;
|
|
867
880
|
private loadingPage = false;
|
|
881
|
+
private refreshPending = false;
|
|
868
882
|
private pageError?: string;
|
|
869
883
|
private latestPage = true;
|
|
870
884
|
private readSequence = -1;
|
|
@@ -953,6 +967,7 @@ export class AgentConversation extends Container {
|
|
|
953
967
|
private async loadPage(paging: Pick<HistoryPageInput, "before" | "after" | "cursor"> = {}, anchor?: string | null): Promise<void> {
|
|
954
968
|
if (this.closed) return;
|
|
955
969
|
const request = ++this.pageRequest;
|
|
970
|
+
this.refreshPending = false;
|
|
956
971
|
this.loadingPage = true; this.pageError = undefined;
|
|
957
972
|
if (this.task) this.task.historyLoading = true;
|
|
958
973
|
this.latestPage = paging.before === undefined && paging.after === undefined && paging.cursor === undefined;
|
|
@@ -966,16 +981,17 @@ export class AgentConversation extends Container {
|
|
|
966
981
|
if (reportPage) result = reportPage;
|
|
967
982
|
}
|
|
968
983
|
let task = this.task;
|
|
969
|
-
if (result.readThroughSequence !== undefined) this.readSequence = result.readThroughSequence;
|
|
970
|
-
this.latestPage = result.latestPage;
|
|
971
984
|
let history = result.history;
|
|
972
|
-
if ((this.initialPosition ||
|
|
985
|
+
if ((this.initialPosition || result.latestPage || history.finalId && history.entryIds.includes(history.finalId)) && task.child.state !== "live" && task.child.result && getSingleResultOutput(task.child.result)) {
|
|
973
986
|
const report = await this.controller.savedResult(this.key, `result:${task.run.runId}`);
|
|
974
987
|
const currentTask = this.task;
|
|
975
988
|
if (this.closed || request !== this.pageRequest || !currentTask || currentTask.run.runId !== task.run.runId) return;
|
|
976
989
|
task = currentTask;
|
|
977
990
|
history = withFinalResult(history, report.text, task.run.runId, task.run.updatedAt);
|
|
978
991
|
}
|
|
992
|
+
if (!result.isCurrent()) { void this.loadPage(paging, anchor); return; }
|
|
993
|
+
if (result.readThroughSequence !== undefined) this.readSequence = result.readThroughSequence;
|
|
994
|
+
this.latestPage = result.latestPage;
|
|
979
995
|
task.history = history.items; task.historyIds = history.entryIds; task.finalId = history.finalId; task.page = result.page;
|
|
980
996
|
for (const item of task.history) if (item.id === `result:${task.run.runId}`) item.load = () => this.controller.savedResult(this.key, item.id);
|
|
981
997
|
this.seenSource ||= result.page.count > 0;
|
|
@@ -985,7 +1001,11 @@ export class AgentConversation extends Container {
|
|
|
985
1001
|
} catch (error) {
|
|
986
1002
|
if (!this.closed && request === this.pageRequest) this.pageError = `History unavailable: ${error instanceof Error ? error.message : String(error)}. F5 retries the selected run.`;
|
|
987
1003
|
} finally {
|
|
988
|
-
if (!this.closed && request === this.pageRequest) {
|
|
1004
|
+
if (!this.closed && request === this.pageRequest) {
|
|
1005
|
+
this.loadingPage = false; if (this.task) this.task.historyLoading = false;
|
|
1006
|
+
if (this.refreshPending && !this.pageError) { this.refreshPending = false; this.refresh(); }
|
|
1007
|
+
this.tui.requestRender();
|
|
1008
|
+
}
|
|
989
1009
|
}
|
|
990
1010
|
}
|
|
991
1011
|
|
|
@@ -1001,7 +1021,10 @@ export class AgentConversation extends Container {
|
|
|
1001
1021
|
if (this.closed) return;
|
|
1002
1022
|
if (this.detail?.id === "assignment" && this.task) this.detail = this.assignment();
|
|
1003
1023
|
if (!this.initialPosition && !this.scroll.isFollowingEnd) this.restoreAnchor = this.anchor();
|
|
1004
|
-
if (
|
|
1024
|
+
if (this.latestPage && this.scroll.isFollowingEnd && !this.detail && !this.pageError) {
|
|
1025
|
+
if (this.loadingPage) this.refreshPending = true;
|
|
1026
|
+
else void this.loadPage();
|
|
1027
|
+
}
|
|
1005
1028
|
this.tui.requestRender();
|
|
1006
1029
|
}
|
|
1007
1030
|
syncDraft(): void { if (!this.closed && this.editor.getExpandedText() !== this.visit.draft) this.editor.setText(this.visit.draft); }
|