rewritable 0.12.0 → 0.13.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 +80 -1
package/package.json
CHANGED
package/seeds/rewritable.html
CHANGED
|
@@ -2322,6 +2322,18 @@ 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 agentRows = agentList.length ? agentList.map(a => {
|
|
2330
|
+
const isActive = a.role === activeRole;
|
|
2331
|
+
const meta = (a.verified ? 'verified' : 'unverified') + (isActive ? ' · active' : '');
|
|
2332
|
+
const btn = !a.verified ? '' : (isActive
|
|
2333
|
+
? '<button type="button" data-agent-off="1">Deactivate</button>'
|
|
2334
|
+
: '<button type="button" data-agent-on="' + escRuntimeHtml(a.role) + '">Activate</button>');
|
|
2335
|
+
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>' + btn + '</div>';
|
|
2336
|
+
}).join('') : '<div class="rwa-mode-empty">No intelligences installed.</div>';
|
|
2325
2337
|
panel.innerHTML = [
|
|
2326
2338
|
'<div class="rwa-mode-section">',
|
|
2327
2339
|
'<div class="rwa-mode-kicker">Activity</div>',
|
|
@@ -2336,6 +2348,7 @@ async function renderActionsModePanel(panel) {
|
|
|
2336
2348
|
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Recent runs</div>' + histRows + '</div>',
|
|
2337
2349
|
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Live affordances</div>' + affRows + '</div>',
|
|
2338
2350
|
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Installed skill actions</div>' + skillRows + '</div>',
|
|
2351
|
+
'<div class="rwa-mode-section"><div class="rwa-mode-kicker">Intelligences</div>' + agentRows + '</div>',
|
|
2339
2352
|
].join('');
|
|
2340
2353
|
const undoBtn = panel.querySelector('#rwa-actions-undo');
|
|
2341
2354
|
if (undoBtn) undoBtn.addEventListener('click', () => runtimeUndo());
|
|
@@ -2352,6 +2365,13 @@ async function renderActionsModePanel(panel) {
|
|
|
2352
2365
|
panel.querySelectorAll('[data-action-skill]').forEach(btn => {
|
|
2353
2366
|
btn.addEventListener('click', () => runtimeSetMode('skills'));
|
|
2354
2367
|
});
|
|
2368
|
+
panel.querySelectorAll('[data-agent-on]').forEach(btn => btn.addEventListener('click', () => {
|
|
2369
|
+
try { runtimeActivateAgent(btn.getAttribute('data-agent-on')); } // setActive + offer recommended model
|
|
2370
|
+
catch (e) { if (typeof setStatus === 'function') setStatus('err', '✗ ' + (e && (e.code || e.message))); }
|
|
2371
|
+
renderActionsModePanel(panel);
|
|
2372
|
+
}));
|
|
2373
|
+
const agentOff = panel.querySelector('[data-agent-off]');
|
|
2374
|
+
if (agentOff) agentOff.addEventListener('click', () => { runtimeSetActiveAgent(null); renderActionsModePanel(panel); });
|
|
2355
2375
|
}
|
|
2356
2376
|
|
|
2357
2377
|
// ─── Agent (rwa-edit/1) ─────────────────────────────────────────────
|
|
@@ -8083,6 +8103,65 @@ window.__rwaClassifyInstallText = classifyInstallText;
|
|
|
8083
8103
|
window.__rwaInstallFromText = routeInstallFromText;
|
|
8084
8104
|
window.__rwaHandleCarrierDrop = handleCarrierDrop;
|
|
8085
8105
|
|
|
8106
|
+
// ── intelligence/0.2 I-A (docs/specs/rwa-intelligence-spec.md §6) — recommended model on activation.
|
|
8107
|
+
// A carrier may carry a NON-SECRET recommended_model / recommended_backend on its rwa-agent/1
|
|
8108
|
+
// ENVELOPE (OUTSIDE the signed `agent`, so canonicalAgent is unchanged and the signature still
|
|
8109
|
+
// verifies — this stays seed-only). On activation the runtime OFFERS to apply it to sessionStorage
|
|
8110
|
+
// behind a one-line consent: it never auto-applies, never sets a base-URL, never touches the API
|
|
8111
|
+
// key. A recommendation is a suggestion, not a stored credential (key/model are sessionStorage-only).
|
|
8112
|
+
const REC_MODEL_RE = /^[A-Za-z0-9._:\/-]{1,200}$/; // a model id: provider/name, dots, colon (ollama), hyphen
|
|
8113
|
+
const REC_BACKENDS = ['openrouter', 'ollama', 'lmstudio', 'atomic', 'bridge', 'bridge-session'];
|
|
8114
|
+
function getRecommendation(envelope) {
|
|
8115
|
+
const e = envelope || {};
|
|
8116
|
+
const out = {};
|
|
8117
|
+
if (typeof e.recommended_model === 'string' && REC_MODEL_RE.test(e.recommended_model.trim())) out.model = e.recommended_model.trim();
|
|
8118
|
+
if (typeof e.recommended_backend === 'string' && REC_BACKENDS.includes(e.recommended_backend.trim())) out.backend = e.recommended_backend.trim();
|
|
8119
|
+
return (out.model || out.backend) ? out : null;
|
|
8120
|
+
}
|
|
8121
|
+
function applyRecommendation(rec) {
|
|
8122
|
+
const r = rec || {};
|
|
8123
|
+
const applied = {};
|
|
8124
|
+
if (r.model && REC_MODEL_RE.test(String(r.model))) { sessionStorage.setItem(RWA.K_MODEL, String(r.model)); applied.model = String(r.model); }
|
|
8125
|
+
if (r.backend && REC_BACKENDS.includes(String(r.backend))) { sessionStorage.setItem(RWA.K_BACKEND, String(r.backend)); applied.backend = String(r.backend); }
|
|
8126
|
+
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 (_) {}
|
|
8127
|
+
return applied;
|
|
8128
|
+
}
|
|
8129
|
+
// Offer the role's recommended model, if any and if it differs from the current session. Fire-and-
|
|
8130
|
+
// forget consent dialog; resolves with the choice. Activation already happened — this only proposes.
|
|
8131
|
+
function offerRecommendedModel(role) {
|
|
8132
|
+
const recRec = Array.from(installedAgents.values()).find(a => a.role === role);
|
|
8133
|
+
const rec = recRec && getRecommendation(recRec.envelope);
|
|
8134
|
+
if (!rec) return Promise.resolve({ offered: false });
|
|
8135
|
+
const curModel = sessionStorage.getItem(RWA.K_MODEL) || RWA.MODEL;
|
|
8136
|
+
const curBackend = sessionStorage.getItem(RWA.K_BACKEND) || 'openrouter';
|
|
8137
|
+
if ((!rec.model || rec.model === curModel) && (!rec.backend || rec.backend === curBackend)) return Promise.resolve({ offered: false });
|
|
8138
|
+
return new Promise(resolve => {
|
|
8139
|
+
const prev = document.getElementById('rwa-model-offer'); if (prev) prev.remove();
|
|
8140
|
+
const overlay = document.createElement('div'); overlay.id = 'rwa-model-offer';
|
|
8141
|
+
overlay.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;';
|
|
8142
|
+
const card = document.createElement('div');
|
|
8143
|
+
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);';
|
|
8144
|
+
const what = [rec.model ? 'model <code>' + _skEsc(rec.model) + '</code>' : '', rec.backend ? 'backend <code>' + _skEsc(rec.backend) + '</code>' : ''].filter(Boolean).join(' on ');
|
|
8145
|
+
card.innerHTML =
|
|
8146
|
+
'<h2 style="margin:0 0 .4em;font-size:1.15rem">Use this intelligence’s recommended ' + (rec.model ? 'model' : 'backend') + '?</h2>' +
|
|
8147
|
+
'<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>' +
|
|
8148
|
+
'<div style="display:flex;gap:10px;margin-top:1.2em;justify-content:flex-end">' +
|
|
8149
|
+
'<button data-act="keep" style="padding:9px 16px;border:1px solid #ccc;border-radius:10px;background:#fff;cursor:pointer">Keep current</button>' +
|
|
8150
|
+
'<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>' +
|
|
8151
|
+
'</div>';
|
|
8152
|
+
overlay.appendChild(card); document.body.appendChild(overlay);
|
|
8153
|
+
const close = (choice) => { overlay.remove(); resolve(choice); };
|
|
8154
|
+
card.querySelector('[data-act=keep]').onclick = () => close({ offered: true, applied: null });
|
|
8155
|
+
card.querySelector('[data-act=apply]').onclick = () => close({ offered: true, applied: applyRecommendation(rec) });
|
|
8156
|
+
});
|
|
8157
|
+
}
|
|
8158
|
+
// Activate a role AND offer its recommended model — the "on activation" entry the UI calls.
|
|
8159
|
+
function runtimeActivateAgent(role) { runtimeSetActiveAgent(role); return offerRecommendedModel(role); }
|
|
8160
|
+
window.__rwaGetRecommendation = getRecommendation;
|
|
8161
|
+
window.__rwaApplyRecommendation = applyRecommendation;
|
|
8162
|
+
window.__rwaOfferRecommendedModel = offerRecommendedModel;
|
|
8163
|
+
window.__rwaActivateAgent = runtimeActivateAgent;
|
|
8164
|
+
|
|
8086
8165
|
// §4/§5a — does a network: host pattern admit a host? Mirror of cli/src/skill-manifest.mjs
|
|
8087
8166
|
// matchNetworkOrigin (keep in step). The bridge's per-call origin check.
|
|
8088
8167
|
function _skMatchNetworkOrigin(pattern, host) {
|
|
@@ -9615,7 +9694,7 @@ document.addEventListener('keydown', e => {
|
|
|
9615
9694
|
discoverSkills: runtimeDiscoverSkills, // v0.9 §11 (I6) — GET the marketplace index (opt-in network)
|
|
9616
9695
|
fetchSkillFromIndex: runtimeFetchSkillFromIndex, // v0.9 §11 (I6) — fetch + client-side-verify an indexed skill
|
|
9617
9696
|
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
|
|
9697
|
+
agents: { list: runtimeListAgents, active: runtimeAgentActive, setActive: runtimeSetActiveAgent, activate: runtimeActivateAgent, install: runtimeInstallAgent, uninstall: runtimeUninstallAgent, message: runtimeAgentMessage, showInstallDialog: showAgentInstallDialog, offerModel: offerRecommendedModel }, // v0.9 §12 — multi-agent roles; `activate` = setActive + offer recommended model (intelligence/0.2 I-A)
|
|
9619
9698
|
hookLog: runtimeHookLog, // v0.9 §9 — the hook audit trail (rwa_hook_log)
|
|
9620
9699
|
};
|
|
9621
9700
|
// `status` is a getter so each read returns a fresh snapshot of
|