@wenathlan/extension 1.1.63 → 1.1.64

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.
Files changed (38) hide show
  1. package/README.md +4 -3
  2. package/dist/index.d.ts +3 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +404 -1
  5. package/dist/index.js.map +4 -4
  6. package/dist/memory.d.ts +28 -1
  7. package/dist/memory.d.ts.map +1 -1
  8. package/dist/planreview.d.ts +87 -0
  9. package/dist/planreview.d.ts.map +1 -0
  10. package/dist/policy.d.ts +47 -0
  11. package/dist/policy.d.ts.map +1 -1
  12. package/dist/protocol.d.ts +135 -0
  13. package/dist/protocol.d.ts.map +1 -1
  14. package/dist/surfaces.d.ts +59 -0
  15. package/dist/surfaces.d.ts.map +1 -0
  16. package/dist/types.d.ts +181 -3
  17. package/dist/types.d.ts.map +1 -1
  18. package/dist/version.d.ts +1 -1
  19. package/extension/dist/background.js +669 -2
  20. package/extension/dist/background.js.map +4 -4
  21. package/extension/dist/dashboardpage.html +13 -0
  22. package/extension/dist/dashboardpage.js +129 -0
  23. package/extension/dist/dashboardpage.js.map +7 -0
  24. package/extension/dist/manifest.json +5 -2
  25. package/extension/dist/offscreen.js +1 -0
  26. package/extension/dist/offscreen.js.map +2 -2
  27. package/extension/dist/optionspage.html +14 -0
  28. package/extension/dist/optionspage.js +118 -0
  29. package/extension/dist/optionspage.js.map +7 -0
  30. package/extension/dist/pagebridge.js.map +1 -1
  31. package/extension/dist/popup.html +4 -1
  32. package/extension/dist/popup.js +167 -0
  33. package/extension/dist/popup.js.map +3 -3
  34. package/extension/dist/sidepanel.html +7 -2
  35. package/extension/dist/sidepanel.js +279 -0
  36. package/extension/dist/sidepanel.js.map +2 -2
  37. package/extension/manifest.json +5 -2
  38. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5206,6 +5206,59 @@ var sessionmemory = class {
5206
5206
  async exportsessionbundle(exportedat) {
5207
5207
  return { kind: "sessionbundle", notes: await this.getsitenotes(), summaries: await this.listrunsummaries(), corrections: await this.getcorrections(), exportedat };
5208
5208
  }
5209
+ /**
5210
+ * Interface surface stores of the 1.1.64 family live here, scoped per profile workspace: the commandpalette usage counts the recent first ranking reads, the taskinput history of natural language goals, the onboarding completion state, the per surface layout preferences, the logstream filter preferences and the stepapprove resolution history per origin.
5211
+ */
5212
+ /** Returns every commandpalette usage record so the ranking lifts the recent commands first. */
5213
+ async getpaletteusage() {
5214
+ return await this.adapter.get("paletteusage") ?? [];
5215
+ }
5216
+ /** Replaces the commandpalette usage records after one use: the count grows and the last use time moves so the ranking reads both. */
5217
+ async setpaletteusage(records) {
5218
+ return this.adapter.set("paletteusage", records);
5219
+ }
5220
+ /** Returns the stored taskinput history, newest first. */
5221
+ async gettaskinputs() {
5222
+ return await this.adapter.get("taskinputs") ?? [];
5223
+ }
5224
+ /** Adds one taskinput submission to the per profile history; the retention window stays a user setting. */
5225
+ async addtaskinput(entry) {
5226
+ const retention = (await this.getsettings())?.taskinputretention;
5227
+ const history = [entry, ...await this.gettaskinputs()];
5228
+ await this.adapter.set("taskinputs", retention === void 0 ? history : history.filter((candidate) => entry.at - candidate.at < retention));
5229
+ }
5230
+ /** Returns the onboarding completion state; an absent state means the walkthrough never ran. */
5231
+ async getonboardingstate() {
5232
+ return this.adapter.get("onboarding");
5233
+ }
5234
+ /** Stores the onboarding completion state; a done walkthrough never runs again on its own. */
5235
+ async setonboardingstate(state) {
5236
+ return this.adapter.set("onboarding", state);
5237
+ }
5238
+ /** Returns the layout preferences of one surface; an absent preference set returns undefined. */
5239
+ async getsurfacelayout(surface) {
5240
+ return this.adapter.get(`surfacelayout:${surface}`);
5241
+ }
5242
+ /** Stores the layout preferences of one surface, scoped per profile workspace. */
5243
+ async setsurfacelayout(layout) {
5244
+ return this.adapter.set(`surfacelayout:${layout.surface}`, layout);
5245
+ }
5246
+ /** Returns the stored logstream filter preferences of the live view. */
5247
+ async getlogstreamfilters() {
5248
+ return this.adapter.get("logstreamfilters");
5249
+ }
5250
+ /** Stores the logstream filter preferences of the live view. */
5251
+ async setlogstreamfilters(filter) {
5252
+ return this.adapter.set("logstreamfilters", filter);
5253
+ }
5254
+ /** Returns every stored stepapprove resolution, newest first, with its human provenance. */
5255
+ async getstepapproveresolutions() {
5256
+ return await this.adapter.get("stepapproveresolutions") ?? [];
5257
+ }
5258
+ /** Records one stepapprove resolution in the per origin history. */
5259
+ async addstepapproveresolution(resolution) {
5260
+ await this.adapter.set("stepapproveresolutions", [resolution, ...await this.getstepapproveresolutions()]);
5261
+ }
5209
5262
  };
5210
5263
  function mediakindof(record2) {
5211
5264
  if ("pages" in record2) return "pdf";
@@ -11350,6 +11403,48 @@ function retrydispatchgate(input) {
11350
11403
  if (!input.reviewed) return { allowed: false, reason: `The retry of the step ${input.stepid} passes only through a new reviewed dispatch; an automatic retry never bypasses the review.` };
11351
11404
  return { allowed: true, reason: `The retry of the step ${input.stepid} dispatches again through the full consent gate chain: the session, the plan and the origin gates all recheck the step.` };
11352
11405
  }
11406
+ function paletteactiongate(input) {
11407
+ if (input.action.permission !== void 0 && !input.granted.includes(input.action.permission)) return { allowed: false, reason: `The ${input.action.command} command needs the ${input.action.permission} capability granted before the palette lists it; the palette never offers an action the current capability set refuses.` };
11408
+ if (input.action.session === true && !input.sessionactive) return { allowed: false, reason: `The ${input.action.command} command needs an active browser session before the palette lists it; the palette never offers a run action without its session.` };
11409
+ return { allowed: true, reason: `The ${input.action.command} command rides its granted permissions and lists in the palette.` };
11410
+ }
11411
+ function taskinputproposalgate(input) {
11412
+ if (input.direct) return { allowed: false, reason: "The taskinput never executes a goal directly; every natural language goal routes through the same proposal flow as the api and becomes a reviewed plan first." };
11413
+ if (input.text.trim() === "") return { allowed: false, reason: "The taskinput submission needs its natural language goal; an empty goal never reaches the proposal flow." };
11414
+ if (input.origin.trim() === "") return { allowed: false, reason: "The taskinput submission needs its active origin scope; a goal without an origin never reaches the proposal flow." };
11415
+ return { allowed: true, reason: `The taskinput goal for ${input.origin} rides the same proposal flow as the api: the observation, the capabilities and the plan review all recheck it.` };
11416
+ }
11417
+ function planreviewgate(input) {
11418
+ if (input.state === "approved") return { allowed: true, reason: "The plan already passed its review: the approval is the review of record and the execution proceeds." };
11419
+ if (!input.reviewed) return { allowed: false, reason: "The pending plan has no plancard review yet; every step renders its card with the risk class, the environment and the options before any execution." };
11420
+ return { allowed: true, reason: "The plancard review of the pending plan is open; the resolution of each step stays a distinct human action." };
11421
+ }
11422
+ function stepapprovegate(input) {
11423
+ if (input.stepids.length === 0) return { allowed: false, reason: "A stepapprove resolution names its single step." };
11424
+ if (input.stepids.length > 1) return { allowed: false, reason: `One human action resolves exactly one step; the batch of ${input.stepids.length} steps refuses in full because no batch approval exists.` };
11425
+ if (input.surface === "background") return { allowed: false, reason: `The ${input.resolution} resolution of the step ${input.stepids[0]} needs its distinct human action from a surface; the background never resolves a review on its own.` };
11426
+ if (input.resolution === "edit") return { allowed: true, reason: `The user edits the step ${input.stepids[0]} from the ${input.surface} before approving; the corrected shape rides the plan and the resolution keeps its human provenance.` };
11427
+ return { allowed: true, reason: `The user ${input.resolution === "approve" ? "approved" : "rejected"} the step ${input.stepids[0]} from the ${input.surface}; one distinct human action resolved the step alone.` };
11428
+ }
11429
+ function diffpreviewgate(input) {
11430
+ if (input.risk !== "sensitive") return { allowed: false, reason: `The ${input.risk} step changes no page or browser state; the diffpreview compares the observed before state with the predicted after state of write class steps only.` };
11431
+ return { allowed: true, reason: "The write class step changes page or browser state, so the diffpreview compares its observed before state with its predicted after state." };
11432
+ }
11433
+ function onboardingconsentgate(input) {
11434
+ if (input.consentevents.length === 0) return { allowed: true, reason: "The onboarding completion writes its single consent scoped event; no consent event exists yet." };
11435
+ if (input.consentevents.length === 1) return { allowed: false, reason: `The onboarding already wrote its single consent scoped event ${input.consentevents[0]}; a walkthrough never writes a second one.` };
11436
+ return { allowed: false, reason: `The onboarding found ${input.consentevents.length} consent scoped events; a walkthrough writes exactly one and the extra events refuse.` };
11437
+ }
11438
+ function logbufferboundvalid(bound) {
11439
+ if (bound === void 0) return { allowed: true, reason: "No logstream buffer bound is configured, so the live window keeps every event while the full history stays in memory." };
11440
+ if (!Number.isInteger(bound) || bound <= 0) return { allowed: false, reason: "The logstream buffer bound stays a positive whole number of events the user chose; no engine cap exists." };
11441
+ return { allowed: true, reason: `The logstream buffer bound of ${bound} event${bound === 1 ? "" : "s"} stays the user configured choice; the full history stays in memory.` };
11442
+ }
11443
+ function logstreamegressgate(input) {
11444
+ if (input.entries === 0) return { allowed: false, reason: "The audit excerpt names no event of the logstream; an empty range never copies." };
11445
+ if (!input.verified) return { allowed: false, reason: "The logstream chain failed its live verification; the audit excerpt refuses the copy because only a verified range leaves the stream." };
11446
+ return { allowed: true, reason: `The logstream chain verifies across the ${input.entries} event${input.entries === 1 ? "" : "s"} of the range; the audit excerpt copies as one verified record.` };
11447
+ }
11353
11448
 
11354
11449
  // llm.ts
11355
11450
  var defaultrefusalmarkers = ["i cannot", "i can't", "i'm unable", "refusal:", "cannot comply"];
@@ -11710,7 +11805,7 @@ function budgetcheck(input) {
11710
11805
  }
11711
11806
 
11712
11807
  // version.ts
11713
- var packageversion = "1.1.63";
11808
+ var packageversion = "1.1.64";
11714
11809
 
11715
11810
  // types.ts
11716
11811
  var protocolversion = packageversion;
@@ -13056,6 +13151,273 @@ function sessionbundleof(input) {
13056
13151
  return { kind: "sessionbundle", notes: input.notes, summaries: input.summaries, corrections: input.corrections, exportedat: input.exportedat };
13057
13152
  }
13058
13153
 
13154
+ // planreview.ts
13155
+ function plancardsof(input) {
13156
+ return input.plan.steps.map((step) => ({
13157
+ stepid: step.id,
13158
+ kind: step.kind,
13159
+ risk: step.risk,
13160
+ environment: step.environment ?? defaultenvironment(step),
13161
+ options: step.options ?? "",
13162
+ summary: step.summary,
13163
+ corrections: matchingcorrections(input.corrections, { origin: input.plan.origin, kind: step.kind }).map((entry) => ({ id: entry.id, source: entry.source, reason: entry.reason })),
13164
+ editable: input.plan.state === "pending"
13165
+ }));
13166
+ }
13167
+ function plancardgroups(cards) {
13168
+ const order = ["sensitive", "interaction", "read"];
13169
+ return order.map((risk) => ({ risk, cards: cards.filter((card) => card.risk === risk), expanded: risk === "sensitive" })).filter((group) => group.cards.length > 0);
13170
+ }
13171
+ function stepresolutionof(input) {
13172
+ if (input.stepid.trim() === "") throw new Error("The stepapprove resolution needs its step.");
13173
+ if (input.resolution === "edit" && (input.edited ?? "").trim() === "") throw new Error("The edited resolution needs its corrected step shape.");
13174
+ return { stepid: input.stepid, planid: input.planid, origin: input.origin, resolution: input.resolution, surface: input.surface, ...input.edited !== void 0 && input.edited.trim() !== "" ? { edited: input.edited } : {}, at: input.at };
13175
+ }
13176
+ function resolutionlogeventof(resolution) {
13177
+ return {
13178
+ kind: "review",
13179
+ stepid: resolution.stepid,
13180
+ summary: resolution.resolution === "edit" ? `The user edited the step ${resolution.stepid} of the plan ${resolution.planid} from the ${resolution.surface} before approving; the corrected shape rides the plan.` : `The user ${resolution.resolution === "approve" ? "approved" : "rejected"} the step ${resolution.stepid} of the plan ${resolution.planid} from the ${resolution.surface}; one distinct human action resolved the step alone.`
13181
+ };
13182
+ }
13183
+ function resolutionhistoryafter(history, resolution) {
13184
+ return [resolution, ...history];
13185
+ }
13186
+ function maskverdictsof(state, sensitivefields) {
13187
+ const verdicts = {};
13188
+ for (const [field, value] of Object.entries(state)) {
13189
+ if (sensitivefields.includes(field)) verdicts[field] = `The ${field} value stays masked (${value.length} characters) and never renders in the clear.`;
13190
+ }
13191
+ return verdicts;
13192
+ }
13193
+ function diffpreviewof(input) {
13194
+ const changes = [];
13195
+ const fields = [.../* @__PURE__ */ new Set([...Object.keys(input.before), ...Object.keys(input.after)])];
13196
+ for (const field of fields) {
13197
+ const hasbefore = Object.prototype.hasOwnProperty.call(input.before, field);
13198
+ const hasafter = Object.prototype.hasOwnProperty.call(input.after, field);
13199
+ const beforevalue = input.before[field];
13200
+ const aftervalue = input.after[field];
13201
+ if (hasbefore && !hasafter && beforevalue !== void 0) changes.push({ field, kind: "removed", before: beforevalue });
13202
+ else if (!hasbefore && hasafter && aftervalue !== void 0) changes.push({ field, kind: "added", after: aftervalue });
13203
+ else if (hasbefore && hasafter && beforevalue !== void 0 && aftervalue !== void 0 && beforevalue !== aftervalue) changes.push({ field, kind: "changed", before: beforevalue, after: aftervalue });
13204
+ }
13205
+ return { stepid: input.stepid, before: input.before, after: input.after, changes, maskverdicts: input.maskverdicts ?? {}, provenance: input.provenance };
13206
+ }
13207
+ function stepstimelinenodes(input) {
13208
+ const completed = input.progress?.completedsteps ?? [];
13209
+ const outcomes = input.progress?.outcomes ?? [];
13210
+ const environments = input.progress?.environments;
13211
+ const turnarounds = input.progress?.turnarounds;
13212
+ const gatewaits = input.progress?.gatewaits;
13213
+ let activeset = false;
13214
+ let blocked = false;
13215
+ return input.plan.steps.map((step) => {
13216
+ const outcome = [...outcomes].reverse().find((candidate) => candidate.stepid === step.id);
13217
+ const gatewait = gatewaits?.[step.id];
13218
+ let status;
13219
+ if (outcome !== void 0) status = outcome.ok ? "done" : "failed";
13220
+ else if (gatewait !== void 0) status = "waiting";
13221
+ else if (completed.includes(step.id)) status = "done";
13222
+ else if (input.plan.state === "cancelled" || input.plan.state === "expired") status = "halted";
13223
+ else if (input.plan.state === "rejected") status = "halted";
13224
+ else if (input.plan.state === "approved" && !activeset && !blocked) {
13225
+ status = "running";
13226
+ activeset = true;
13227
+ } else status = "pending";
13228
+ if (status === "waiting") blocked = true;
13229
+ const active = status === "running";
13230
+ return {
13231
+ stepid: step.id,
13232
+ kind: step.kind,
13233
+ status,
13234
+ ...turnarounds?.[step.id] !== void 0 ? { durationms: turnarounds[step.id] } : {},
13235
+ ...environments?.[step.id] !== void 0 ? { environment: environments[step.id] } : step.environment !== void 0 ? { environment: step.environment } : {},
13236
+ active,
13237
+ anchor: `#step-${step.id}`,
13238
+ ...outcome !== void 0 ? { resultsummary: outcome.summary } : {}
13239
+ };
13240
+ });
13241
+ }
13242
+ function activetimelineanchor(nodes) {
13243
+ return nodes.find((node) => node.active)?.anchor;
13244
+ }
13245
+ var logstreamgenesis = "0".repeat(64);
13246
+ async function logstreameventof(input) {
13247
+ if (input.summary.trim() === "") throw new Error("The logstream event needs its summary.");
13248
+ const id = randomid();
13249
+ const hash = await entryhashof({ previous: input.previous, entry: { id, runid: "surfaces", kind: "step", summary: input.summary, origin: input.origin, ...input.stepid !== void 0 ? { stepid: input.stepid } : {}, at: input.at } });
13250
+ return { id, level: input.level, source: input.source, origin: input.origin, summary: input.summary, ...input.stepid !== void 0 ? { stepid: input.stepid } : {}, masked: input.masked, maskverdict: input.maskverdict, hash, at: input.at };
13251
+ }
13252
+ function appendlogstreamevent(events, event) {
13253
+ return [...events, event];
13254
+ }
13255
+ function filterlogstream(events, filter) {
13256
+ return events.filter((event) => (filter.level === void 0 || event.level === filter.level) && (filter.origin === void 0 || filter.origin === "" || event.origin === filter.origin) && (filter.stepid === void 0 || filter.stepid === "" || event.stepid === filter.stepid));
13257
+ }
13258
+ function livebufferof(events, bound) {
13259
+ if (bound === void 0) return events;
13260
+ if (!Number.isInteger(bound) || bound <= 0) return events;
13261
+ return events.slice(-bound);
13262
+ }
13263
+ async function verifylogstream(events) {
13264
+ for (let index = 0; index < events.length; index += 1) {
13265
+ const event = events[index];
13266
+ if (event === void 0) continue;
13267
+ const predecessor = events[index - 1];
13268
+ const expectedprevious = index === 0 || predecessor === void 0 ? logstreamgenesis : predecessor.hash.current;
13269
+ if (event.hash.previous !== expectedprevious) return { valid: false, brokenat: index, reason: `The logstream chain breaks at the event ${event.id}: its previous hash does not link to its predecessor.` };
13270
+ const recomputed = await entryhashof({ previous: event.hash.previous, entry: { id: event.id, runid: "surfaces", kind: "step", summary: event.summary, origin: event.origin, ...event.stepid !== void 0 ? { stepid: event.stepid } : {}, at: event.at } });
13271
+ if (recomputed.current !== event.hash.current) return { valid: false, brokenat: index, reason: `The logstream chain breaks at the event ${event.id}: its own hash does not reproduce.` };
13272
+ }
13273
+ return { valid: true, reason: `The logstream chain of ${events.length} event${events.length === 1 ? "" : "s"} verifies link by link.` };
13274
+ }
13275
+ async function auditexcerptof(events, input) {
13276
+ if (input.from < 0 || input.to <= input.from || input.to > events.length) return { ok: false, text: "", reason: `The excerpt range ${input.from} to ${input.to} names no contiguous slice of the ${events.length} event${events.length === 1 ? "" : "s"}.` };
13277
+ const range = events.slice(input.from, input.to);
13278
+ const verification = await verifylogstream(range);
13279
+ if (!verification.valid) return { ok: false, text: "", reason: `The excerpt refuses the copy: ${verification.reason}` };
13280
+ const text2 = range.map((event) => `[${event.at}] ${event.level} ${event.source}${event.stepid !== void 0 ? ` step ${event.stepid}` : ""} ${event.origin} \u2014 ${event.summary}${event.masked ? ` (${event.maskverdict})` : ""}`).join("\n");
13281
+ return { ok: true, text: text2, reason: `The excerpt copied the verified range ${input.from} to ${input.to} of the logstream.` };
13282
+ }
13283
+ function loglevelof(kind) {
13284
+ if (kind === "error") return "error";
13285
+ if (["deny", "revoke", "stop", "quarantine", "phish", "defer", "schema", "expiry"].includes(kind)) return "warn";
13286
+ return "info";
13287
+ }
13288
+
13289
+ // surfaces.ts
13290
+ function surfacepalette() {
13291
+ return [
13292
+ { id: "starttask", label: "Start task", keywords: ["task", "objective", "run", "goal", "plan"], action: { command: "starttask", surface: "popup" } },
13293
+ { id: "pauserun", label: "Pause run", keywords: ["pause", "hold", "stop", "run"], action: { command: "pauserun", surface: "popup", session: true } },
13294
+ { id: "resumerun", label: "Resume run", keywords: ["resume", "continue", "unpause", "run"], action: { command: "resumerun", surface: "popup", session: true } },
13295
+ { id: "cancelrun", label: "Cancel run", keywords: ["cancel", "stop", "rollback", "queued"], action: { command: "cancelrun", surface: "popup", session: true } },
13296
+ { id: "resumesession", label: "Resume session", keywords: ["session", "resume", "grid", "reopen"], action: { command: "resumesession", surface: "sidepanel" } },
13297
+ { id: "stepapprove", label: "Review step", keywords: ["approve", "reject", "edit", "step", "review", "plancard"], action: { command: "stepapprove", surface: "sidepanel", session: true } },
13298
+ { id: "diffpreview", label: "Preview step diff", keywords: ["diff", "preview", "before", "after", "write"], action: { command: "diffpreview", surface: "sidepanel", session: true } },
13299
+ { id: "historysearch", label: "Search history", keywords: ["history", "search", "notes", "summaries", "corpus"], action: { command: "historysearch", surface: "dashboardpage" } },
13300
+ { id: "revokeconsent", label: "Revoke consent", keywords: ["revoke", "consent", "allowlist", "origin", "grant"], action: { command: "revokeconsent", surface: "dashboardpage", session: true } },
13301
+ { id: "opentransparencypage", label: "Open transparency page", keywords: ["transparency", "grants", "permissions", "diff"], action: { command: "opentransparencypage", surface: "optionspage" } },
13302
+ { id: "opendashboardpage", label: "Open dashboard", keywords: ["dashboard", "sessions", "runs", "notes", "full"], action: { command: "opendashboardpage", surface: "dashboardpage" } },
13303
+ { id: "openoptionspage", label: "Open options", keywords: ["options", "settings", "preferences", "configure"], action: { command: "openoptionspage", surface: "optionspage" } },
13304
+ { id: "copyauditexcerpt", label: "Copy audit excerpt", keywords: ["audit", "excerpt", "copy", "verified", "range"], action: { command: "copyauditexcerpt", surface: "dashboardpage" } },
13305
+ { id: "replayonboarding", label: "Replay onboarding", keywords: ["onboarding", "tour", "walkthrough", "replay", "first"], action: { command: "replayonboarding", surface: "onboarding" } }
13306
+ ];
13307
+ }
13308
+ function palettecommandsof(entries, input) {
13309
+ return entries.filter((entry) => paletteactiongate({ action: entry.action, granted: input.granted, sessionactive: input.sessionactive }).allowed);
13310
+ }
13311
+ function fuzzyentryscore(entry, query) {
13312
+ const text2 = query.trim().toLowerCase();
13313
+ if (text2 === "") return 1;
13314
+ const id = entry.id.toLowerCase();
13315
+ const label = entry.label.toLowerCase();
13316
+ if (id === text2 || label === text2) return 100;
13317
+ let score = 0;
13318
+ if (id.includes(text2)) score += 40;
13319
+ if (label.includes(text2)) score += 30;
13320
+ for (const keyword of entry.keywords) {
13321
+ const lower = keyword.toLowerCase();
13322
+ if (lower === text2) score += 20;
13323
+ else if (lower.includes(text2)) score += 10;
13324
+ }
13325
+ if (score === 0 && text2.length > 1) {
13326
+ for (const haystack of [label, id]) {
13327
+ let cursor = 0;
13328
+ let matched = true;
13329
+ for (const letter of text2) {
13330
+ const found = haystack.indexOf(letter, cursor);
13331
+ if (found === -1) {
13332
+ matched = false;
13333
+ break;
13334
+ }
13335
+ cursor = found + 1;
13336
+ }
13337
+ if (matched) {
13338
+ score += 15;
13339
+ break;
13340
+ }
13341
+ }
13342
+ }
13343
+ return score;
13344
+ }
13345
+ function palettequery(entries, input) {
13346
+ const text2 = input.text.trim();
13347
+ const matches = entries.map((entry) => ({ entry, score: fuzzyentryscore(entry, text2) })).filter((match) => match.score > 0);
13348
+ const lastusedof = (command) => input.usage.find((record2) => record2.command === command)?.lastusedat ?? 0;
13349
+ const countof = (command) => input.usage.find((record2) => record2.command === command)?.count ?? 0;
13350
+ const recentwindow = input.recentwindow;
13351
+ const ranked = matches.sort((left, right) => {
13352
+ if (right.score !== left.score) return right.score - left.score;
13353
+ const leftrecent = recentwindow === void 0 ? 0 : countof(left.entry.action.command) > 0 && lastusedof(left.entry.action.command) >= lastusedof(right.entry.action.command) ? 1 : 0;
13354
+ const rightrecent = recentwindow === void 0 ? 0 : countof(right.entry.action.command) > 0 && lastusedof(right.entry.action.command) >= lastusedof(left.entry.action.command) ? 1 : 0;
13355
+ if (rightrecent !== leftrecent) return rightrecent - leftrecent;
13356
+ return lastusedof(right.entry.action.command) - lastusedof(left.entry.action.command);
13357
+ });
13358
+ return ranked.map((match) => ({ entry: match.entry, score: match.score, reason: match.score >= 100 ? `The query matches the ${match.entry.id} command exactly.` : `The query matches the label or the keywords of the ${match.entry.id} command${countof(match.entry.action.command) > 0 ? ` and its ${countof(match.entry.action.command)} recorded use${countof(match.entry.action.command) === 1 ? "" : "s"} rank it first among equals` : ""}.` }));
13359
+ }
13360
+ function paletteuseafter(usage, command, now) {
13361
+ const existing = usage.find((record2) => record2.command === command);
13362
+ if (existing === void 0) return [{ command, count: 1, lastusedat: now }, ...usage];
13363
+ return usage.map((record2) => record2.command === command ? { ...record2, count: record2.count + 1, lastusedat: now } : record2);
13364
+ }
13365
+ function taskinputof(input) {
13366
+ if (input.text.trim() === "") throw new Error("The taskinput needs its natural language goal.");
13367
+ if (input.origin.trim() === "") throw new Error("The taskinput needs its active origin scope.");
13368
+ return { id: randomid(), text: input.text.trim(), context: input.context ?? "", origin: input.origin.trim(), surface: input.surface, at: input.at };
13369
+ }
13370
+ function taskhistoryafter(history, entry, retention, now) {
13371
+ if (retention === void 0) return [entry, ...history];
13372
+ return [entry, ...history].filter((candidate) => now - candidate.at < retention);
13373
+ }
13374
+ function onboardingsteps() {
13375
+ return [
13376
+ { id: "origingrants", surface: "popup", title: "Origin grants", body: "Devthink denies automation by default; grant one exact origin at a time from the popup and every run stays inside the granted origins.", completion: "origingrantscompleted" },
13377
+ { id: "planreview", surface: "sidepanel", title: "Plan review", body: "Every task becomes a plan of reviewed steps; read the plancards of each risk class and approve, reject or edit one step at a time.", completion: "planreviewcompleted" },
13378
+ { id: "runcontrol", surface: "sidepanel", title: "Run control", body: "Runs start, pause, resume and cancel under your hand; a cancelled run rolls only its queued steps back while the executed steps stay sealed.", completion: "runcontrolcompleted" },
13379
+ { id: "logaudit", surface: "dashboardpage", title: "Log audit", body: "The immutable log chains every step transition with masked values; open the dashboard, verify the chain and copy a verified range as an audit excerpt.", completion: "logauditcompleted" }
13380
+ ];
13381
+ }
13382
+ function onboardingstart(previous, now) {
13383
+ return { stepscompleted: [], done: false, startedat: now };
13384
+ }
13385
+ function onboardingcomplete(state, stepid, now) {
13386
+ const steps = onboardingsteps();
13387
+ const step = steps.find((candidate) => candidate.id === stepid);
13388
+ if (step === void 0) throw new Error(`The onboarding knows no ${stepid} step.`);
13389
+ const completed = state.stepscompleted.includes(stepid) ? state.stepscompleted : [...state.stepscompleted, stepid];
13390
+ const done = steps.every((candidate) => completed.includes(candidate.id));
13391
+ if (!done) return { state: { ...state, stepscompleted: completed, done: false } };
13392
+ const consentevent = "onboardingconsentgranted";
13393
+ return { state: { stepscompleted: completed, done: true, ...state.startedat !== void 0 ? { startedat: state.startedat } : {}, consentevent, completedat: now }, consentevent };
13394
+ }
13395
+ function broadcastframeof(input) {
13396
+ if (input.summary.trim() === "") throw new Error("The broadcast frame needs its summary.");
13397
+ return { channel: input.channel, surface: input.surface, summary: input.summary, at: input.at };
13398
+ }
13399
+ function broadcastchannelof(kind) {
13400
+ if (["session", "proposal", "approval", "action", "stop", "pause", "resume", "complete", "cancel", "error", "capability"].includes(kind)) return "runstate";
13401
+ if (["notes", "scratchpad", "summary", "recall", "correction", "consentmemory", "search", "vault", "gate", "grant", "revoke", "expiry", "deny"].includes(kind)) return "sessions";
13402
+ if (["configure", "transparency"].includes(kind)) return "settings";
13403
+ return "logstream";
13404
+ }
13405
+ function busrouteaction(action, input) {
13406
+ const entry = surfacepalette().find((candidate) => candidate.action.command === action.command);
13407
+ if (entry === void 0) return { dispatched: false, gate: "commandbus", reason: `The ${action.surface} asked for the unknown ${action.command} command; the bus routes only catalog commands.` };
13408
+ const permission = paletteactiongate({ action: entry.action, granted: input.granted, sessionactive: input.sessionactive });
13409
+ if (!permission.allowed) return { dispatched: false, gate: "paletteactiongate", reason: permission.reason ?? "The command misses its granted permission." };
13410
+ if (action.command === "starttask") {
13411
+ const proposal = taskinputproposalgate({ text: input.text ?? "", origin: input.origin ?? "", direct: false });
13412
+ if (!proposal.allowed) return { dispatched: false, gate: "taskinputproposalgate", reason: proposal.reason ?? "The task submission refuses." };
13413
+ }
13414
+ if (action.command === "stepapprove" || action.command === "diffpreview") {
13415
+ const review = planreviewgate({ reviewed: input.planreviewed, state: input.planstate });
13416
+ if (!review.allowed) return { dispatched: false, gate: "planreviewgate", reason: review.reason ?? "The plan review stays open." };
13417
+ }
13418
+ return { dispatched: true, gate: "commandbus", reason: `The ${action.command} action of the ${action.surface} routed through its policy gates and dispatches.` };
13419
+ }
13420
+
13059
13421
  // taskqueue.ts
13060
13422
  function emptyqueue(input = {}) {
13061
13423
  return { lanes: input.lanes ?? [], priorities: input.priorities ?? [], completionpolicy: input.completionpolicy ?? "all", items: [], claims: [] };
@@ -14009,6 +14371,9 @@ function logchainreport(input) {
14009
14371
  function transparencyreport(input) {
14010
14372
  return { version: protocolversion, posture: "denydefault", grants: input.grants, windows: input.windows, connectallow: input.connectallow, permdiffs: input.permdiffs, safedefaults: input.safedefaults, vault: input.vault };
14011
14373
  }
14374
+ function surfacesnapshot(input) {
14375
+ return { version: protocolversion, surface: input.surface, palette: input.palette, timeline: input.timeline, logstream: input.logstream, plancards: input.plancards, ...input.onboarding !== void 0 ? { onboarding: input.onboarding } : {} };
14376
+ }
14012
14377
 
14013
14378
  // workfloweditor.ts
14014
14379
  var palettecategories = ["actions", "controlflow", "waits", "variables", "triggers"];
@@ -14720,6 +15085,7 @@ export {
14720
15085
  acquirelock,
14721
15086
  acquirerunlock,
14722
15087
  activelayers,
15088
+ activetimelineanchor,
14723
15089
  addedge,
14724
15090
  addhistoryentry,
14725
15091
  addnode,
@@ -14745,6 +15111,7 @@ export {
14745
15111
  apikeyconsentgranted,
14746
15112
  apireplayspecof,
14747
15113
  appendlogentry,
15114
+ appendlogstreamevent,
14748
15115
  applycooldown,
14749
15116
  applyheaderules,
14750
15117
  applylayer,
@@ -14764,6 +15131,7 @@ export {
14764
15131
  attachcdpsession,
14765
15132
  attachtargetof,
14766
15133
  attachtimeline,
15134
+ auditexcerptof,
14767
15135
  authconsentgranted,
14768
15136
  authorizeurl,
14769
15137
  authrefusedmessage,
@@ -14795,6 +15163,8 @@ export {
14795
15163
  breakpointbudgetallowed,
14796
15164
  breakpointceilingof,
14797
15165
  breakpointinputof,
15166
+ broadcastchannelof,
15167
+ broadcastframeof,
14798
15168
  broadcastrecipient,
14799
15169
  browserpermissions,
14800
15170
  bucketboundsvalid,
@@ -14809,6 +15179,7 @@ export {
14809
15179
  buildstitchplan,
14810
15180
  buildtoolcatalog,
14811
15181
  bumprevision,
15182
+ busrouteaction,
14812
15183
  callgraphql,
14813
15184
  calllocal,
14814
15185
  calllogreport,
@@ -14940,6 +15311,8 @@ export {
14940
15311
  actionrisk as deriveactionrisk,
14941
15312
  detachcdpsession,
14942
15313
  devicepresetof,
15314
+ diffpreviewgate,
15315
+ diffpreviewof,
14943
15316
  diffresponse,
14944
15317
  diffreviewgrade,
14945
15318
  diffsessionrecords,
@@ -15030,6 +15403,7 @@ export {
15030
15403
  filteredsessions,
15031
15404
  filterentries,
15032
15405
  filterexchanges,
15406
+ filterlogstream,
15033
15407
  finishrecording,
15034
15408
  fixedheadermatch,
15035
15409
  flowmetricnames,
@@ -15123,6 +15497,7 @@ export {
15123
15497
  listdue,
15124
15498
  listremotestatus,
15125
15499
  listtools,
15500
+ livebufferof,
15126
15501
  loadworkflow,
15127
15502
  localhostbind,
15128
15503
  localsensitivegrade,
@@ -15131,10 +15506,15 @@ export {
15131
15506
  locationpresetof,
15132
15507
  locationrangevalid,
15133
15508
  lockkey,
15509
+ logbufferboundvalid,
15134
15510
  logchainreport,
15135
15511
  logentryof,
15512
+ loglevelof,
15136
15513
  loglevels,
15137
15514
  logreadgate,
15515
+ logstreamegressgate,
15516
+ logstreameventof,
15517
+ logstreamgenesis,
15138
15518
  longtaskcapture,
15139
15519
  lookalikedistance,
15140
15520
  loopof,
@@ -15157,6 +15537,7 @@ export {
15157
15537
  maskstoredvalues,
15158
15538
  masktypedvalues,
15159
15539
  maskvalue,
15540
+ maskverdictsof,
15160
15541
  matchingcorrections,
15161
15542
  matchmessage,
15162
15543
  matchurl,
@@ -15211,6 +15592,10 @@ export {
15211
15592
  offfamilyof,
15212
15593
  offloadkinds,
15213
15594
  offscreencapabilitygate,
15595
+ onboardingcomplete,
15596
+ onboardingconsentgate,
15597
+ onboardingstart,
15598
+ onboardingsteps,
15214
15599
  openchannel,
15215
15600
  openconsensus,
15216
15601
  openconsentwindow,
@@ -15234,8 +15619,12 @@ export {
15234
15619
  pairexchange,
15235
15620
  pairingframes,
15236
15621
  pairstates,
15622
+ paletteactiongate,
15237
15623
  palettecategories,
15624
+ palettecommandsof,
15238
15625
  palettenodes,
15626
+ palettequery,
15627
+ paletteuseafter,
15239
15628
  parallelof,
15240
15629
  parsecommand,
15241
15630
  parsecompletion,
@@ -15277,9 +15666,12 @@ export {
15277
15666
  phishverdictof,
15278
15667
  ping,
15279
15668
  planallowlist,
15669
+ plancardgroups,
15670
+ plancardsof,
15280
15671
  plandraftreviewgate,
15281
15672
  planlint,
15282
15673
  plannersplit,
15674
+ planreviewgate,
15283
15675
  pollcursorof,
15284
15676
  polldecision,
15285
15677
  pollurl,
@@ -15380,6 +15772,8 @@ export {
15380
15772
  requestreview,
15381
15773
  requeue,
15382
15774
  requireapproval,
15775
+ resolutionhistoryafter,
15776
+ resolutionlogeventof,
15383
15777
  resolutionverdict,
15384
15778
  resolveapproval,
15385
15779
  resolvedrisk,
@@ -15538,8 +15932,11 @@ export {
15538
15932
  starttls,
15539
15933
  statusclassof,
15540
15934
  steal,
15935
+ stepapprovegate,
15541
15936
  stepenvironmentvalid,
15542
15937
  stepmodeof,
15938
+ stepresolutionof,
15939
+ stepstimelinenodes,
15543
15940
  steptemplateof,
15544
15941
  stepwindows,
15545
15942
  stopone,
@@ -15557,6 +15954,8 @@ export {
15557
15954
  summaryhistoryentry,
15558
15955
  summaryrequestof,
15559
15956
  summarywindowvalid,
15957
+ surfacepalette,
15958
+ surfacesnapshot,
15560
15959
  swarmcosts,
15561
15960
  swarmoverview,
15562
15961
  swarmreport,
@@ -15568,6 +15967,9 @@ export {
15568
15967
  tabsessionrefof,
15569
15968
  targetgate,
15570
15969
  taskcounts,
15970
+ taskhistoryafter,
15971
+ taskinputof,
15972
+ taskinputproposalgate,
15571
15973
  taskstatechecksum,
15572
15974
  taskstateof,
15573
15975
  taskstatevalid,
@@ -15658,6 +16060,7 @@ export {
15658
16060
  verdictfresh,
15659
16061
  verifyauth,
15660
16062
  verifylogchain,
16063
+ verifylogstream,
15661
16064
  verifytoken,
15662
16065
  verifywebhook,
15663
16066
  visitmatch,