@cmetech/otto 1.2.6 → 1.3.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.
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/coworker-scratchpad/scratchpad-tool.js +5 -5
- package/dist/resources/extensions/otto/commands/release-notes/_data.js +10 -2
- package/package.json +10 -7
- package/packages/contracts/package.json +1 -1
- package/packages/coworker-scratchpad/dist/kernel-bindings.d.ts +2 -4
- package/packages/coworker-scratchpad/dist/kernel-bindings.js +4 -4
- package/packages/coworker-scratchpad/dist/kernel-entry.js +1 -0
- package/packages/coworker-scratchpad/src/child-process-runtime.test.ts +8 -1
- package/packages/coworker-scratchpad/src/kernel-bindings.test.ts +3 -2
- package/packages/coworker-scratchpad/src/kernel-bindings.ts +4 -4
- package/packages/coworker-scratchpad/src/kernel-entry.ts +1 -0
- package/packages/daemon/package.json +3 -3
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +2 -2
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.ts +5 -5
- package/src/resources/extensions/otto/commands/release-notes/_data.ts +10 -2
- package/vendor/README.md +68 -0
- package/vendor/xlsx-0.20.3.tgz +0 -0
- package/vendor/xlsx-0.20.3.tgz.sha256 +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d8315aa1c7fe9b29
|
|
@@ -44,17 +44,17 @@ export function registerScratchpadTool(pi, deps) {
|
|
|
44
44
|
pi.registerTool({
|
|
45
45
|
name: 'cw_scratchpad',
|
|
46
46
|
label: 'Co-worker scratchpad',
|
|
47
|
-
description: 'USE FOR: loading or analyzing files (CSV, JSON, Parquet), tabular data manipulation with polars or DuckDB, multi-step data exploration where state should persist across turns, or anything that calls otto.collectors. ' +
|
|
47
|
+
description: 'USE FOR: loading or analyzing files (CSV, JSON, Parquet, XLSX), tabular data manipulation with polars or DuckDB, multi-step data exploration where state should persist across turns, or anything that calls otto.collectors. ' +
|
|
48
48
|
'DO NOT USE FOR: simple arithmetic, lookups answerable from reasoning alone, pure prose, code review, or one-off calculations with no file or data source involved. ' +
|
|
49
49
|
'IF the user explicitly names this tool ("use cw_scratchpad", "run this in the scratchpad", "exec a cell"), use it regardless of the rules above. ' +
|
|
50
50
|
'IF UNSURE whether a request belongs here, ASK the user once: "Do you want me to run this in cw_scratchpad so you can inspect the cells via /sp view, or answer inline?" Wait for their reply before deciding. ' +
|
|
51
51
|
'Runs TypeScript cells in a persistent JS kernel scoped to a named scratchpad. State persists across cells via globalThis.* and across Otto sessions via on-disk kernel.db + namespace.json. ' +
|
|
52
|
-
'Pre-bound libs in every cell: polars, DuckDB, dateFns, lodash, zod, axios. otto.collectors.{list,open} enumerates and loads data sources. ' +
|
|
52
|
+
'Pre-bound libs in every cell: polars, DuckDB, XLSX, dateFns, lodash, zod, axios. otto.collectors.{list,open} enumerates and loads data sources. ' +
|
|
53
53
|
'Actions: exec (run a TypeScript cell), view (return the last N cells). ' +
|
|
54
54
|
'Distinct from the analyst extension\'s SQL-only `scratchpad` tool — this one runs arbitrary TypeScript.',
|
|
55
|
-
promptSnippet: 'cw_scratchpad — run TypeScript cells in a persistent JS kernel. USE for files (CSV/JSON/Parquet), polars/DuckDB analysis, otto.collectors, or multi-step data work. NOT for arithmetic or pure prose. If unsure, ASK the user first.',
|
|
55
|
+
promptSnippet: 'cw_scratchpad — run TypeScript cells in a persistent JS kernel. USE for files (CSV/JSON/Parquet/XLSX), polars/DuckDB analysis, otto.collectors, or multi-step data work. NOT for arithmetic or pure prose. If unsure, ASK the user first.',
|
|
56
56
|
promptGuidelines: [
|
|
57
|
-
'Trigger criteria: the request involves loading a file (CSV/JSON/Parquet/etc.), querying tabular data via polars or DuckDB, calling otto.collectors, or building state that must survive across turns.',
|
|
57
|
+
'Trigger criteria: the request involves loading a file (CSV/JSON/Parquet/XLSX/etc.), querying tabular data via polars or DuckDB, calling otto.collectors, or building state that must survive across turns.',
|
|
58
58
|
'Skip the tool for: trivial arithmetic, lookups you can answer from reasoning, prose generation, code review, and pure-explanation tasks.',
|
|
59
59
|
'If the user names the tool explicitly (e.g. "use cw_scratchpad", "in the scratchpad", "exec a cell"), always honor that request and skip the unsure-prompt.',
|
|
60
60
|
'IF UNSURE whether a request fits the trigger criteria, ask the user once before deciding: "Do you want me to run this in cw_scratchpad (you can inspect the cells via /sp view) or answer inline?" Wait for the user\'s reply before either calling the tool or answering inline.',
|
|
@@ -62,7 +62,7 @@ export function registerScratchpadTool(pi, deps) {
|
|
|
62
62
|
'The cell body is wrapped in (async () => { ... })(). let/const/var are local to the cell. To persist, assign to globalThis.foo = ...',
|
|
63
63
|
'For DuckDB tables that survive across Otto sessions, use `await otto.duckdb.connect()`. For ephemeral in-memory, use `DuckDB.DuckDBInstance.create(":memory:")`.',
|
|
64
64
|
'For polars→DuckDB: prefer `otto.duckdb.registerDf(name, df)` over manual API discovery. If inference picks the wrong column type, pass `{ schema: { col: \'TYPE\' } }` as the third argument. Falls back to polars\' own SQL (`df.sql(...)`) for one-off aggregations.',
|
|
65
|
-
'Pre-bound libs available in every cell: polars, DuckDB, dateFns, lodash, zod, axios. No imports needed.',
|
|
65
|
+
'Pre-bound libs available in every cell: polars, DuckDB, XLSX, dateFns, lodash, zod, axios. No imports needed.',
|
|
66
66
|
'Use otto.collectors.list() to discover data sources and otto.collectors.open(uri) to load one.',
|
|
67
67
|
'The `name` parameter defaults to the currently attached scratchpad. Omit it unless you want to operate on a different one (this does NOT switch the user attachment).',
|
|
68
68
|
'A returned string that looks markdown-shaped will appear in the response as text/markdown automatically. Return a markdown table or heading to render it.',
|
|
@@ -9,12 +9,20 @@
|
|
|
9
9
|
// runtime command surfaces a link when a requested version isn't bundled.
|
|
10
10
|
export const RELEASE_NOTES_MANIFEST = {
|
|
11
11
|
truncated: false,
|
|
12
|
-
total:
|
|
12
|
+
total: 16,
|
|
13
13
|
oldestBundled: '1.0.0',
|
|
14
|
-
newestBundled: '1.
|
|
14
|
+
newestBundled: '1.3.0',
|
|
15
15
|
historyUrl: 'https://github.com/cmetech/otto-cli/blob/main/CHANGELOG.md',
|
|
16
16
|
};
|
|
17
17
|
export const RELEASE_NOTES = [
|
|
18
|
+
{
|
|
19
|
+
version: '1.3.0',
|
|
20
|
+
date: '2026-06-03',
|
|
21
|
+
headline: 'Restores xlsx capability in scratchpad cells via SheetJS Community Edition, replacing the 1.2.6 removal of `exceljs`. Vendored install means `npm i -g @cmetech/otto` remains a single command with no outbound CDN reach.',
|
|
22
|
+
added: [
|
|
23
|
+
'**SheetJS Community Edition (`XLSX`) bound in scratchpad cells.** Restores the xlsx read/write capability dropped in 1.2.6 with the removal of `exceljs`. The SheetJS CE tarball is vendored at `vendor/xlsx-0.20.3.tgz` (SHA-256 verified at prepublish by `scripts/verify-vendored-xlsx.mjs` and at unit-test time by `src/tests/vendor-xlsx.test.ts`), so there is no outbound CDN reach at install time — `npm i -g @cmetech/otto` remains the single command for compliance/air-gapped environments. Cells now write `const wb = XLSX.utils.book_new(); …` (SheetJS canonical API; ExcelJS-style `new Workbook()` calls from pre-1.2.6 cells continue to ReferenceError). CE → Pro upgrade path is documented in `vendor/README.md`: drop a Pro tarball, swap the `file:` reference, regenerate the lockfile — no code change required; the `XLSX` binding name stays.',
|
|
24
|
+
],
|
|
25
|
+
},
|
|
18
26
|
{
|
|
19
27
|
version: '1.2.6',
|
|
20
28
|
date: '2026-06-03',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmetech/otto",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Terminal-based developer chat assistant. Permanent hard fork of gsd-pi with LangFlow flow triggers, a flow builder, and optional gateway routing for compliance environments.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"dist",
|
|
35
35
|
"packages",
|
|
36
36
|
"pkg",
|
|
37
|
+
"vendor",
|
|
37
38
|
"src/resources",
|
|
38
39
|
"scripts/postinstall.js",
|
|
39
40
|
"scripts/install.js",
|
|
@@ -123,6 +124,7 @@
|
|
|
123
124
|
"sync-platform-versions": "node native/scripts/sync-platform-versions.cjs",
|
|
124
125
|
"verify:native-platform-packages": "node scripts/verify-native-platform-packages.mjs",
|
|
125
126
|
"verify:version-sync": "node scripts/verify-version-sync.cjs",
|
|
127
|
+
"verify:vendored-xlsx": "node scripts/verify-vendored-xlsx.mjs",
|
|
126
128
|
"validate-pack": "node scripts/validate-pack.js",
|
|
127
129
|
"typecheck:extensions": "tsc --noEmit --project tsconfig.extensions.json",
|
|
128
130
|
"verify:fast": "bash scripts/ci-fast-gates.sh",
|
|
@@ -135,7 +137,7 @@
|
|
|
135
137
|
"release:publish": "gh workflow run build-native.yml -f publish=true -f publish_auth=trusted",
|
|
136
138
|
"docker:build-runtime": "docker build --target runtime -t ghcr.io/cmetech/otto .",
|
|
137
139
|
"docker:build-builder": "docker build --target builder -t ghcr.io/open-gsd/otto-ci-builder .",
|
|
138
|
-
"prepublishOnly": "npm run sync-pkg-version && npm run verify:version-sync && npm run verify:piconfig-sync && npm run branding:check && node scripts/prepublish-check.mjs && npm run build && npm run typecheck:extensions && npm run verify:native-platform-packages && npm run validate-pack",
|
|
140
|
+
"prepublishOnly": "npm run sync-pkg-version && npm run verify:version-sync && npm run verify:vendored-xlsx && npm run verify:piconfig-sync && npm run branding:check && node scripts/prepublish-check.mjs && npm run build && npm run typecheck:extensions && npm run verify:native-platform-packages && npm run validate-pack",
|
|
139
141
|
"test:live-regression": "node --experimental-strip-types tests/live-regression/run.ts",
|
|
140
142
|
"test:e2e": "node --experimental-strip-types --test --test-concurrency=1 \"tests/e2e/*.e2e.test.ts\"",
|
|
141
143
|
"test:e2e:windows-smoke": "node --experimental-strip-types --test tests/e2e/sanity.e2e.test.ts tests/e2e/migration.e2e.test.ts tests/e2e/native-abi.e2e.test.ts",
|
|
@@ -180,6 +182,7 @@
|
|
|
180
182
|
"sql.js": "^1.14.1",
|
|
181
183
|
"strip-ansi": "^7.1.0",
|
|
182
184
|
"undici": "^7.24.2",
|
|
185
|
+
"xlsx": "file:vendor/xlsx-0.20.3.tgz",
|
|
183
186
|
"yaml": "^2.8.2",
|
|
184
187
|
"zod": "^4.4.3"
|
|
185
188
|
},
|
|
@@ -196,11 +199,11 @@
|
|
|
196
199
|
},
|
|
197
200
|
"optionalDependencies": {
|
|
198
201
|
"@anthropic-ai/claude-agent-sdk": "0.2.83",
|
|
199
|
-
"@cmetech/otto-engine-darwin-arm64": "1.
|
|
200
|
-
"@cmetech/otto-engine-darwin-x64": "1.
|
|
201
|
-
"@cmetech/otto-engine-linux-arm64-gnu": "1.
|
|
202
|
-
"@cmetech/otto-engine-linux-x64-gnu": "1.
|
|
203
|
-
"@cmetech/otto-engine-win32-x64-msvc": "1.
|
|
202
|
+
"@cmetech/otto-engine-darwin-arm64": "1.3.0",
|
|
203
|
+
"@cmetech/otto-engine-darwin-x64": "1.3.0",
|
|
204
|
+
"@cmetech/otto-engine-linux-arm64-gnu": "1.3.0",
|
|
205
|
+
"@cmetech/otto-engine-linux-x64-gnu": "1.3.0",
|
|
206
|
+
"@cmetech/otto-engine-win32-x64-msvc": "1.3.0",
|
|
204
207
|
"fsevents": "~2.3.3",
|
|
205
208
|
"koffi": "^2.9.0"
|
|
206
209
|
},
|
|
@@ -4,10 +4,8 @@ import { type AuditLog } from '@otto/coworker-utils';
|
|
|
4
4
|
* The data libraries pre-bound into every scratchpad cell's vm sandbox.
|
|
5
5
|
* DuckDB is bound as an in-memory-capable lib here; on-disk kernel.db wiring is 1d2.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* and exceljs is no longer maintained upstream. xlsx-populate is the candidate
|
|
10
|
-
* replacement; tracked in docs/superpowers/notes/2026-06-01-coworker-roadmap.md.
|
|
7
|
+
* XLSX is SheetJS Community Edition (vendored — see vendor/README.md for the
|
|
8
|
+
* CE → Pro swap procedure).
|
|
11
9
|
*/
|
|
12
10
|
export declare function buildDataLibBindings(): Record<string, unknown>;
|
|
13
11
|
/** SQL column type string passed straight into CREATE TABLE (e.g. VARCHAR, BIGINT). */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pl from 'nodejs-polars';
|
|
2
|
+
import XLSX from 'xlsx';
|
|
2
3
|
import lodash from 'lodash';
|
|
3
4
|
import axios from 'axios';
|
|
4
5
|
import { z } from 'zod';
|
|
@@ -9,15 +10,14 @@ import { SecretScanner } from '@otto/coworker-utils';
|
|
|
9
10
|
* The data libraries pre-bound into every scratchpad cell's vm sandbox.
|
|
10
11
|
* DuckDB is bound as an in-memory-capable lib here; on-disk kernel.db wiring is 1d2.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* and exceljs is no longer maintained upstream. xlsx-populate is the candidate
|
|
15
|
-
* replacement; tracked in docs/superpowers/notes/2026-06-01-coworker-roadmap.md.
|
|
13
|
+
* XLSX is SheetJS Community Edition (vendored — see vendor/README.md for the
|
|
14
|
+
* CE → Pro swap procedure).
|
|
16
15
|
*/
|
|
17
16
|
export function buildDataLibBindings() {
|
|
18
17
|
return {
|
|
19
18
|
polars: pl,
|
|
20
19
|
DuckDB,
|
|
20
|
+
XLSX,
|
|
21
21
|
dateFns,
|
|
22
22
|
lodash,
|
|
23
23
|
zod: z,
|
|
@@ -160,13 +160,20 @@ describe('data-lib bindings inside a live kernel', () => {
|
|
|
160
160
|
await rm(ws, { recursive: true, force: true });
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
it('polars / lodash / zod / date-fns / axios / DuckDB are bound', async () => {
|
|
163
|
+
it('polars / lodash / zod / date-fns / XLSX / axios / DuckDB are bound', async () => {
|
|
164
164
|
rt = new ChildProcessRuntime({ workspace: ws, inactivityTimeoutMs: 20_000, cellTimeoutMs: 20_000 });
|
|
165
165
|
await rt.start();
|
|
166
166
|
assert.equal((await rt.runCell('return polars.DataFrame({ a: [1, 2, 3] }).height;')).value, 3);
|
|
167
167
|
assert.equal((await rt.runCell('return lodash.chunk([1, 2, 3, 4], 2).length;')).value, 2);
|
|
168
168
|
assert.equal((await rt.runCell('return zod.string().parse("hi");')).value, 'hi');
|
|
169
169
|
assert.equal((await rt.runCell('return dateFns.format(new Date(1970, 0, 1), "yyyy");')).value, '1970');
|
|
170
|
+
assert.equal((await rt.runCell(
|
|
171
|
+
'const wb = XLSX.utils.book_new();' +
|
|
172
|
+
'const ws = XLSX.utils.aoa_to_sheet([[1,2,3]]);' +
|
|
173
|
+
'XLSX.utils.book_append_sheet(wb, ws, "s");' +
|
|
174
|
+
'const buf = XLSX.write(wb, {type:"buffer", bookType:"xlsx"});' +
|
|
175
|
+
'return buf.byteLength > 0;'
|
|
176
|
+
)).value, true);
|
|
170
177
|
assert.equal((await rt.runCell('return typeof axios.get;')).value, 'function');
|
|
171
178
|
assert.equal((await rt.runCell('return typeof DuckDB.DuckDBInstance;')).value, 'function');
|
|
172
179
|
});
|
|
@@ -9,9 +9,9 @@ import { buildDataLibBindings, redactForJournal } from './kernel-bindings.js';
|
|
|
9
9
|
import { ChildProcessRuntime } from './child-process-runtime.js';
|
|
10
10
|
|
|
11
11
|
describe('kernel-bindings', () => {
|
|
12
|
-
it('exposes all
|
|
12
|
+
it('exposes all seven pre-bound data libraries', () => {
|
|
13
13
|
const b = buildDataLibBindings();
|
|
14
|
-
for (const key of ['polars', 'DuckDB', 'dateFns', 'lodash', 'zod', 'axios']) {
|
|
14
|
+
for (const key of ['polars', 'DuckDB', 'XLSX', 'dateFns', 'lodash', 'zod', 'axios']) {
|
|
15
15
|
assert.ok(key in b, `missing binding: ${key}`);
|
|
16
16
|
assert.notEqual(b[key], undefined, `binding is undefined: ${key}`);
|
|
17
17
|
}
|
|
@@ -24,6 +24,7 @@ describe('kernel-bindings', () => {
|
|
|
24
24
|
assert.equal(typeof b.dateFns.format, 'function');
|
|
25
25
|
assert.equal(typeof b.lodash.chunk, 'function');
|
|
26
26
|
assert.equal(typeof b.axios.get, 'function');
|
|
27
|
+
assert.equal(typeof b.XLSX.utils.book_new, 'function');
|
|
27
28
|
});
|
|
28
29
|
});
|
|
29
30
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pl from 'nodejs-polars';
|
|
2
|
+
import XLSX from 'xlsx';
|
|
2
3
|
import lodash from 'lodash';
|
|
3
4
|
import axios from 'axios';
|
|
4
5
|
import { z } from 'zod';
|
|
@@ -11,15 +12,14 @@ import { SecretScanner, type AuditLog, type AuditRecord } from '@otto/coworker-u
|
|
|
11
12
|
* The data libraries pre-bound into every scratchpad cell's vm sandbox.
|
|
12
13
|
* DuckDB is bound as an in-memory-capable lib here; on-disk kernel.db wiring is 1d2.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* and exceljs is no longer maintained upstream. xlsx-populate is the candidate
|
|
17
|
-
* replacement; tracked in docs/superpowers/notes/2026-06-01-coworker-roadmap.md.
|
|
15
|
+
* XLSX is SheetJS Community Edition (vendored — see vendor/README.md for the
|
|
16
|
+
* CE → Pro swap procedure).
|
|
18
17
|
*/
|
|
19
18
|
export function buildDataLibBindings(): Record<string, unknown> {
|
|
20
19
|
return {
|
|
21
20
|
polars: pl,
|
|
22
21
|
DuckDB,
|
|
22
|
+
XLSX,
|
|
23
23
|
dateFns,
|
|
24
24
|
lodash,
|
|
25
25
|
zod: z,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otto-build/daemon",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "OTTO daemon — background process for project monitoring and Discord integration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@anthropic-ai/sdk": "^0.52.0",
|
|
32
|
-
"@otto-build/contracts": "^1.
|
|
33
|
-
"@otto-build/rpc-client": "^1.
|
|
32
|
+
"@otto-build/contracts": "^1.3.0",
|
|
33
|
+
"@otto-build/rpc-client": "^1.3.0",
|
|
34
34
|
"discord.js": "^14.25.1",
|
|
35
35
|
"yaml": "^2.8.0",
|
|
36
36
|
"zod": "^3.24.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otto-build/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "MCP server exposing OTTO orchestration tools for compatible clients",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"otto": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"test": "npm run build:test && node --test dist/mcp-server.test.js dist/remote-questions.test.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@otto-build/contracts": "^1.
|
|
38
|
-
"@otto-build/rpc-client": "^1.
|
|
37
|
+
"@otto-build/contracts": "^1.3.0",
|
|
38
|
+
"@otto-build/rpc-client": "^1.3.0",
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
40
40
|
"zod": "^4.0.0"
|
|
41
41
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otto/pi-coding-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Coding agent CLI (vendored from pi-mono)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"otto": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"copy-assets": "node scripts/copy-assets.cjs"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@otto-build/contracts": "^1.
|
|
31
|
+
"@otto-build/contracts": "^1.3.0",
|
|
32
32
|
"@mariozechner/jiti": "^2.6.2",
|
|
33
33
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
34
34
|
"chalk": "^5.5.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otto-build/rpc-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Standalone RPC client SDK for OTTO — zero internal dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"otto": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test": "node --test dist/rpc-client.test.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@otto-build/contracts": "^1.
|
|
37
|
+
"@otto-build/contracts": "^1.3.0"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=22.0.0"
|
package/pkg/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loop24/client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"piConfig": {
|
|
5
5
|
"_comment": "AUTO-SYNCED from root package.json by scripts/sync-piconfig.mjs (runs on prebuild). Do not edit this block directly — edit root package.json and re-run `npm run build` or `npm run sync-piconfig`.",
|
|
6
6
|
"name": "otto",
|
|
@@ -90,18 +90,18 @@ export function registerScratchpadTool(pi: ExtensionAPI, deps: ScratchpadToolDep
|
|
|
90
90
|
name: 'cw_scratchpad',
|
|
91
91
|
label: 'Co-worker scratchpad',
|
|
92
92
|
description:
|
|
93
|
-
'USE FOR: loading or analyzing files (CSV, JSON, Parquet), tabular data manipulation with polars or DuckDB, multi-step data exploration where state should persist across turns, or anything that calls otto.collectors. ' +
|
|
93
|
+
'USE FOR: loading or analyzing files (CSV, JSON, Parquet, XLSX), tabular data manipulation with polars or DuckDB, multi-step data exploration where state should persist across turns, or anything that calls otto.collectors. ' +
|
|
94
94
|
'DO NOT USE FOR: simple arithmetic, lookups answerable from reasoning alone, pure prose, code review, or one-off calculations with no file or data source involved. ' +
|
|
95
95
|
'IF the user explicitly names this tool ("use cw_scratchpad", "run this in the scratchpad", "exec a cell"), use it regardless of the rules above. ' +
|
|
96
96
|
'IF UNSURE whether a request belongs here, ASK the user once: "Do you want me to run this in cw_scratchpad so you can inspect the cells via /sp view, or answer inline?" Wait for their reply before deciding. ' +
|
|
97
97
|
'Runs TypeScript cells in a persistent JS kernel scoped to a named scratchpad. State persists across cells via globalThis.* and across Otto sessions via on-disk kernel.db + namespace.json. ' +
|
|
98
|
-
'Pre-bound libs in every cell: polars, DuckDB, dateFns, lodash, zod, axios. otto.collectors.{list,open} enumerates and loads data sources. ' +
|
|
98
|
+
'Pre-bound libs in every cell: polars, DuckDB, XLSX, dateFns, lodash, zod, axios. otto.collectors.{list,open} enumerates and loads data sources. ' +
|
|
99
99
|
'Actions: exec (run a TypeScript cell), view (return the last N cells). ' +
|
|
100
100
|
'Distinct from the analyst extension\'s SQL-only `scratchpad` tool — this one runs arbitrary TypeScript.',
|
|
101
101
|
promptSnippet:
|
|
102
|
-
'cw_scratchpad — run TypeScript cells in a persistent JS kernel. USE for files (CSV/JSON/Parquet), polars/DuckDB analysis, otto.collectors, or multi-step data work. NOT for arithmetic or pure prose. If unsure, ASK the user first.',
|
|
102
|
+
'cw_scratchpad — run TypeScript cells in a persistent JS kernel. USE for files (CSV/JSON/Parquet/XLSX), polars/DuckDB analysis, otto.collectors, or multi-step data work. NOT for arithmetic or pure prose. If unsure, ASK the user first.',
|
|
103
103
|
promptGuidelines: [
|
|
104
|
-
'Trigger criteria: the request involves loading a file (CSV/JSON/Parquet/etc.), querying tabular data via polars or DuckDB, calling otto.collectors, or building state that must survive across turns.',
|
|
104
|
+
'Trigger criteria: the request involves loading a file (CSV/JSON/Parquet/XLSX/etc.), querying tabular data via polars or DuckDB, calling otto.collectors, or building state that must survive across turns.',
|
|
105
105
|
'Skip the tool for: trivial arithmetic, lookups you can answer from reasoning, prose generation, code review, and pure-explanation tasks.',
|
|
106
106
|
'If the user names the tool explicitly (e.g. "use cw_scratchpad", "in the scratchpad", "exec a cell"), always honor that request and skip the unsure-prompt.',
|
|
107
107
|
'IF UNSURE whether a request fits the trigger criteria, ask the user once before deciding: "Do you want me to run this in cw_scratchpad (you can inspect the cells via /sp view) or answer inline?" Wait for the user\'s reply before either calling the tool or answering inline.',
|
|
@@ -109,7 +109,7 @@ export function registerScratchpadTool(pi: ExtensionAPI, deps: ScratchpadToolDep
|
|
|
109
109
|
'The cell body is wrapped in (async () => { ... })(). let/const/var are local to the cell. To persist, assign to globalThis.foo = ...',
|
|
110
110
|
'For DuckDB tables that survive across Otto sessions, use `await otto.duckdb.connect()`. For ephemeral in-memory, use `DuckDB.DuckDBInstance.create(":memory:")`.',
|
|
111
111
|
'For polars→DuckDB: prefer `otto.duckdb.registerDf(name, df)` over manual API discovery. If inference picks the wrong column type, pass `{ schema: { col: \'TYPE\' } }` as the third argument. Falls back to polars\' own SQL (`df.sql(...)`) for one-off aggregations.',
|
|
112
|
-
'Pre-bound libs available in every cell: polars, DuckDB, dateFns, lodash, zod, axios. No imports needed.',
|
|
112
|
+
'Pre-bound libs available in every cell: polars, DuckDB, XLSX, dateFns, lodash, zod, axios. No imports needed.',
|
|
113
113
|
'Use otto.collectors.list() to discover data sources and otto.collectors.open(uri) to load one.',
|
|
114
114
|
'The `name` parameter defaults to the currently attached scratchpad. Omit it unless you want to operate on a different one (this does NOT switch the user attachment).',
|
|
115
115
|
'A returned string that looks markdown-shaped will appear in the response as text/markdown automatically. Return a markdown table or heading to render it.',
|
|
@@ -33,13 +33,21 @@ export interface ReleaseNotesManifest {
|
|
|
33
33
|
|
|
34
34
|
export const RELEASE_NOTES_MANIFEST: ReleaseNotesManifest = {
|
|
35
35
|
truncated: false,
|
|
36
|
-
total:
|
|
36
|
+
total: 16,
|
|
37
37
|
oldestBundled: '1.0.0',
|
|
38
|
-
newestBundled: '1.
|
|
38
|
+
newestBundled: '1.3.0',
|
|
39
39
|
historyUrl: 'https://github.com/cmetech/otto-cli/blob/main/CHANGELOG.md',
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
export const RELEASE_NOTES: ReleaseNote[] = [
|
|
43
|
+
{
|
|
44
|
+
version: '1.3.0',
|
|
45
|
+
date: '2026-06-03',
|
|
46
|
+
headline: 'Restores xlsx capability in scratchpad cells via SheetJS Community Edition, replacing the 1.2.6 removal of `exceljs`. Vendored install means `npm i -g @cmetech/otto` remains a single command with no outbound CDN reach.',
|
|
47
|
+
added: [
|
|
48
|
+
'**SheetJS Community Edition (`XLSX`) bound in scratchpad cells.** Restores the xlsx read/write capability dropped in 1.2.6 with the removal of `exceljs`. The SheetJS CE tarball is vendored at `vendor/xlsx-0.20.3.tgz` (SHA-256 verified at prepublish by `scripts/verify-vendored-xlsx.mjs` and at unit-test time by `src/tests/vendor-xlsx.test.ts`), so there is no outbound CDN reach at install time — `npm i -g @cmetech/otto` remains the single command for compliance/air-gapped environments. Cells now write `const wb = XLSX.utils.book_new(); …` (SheetJS canonical API; ExcelJS-style `new Workbook()` calls from pre-1.2.6 cells continue to ReferenceError). CE → Pro upgrade path is documented in `vendor/README.md`: drop a Pro tarball, swap the `file:` reference, regenerate the lockfile — no code change required; the `XLSX` binding name stays.',
|
|
49
|
+
],
|
|
50
|
+
},
|
|
43
51
|
{
|
|
44
52
|
version: '1.2.6',
|
|
45
53
|
date: '2026-06-03',
|
package/vendor/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Vendored dependencies
|
|
2
|
+
|
|
3
|
+
This directory holds vendored npm package tarballs that are bundled inside the
|
|
4
|
+
published `@cmetech/otto` package. They are referenced from root `package.json`
|
|
5
|
+
via `"file:vendor/<name>.tgz"` deps. End users never reach the upstream CDN
|
|
6
|
+
during `npm i -g @cmetech/otto` — the tarball ships inside the OTTO tarball.
|
|
7
|
+
|
|
8
|
+
## Files
|
|
9
|
+
|
|
10
|
+
| File | Purpose |
|
|
11
|
+
|---|---|
|
|
12
|
+
| `xlsx-0.20.3.tgz` | SheetJS Community Edition 0.20.3 (binding name `XLSX` in scratchpad cells). Source: <https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz>. |
|
|
13
|
+
| `xlsx-0.20.3.tgz.sha256` | Recorded SHA-256 of the file above. Verified at `prepublishOnly` and by `src/tests/vendor-xlsx.test.ts`. |
|
|
14
|
+
| `README.md` | This file. |
|
|
15
|
+
|
|
16
|
+
## Refresh procedure (new CE version)
|
|
17
|
+
|
|
18
|
+
1. Download the new tarball:
|
|
19
|
+
```bash
|
|
20
|
+
curl -sL "https://cdn.sheetjs.com/xlsx-X.Y.Z/xlsx-X.Y.Z.tgz" -o vendor/xlsx-X.Y.Z.tgz
|
|
21
|
+
```
|
|
22
|
+
2. Compute and record the SHA-256:
|
|
23
|
+
```bash
|
|
24
|
+
shasum -a 256 vendor/xlsx-X.Y.Z.tgz | awk '{print $1 " xlsx-X.Y.Z.tgz"}' > vendor/xlsx-X.Y.Z.tgz.sha256
|
|
25
|
+
```
|
|
26
|
+
3. Update root `package.json`:
|
|
27
|
+
- `dependencies.xlsx` → `"file:vendor/xlsx-X.Y.Z.tgz"`.
|
|
28
|
+
4. Update `scripts/verify-vendored-xlsx.mjs`: change the `TARBALL_BASENAME` constant to `xlsx-X.Y.Z.tgz`.
|
|
29
|
+
5. Update `src/tests/vendor-xlsx.test.ts`: change the `TARBALL_BASENAME` constant.
|
|
30
|
+
6. Regenerate the lockfile:
|
|
31
|
+
```bash
|
|
32
|
+
npm install --package-lock-only --ignore-scripts
|
|
33
|
+
```
|
|
34
|
+
7. Run the verification:
|
|
35
|
+
```bash
|
|
36
|
+
npm run verify:vendored-xlsx
|
|
37
|
+
```
|
|
38
|
+
8. Remove the previous tarball + SHA file from `vendor/`.
|
|
39
|
+
9. Commit.
|
|
40
|
+
|
|
41
|
+
## CE → Pro upgrade procedure
|
|
42
|
+
|
|
43
|
+
SheetJS Pro is distributed as a separate tarball (`xlsxPro-X.Y.Z.tgz`) and
|
|
44
|
+
requires a license token at download time. The runtime API is identical to CE —
|
|
45
|
+
no code change is needed; only the vendored file and its references move.
|
|
46
|
+
|
|
47
|
+
1. Obtain the Pro tarball from SheetJS (purchase + tarball URL with embedded
|
|
48
|
+
license token). Download to `vendor/xlsxPro-X.Y.Z.tgz`.
|
|
49
|
+
2. Compute and record the SHA-256:
|
|
50
|
+
```bash
|
|
51
|
+
shasum -a 256 vendor/xlsxPro-X.Y.Z.tgz | awk '{print $1 " xlsxPro-X.Y.Z.tgz"}' > vendor/xlsxPro-X.Y.Z.tgz.sha256
|
|
52
|
+
```
|
|
53
|
+
3. Update root `package.json`:
|
|
54
|
+
- `dependencies.xlsx` → `"file:vendor/xlsxPro-X.Y.Z.tgz"`.
|
|
55
|
+
4. Update `scripts/verify-vendored-xlsx.mjs`: change `TARBALL_BASENAME` to
|
|
56
|
+
`xlsxPro-X.Y.Z.tgz`.
|
|
57
|
+
5. Update `src/tests/vendor-xlsx.test.ts`: change `TARBALL_BASENAME`.
|
|
58
|
+
6. Regenerate the lockfile:
|
|
59
|
+
```bash
|
|
60
|
+
npm install --package-lock-only --ignore-scripts
|
|
61
|
+
```
|
|
62
|
+
7. Optionally remove `vendor/xlsx-*.tgz` (the previous CE tarball) once confident
|
|
63
|
+
in the swap.
|
|
64
|
+
8. Commit. Tag a release. Publish.
|
|
65
|
+
|
|
66
|
+
The `XLSX` binding name does **not** change. No edits to `kernel-bindings.ts`,
|
|
67
|
+
`kernel-entry.ts`, the cell sandbox, prompts, or tests other than the basename
|
|
68
|
+
constants.
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8dc73fc3b00203e72d176e85b50938627c7b086e607c682e8d3c22c02bb99fe8 xlsx-0.20.3.tgz
|