rewritable 0.12.0 → 0.14.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/package.json +1 -1
- package/seeds/rewritable.html +132 -3
package/package.json
CHANGED
package/seeds/rewritable.html
CHANGED
|
@@ -2322,6 +2322,27 @@ async function renderActionsModePanel(panel) {
|
|
|
2322
2322
|
const skillRows = skillAffs.length ? skillAffs.map(a =>
|
|
2323
2323
|
'<div class="rwa-mode-row"><div><div class="rwa-mode-title">' + escRuntimeHtml(a.name) + '</div><div class="rwa-mode-meta">' + escRuntimeHtml(a.kind || 'skill') + ' · ' + escRuntimeHtml(a.skillId) + '</div></div><button type="button" data-action-skill="' + escRuntimeHtml(a.skillId) + '">Open in Skills</button></div>'
|
|
2324
2324
|
).join('') : '<div class="rwa-mode-empty">No installed skills.</div>';
|
|
2325
|
+
// Intelligences (rwa-agent/1 roles) — list + activate/deactivate. Activating offers the role's
|
|
2326
|
+
// recommended model (intelligence/0.2 I-A). A verified role can be activated; unverified cannot.
|
|
2327
|
+
const agentList = (typeof runtimeListAgents === 'function') ? runtimeListAgents() : [];
|
|
2328
|
+
const activeRole = (runtimeAgentActive() || {}).role || null;
|
|
2329
|
+
const advisorSet = (typeof runtimeListAdvisors === 'function') ? runtimeListAdvisors() : [];
|
|
2330
|
+
const advisorFull = advisorSet.length >= 3;
|
|
2331
|
+
const agentRows = agentList.length ? agentList.map(a => {
|
|
2332
|
+
const isActive = a.role === activeRole;
|
|
2333
|
+
const isAdvisor = advisorSet.indexOf(a.role) >= 0;
|
|
2334
|
+
const state = isActive ? 'primary' : (isAdvisor ? 'advisor' : '');
|
|
2335
|
+
const meta = (a.verified ? 'verified' : 'unverified') + (state ? ' · ' + state : '');
|
|
2336
|
+
let btns = '';
|
|
2337
|
+
if (a.verified) {
|
|
2338
|
+
const r = escRuntimeHtml(a.role);
|
|
2339
|
+
if (isActive) btns = '<button type="button" data-agent-off="1">Deactivate</button>';
|
|
2340
|
+
else if (isAdvisor) btns = '<button type="button" data-agent-advoff="' + r + '">Remove advisor</button>';
|
|
2341
|
+
else btns = '<button type="button" data-agent-on="' + r + '">Activate</button>'
|
|
2342
|
+
+ (advisorFull ? '<button type="button" disabled title="advisor limit reached">Add advisor</button>' : '<button type="button" data-agent-advon="' + r + '">Add advisor</button>');
|
|
2343
|
+
}
|
|
2344
|
+
return '<div class="rwa-mode-row"><div><div class="rwa-mode-title">' + escRuntimeHtml(a.role) + '</div><div class="rwa-mode-meta">' + escRuntimeHtml('intelligence · ' + meta) + '</div></div>' + btns + '</div>';
|
|
2345
|
+
}).join('') : '<div class="rwa-mode-empty">No intelligences installed.</div>';
|
|
2325
2346
|
panel.innerHTML = [
|
|
2326
2347
|
'<div class="rwa-mode-section">',
|
|
2327
2348
|
'<div class="rwa-mode-kicker">Activity</div>',
|
|
@@ -2336,6 +2357,7 @@ async function renderActionsModePanel(panel) {
|
|
|
2336
2357
|
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Recent runs</div>' + histRows + '</div>',
|
|
2337
2358
|
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Live affordances</div>' + affRows + '</div>',
|
|
2338
2359
|
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Installed skill actions</div>' + skillRows + '</div>',
|
|
2360
|
+
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Intelligences</div>' + agentRows + '</div>',
|
|
2339
2361
|
].join('');
|
|
2340
2362
|
const undoBtn = panel.querySelector('#rwa-actions-undo');
|
|
2341
2363
|
if (undoBtn) undoBtn.addEventListener('click', () => runtimeUndo());
|
|
@@ -2352,6 +2374,19 @@ async function renderActionsModePanel(panel) {
|
|
|
2352
2374
|
panel.querySelectorAll('[data-action-skill]').forEach(btn => {
|
|
2353
2375
|
btn.addEventListener('click', () => runtimeSetMode('skills'));
|
|
2354
2376
|
});
|
|
2377
|
+
panel.querySelectorAll('[data-agent-on]').forEach(btn => btn.addEventListener('click', () => {
|
|
2378
|
+
try { runtimeActivateAgent(btn.getAttribute('data-agent-on')); } // setActive + offer recommended model
|
|
2379
|
+
catch (e) { if (typeof setStatus === 'function') setStatus('err', '✗ ' + (e && (e.code || e.message))); }
|
|
2380
|
+
renderActionsModePanel(panel);
|
|
2381
|
+
}));
|
|
2382
|
+
const agentOff = panel.querySelector('[data-agent-off]');
|
|
2383
|
+
if (agentOff) agentOff.addEventListener('click', () => { runtimeSetActiveAgent(null); renderActionsModePanel(panel); });
|
|
2384
|
+
panel.querySelectorAll('[data-agent-advon]').forEach(btn => btn.addEventListener('click', () => {
|
|
2385
|
+
try { runtimeAddAdvisor(btn.getAttribute('data-agent-advon')); } // I-E: layer an advisory lens
|
|
2386
|
+
catch (e) { if (typeof setStatus === 'function') setStatus('err', '✗ ' + (e && (e.code || e.message))); }
|
|
2387
|
+
renderActionsModePanel(panel);
|
|
2388
|
+
}));
|
|
2389
|
+
panel.querySelectorAll('[data-agent-advoff]').forEach(btn => btn.addEventListener('click', () => { runtimeRemoveAdvisor(btn.getAttribute('data-agent-advoff')); renderActionsModePanel(panel); }));
|
|
2355
2390
|
}
|
|
2356
2391
|
|
|
2357
2392
|
// ─── Agent (rwa-edit/1) ─────────────────────────────────────────────
|
|
@@ -5593,11 +5628,26 @@ function getActiveActor() {
|
|
|
5593
5628
|
// system_prompt swaps the per-kind FRAMING; the shared SYSTEM_PROMPT_RULES (tool protocol, frozen-
|
|
5594
5629
|
// zone rules, data-rwa-id) are always appended so editing still works. No agent → the singleton.
|
|
5595
5630
|
function resolveSystemPrompt() {
|
|
5631
|
+
let base = SYSTEM_PROMPT;
|
|
5596
5632
|
if (activeAgentRole) {
|
|
5597
5633
|
const rec = Array.from(installedAgents.values()).find(a => a.role === activeAgentRole && a.verified);
|
|
5598
|
-
if (rec && typeof rec.manifest.system_prompt === 'string')
|
|
5634
|
+
if (rec && typeof rec.manifest.system_prompt === 'string') base = rec.manifest.system_prompt + '\n' + SYSTEM_PROMPT_RULES;
|
|
5635
|
+
}
|
|
5636
|
+
return base + _agAdvisorBlock(); // I-E: append any advisory lenses (secondary; empty → byte-identical)
|
|
5637
|
+
}
|
|
5638
|
+
// I-E (intelligence/0.2 §6) — blended overlays. The PRIMARY is activeAgentRole (framing/actor/vault,
|
|
5639
|
+
// unchanged). advisorRoles add advisory PROSE only — never capabilities, so the vault gate
|
|
5640
|
+
// (_agVaultAllowed, keyed on the active record) stays primary-only by construction. Verified-only,
|
|
5641
|
+
// ephemeral (never serialized), capped. Block is omitted when empty (single-role prompt unchanged).
|
|
5642
|
+
function _agAdvisorBlock() {
|
|
5643
|
+
if (!advisorRoles.size) return '';
|
|
5644
|
+
const lines = [];
|
|
5645
|
+
for (const role of advisorRoles) {
|
|
5646
|
+
if (role === activeAgentRole) continue; // a role is primary XOR advisor, never both
|
|
5647
|
+
const rec = Array.from(installedAgents.values()).find(a => a.role === role && a.verified);
|
|
5648
|
+
if (rec && typeof rec.manifest.system_prompt === 'string') lines.push('- ' + role + ': ' + rec.manifest.system_prompt);
|
|
5599
5649
|
}
|
|
5600
|
-
return
|
|
5650
|
+
return lines.length ? '\n\nAdditional advisory lenses (secondary — apply only where they don\'t conflict with the above):\n' + lines.join('\n') : '';
|
|
5601
5651
|
}
|
|
5602
5652
|
// I12 — the role-scoped vault gate: exact vault:<ns> membership in the agent's vault_namespace_set
|
|
5603
5653
|
// (mirrors _skVaultAllowed against the agent record instead of the skill's permissions).
|
|
@@ -6812,6 +6862,10 @@ const installedSkills = new Map();
|
|
|
6812
6862
|
// starts with no agent active per §12).
|
|
6813
6863
|
const installedAgents = new Map();
|
|
6814
6864
|
let activeAgentRole = null;
|
|
6865
|
+
// I-E — advisory roles layered atop the primary (in-memory, ephemeral, never serialized — like the
|
|
6866
|
+
// active role). Capped for prompt coherence/size. Advisors contribute prose only (see _agAdvisorBlock).
|
|
6867
|
+
const advisorRoles = new Set();
|
|
6868
|
+
const ADVISOR_CAP = 3;
|
|
6815
6869
|
// I8 (v0.9 §9) — hook firing state. activeHooks holds skillIds currently executing (re-entrancy
|
|
6816
6870
|
// guard, Inv 23); _lastHookMode tracks the prior mode for on-mode-change's `previous`; _hookSeq
|
|
6817
6871
|
// makes rwa_hook_log keys unique within a millisecond.
|
|
@@ -7806,6 +7860,19 @@ function runtimeSetActiveAgent(role) {
|
|
|
7806
7860
|
if (!rec.verified) throw new RwaEditError('unverified_agent', null, { role });
|
|
7807
7861
|
activeAgentRole = role;
|
|
7808
7862
|
}
|
|
7863
|
+
// I-E — add/remove an advisory role. Verified-only (its prompt drives modify), not-the-primary,
|
|
7864
|
+
// capped. Checks order so unverified/not-found beat the cap. Returns the current advisor list.
|
|
7865
|
+
function runtimeAddAdvisor(role) {
|
|
7866
|
+
const rec = Array.from(installedAgents.values()).find(a => a.role === role);
|
|
7867
|
+
if (!rec) throw new RwaEditError('agent_not_found', null, { role });
|
|
7868
|
+
if (!rec.verified) throw new RwaEditError('unverified_agent', null, { role });
|
|
7869
|
+
if (role === activeAgentRole || advisorRoles.has(role)) return Array.from(advisorRoles); // primary / already → no-op
|
|
7870
|
+
if (advisorRoles.size >= ADVISOR_CAP) throw new RwaEditError('advisor_cap_reached', null, { cap: ADVISOR_CAP });
|
|
7871
|
+
advisorRoles.add(role);
|
|
7872
|
+
return Array.from(advisorRoles);
|
|
7873
|
+
}
|
|
7874
|
+
function runtimeRemoveAdvisor(role) { advisorRoles.delete(role); return Array.from(advisorRoles); }
|
|
7875
|
+
function runtimeListAdvisors() { return Array.from(advisorRoles); }
|
|
7809
7876
|
// §12 — validate + verify + register an agent, then persist the #rwa-agents zone (same discipline as
|
|
7810
7877
|
// runtimeInstallSkill: rollback the in-memory map on a persist failure). A signed-but-unverified
|
|
7811
7878
|
// agent registers (verified:false) but can't activate.
|
|
@@ -7831,6 +7898,7 @@ async function runtimeUninstallAgent(agentId) {
|
|
|
7831
7898
|
if (!prev) return { ok: false, errors: ['not_installed'] };
|
|
7832
7899
|
installedAgents.delete(agentId);
|
|
7833
7900
|
if (activeAgentRole && prev.role === activeAgentRole && !Array.from(installedAgents.values()).some(a => a.role === activeAgentRole)) activeAgentRole = null;
|
|
7901
|
+
if (prev.role && !Array.from(installedAgents.values()).some(a => a.role === prev.role)) advisorRoles.delete(prev.role); // I-E: drop a removed role from advisors
|
|
7834
7902
|
try {
|
|
7835
7903
|
await runtimeRegionCommit({ regions: [_agAgentsRegion()], actor: 'agent:uninstall', reachability: 'frozen' });
|
|
7836
7904
|
} catch (e) {
|
|
@@ -8083,6 +8151,67 @@ window.__rwaClassifyInstallText = classifyInstallText;
|
|
|
8083
8151
|
window.__rwaInstallFromText = routeInstallFromText;
|
|
8084
8152
|
window.__rwaHandleCarrierDrop = handleCarrierDrop;
|
|
8085
8153
|
|
|
8154
|
+
// ── intelligence/0.2 I-A (docs/specs/rwa-intelligence-spec.md §6) — recommended model on activation.
|
|
8155
|
+
// A carrier may carry a NON-SECRET recommended_model / recommended_backend on its rwa-agent/1
|
|
8156
|
+
// ENVELOPE (OUTSIDE the signed `agent`, so canonicalAgent is unchanged and the signature still
|
|
8157
|
+
// verifies — this stays seed-only). On activation the runtime OFFERS to apply it to sessionStorage
|
|
8158
|
+
// behind a one-line consent: it never auto-applies, never sets a base-URL, never touches the API
|
|
8159
|
+
// key. A recommendation is a suggestion, not a stored credential (key/model are sessionStorage-only).
|
|
8160
|
+
const REC_MODEL_RE = /^[A-Za-z0-9._:\/-]{1,200}$/; // a model id: provider/name, dots, colon (ollama), hyphen
|
|
8161
|
+
const REC_BACKENDS = ['openrouter', 'ollama', 'lmstudio', 'atomic', 'bridge', 'bridge-session'];
|
|
8162
|
+
function getRecommendation(envelope) {
|
|
8163
|
+
const e = envelope || {};
|
|
8164
|
+
const out = {};
|
|
8165
|
+
if (typeof e.recommended_model === 'string' && REC_MODEL_RE.test(e.recommended_model.trim())) out.model = e.recommended_model.trim();
|
|
8166
|
+
if (typeof e.recommended_backend === 'string' && REC_BACKENDS.includes(e.recommended_backend.trim())) out.backend = e.recommended_backend.trim();
|
|
8167
|
+
return (out.model || out.backend) ? out : null;
|
|
8168
|
+
}
|
|
8169
|
+
function applyRecommendation(rec) {
|
|
8170
|
+
const r = rec || {};
|
|
8171
|
+
const applied = {};
|
|
8172
|
+
if (r.model && REC_MODEL_RE.test(String(r.model))) { sessionStorage.setItem(RWA.K_MODEL, String(r.model)); applied.model = String(r.model); }
|
|
8173
|
+
if (r.backend && REC_BACKENDS.includes(String(r.backend))) { sessionStorage.setItem(RWA.K_BACKEND, String(r.backend)); applied.backend = String(r.backend); }
|
|
8174
|
+
try { const m = document.getElementById('rwa-model'); if (m && applied.model) m.value = applied.model; const b = document.getElementById('rwa-backend'); if (b && applied.backend) { b.value = applied.backend; b.dispatchEvent(new Event('change')); } } catch (_) {}
|
|
8175
|
+
return applied;
|
|
8176
|
+
}
|
|
8177
|
+
// Offer the role's recommended model, if any and if it differs from the current session. Fire-and-
|
|
8178
|
+
// forget consent dialog; resolves with the choice. Activation already happened — this only proposes.
|
|
8179
|
+
function offerRecommendedModel(role) {
|
|
8180
|
+
const recRec = Array.from(installedAgents.values()).find(a => a.role === role);
|
|
8181
|
+
const rec = recRec && getRecommendation(recRec.envelope);
|
|
8182
|
+
if (!rec) return Promise.resolve({ offered: false });
|
|
8183
|
+
const curModel = sessionStorage.getItem(RWA.K_MODEL) || RWA.MODEL;
|
|
8184
|
+
const curBackend = sessionStorage.getItem(RWA.K_BACKEND) || 'openrouter';
|
|
8185
|
+
if ((!rec.model || rec.model === curModel) && (!rec.backend || rec.backend === curBackend)) return Promise.resolve({ offered: false });
|
|
8186
|
+
return new Promise(resolve => {
|
|
8187
|
+
const prev = document.getElementById('rwa-model-offer'); if (prev) prev.remove();
|
|
8188
|
+
const overlay = document.createElement('div'); overlay.id = 'rwa-model-offer';
|
|
8189
|
+
overlay.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;';
|
|
8190
|
+
const card = document.createElement('div');
|
|
8191
|
+
card.style.cssText = 'background:#fff;max-width:480px;width:92%;border-radius:18px;padding:24px 26px;font:14px/1.5 var(--font-ui,system-ui);box-shadow:0 12px 48px rgba(0,0,0,.28);';
|
|
8192
|
+
const what = [rec.model ? 'model <code>' + _skEsc(rec.model) + '</code>' : '', rec.backend ? 'backend <code>' + _skEsc(rec.backend) + '</code>' : ''].filter(Boolean).join(' on ');
|
|
8193
|
+
card.innerHTML =
|
|
8194
|
+
'<h2 style="margin:0 0 .4em;font-size:1.15rem">Use this intelligence’s recommended ' + (rec.model ? 'model' : 'backend') + '?</h2>' +
|
|
8195
|
+
'<p style="margin:.2em 0;color:#444">The <strong>' + _skEsc(role) + '</strong> role suggests ' + what + ' for ⌘K. This is a <em>recommendation</em> (not part of the signed role) — applying it changes only your session’s model/backend selection. Your API key is untouched.</p>' +
|
|
8196
|
+
'<div style="display:flex;gap:10px;margin-top:1.2em;justify-content:flex-end">' +
|
|
8197
|
+
'<button data-act="keep" style="padding:9px 16px;border:1px solid #ccc;border-radius:10px;background:#fff;cursor:pointer">Keep current</button>' +
|
|
8198
|
+
'<button data-act="apply" style="padding:9px 16px;border:none;border-radius:10px;background:var(--gray-900,#111);color:#fff;cursor:pointer">Use it</button>' +
|
|
8199
|
+
'</div>';
|
|
8200
|
+
overlay.appendChild(card); document.body.appendChild(overlay);
|
|
8201
|
+
const close = (choice) => { overlay.remove(); resolve(choice); };
|
|
8202
|
+
card.querySelector('[data-act=keep]').onclick = () => close({ offered: true, applied: null });
|
|
8203
|
+
card.querySelector('[data-act=apply]').onclick = () => close({ offered: true, applied: applyRecommendation(rec) });
|
|
8204
|
+
});
|
|
8205
|
+
}
|
|
8206
|
+
// Activate a role AND offer its recommended model — the "on activation" entry the UI calls.
|
|
8207
|
+
function runtimeActivateAgent(role) { runtimeSetActiveAgent(role); return offerRecommendedModel(role); }
|
|
8208
|
+
window.__rwaGetRecommendation = getRecommendation;
|
|
8209
|
+
window.__rwaApplyRecommendation = applyRecommendation;
|
|
8210
|
+
window.__rwaOfferRecommendedModel = offerRecommendedModel;
|
|
8211
|
+
window.__rwaActivateAgent = runtimeActivateAgent;
|
|
8212
|
+
window.__rwaResolveSystemPrompt = resolveSystemPrompt; // I-E test hook — the assembled modify() prompt
|
|
8213
|
+
window.__rwaGetActiveActor = getActiveActor;
|
|
8214
|
+
|
|
8086
8215
|
// §4/§5a — does a network: host pattern admit a host? Mirror of cli/src/skill-manifest.mjs
|
|
8087
8216
|
// matchNetworkOrigin (keep in step). The bridge's per-call origin check.
|
|
8088
8217
|
function _skMatchNetworkOrigin(pattern, host) {
|
|
@@ -9615,7 +9744,7 @@ document.addEventListener('keydown', e => {
|
|
|
9615
9744
|
discoverSkills: runtimeDiscoverSkills, // v0.9 §11 (I6) — GET the marketplace index (opt-in network)
|
|
9616
9745
|
fetchSkillFromIndex: runtimeFetchSkillFromIndex, // v0.9 §11 (I6) — fetch + client-side-verify an indexed skill
|
|
9617
9746
|
vault: { get: runtimeVaultGet, set: runtimeVaultSet, has: runtimeVaultHas, namespaces: runtimeVaultNamespaces, unlock: runtimeVaultUnlock, lock: runtimeVaultLock, isLocked: runtimeVaultIsLocked, export: runtimeVaultExport, import: runtimeVaultImport }, // v0.8 §6 + v0.9 §14 (I13) portable export/import
|
|
9618
|
-
agents: { list: runtimeListAgents, active: runtimeAgentActive, setActive: runtimeSetActiveAgent, install: runtimeInstallAgent, uninstall: runtimeUninstallAgent, message: runtimeAgentMessage, showInstallDialog: showAgentInstallDialog }, // v0.9 §12 — multi-agent roles
|
|
9747
|
+
agents: { list: runtimeListAgents, active: runtimeAgentActive, setActive: runtimeSetActiveAgent, activate: runtimeActivateAgent, install: runtimeInstallAgent, uninstall: runtimeUninstallAgent, message: runtimeAgentMessage, showInstallDialog: showAgentInstallDialog, offerModel: offerRecommendedModel, addAdvisor: runtimeAddAdvisor, removeAdvisor: runtimeRemoveAdvisor, advisors: runtimeListAdvisors }, // v0.9 §12 — multi-agent roles; `activate` = setActive + offer recommended model (I-A); addAdvisor/removeAdvisor/advisors = blended overlays (I-E)
|
|
9619
9748
|
hookLog: runtimeHookLog, // v0.9 §9 — the hook audit trail (rwa_hook_log)
|
|
9620
9749
|
};
|
|
9621
9750
|
// `status` is a getter so each read returns a fresh snapshot of
|