Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/components/Actions/Actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,9 @@ export default function Actions() {
explorer.mountDrive(driveUrl){"\n"}
explorer.openPicker(){"\n"}
explorer.listFolders(){"\n"}
runme.getCurrentNotebook(){"\n"}
runme.clearOutputs(runme.getCurrentNotebook()){"\n"}
runme.runAll(runme.getCurrentNotebook()){"\n"}
help(){"\n\n"}
To attach test notebooks: use the Explorer + button to pick the fixtures folder
{"\n"}
Expand Down
72 changes: 71 additions & 1 deletion app/src/components/AppConsole/AppConsole.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ import { JSKernel } from "../../lib/runtime/jsKernel";
import { useRunners } from "../../contexts/RunnersContext";
import { useWorkspace } from "../../contexts/WorkspaceContext";
import { useFilesystemStore } from "../../contexts/FilesystemStoreContext";
import { useCurrentDoc } from "../../contexts/CurrentDocContext";
import { useNotebookContext } from "../../contexts/NotebookContext";
import { appState } from "../../lib/runtime/AppState";
import {
FilesystemNotebookStore,
isFileSystemAccessSupported,
} from "../../storage/fs";
import { Runner } from "../../lib/runner";
import { getRunnersManager } from "../../lib/runtime/runnersManager";
import {
createRunmeConsoleApi,
type NotebookDataLike,
} from "../../lib/runtime/runmeConsole";
import { googleClientManager } from "../../lib/googleClientManager";
import { oidcConfigManager } from "../../auth/oidcConfig";
import type { OidcConfig } from "../../auth/oidcConfig";
Expand Down Expand Up @@ -66,6 +72,8 @@ export default function AppConsole() {
// WorkspaceContext provides the persisted list of workspace URIs so we can
// mount/unmount folders from the App Console without drilling props.
const { getItems, addItem, removeItem } = useWorkspace();
const { getCurrentDoc } = useCurrentDoc();
const { getNotebookData } = useNotebookContext();
// FilesystemStoreContext owns the File System Access API store instance that
// actually opens folders and produces fs:// workspace URIs.
const { fsStore, setFsStore } = useFilesystemStore();
Expand Down Expand Up @@ -136,10 +144,66 @@ export default function AppConsole() {
return "Opening directory picker...";
}, [addItem, ensureFilesystemStore, getItems, sendStdout]);

const resolveNotebookData = useCallback(
(target?: unknown): NotebookDataLike | null => {
if (target && typeof target === "object") {
const candidate = target as Partial<NotebookDataLike>;
if (
typeof candidate.getUri === "function" &&
typeof candidate.getName === "function" &&
typeof candidate.getNotebook === "function" &&
typeof candidate.updateCell === "function" &&
typeof candidate.getCell === "function"
) {
return candidate as NotebookDataLike;
}
}

if (typeof target === "string" && target.trim() !== "") {
return getNotebookData(target) ?? null;
}

const uri = getCurrentDoc();
if (!uri) {
return null;
}
return getNotebookData(uri) ?? null;
},
[getCurrentDoc, getNotebookData],
);

const runme = useMemo(
() =>
createRunmeConsoleApi({
resolveNotebook: resolveNotebookData,
}),
[resolveNotebookData],
);

const kernel = useMemo(
() =>
new JSKernel({
globals: {
runme: {
getCurrentNotebook: () => {
return runme.getCurrentNotebook();
},
clearOutputs: (target?: unknown) => {
const message = runme.clearOutputs(target);
sendStdout(`${message}\r\n`);
return message;
},
runAll: (target?: unknown) => {
const message = runme.runAll(target);
sendStdout(`${message}\r\n`);
return message;
},
help: () => {
const message = runme.help();
sendStdout(`${message}\r\n`);
return message;
},
},
aisreRunners: {
get: () => {
const mgr = getRunnersManager();
Expand Down Expand Up @@ -291,8 +355,9 @@ export default function AppConsole() {
},
},
help: () => {
return [
const message = [
"Available namespaces:",
" runme - Notebook helpers (run all, clear outputs)",
" explorer - Manage workspace folders and notebooks",
" aisreRunners - Configure runner endpoints",
" oidc - OIDC/OAuth configuration and auth status",
Expand All @@ -302,6 +367,8 @@ export default function AppConsole() {
"",
"Type <namespace>.help() for detailed commands, e.g. explorer.help()",
].join("\n");
sendStdout(`${message}\r\n`);
return message;
},
explorer: {
addFolder: (path?: string) => {
Expand Down Expand Up @@ -363,11 +430,14 @@ export default function AppConsole() {
addItem,
defaultRunnerName,
deleteRunner,
getCurrentDoc,
getItems,
getNotebookData,
listRunners,
ensureFilesystemStore,
openWorkspaceAndAdd,
removeItem,
runme,
sendStdout,
updateRunner,
],
Expand Down
37 changes: 21 additions & 16 deletions app/src/lib/runtime/jsKernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ export class JSKernel {
stdout,
appRunners,
);
const globalHelp =
(options.globals?.help as (() => unknown) | undefined) ??
(this.baseGlobals.help as (() => unknown) | undefined);

const mergedGlobals: Record<string, unknown> = {
...this.baseGlobals,
Expand All @@ -82,22 +85,24 @@ export class JSKernel {
app,
// Keep `aisre` as a compatibility alias for existing snippets.
aisre: app,
help: () =>
stdout(
[
"App JS console helpers:",
"- d3: D3.js",
"- app.clear(): clear the render container",
"- app.render(fn): render into the container with a D3 selection",
"- console.log/info/warn/error: write to this console",
"- app.runners.get(): list configured runners",
"- app.runners.update(name, endpoint): add/update a runner",
"- app.runners.delete(name): remove a runner",
"- app.runners.getDefault(): show default runner",
"- app.runners.setDefault(name): set default runner",
"- help(): show this message",
].join("\n") + "\n",
),
help:
globalHelp ??
(() =>
stdout(
[
"App JS console helpers:",
"- d3: D3.js",
"- app.clear(): clear the render container",
"- app.render(fn): render into the container with a D3 selection",
"- console.log/info/warn/error: write to this console",
"- app.runners.get(): list configured runners",
"- app.runners.update(name, endpoint): add/update a runner",
"- app.runners.delete(name): remove a runner",
"- app.runners.getDefault(): show default runner",
"- app.runners.setDefault(name): set default runner",
"- help(): show this message",
].join("\n") + "\n",
)),
};

const argNames = Object.keys(mergedGlobals);
Expand Down
Loading