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 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. Selectors are not full jq: pipes,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-supernova",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "CodeMode for Pi and OMP: read, edit, write and bash, with transactional files, source views and shared-input program batches.",
5
5
  "type": "module",
6
6
  "author": "AdityaVG13",
@@ -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
- if (params.path !== undefined && params.target !== undefined && params.path !== params.target) {
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({ ...params, path: params.path ?? params.target });
88
+ const args = sessionJsonArgs({ ...folded, path: folded.path ?? folded.target });
87
89
  validateJsonRead(args);
88
90
  assertReadOptions(args);
89
91
  assertReadFlags(args);
@@ -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("?");
@@ -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|selector}) → JSON, no jq (16MiB input/64MiB selection). Values retain their types.
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.