@plmbr/notebook-intelligence 5.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.
Files changed (137) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +412 -0
  3. package/lib/api.d.ts +288 -0
  4. package/lib/api.js +927 -0
  5. package/lib/cell-output-bundle.d.ts +25 -0
  6. package/lib/cell-output-bundle.js +129 -0
  7. package/lib/cell-output-toolbar.d.ts +26 -0
  8. package/lib/cell-output-toolbar.js +188 -0
  9. package/lib/chat-progress-feedback.d.ts +3 -0
  10. package/lib/chat-progress-feedback.js +27 -0
  11. package/lib/chat-sidebar.d.ts +92 -0
  12. package/lib/chat-sidebar.js +3452 -0
  13. package/lib/command-ids.d.ts +39 -0
  14. package/lib/command-ids.js +44 -0
  15. package/lib/components/ask-user-question.d.ts +2 -0
  16. package/lib/components/ask-user-question.js +85 -0
  17. package/lib/components/checkbox.d.ts +2 -0
  18. package/lib/components/checkbox.js +30 -0
  19. package/lib/components/claude-mcp-panel.d.ts +2 -0
  20. package/lib/components/claude-mcp-panel.js +275 -0
  21. package/lib/components/claude-mcp-paste.d.ts +7 -0
  22. package/lib/components/claude-mcp-paste.js +104 -0
  23. package/lib/components/claude-session-picker.d.ts +8 -0
  24. package/lib/components/claude-session-picker.js +127 -0
  25. package/lib/components/form-dialog.d.ts +25 -0
  26. package/lib/components/form-dialog.js +35 -0
  27. package/lib/components/launcher-picker.d.ts +6 -0
  28. package/lib/components/launcher-picker.js +135 -0
  29. package/lib/components/mcp-util.d.ts +2 -0
  30. package/lib/components/mcp-util.js +37 -0
  31. package/lib/components/notebook-generation-popover.d.ts +7 -0
  32. package/lib/components/notebook-generation-popover.js +60 -0
  33. package/lib/components/pill.d.ts +2 -0
  34. package/lib/components/pill.js +5 -0
  35. package/lib/components/plugins-panel.d.ts +3 -0
  36. package/lib/components/plugins-panel.js +466 -0
  37. package/lib/components/settings-panel.d.ts +11 -0
  38. package/lib/components/settings-panel.js +742 -0
  39. package/lib/components/skills-panel.d.ts +2 -0
  40. package/lib/components/skills-panel.js +1264 -0
  41. package/lib/handler.d.ts +8 -0
  42. package/lib/handler.js +36 -0
  43. package/lib/icons.d.ts +45 -0
  44. package/lib/icons.js +54 -0
  45. package/lib/index.d.ts +8 -0
  46. package/lib/index.js +2079 -0
  47. package/lib/markdown-renderer.d.ts +10 -0
  48. package/lib/markdown-renderer.js +64 -0
  49. package/lib/notebook-generation-toolbar.d.ts +16 -0
  50. package/lib/notebook-generation-toolbar.js +197 -0
  51. package/lib/notebook-generation.d.ts +8 -0
  52. package/lib/notebook-generation.js +12 -0
  53. package/lib/open-file-refresh-watcher-env.d.ts +4 -0
  54. package/lib/open-file-refresh-watcher-env.js +33 -0
  55. package/lib/open-file-refresh-watcher.d.ts +97 -0
  56. package/lib/open-file-refresh-watcher.js +190 -0
  57. package/lib/shell-utils.d.ts +6 -0
  58. package/lib/shell-utils.js +9 -0
  59. package/lib/task-target-notebook.d.ts +2 -0
  60. package/lib/task-target-notebook.js +28 -0
  61. package/lib/terminal-drag-format.d.ts +9 -0
  62. package/lib/terminal-drag-format.js +23 -0
  63. package/lib/terminal-drag.d.ts +12 -0
  64. package/lib/terminal-drag.js +268 -0
  65. package/lib/tokens.d.ts +149 -0
  66. package/lib/tokens.js +88 -0
  67. package/lib/tour/tour-anchors.d.ts +18 -0
  68. package/lib/tour/tour-anchors.js +18 -0
  69. package/lib/tour/tour-config.d.ts +66 -0
  70. package/lib/tour/tour-config.js +99 -0
  71. package/lib/tour/tour-defaults.json +58 -0
  72. package/lib/tour/tour-events.d.ts +19 -0
  73. package/lib/tour/tour-events.js +30 -0
  74. package/lib/tour/tour-overlay.d.ts +6 -0
  75. package/lib/tour/tour-overlay.js +350 -0
  76. package/lib/tour/tour-state.d.ts +20 -0
  77. package/lib/tour/tour-state.js +81 -0
  78. package/lib/tour/tour-steps.d.ts +33 -0
  79. package/lib/tour/tour-steps.js +216 -0
  80. package/lib/utils.d.ts +53 -0
  81. package/lib/utils.js +385 -0
  82. package/package.json +258 -0
  83. package/schema/plugin.json +42 -0
  84. package/src/api.ts +1424 -0
  85. package/src/cell-output-bundle.ts +176 -0
  86. package/src/cell-output-toolbar.ts +232 -0
  87. package/src/chat-progress-feedback.ts +35 -0
  88. package/src/chat-sidebar.tsx +5147 -0
  89. package/src/command-ids.ts +67 -0
  90. package/src/components/ask-user-question.tsx +151 -0
  91. package/src/components/checkbox.tsx +62 -0
  92. package/src/components/claude-mcp-panel.tsx +543 -0
  93. package/src/components/claude-mcp-paste.ts +132 -0
  94. package/src/components/claude-session-picker.tsx +214 -0
  95. package/src/components/form-dialog.tsx +75 -0
  96. package/src/components/launcher-picker.tsx +237 -0
  97. package/src/components/mcp-util.ts +53 -0
  98. package/src/components/notebook-generation-popover.tsx +127 -0
  99. package/src/components/pill.tsx +15 -0
  100. package/src/components/plugins-panel.tsx +774 -0
  101. package/src/components/settings-panel.tsx +1631 -0
  102. package/src/components/skills-panel.tsx +2084 -0
  103. package/src/handler.ts +51 -0
  104. package/src/icons.ts +71 -0
  105. package/src/index.ts +2583 -0
  106. package/src/markdown-renderer.tsx +153 -0
  107. package/src/notebook-generation-toolbar.tsx +281 -0
  108. package/src/notebook-generation.ts +23 -0
  109. package/src/open-file-refresh-watcher-env.ts +52 -0
  110. package/src/open-file-refresh-watcher.ts +260 -0
  111. package/src/shell-utils.ts +10 -0
  112. package/src/svg.d.ts +4 -0
  113. package/src/task-target-notebook.ts +37 -0
  114. package/src/terminal-drag-format.ts +29 -0
  115. package/src/terminal-drag.ts +382 -0
  116. package/src/tokens.ts +171 -0
  117. package/src/tour/tour-anchors.ts +21 -0
  118. package/src/tour/tour-config.ts +160 -0
  119. package/src/tour/tour-events.ts +34 -0
  120. package/src/tour/tour-overlay.tsx +474 -0
  121. package/src/tour/tour-state.ts +87 -0
  122. package/src/tour/tour-steps.ts +281 -0
  123. package/src/utils.ts +455 -0
  124. package/style/base.css +3238 -0
  125. package/style/icons/cell-toolbar-bug.svg +5 -0
  126. package/style/icons/cell-toolbar-chat.svg +5 -0
  127. package/style/icons/cell-toolbar-sparkle.svg +5 -0
  128. package/style/icons/claude.svg +1 -0
  129. package/style/icons/copilot-warning.svg +1 -0
  130. package/style/icons/copilot.svg +1 -0
  131. package/style/icons/copy.svg +1 -0
  132. package/style/icons/openai.svg +1 -0
  133. package/style/icons/opencode.svg +1 -0
  134. package/style/icons/sparkles-warning.svg +5 -0
  135. package/style/icons/sparkles.svg +1 -0
  136. package/style/index.css +1 -0
  137. package/style/index.js +1 -0
@@ -0,0 +1,81 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ /**
3
+ * localStorage-backed persistence for the first-run tour.
4
+ *
5
+ * The tour is shown exactly once per browser per major tour version. The
6
+ * version is bumped (in code) whenever the step set changes meaningfully
7
+ * so existing users get re-prompted instead of silently missing new
8
+ * onboarding content. Users can also re-run the tour on demand via the
9
+ * `notebook-intelligence:show-tour` command, which calls `resetTour()`.
10
+ *
11
+ * Why localStorage and not server-side state: the tour is purely UI; a
12
+ * round trip to the Jupyter server on every sidebar mount just to check
13
+ * a single flag would add latency to a hot path. localStorage is
14
+ * per-browser, which is the right granularity (a user signing in on a
15
+ * second browser benefits from seeing the tour again).
16
+ */
17
+ // Bump when the tour's step set changes meaningfully enough to want
18
+ // existing users to re-see it. Keys older than the current version are
19
+ // ignored, and writes always use the current version.
20
+ export const TOUR_VERSION = 1;
21
+ // Exported so tests can clear the same key the production code writes,
22
+ // instead of duplicating the string literal.
23
+ export const TOUR_STORAGE_KEY = 'nbi.tour.completed';
24
+ const TOUR_KEY = TOUR_STORAGE_KEY;
25
+ function safeStorage() {
26
+ // localStorage can throw under some sandboxed iframe / privacy modes;
27
+ // a thrown access here would crash the sidebar mount. Treat absence
28
+ // as "tour was never completed" rather than failing closed.
29
+ try {
30
+ return typeof window !== 'undefined' ? window.localStorage : null;
31
+ }
32
+ catch (_a) {
33
+ return null;
34
+ }
35
+ }
36
+ export function hasCompletedTour() {
37
+ const storage = safeStorage();
38
+ if (!storage) {
39
+ return false;
40
+ }
41
+ const raw = storage.getItem(TOUR_KEY);
42
+ if (!raw) {
43
+ return false;
44
+ }
45
+ try {
46
+ const parsed = JSON.parse(raw);
47
+ return (parsed === null || parsed === void 0 ? void 0 : parsed.version) === TOUR_VERSION;
48
+ }
49
+ catch (_a) {
50
+ // Stale / corrupt entry from an older NBI version. Treat as not
51
+ // completed; the next markCompleted will overwrite with the current
52
+ // shape.
53
+ return false;
54
+ }
55
+ }
56
+ export function markTourCompleted() {
57
+ const storage = safeStorage();
58
+ if (!storage) {
59
+ return;
60
+ }
61
+ try {
62
+ storage.setItem(TOUR_KEY, JSON.stringify({ version: TOUR_VERSION }));
63
+ }
64
+ catch (_a) {
65
+ // Quota exceeded / private mode rejecting writes. Worst case the
66
+ // tour fires again on the next sidebar mount, which is preferable
67
+ // to crashing the sidebar.
68
+ }
69
+ }
70
+ export function resetTour() {
71
+ const storage = safeStorage();
72
+ if (!storage) {
73
+ return;
74
+ }
75
+ try {
76
+ storage.removeItem(TOUR_KEY);
77
+ }
78
+ catch (_a) {
79
+ // See markTourCompleted.
80
+ }
81
+ }
@@ -0,0 +1,33 @@
1
+ export type TourPlacement = 'top' | 'bottom' | 'left' | 'right' | 'center';
2
+ export interface ITourStep {
3
+ id: string;
4
+ title: string;
5
+ description: string | (() => string);
6
+ anchorId: string | null;
7
+ placement: TourPlacement;
8
+ requires?: () => boolean;
9
+ }
10
+ interface IDefaultsSchema {
11
+ command?: {
12
+ label?: string;
13
+ };
14
+ ui?: {
15
+ skip?: string;
16
+ next?: string;
17
+ back?: string;
18
+ done?: string;
19
+ };
20
+ steps?: Record<string, {
21
+ title?: string;
22
+ description?: string;
23
+ description_singular?: string;
24
+ description_plural?: string;
25
+ }>;
26
+ }
27
+ export declare const TOUR_DEFAULTS: IDefaultsSchema;
28
+ export declare const ALL_TOUR_STEPS: readonly ITourStep[];
29
+ export type IResolvedTourStep = Omit<ITourStep, 'description'> & {
30
+ description: string;
31
+ };
32
+ export declare function activeTourSteps(): IResolvedTourStep[];
33
+ export {};
@@ -0,0 +1,216 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ /**
3
+ * Step definitions for the first-run tour.
4
+ *
5
+ * The copy (titles, descriptions, button labels, command palette
6
+ * label) lives in `tour-defaults.json`, which uses the same schema as
7
+ * an admin override file (see `docs/admin-tour-config.md`). The
8
+ * structural wiring (DOM anchor ids, placements, capability gates)
9
+ * lives in TypeScript because it isn't user-facing copy.
10
+ *
11
+ * Each step anchors to a DOM element by `data-tour-id` (added on the
12
+ * matching React element). Using a dedicated attribute rather than a
13
+ * CSS class makes the contract explicit and decouples the tour from
14
+ * styling changes.
15
+ *
16
+ * The `requires` predicate filters out steps that don't apply to the
17
+ * current deployment (e.g. the Claude history step is skipped when
18
+ * Claude CLI is not installed). Predicates close over the snapshot of
19
+ * capabilities at tour start, so a CLI being installed mid-tour does
20
+ * not retroactively insert a step.
21
+ */
22
+ import { NBIAPI } from '../api';
23
+ import { applyTourOverrides, launcherTileTemplates } from './tour-config';
24
+ import { TOUR_ANCHOR } from './tour-anchors';
25
+ import defaultsJson from './tour-defaults.json';
26
+ // Bundled defaults file. Same schema as an admin override; the
27
+ // override applier overlays the admin layer on top of these.
28
+ export const TOUR_DEFAULTS = defaultsJson;
29
+ function defaultText(stepId, key) {
30
+ var _a;
31
+ const step = (_a = TOUR_DEFAULTS.steps) === null || _a === void 0 ? void 0 : _a[stepId];
32
+ const value = step === null || step === void 0 ? void 0 : step[key];
33
+ return typeof value === 'string' ? value : '';
34
+ }
35
+ // Map every Coding Agent launcher id to (a) the capability flag that
36
+ // decides whether the tile shows up at all and (b) the display name
37
+ // the tour should use. Order matches what users see in the JL
38
+ // Launcher.
39
+ const CODING_AGENT_LAUNCHERS = [
40
+ {
41
+ id: 'claude-code',
42
+ label: 'Claude Code',
43
+ available: () => NBIAPI.config.isClaudeCliAvailable
44
+ },
45
+ {
46
+ id: 'codex',
47
+ label: 'Codex',
48
+ available: () => NBIAPI.config.isCodexCliAvailable
49
+ },
50
+ {
51
+ id: 'opencode',
52
+ label: 'opencode',
53
+ available: () => NBIAPI.config.isOpenCodeCliAvailable
54
+ },
55
+ {
56
+ id: 'pi',
57
+ label: 'Pi',
58
+ available: () => NBIAPI.config.isPiCliAvailable
59
+ },
60
+ {
61
+ id: 'github-copilot-cli',
62
+ label: 'GitHub Copilot CLI',
63
+ available: () => NBIAPI.config.isGitHubCopilotCliAvailable
64
+ }
65
+ ];
66
+ function visibleCodingAgentLaunchers() {
67
+ return CODING_AGENT_LAUNCHERS.filter(l => l.available() &&
68
+ !NBIAPI.config.isCodingAgentLauncherDisabledByPolicy(l.id)).map(l => l.label);
69
+ }
70
+ function formatLauncherList(names) {
71
+ if (names.length === 0) {
72
+ return '';
73
+ }
74
+ if (names.length === 1) {
75
+ return names[0];
76
+ }
77
+ if (names.length === 2) {
78
+ return `${names[0]} and ${names[1]}`;
79
+ }
80
+ return `${names.slice(0, -1).join(', ')}, and ${names[names.length - 1]}`;
81
+ }
82
+ function launcherTilesDescription() {
83
+ var _a, _b, _c;
84
+ const names = visibleCodingAgentLaunchers();
85
+ const list = formatLauncherList(names);
86
+ // Admin overrides win; defaults supply the fallback templates.
87
+ const overrideTemplates = launcherTileTemplates(NBIAPI.config.tourOverrides);
88
+ const defaultStep = (_a = TOUR_DEFAULTS.steps) === null || _a === void 0 ? void 0 : _a['launcher-tiles'];
89
+ const template = names.length === 1
90
+ ? ((_b = overrideTemplates.singular) !== null && _b !== void 0 ? _b : defaultStep === null || defaultStep === void 0 ? void 0 : defaultStep.description_singular)
91
+ : ((_c = overrideTemplates.plural) !== null && _c !== void 0 ? _c : defaultStep === null || defaultStep === void 0 ? void 0 : defaultStep.description_plural);
92
+ return template ? template.replace(/\{launchers\}/g, list) : '';
93
+ }
94
+ export const ALL_TOUR_STEPS = Object.freeze([
95
+ {
96
+ id: 'welcome',
97
+ title: defaultText('welcome', 'title'),
98
+ description: defaultText('welcome', 'description'),
99
+ anchorId: null,
100
+ placement: 'center'
101
+ },
102
+ {
103
+ id: 'new-chat',
104
+ title: defaultText('new-chat', 'title'),
105
+ description: defaultText('new-chat', 'description'),
106
+ anchorId: TOUR_ANCHOR.newChat,
107
+ placement: 'bottom',
108
+ // The + button is only rendered in Claude mode (it restarts the
109
+ // Claude client). Skip when not in Claude mode so the tour doesn't
110
+ // describe a missing affordance.
111
+ requires: () => NBIAPI.config.isInClaudeCodeMode
112
+ },
113
+ {
114
+ id: 'claude-history',
115
+ title: defaultText('claude-history', 'title'),
116
+ description: defaultText('claude-history', 'description'),
117
+ anchorId: TOUR_ANCHOR.claudeHistory,
118
+ placement: 'bottom',
119
+ // Visible only when Claude CLI is available AND Claude mode is on.
120
+ // Without the second guard the anchor isn't even rendered, so the
121
+ // tour would silently skip; the `requires` keeps the skip
122
+ // explicit.
123
+ requires: () => NBIAPI.config.isClaudeCliAvailable && NBIAPI.config.isInClaudeCodeMode
124
+ },
125
+ {
126
+ id: 'settings-gear',
127
+ title: defaultText('settings-gear', 'title'),
128
+ description: defaultText('settings-gear', 'description'),
129
+ anchorId: TOUR_ANCHOR.settingsGear,
130
+ placement: 'bottom'
131
+ },
132
+ {
133
+ id: 'slash-commands',
134
+ title: defaultText('slash-commands', 'title'),
135
+ description: defaultText('slash-commands', 'description'),
136
+ anchorId: TOUR_ANCHOR.slashCommands,
137
+ placement: 'top'
138
+ },
139
+ {
140
+ id: 'add-context',
141
+ title: defaultText('add-context', 'title'),
142
+ description: defaultText('add-context', 'description'),
143
+ anchorId: TOUR_ANCHOR.addContext,
144
+ placement: 'top'
145
+ },
146
+ {
147
+ id: 'upload-file',
148
+ title: defaultText('upload-file', 'title'),
149
+ description: defaultText('upload-file', 'description'),
150
+ anchorId: TOUR_ANCHOR.uploadFile,
151
+ placement: 'top'
152
+ },
153
+ {
154
+ id: 'drag-and-drop',
155
+ title: defaultText('drag-and-drop', 'title'),
156
+ description: defaultText('drag-and-drop', 'description'),
157
+ anchorId: TOUR_ANCHOR.promptInput,
158
+ placement: 'top'
159
+ },
160
+ {
161
+ id: 'chat-mode',
162
+ title: defaultText('chat-mode', 'title'),
163
+ description: defaultText('chat-mode', 'description'),
164
+ anchorId: TOUR_ANCHOR.chatMode,
165
+ placement: 'top',
166
+ // Mode picker is hidden in Claude mode (Claude owns its own loop).
167
+ requires: () => !NBIAPI.config.isInClaudeCodeMode
168
+ },
169
+ {
170
+ id: 'launcher-tiles',
171
+ title: defaultText('launcher-tiles', 'title'),
172
+ // Dynamic description so the step only mentions the CLI tools the
173
+ // user actually has installed. Skipped entirely when zero are
174
+ // available (see the requires predicate below). Both the default
175
+ // templates and admin overrides flow through this thunk so the
176
+ // {launchers} placeholder gets substituted with the same
177
+ // comma-joined list either way.
178
+ description: launcherTilesDescription,
179
+ anchorId: null,
180
+ placement: 'center',
181
+ // Skip the step on machines where no coding-agent CLI is installed
182
+ // (or admin policy hides every tile) so the tour doesn't promise an
183
+ // affordance the user can't reach.
184
+ requires: () => visibleCodingAgentLaunchers().length > 0
185
+ },
186
+ {
187
+ id: 'done',
188
+ title: defaultText('done', 'title'),
189
+ description: defaultText('done', 'description'),
190
+ anchorId: null,
191
+ placement: 'center'
192
+ }
193
+ ]);
194
+ export function activeTourSteps() {
195
+ // Pipeline:
196
+ // 1. Apply admin overrides (title/description rewrites, per-step
197
+ // enabled:false drops). The default-overrides path returns a
198
+ // shallow copy so the rest of the pipeline doesn't mutate the
199
+ // ALL_TOUR_STEPS module-level constant.
200
+ // 2. Filter on the per-step `requires()` predicate (capability /
201
+ // mode gates).
202
+ // 3. Resolve any thunk descriptions to plain strings so the
203
+ // overlay can render them directly. Doing this here (rather
204
+ // than at render time) matches the "snapshot on mount"
205
+ // semantics: a capability change mid-tour doesn't reshape step
206
+ // copy under the user.
207
+ const overrides = NBIAPI.config.tourOverrides;
208
+ return applyTourOverrides(ALL_TOUR_STEPS, overrides)
209
+ .filter(step => (step.requires ? step.requires() : true))
210
+ .map(step => ({
211
+ ...step,
212
+ description: typeof step.description === 'function'
213
+ ? step.description()
214
+ : step.description
215
+ }));
216
+ }
package/lib/utils.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import { CodeCell } from '@jupyterlab/cells';
2
+ import { CodeEditor } from '@jupyterlab/codeeditor';
3
+ import { IDocumentManager } from '@jupyterlab/docmanager';
4
+ import { NotebookPanel } from '@jupyterlab/notebook';
5
+ import { shellSingleQuote } from './shell-utils';
6
+ export declare function removeAnsiChars(str: string): string;
7
+ export declare function waitForDuration(duration: number): Promise<void>;
8
+ export declare function moveCodeSectionBoundaryMarkersToNewLine(source: string): string;
9
+ export declare function extractLLMGeneratedCode(code: string): string;
10
+ export declare function isDarkTheme(): boolean;
11
+ export declare function markdownToComment(source: string): string;
12
+ export declare function formatJupyterError(output: any): string;
13
+ export declare function cellOutputHasError(cell: CodeCell): boolean;
14
+ export declare function cellOutputAsText(cell: CodeCell): string;
15
+ export declare function joinMultilineString(value: unknown): string;
16
+ export declare function getTokenCount(source: string): number;
17
+ export declare function truncateToTokenCount(text: string, maxTokens: number): {
18
+ text: string;
19
+ size: number;
20
+ truncated: boolean;
21
+ };
22
+ export declare function compareSelectionPoints(lhs: CodeEditor.IPosition, rhs: CodeEditor.IPosition): boolean;
23
+ export declare function compareSelections(lhs: CodeEditor.IRange, rhs: CodeEditor.IRange): boolean;
24
+ export declare function isSelectionEmpty(selection: CodeEditor.IRange): boolean;
25
+ export declare function getSelectionInEditor(editor: CodeEditor.IEditor): string;
26
+ export declare function getWholeNotebookContent(np: NotebookPanel): string;
27
+ export declare function applyCodeToSelectionInEditor(editor: CodeEditor.IEditor, code: string): void;
28
+ export { shellSingleQuote };
29
+ /**
30
+ * Return `uri` if its scheme is in the chat-anchor allowlist, else null.
31
+ * Mirrors the server-side `safe_anchor_uri` check so that anchor parts
32
+ * coming from arbitrary LLM/tool output cannot render `javascript:`,
33
+ * `data:`, `vbscript:`, `blob:`, or other dangerous schemes through React's
34
+ * `href` attribute. The server applies the same filter at emit time; this
35
+ * is defense in depth for stream replays, persisted history, and any path
36
+ * that injects anchor parts directly into the React tree.
37
+ */
38
+ export declare function safeAnchorUri(uri: string | undefined | null): string | null;
39
+ /**
40
+ * Build a `claude --resume <id>` command wrapped in `cd <cwd>` so the
41
+ * resulting one-liner works from any terminal. `claude --resume` is
42
+ * cwd-scoped — it looks up the transcript under the encoded form of the
43
+ * user's CURRENT shell cwd — so the bare id alone only works when the
44
+ * user happens to be in the JupyterLab working directory.
45
+ */
46
+ export declare function buildResumeCommand(cwd: string, sessionId: string): string;
47
+ /**
48
+ * Write `text` to the system clipboard. Falls back to a hidden textarea +
49
+ * `document.execCommand('copy')` when the async Clipboard API is unavailable
50
+ * or rejects (e.g. missing permission, insecure context).
51
+ */
52
+ export declare function writeTextToClipboard(text: string): Promise<boolean>;
53
+ export declare function chooseWorkspaceDirectory(docManager: IDocumentManager, label: string, defaultPath?: string): Promise<string | undefined>;