@oceanum/oceanumlab 4.6.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 (83) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +116 -0
  3. package/lib/DatameshUI.d.ts +5 -0
  4. package/lib/DatameshUI.js +8 -0
  5. package/lib/DatameshUI.js.map +1 -0
  6. package/lib/DatameshWidget.d.ts +59 -0
  7. package/lib/DatameshWidget.js +573 -0
  8. package/lib/DatameshWidget.js.map +1 -0
  9. package/lib/DatasourceItem.d.ts +12 -0
  10. package/lib/DatasourceItem.js +47 -0
  11. package/lib/DatasourceItem.js.map +1 -0
  12. package/lib/aiLoop.d.ts +60 -0
  13. package/lib/aiLoop.js +85 -0
  14. package/lib/aiLoop.js.map +1 -0
  15. package/lib/chatRouter.d.ts +64 -0
  16. package/lib/chatRouter.js +225 -0
  17. package/lib/chatRouter.js.map +1 -0
  18. package/lib/constants.d.ts +14 -0
  19. package/lib/constants.js +15 -0
  20. package/lib/constants.js.map +1 -0
  21. package/lib/conversationPin.d.ts +68 -0
  22. package/lib/conversationPin.js +120 -0
  23. package/lib/conversationPin.js.map +1 -0
  24. package/lib/handler.d.ts +8 -0
  25. package/lib/handler.js +36 -0
  26. package/lib/handler.js.map +1 -0
  27. package/lib/index.d.ts +16 -0
  28. package/lib/index.js +273 -0
  29. package/lib/index.js.map +1 -0
  30. package/lib/kernelHandoff.d.ts +61 -0
  31. package/lib/kernelHandoff.js +236 -0
  32. package/lib/kernelHandoff.js.map +1 -0
  33. package/lib/notebookContext.d.ts +48 -0
  34. package/lib/notebookContext.js +118 -0
  35. package/lib/notebookContext.js.map +1 -0
  36. package/lib/notebookHost.d.ts +6 -0
  37. package/lib/notebookHost.js +72 -0
  38. package/lib/notebookHost.js.map +1 -0
  39. package/lib/notebookRun.d.ts +37 -0
  40. package/lib/notebookRun.js +70 -0
  41. package/lib/notebookRun.js.map +1 -0
  42. package/lib/progress.d.ts +43 -0
  43. package/lib/progress.js +103 -0
  44. package/lib/progress.js.map +1 -0
  45. package/lib/sse.d.ts +26 -0
  46. package/lib/sse.js +112 -0
  47. package/lib/sse.js.map +1 -0
  48. package/package.json +151 -0
  49. package/schema/datamesh-connect.json +35 -0
  50. package/src/DatameshUI.tsx +15 -0
  51. package/src/DatameshWidget.tsx +909 -0
  52. package/src/DatasourceItem.tsx +124 -0
  53. package/src/__tests__/aiLoop.spec.ts +304 -0
  54. package/src/__tests__/chatRouter.spec.ts +315 -0
  55. package/src/__tests__/conversationPin.spec.ts +236 -0
  56. package/src/__tests__/kernelHandoff.spec.ts +106 -0
  57. package/src/__tests__/notebookContext.spec.ts +97 -0
  58. package/src/__tests__/notebookHost.spec.ts +195 -0
  59. package/src/__tests__/notebookRun.spec.ts +95 -0
  60. package/src/__tests__/notebookSnapshot.spec.ts +62 -0
  61. package/src/__tests__/oceanumlab.spec.ts +9 -0
  62. package/src/__tests__/sse.spec.ts +304 -0
  63. package/src/aiLoop.ts +140 -0
  64. package/src/chatRouter.ts +329 -0
  65. package/src/constants.ts +16 -0
  66. package/src/conversationPin.ts +148 -0
  67. package/src/global.d.ts +5 -0
  68. package/src/handler.ts +46 -0
  69. package/src/index.ts +327 -0
  70. package/src/kernelHandoff.ts +284 -0
  71. package/src/notebookContext.ts +144 -0
  72. package/src/notebookHost.ts +97 -0
  73. package/src/notebookRun.ts +104 -0
  74. package/src/progress.ts +121 -0
  75. package/src/sse.ts +127 -0
  76. package/src/svg.d.ts +4 -0
  77. package/style/base.css +5 -0
  78. package/style/icons/oceanum-dark.svg +1 -0
  79. package/style/icons/oceanum-light.svg +1 -0
  80. package/style/icons/oceanum.png +0 -0
  81. package/style/icons/oceanum.svg +1 -0
  82. package/style/index.css +477 -0
  83. package/style/index.js +1 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * What the agent is doing right now, from the extension host to the widget
3
+ * (OCE-175).
4
+ *
5
+ * A channel is needed because the widget does not call the router: it issues
6
+ * the `oceanum-ai:submit-prompt` COMMAND, and command arguments must be JSON,
7
+ * so a callback cannot cross. The Stop button has the same constraint and
8
+ * solves it the same way -- an AbortController held in the plugin's closure.
9
+ *
10
+ * A module singleton rather than a JupyterLab `Signal`, because a Signal wants
11
+ * an owner object and there is no natural one here: the producer is a command
12
+ * handler and the consumer is a React component that mounts and unmounts
13
+ * independently of it.
14
+ */
15
+ /** A phase the backend named, and the tool it is using if that is the phase. */
16
+ export interface Progress {
17
+ phase: string;
18
+ tool?: string;
19
+ }
20
+ type Listener = (progress: Progress | null) => void;
21
+ /** Subscribe. Returns the unsubscribe, for a React effect's cleanup. */
22
+ export declare function onProgress(listener: Listener): () => void;
23
+ /**
24
+ * Publish. `null` means "no longer working", which the widget uses to fall
25
+ * back to its own wording rather than leaving the last phase on screen after
26
+ * the answer has arrived.
27
+ *
28
+ * A listener that throws must not stop the others hearing, nor break the
29
+ * request: this is decoration, and a broken indicator is not worth failing an
30
+ * answer over.
31
+ */
32
+ export declare function reportProgress(progress: Progress | null): void;
33
+ /**
34
+ * A reporter for one run: it publishes only while `isCurrent()` holds.
35
+ *
36
+ * A run that New chat or a newer prompt replaced is aborted, but it can take a
37
+ * while to unwind -- a cell that ignores the interrupt keeps it in its handoff
38
+ * -- and whatever it reports on the way out, a phase or its "no longer
39
+ * working", would land on the new run's progress line.
40
+ */
41
+ export declare function reporterFor(isCurrent: () => boolean): (progress: Progress | null) => void;
42
+ export declare function describeProgress(progress: Progress | null): string;
43
+ export {};
@@ -0,0 +1,103 @@
1
+ /**
2
+ * What the agent is doing right now, from the extension host to the widget
3
+ * (OCE-175).
4
+ *
5
+ * A channel is needed because the widget does not call the router: it issues
6
+ * the `oceanum-ai:submit-prompt` COMMAND, and command arguments must be JSON,
7
+ * so a callback cannot cross. The Stop button has the same constraint and
8
+ * solves it the same way -- an AbortController held in the plugin's closure.
9
+ *
10
+ * A module singleton rather than a JupyterLab `Signal`, because a Signal wants
11
+ * an owner object and there is no natural one here: the producer is a command
12
+ * handler and the consumer is a React component that mounts and unmounts
13
+ * independently of it.
14
+ */
15
+ const listeners = new Set();
16
+ /** Subscribe. Returns the unsubscribe, for a React effect's cleanup. */
17
+ export function onProgress(listener) {
18
+ listeners.add(listener);
19
+ return () => {
20
+ listeners.delete(listener);
21
+ };
22
+ }
23
+ /**
24
+ * Publish. `null` means "no longer working", which the widget uses to fall
25
+ * back to its own wording rather than leaving the last phase on screen after
26
+ * the answer has arrived.
27
+ *
28
+ * A listener that throws must not stop the others hearing, nor break the
29
+ * request: this is decoration, and a broken indicator is not worth failing an
30
+ * answer over.
31
+ */
32
+ export function reportProgress(progress) {
33
+ for (const listener of listeners) {
34
+ try {
35
+ listener(progress);
36
+ }
37
+ catch (err) {
38
+ console.error('Oceanum AI: a progress listener threw', err);
39
+ }
40
+ }
41
+ }
42
+ /**
43
+ * A reporter for one run: it publishes only while `isCurrent()` holds.
44
+ *
45
+ * A run that New chat or a newer prompt replaced is aborted, but it can take a
46
+ * while to unwind -- a cell that ignores the interrupt keeps it in its handoff
47
+ * -- and whatever it reports on the way out, a phase or its "no longer
48
+ * working", would land on the new run's progress line.
49
+ */
50
+ export function reporterFor(isCurrent) {
51
+ return progress => {
52
+ if (isCurrent()) {
53
+ reportProgress(progress);
54
+ }
55
+ };
56
+ }
57
+ /**
58
+ * What each phase is, in the user's terms.
59
+ *
60
+ * An unlisted phase or tool falls back to something generic rather than
61
+ * showing its internal name: a new server-side tool should read as progress,
62
+ * not as a leak of what the agent is made of. And no phase at all reads as
63
+ * "Thinking…", which is what this said before there was anything better to
64
+ * say -- so a backend that does not stream, or a proxy that buffered the
65
+ * stream away, degrades to exactly the old behaviour rather than to a blank.
66
+ */
67
+ const TOOL_LABELS = {
68
+ search_catalog: 'Searching the catalogue…',
69
+ get_datasource_info: 'Reading dataset details…',
70
+ save_memory: 'Saving a note…'
71
+ };
72
+ const PHASE_LABELS = {
73
+ generating: 'Thinking…',
74
+ interpreting: 'Reading the result…',
75
+ // Reported by the client, not the server: these two are the notebook's turn.
76
+ // Everything else here names something the agent is doing, and saying so
77
+ // while a cell runs would be actively false rather than merely vague.
78
+ running: 'Running the code…',
79
+ placing: 'Adding the code to the notebook…'
80
+ };
81
+ export function describeProgress(progress) {
82
+ var _a, _b;
83
+ if (!progress) {
84
+ return 'Thinking…';
85
+ }
86
+ if (progress.phase === 'tool') {
87
+ return (_a = labelFor(TOOL_LABELS, progress.tool)) !== null && _a !== void 0 ? _a : 'Looking something up…';
88
+ }
89
+ return (_b = labelFor(PHASE_LABELS, progress.phase)) !== null && _b !== void 0 ? _b : 'Working…';
90
+ }
91
+ /**
92
+ * The label `labels` itself gives `name`, if any. Only its own entries: the
93
+ * name comes off the stream -- a tool name is whatever the model called -- and
94
+ * `__proto__` or `toString` must not reach into Object.prototype. That hands
95
+ * React an object or a function to render, and an object breaks the panel.
96
+ */
97
+ function labelFor(labels, name) {
98
+ return name !== undefined &&
99
+ Object.prototype.hasOwnProperty.call(labels, name)
100
+ ? labels[name]
101
+ : undefined;
102
+ }
103
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAY,CAAC;AAEtC,wEAAwE;AACxE,MAAM,UAAU,UAAU,CAAC,QAAkB;IAC3C,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,QAAyB;IACtD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CACzB,SAAwB;IAExB,OAAO,QAAQ,CAAC,EAAE;QAChB,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,GAA2B;IAC1C,cAAc,EAAE,0BAA0B;IAC1C,mBAAmB,EAAE,0BAA0B;IAC/C,WAAW,EAAE,gBAAgB;CAC9B,CAAC;AAEF,MAAM,YAAY,GAA2B;IAC3C,UAAU,EAAE,WAAW;IACvB,YAAY,EAAE,qBAAqB;IACnC,6EAA6E;IAC7E,yEAAyE;IACzE,sEAAsE;IACtE,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE,kCAAkC;CAC5C,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,QAAyB;;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC9B,OAAO,MAAA,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,mCAAI,uBAAuB,CAAC;IACzE,CAAC;IACD,OAAO,MAAA,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,mCAAI,UAAU,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,SAAS,QAAQ,CACf,MAA8B,EAC9B,IAAwB;IAExB,OAAO,IAAI,KAAK,SAAS;QACvB,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;QAClD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;QACd,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
package/lib/sse.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Reading a Server-Sent Events body (OCE-175).
3
+ *
4
+ * Small and local rather than a dependency: SSE is a line format, the backend
5
+ * emits one `data:` line per event, and a library would bring a parser for the
6
+ * multi-line and retry-directive cases this stream does not use.
7
+ *
8
+ * Note it is NOT `EventSource`. That only issues GETs, and these are POSTs with
9
+ * a body and an auth header, which is why every client of this API hand-rolls
10
+ * the read.
11
+ */
12
+ /** One frame off the wire. `data` is raw; the caller parses it. */
13
+ export interface SseEvent {
14
+ event: string;
15
+ data: string;
16
+ id?: string;
17
+ }
18
+ /**
19
+ * Yield each event as it arrives.
20
+ *
21
+ * Decodes with `stream: true` so a multi-byte character split across two
22
+ * network chunks is reassembled rather than mangled -- a UTF-8 sequence has no
23
+ * obligation to arrive whole, and a dataset name with an accent in it is the
24
+ * kind of thing that finds this bug in production rather than in a test.
25
+ */
26
+ export declare function readSse(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<SseEvent>;
package/lib/sse.js ADDED
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Reading a Server-Sent Events body (OCE-175).
3
+ *
4
+ * Small and local rather than a dependency: SSE is a line format, the backend
5
+ * emits one `data:` line per event, and a library would bring a parser for the
6
+ * multi-line and retry-directive cases this stream does not use.
7
+ *
8
+ * Note it is NOT `EventSource`. That only issues GETs, and these are POSTs with
9
+ * a body and an auth header, which is why every client of this API hand-rolls
10
+ * the read.
11
+ */
12
+ /**
13
+ * Yield each event as it arrives.
14
+ *
15
+ * Decodes with `stream: true` so a multi-byte character split across two
16
+ * network chunks is reassembled rather than mangled -- a UTF-8 sequence has no
17
+ * obligation to arrive whole, and a dataset name with an accent in it is the
18
+ * kind of thing that finds this bug in production rather than in a test.
19
+ */
20
+ export async function* readSse(body, signal) {
21
+ const reader = body.getReader();
22
+ const decoder = new TextDecoder();
23
+ let buffer = '';
24
+ /** Every complete frame currently in the buffer. Events are separated by a
25
+ * blank line; anything after the last one is partial and stays put. */
26
+ function* drain() {
27
+ let split = buffer.indexOf('\n\n');
28
+ while (split !== -1) {
29
+ const frame = buffer.slice(0, split);
30
+ buffer = buffer.slice(split + 2);
31
+ const parsed = parseFrame(frame);
32
+ if (parsed) {
33
+ yield parsed;
34
+ }
35
+ split = buffer.indexOf('\n\n');
36
+ }
37
+ }
38
+ try {
39
+ while (true) {
40
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
41
+ return;
42
+ }
43
+ const { done, value } = await reader.read();
44
+ if (done) {
45
+ // Flush the deferred `\r`, if any: no further chunk is coming, so it
46
+ // cannot be half of a CRLF and IS a line ending. Without this a stream
47
+ // using bare CR loses its final frame -- the terminator never forms.
48
+ buffer = normaliseNewlines(buffer, true);
49
+ yield* drain();
50
+ break;
51
+ }
52
+ buffer = normaliseNewlines(buffer + decoder.decode(value, { stream: true }));
53
+ yield* drain();
54
+ }
55
+ }
56
+ finally {
57
+ // Releases the reader's lock whether the consumer finished, threw, or
58
+ // stopped early -- a `break` in a for-await runs this. It does not cancel
59
+ // the body: the backend ends the stream after `done` or `error`, and Stop's
60
+ // abort closes the connection itself.
61
+ reader.releaseLock();
62
+ }
63
+ }
64
+ /**
65
+ * Collapse CRLF and bare CR to LF, so the rest of the parser can look for a
66
+ * single line ending.
67
+ *
68
+ * The spec allows all three, and our own backend sends LF -- but "our backend
69
+ * sends LF" is a statement about one hop. Anything between it and the browser
70
+ * may rewrite line endings, and the failure if it does is total rather than
71
+ * partial: the frame separator `\n\n` never matches `\r\n\r\n`, so ZERO events
72
+ * parse, the stream looks empty, and the caller reports the response as
73
+ * incomplete. Measured before this existed: 0 events from a well-formed CRLF
74
+ * stream.
75
+ *
76
+ * The trailing `\r` is held back, and that is the whole subtlety. A chunk may
77
+ * end mid-CRLF, with the `\n` arriving next; converting that `\r` to `\n` now
78
+ * and meeting its partner later would manufacture a blank line -- a frame
79
+ * boundary that was never sent, splitting one event into two malformed ones.
80
+ * So it waits for the next chunk, exactly as a split multi-byte character does.
81
+ */
82
+ function normaliseNewlines(buffer, final = false) {
83
+ const held = !final && buffer.endsWith('\r') ? '\r' : '';
84
+ const body = held ? buffer.slice(0, -1) : buffer;
85
+ return body.replace(/\r\n/g, '\n').replace(/\r/g, '\n') + held;
86
+ }
87
+ function parseFrame(frame) {
88
+ let event = 'message';
89
+ let id;
90
+ const data = [];
91
+ for (const line of frame.split('\n')) {
92
+ // A comment. The backend sends these as keepalives during a long wait, and
93
+ // they carry nothing.
94
+ if (line.startsWith(':')) {
95
+ continue;
96
+ }
97
+ if (line.startsWith('event:')) {
98
+ event = line.slice('event:'.length).trim();
99
+ }
100
+ else if (line.startsWith('data:')) {
101
+ data.push(line.slice('data:'.length).trim());
102
+ }
103
+ else if (line.startsWith('id:')) {
104
+ id = line.slice('id:'.length).trim();
105
+ }
106
+ }
107
+ if (data.length === 0) {
108
+ return null;
109
+ }
110
+ return { event, data: data.join('\n'), id };
111
+ }
112
+ //# sourceMappingURL=sse.js.map
package/lib/sse.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,151 @@
1
+ {
2
+ "name": "@oceanum/oceanumlab",
3
+ "version": "4.6.0",
4
+ "description": "A Jupyterlab extension to interact with the Oceanum.io platform",
5
+ "keywords": [
6
+ "jupyter",
7
+ "jupyterlab",
8
+ "jupyterlab-extension"
9
+ ],
10
+ "homepage": "https://github.com/oceanum-io/oceanumlab.git",
11
+ "bugs": {
12
+ "url": "https://github.com/oceanum-io/oceanumlab.git/issues"
13
+ },
14
+ "license": "BSD-3-Clause",
15
+ "author": {
16
+ "name": "Oceanum",
17
+ "email": "developers@oceanum.science"
18
+ },
19
+ "files": [
20
+ "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
21
+ "style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
22
+ "src/**/*.{ts,tsx}",
23
+ "schema/*.json"
24
+ ],
25
+ "main": "lib/index.js",
26
+ "types": "lib/index.d.ts",
27
+ "style": "style/index.css",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/oceanum-io/oceanumlab.git"
31
+ },
32
+ "scripts": {
33
+ "build": "jlpm build:lib && jlpm build:labextension:dev",
34
+ "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
35
+ "build:labextension": "jupyter labextension build .",
36
+ "build:labextension:dev": "jupyter labextension build --development True .",
37
+ "build:lib": "tsc --sourceMap",
38
+ "build:lib:prod": "tsc",
39
+ "clean": "jlpm clean:lib",
40
+ "clean:lib": "rimraf lib tsconfig.tsbuildinfo",
41
+ "clean:lintcache": "rimraf .eslintcache .stylelintcache",
42
+ "clean:labextension": "rimraf oceanumlab/labextension oceanumlab/_version.py",
43
+ "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache",
44
+ "eslint": "jlpm eslint:check --fix",
45
+ "eslint:check": "ESLINT_USE_FLAT_CONFIG=false eslint . --cache --ext .ts,.tsx",
46
+ "install:extension": "jlpm build",
47
+ "lint": "jlpm stylelint && jlpm prettier && jlpm eslint",
48
+ "lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check",
49
+ "prettier": "jlpm prettier:base --write --list-different",
50
+ "prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"",
51
+ "prettier:check": "jlpm prettier:base --check",
52
+ "stylelint": "jlpm stylelint:check --fix",
53
+ "stylelint:check": "stylelint --cache \"style/**/*.css\"",
54
+ "test": "jest --coverage",
55
+ "watch": "run-p watch:src watch:labextension",
56
+ "watch:src": "tsc -w --sourceMap",
57
+ "watch:labextension": "jupyter labextension watch ."
58
+ },
59
+ "dependencies": {
60
+ "@jupyterlab/application": "^4.6.3",
61
+ "@jupyterlab/apputils": "^4.7.3",
62
+ "@jupyterlab/cells": "^4.6.3",
63
+ "@jupyterlab/notebook": "^4.6.3",
64
+ "@jupyterlab/settingregistry": "^4.6.3",
65
+ "@phosphor-icons/react": "^2.1.10",
66
+ "marked": "^18.0.13"
67
+ },
68
+ "devDependencies": {
69
+ "@jupyterlab/builder": "^4.5.10",
70
+ "@jupyterlab/testutils": "^4.6.3",
71
+ "@types/jest": "^29.5.12",
72
+ "@types/json-schema": "^7.0.15",
73
+ "@types/react": "^18.2.75",
74
+ "@types/react-addons-linked-state-mixin": "^0.14.27",
75
+ "@typescript-eslint/eslint-plugin": "^7.6.0",
76
+ "@typescript-eslint/parser": "^7.6.0",
77
+ "css-loader": "^7.1.5",
78
+ "eslint": "^9.0.0",
79
+ "eslint-config-prettier": "^10.1.8",
80
+ "eslint-plugin-prettier": "^5.5.6",
81
+ "jest": "^29.7.0",
82
+ "npm-run-all": "^4.1.5",
83
+ "prettier": "^3.9.6",
84
+ "rimraf": "^6.1.3",
85
+ "source-map-loader": "^5.0.0",
86
+ "style-loader": "^4.0.0",
87
+ "stylelint": "^17.15.0",
88
+ "stylelint-config-recommended": "^18.0.0",
89
+ "stylelint-config-standard": "^40.0.0",
90
+ "stylelint-csstree-validator": "^4.0.0",
91
+ "stylelint-prettier": "^5.0.3",
92
+ "typescript": "~5.9.3",
93
+ "yjs": "^13.6.32"
94
+ },
95
+ "sideEffects": [
96
+ "style/*.css",
97
+ "style/index.js"
98
+ ],
99
+ "styleModule": "style/index.js",
100
+ "publishConfig": {
101
+ "access": "public"
102
+ },
103
+ "jupyterlab": {
104
+ "extension": true,
105
+ "outputDir": "oceanumlab/labextension",
106
+ "schemaDir": "schema",
107
+ "webpackConfig": "./webpack.config.js"
108
+ },
109
+ "eslintIgnore": [
110
+ "node_modules",
111
+ "dist",
112
+ "coverage",
113
+ "**/*.d.ts",
114
+ "tests",
115
+ "**/__tests__",
116
+ "ui-tests"
117
+ ],
118
+ "prettier": {
119
+ "singleQuote": true,
120
+ "trailingComma": "none",
121
+ "arrowParens": "avoid",
122
+ "endOfLine": "auto",
123
+ "overrides": [
124
+ {
125
+ "files": "package.json",
126
+ "options": {
127
+ "tabWidth": 4
128
+ }
129
+ }
130
+ ]
131
+ },
132
+ "stylelint": {
133
+ "extends": [
134
+ "stylelint-config-recommended",
135
+ "stylelint-config-standard",
136
+ "stylelint-prettier/recommended"
137
+ ],
138
+ "plugins": [
139
+ "stylelint-csstree-validator"
140
+ ],
141
+ "rules": {
142
+ "csstree/validator": true,
143
+ "custom-property-pattern": null,
144
+ "no-descending-specificity": null,
145
+ "property-no-vendor-prefix": null,
146
+ "selector-class-pattern": "^([a-z][A-z\\d]*)(-{1,2}[A-z\\d]+)*$",
147
+ "selector-no-vendor-prefix": null,
148
+ "value-no-vendor-prefix": null
149
+ }
150
+ }
151
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "jupyter.lab.shortcuts": [],
3
+ "jupyter.lab.setting-icon": "oceanum:icon",
4
+ "jupyter.lab.setting-icon-label": "Oceanum",
5
+ "title": "Oceanum.io",
6
+ "description": "Oceanum.io JupyterLab extension settings",
7
+ "type": "object",
8
+ "properties": {
9
+ "datameshToken": {
10
+ "type": "string",
11
+ "title": "Datamesh token",
12
+ "description": "Your Oceanum Datamesh token or JWT. Obtain at https://home.oceanum.io/account.",
13
+ "default": ""
14
+ },
15
+ "injectToken": {
16
+ "type": "boolean",
17
+ "title": "Inject token",
18
+ "description": "Inject Datamesh token into code.",
19
+ "default": false
20
+ },
21
+ "autoRunCode": {
22
+ "type": "boolean",
23
+ "title": "Auto-run code",
24
+ "description": "Run code cells the AI inserts as soon as they are placed.",
25
+ "default": false
26
+ },
27
+ "iterate": {
28
+ "type": "boolean",
29
+ "title": "Iterate",
30
+ "description": "After running, send each cell's output back to the AI so it can fix an error or take the next step. Only takes effect with Auto-run code on.",
31
+ "default": false
32
+ }
33
+ },
34
+ "additionalProperties": false
35
+ }
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { ReactWidget } from '@jupyterlab/apputils';
3
+
4
+ declare const DATAMESH_UI_SERVICE: string;
5
+
6
+ export class DatameshUI extends ReactWidget {
7
+ render(): React.ReactElement {
8
+ return (
9
+ <iframe
10
+ src={`${DATAMESH_UI_SERVICE}`}
11
+ className="datamesh-iframe"
12
+ ></iframe>
13
+ );
14
+ }
15
+ }