jupyterlab_ai_code_assistants_extension 1.0.29 → 1.0.31
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 +1 -0
- package/lib/index.js +35 -4
- package/package.json +1 -1
- package/src/index.ts +37 -4
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ Chat-panel extensions re-implement the agent loop and trail the real tool. This
|
|
|
30
30
|
- **Joint settings page** - one settings section covering all assistants, with a per-assistant toggle (all on by default); toggling takes effect live, no JupyterLab reload
|
|
31
31
|
- **Three-section side panel** - Favorites, Recent, and All projects, each scrolling independently
|
|
32
32
|
- **One-click resume** - click a row to jump back into that session in a terminal; an open terminal for the project is reused instead of duplicated
|
|
33
|
+
- **Your terminal's `claude -c` follows the panel** (Claude) - switching to or launching a conversation makes plain `claude -c` in that project resume that same conversation, including one that has been compacted, which Claude Code otherwise refuses to continue
|
|
33
34
|
- **Conversation switcher** - a right-click "Switch and Manage Sessions" submenu lists a project's other conversations by name and short id with last-activity time; "Manage Sessions..." opens a searchable popup over the full list with multi-select delete and per-row open and copy-id buttons
|
|
34
35
|
- **Branch session** - fork the current conversation into a new named session via the right-click menu; each assistant forks its own way (Claude's native `--fork-session`, Codex's `codex fork`, server-side copies for Kimi and Gemini) behind the same menu item
|
|
35
36
|
- **Launch modes under each assistant's own name** - Claude's skip-permissions, Codex's approval bypass, Kimi's `--yolo`, Gemini's YOLO; unsafe variants carry a shield glyph in the launch menus
|
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.31",
|
|
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
|
);
|