jupyterlab_ai_code_assistants_extension 1.0.29 → 1.0.30
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/lib/index.js +35 -4
- package/package.json +1 -1
- package/src/index.ts +37 -4
package/lib/index.js
CHANGED
|
@@ -64,18 +64,34 @@ const plugin = {
|
|
|
64
64
|
let status = null;
|
|
65
65
|
let settings = null;
|
|
66
66
|
let sidebar = DEFAULT_SIDEBAR;
|
|
67
|
+
let probeGeneration = 0;
|
|
67
68
|
/** Ask the server which providers exist and which of their binaries are on
|
|
68
|
-
* PATH.
|
|
69
|
-
* dialog,
|
|
69
|
+
* PATH. An unsuperseded failure leaves the extension activated with no
|
|
70
|
+
* panels until a later probe succeeds - never a dialog, never a thrown
|
|
71
|
+
* activation.
|
|
72
|
+
*
|
|
73
|
+
* Probes overlap: a probe can outlive one issued after it, so verdicts do
|
|
74
|
+
* not arrive in the order they were asked for. A ROSTER is always written,
|
|
75
|
+
* whichever settles last - both are answers from the same server, and the
|
|
76
|
+
* loser is at worst one client deadline stale (DEF-125). A FAILURE is not an answer, so it
|
|
77
|
+
* is written only while no newer probe has been issued; otherwise a
|
|
78
|
+
* timeout could discard a roster the server has since confirmed, undocking
|
|
79
|
+
* every panel while it is healthy (DEF-121). No request is suppressed. */
|
|
70
80
|
const probeStatus = async () => {
|
|
81
|
+
const mine = ++probeGeneration;
|
|
71
82
|
try {
|
|
72
83
|
status = await requestAPI('status', serverSettings, {
|
|
73
84
|
cache: 'no-store'
|
|
74
85
|
});
|
|
75
86
|
}
|
|
76
87
|
catch (err) {
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
// No cadence named here: this also prints from the activation probe,
|
|
89
|
+
// and neither the interval nor the wake listeners are armed until
|
|
90
|
+
// after `await migrate()` below (DEF-122).
|
|
91
|
+
console.warn(`${LOG_PREFIX} status probe failed; panels dock again once a later probe succeeds.`, err);
|
|
92
|
+
if (mine === probeGeneration) {
|
|
93
|
+
status = null;
|
|
94
|
+
}
|
|
79
95
|
}
|
|
80
96
|
};
|
|
81
97
|
const statusFor = (id) => { var _a, _b; return (_b = (_a = status === null || status === void 0 ? void 0 : status.providers) === null || _a === void 0 ? void 0 : _a.find(p => p.id === id)) !== null && _b !== void 0 ? _b : null; };
|
|
@@ -306,6 +322,21 @@ const plugin = {
|
|
|
306
322
|
window.setInterval(() => {
|
|
307
323
|
void probeStatus().then(reconcile);
|
|
308
324
|
}, STATUS_INTERVAL_MS);
|
|
325
|
+
// A suspended network stack - laptop asleep, tab backgrounded - is exactly
|
|
326
|
+
// when the probe fails, and the slow cadence above would leave the sidebar
|
|
327
|
+
// panel-less for up to a minute after the machine comes back. A wake fires
|
|
328
|
+
// both events, so it costs two probes; deliberately, because a guard that
|
|
329
|
+
// let the second join the first answered the wake with a request issued
|
|
330
|
+
// before it, and starved the interval above of its own tick (DEF-117).
|
|
331
|
+
const reprobe = () => {
|
|
332
|
+
void probeStatus().then(reconcile);
|
|
333
|
+
};
|
|
334
|
+
window.addEventListener('online', reprobe);
|
|
335
|
+
document.addEventListener('visibilitychange', () => {
|
|
336
|
+
if (document.visibilityState === 'visible') {
|
|
337
|
+
reprobe();
|
|
338
|
+
}
|
|
339
|
+
});
|
|
309
340
|
console.log(`${LOG_PREFIX} ${live.size} of ${registry.ids.length} assistant panel(s) docked.`);
|
|
310
341
|
}
|
|
311
342
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab_ai_code_assistants_extension",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "Jupyterlab extension to replace individual jupyterlab_*_code_extension and integrate into one, that offers joint capability, joint settings page and individual right toolbar panels per code assistant, with the ability in settings to decide which code assistant support is on (default - all are enabled)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
package/src/index.ts
CHANGED
|
@@ -116,20 +116,37 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
116
116
|
let settings: ISettingRegistry.ISettings | null = null;
|
|
117
117
|
let sidebar: Sidebar = DEFAULT_SIDEBAR;
|
|
118
118
|
|
|
119
|
+
let probeGeneration = 0;
|
|
120
|
+
|
|
119
121
|
/** Ask the server which providers exist and which of their binaries are on
|
|
120
|
-
* PATH.
|
|
121
|
-
* dialog,
|
|
122
|
+
* PATH. An unsuperseded failure leaves the extension activated with no
|
|
123
|
+
* panels until a later probe succeeds - never a dialog, never a thrown
|
|
124
|
+
* activation.
|
|
125
|
+
*
|
|
126
|
+
* Probes overlap: a probe can outlive one issued after it, so verdicts do
|
|
127
|
+
* not arrive in the order they were asked for. A ROSTER is always written,
|
|
128
|
+
* whichever settles last - both are answers from the same server, and the
|
|
129
|
+
* loser is at worst one client deadline stale (DEF-125). A FAILURE is not an answer, so it
|
|
130
|
+
* is written only while no newer probe has been issued; otherwise a
|
|
131
|
+
* timeout could discard a roster the server has since confirmed, undocking
|
|
132
|
+
* every panel while it is healthy (DEF-121). No request is suppressed. */
|
|
122
133
|
const probeStatus = async (): Promise<void> => {
|
|
134
|
+
const mine = ++probeGeneration;
|
|
123
135
|
try {
|
|
124
136
|
status = await requestAPI<IStatusResponse>('status', serverSettings, {
|
|
125
137
|
cache: 'no-store'
|
|
126
138
|
});
|
|
127
139
|
} catch (err) {
|
|
140
|
+
// No cadence named here: this also prints from the activation probe,
|
|
141
|
+
// and neither the interval nor the wake listeners are armed until
|
|
142
|
+
// after `await migrate()` below (DEF-122).
|
|
128
143
|
console.warn(
|
|
129
|
-
`${LOG_PREFIX} status probe failed;
|
|
144
|
+
`${LOG_PREFIX} status probe failed; panels dock again once a later probe succeeds.`,
|
|
130
145
|
err
|
|
131
146
|
);
|
|
132
|
-
|
|
147
|
+
if (mine === probeGeneration) {
|
|
148
|
+
status = null;
|
|
149
|
+
}
|
|
133
150
|
}
|
|
134
151
|
};
|
|
135
152
|
|
|
@@ -392,6 +409,22 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
392
409
|
void probeStatus().then(reconcile);
|
|
393
410
|
}, STATUS_INTERVAL_MS);
|
|
394
411
|
|
|
412
|
+
// A suspended network stack - laptop asleep, tab backgrounded - is exactly
|
|
413
|
+
// when the probe fails, and the slow cadence above would leave the sidebar
|
|
414
|
+
// panel-less for up to a minute after the machine comes back. A wake fires
|
|
415
|
+
// both events, so it costs two probes; deliberately, because a guard that
|
|
416
|
+
// let the second join the first answered the wake with a request issued
|
|
417
|
+
// before it, and starved the interval above of its own tick (DEF-117).
|
|
418
|
+
const reprobe = (): void => {
|
|
419
|
+
void probeStatus().then(reconcile);
|
|
420
|
+
};
|
|
421
|
+
window.addEventListener('online', reprobe);
|
|
422
|
+
document.addEventListener('visibilitychange', () => {
|
|
423
|
+
if (document.visibilityState === 'visible') {
|
|
424
|
+
reprobe();
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
395
428
|
console.log(
|
|
396
429
|
`${LOG_PREFIX} ${live.size} of ${registry.ids.length} assistant panel(s) docked.`
|
|
397
430
|
);
|