@floless/app 0.31.2 → 0.31.3

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.
@@ -52835,7 +52835,7 @@ function appVersion() {
52835
52835
  return resolveVersion({
52836
52836
  isSea: isSea2(),
52837
52837
  sqVersionXml: readSqVersionXml(),
52838
- define: true ? "0.31.2" : void 0,
52838
+ define: true ? "0.31.3" : void 0,
52839
52839
  pkgVersion: readPkgVersion()
52840
52840
  });
52841
52841
  }
@@ -52845,7 +52845,7 @@ function resolveChannel(s) {
52845
52845
  return "dev";
52846
52846
  }
52847
52847
  function appChannel() {
52848
- return resolveChannel({ isSea: isSea2(), define: true ? "0.31.2" : void 0 });
52848
+ return resolveChannel({ isSea: isSea2(), define: true ? "0.31.3" : void 0 });
52849
52849
  }
52850
52850
 
52851
52851
  // oauth-presets.ts
package/dist/web/aware.js CHANGED
@@ -171,6 +171,57 @@
171
171
  .join('')}</table>`;
172
172
  }
173
173
 
174
+ // The Description tab is for non-coders — it must read as plain English about what a
175
+ // node does, never a wall of code/markup. Short scalar inputs (phase: 1, version:
176
+ // '2025.0') are the real knobs and show verbatim; but a baked blob (HTML markup, a
177
+ // large JSON payload pre-built at compile time, e.g. a steel overlay's `args.html`)
178
+ // is NOT plain English — dumping it raw is the "rubbish" this view must never show.
179
+ // So anything oversized collapses to a dimmed one-line summary ("baked HTML · 210.0 KB").
180
+ const DESC_BLOB_CHARS = 500;
181
+ function summarizeInputValue(v) {
182
+ const isStr = typeof v === 'string';
183
+ const raw = isStr ? v : v == null ? '' : JSON.stringify(v);
184
+ // Summarize on size OR on any markup/code shape — a non-coder must never see raw
185
+ // markup, however short. (The slice bounds the scan to 500 chars; the regex is
186
+ // already linear — a single [^>]* with a disjoint `>` terminator — so no ReDoS.)
187
+ const markup = /<\/?[a-z!][^>]*>/i.test(raw.slice(0, 500));
188
+ if (raw.length <= DESC_BLOB_CHARS && !markup) return { text: raw, blob: false };
189
+ const size = raw.length >= 1024 ? (raw.length / 1024).toFixed(1) + ' KB' : raw.length + ' chars';
190
+ const kind = markup ? 'HTML' : isStr ? 'content' : 'JSON';
191
+ return { text: `baked ${kind} · ${size}`, blob: true };
192
+ }
193
+
194
+ // Exec nodes receive their inputs wrapped in an `args` object (an AWARE implementation
195
+ // detail of how exec passes data in). Flatten that one level so a non-coder sees the
196
+ // real knobs (phase, html…) directly instead of an `args: {…}` row. `code` is the
197
+ // implementation, never an input, so it's dropped; a flattened member that collides
198
+ // with a real top-level input yields to the top-level value.
199
+ function flattenInputs(inputs) {
200
+ const out = Object.create(null); // null-proto: keys like `constructor`/`__proto__` stay plain data
201
+ for (const [k, v] of Object.entries(inputs || {})) {
202
+ if (k === 'code') continue;
203
+ if (k === 'args' && v && typeof v === 'object' && !Array.isArray(v)) {
204
+ for (const [ak, av] of Object.entries(v)) if (ak !== 'code' && !Object.hasOwn(out, ak)) out[ak] = av;
205
+ } else {
206
+ out[k] = v;
207
+ }
208
+ }
209
+ return out;
210
+ }
211
+
212
+ // Description-tab Inputs block: flattened, plain-English, baked blobs summarized and
213
+ // dimmed (meta, not data). Empty inputs → no block at all.
214
+ function descInputs(inputs) {
215
+ const rows = Object.entries(flattenInputs(inputs));
216
+ if (!rows.length) return '';
217
+ const body = rows.map(([k, v]) => {
218
+ const s = summarizeInputValue(v);
219
+ const cell = s.blob ? `<span class="dim-note">${escapeHtml(s.text)}</span>` : escapeHtml(s.text);
220
+ return `<tr><th>${escapeHtml(k)}</th><td>${cell}</td></tr>`;
221
+ }).join('');
222
+ return `<p><strong>Inputs</strong></p><table class="kv">${body}</table>`;
223
+ }
224
+
174
225
  // Plain-text summary of one declared command input (for the Skill tab's inputs
175
226
  // table — kvTable escapes it, so this stays text, no markup): "type (enum vals)
176
227
  // · default X — description".
@@ -308,8 +359,6 @@
308
359
  // EXCLUDES the code (code belongs to the Code tab, never dumped here).
309
360
  const plainDesc = execSource ? leadingComment(execSource) : '';
310
361
  const blurbText = plainDesc && (s => s.length > 80 ? s.slice(0, 79) + '…' : s)(plainDesc.replace(/\.\s+.*/, '.').trim());
311
- const inputsNoCode = {};
312
- for (const [k, v] of Object.entries(inputs || {})) if (k !== 'code') inputsNoCode[k] = v;
313
362
  return {
314
363
  _mode: n.mode,
315
364
  _runtimeModel: !!n.runtimeModel, // B2: lock stamped runtime-model → card badge
@@ -321,7 +370,7 @@
321
370
  title: escapeHtml(n.id),
322
371
  subtitle: `${agentLabel}${cmd ? '/' + cmd : ''} · ${mode}`,
323
372
  blurb: blurbText ? escapeHtml(blurbText) : n.notes[0] ? escapeHtml(humanizeNote(n.notes[0].text)) : `${mode}-mode ${cmd ? '<code>' + cmd + '</code>' : escapeHtml(n.kind)} node`,
324
- description: `${plainDesc ? `<p>${escapeHtml(plainDesc)}</p>` : ''}<p>Resolves to ${modeBadge} via <code>${escapeHtml(n.agent || n.kind)}${n.command ? '.' + escapeHtml(n.command) : ''}</code>.</p>${Object.keys(inputsNoCode).length ? `<p><strong>Inputs</strong></p>${kvTable(inputsNoCode)}` : ''}${execSource ? `<p class="dim-note">Full source in the <strong>Code</strong> tab.</p>` : ''}${notesHtml}`,
373
+ description: `${plainDesc ? `<p>${escapeHtml(plainDesc)}</p>` : ''}<p>Resolves to ${modeBadge} via <code>${escapeHtml(n.agent || n.kind)}${n.command ? '.' + escapeHtml(n.command) : ''}</code>.</p>${descInputs(inputs)}${execSource ? `<p class="dim-note">Full source in the <strong>Code</strong> tab.</p>` : ''}${notesHtml}`,
325
374
  // Rich agent/command detail when the manifest is installed (n.skill); else
326
375
  // the lock-pointer fallback below (exec/agent-less nodes, uninstalled agents).
327
376
  skill: skillBody(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floless/app",
3
- "version": "0.31.2",
3
+ "version": "0.31.3",
4
4
  "type": "module",
5
5
  "description": "Thin localhost host for floless.app — serves web/ and shells the aware CLI. No engine, no LLM.",
6
6
  "bin": {