pi-supernova 0.10.0 → 0.10.1
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 +10 -1
- package/docs/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/src/contract/read.js +5 -3
- package/src/fs/json-read.js +42 -0
- package/src/runtime/reference.js +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,13 @@ Ordinary JavaScript control flow remains available; the guest command bindings
|
|
|
12
12
|
are only `read`, `edit`, `write`, and `bash`. Supernova supplies retrieval,
|
|
13
13
|
transactional file operations, batching, bounded results and the grouped nova UI.
|
|
14
14
|
|
|
15
|
+
## What is new in 0.10.1
|
|
16
|
+
|
|
17
|
+
- JSON reads that still send a leftover `selector` key (the standing schema's
|
|
18
|
+
`json:true|selector` union, misread as a second option) fold into `json`.
|
|
19
|
+
`json:true` plus `selector:".field"` or `selector:"field"` is `.field`.
|
|
20
|
+
Two real projections (`json:".a"` and `selector:".b"`) still fail.
|
|
21
|
+
|
|
15
22
|
## What is new in 0.10.0
|
|
16
23
|
|
|
17
24
|
- Background bash sessions support launch, polling, input and stop with bounded
|
|
@@ -640,7 +647,9 @@ return {verdict, values};
|
|
|
640
647
|
```
|
|
641
648
|
|
|
642
649
|
Selectors support "." (root), .field, .nested[0], .items[0:10], and .["quoted.key"].
|
|
643
|
-
Use json:true for the complete parsed value.
|
|
650
|
+
Use json:true for the complete parsed value. Put the selector in `json`
|
|
651
|
+
(`json:".field"`), not a second `selector` key; a leftover `selector` folds
|
|
652
|
+
when `json` is absent, `true`, or `"."`. Selectors are not full jq: pipes,
|
|
644
653
|
filters, wildcards and negative indices fail explicitly. Missing keys and indices
|
|
645
654
|
fail; false, zero and null remain values. Slices use an exclusive end and clamp to
|
|
646
655
|
array length. Only own JSON properties are traversed; nothing is evaluated.
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.1] - 2026-09-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- JSON `read` folds a leftover `selector` key into `json`. The standing schema
|
|
8
|
+
wrote `json:true|selector` as a union on `json`'s value; models sent a second
|
|
9
|
+
option and hit `read does not accept option "selector"`. `json:true` plus
|
|
10
|
+
`selector:".field"` or `selector:"field"` now projects `.field`. Two real
|
|
11
|
+
projections still fail.
|
|
12
|
+
|
|
3
13
|
## [0.9.0] - 2026-09-20
|
|
4
14
|
|
|
5
15
|
### Changed
|
package/package.json
CHANGED
package/src/contract/read.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { errorMessage, isString, isObject, isNumber, looksLikePath } from "../shared/decode.js";
|
|
2
|
-
import { sessionJsonArgs, validateJsonRead } from "../fs/json-read.js";
|
|
2
|
+
import { foldJsonSelectorAlias, sessionJsonArgs, validateJsonRead } from "../fs/json-read.js";
|
|
3
3
|
|
|
4
4
|
export const SESSION_URI = /^(?:agent|artifact):\/\//i;
|
|
5
5
|
|
|
@@ -79,11 +79,13 @@ function autoResolve(args) {
|
|
|
79
79
|
export function normalizeRead(params) {
|
|
80
80
|
if (!isObject(params)) throw new Error("read requires an options object");
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
const folded = foldJsonSelectorAlias(params);
|
|
83
|
+
|
|
84
|
+
if (folded.path !== undefined && folded.target !== undefined && folded.path !== folded.target) {
|
|
83
85
|
throw new Error("read accepts either path or target, not both");
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
const args = sessionJsonArgs({ ...
|
|
88
|
+
const args = sessionJsonArgs({ ...folded, path: folded.path ?? folded.target });
|
|
87
89
|
validateJsonRead(args);
|
|
88
90
|
assertReadOptions(args);
|
|
89
91
|
assertReadFlags(args);
|
package/src/fs/json-read.js
CHANGED
|
@@ -96,6 +96,48 @@ export function jsonProjector(json) {
|
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
function isWholeJson(json) {
|
|
100
|
+
return json === true || json === ".";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function coerceOneSelector(value) {
|
|
104
|
+
if (!isString(value) || value.length === 0 || value.length > 2048) throw new Error(SELECTOR_HELP);
|
|
105
|
+
const selector = value.startsWith(".") ? value : "." + value;
|
|
106
|
+
|
|
107
|
+
parseSelector(selector);
|
|
108
|
+
|
|
109
|
+
return selector;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function coerceSelector(value) {
|
|
113
|
+
if (Array.isArray(value)) {
|
|
114
|
+
if (!value.length || value.length > 64) throw new Error("JSON selector list requires 1 to 64 selectors");
|
|
115
|
+
|
|
116
|
+
return value.map(coerceOneSelector);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return coerceOneSelector(value);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Standing copy writes json:true|selector as a union on json's value.
|
|
124
|
+
* Models still send a leftover selector key (often with json:true).
|
|
125
|
+
* Fold it when json is absent or the whole document; reject two real projections.
|
|
126
|
+
*/
|
|
127
|
+
export function foldJsonSelectorAlias(args) {
|
|
128
|
+
if (!isObject(args) || args.selector === undefined) return args;
|
|
129
|
+
|
|
130
|
+
if (args.json !== undefined && !isWholeJson(args.json)) {
|
|
131
|
+
throw new Error("read accepts json or selector, not both; put the selector in json (json:\".field\")");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const next = { ...args, json: coerceSelector(args.selector) };
|
|
135
|
+
|
|
136
|
+
delete next.selector;
|
|
137
|
+
|
|
138
|
+
return next;
|
|
139
|
+
}
|
|
140
|
+
|
|
99
141
|
export function sessionJsonArgs(args) {
|
|
100
142
|
if (!isString(args.path) || !/^(agent|artifact):\/\//i.test(args.path) || !args.path.includes("?")) return args;
|
|
101
143
|
const [uri, query] = args.path.split("?");
|
package/src/runtime/reference.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const REFERENCE = `JS body/async arrow; read/write/edit/bash, no fs/import/require. file: workspace JS; data: literals ≤48000 JSON chars.
|
|
3
3
|
read(path|paths,offset=1,limit?) → text/text[]; dirs→entries; PNG/JPEG/GIF/WebP ≤16/20MiB.
|
|
4
4
|
Text ≤64 MiB internally; complete:true requires whole file. Display capped: summarize or read(path,{offset:1,limit:80}); larger files via bash.
|
|
5
|
-
read({path,json:true
|
|
5
|
+
read({path,json:true}) or json:".field" or json:[".a"] → JSON, no jq (16MiB input/64MiB selection). Values retain their types. selector is json's value; a leftover selector key folds.
|
|
6
6
|
read("symbol or question") = read({query,resolve:true}) → view; check status; view.text is a span. read(path,{about}) windows; read({query,evidence:true}) evidence; read({path,outline:true}) declarations.
|
|
7
7
|
write/edit workspace-only; external changes need separately authorized command. write(path,text) or {path,content,append:true}; after read edit or replace:true.
|
|
8
8
|
edit(path,oldText,newText) or {path,edits:[{oldText,newText}]}; unique exact match; numbered windows. edit(view,text) or edit(view,old,new). edit(async()=>{...}) checkpoint: no bash; merge/rollback+rethrow.
|