@wenathlan/extension 1.1.63 → 1.1.65
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 +5 -3
- package/dist/datagrid.d.ts +46 -0
- package/dist/datagrid.d.ts.map +1 -0
- package/dist/evidenceviews.d.ts +45 -0
- package/dist/evidenceviews.d.ts.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1155 -1
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +65 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/pickerviews.d.ts +72 -0
- package/dist/pickerviews.d.ts.map +1 -0
- package/dist/planreview.d.ts +87 -0
- package/dist/planreview.d.ts.map +1 -0
- package/dist/policy.d.ts +105 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/portability.d.ts +35 -0
- package/dist/portability.d.ts.map +1 -0
- package/dist/protocol.d.ts +248 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/quickactions.d.ts +46 -0
- package/dist/quickactions.d.ts.map +1 -0
- package/dist/siteprefs.d.ts +45 -0
- package/dist/siteprefs.d.ts.map +1 -0
- package/dist/statusviews.d.ts +65 -0
- package/dist/statusviews.d.ts.map +1 -0
- package/dist/surfaces.d.ts +59 -0
- package/dist/surfaces.d.ts.map +1 -0
- package/dist/tourviews.d.ts +28 -0
- package/dist/tourviews.d.ts.map +1 -0
- package/dist/types.d.ts +429 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +1567 -2
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/dashboardpage.html +14 -0
- package/extension/dist/dashboardpage.js +147 -0
- package/extension/dist/dashboardpage.js.map +7 -0
- package/extension/dist/manifest.json +5 -2
- package/extension/dist/offscreen.js +1 -0
- package/extension/dist/offscreen.js.map +2 -2
- package/extension/dist/optionspage.html +18 -0
- package/extension/dist/optionspage.js +267 -0
- package/extension/dist/optionspage.js.map +7 -0
- package/extension/dist/pagebridge.js.map +1 -1
- package/extension/dist/popup.html +4 -1
- package/extension/dist/popup.js +257 -0
- package/extension/dist/popup.js.map +3 -3
- package/extension/dist/sidepanel.html +7 -2
- package/extension/dist/sidepanel.js +360 -0
- package/extension/dist/sidepanel.js.map +2 -2
- package/extension/dist/style.css +3 -1
- package/extension/manifest.json +5 -2
- package/package.json +1 -1
|
@@ -5106,6 +5106,121 @@ var sessionmemory = class {
|
|
|
5106
5106
|
async exportsessionbundle(exportedat) {
|
|
5107
5107
|
return { kind: "sessionbundle", notes: await this.getsitenotes(), summaries: await this.listrunsummaries(), corrections: await this.getcorrections(), exportedat };
|
|
5108
5108
|
}
|
|
5109
|
+
/**
|
|
5110
|
+
* 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.
|
|
5111
|
+
*/
|
|
5112
|
+
/** Returns every commandpalette usage record so the ranking lifts the recent commands first. */
|
|
5113
|
+
async getpaletteusage() {
|
|
5114
|
+
return await this.adapter.get("paletteusage") ?? [];
|
|
5115
|
+
}
|
|
5116
|
+
/** Replaces the commandpalette usage records after one use: the count grows and the last use time moves so the ranking reads both. */
|
|
5117
|
+
async setpaletteusage(records) {
|
|
5118
|
+
return this.adapter.set("paletteusage", records);
|
|
5119
|
+
}
|
|
5120
|
+
/** Returns the stored taskinput history, newest first. */
|
|
5121
|
+
async gettaskinputs() {
|
|
5122
|
+
return await this.adapter.get("taskinputs") ?? [];
|
|
5123
|
+
}
|
|
5124
|
+
/** Adds one taskinput submission to the per profile history; the retention window stays a user setting. */
|
|
5125
|
+
async addtaskinput(entry) {
|
|
5126
|
+
const retention = (await this.getsettings())?.taskinputretention;
|
|
5127
|
+
const history2 = [entry, ...await this.gettaskinputs()];
|
|
5128
|
+
await this.adapter.set("taskinputs", retention === void 0 ? history2 : history2.filter((candidate) => entry.at - candidate.at < retention));
|
|
5129
|
+
}
|
|
5130
|
+
/** Returns the onboarding completion state; an absent state means the walkthrough never ran. */
|
|
5131
|
+
async getonboardingstate() {
|
|
5132
|
+
return this.adapter.get("onboarding");
|
|
5133
|
+
}
|
|
5134
|
+
/** Stores the onboarding completion state; a done walkthrough never runs again on its own. */
|
|
5135
|
+
async setonboardingstate(state) {
|
|
5136
|
+
return this.adapter.set("onboarding", state);
|
|
5137
|
+
}
|
|
5138
|
+
/** Returns the layout preferences of one surface; an absent preference set returns undefined. */
|
|
5139
|
+
async getsurfacelayout(surface) {
|
|
5140
|
+
return this.adapter.get(`surfacelayout:${surface}`);
|
|
5141
|
+
}
|
|
5142
|
+
/** Stores the layout preferences of one surface, scoped per profile workspace. */
|
|
5143
|
+
async setsurfacelayout(layout) {
|
|
5144
|
+
return this.adapter.set(`surfacelayout:${layout.surface}`, layout);
|
|
5145
|
+
}
|
|
5146
|
+
/** Returns the stored logstream filter preferences of the live view. */
|
|
5147
|
+
async getlogstreamfilters() {
|
|
5148
|
+
return this.adapter.get("logstreamfilters");
|
|
5149
|
+
}
|
|
5150
|
+
/** Stores the logstream filter preferences of the live view. */
|
|
5151
|
+
async setlogstreamfilters(filter) {
|
|
5152
|
+
return this.adapter.set("logstreamfilters", filter);
|
|
5153
|
+
}
|
|
5154
|
+
/** Returns every stored stepapprove resolution, newest first, with its human provenance. */
|
|
5155
|
+
async getstepapproveresolutions() {
|
|
5156
|
+
return await this.adapter.get("stepapproveresolutions") ?? [];
|
|
5157
|
+
}
|
|
5158
|
+
/** Records one stepapprove resolution in the per origin history. */
|
|
5159
|
+
async addstepapproveresolution(resolution) {
|
|
5160
|
+
await this.adapter.set("stepapproveresolutions", [resolution, ...await this.getstepapproveresolutions()]);
|
|
5161
|
+
}
|
|
5162
|
+
/**
|
|
5163
|
+
* Interface surface stores of the 1.1.65 family live here, scoped per profile workspace: the siteprofiles with the per site interface preferences, the shortcutkeys bindings and the theme preference per profile, the recenttray entries with their configurable depth and the notification consent and preference per profile.
|
|
5164
|
+
*/
|
|
5165
|
+
/** Returns the siteprofile of one origin; an absent profile keeps the global interface preferences. */
|
|
5166
|
+
async getsiteprofile(origin) {
|
|
5167
|
+
return this.adapter.get(`siteprofile:${origin}`);
|
|
5168
|
+
}
|
|
5169
|
+
/** Stores the siteprofile of one origin with its theme, shortcutkeys and default view; the profile never adjusts a policy gate. */
|
|
5170
|
+
async setsiteprofile(profile) {
|
|
5171
|
+
return this.adapter.set(`siteprofile:${profile.origin}`, profile);
|
|
5172
|
+
}
|
|
5173
|
+
/** Returns every stored siteprofile keyed by origin. */
|
|
5174
|
+
async listsiteprofiles() {
|
|
5175
|
+
const entries = Object.entries(await this.adapter.get("siteprofiles") ?? {});
|
|
5176
|
+
return entries.map(([, profile]) => profile);
|
|
5177
|
+
}
|
|
5178
|
+
/** Stores every siteprofile keyed by origin so the list view reads them in one call. */
|
|
5179
|
+
async setsiteprofiles(profiles) {
|
|
5180
|
+
await this.adapter.set("siteprofiles", Object.fromEntries(profiles.map((profile) => [profile.origin, profile])));
|
|
5181
|
+
}
|
|
5182
|
+
/** Returns the stored shortcutkeys bindings of the profile; an absent set keeps the shipped editable defaults. */
|
|
5183
|
+
async getshortcutbindings() {
|
|
5184
|
+
return await this.adapter.get("shortcutbindings") ?? [];
|
|
5185
|
+
}
|
|
5186
|
+
/** Stores the shortcutkeys bindings the user edited in the optionspage. */
|
|
5187
|
+
async setshortcutbindings(bindings) {
|
|
5188
|
+
return this.adapter.set("shortcutbindings", bindings);
|
|
5189
|
+
}
|
|
5190
|
+
/** Returns the stored darklight theme preference of the profile; an absent preference follows the os preference alone. */
|
|
5191
|
+
async getthemepreference() {
|
|
5192
|
+
return this.adapter.get("themepreference");
|
|
5193
|
+
}
|
|
5194
|
+
/** Stores the darklight theme preference of the profile with its manual override. */
|
|
5195
|
+
async setthemepreference(preference) {
|
|
5196
|
+
return this.adapter.set("themepreference", preference);
|
|
5197
|
+
}
|
|
5198
|
+
/** Returns the recenttray entries, newest first, with their resume and reopen offers. */
|
|
5199
|
+
async getrecenttray() {
|
|
5200
|
+
return await this.adapter.get("recenttray") ?? [];
|
|
5201
|
+
}
|
|
5202
|
+
/** Adds one recenttray entry with the user configured depth; an absent depth keeps every run. */
|
|
5203
|
+
async addrecenttrayentry(entry) {
|
|
5204
|
+
const depth = (await this.getsettings())?.recenttraydepth;
|
|
5205
|
+
const appended = [entry, ...(await this.getrecenttray()).filter((candidate) => candidate.runid !== entry.runid)];
|
|
5206
|
+
await this.adapter.set("recenttray", depth !== void 0 && Number.isInteger(depth) && depth > 0 ? appended.slice(0, depth) : appended);
|
|
5207
|
+
}
|
|
5208
|
+
/** Returns the notification consent and preference of the profile; an absent record keeps the notifications content free and on. */
|
|
5209
|
+
async getnotificationprefs() {
|
|
5210
|
+
return this.adapter.get("notificationprefs");
|
|
5211
|
+
}
|
|
5212
|
+
/** Stores the notification consent and preference of the profile; the content consent gates every page content bearing body. */
|
|
5213
|
+
async setnotificationprefs(prefs) {
|
|
5214
|
+
return this.adapter.set("notificationprefs", prefs);
|
|
5215
|
+
}
|
|
5216
|
+
/** Returns the notification payloads the surface history keeps for the user to open after a do not disturb quiet. */
|
|
5217
|
+
async getnotificationhistory() {
|
|
5218
|
+
return await this.adapter.get("notificationhistory") ?? [];
|
|
5219
|
+
}
|
|
5220
|
+
/** Records one notification payload in the history so its deep link stays reachable while the notifications permission stays outside the manifest. */
|
|
5221
|
+
async addnotificationhistory(payload) {
|
|
5222
|
+
await this.adapter.set("notificationhistory", [payload, ...await this.getnotificationhistory()]);
|
|
5223
|
+
}
|
|
5109
5224
|
};
|
|
5110
5225
|
function mediakindof(record2) {
|
|
5111
5226
|
if ("pages" in record2) return "pdf";
|
|
@@ -10617,6 +10732,87 @@ function retrydispatchgate(input) {
|
|
|
10617
10732
|
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.` };
|
|
10618
10733
|
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.` };
|
|
10619
10734
|
}
|
|
10735
|
+
function paletteactiongate(input) {
|
|
10736
|
+
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.` };
|
|
10737
|
+
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.` };
|
|
10738
|
+
return { allowed: true, reason: `The ${input.action.command} command rides its granted permissions and lists in the palette.` };
|
|
10739
|
+
}
|
|
10740
|
+
function taskinputproposalgate(input) {
|
|
10741
|
+
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." };
|
|
10742
|
+
if (input.text.trim() === "") return { allowed: false, reason: "The taskinput submission needs its natural language goal; an empty goal never reaches the proposal flow." };
|
|
10743
|
+
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." };
|
|
10744
|
+
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.` };
|
|
10745
|
+
}
|
|
10746
|
+
function planreviewgate(input) {
|
|
10747
|
+
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." };
|
|
10748
|
+
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." };
|
|
10749
|
+
return { allowed: true, reason: "The plancard review of the pending plan is open; the resolution of each step stays a distinct human action." };
|
|
10750
|
+
}
|
|
10751
|
+
function stepapprovegate(input) {
|
|
10752
|
+
if (input.stepids.length === 0) return { allowed: false, reason: "A stepapprove resolution names its single step." };
|
|
10753
|
+
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.` };
|
|
10754
|
+
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.` };
|
|
10755
|
+
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.` };
|
|
10756
|
+
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.` };
|
|
10757
|
+
}
|
|
10758
|
+
function diffpreviewgate(input) {
|
|
10759
|
+
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.` };
|
|
10760
|
+
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." };
|
|
10761
|
+
}
|
|
10762
|
+
function onboardingconsentgate(input) {
|
|
10763
|
+
if (input.consentevents.length === 0) return { allowed: true, reason: "The onboarding completion writes its single consent scoped event; no consent event exists yet." };
|
|
10764
|
+
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.` };
|
|
10765
|
+
return { allowed: false, reason: `The onboarding found ${input.consentevents.length} consent scoped events; a walkthrough writes exactly one and the extra events refuse.` };
|
|
10766
|
+
}
|
|
10767
|
+
function logbufferboundvalid(bound) {
|
|
10768
|
+
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." };
|
|
10769
|
+
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." };
|
|
10770
|
+
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.` };
|
|
10771
|
+
}
|
|
10772
|
+
function logstreamegressgate(input) {
|
|
10773
|
+
if (input.entries === 0) return { allowed: false, reason: "The audit excerpt names no event of the logstream; an empty range never copies." };
|
|
10774
|
+
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." };
|
|
10775
|
+
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.` };
|
|
10776
|
+
}
|
|
10777
|
+
function quickactiongate(input) {
|
|
10778
|
+
if (input.action.origin.trim() === "") return { allowed: false, reason: `The ${input.action.command} quickaction needs the origin of the clicked tab; an originless entry never registers.` };
|
|
10779
|
+
if (!input.granted.includes(input.action.origin)) return { allowed: false, reason: `The ${input.action.command} quickaction stays off the ${input.action.origin} tab because its origin holds no allowlist entry; only permitted actions surface.` };
|
|
10780
|
+
if (input.action.session === true && !input.sessionactive) return { allowed: false, reason: `The ${input.action.command} quickaction needs an active browser session before it registers; the context menu never offers a run action without its session.` };
|
|
10781
|
+
if (input.action.permission !== void 0 && !(input.capabilities ?? []).includes(input.action.permission)) return { allowed: false, reason: `The ${input.action.command} quickaction needs the ${input.action.permission} capability granted before it registers; the context menu never offers an action the current capability set refuses.` };
|
|
10782
|
+
return { allowed: true, reason: `The ${input.action.command} quickaction rides the origin allowlist of the clicked ${input.action.origin} tab and registers.` };
|
|
10783
|
+
}
|
|
10784
|
+
function omniboxtaskgate(input) {
|
|
10785
|
+
if (input.direct) return { allowed: false, reason: "The omnibox keyword never executes a goal directly; every keyword goal routes through the same proposal and review flow as the api and becomes a reviewed plan first." };
|
|
10786
|
+
if (input.text.trim() === "") return { allowed: false, reason: "The omnibox task needs its natural language goal after the keyword; an empty goal never reaches the proposal flow." };
|
|
10787
|
+
if (input.origin.trim() === "") return { allowed: false, reason: "The omnibox task needs its active origin scope; a goal without an origin never reaches the proposal flow." };
|
|
10788
|
+
return { allowed: true, reason: `The omnibox goal for ${input.origin} rides the same proposal flow as the api: the observation, the capabilities and the plan review all recheck it.` };
|
|
10789
|
+
}
|
|
10790
|
+
function notificationcontentgate(input) {
|
|
10791
|
+
if (!input.content) return { allowed: true, reason: "The notification body carries no page content, so no content consent is needed and it shows." };
|
|
10792
|
+
if (!input.consent) return { allowed: false, reason: "The notification body carries page content and no content consent exists; a content bearing notification never shows without its consent." };
|
|
10793
|
+
return { allowed: true, reason: "The notification body carries page content and its consent exists, so it shows with the content the user agreed to." };
|
|
10794
|
+
}
|
|
10795
|
+
function pickeroverlaygate(input) {
|
|
10796
|
+
if (input.origin.trim() === "") return { allowed: false, reason: "The pickeroverlay session needs its origin; an originless read never starts." };
|
|
10797
|
+
if (!input.granted.includes(input.origin)) return { allowed: false, reason: `The pickeroverlay reads no element candidate of ${input.origin} because the origin holds no allowlist entry; picker reads stay inside the granted origins.` };
|
|
10798
|
+
return { allowed: true, reason: `The pickeroverlay lists the element candidates of the granted origin ${input.origin} with their stability scored selectors.` };
|
|
10799
|
+
}
|
|
10800
|
+
function shotpanelgate(input) {
|
|
10801
|
+
if (input.captureorigin.trim() === "") return { allowed: false, reason: "The shotpanel view needs the origin of its capture; an originless capture never opens." };
|
|
10802
|
+
if (!input.granted.includes(input.captureorigin)) return { allowed: false, reason: `The shotpanel opens no capture of ${input.captureorigin} because the origin holds no allowlist entry; capture views stay inside the granted origins.` };
|
|
10803
|
+
return { allowed: true, reason: `The shotpanel previews the capture of the granted origin ${input.captureorigin} with its redaction verdicts.` };
|
|
10804
|
+
}
|
|
10805
|
+
function siteprofilegate(input) {
|
|
10806
|
+
const origin = input.origin.trim();
|
|
10807
|
+
if (origin === "") return { allowed: false, reason: "The siteprofile needs its origin; an originless profile never stores." };
|
|
10808
|
+
if (!origin.startsWith("https://") || origin.length <= "https://".length) return { allowed: false, reason: `The siteprofile stores per site interface preferences of https origins only; ${origin} holds no https origin shape.` };
|
|
10809
|
+
return { allowed: true, reason: `The siteprofile of ${origin} stores its theme, shortcutkeys and default view beside the originprofiles policy preferences; no profile ever adjusts a policy gate.` };
|
|
10810
|
+
}
|
|
10811
|
+
function importexportgate(input) {
|
|
10812
|
+
if (input.containssecrets) return { allowed: false, reason: "The importexport bundle carries a secretvault value shape; secret values never leave the browser under any flag, so the bundle refuses in full." };
|
|
10813
|
+
if (input.unmaskedlogs) return { allowed: false, reason: "The importexport bundle carries unmasked log entries; only masked summaries ever move between profiles, so the bundle refuses in full." };
|
|
10814
|
+
return { allowed: true, reason: "The importexport bundle carries no secretvault value and no unmasked log; the originprofiles, the siteprofiles, the notes and the preferences move with their honest exclusion list." };
|
|
10815
|
+
}
|
|
10620
10816
|
|
|
10621
10817
|
// progress.ts
|
|
10622
10818
|
function emptyprogress(planid, now) {
|
|
@@ -10867,7 +11063,7 @@ function maskexport(record2, shapes) {
|
|
|
10867
11063
|
}
|
|
10868
11064
|
|
|
10869
11065
|
// version.ts
|
|
10870
|
-
var packageversion = "1.1.
|
|
11066
|
+
var packageversion = "1.1.65";
|
|
10871
11067
|
|
|
10872
11068
|
// types.ts
|
|
10873
11069
|
var protocolversion = packageversion;
|
|
@@ -11844,6 +12040,9 @@ function environmentreport(input) {
|
|
|
11844
12040
|
function transparencyreport(input) {
|
|
11845
12041
|
return { version: protocolversion, posture: "denydefault", grants: input.grants, windows: input.windows, connectallow: input.connectallow, permdiffs: input.permdiffs, safedefaults: input.safedefaults, vault: input.vault };
|
|
11846
12042
|
}
|
|
12043
|
+
function surfacesnapshot(input) {
|
|
12044
|
+
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 } : {} };
|
|
12045
|
+
}
|
|
11847
12046
|
|
|
11848
12047
|
// capture.ts
|
|
11849
12048
|
var capturekinds = ["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"];
|
|
@@ -13091,6 +13290,9 @@ function rejectedcorrectionof(input) {
|
|
|
13091
13290
|
if (input.stepid.trim() === "" || input.reason.trim() === "") throw new Error("The rejected correction needs its step and its rejection reason.");
|
|
13092
13291
|
return { id: input.id ?? randomid(), origin: input.origin, kind: input.kind, stepid: input.stepid, source: "rejected", original: input.original, reason: input.reason, at: input.now };
|
|
13093
13292
|
}
|
|
13293
|
+
function matchingcorrections(corrections, proposal) {
|
|
13294
|
+
return corrections.filter((entry) => entry.origin === proposal.origin && entry.kind === proposal.kind);
|
|
13295
|
+
}
|
|
13094
13296
|
function consentmemoryof(input) {
|
|
13095
13297
|
if (input.origin.trim() === "") throw new Error("The consent memory entry needs its origin.");
|
|
13096
13298
|
if (input.boundary.trim() === "") throw new Error("The consent memory entry needs the boundary the prompt named.");
|
|
@@ -13180,6 +13382,726 @@ function tabsessionrefof(input) {
|
|
|
13180
13382
|
return { tabid: input.tabid, sessionid: input.sessionid, ...input.runid !== void 0 && input.runid.trim() !== "" ? { runid: input.runid } : {}, origin: input.origin, updatedat: input.now };
|
|
13181
13383
|
}
|
|
13182
13384
|
|
|
13385
|
+
// surfaces.ts
|
|
13386
|
+
function surfacepalette() {
|
|
13387
|
+
return [
|
|
13388
|
+
{ id: "starttask", label: "Start task", keywords: ["task", "objective", "run", "goal", "plan"], action: { command: "starttask", surface: "popup" } },
|
|
13389
|
+
{ id: "pauserun", label: "Pause run", keywords: ["pause", "hold", "stop", "run"], action: { command: "pauserun", surface: "popup", session: true } },
|
|
13390
|
+
{ id: "resumerun", label: "Resume run", keywords: ["resume", "continue", "unpause", "run"], action: { command: "resumerun", surface: "popup", session: true } },
|
|
13391
|
+
{ id: "cancelrun", label: "Cancel run", keywords: ["cancel", "stop", "rollback", "queued"], action: { command: "cancelrun", surface: "popup", session: true } },
|
|
13392
|
+
{ id: "resumesession", label: "Resume session", keywords: ["session", "resume", "grid", "reopen"], action: { command: "resumesession", surface: "sidepanel" } },
|
|
13393
|
+
{ id: "stepapprove", label: "Review step", keywords: ["approve", "reject", "edit", "step", "review", "plancard"], action: { command: "stepapprove", surface: "sidepanel", session: true } },
|
|
13394
|
+
{ id: "diffpreview", label: "Preview step diff", keywords: ["diff", "preview", "before", "after", "write"], action: { command: "diffpreview", surface: "sidepanel", session: true } },
|
|
13395
|
+
{ id: "historysearch", label: "Search history", keywords: ["history", "search", "notes", "summaries", "corpus"], action: { command: "historysearch", surface: "dashboardpage" } },
|
|
13396
|
+
{ id: "revokeconsent", label: "Revoke consent", keywords: ["revoke", "consent", "allowlist", "origin", "grant"], action: { command: "revokeconsent", surface: "dashboardpage", session: true } },
|
|
13397
|
+
{ id: "opentransparencypage", label: "Open transparency page", keywords: ["transparency", "grants", "permissions", "diff"], action: { command: "opentransparencypage", surface: "optionspage" } },
|
|
13398
|
+
{ id: "opendashboardpage", label: "Open dashboard", keywords: ["dashboard", "sessions", "runs", "notes", "full"], action: { command: "opendashboardpage", surface: "dashboardpage" } },
|
|
13399
|
+
{ id: "openoptionspage", label: "Open options", keywords: ["options", "settings", "preferences", "configure"], action: { command: "openoptionspage", surface: "optionspage" } },
|
|
13400
|
+
{ id: "copyauditexcerpt", label: "Copy audit excerpt", keywords: ["audit", "excerpt", "copy", "verified", "range"], action: { command: "copyauditexcerpt", surface: "dashboardpage" } },
|
|
13401
|
+
{ id: "replayonboarding", label: "Replay onboarding", keywords: ["onboarding", "tour", "walkthrough", "replay", "first"], action: { command: "replayonboarding", surface: "onboarding" } }
|
|
13402
|
+
];
|
|
13403
|
+
}
|
|
13404
|
+
function palettecommandsof(entries, input) {
|
|
13405
|
+
return entries.filter((entry) => paletteactiongate({ action: entry.action, granted: input.granted, sessionactive: input.sessionactive }).allowed);
|
|
13406
|
+
}
|
|
13407
|
+
function fuzzyentryscore(entry, query) {
|
|
13408
|
+
const text2 = query.trim().toLowerCase();
|
|
13409
|
+
if (text2 === "") return 1;
|
|
13410
|
+
const id = entry.id.toLowerCase();
|
|
13411
|
+
const label = entry.label.toLowerCase();
|
|
13412
|
+
if (id === text2 || label === text2) return 100;
|
|
13413
|
+
let score = 0;
|
|
13414
|
+
if (id.includes(text2)) score += 40;
|
|
13415
|
+
if (label.includes(text2)) score += 30;
|
|
13416
|
+
for (const keyword of entry.keywords) {
|
|
13417
|
+
const lower = keyword.toLowerCase();
|
|
13418
|
+
if (lower === text2) score += 20;
|
|
13419
|
+
else if (lower.includes(text2)) score += 10;
|
|
13420
|
+
}
|
|
13421
|
+
if (score === 0 && text2.length > 1) {
|
|
13422
|
+
for (const haystack of [label, id]) {
|
|
13423
|
+
let cursor = 0;
|
|
13424
|
+
let matched = true;
|
|
13425
|
+
for (const letter of text2) {
|
|
13426
|
+
const found = haystack.indexOf(letter, cursor);
|
|
13427
|
+
if (found === -1) {
|
|
13428
|
+
matched = false;
|
|
13429
|
+
break;
|
|
13430
|
+
}
|
|
13431
|
+
cursor = found + 1;
|
|
13432
|
+
}
|
|
13433
|
+
if (matched) {
|
|
13434
|
+
score += 15;
|
|
13435
|
+
break;
|
|
13436
|
+
}
|
|
13437
|
+
}
|
|
13438
|
+
}
|
|
13439
|
+
return score;
|
|
13440
|
+
}
|
|
13441
|
+
function palettequery(entries, input) {
|
|
13442
|
+
const text2 = input.text.trim();
|
|
13443
|
+
const matches = entries.map((entry) => ({ entry, score: fuzzyentryscore(entry, text2) })).filter((match) => match.score > 0);
|
|
13444
|
+
const lastusedof = (command) => input.usage.find((record2) => record2.command === command)?.lastusedat ?? 0;
|
|
13445
|
+
const countof = (command) => input.usage.find((record2) => record2.command === command)?.count ?? 0;
|
|
13446
|
+
const recentwindow = input.recentwindow;
|
|
13447
|
+
const ranked = matches.sort((left, right) => {
|
|
13448
|
+
if (right.score !== left.score) return right.score - left.score;
|
|
13449
|
+
const leftrecent = recentwindow === void 0 ? 0 : countof(left.entry.action.command) > 0 && lastusedof(left.entry.action.command) >= lastusedof(right.entry.action.command) ? 1 : 0;
|
|
13450
|
+
const rightrecent = recentwindow === void 0 ? 0 : countof(right.entry.action.command) > 0 && lastusedof(right.entry.action.command) >= lastusedof(left.entry.action.command) ? 1 : 0;
|
|
13451
|
+
if (rightrecent !== leftrecent) return rightrecent - leftrecent;
|
|
13452
|
+
return lastusedof(right.entry.action.command) - lastusedof(left.entry.action.command);
|
|
13453
|
+
});
|
|
13454
|
+
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` : ""}.` }));
|
|
13455
|
+
}
|
|
13456
|
+
function paletteuseafter(usage, command, now) {
|
|
13457
|
+
const existing = usage.find((record2) => record2.command === command);
|
|
13458
|
+
if (existing === void 0) return [{ command, count: 1, lastusedat: now }, ...usage];
|
|
13459
|
+
return usage.map((record2) => record2.command === command ? { ...record2, count: record2.count + 1, lastusedat: now } : record2);
|
|
13460
|
+
}
|
|
13461
|
+
function taskinputof(input) {
|
|
13462
|
+
if (input.text.trim() === "") throw new Error("The taskinput needs its natural language goal.");
|
|
13463
|
+
if (input.origin.trim() === "") throw new Error("The taskinput needs its active origin scope.");
|
|
13464
|
+
return { id: randomid(), text: input.text.trim(), context: input.context ?? "", origin: input.origin.trim(), surface: input.surface, at: input.at };
|
|
13465
|
+
}
|
|
13466
|
+
function onboardingsteps() {
|
|
13467
|
+
return [
|
|
13468
|
+
{ 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" },
|
|
13469
|
+
{ 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" },
|
|
13470
|
+
{ 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" },
|
|
13471
|
+
{ 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" }
|
|
13472
|
+
];
|
|
13473
|
+
}
|
|
13474
|
+
function onboardingstart(previous, now) {
|
|
13475
|
+
return { stepscompleted: [], done: false, startedat: now };
|
|
13476
|
+
}
|
|
13477
|
+
function onboardingcomplete(state, stepid, now) {
|
|
13478
|
+
const steps = onboardingsteps();
|
|
13479
|
+
const step = steps.find((candidate) => candidate.id === stepid);
|
|
13480
|
+
if (step === void 0) throw new Error(`The onboarding knows no ${stepid} step.`);
|
|
13481
|
+
const completed = state.stepscompleted.includes(stepid) ? state.stepscompleted : [...state.stepscompleted, stepid];
|
|
13482
|
+
const done = steps.every((candidate) => completed.includes(candidate.id));
|
|
13483
|
+
if (!done) return { state: { ...state, stepscompleted: completed, done: false } };
|
|
13484
|
+
const consentevent = "onboardingconsentgranted";
|
|
13485
|
+
return { state: { stepscompleted: completed, done: true, ...state.startedat !== void 0 ? { startedat: state.startedat } : {}, consentevent, completedat: now }, consentevent };
|
|
13486
|
+
}
|
|
13487
|
+
function broadcastframeof(input) {
|
|
13488
|
+
if (input.summary.trim() === "") throw new Error("The broadcast frame needs its summary.");
|
|
13489
|
+
return { channel: input.channel, surface: input.surface, summary: input.summary, at: input.at };
|
|
13490
|
+
}
|
|
13491
|
+
function broadcastchannelof(kind) {
|
|
13492
|
+
if (["session", "proposal", "approval", "action", "stop", "pause", "resume", "complete", "cancel", "error", "capability"].includes(kind)) return "runstate";
|
|
13493
|
+
if (["notes", "scratchpad", "summary", "recall", "correction", "consentmemory", "search", "vault", "gate", "grant", "revoke", "expiry", "deny"].includes(kind)) return "sessions";
|
|
13494
|
+
if (["configure", "transparency"].includes(kind)) return "settings";
|
|
13495
|
+
return "logstream";
|
|
13496
|
+
}
|
|
13497
|
+
function busrouteaction(action, input) {
|
|
13498
|
+
const entry = surfacepalette().find((candidate) => candidate.action.command === action.command);
|
|
13499
|
+
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.` };
|
|
13500
|
+
const permission = paletteactiongate({ action: entry.action, granted: input.granted, sessionactive: input.sessionactive });
|
|
13501
|
+
if (!permission.allowed) return { dispatched: false, gate: "paletteactiongate", reason: permission.reason ?? "The command misses its granted permission." };
|
|
13502
|
+
if (action.command === "starttask") {
|
|
13503
|
+
const proposal = taskinputproposalgate({ text: input.text ?? "", origin: input.origin ?? "", direct: false });
|
|
13504
|
+
if (!proposal.allowed) return { dispatched: false, gate: "taskinputproposalgate", reason: proposal.reason ?? "The task submission refuses." };
|
|
13505
|
+
}
|
|
13506
|
+
if (action.command === "stepapprove" || action.command === "diffpreview") {
|
|
13507
|
+
const review = planreviewgate({ reviewed: input.planreviewed, state: input.planstate });
|
|
13508
|
+
if (!review.allowed) return { dispatched: false, gate: "planreviewgate", reason: review.reason ?? "The plan review stays open." };
|
|
13509
|
+
}
|
|
13510
|
+
return { dispatched: true, gate: "commandbus", reason: `The ${action.command} action of the ${action.surface} routed through its policy gates and dispatches.` };
|
|
13511
|
+
}
|
|
13512
|
+
|
|
13513
|
+
// planreview.ts
|
|
13514
|
+
function plancardsof(input) {
|
|
13515
|
+
return input.plan.steps.map((step) => ({
|
|
13516
|
+
stepid: step.id,
|
|
13517
|
+
kind: step.kind,
|
|
13518
|
+
risk: step.risk,
|
|
13519
|
+
environment: step.environment ?? defaultenvironment(step),
|
|
13520
|
+
options: step.options ?? "",
|
|
13521
|
+
summary: step.summary,
|
|
13522
|
+
corrections: matchingcorrections(input.corrections, { origin: input.plan.origin, kind: step.kind }).map((entry) => ({ id: entry.id, source: entry.source, reason: entry.reason })),
|
|
13523
|
+
editable: input.plan.state === "pending"
|
|
13524
|
+
}));
|
|
13525
|
+
}
|
|
13526
|
+
function plancardgroups(cards) {
|
|
13527
|
+
const order = ["sensitive", "interaction", "read"];
|
|
13528
|
+
return order.map((risk) => ({ risk, cards: cards.filter((card) => card.risk === risk), expanded: risk === "sensitive" })).filter((group) => group.cards.length > 0);
|
|
13529
|
+
}
|
|
13530
|
+
function stepresolutionof(input) {
|
|
13531
|
+
if (input.stepid.trim() === "") throw new Error("The stepapprove resolution needs its step.");
|
|
13532
|
+
if (input.resolution === "edit" && (input.edited ?? "").trim() === "") throw new Error("The edited resolution needs its corrected step shape.");
|
|
13533
|
+
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 };
|
|
13534
|
+
}
|
|
13535
|
+
function resolutionlogeventof(resolution) {
|
|
13536
|
+
return {
|
|
13537
|
+
kind: "review",
|
|
13538
|
+
stepid: resolution.stepid,
|
|
13539
|
+
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.`
|
|
13540
|
+
};
|
|
13541
|
+
}
|
|
13542
|
+
function maskverdictsof(state, sensitivefields) {
|
|
13543
|
+
const verdicts = {};
|
|
13544
|
+
for (const [field, value] of Object.entries(state)) {
|
|
13545
|
+
if (sensitivefields.includes(field)) verdicts[field] = `The ${field} value stays masked (${value.length} characters) and never renders in the clear.`;
|
|
13546
|
+
}
|
|
13547
|
+
return verdicts;
|
|
13548
|
+
}
|
|
13549
|
+
function diffpreviewof(input) {
|
|
13550
|
+
const changes = [];
|
|
13551
|
+
const fields = [.../* @__PURE__ */ new Set([...Object.keys(input.before), ...Object.keys(input.after)])];
|
|
13552
|
+
for (const field of fields) {
|
|
13553
|
+
const hasbefore = Object.prototype.hasOwnProperty.call(input.before, field);
|
|
13554
|
+
const hasafter = Object.prototype.hasOwnProperty.call(input.after, field);
|
|
13555
|
+
const beforevalue = input.before[field];
|
|
13556
|
+
const aftervalue = input.after[field];
|
|
13557
|
+
if (hasbefore && !hasafter && beforevalue !== void 0) changes.push({ field, kind: "removed", before: beforevalue });
|
|
13558
|
+
else if (!hasbefore && hasafter && aftervalue !== void 0) changes.push({ field, kind: "added", after: aftervalue });
|
|
13559
|
+
else if (hasbefore && hasafter && beforevalue !== void 0 && aftervalue !== void 0 && beforevalue !== aftervalue) changes.push({ field, kind: "changed", before: beforevalue, after: aftervalue });
|
|
13560
|
+
}
|
|
13561
|
+
return { stepid: input.stepid, before: input.before, after: input.after, changes, maskverdicts: input.maskverdicts ?? {}, provenance: input.provenance };
|
|
13562
|
+
}
|
|
13563
|
+
function stepstimelinenodes(input) {
|
|
13564
|
+
const completed = input.progress?.completedsteps ?? [];
|
|
13565
|
+
const outcomes = input.progress?.outcomes ?? [];
|
|
13566
|
+
const environments = input.progress?.environments;
|
|
13567
|
+
const turnarounds = input.progress?.turnarounds;
|
|
13568
|
+
const gatewaits = input.progress?.gatewaits;
|
|
13569
|
+
let activeset = false;
|
|
13570
|
+
let blocked = false;
|
|
13571
|
+
return input.plan.steps.map((step) => {
|
|
13572
|
+
const outcome = [...outcomes].reverse().find((candidate) => candidate.stepid === step.id);
|
|
13573
|
+
const gatewait = gatewaits?.[step.id];
|
|
13574
|
+
let status;
|
|
13575
|
+
if (outcome !== void 0) status = outcome.ok ? "done" : "failed";
|
|
13576
|
+
else if (gatewait !== void 0) status = "waiting";
|
|
13577
|
+
else if (completed.includes(step.id)) status = "done";
|
|
13578
|
+
else if (input.plan.state === "cancelled" || input.plan.state === "expired") status = "halted";
|
|
13579
|
+
else if (input.plan.state === "rejected") status = "halted";
|
|
13580
|
+
else if (input.plan.state === "approved" && !activeset && !blocked) {
|
|
13581
|
+
status = "running";
|
|
13582
|
+
activeset = true;
|
|
13583
|
+
} else status = "pending";
|
|
13584
|
+
if (status === "waiting") blocked = true;
|
|
13585
|
+
const active = status === "running";
|
|
13586
|
+
return {
|
|
13587
|
+
stepid: step.id,
|
|
13588
|
+
kind: step.kind,
|
|
13589
|
+
status,
|
|
13590
|
+
...turnarounds?.[step.id] !== void 0 ? { durationms: turnarounds[step.id] } : {},
|
|
13591
|
+
...environments?.[step.id] !== void 0 ? { environment: environments[step.id] } : step.environment !== void 0 ? { environment: step.environment } : {},
|
|
13592
|
+
active,
|
|
13593
|
+
anchor: `#step-${step.id}`,
|
|
13594
|
+
...outcome !== void 0 ? { resultsummary: outcome.summary } : {}
|
|
13595
|
+
};
|
|
13596
|
+
});
|
|
13597
|
+
}
|
|
13598
|
+
var logstreamgenesis = "0".repeat(64);
|
|
13599
|
+
async function logstreameventof(input) {
|
|
13600
|
+
if (input.summary.trim() === "") throw new Error("The logstream event needs its summary.");
|
|
13601
|
+
const id = randomid();
|
|
13602
|
+
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 } });
|
|
13603
|
+
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 };
|
|
13604
|
+
}
|
|
13605
|
+
function appendlogstreamevent(events, event) {
|
|
13606
|
+
return [...events, event];
|
|
13607
|
+
}
|
|
13608
|
+
function filterlogstream(events, filter) {
|
|
13609
|
+
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));
|
|
13610
|
+
}
|
|
13611
|
+
function livebufferof(events, bound) {
|
|
13612
|
+
if (bound === void 0) return events;
|
|
13613
|
+
if (!Number.isInteger(bound) || bound <= 0) return events;
|
|
13614
|
+
return events.slice(-bound);
|
|
13615
|
+
}
|
|
13616
|
+
async function verifylogstream(events) {
|
|
13617
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
13618
|
+
const event = events[index];
|
|
13619
|
+
if (event === void 0) continue;
|
|
13620
|
+
const predecessor = events[index - 1];
|
|
13621
|
+
const expectedprevious = index === 0 || predecessor === void 0 ? logstreamgenesis : predecessor.hash.current;
|
|
13622
|
+
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.` };
|
|
13623
|
+
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 } });
|
|
13624
|
+
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.` };
|
|
13625
|
+
}
|
|
13626
|
+
return { valid: true, reason: `The logstream chain of ${events.length} event${events.length === 1 ? "" : "s"} verifies link by link.` };
|
|
13627
|
+
}
|
|
13628
|
+
async function auditexcerptof(events, input) {
|
|
13629
|
+
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"}.` };
|
|
13630
|
+
const range = events.slice(input.from, input.to);
|
|
13631
|
+
const verification = await verifylogstream(range);
|
|
13632
|
+
if (!verification.valid) return { ok: false, text: "", reason: `The excerpt refuses the copy: ${verification.reason}` };
|
|
13633
|
+
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");
|
|
13634
|
+
return { ok: true, text: text2, reason: `The excerpt copied the verified range ${input.from} to ${input.to} of the logstream.` };
|
|
13635
|
+
}
|
|
13636
|
+
function loglevelof(kind) {
|
|
13637
|
+
if (kind === "error") return "error";
|
|
13638
|
+
if (["deny", "revoke", "stop", "quarantine", "phish", "defer", "schema", "expiry"].includes(kind)) return "warn";
|
|
13639
|
+
return "info";
|
|
13640
|
+
}
|
|
13641
|
+
|
|
13642
|
+
// datagrid.ts
|
|
13643
|
+
function infercolumntype(values) {
|
|
13644
|
+
const present = values.filter((value) => value.trim() !== "");
|
|
13645
|
+
if (present.length === 0) return "empty";
|
|
13646
|
+
if (present.every((value) => /^-?\d+(?:\.\d+)?$/.test(value.trim()))) return "number";
|
|
13647
|
+
if (present.every((value) => value.trim() === "true" || value.trim() === "false")) return "boolean";
|
|
13648
|
+
if (present.every((value) => !Number.isNaN(Date.parse(value.trim())) && /\d{4}-\d{2}-\d{2}/.test(value.trim()))) return "date";
|
|
13649
|
+
return "text";
|
|
13650
|
+
}
|
|
13651
|
+
function datagridcolumnsof(rows) {
|
|
13652
|
+
const fields = [...new Set(rows.flatMap((row) => Object.keys(row)))];
|
|
13653
|
+
return fields.map((field) => ({ field, label: field, type: infercolumntype(rows.map((row) => row[field] ?? "")), inferred: true }));
|
|
13654
|
+
}
|
|
13655
|
+
function datagridof(input) {
|
|
13656
|
+
if (input.title.trim() === "") throw new Error("The datagrid view needs its title.");
|
|
13657
|
+
if (input.origin.trim() === "") throw new Error("The datagrid view needs its origin.");
|
|
13658
|
+
if (input.rows.length === 0) throw new Error("The datagrid view needs at least one extracted row.");
|
|
13659
|
+
const columns = datagridcolumnsof(input.rows);
|
|
13660
|
+
const rows = input.rows.map((row, index) => ({ index, values: Object.fromEntries(columns.map((column) => [column.field, row[column.field] ?? ""])) }));
|
|
13661
|
+
return { id: randomid(), title: input.title.trim(), origin: input.origin.trim(), runid: input.runid, columns, rows, at: input.at };
|
|
13662
|
+
}
|
|
13663
|
+
function exportmenudescriptors() {
|
|
13664
|
+
return ["csv", "json", "clipboard"].flatMap((format) => ["selection", "step", "run"].map((scope) => ({ format, scope, destination: format === "clipboard" ? "clipboard" : "download" })));
|
|
13665
|
+
}
|
|
13666
|
+
|
|
13667
|
+
// quickactions.ts
|
|
13668
|
+
function quickactioncatalog() {
|
|
13669
|
+
return [
|
|
13670
|
+
{ id: "extractpage", label: "Extract page data", command: "starttask", surface: "sidepanel", session: true },
|
|
13671
|
+
{ id: "captureshot", label: "Capture a shot", command: "starttask", surface: "sidepanel", permission: "downloads", session: true },
|
|
13672
|
+
{ id: "runrecent", label: "Run the recent task", command: "starttask", surface: "popup", session: true },
|
|
13673
|
+
{ id: "opendashboardpage", label: "Open the dashboard", command: "opendashboardpage", surface: "dashboardpage" }
|
|
13674
|
+
];
|
|
13675
|
+
}
|
|
13676
|
+
function quickactionsfor(catalog, input) {
|
|
13677
|
+
const capabilities = input.grantedcapabilities ?? ["activeTab", "storage", "scripting", "sidePanel"];
|
|
13678
|
+
const grantedcapabilities2 = capabilities;
|
|
13679
|
+
return catalog.filter((action) => quickactiongate({ action: { command: action.command, origin: input.origin, ...action.permission !== void 0 ? { permission: action.permission } : {}, ...action.session !== void 0 ? { session: action.session } : {} }, granted: input.granted, sessionactive: input.sessionactive, capabilities: grantedcapabilities2 }).allowed);
|
|
13680
|
+
}
|
|
13681
|
+
function shortcutdefaults() {
|
|
13682
|
+
return [
|
|
13683
|
+
{ command: "starttask", key: "Enter", modifiers: [], editable: true, surface: "popup" },
|
|
13684
|
+
{ command: "pauserun", key: "p", modifiers: ["ctrl", "shift"], editable: true, surface: "sidepanel" },
|
|
13685
|
+
{ command: "resumerun", key: "r", modifiers: ["ctrl", "shift"], editable: true, surface: "sidepanel" },
|
|
13686
|
+
{ command: "cancelrun", key: "x", modifiers: ["ctrl", "shift"], editable: true, surface: "sidepanel" },
|
|
13687
|
+
{ command: "commandpalette", key: ".", modifiers: ["ctrl"], editable: true, surface: "popup" }
|
|
13688
|
+
];
|
|
13689
|
+
}
|
|
13690
|
+
function parseshortcut(text2) {
|
|
13691
|
+
const parts = text2.trim().toLowerCase().split("+").map((part) => part.trim()).filter((part) => part !== "");
|
|
13692
|
+
if (parts.length === 0) throw new Error("The shortcut binding needs its key.");
|
|
13693
|
+
const modifiers = ["ctrl", "alt", "shift", "meta"];
|
|
13694
|
+
const key = parts.filter((part) => !modifiers.includes(part))[0];
|
|
13695
|
+
if (key === void 0 || key === "") throw new Error("The shortcut binding needs its key beside its modifiers.");
|
|
13696
|
+
return { key, modifiers: parts.filter((part) => modifiers.includes(part)) };
|
|
13697
|
+
}
|
|
13698
|
+
function shortcuttext(binding) {
|
|
13699
|
+
return [...binding.modifiers, binding.key].join("+");
|
|
13700
|
+
}
|
|
13701
|
+
function shortcutbindingafter(bindings, command, text2) {
|
|
13702
|
+
const existing = bindings.find((binding) => binding.command === command);
|
|
13703
|
+
if (existing === void 0) throw new Error(`The shortcutkeys know no ${command} command to edit.`);
|
|
13704
|
+
const parsed = parseshortcut(text2);
|
|
13705
|
+
return bindings.map((binding) => binding.command === command ? { ...binding, key: parsed.key, modifiers: parsed.modifiers } : binding);
|
|
13706
|
+
}
|
|
13707
|
+
function shortcutcommandof(bindings, input) {
|
|
13708
|
+
const pressed = [...input.modifiers].map((modifier) => modifier.toLowerCase()).sort();
|
|
13709
|
+
return bindings.find((binding) => binding.key.toLowerCase() === input.key.toLowerCase() && [...binding.modifiers].sort().join("+") === pressed.join("+") && (binding.command === "commandpalette" || binding.surface === input.surface))?.command;
|
|
13710
|
+
}
|
|
13711
|
+
function shortcutdispatchable(command, entries, input) {
|
|
13712
|
+
const entry = entries.find((candidate) => candidate.action.command === command);
|
|
13713
|
+
if (entry === void 0) return command === "commandpalette";
|
|
13714
|
+
return paletteactiongate({ action: { command: entry.action.command, ...entry.action.permission !== void 0 ? { permission: entry.action.permission } : {}, ...entry.action.session !== void 0 ? { session: entry.action.session } : {} }, granted: input.granted, sessionactive: input.sessionactive }).allowed;
|
|
13715
|
+
}
|
|
13716
|
+
function parseomniboxtask(input) {
|
|
13717
|
+
const text2 = input.text.trim();
|
|
13718
|
+
if (text2 === "") throw new Error("The omnibox task needs its natural language goal after the keyword.");
|
|
13719
|
+
if (input.origin.trim() === "") throw new Error("The omnibox task needs its active origin scope.");
|
|
13720
|
+
return { id: randomid(), text: text2, origin: input.origin.trim(), surface: "omnibox", at: input.at };
|
|
13721
|
+
}
|
|
13722
|
+
function omniboxtasktotaskinput(submission) {
|
|
13723
|
+
return { id: submission.id, text: submission.text, context: "", origin: submission.origin, surface: "omnibox", at: submission.at };
|
|
13724
|
+
}
|
|
13725
|
+
|
|
13726
|
+
// statusviews.ts
|
|
13727
|
+
function statusbadgeof(input) {
|
|
13728
|
+
if (input.planstate === void 0) return { state: "idle", waitingcount: 0 };
|
|
13729
|
+
if (input.waitingcount > 0) return { state: "attention", waitingcount: input.waitingcount, ...input.runid !== void 0 ? { runid: input.runid } : {} };
|
|
13730
|
+
if (input.planstate === "approved") return { state: "running", waitingcount: 0, ...input.runid !== void 0 ? { runid: input.runid } : {} };
|
|
13731
|
+
if (input.planstate === "pending") return { state: "waiting", waitingcount: 0, ...input.runid !== void 0 ? { runid: input.runid } : {} };
|
|
13732
|
+
return { state: "idle", waitingcount: 0, ...input.runid !== void 0 ? { runid: input.runid } : {} };
|
|
13733
|
+
}
|
|
13734
|
+
function badgetextof(state) {
|
|
13735
|
+
if (state.state === "attention") return String(state.waitingcount);
|
|
13736
|
+
if (state.state === "running") return "run";
|
|
13737
|
+
if (state.state === "waiting") return "wait";
|
|
13738
|
+
return "";
|
|
13739
|
+
}
|
|
13740
|
+
function badgecolorof(state) {
|
|
13741
|
+
if (state.state === "attention") return "#b3261e";
|
|
13742
|
+
if (state.state === "running") return "#1a73e8";
|
|
13743
|
+
if (state.state === "waiting") return "#e37400";
|
|
13744
|
+
return "#5f6368";
|
|
13745
|
+
}
|
|
13746
|
+
function notifydoneof(input) {
|
|
13747
|
+
if (input.runid.trim() === "") throw new Error("The done notification needs its run id.");
|
|
13748
|
+
return { id: randomid(), kind: "done", title: "The run completed", body: input.summary.trim() === "" ? `The run of ${input.origin} completed; the runsummary holds every step outcome.` : input.summary, deeplink: `#run-${input.runid}`, runid: input.runid, content: false, at: input.at };
|
|
13749
|
+
}
|
|
13750
|
+
function notifyattentionof(input) {
|
|
13751
|
+
if (input.stepid.trim() === "") throw new Error("The attention notification needs its waiting step.");
|
|
13752
|
+
const gate = notificationcontentgate({ content: input.content === true, consent: input.consent === true });
|
|
13753
|
+
if (!gate.allowed) throw new Error(gate.reason ?? "The attention notification refuses its page content.");
|
|
13754
|
+
return { id: randomid(), kind: "attention", title: input.cause === "gatewait" ? "The run waits for review" : input.cause === "phishguard" ? "The phishguard blocked a step" : "The run deferred a step", body: input.reason, deeplink: `#step-${input.stepid}`, runid: input.runid, stepid: input.stepid, content: input.content === true, at: input.at };
|
|
13755
|
+
}
|
|
13756
|
+
function notificationrespectsdnd(payload, dnd) {
|
|
13757
|
+
if (dnd) return { show: false, reason: `The os stays in do not disturb, so the ${payload.kind} notification holds its deep link ${payload.deeplink} in the history instead of showing.` };
|
|
13758
|
+
return { show: true, reason: `The ${payload.kind} notification shows with its deep link ${payload.deeplink}.` };
|
|
13759
|
+
}
|
|
13760
|
+
function recenttrayentryof(input) {
|
|
13761
|
+
if (input.runid.trim() === "") throw new Error("The recenttray entry needs its run id.");
|
|
13762
|
+
return { runid: input.runid, origin: input.origin, outcome: input.outcome, title: input.title, at: input.at, resumable: input.outcome === "halted", reopenable: input.outcome === "completed" || input.outcome === "failed" };
|
|
13763
|
+
}
|
|
13764
|
+
function recenttrayactions(entry) {
|
|
13765
|
+
const actions = [];
|
|
13766
|
+
if (entry.resumable) actions.push("resume");
|
|
13767
|
+
if (entry.reopenable) actions.push("reopen");
|
|
13768
|
+
return actions;
|
|
13769
|
+
}
|
|
13770
|
+
function stetoastof(input) {
|
|
13771
|
+
if (input.stepid.trim() === "") throw new Error("The stetoast needs its step.");
|
|
13772
|
+
return { id: randomid(), stepid: input.stepid, kind: input.kind, durationms: input.durationms, at: input.at };
|
|
13773
|
+
}
|
|
13774
|
+
function stetoaststackafter(toasts, toast, livecount) {
|
|
13775
|
+
const history2 = [...toasts, toast];
|
|
13776
|
+
if (livecount === void 0 || !Number.isInteger(livecount) || livecount <= 0) return { live: history2, history: history2 };
|
|
13777
|
+
return { live: history2.slice(-livecount), history: history2 };
|
|
13778
|
+
}
|
|
13779
|
+
function stetoasthistory(toasts) {
|
|
13780
|
+
return [...toasts].reverse();
|
|
13781
|
+
}
|
|
13782
|
+
|
|
13783
|
+
// pickerviews.ts
|
|
13784
|
+
function stabilityscoreof(input) {
|
|
13785
|
+
let score = 0;
|
|
13786
|
+
if (input.hasid) score += 40;
|
|
13787
|
+
if (input.hasstableattributes) score += 25;
|
|
13788
|
+
if (input.hasrole) score += 15;
|
|
13789
|
+
if (input.textunique) score += 10;
|
|
13790
|
+
if (input.selector.trim() === "") score -= 20;
|
|
13791
|
+
else if (input.selector.includes(":nth-child") || input.selector.includes(":nth-of-type")) score -= 15;
|
|
13792
|
+
return Math.max(0, Math.min(100, score));
|
|
13793
|
+
}
|
|
13794
|
+
function pickercandidateof(input) {
|
|
13795
|
+
const score = stabilityscoreof(input);
|
|
13796
|
+
const reasons = [];
|
|
13797
|
+
if (input.hasid) reasons.push("the id anchors the selector");
|
|
13798
|
+
if (input.hasstableattributes) reasons.push("stable attributes back the selector");
|
|
13799
|
+
if (input.hasrole) reasons.push("the aria role names the element");
|
|
13800
|
+
if (input.textunique) reasons.push("the text stays unique on the page");
|
|
13801
|
+
if (reasons.length === 0) reasons.push("only the positional shape anchors the selector");
|
|
13802
|
+
return { selector: input.selector, ...input.text !== void 0 && input.text !== "" ? { text: input.text } : {}, ...input.role !== void 0 && input.role !== "" ? { role: input.role } : {}, stabilityscore: score, reason: `The stability score of ${score} stands because ${reasons.join(", ")}.` };
|
|
13803
|
+
}
|
|
13804
|
+
function pickersessionstart(input) {
|
|
13805
|
+
const gate = pickeroverlaygate({ origin: input.origin, granted: input.granted });
|
|
13806
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
13807
|
+
return { id: randomid(), origin: input.origin, candidates: rankcandidates(input.candidates), startedat: input.at };
|
|
13808
|
+
}
|
|
13809
|
+
function rankcandidates(candidates) {
|
|
13810
|
+
return [...candidates].sort((left, right) => right.stabilityscore - left.stabilityscore);
|
|
13811
|
+
}
|
|
13812
|
+
function haloof(input) {
|
|
13813
|
+
if (input.selector.trim() === "") throw new Error("The targethalo needs its target selector.");
|
|
13814
|
+
return { stepid: input.stepid, selector: input.selector, rect: input.rect, state: input.state };
|
|
13815
|
+
}
|
|
13816
|
+
function halocolorof(state) {
|
|
13817
|
+
if (state === "running") return "#1a73e8";
|
|
13818
|
+
if (state === "waiting") return "#e37400";
|
|
13819
|
+
if (state === "done") return "#188038";
|
|
13820
|
+
if (state === "failed") return "#b3261e";
|
|
13821
|
+
if (state === "halted") return "#3c4043";
|
|
13822
|
+
return "#5f6368";
|
|
13823
|
+
}
|
|
13824
|
+
function guidedtips() {
|
|
13825
|
+
return [
|
|
13826
|
+
{ id: "selectorstability", surface: "sidepanel", title: "Selector stability", body: "Devthink scores every candidate selector by its stability: an id anchor, stable attributes, an aria role and a unique text each lift the score while a positional shape lowers it, so the proposed step binds to the selector least likely to break.", pickerstep: "candidatepick" },
|
|
13827
|
+
{ id: "candidatelock", surface: "sidepanel", title: "Locking a candidate", body: "Lock one candidate to bind it to the proposed step; one picker session locks one candidate and the locked selector rides the step for its review.", pickerstep: "candidatelock" },
|
|
13828
|
+
{ id: "haloreadout", surface: "sidepanel", title: "The halo read out", body: "During a run the targethalo outlines the active target element and its color follows the step state: gray while pending, blue while running, amber at a gate, green when done, red on failure and dark when halted.", pickerstep: "halotracking" }
|
|
13829
|
+
];
|
|
13830
|
+
}
|
|
13831
|
+
function guidedtipdismiss(tips, dismissed, tipid) {
|
|
13832
|
+
const tip = tips.find((candidate) => candidate.id === tipid);
|
|
13833
|
+
if (tip === void 0) throw new Error(`The guidedtips know no ${tipid} tip.`);
|
|
13834
|
+
return [.../* @__PURE__ */ new Set([...dismissed, tipid])];
|
|
13835
|
+
}
|
|
13836
|
+
function guidedtiprecall(dismissed) {
|
|
13837
|
+
return [];
|
|
13838
|
+
}
|
|
13839
|
+
function pagechipof(input) {
|
|
13840
|
+
if (input.stepid.trim() === "") throw new Error("The pagechip needs its step.");
|
|
13841
|
+
if (input.selector.trim() === "") throw new Error("The pagechip needs its anchor selector.");
|
|
13842
|
+
return { id: randomid(), stepid: input.stepid, selector: input.selector, origin: input.origin, at: input.at };
|
|
13843
|
+
}
|
|
13844
|
+
function pagechipresolve(chip, resolution, surface, at) {
|
|
13845
|
+
if (surface === "background") throw new Error("The pagechip resolution needs its distinct human action from a surface; the background never resolves a review on its own.");
|
|
13846
|
+
const resolved = { ...chip, resolution, resolvedat: at };
|
|
13847
|
+
return {
|
|
13848
|
+
chip: resolved,
|
|
13849
|
+
logevent: { kind: "review", stepid: chip.stepid, summary: `The user ${resolution === "approve" ? "approved" : "rejected"} the step ${chip.stepid} of ${chip.origin} from the pagechip anchored to ${chip.selector} on the ${surface}; one distinct human action resolved the step alone.` }
|
|
13850
|
+
};
|
|
13851
|
+
}
|
|
13852
|
+
|
|
13853
|
+
// evidenceviews.ts
|
|
13854
|
+
function shotpanelof(input) {
|
|
13855
|
+
const gate = shotpanelgate({ captureorigin: input.origin, granted: input.granted });
|
|
13856
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
13857
|
+
if (input.stepid.trim() === "") throw new Error("The shotpanel view needs its step.");
|
|
13858
|
+
return { id: randomid(), stepid: input.stepid, runid: input.runid, captureid: input.captureid, provenance: input.provenance, origin: input.origin, redactions: input.redactions ?? [], zoom: 1, pan: { x: 0, y: 0 }, at: input.at };
|
|
13859
|
+
}
|
|
13860
|
+
function comparepairof(input) {
|
|
13861
|
+
if (input.stepid.trim() === "") throw new Error("The compareviewer pair needs its step.");
|
|
13862
|
+
if (input.beforecaptureid === input.aftercaptureid) throw new Error("The compareviewer pair needs its distinct before and after captures.");
|
|
13863
|
+
return { id: randomid(), stepid: input.stepid, beforecaptureid: input.beforecaptureid, aftercaptureid: input.aftercaptureid, slidervalue: 50 };
|
|
13864
|
+
}
|
|
13865
|
+
|
|
13866
|
+
// siteprefs.ts
|
|
13867
|
+
function siteprofileof(input) {
|
|
13868
|
+
const gate = siteprofilegate({ origin: input.origin });
|
|
13869
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
13870
|
+
return { origin: input.origin, ...input.theme !== void 0 ? { theme: input.theme } : {}, ...input.shortcuts !== void 0 ? { shortcuts: input.shortcuts } : {}, ...input.defaultview !== void 0 ? { defaultview: input.defaultview } : {}, updatedat: input.at };
|
|
13871
|
+
}
|
|
13872
|
+
function siteprofileactive(profile, origin) {
|
|
13873
|
+
return profile.origin === origin;
|
|
13874
|
+
}
|
|
13875
|
+
function siteprofilefor(profiles, origin) {
|
|
13876
|
+
return profiles.find((profile) => siteprofileactive(profile, origin));
|
|
13877
|
+
}
|
|
13878
|
+
function darklighttokensof(mode) {
|
|
13879
|
+
const tokens = mode === "dark" ? { surface: "#1f1f1f", elevated: "#2b2b2b", text: "#e3e3e3", muted: "#9aa0a6", accent: "#8ab4f8", border: "#3c4043", focus: "#aecbfa", error: "#f28b82", success: "#81c995", warning: "#fdd663" } : { surface: "#ffffff", elevated: "#f8f9fa", text: "#202124", muted: "#5f6368", accent: "#1a73e8", border: "#dadce0", focus: "#174ea6", error: "#b3261e", success: "#188038", warning: "#e37400" };
|
|
13880
|
+
return { mode, tokens };
|
|
13881
|
+
}
|
|
13882
|
+
function resolveappearance(input) {
|
|
13883
|
+
if (input.siteprofile?.theme !== void 0 && input.siteprofile.theme !== "system") return { ...darklighttokensof(input.siteprofile.theme), source: "site" };
|
|
13884
|
+
if (input.useroverride !== void 0 && input.useroverride !== "system") return { ...darklighttokensof(input.useroverride), source: "user" };
|
|
13885
|
+
return { ...darklighttokensof(input.ospreference), source: "os" };
|
|
13886
|
+
}
|
|
13887
|
+
function localebundles() {
|
|
13888
|
+
return [
|
|
13889
|
+
{
|
|
13890
|
+
language: "en",
|
|
13891
|
+
strings: {
|
|
13892
|
+
"popup.title": "Devthink",
|
|
13893
|
+
"popup.taskinput.placeholder": "Describe the goal for the active tab",
|
|
13894
|
+
"popup.taskinput.submit": "Propose the plan",
|
|
13895
|
+
"popup.palette.open": "Open the commandpalette",
|
|
13896
|
+
"popup.recent.title": "Recent runs",
|
|
13897
|
+
"popup.recent.resume": "Resume",
|
|
13898
|
+
"popup.recent.reopen": "Reopen",
|
|
13899
|
+
"sidepanel.tab.plan": "Plan",
|
|
13900
|
+
"sidepanel.tab.run": "Run",
|
|
13901
|
+
"sidepanel.tab.review": "Review",
|
|
13902
|
+
"sidepanel.data.export": "Export",
|
|
13903
|
+
"dashboard.title": "Dashboard",
|
|
13904
|
+
"options.title": "Options",
|
|
13905
|
+
"options.theme.label": "Theme",
|
|
13906
|
+
"options.theme.dark": "Dark",
|
|
13907
|
+
"options.theme.light": "Light",
|
|
13908
|
+
"options.theme.system": "Follow the system",
|
|
13909
|
+
"options.locale.label": "Language",
|
|
13910
|
+
"options.shortcuts.label": "Shortcutkeys",
|
|
13911
|
+
"options.notifications.label": "Notifications",
|
|
13912
|
+
"options.importexport.label": "Import and export",
|
|
13913
|
+
"options.tour.label": "Feature tour",
|
|
13914
|
+
"stepapprove.approve": "Approve",
|
|
13915
|
+
"stepapprove.reject": "Reject",
|
|
13916
|
+
"stepapprove.edit": "Edit",
|
|
13917
|
+
"pagechip.approve": "Approve",
|
|
13918
|
+
"pagechip.reject": "Reject",
|
|
13919
|
+
"grid.empty": "No extracted rows yet",
|
|
13920
|
+
"toast.stepdone": "Step completed"
|
|
13921
|
+
}
|
|
13922
|
+
},
|
|
13923
|
+
{
|
|
13924
|
+
language: "pt",
|
|
13925
|
+
strings: {
|
|
13926
|
+
"popup.title": "Devthink",
|
|
13927
|
+
"popup.taskinput.placeholder": "Descreva o objetivo para a aba ativa",
|
|
13928
|
+
"popup.taskinput.submit": "Propor o plano",
|
|
13929
|
+
"popup.palette.open": "Abrir a paleta de comandos",
|
|
13930
|
+
"popup.recent.title": "Execu\xE7\xF5es recentes",
|
|
13931
|
+
"popup.recent.resume": "Retomar",
|
|
13932
|
+
"popup.recent.reopen": "Reabrir",
|
|
13933
|
+
"sidepanel.tab.plan": "Plano",
|
|
13934
|
+
"sidepanel.tab.run": "Execu\xE7\xE3o",
|
|
13935
|
+
"sidepanel.tab.review": "Revis\xE3o",
|
|
13936
|
+
"sidepanel.data.export": "Exportar",
|
|
13937
|
+
"dashboard.title": "Painel",
|
|
13938
|
+
"options.title": "Op\xE7\xF5es",
|
|
13939
|
+
"options.theme.label": "Tema",
|
|
13940
|
+
"options.theme.dark": "Escuro",
|
|
13941
|
+
"options.theme.light": "Claro",
|
|
13942
|
+
"options.theme.system": "Seguir o sistema",
|
|
13943
|
+
"options.locale.label": "Idioma",
|
|
13944
|
+
"options.shortcuts.label": "Atalhos",
|
|
13945
|
+
"options.notifications.label": "Notifica\xE7\xF5es",
|
|
13946
|
+
"options.importexport.label": "Importar e exportar",
|
|
13947
|
+
"options.tour.label": "Tour de recursos",
|
|
13948
|
+
"stepapprove.approve": "Aprovar",
|
|
13949
|
+
"stepapprove.reject": "Rejeitar",
|
|
13950
|
+
"stepapprove.edit": "Editar",
|
|
13951
|
+
"pagechip.approve": "Aprovar",
|
|
13952
|
+
"pagechip.reject": "Rejeitar",
|
|
13953
|
+
"grid.empty": "Nenhuma linha extra\xEDda ainda",
|
|
13954
|
+
"toast.stepdone": "Etapa conclu\xEDda"
|
|
13955
|
+
}
|
|
13956
|
+
}
|
|
13957
|
+
];
|
|
13958
|
+
}
|
|
13959
|
+
function localestring(bundles, language, key) {
|
|
13960
|
+
const requested = bundles.find((bundle) => bundle.language === language);
|
|
13961
|
+
const english = bundles.find((bundle) => bundle.language === "en");
|
|
13962
|
+
return requested?.strings[key] ?? english?.strings[key] ?? key;
|
|
13963
|
+
}
|
|
13964
|
+
function supportedlanguages(bundles) {
|
|
13965
|
+
return bundles.map((bundle) => bundle.language);
|
|
13966
|
+
}
|
|
13967
|
+
function localeformat(input) {
|
|
13968
|
+
if (input.kind === "date") {
|
|
13969
|
+
const date = new Date(input.value);
|
|
13970
|
+
const year = date.getUTCFullYear();
|
|
13971
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
13972
|
+
const day = String(date.getUTCDate()).padStart(2, "0");
|
|
13973
|
+
const hours = String(date.getUTCHours()).padStart(2, "0");
|
|
13974
|
+
const minutes = String(date.getUTCMinutes()).padStart(2, "0");
|
|
13975
|
+
return input.language === "pt" ? `${day}/${month}/${year} ${hours}:${minutes}` : `${year}-${month}-${day} ${hours}:${minutes}`;
|
|
13976
|
+
}
|
|
13977
|
+
if (input.kind === "duration") {
|
|
13978
|
+
const seconds = Math.round(input.value / 1e3);
|
|
13979
|
+
const minutes = Math.floor(seconds / 60);
|
|
13980
|
+
const rest = seconds % 60;
|
|
13981
|
+
return input.language === "pt" ? `${minutes} min ${rest} s` : `${minutes}m ${rest}s`;
|
|
13982
|
+
}
|
|
13983
|
+
const text2 = String(input.value);
|
|
13984
|
+
const parts = text2.split(".");
|
|
13985
|
+
const whole = parts[0] ?? "0";
|
|
13986
|
+
const fraction = parts[1];
|
|
13987
|
+
const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/g, input.language === "pt" ? "." : ",");
|
|
13988
|
+
return fraction !== void 0 ? `${grouped}${input.language === "pt" ? "," : "."}${fraction}` : grouped;
|
|
13989
|
+
}
|
|
13990
|
+
|
|
13991
|
+
// portability.ts
|
|
13992
|
+
function importexportpayloadof(input) {
|
|
13993
|
+
if (input.profile.trim() === "") throw new Error("The importexport payload needs its profile name.");
|
|
13994
|
+
const secrets = [...input.originprofiles, ...input.siteprofiles, ...input.notes, ...Object.values(input.preferences)].find((record2) => secretcarrying(record2)) !== void 0;
|
|
13995
|
+
const gate = importexportgate({ containssecrets: secrets, unmaskedlogs: false });
|
|
13996
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
13997
|
+
return { version: 1, kind: "settings", profile: input.profile.trim(), exportedat: input.at, contents: { originprofiles: input.originprofiles, siteprofiles: input.siteprofiles, notes: input.notes, preferences: input.preferences }, exclusions: ["secretvault values", "unmasked logs"] };
|
|
13998
|
+
}
|
|
13999
|
+
function secretcarrying(record2) {
|
|
14000
|
+
if (record2 === null || typeof record2 !== "object") return false;
|
|
14001
|
+
const entries = Object.entries(record2);
|
|
14002
|
+
const secretkeys = ["secret", "token", "password", "apikey", "authorization"];
|
|
14003
|
+
return entries.some(([key, value]) => secretkeys.some((shape) => key.toLowerCase().includes(shape)) && typeof value === "string" && value.trim() !== "");
|
|
14004
|
+
}
|
|
14005
|
+
function importexportvalidate(payload) {
|
|
14006
|
+
const records = [...payload.contents.originprofiles, ...payload.contents.siteprofiles, ...payload.contents.notes, ...Object.values(payload.contents.preferences)];
|
|
14007
|
+
const preferencessecrets = Object.entries(payload.contents.preferences).some(([key, value]) => secretcarrying({ [key]: value }));
|
|
14008
|
+
const gate = importexportgate({ containssecrets: records.some((record2) => secretcarrying(record2)) || preferencessecrets, unmaskedlogs: payload.contents.unmaskedlogs !== void 0 });
|
|
14009
|
+
if (!gate.allowed) return { ok: false, reason: gate.reason ?? "The importexport bundle refuses." };
|
|
14010
|
+
if (payload.profile.trim() === "") return { ok: false, reason: "The importexport bundle needs its profile name." };
|
|
14011
|
+
return { ok: true, reason: `The importexport bundle of the profile ${payload.profile} validates with ${payload.contents.originprofiles.length} origin profile${payload.contents.originprofiles.length === 1 ? "" : "s"}, ${payload.contents.siteprofiles.length} site profile${payload.contents.siteprofiles.length === 1 ? "" : "s"} and ${payload.contents.notes.length} note${payload.contents.notes.length === 1 ? "" : "s"}; ${payload.exclusions.join(" and ")} never enter any bundle.` };
|
|
14012
|
+
}
|
|
14013
|
+
function applyimport(payload, current) {
|
|
14014
|
+
const validation = importexportvalidate(payload);
|
|
14015
|
+
if (!validation.ok) throw new Error(validation.reason);
|
|
14016
|
+
const applied = Object.keys(payload.contents.preferences);
|
|
14017
|
+
return { preferences: { ...current, ...payload.contents.preferences }, applied };
|
|
14018
|
+
}
|
|
14019
|
+
function detectfilekind(filename, head) {
|
|
14020
|
+
const extension = filename.toLowerCase().split(".").pop() ?? "";
|
|
14021
|
+
if (extension === "csv") return "csv";
|
|
14022
|
+
if (extension === "json") {
|
|
14023
|
+
const trimmed = head.trim();
|
|
14024
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) return trimmed.includes('"steps"') ? "workflow" : "json";
|
|
14025
|
+
return "json";
|
|
14026
|
+
}
|
|
14027
|
+
if (extension === "yaml" || extension === "yml") return "workflow";
|
|
14028
|
+
return void 0;
|
|
14029
|
+
}
|
|
14030
|
+
function dropimportof(input) {
|
|
14031
|
+
if (input.filename.trim() === "") throw new Error("The dropimport session needs its filename.");
|
|
14032
|
+
const kind = detectfilekind(input.filename, input.head);
|
|
14033
|
+
if (kind === void 0) throw new Error(`The dropimport detects no csv, json or workflow kind in ${input.filename}; the import path refuses the file.`);
|
|
14034
|
+
return { id: `${input.filename}:${input.at}`, filename: input.filename, kind, bytes: input.bytes, accepted: true, at: input.at };
|
|
14035
|
+
}
|
|
14036
|
+
|
|
14037
|
+
// tourviews.ts
|
|
14038
|
+
function featuretourstops() {
|
|
14039
|
+
return [
|
|
14040
|
+
{ id: "origingrants", surface: "popup", focus: "#allowlist", title: "Origin grants", body: "Devthink denies automation by default; grant one exact origin at a time and every run stays inside the granted origins.", order: 1 },
|
|
14041
|
+
{ id: "planreview", surface: "sidepanel", focus: "#plancards", 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.", order: 2 },
|
|
14042
|
+
{ id: "runcontrol", surface: "sidepanel", focus: "#timeline", title: "Run control", body: "Runs start, pause, resume and cancel under your hand while the stepstimeline follows every transition.", order: 3 },
|
|
14043
|
+
{ id: "logaudit", surface: "dashboardpage", focus: "#sessiongrid", title: "Log audit", body: "The immutable log chains every step transition with masked values; verify the chain and copy a verified range as an audit excerpt.", order: 4 },
|
|
14044
|
+
{ id: "datagrid", surface: "sidepanel", focus: "#datagrid", title: "The datagrid", body: "Extraction results render as a grid with inferred column types; sort and filter locally, select a row range and export csv, json or clipboard with masked values only.", order: 5 },
|
|
14045
|
+
{ id: "compareviewer", surface: "sidepanel", focus: "#compareviewer", title: "The compareviewer", body: "Every executed write step pairs its before and after captures; the slider overlays the two so you see exactly what the step changed.", order: 6 },
|
|
14046
|
+
{ id: "pickeroverlay", surface: "sidepanel", focus: "#picker", title: "The pickeroverlay", body: "Start a picker session to list the element candidates of the granted origin with stability scored selectors; lock one candidate for the proposed step.", order: 7 }
|
|
14047
|
+
];
|
|
14048
|
+
}
|
|
14049
|
+
function featuretourordered(stops) {
|
|
14050
|
+
return [...stops].sort((left, right) => left.order - right.order);
|
|
14051
|
+
}
|
|
14052
|
+
function a11ylabelof(input) {
|
|
14053
|
+
if (input.control.trim() === "") throw new Error("The a11ylabel needs its control.");
|
|
14054
|
+
if (input.name.trim() === "") throw new Error("The a11ylabel needs its accessible name.");
|
|
14055
|
+
return { control: input.control, role: input.role, name: input.name, ...input.state !== void 0 ? { state: input.state } : {}, ...input.value !== void 0 ? { value: input.value } : {} };
|
|
14056
|
+
}
|
|
14057
|
+
function a11ylabelsfor(surface) {
|
|
14058
|
+
const labels = {
|
|
14059
|
+
popup: [
|
|
14060
|
+
a11ylabelof({ control: "taskinput", role: "textbox", name: "popup.taskinput.placeholder", state: "idle" }),
|
|
14061
|
+
a11ylabelof({ control: "submit", role: "button", name: "popup.taskinput.submit" }),
|
|
14062
|
+
a11ylabelof({ control: "palette", role: "button", name: "popup.palette.open" }),
|
|
14063
|
+
a11ylabelof({ control: "recenttray", role: "list", name: "popup.recent.title", value: "0 runs" })
|
|
14064
|
+
],
|
|
14065
|
+
sidepanel: [
|
|
14066
|
+
a11ylabelof({ control: "plantab", role: "tab", name: "sidepanel.tab.plan", state: "selected" }),
|
|
14067
|
+
a11ylabelof({ control: "runtab", role: "tab", name: "sidepanel.tab.run", state: "unselected" }),
|
|
14068
|
+
a11ylabelof({ control: "reviewtab", role: "tab", name: "sidepanel.tab.review", state: "unselected" }),
|
|
14069
|
+
a11ylabelof({ control: "datagrid", role: "table", name: "grid.empty" }),
|
|
14070
|
+
a11ylabelof({ control: "compareviewer", role: "slider", name: "sidepanel.data.compare", value: "50" }),
|
|
14071
|
+
a11ylabelof({ control: "picker", role: "button", name: "sidepanel.data.picker" })
|
|
14072
|
+
],
|
|
14073
|
+
dashboardpage: [
|
|
14074
|
+
a11ylabelof({ control: "sessiongrid", role: "table", name: "dashboard.title", value: "0 runs" }),
|
|
14075
|
+
a11ylabelof({ control: "historysearch", role: "search", name: "dashboard.history" }),
|
|
14076
|
+
a11ylabelof({ control: "dropzone", role: "region", name: "options.importexport.label" })
|
|
14077
|
+
],
|
|
14078
|
+
optionspage: [
|
|
14079
|
+
a11ylabelof({ control: "theme", role: "radiogroup", name: "options.theme.label", value: "system" }),
|
|
14080
|
+
a11ylabelof({ control: "locale", role: "combobox", name: "options.locale.label", value: "en" }),
|
|
14081
|
+
a11ylabelof({ control: "shortcuts", role: "group", name: "options.shortcuts.label" }),
|
|
14082
|
+
a11ylabelof({ control: "notifications", role: "switch", name: "options.notifications.label", state: "off" }),
|
|
14083
|
+
a11ylabelof({ control: "importexport", role: "region", name: "options.importexport.label" }),
|
|
14084
|
+
a11ylabelof({ control: "tour", role: "button", name: "options.tour.label" })
|
|
14085
|
+
],
|
|
14086
|
+
onboarding: [
|
|
14087
|
+
a11ylabelof({ control: "onboarding", role: "dialog", name: "options.tour.label", state: "open" })
|
|
14088
|
+
],
|
|
14089
|
+
omnibox: [
|
|
14090
|
+
a11ylabelof({ control: "omnibox", role: "textbox", name: "popup.taskinput.placeholder" })
|
|
14091
|
+
],
|
|
14092
|
+
page: [
|
|
14093
|
+
a11ylabelof({ control: "pagechip", role: "group", name: "pagechip.approve", state: "pending" })
|
|
14094
|
+
]
|
|
14095
|
+
};
|
|
14096
|
+
return labels[surface];
|
|
14097
|
+
}
|
|
14098
|
+
function a11ylabellocalized(label, bundles, language) {
|
|
14099
|
+
return { ...label, name: localestring(bundles, language, label.name) };
|
|
14100
|
+
}
|
|
14101
|
+
function a11ylabelslocalizedfor(surface, bundles, language) {
|
|
14102
|
+
return a11ylabelsfor(surface).map((label) => a11ylabellocalized(label, bundles, language));
|
|
14103
|
+
}
|
|
14104
|
+
|
|
13183
14105
|
// llm.ts
|
|
13184
14106
|
var defaultrefusalmarkers = ["i cannot", "i can't", "i'm unable", "refusal:", "cannot comply"];
|
|
13185
14107
|
function buildrequest(input) {
|
|
@@ -15378,6 +16300,33 @@ function extensionpage(sender) {
|
|
|
15378
16300
|
}
|
|
15379
16301
|
async function audit(kind, summary, extra = {}) {
|
|
15380
16302
|
await memory.addaudi({ id: randomid(), kind, at: Date.now(), summary, ...extra });
|
|
16303
|
+
await recordsurfaceevent(kind, summary, extra);
|
|
16304
|
+
if (kind === "session" || kind === "pause" || kind === "resume" || kind === "complete" || kind === "cancel" || kind === "gate" || kind === "notify") void updatestatusbadge().catch(() => {
|
|
16305
|
+
});
|
|
16306
|
+
}
|
|
16307
|
+
var surfacechannel = typeof BroadcastChannel === "function" ? new BroadcastChannel("devthinksurfaces") : void 0;
|
|
16308
|
+
var logstreamhistory = [];
|
|
16309
|
+
var recentframes = [];
|
|
16310
|
+
async function recordsurfaceevent(kind, summary, extra = {}) {
|
|
16311
|
+
try {
|
|
16312
|
+
const session = await memory.getsession();
|
|
16313
|
+
const origin = session?.origin ?? "";
|
|
16314
|
+
if (origin === "") return;
|
|
16315
|
+
const at = Date.now();
|
|
16316
|
+
const lastevent = logstreamhistory[logstreamhistory.length - 1];
|
|
16317
|
+
const previous = lastevent !== void 0 ? lastevent.hash.current : logstreamgenesis;
|
|
16318
|
+
const event = await logstreameventof({ level: loglevelof(kind), source: "background", origin, summary, ...extra.stepid !== void 0 ? { stepid: extra.stepid } : {}, masked: extra.masked === true, maskverdict: extra.masked === true ? extra.maskverdict ?? "The source payload stayed masked before it streamed." : "The source payload carries no masked value.", previous, at });
|
|
16319
|
+
logstreamhistory = appendlogstreamevent(logstreamhistory, event);
|
|
16320
|
+
const frame = broadcastframeof({ channel: broadcastchannelof(kind), surface: "background", summary, at });
|
|
16321
|
+
recentframes = [...recentframes, frame];
|
|
16322
|
+
surfacechannel?.postMessage(frame);
|
|
16323
|
+
} catch {
|
|
16324
|
+
}
|
|
16325
|
+
}
|
|
16326
|
+
async function broadcastsurfaceframe(input) {
|
|
16327
|
+
const frame = broadcastframeof({ ...input, at: Date.now() });
|
|
16328
|
+
recentframes = [...recentframes, frame];
|
|
16329
|
+
surfacechannel?.postMessage(frame);
|
|
15381
16330
|
}
|
|
15382
16331
|
function stepoptions6(step) {
|
|
15383
16332
|
try {
|
|
@@ -21145,6 +22094,8 @@ var commandschemas = {
|
|
|
21145
22094
|
sessions: { note: "object", scratch: "object", summary: "object", recall: "object", correction: "object", consent: "object", grid: "object", search: "object", cancel: "object", retry: "object", error: "object", settings: "object", bundle: "object" },
|
|
21146
22095
|
environments: { action: "string", grants: "array", requestcapability: "boolean", pool: "object", offscreenclose: "boolean", sandbox: "object", settings: "object", render: "object", sandboxhost: "object" },
|
|
21147
22096
|
transparency: {},
|
|
22097
|
+
surface: { palette: "object", task: "object", onboarding: "object", bus: "object", broadcast: "object", layout: "object", logstream: "object", approve: "object", diff: "object", review: "object", timeline: "object", dashboard: "object", settings: "object" },
|
|
22098
|
+
views: { datagrid: "object", export: "object", quickaction: "object", shortcut: "object", omnibox: "object", badge: "object", notify: "object", recent: "object", picker: "object", halo: "object", tips: "object", shotpanel: "object", compare: "object", siteprofile: "object", theme: "object", locale: "object", importexport: "object", dropimport: "object", tour: "object", a11y: "object", chip: "object", toast: "object", settings: "object" },
|
|
21148
22099
|
execute: { stepid: "string" },
|
|
21149
22100
|
configure: { endpoint: "string" }
|
|
21150
22101
|
};
|
|
@@ -21371,6 +22322,608 @@ async function handlesessionscommand(message) {
|
|
|
21371
22322
|
}
|
|
21372
22323
|
throw new Error("The sessions command carries no note, scratch, summary, recall, correction, consent, grid, search, cancel, retry, error, settings or bundle action.");
|
|
21373
22324
|
}
|
|
22325
|
+
async function grantedcapabilities() {
|
|
22326
|
+
const report = await memory.getcapabilities();
|
|
22327
|
+
const granted = ["activeTab", "storage", "scripting", "sidePanel"];
|
|
22328
|
+
if (report?.tabs) granted.push("tabs");
|
|
22329
|
+
if (report?.downloads) granted.push("downloads");
|
|
22330
|
+
if (report?.clipboardread) granted.push("clipboardRead");
|
|
22331
|
+
if (report?.clipboardwrite) granted.push("clipboardWrite");
|
|
22332
|
+
if (await offscreengranted()) granted.push("offscreen");
|
|
22333
|
+
return granted;
|
|
22334
|
+
}
|
|
22335
|
+
async function surfacesnapshotof(surface) {
|
|
22336
|
+
const settings = await memory.getsettings();
|
|
22337
|
+
const session = await memory.getsession();
|
|
22338
|
+
const sessionactive = Boolean(session && !session.stoppedat && session.expiresat > Date.now());
|
|
22339
|
+
const granted = await grantedcapabilities();
|
|
22340
|
+
const plan = await memory.getplan();
|
|
22341
|
+
const progress = await memory.getprogress();
|
|
22342
|
+
const onboarding = await memory.getonboardingstate();
|
|
22343
|
+
const palette = palettequery(palettecommandsof(surfacepalette(), { granted, sessionactive }), { text: "", usage: await memory.getpaletteusage(), ...settings?.paletterecents !== void 0 ? { recentwindow: settings.paletterecents } : {} });
|
|
22344
|
+
const verification = await verifylogstream(logstreamhistory);
|
|
22345
|
+
return surfacesnapshot({
|
|
22346
|
+
surface,
|
|
22347
|
+
palette,
|
|
22348
|
+
timeline: plan ? stepstimelinenodes({ plan, ...progress !== void 0 && progress.planid === plan.id ? { progress } : {}, now: Date.now() }) : [],
|
|
22349
|
+
logstream: { events: livebufferof(logstreamhistory, settings?.logstreambuffer).map((event) => ({ id: event.id, level: event.level, source: event.source, origin: event.origin, summary: event.summary, ...event.stepid !== void 0 ? { stepid: event.stepid } : {}, masked: event.masked, maskverdict: event.maskverdict, at: event.at })), chainvalid: verification.valid, reason: verification.reason },
|
|
22350
|
+
plancards: plan !== void 0 ? plancardgroups(plancardsof({ plan, corrections: await memory.getcorrections() })) : [],
|
|
22351
|
+
...onboarding !== void 0 ? { onboarding: { stepscompleted: onboarding.stepscompleted, done: onboarding.done } } : {}
|
|
22352
|
+
});
|
|
22353
|
+
}
|
|
22354
|
+
async function handlesurfacecommand(message) {
|
|
22355
|
+
const input = message;
|
|
22356
|
+
const now = Date.now();
|
|
22357
|
+
const session = await memory.getsession();
|
|
22358
|
+
const sessionactive = Boolean(session && !session.stoppedat && session.expiresat > now);
|
|
22359
|
+
const settings = await memory.getsettings();
|
|
22360
|
+
const plan = await memory.getplan();
|
|
22361
|
+
const surfaceof = (value, fallback) => ["popup", "sidepanel", "dashboardpage", "optionspage", "onboarding"].includes(value ?? "") ? value : fallback;
|
|
22362
|
+
if (input.palette !== void 0) {
|
|
22363
|
+
const granted = await grantedcapabilities();
|
|
22364
|
+
const entries = surfacepalette();
|
|
22365
|
+
if (input.palette.used !== void 0) {
|
|
22366
|
+
const command = input.palette.used.command?.trim() ?? "";
|
|
22367
|
+
if (command === "") throw new Error("The palette use record needs its command.");
|
|
22368
|
+
const usage = paletteuseafter(await memory.getpaletteusage(), command, now);
|
|
22369
|
+
const record2 = usage[0];
|
|
22370
|
+
if (record2 === void 0) throw new Error("The palette use record never landed.");
|
|
22371
|
+
await memory.setpaletteusage(usage);
|
|
22372
|
+
await audit("palette", `The user ran the ${command} command from the commandpalette; its ${record2.count} recorded use${record2.count === 1 ? "" : "s"} rank it first among equal matches.`, { ...session ? { sessionid: session.id } : {} });
|
|
22373
|
+
return { usage: record2 };
|
|
22374
|
+
}
|
|
22375
|
+
if (input.palette.query !== void 0) {
|
|
22376
|
+
const matches = palettequery(palettecommandsof(entries, { granted, sessionactive }), { text: input.palette.query.text ?? "", usage: await memory.getpaletteusage(), ...settings?.paletterecents !== void 0 ? { recentwindow: settings.paletterecents } : {} });
|
|
22377
|
+
return { matches };
|
|
22378
|
+
}
|
|
22379
|
+
return { entries: palettecommandsof(entries, { granted, sessionactive }) };
|
|
22380
|
+
}
|
|
22381
|
+
if (input.task !== void 0) {
|
|
22382
|
+
if (input.task.submit !== void 0) {
|
|
22383
|
+
if (!session || session.stoppedat || session.expiresat <= now) throw new Error("Start a current browser session before submitting a task goal.");
|
|
22384
|
+
const { tab, origin } = await activecontext();
|
|
22385
|
+
if (session.tabid !== tab.id || session.origin !== origin) throw new Error("The selected tab or origin no longer matches the approved session.");
|
|
22386
|
+
const version = await memory.getobservationversion();
|
|
22387
|
+
const storedobservation = version !== void 0 ? await memory.getobservation(version) : void 0;
|
|
22388
|
+
const context = storedobservation ? `${storedobservation.observation.title}: ${storedobservation.observation.textpreview}` : tab.title ?? "";
|
|
22389
|
+
const submission = taskinputof({ text: input.task.submit.text ?? "", context, origin, surface: surfaceof(input.task.submit.surface, "popup"), at: now });
|
|
22390
|
+
await memory.addtaskinput(submission);
|
|
22391
|
+
const proposed = await propose(submission.text, false);
|
|
22392
|
+
await audit("surface", `The ${submission.surface} taskinput submitted a natural language goal for ${origin} with the active origin and the page outline attached; the goal routed through the same proposal flow as the api and the plan ${proposed.id} now awaits its plancard review.`, { sessionid: session.id, planid: proposed.id });
|
|
22393
|
+
await broadcastsurfaceframe({ channel: "runstate", surface: "background", summary: `A taskinput goal became the plan ${proposed.id} and awaits review.` });
|
|
22394
|
+
return { submission, plan: proposed, status: "ready" };
|
|
22395
|
+
}
|
|
22396
|
+
if (input.task.history === true) return { history: await memory.gettaskinputs() };
|
|
22397
|
+
if (input.task.status === true) return { status: plan === void 0 ? "idle" : plan.state === "pending" ? "ready" : plan.state === "approved" ? "ready" : "failed" };
|
|
22398
|
+
}
|
|
22399
|
+
if (input.onboarding !== void 0) {
|
|
22400
|
+
const state = await memory.getonboardingstate();
|
|
22401
|
+
if (input.onboarding.complete !== void 0) {
|
|
22402
|
+
const stepid = input.onboarding.complete.stepid?.trim() ?? "";
|
|
22403
|
+
const current = state ?? onboardingstart(void 0, now);
|
|
22404
|
+
const completion = onboardingcomplete(current, stepid, now);
|
|
22405
|
+
if (completion.consentevent !== void 0) {
|
|
22406
|
+
const consentgate = onboardingconsentgate({ consentevents: current.consentevent !== void 0 ? [current.consentevent] : [] });
|
|
22407
|
+
if (!consentgate.allowed) throw new Error(consentgate.reason);
|
|
22408
|
+
const origin = session?.origin ?? "onboarding";
|
|
22409
|
+
await memory.addconsentmemoryentry(consentmemoryof({ origin, decision: "grant", boundary: "onboarding", kinds: [], now }));
|
|
22410
|
+
}
|
|
22411
|
+
await memory.setonboardingstate(completion.state);
|
|
22412
|
+
await audit("onboarding", completion.consentevent !== void 0 ? `The user finished the onboarding walkthrough and its completion wrote the single consent scoped event ${completion.consentevent}; the walkthrough never writes a second one.` : `The user completed the ${stepid} step of the onboarding walkthrough; ${completion.state.stepscompleted.length} of ${onboardingsteps().length} steps stand done.`, { ...session ? { sessionid: session.id } : {} });
|
|
22413
|
+
await broadcastsurfaceframe({ channel: "settings", surface: "background", summary: completion.consentevent !== void 0 ? "The onboarding walkthrough completed." : `The onboarding step ${stepid} completed.` });
|
|
22414
|
+
return { steps: onboardingsteps(), state: completion.state, ...completion.consentevent !== void 0 ? { consentevent: completion.consentevent } : {} };
|
|
22415
|
+
}
|
|
22416
|
+
if (input.onboarding.replay === true) {
|
|
22417
|
+
const replayed = onboardingstart(state, now);
|
|
22418
|
+
await memory.setonboardingstate(replayed);
|
|
22419
|
+
await audit("onboarding", "The user replayed the onboarding walkthrough on demand from the optionspage; the replay restarts the steps and writes no second consent event.", {});
|
|
22420
|
+
return { steps: onboardingsteps(), state: replayed };
|
|
22421
|
+
}
|
|
22422
|
+
return { steps: onboardingsteps(), ...state ? { state } : {} };
|
|
22423
|
+
}
|
|
22424
|
+
if (input.bus !== void 0 && input.bus.action !== void 0) {
|
|
22425
|
+
const surface = surfaceof(input.bus.action.surface, "popup");
|
|
22426
|
+
const command = input.bus.action.command?.trim() ?? "";
|
|
22427
|
+
const action = { surface, command, ...input.bus.action.stepid !== void 0 && input.bus.action.stepid.trim() !== "" ? { stepid: input.bus.action.stepid } : {}, ...input.bus.action.payload !== void 0 && input.bus.action.payload.trim() !== "" ? { payload: input.bus.action.payload } : {} };
|
|
22428
|
+
const granted = await grantedcapabilities();
|
|
22429
|
+
const route = busrouteaction(action, { sessionactive, granted, planreviewed: Boolean(plan && plan.state === "approved"), planstate: plan?.state === "pending" ? "pending" : "approved", text: input.bus.action.payload ?? "", origin: session?.origin ?? "" });
|
|
22430
|
+
if (!route.dispatched) throw new Error(route.reason);
|
|
22431
|
+
await audit("surface", `The ${surface} routed the ${command} action through the command bus: ${route.reason}`, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {} });
|
|
22432
|
+
if (command === "starttask") {
|
|
22433
|
+
if (!sessionactive) await handlerequest({ kind: "startsession" }, {});
|
|
22434
|
+
const goal = (input.bus.action.payload ?? "").trim();
|
|
22435
|
+
if (goal !== "") await propose(goal, false);
|
|
22436
|
+
} else if (command === "pauserun") await handlerequest({ kind: "pausesession" }, {});
|
|
22437
|
+
else if (command === "resumerun") await handlerequest({ kind: "resumesession" }, {});
|
|
22438
|
+
else if (command === "cancelrun") {
|
|
22439
|
+
if (plan) await handlerequest({ kind: "sessions", cancel: { runid: plan.id } }, {}).catch(() => {
|
|
22440
|
+
});
|
|
22441
|
+
} else if (command === "revokeconsent") {
|
|
22442
|
+
if (session) await handlerequest({ kind: "security", allowlist: { remove: { origin: session.origin } } }, {}).catch(() => {
|
|
22443
|
+
});
|
|
22444
|
+
}
|
|
22445
|
+
await broadcastsurfaceframe({ channel: "runstate", surface, summary: `The ${command} action of the ${surface} dispatched through the command bus.` });
|
|
22446
|
+
return { route, palette: palettecommandsof(surfacepalette(), { granted, sessionactive }) };
|
|
22447
|
+
}
|
|
22448
|
+
if (input.broadcast !== void 0 && input.broadcast.frames === true) {
|
|
22449
|
+
const bound = settings?.logstreambuffer;
|
|
22450
|
+
const boundgate = logbufferboundvalid(bound);
|
|
22451
|
+
if (!boundgate.allowed) throw new Error(boundgate.reason);
|
|
22452
|
+
return { frames: bound === void 0 ? recentframes : recentframes.slice(-bound), logstream: livebufferof(logstreamhistory, bound), total: logstreamhistory.length };
|
|
22453
|
+
}
|
|
22454
|
+
if (input.layout !== void 0) {
|
|
22455
|
+
if (input.layout.set !== void 0) {
|
|
22456
|
+
const surface = surfaceof(input.layout.set.surface, "popup");
|
|
22457
|
+
const preferences = input.layout.set.preferences ?? {};
|
|
22458
|
+
await memory.setsurfacelayout({ surface, preferences, updatedat: now });
|
|
22459
|
+
await audit("surface", `The user saved the layout preferences of the ${surface} with ${Object.keys(preferences).length} key${Object.keys(preferences).length === 1 ? "" : "s"}; the preferences scope per profile workspace and take effect without a reload.`, { ...session ? { sessionid: session.id } : {} });
|
|
22460
|
+
return { layout: { surface, preferences, updatedat: now } };
|
|
22461
|
+
}
|
|
22462
|
+
if (input.layout.get !== void 0) return { layout: await memory.getsurfacelayout(surfaceof(input.layout.get.surface, "popup")) };
|
|
22463
|
+
}
|
|
22464
|
+
if (input.logstream !== void 0) {
|
|
22465
|
+
if (input.logstream.read !== void 0) {
|
|
22466
|
+
const stored = await memory.getlogstreamfilters();
|
|
22467
|
+
const requested = input.logstream.read.filters;
|
|
22468
|
+
const level = requested?.level !== void 0 && requested.level !== "" ? requested.level : stored?.level;
|
|
22469
|
+
const origin = requested?.origin !== void 0 && requested.origin !== "" ? requested.origin : stored?.origin;
|
|
22470
|
+
const stepid = requested?.stepid !== void 0 && requested.stepid !== "" ? requested.stepid : stored?.stepid;
|
|
22471
|
+
const filter = {};
|
|
22472
|
+
if (level !== void 0 && level !== "") filter.level = level;
|
|
22473
|
+
if (origin !== void 0 && origin !== "") filter.origin = origin;
|
|
22474
|
+
if (stepid !== void 0 && stepid !== "") filter.stepid = stepid;
|
|
22475
|
+
const verification = await verifylogstream(logstreamhistory);
|
|
22476
|
+
return { events: filterlogstream(livebufferof(logstreamhistory, settings?.logstreambuffer), filter), chain: verification, total: logstreamhistory.length };
|
|
22477
|
+
}
|
|
22478
|
+
if (input.logstream.excerpt !== void 0) {
|
|
22479
|
+
const from = input.logstream.excerpt.from ?? 0;
|
|
22480
|
+
const to = input.logstream.excerpt.to ?? logstreamhistory.length;
|
|
22481
|
+
const excerpt = await auditexcerptof(logstreamhistory, { from, to });
|
|
22482
|
+
const gate = logstreamegressgate({ verified: excerpt.ok, entries: Math.max(0, Math.min(to, logstreamhistory.length) - Math.max(0, from)) });
|
|
22483
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
22484
|
+
await audit("logstream", `The user copied the verified range ${from} to ${to} of the live logstream as an audit excerpt; the copy left the stream only after the chain verified.`, { ...session ? { sessionid: session.id } : {} });
|
|
22485
|
+
return { excerpt: excerpt.text, reason: excerpt.reason };
|
|
22486
|
+
}
|
|
22487
|
+
if (input.logstream.filters?.set !== void 0) {
|
|
22488
|
+
const requested = input.logstream.filters.set;
|
|
22489
|
+
const filter = {};
|
|
22490
|
+
if (requested?.level !== void 0 && requested.level !== "") filter.level = requested.level;
|
|
22491
|
+
if (requested?.origin !== void 0 && requested.origin !== "") filter.origin = requested.origin;
|
|
22492
|
+
if (requested?.stepid !== void 0 && requested.stepid !== "") filter.stepid = requested.stepid;
|
|
22493
|
+
await memory.setlogstreamfilters(filter);
|
|
22494
|
+
await audit("surface", `The user saved the logstream filter preferences${Object.keys(filter).length > 0 ? ` for ${Object.entries(filter).map(([key, value]) => `${key} ${value}`).join(" and ")}` : ""}; the live view reopens with them.`, {});
|
|
22495
|
+
return { filters: filter };
|
|
22496
|
+
}
|
|
22497
|
+
}
|
|
22498
|
+
if (input.approve !== void 0 && input.approve.resolve !== void 0) {
|
|
22499
|
+
const stepid = input.approve.resolve.stepid?.trim() ?? "";
|
|
22500
|
+
const resolution = input.approve.resolve.resolution === "approve" || input.approve.resolve.resolution === "edit" ? input.approve.resolve.resolution : input.approve.resolve.resolution === "reject" ? "reject" : void 0;
|
|
22501
|
+
if (resolution === void 0) throw new Error("The stepapprove resolution needs its approve, reject or edit decision.");
|
|
22502
|
+
const surface = surfaceof(input.approve.resolve.surface, "sidepanel");
|
|
22503
|
+
if (!plan || !["pending", "approved"].includes(plan.state)) throw new Error("The stepapprove resolution serves the pending or approved plan under review.");
|
|
22504
|
+
const step = plan.steps.find((candidate) => candidate.id === stepid);
|
|
22505
|
+
if (!step) throw new Error(`No step ${stepid} of the plan ${plan.id} exists to resolve.`);
|
|
22506
|
+
const gate = stepapprovegate({ stepids: [stepid], resolution, surface });
|
|
22507
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
22508
|
+
const record2 = stepresolutionof({ stepid, planid: plan.id, origin: plan.origin, resolution, surface, ...resolution === "edit" && input.approve.resolve.edited !== void 0 ? { edited: input.approve.resolve.edited } : {}, at: now });
|
|
22509
|
+
await memory.addstepapproveresolution(record2);
|
|
22510
|
+
const event = resolutionlogeventof(record2);
|
|
22511
|
+
if (resolution === "edit") {
|
|
22512
|
+
const edited = input.approve.resolve.edited ?? "";
|
|
22513
|
+
try {
|
|
22514
|
+
const shape = JSON.parse(edited);
|
|
22515
|
+
const editedkind = shape.kind;
|
|
22516
|
+
const editedsummary = shape.summary;
|
|
22517
|
+
if (typeof editedkind !== "string" || editedkind.trim() === "" || typeof editedsummary !== "string" || editedsummary.trim() === "") throw new Error("The edited step shape needs its kind and summary.");
|
|
22518
|
+
await memory.setplan({ ...plan, steps: plan.steps.map((candidate) => candidate.id === stepid ? { ...candidate, kind: editedkind, summary: editedsummary, ...shape.target !== void 0 ? { target: shape.target } : {}, ...shape.value !== void 0 ? { value: shape.value } : {}, ...shape.options !== void 0 ? { options: shape.options } : {} } : candidate) });
|
|
22519
|
+
await memory.addcorrection(editedcorrectionof({ origin: plan.origin, kind: step.kind, stepid, original: JSON.stringify({ kind: step.kind, summary: step.summary, ...step.target !== void 0 ? { target: step.target } : {}, ...step.value !== void 0 ? { value: step.value } : {}, ...step.options !== void 0 ? { options: step.options } : {} }), corrected: edited, reason: `The user edited the step ${stepid} from the ${surface} before approving.`, now }));
|
|
22520
|
+
} catch (error) {
|
|
22521
|
+
throw new Error(error instanceof Error ? error.message : "The edited step shape failed to parse.");
|
|
22522
|
+
}
|
|
22523
|
+
}
|
|
22524
|
+
if (resolution === "reject") await memory.addcorrection(rejectedcorrectionof({ origin: plan.origin, kind: step.kind, stepid, original: JSON.stringify({ kind: step.kind, summary: step.summary }), reason: `The user rejected the step ${stepid} from the ${surface}.`, now }));
|
|
22525
|
+
await appendrunevent("review", event.summary, session, plan.origin, stepid);
|
|
22526
|
+
await audit("approval", event.summary, { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid });
|
|
22527
|
+
await broadcastsurfaceframe({ channel: "runstate", surface, summary: `The step ${stepid} resolved with a ${resolution} from the ${surface}.` });
|
|
22528
|
+
return { resolution: record2, cards: plancardsof({ plan: await memory.getplan() ?? plan, corrections: await memory.getcorrections() }) };
|
|
22529
|
+
}
|
|
22530
|
+
if (input.diff !== void 0 && input.diff.preview !== void 0) {
|
|
22531
|
+
const stepid = input.diff.preview.stepid?.trim() ?? "";
|
|
22532
|
+
if (!plan) throw new Error("The diffpreview serves the plan under review.");
|
|
22533
|
+
const step = plan.steps.find((candidate) => candidate.id === stepid);
|
|
22534
|
+
if (!step) throw new Error(`No step ${stepid} of the plan ${plan.id} exists to preview.`);
|
|
22535
|
+
const gate = diffpreviewgate({ risk: step.risk });
|
|
22536
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
22537
|
+
if (!session) throw new Error("The diffpreview needs its session to observe the before state.");
|
|
22538
|
+
const before = input.diff.preview.before ?? {};
|
|
22539
|
+
const options = stepoptions6(step);
|
|
22540
|
+
const predicted = { ...Object.fromEntries(Object.entries(options).filter(([, value]) => typeof value === "string" || typeof value === "number" || typeof value === "boolean").map(([key, value]) => [key, String(value)])), ...step.value !== void 0 ? { value: step.value } : {}, ...step.target !== void 0 ? { target: step.target } : {} };
|
|
22541
|
+
const after = Object.keys(input.diff.preview.after ?? {}).length > 0 ? input.diff.preview.after : predicted;
|
|
22542
|
+
const payload = JSON.stringify({ before, after });
|
|
22543
|
+
let provenance = "inline";
|
|
22544
|
+
if (settings?.diffpreviewbytes !== void 0 && payload.length >= settings.diffpreviewbytes && await offscreengranted()) {
|
|
22545
|
+
try {
|
|
22546
|
+
const answer = await chrome.runtime.sendMessage({ kind: "offscreen", action: "parse", request: { id: randomid(), runid: plan.id, stepid, task: "diffpreview", payload, transferables: [] } });
|
|
22547
|
+
if (answer?.ok === true) provenance = "offscreenworker";
|
|
22548
|
+
} catch {
|
|
22549
|
+
}
|
|
22550
|
+
}
|
|
22551
|
+
const sensitivefields = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])].filter((field) => defaultmaskshapes.some((shape) => field.toLowerCase().includes(shape)));
|
|
22552
|
+
const preview = diffpreviewof({ stepid, before, after, maskverdicts: maskverdictsof({ ...before, ...after }, sensitivefields), provenance });
|
|
22553
|
+
await audit("diff", `The user opened the diffpreview of the write class step ${stepid} of the plan ${plan.id}: ${preview.changes.filter((change) => change.kind === "added").length} added, ${preview.changes.filter((change) => change.kind === "changed").length} changed and ${preview.changes.filter((change) => change.kind === "removed").length} removed field${preview.changes.length === 1 ? "" : "s"}${preview.maskverdicts && Object.keys(preview.maskverdicts).length > 0 ? ` with ${Object.keys(preview.maskverdicts).length} masked value${Object.keys(preview.maskverdicts).length === 1 ? "" : "s"} carrying their mask verdicts` : ""}${provenance === "offscreenworker" ? "; the generation offloaded to the offscreen worker pool" : ""}.`, { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid });
|
|
22554
|
+
return { preview };
|
|
22555
|
+
}
|
|
22556
|
+
if (input.review !== void 0) {
|
|
22557
|
+
const corrections = await memory.getcorrections();
|
|
22558
|
+
const cards = plan ? plancardsof({ plan, corrections }) : [];
|
|
22559
|
+
if (input.review.groups !== void 0 || input.review.cards !== void 0) return { cards, groups: plancardgroups(cards) };
|
|
22560
|
+
return { cards };
|
|
22561
|
+
}
|
|
22562
|
+
if (input.timeline !== void 0 && input.timeline.nodes === true) {
|
|
22563
|
+
if (!plan) return { nodes: [] };
|
|
22564
|
+
const progress = await memory.getprogress();
|
|
22565
|
+
return { nodes: stepstimelinenodes({ plan, ...progress !== void 0 && progress.planid === plan.id ? { progress } : {}, now }) };
|
|
22566
|
+
}
|
|
22567
|
+
if (input.dashboard !== void 0 && input.dashboard.view === true) {
|
|
22568
|
+
const view = await memory.gettransparencyview();
|
|
22569
|
+
const report = transparencyreport({ grants: transparencygrants({ allowlist: view.allowlist, profiles: view.profiles }), windows: windowhistory(view.windows), connectallow: connectallowlist(view.connectallow), permdiffs: view.permdiffs, safedefaults: view.safedefaults, vault: vaultview(view.vault) });
|
|
22570
|
+
const onboarding = await memory.getonboardingstate();
|
|
22571
|
+
return { sessionview: await sessionviewof(), transparency: report, onboarding: onboarding ?? { stepscompleted: [], done: false }, environments: await environmentviewof(), security: await securityviewof() };
|
|
22572
|
+
}
|
|
22573
|
+
if (input.snapshot !== void 0) return await surfacesnapshotof(surfaceof(input.snapshot.surface, "popup"));
|
|
22574
|
+
if (input.settings !== void 0) {
|
|
22575
|
+
const current = settings ?? {};
|
|
22576
|
+
if (input.settings.logstreambuffer !== void 0) {
|
|
22577
|
+
const boundgate = logbufferboundvalid(input.settings.logstreambuffer);
|
|
22578
|
+
if (!boundgate.allowed) throw new Error(boundgate.reason);
|
|
22579
|
+
}
|
|
22580
|
+
if (input.settings.paletterecents !== void 0 && (!Number.isInteger(input.settings.paletterecents) || input.settings.paletterecents < 0)) throw new Error("The palette recent window stays a whole number of commands the user chose.");
|
|
22581
|
+
if (input.settings.taskinputretention !== void 0 && input.settings.taskinputretention <= 0) throw new Error("The taskinput history retention stays a positive user value in milliseconds.");
|
|
22582
|
+
if (input.settings.diffpreviewbytes !== void 0 && input.settings.diffpreviewbytes <= 0) throw new Error("The diffpreview byte ceiling stays a positive user value.");
|
|
22583
|
+
const next = {
|
|
22584
|
+
...current,
|
|
22585
|
+
...input.settings.paletterecents !== void 0 ? { paletterecents: input.settings.paletterecents } : {},
|
|
22586
|
+
...input.settings.logstreambuffer !== void 0 ? { logstreambuffer: input.settings.logstreambuffer } : {},
|
|
22587
|
+
...input.settings.taskinputretention !== void 0 ? { taskinputretention: input.settings.taskinputretention } : {},
|
|
22588
|
+
...input.settings.paletteshortcut !== void 0 ? { paletteshortcut: input.settings.paletteshortcut } : {},
|
|
22589
|
+
...input.settings.diffpreviewbytes !== void 0 ? { diffpreviewbytes: input.settings.diffpreviewbytes } : {}
|
|
22590
|
+
};
|
|
22591
|
+
await memory.setsettings(next);
|
|
22592
|
+
await audit("configure", `The user set the interface surface options${input.settings.paletterecents !== void 0 ? ` with the palette recent window of ${input.settings.paletterecents}` : ""}${input.settings.logstreambuffer !== void 0 ? ` and the logstream live buffer bound of ${input.settings.logstreambuffer}` : ""}${input.settings.paletteshortcut !== void 0 ? ` and the palette shortcut ${input.settings.paletteshortcut}` : ""}${input.settings.diffpreviewbytes !== void 0 ? ` and the diffpreview byte ceiling of ${input.settings.diffpreviewbytes}` : ""}; every write takes effect without reloading the extension.`, { ...session ? { sessionid: session.id } : {} });
|
|
22593
|
+
await broadcastsurfaceframe({ channel: "settings", surface: "optionspage", summary: "The interface surface options changed and take effect without a reload." });
|
|
22594
|
+
return { settings: next };
|
|
22595
|
+
}
|
|
22596
|
+
throw new Error("The surface command carries no palette, task, onboarding, bus, broadcast, layout, logstream, approve, diff, review, timeline, dashboard, snapshot or settings action.");
|
|
22597
|
+
}
|
|
22598
|
+
async function updatestatusbadge() {
|
|
22599
|
+
try {
|
|
22600
|
+
const plan = await memory.getplan();
|
|
22601
|
+
const progress = await memory.getprogress();
|
|
22602
|
+
const waitingcount = plan !== void 0 && progress !== void 0 && progress.planid === plan.id ? Object.keys(progress.gatewaits ?? {}).length : 0;
|
|
22603
|
+
const state = statusbadgeof({ ...plan !== void 0 && (plan.state === "pending" || plan.state === "approved") ? { planstate: plan.state } : {}, waitingcount, ...plan !== void 0 ? { runid: plan.id } : {} });
|
|
22604
|
+
await chrome.action.setBadgeText({ text: badgetextof(state) });
|
|
22605
|
+
await chrome.action.setBadgeBackgroundColor({ color: badgecolorof(state) });
|
|
22606
|
+
} catch {
|
|
22607
|
+
}
|
|
22608
|
+
}
|
|
22609
|
+
function windowmatchmedia() {
|
|
22610
|
+
const query = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
|
|
22611
|
+
return query?.matches === true ? "dark" : "light";
|
|
22612
|
+
}
|
|
22613
|
+
async function handlesurfaceviewcommand(message) {
|
|
22614
|
+
const input = message;
|
|
22615
|
+
const now = Date.now();
|
|
22616
|
+
const session = await memory.getsession();
|
|
22617
|
+
const sessionactive = Boolean(session && !session.stoppedat && session.expiresat > now);
|
|
22618
|
+
const settings = await memory.getsettings();
|
|
22619
|
+
const plan = await memory.getplan();
|
|
22620
|
+
const grantedorigins = session ? [.../* @__PURE__ */ new Set([session.origin, ...session.grants ?? []])] : [];
|
|
22621
|
+
const surfaceof = (value, fallback) => ["popup", "sidepanel", "dashboardpage", "optionspage", "onboarding", "omnibox", "page"].includes(value ?? "") ? value : fallback;
|
|
22622
|
+
if (input.datagrid !== void 0) {
|
|
22623
|
+
if (input.datagrid.view !== void 0) {
|
|
22624
|
+
const rows = input.datagrid.view.rows ?? [];
|
|
22625
|
+
if (rows.length === 0) throw new Error("The datagrid view needs at least one extracted row.");
|
|
22626
|
+
const view = datagridof({ title: input.datagrid.view.title ?? "Extraction result", origin: session?.origin ?? "", runid: plan?.id ?? "", rows, at: now });
|
|
22627
|
+
await audit("datagrid", `The user opened the datagrid ${view.id} of ${view.rows.length} row${view.rows.length === 1 ? "" : "s"} and ${view.columns.length} inferred column${view.columns.length === 1 ? "" : "s"}; the grid previews the extraction result before any export.`, { ...session ? { sessionid: session.id } : {} });
|
|
22628
|
+
return { view, menu: exportmenudescriptors() };
|
|
22629
|
+
}
|
|
22630
|
+
if (input.datagrid.sort !== void 0) return { hint: "The datagrid sort runs inside the surface module on the opened view; the sort needs its view id and its column field." };
|
|
22631
|
+
if (input.datagrid.filter !== void 0) return { hint: "The datagrid filter runs locally inside the surface module; no row ever leaves the surface to filter." };
|
|
22632
|
+
if (input.datagrid.select !== void 0) return { hint: "The row range selection marks the partial export scope inside the surface module." };
|
|
22633
|
+
}
|
|
22634
|
+
if (input.export !== void 0) {
|
|
22635
|
+
if (input.export.menu === true) return { menu: exportmenudescriptors() };
|
|
22636
|
+
if (input.export.run !== void 0) {
|
|
22637
|
+
const format = input.export.run.format === "json" ? "json" : input.export.run.format === "clipboard" ? "clipboard" : "csv";
|
|
22638
|
+
const scope = input.export.run.scope === "selection" ? "selection" : input.export.run.scope === "step" ? "step" : "run";
|
|
22639
|
+
await audit("datagrid", `The user ran the ${format} export of the ${scope} scope; the masked values only rule honors the maskinputs verdicts of every sensitive field shape.`, { ...session ? { sessionid: session.id } : {} });
|
|
22640
|
+
return { hint: "The export renders inside the surface module on the datagrid view the surface holds; the background never rebuilds the masked values twice.", format, scope };
|
|
22641
|
+
}
|
|
22642
|
+
}
|
|
22643
|
+
if (input.quickaction !== void 0) {
|
|
22644
|
+
const origin = input.quickaction.list?.origin?.trim() || session?.origin || "";
|
|
22645
|
+
const capabilities = await grantedcapabilities();
|
|
22646
|
+
const actions = quickactionsfor(quickactioncatalog(), { origin, granted: grantedorigins, sessionactive, grantedcapabilities: capabilities });
|
|
22647
|
+
if (input.quickaction.surface === true) {
|
|
22648
|
+
await audit("quickaction", `The ${origin || "originless"} tab lists ${actions.length} permitted quickaction${actions.length === 1 ? "" : "s"}; only the actions the origin allowlist and the capability set permit register.`, { ...session ? { sessionid: session.id } : {} });
|
|
22649
|
+
}
|
|
22650
|
+
return { actions, origin };
|
|
22651
|
+
}
|
|
22652
|
+
if (input.shortcut !== void 0) {
|
|
22653
|
+
const stored = await memory.getshortcutbindings();
|
|
22654
|
+
const bindings = stored.length > 0 ? stored : shortcutdefaults();
|
|
22655
|
+
if (input.shortcut.edit !== void 0) {
|
|
22656
|
+
const command = input.shortcut.edit.command?.trim() ?? "";
|
|
22657
|
+
const text2 = input.shortcut.edit.text?.trim() ?? "";
|
|
22658
|
+
const edited = shortcutbindingafter(bindings, command, text2);
|
|
22659
|
+
await memory.setshortcutbindings(edited);
|
|
22660
|
+
await audit("shortcut", `The user edited the ${command} shortcut to ${text2}; the binding stays user editable and the command keeps its palette gates.`, { ...session ? { sessionid: session.id } : {} });
|
|
22661
|
+
return { bindings: edited };
|
|
22662
|
+
}
|
|
22663
|
+
if (input.shortcut.match !== void 0) {
|
|
22664
|
+
const key = input.shortcut.match.key ?? "";
|
|
22665
|
+
const modifiers = input.shortcut.match.modifiers ?? [];
|
|
22666
|
+
const surface = surfaceof(input.shortcut.match.surface, "popup");
|
|
22667
|
+
const command = shortcutcommandof(bindings, { key, modifiers, surface });
|
|
22668
|
+
if (command !== void 0) {
|
|
22669
|
+
const entries = palettecommandsof(surfacepalette(), { granted: await grantedcapabilities(), sessionactive });
|
|
22670
|
+
const dispatchable = shortcutdispatchable(command, entries, { granted: await grantedcapabilities(), sessionactive });
|
|
22671
|
+
await audit("shortcut", `The ${surface} pressed ${[...modifiers, key].join("+")} and the ${command} command matched${dispatchable ? "; the palette action gate allows the dispatch" : "; the palette action gate refuses the dispatch"}.`, { ...session ? { sessionid: session.id } : {} });
|
|
22672
|
+
return { command, dispatchable };
|
|
22673
|
+
}
|
|
22674
|
+
return { command: void 0, dispatchable: false };
|
|
22675
|
+
}
|
|
22676
|
+
return { bindings: bindings.map((binding) => ({ ...binding, display: shortcuttext(binding) })) };
|
|
22677
|
+
}
|
|
22678
|
+
if (input.omnibox !== void 0 && input.omnibox.parse !== void 0) {
|
|
22679
|
+
const text2 = input.omnibox.parse.text ?? "";
|
|
22680
|
+
const origin = session?.origin ?? "";
|
|
22681
|
+
const gate = omniboxtaskgate({ text: text2, origin, direct: false });
|
|
22682
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
22683
|
+
const submission = parseomniboxtask({ text: text2, origin, at: now });
|
|
22684
|
+
const taskinput = omniboxtasktotaskinput(submission);
|
|
22685
|
+
await memory.addtaskinput(taskinput);
|
|
22686
|
+
const proposed = await propose(taskinput.text, false);
|
|
22687
|
+
await audit("omnibox", `The omnibox keyword parsed into the taskinput ${submission.id} for ${origin} and routed through the same proposal flow as the api; the plan ${proposed.id} awaits its plancard review.`, { ...session ? { sessionid: session.id } : {}, planid: proposed.id });
|
|
22688
|
+
await broadcastsurfaceframe({ channel: "runstate", surface: "omnibox", summary: `An omnibox goal became the plan ${proposed.id} and awaits review.` });
|
|
22689
|
+
return { submission, plan: proposed };
|
|
22690
|
+
}
|
|
22691
|
+
if (input.badge !== void 0) {
|
|
22692
|
+
await updatestatusbadge();
|
|
22693
|
+
const progress = await memory.getprogress();
|
|
22694
|
+
const waitingcount = plan !== void 0 && progress !== void 0 && progress.planid === plan.id ? Object.keys(progress.gatewaits ?? {}).length : 0;
|
|
22695
|
+
const state = statusbadgeof({ ...plan !== void 0 && (plan.state === "pending" || plan.state === "approved") ? { planstate: plan.state } : {}, waitingcount, ...plan !== void 0 ? { runid: plan.id } : {} });
|
|
22696
|
+
return { badge: state, text: badgetextof(state), color: badgecolorof(state) };
|
|
22697
|
+
}
|
|
22698
|
+
if (input.notify !== void 0) {
|
|
22699
|
+
const prefs = await memory.getnotificationprefs();
|
|
22700
|
+
if (input.notify.consent !== void 0 || input.notify.enabled !== void 0) {
|
|
22701
|
+
const next = { consent: input.notify.consent === true || prefs?.consent === true, enabled: input.notify.enabled === void 0 ? prefs?.enabled !== false : input.notify.enabled };
|
|
22702
|
+
await memory.setnotificationprefs(next);
|
|
22703
|
+
await audit("notify", `The user set the notification preference${input.notify.consent !== void 0 ? ` with the page content consent ${next.consent ? "granted" : "withheld"}` : ""}${input.notify.enabled !== void 0 ? ` and the notifications ${next.enabled ? "on" : "off"}` : ""}; a content bearing body never shows without its consent.`, { ...session ? { sessionid: session.id } : {} });
|
|
22704
|
+
return { prefs: next };
|
|
22705
|
+
}
|
|
22706
|
+
if (input.notify.done !== void 0) {
|
|
22707
|
+
const runid = input.notify.done.runid?.trim() || plan?.id || "";
|
|
22708
|
+
if (runid === "") throw new Error("The done notification needs its run id.");
|
|
22709
|
+
const payload = notifydoneof({ runid, origin: session?.origin ?? "", summary: input.notify.done.summary ?? "", at: now });
|
|
22710
|
+
await memory.addnotificationhistory(payload);
|
|
22711
|
+
await updatestatusbadge();
|
|
22712
|
+
await broadcastsurfaceframe({ channel: "runstate", surface: "background", summary: `The run ${runid} completed; the deep link ${payload.deeplink} opens its runsummary.` });
|
|
22713
|
+
await audit("notify", `The run ${runid} completed and its done notification carries the deep link ${payload.deeplink} to the runsummary; the body carries no page content so no consent is needed.`, { ...session ? { sessionid: session.id } : {} });
|
|
22714
|
+
return { payload, dnd: notificationrespectsdnd(payload, input.notify.dnd === true) };
|
|
22715
|
+
}
|
|
22716
|
+
if (input.notify.attention !== void 0) {
|
|
22717
|
+
const stepid = input.notify.attention.stepid?.trim() ?? "";
|
|
22718
|
+
if (stepid === "") throw new Error("The attention notification needs its waiting step.");
|
|
22719
|
+
const contentgate = notificationcontentgate({ content: input.notify.attention.content === true, consent: prefs?.consent === true || input.notify.attention.content !== true });
|
|
22720
|
+
if (!contentgate.allowed) throw new Error(contentgate.reason);
|
|
22721
|
+
const payload = notifyattentionof({ runid: input.notify.attention.runid?.trim() || plan?.id || "", stepid, cause: input.notify.attention.cause === "phishguard" ? "phishguard" : input.notify.attention.cause === "deferral" ? "deferral" : "gatewait", reason: input.notify.attention.reason ?? "The run waits for a human.", ...input.notify.attention.content === true ? { content: true } : {}, consent: prefs?.consent === true, at: now });
|
|
22722
|
+
await memory.addnotificationhistory(payload);
|
|
22723
|
+
await updatestatusbadge();
|
|
22724
|
+
await broadcastsurfaceframe({ channel: "runstate", surface: "background", summary: `The step ${stepid} needs attention; the deep link ${payload.deeplink} opens the exact waiting step.` });
|
|
22725
|
+
await audit("notify", `The step ${stepid} of the run ${payload.runid} needs attention (${payload.title.toLowerCase()}); the deep link ${payload.deeplink} opens the exact waiting step${input.notify.dnd === true ? " while the os do not disturb state holds the toast in the history" : ""}.`, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid });
|
|
22726
|
+
return { payload, dnd: notificationrespectsdnd(payload, input.notify.dnd === true) };
|
|
22727
|
+
}
|
|
22728
|
+
if (input.notify.history === true) return { history: await memory.getnotificationhistory() };
|
|
22729
|
+
return { prefs: prefs ?? { consent: false, enabled: true } };
|
|
22730
|
+
}
|
|
22731
|
+
if (input.recent !== void 0) {
|
|
22732
|
+
if (input.recent.add !== void 0) {
|
|
22733
|
+
const runid = input.recent.add.runid?.trim() ?? "";
|
|
22734
|
+
if (runid === "") throw new Error("The recenttray entry needs its run id.");
|
|
22735
|
+
const outcome = input.recent.add.outcome === "completed" ? "completed" : input.recent.add.outcome === "halted" ? "halted" : input.recent.add.outcome === "failed" ? "failed" : "running";
|
|
22736
|
+
const entry = recenttrayentryof({ runid, origin: input.recent.add.origin?.trim() || session?.origin || "", outcome, title: input.recent.add.title ?? "", at: now });
|
|
22737
|
+
await memory.addrecenttrayentry(entry);
|
|
22738
|
+
await audit("recent", `The recenttray recorded the run ${runid} with its ${outcome} outcome${settings?.recenttraydepth !== void 0 ? ` inside the user depth of ${settings.recenttraydepth}` : ""}; a halted run offers resume and a completed run offers reopen.`, { ...session ? { sessionid: session.id } : {} });
|
|
22739
|
+
return { tray: await memory.getrecenttray() };
|
|
22740
|
+
}
|
|
22741
|
+
if (input.recent.action !== void 0) {
|
|
22742
|
+
const runid = input.recent.action.runid?.trim() ?? "";
|
|
22743
|
+
const entry = (await memory.getrecenttray()).find((candidate) => candidate.runid === runid);
|
|
22744
|
+
if (entry === void 0) throw new Error(`The recenttray knows no run ${runid}.`);
|
|
22745
|
+
const actions = recenttrayactions(entry);
|
|
22746
|
+
await audit("recent", `The user read the actions of the run ${runid} from the recenttray: ${actions.length === 0 ? "no action offers while the run stays live" : actions.join(" and ")}.`, { ...session ? { sessionid: session.id } : {} });
|
|
22747
|
+
return { actions };
|
|
22748
|
+
}
|
|
22749
|
+
return { tray: await memory.getrecenttray() };
|
|
22750
|
+
}
|
|
22751
|
+
if (input.picker !== void 0) {
|
|
22752
|
+
if (input.picker.start !== void 0) {
|
|
22753
|
+
const candidates = (input.picker.start.candidates ?? []).map((candidate) => pickercandidateof({ selector: candidate.selector ?? "", ...candidate.text !== void 0 ? { text: candidate.text } : {}, ...candidate.role !== void 0 ? { role: candidate.role } : {}, hasid: candidate.hasid === true, hasstableattributes: candidate.hasstableattributes === true, hasrole: candidate.hasrole === true, textunique: candidate.textunique === true }));
|
|
22754
|
+
const picker = pickersessionstart({ origin: session?.origin ?? "", granted: grantedorigins, candidates, at: now });
|
|
22755
|
+
await audit("picker", `The sidepanel started the picker session ${picker.id} on the granted origin ${picker.origin} with ${picker.candidates.length} stability scored candidate${picker.candidates.length === 1 ? "" : "s"}.`, { ...session ? { sessionid: session.id } : {} });
|
|
22756
|
+
return { picker, tips: guidedtips() };
|
|
22757
|
+
}
|
|
22758
|
+
if (input.picker.lock !== void 0) {
|
|
22759
|
+
const stepid = input.picker.lock.stepid?.trim() ?? "";
|
|
22760
|
+
const candidateindex = input.picker.lock.candidateindex ?? 0;
|
|
22761
|
+
if (stepid === "") throw new Error("The candidate lock needs its step.");
|
|
22762
|
+
return { hint: "The candidate lock binds one candidate of the open picker session inside the surface module; the locked selector rides the proposed step for its review.", stepid, candidateindex };
|
|
22763
|
+
}
|
|
22764
|
+
}
|
|
22765
|
+
if (input.halo !== void 0) {
|
|
22766
|
+
const halo = haloof({ stepid: input.halo.stepid?.trim() ?? "", selector: input.halo.selector ?? "", rect: { x: input.halo.rect?.x ?? 0, y: input.halo.rect?.y ?? 0, width: input.halo.rect?.width ?? 0, height: input.halo.rect?.height ?? 0 }, state: input.halo.state === "running" ? "running" : input.halo.state === "waiting" ? "waiting" : input.halo.state === "done" ? "done" : input.halo.state === "failed" ? "failed" : input.halo.state === "halted" ? "halted" : "pending" });
|
|
22767
|
+
return { halo, color: halocolorof(halo.state) };
|
|
22768
|
+
}
|
|
22769
|
+
if (input.tips !== void 0) {
|
|
22770
|
+
const tips = guidedtips();
|
|
22771
|
+
if (input.tips.dismiss !== void 0) {
|
|
22772
|
+
const dismissed = guidedtipdismiss(tips, (await memory.getsurfacelayout("optionspage"))?.preferences.dismissedtips?.split(",").filter((id) => id !== "") ?? [], input.tips.dismiss.tipid?.trim() ?? "");
|
|
22773
|
+
await memory.setsurfacelayout({ surface: "optionspage", preferences: { dismissedtips: dismissed.join(",") }, updatedat: now });
|
|
22774
|
+
await audit("picker", `The user dismissed the ${input.tips.dismiss.tipid} guidedtip; the optionspage recalls every dismissed tip on demand.`, { ...session ? { sessionid: session.id } : {} });
|
|
22775
|
+
return { tips, dismissed };
|
|
22776
|
+
}
|
|
22777
|
+
if (input.tips.recall === true) {
|
|
22778
|
+
const recalled = guidedtiprecall((await memory.getsurfacelayout("optionspage"))?.preferences.dismissedtips?.split(",").filter((id) => id !== "") ?? []);
|
|
22779
|
+
await memory.setsurfacelayout({ surface: "optionspage", preferences: { dismissedtips: "" }, updatedat: now });
|
|
22780
|
+
return { tips, dismissed: recalled };
|
|
22781
|
+
}
|
|
22782
|
+
return { tips, dismissed: (await memory.getsurfacelayout("optionspage"))?.preferences.dismissedtips?.split(",").filter((id) => id !== "") ?? [] };
|
|
22783
|
+
}
|
|
22784
|
+
if (input.shotpanel !== void 0) {
|
|
22785
|
+
if (input.shotpanel.open !== void 0) {
|
|
22786
|
+
const view = shotpanelof({ stepid: input.shotpanel.open.stepid?.trim() ?? "", runid: plan?.id ?? "", captureid: input.shotpanel.open.captureid?.trim() ?? "", provenance: input.shotpanel.open.provenance === "fullpage" ? "fullpage" : input.shotpanel.open.provenance === "element" ? "element" : input.shotpanel.open.provenance === "region" ? "region" : "viewport", origin: session?.origin ?? "", granted: grantedorigins, at: now });
|
|
22787
|
+
await audit("shotpanel", `The user opened the shotpanel of the capture ${view.captureid} (${view.provenance}) of the step ${view.stepid}; the capture origin holds its allowlist entry and the redaction verdicts render beside the preview.`, { ...session ? { sessionid: session.id } : {} });
|
|
22788
|
+
return { view };
|
|
22789
|
+
}
|
|
22790
|
+
return { hint: "The zoom and pan run inside the surface module on the opened shotpanel view." };
|
|
22791
|
+
}
|
|
22792
|
+
if (input.compare !== void 0) {
|
|
22793
|
+
if (input.compare.pair !== void 0) {
|
|
22794
|
+
const pair = comparepairof({ stepid: input.compare.pair.stepid?.trim() ?? "", beforecaptureid: input.compare.pair.beforecaptureid?.trim() ?? "", aftercaptureid: input.compare.pair.aftercaptureid?.trim() ?? "" });
|
|
22795
|
+
return { pair };
|
|
22796
|
+
}
|
|
22797
|
+
return { hint: "The compareviewer pairs the before and after captures of every executed write step inside the surface module; the slider overlays the two captures." };
|
|
22798
|
+
}
|
|
22799
|
+
if (input.siteprofile !== void 0) {
|
|
22800
|
+
if (input.siteprofile.save !== void 0) {
|
|
22801
|
+
const origin = input.siteprofile.save.origin?.trim() || session?.origin || "";
|
|
22802
|
+
const profile = siteprofileof({ origin, ...input.siteprofile.save.theme === "dark" || input.siteprofile.save.theme === "light" || input.siteprofile.save.theme === "system" ? { theme: input.siteprofile.save.theme } : {}, ...input.siteprofile.save.defaultview !== void 0 ? { defaultview: input.siteprofile.save.defaultview } : {}, at: now });
|
|
22803
|
+
const profiles = [...(await memory.listsiteprofiles()).filter((candidate) => candidate.origin !== profile.origin), profile];
|
|
22804
|
+
await memory.setsiteprofile(profile);
|
|
22805
|
+
await memory.setsiteprofiles(profiles);
|
|
22806
|
+
await audit("siteprofile", `The user saved the siteprofile of ${profile.origin}${profile.theme !== void 0 ? ` with the ${profile.theme} theme` : ""}${profile.defaultview !== void 0 ? ` and the ${profile.defaultview} default view` : ""}; the profile adjusts interface preferences only and never a policy gate.`, { ...session ? { sessionid: session.id } : {} });
|
|
22807
|
+
return { profile, profiles };
|
|
22808
|
+
}
|
|
22809
|
+
if (input.siteprofile.get !== void 0) {
|
|
22810
|
+
const origin = input.siteprofile.get.origin?.trim() || session?.origin || "";
|
|
22811
|
+
const profiles = await memory.listsiteprofiles();
|
|
22812
|
+
return { profile: siteprofilefor(profiles, origin), active: profiles.some((profile) => siteprofileactive(profile, origin)) };
|
|
22813
|
+
}
|
|
22814
|
+
return { profiles: await memory.listsiteprofiles() };
|
|
22815
|
+
}
|
|
22816
|
+
if (input.theme !== void 0) {
|
|
22817
|
+
const ospreference = input.theme.ospreference === "dark" ? "dark" : input.theme.ospreference === "light" ? "light" : windowmatchmedia();
|
|
22818
|
+
const preference = input.theme.preference === "dark" || input.theme.preference === "light" || input.theme.preference === "system" ? input.theme.preference : await memory.getthemepreference();
|
|
22819
|
+
if (preference !== void 0 && input.theme.preference !== void 0) await memory.setthemepreference(preference);
|
|
22820
|
+
const profile = session ? siteprofilefor(await memory.listsiteprofiles(), session.origin) : void 0;
|
|
22821
|
+
const appearance = resolveappearance({ ospreference, ...preference !== void 0 ? { useroverride: preference } : {}, ...profile !== void 0 ? { siteprofile: profile } : {} });
|
|
22822
|
+
if (input.theme.preference !== void 0) await audit("theme", `The user set the ${preference} theme preference; the resolved appearance stays ${appearance.mode} from ${appearance.source} and the tokens cover every surface including the dashboardpage.`, { ...session ? { sessionid: session.id } : {} });
|
|
22823
|
+
return { appearance, ospreference, ...preference !== void 0 ? { preference } : {} };
|
|
22824
|
+
}
|
|
22825
|
+
if (input.locale !== void 0) {
|
|
22826
|
+
const bundles = localebundles();
|
|
22827
|
+
const language = settings?.uilanguage ?? "en";
|
|
22828
|
+
if (input.locale.string !== void 0) return { value: localestring(bundles, language, input.locale.string.key ?? "") };
|
|
22829
|
+
if (input.locale.format !== void 0) {
|
|
22830
|
+
const kind = input.locale.format.kind === "date" ? "date" : input.locale.format.kind === "duration" ? "duration" : "number";
|
|
22831
|
+
return { value: localeformat({ language, value: input.locale.format.value ?? 0, kind }) };
|
|
22832
|
+
}
|
|
22833
|
+
return { bundles, languages: supportedlanguages(bundles), language };
|
|
22834
|
+
}
|
|
22835
|
+
if (input.importexport !== void 0) {
|
|
22836
|
+
if (input.importexport.export === true) {
|
|
22837
|
+
const payload = importexportpayloadof({ profile: "profile", originprofiles: [], siteprofiles: (await memory.listsiteprofiles()).map((profile) => ({ origin: profile.origin, ...profile.theme !== void 0 ? { theme: profile.theme } : {}, ...profile.defaultview !== void 0 ? { defaultview: profile.defaultview } : {} })), notes: (await memory.getsitenotes()).map((note) => ({ origin: note.origin, title: note.title, sensitive: note.sensitive })), preferences: { ...settings ?? {} }, at: now });
|
|
22838
|
+
await audit("importexport", `The user exported the settings bundle with ${payload.contents.originprofiles.length} origin profile${payload.contents.originprofiles.length === 1 ? "" : "s"}, ${payload.contents.siteprofiles.length} site profile${payload.contents.siteprofiles.length === 1 ? "" : "s"} and ${payload.contents.notes.length} note${payload.contents.notes.length === 1 ? "" : "s"}; ${payload.exclusions.join(" and ")} never enter any bundle.`, { ...session ? { sessionid: session.id } : {} });
|
|
22839
|
+
return { payload };
|
|
22840
|
+
}
|
|
22841
|
+
if (input.importexport.validate !== void 0) {
|
|
22842
|
+
const validation = importexportvalidate(input.importexport.validate);
|
|
22843
|
+
await audit("importexport", `The import bundle validation ${validation.ok ? "passed" : "refused"}: ${validation.reason}`, { ...session ? { sessionid: session.id } : {} });
|
|
22844
|
+
return validation;
|
|
22845
|
+
}
|
|
22846
|
+
if (input.importexport.apply !== void 0) {
|
|
22847
|
+
const current = settings ?? {};
|
|
22848
|
+
const applied = applyimport(input.importexport.apply, current);
|
|
22849
|
+
await memory.setsettings(applied.preferences);
|
|
22850
|
+
await audit("importexport", `The user imported ${applied.applied.length} preference key${applied.applied.length === 1 ? "" : "s"}; the secrets exclusion list stays untouched because no secret ever rides a bundle.`, { ...session ? { sessionid: session.id } : {} });
|
|
22851
|
+
await broadcastsurfaceframe({ channel: "settings", surface: "optionspage", summary: "An importexport bundle applied its preferences." });
|
|
22852
|
+
return applied;
|
|
22853
|
+
}
|
|
22854
|
+
}
|
|
22855
|
+
if (input.dropimport !== void 0 && input.dropimport.file !== void 0) {
|
|
22856
|
+
const sessionfile = dropimportof({ filename: input.dropimport.file.filename ?? "", bytes: input.dropimport.file.bytes ?? 0, head: input.dropimport.file.head ?? "", at: now });
|
|
22857
|
+
await audit("dropimport", `The user dropped ${sessionfile.filename} (${sessionfile.bytes} byte${sessionfile.bytes === 1 ? "" : "s"}) and the detection named the ${sessionfile.kind} kind; the import path takes the file from here.`, { ...session ? { sessionid: session.id } : {} });
|
|
22858
|
+
return { session: sessionfile };
|
|
22859
|
+
}
|
|
22860
|
+
if (input.tour !== void 0) {
|
|
22861
|
+
const stops = featuretourordered(featuretourstops());
|
|
22862
|
+
if (input.tour.replay === true) {
|
|
22863
|
+
const replayed = await handlerequest({ kind: "surface", onboarding: { replay: true } }, {});
|
|
22864
|
+
void replayed;
|
|
22865
|
+
await audit("tour", `The user replayed the featuretour with ${stops.length} stop${stops.length === 1 ? "" : "s"} across the popup, the sidepanel and the dashboardpage, including the datagrid, the compareviewer and the pickeroverlay stops.`, { ...session ? { sessionid: session.id } : {} });
|
|
22866
|
+
return { stops };
|
|
22867
|
+
}
|
|
22868
|
+
return { stops };
|
|
22869
|
+
}
|
|
22870
|
+
if (input.a11y !== void 0) {
|
|
22871
|
+
if (input.a11y.localized !== void 0) {
|
|
22872
|
+
const surface = surfaceof(input.a11y.localized.surface, "popup");
|
|
22873
|
+
const language = input.a11y.localized.language ?? settings?.uilanguage ?? "en";
|
|
22874
|
+
return { labels: a11ylabelslocalizedfor(surface, localebundles(), language), surface, language };
|
|
22875
|
+
}
|
|
22876
|
+
return { labels: a11ylabelsfor(surfaceof(input.a11y.labels?.surface, "popup")) };
|
|
22877
|
+
}
|
|
22878
|
+
if (input.chip !== void 0) {
|
|
22879
|
+
if (input.chip.open !== void 0) {
|
|
22880
|
+
const chip = pagechipof({ stepid: input.chip.open.stepid?.trim() ?? "", selector: input.chip.open.selector?.trim() ?? "", origin: session?.origin ?? "", at: now });
|
|
22881
|
+
await audit("pagechip", `The pagechip ${chip.id} anchored to ${chip.selector} renders the inline confirmation of the gated step ${chip.stepid} on the page.`, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid: chip.stepid });
|
|
22882
|
+
return { chip };
|
|
22883
|
+
}
|
|
22884
|
+
if (input.chip.resolve !== void 0) {
|
|
22885
|
+
const resolution = input.chip.resolve.resolution === "approve" ? "approve" : input.chip.resolve.resolution === "reject" ? "reject" : void 0;
|
|
22886
|
+
if (resolution === void 0) throw new Error("The pagechip resolution needs its approve or reject decision.");
|
|
22887
|
+
const surface = surfaceof(input.chip.resolve.surface, "page");
|
|
22888
|
+
const chip = pagechipof({ stepid: input.chip.resolve.stepid?.trim() ?? "", selector: input.chip.resolve.selector?.trim() ?? "", origin: input.chip.resolve.origin?.trim() || session?.origin || "", at: now });
|
|
22889
|
+
const resolved = pagechipresolve(chip, resolution, surface, now);
|
|
22890
|
+
await appendrunevent("review", resolved.logevent.summary, session, chip.origin, chip.stepid);
|
|
22891
|
+
await audit("pagechip", resolved.logevent.summary, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid: chip.stepid });
|
|
22892
|
+
await broadcastsurfaceframe({ channel: "runstate", surface, summary: `The step ${chip.stepid} resolved with a ${resolution} from the pagechip.` });
|
|
22893
|
+
return { chip: resolved.chip, logevent: resolved.logevent };
|
|
22894
|
+
}
|
|
22895
|
+
}
|
|
22896
|
+
if (input.toast !== void 0) {
|
|
22897
|
+
if (input.toast.step !== void 0) {
|
|
22898
|
+
const toast = stetoastof({ stepid: input.toast.step.stepid?.trim() ?? "", kind: input.toast.step.kind ?? "", durationms: input.toast.step.durationms ?? 0, at: now });
|
|
22899
|
+
const livecount = settings?.toastlivecount;
|
|
22900
|
+
const stacked = stetoaststackafter([], toast, livecount);
|
|
22901
|
+
await broadcastsurfaceframe({ channel: "logstream", surface: "background", summary: `The step ${toast.stepid} (${toast.kind}) completed in ${toast.durationms} milliseconds.` });
|
|
22902
|
+
await audit("toast", `The step ${toast.stepid} of the kind ${toast.kind} completed in ${toast.durationms} milliseconds; the steteoast confirms it${livecount !== void 0 ? ` inside the user live count of ${livecount}` : ""}.`, { ...session ? { sessionid: session.id } : {}, stepid: toast.stepid });
|
|
22903
|
+
return { toast, live: stacked.live, history: stetoasthistory(stacked.history) };
|
|
22904
|
+
}
|
|
22905
|
+
return { hint: "The steteoast stack keeps its bounded live count inside the surface module while the full history stays queryable." };
|
|
22906
|
+
}
|
|
22907
|
+
if (input.settings !== void 0) {
|
|
22908
|
+
const current = settings ?? {};
|
|
22909
|
+
if (input.settings.recenttraydepth !== void 0 && (!Number.isInteger(input.settings.recenttraydepth) || input.settings.recenttraydepth <= 0)) throw new Error("The recenttray depth stays a positive whole number of runs the user chose; no engine cap exists.");
|
|
22910
|
+
if (input.settings.toastlivecount !== void 0 && (!Number.isInteger(input.settings.toastlivecount) || input.settings.toastlivecount <= 0)) throw new Error("The steteoast live count stays a positive whole number the user chose; no engine cap exists.");
|
|
22911
|
+
const next = {
|
|
22912
|
+
...current,
|
|
22913
|
+
...input.settings.recenttraydepth !== void 0 ? { recenttraydepth: input.settings.recenttraydepth } : {},
|
|
22914
|
+
...input.settings.notifyconsent !== void 0 ? { notifyconsent: input.settings.notifyconsent } : {},
|
|
22915
|
+
...input.settings.notifyenabled !== void 0 ? { notifyenabled: input.settings.notifyenabled } : {},
|
|
22916
|
+
...input.settings.themepreference === "dark" || input.settings.themepreference === "light" || input.settings.themepreference === "system" ? { themepreference: input.settings.themepreference } : {},
|
|
22917
|
+
...input.settings.uilanguage !== void 0 ? { uilanguage: input.settings.uilanguage } : {},
|
|
22918
|
+
...input.settings.toastlivecount !== void 0 ? { toastlivecount: input.settings.toastlivecount } : {}
|
|
22919
|
+
};
|
|
22920
|
+
await memory.setsettings(next);
|
|
22921
|
+
await audit("configure", `The user set the interface finishing options${input.settings.recenttraydepth !== void 0 ? ` with the recenttray depth of ${input.settings.recenttraydepth}` : ""}${input.settings.themepreference !== void 0 ? ` and the ${input.settings.themepreference} theme preference` : ""}${input.settings.uilanguage !== void 0 ? ` and the ${input.settings.uilanguage} interface language` : ""}${input.settings.notifyconsent !== void 0 ? ` and the notification content consent ${input.settings.notifyconsent ? "granted" : "withheld"}` : ""}${input.settings.toastlivecount !== void 0 ? ` and the steteoast live count of ${input.settings.toastlivecount}` : ""}; every write takes effect without reloading the extension.`, { ...session ? { sessionid: session.id } : {} });
|
|
22922
|
+
await broadcastsurfaceframe({ channel: "settings", surface: "optionspage", summary: "The interface finishing options changed and take effect without a reload." });
|
|
22923
|
+
return { settings: next };
|
|
22924
|
+
}
|
|
22925
|
+
throw new Error("The views command carries no datagrid, export, quickaction, shortcut, omnibox, badge, notify, recent, picker, halo, tips, shotpanel, compare, siteprofile, theme, locale, importexport, dropimport, tour, a11y, chip, toast or settings action.");
|
|
22926
|
+
}
|
|
21374
22927
|
async function handlerequest(message, sender) {
|
|
21375
22928
|
const originverdict = origincheckof({ ...sender.id !== void 0 ? { senderid: sender.id } : {}, ...sender.origin !== void 0 ? { senderorigin: sender.origin } : {}, extensionid: chrome.runtime.id, connectallow: await memory.getconnectallow() });
|
|
21376
22929
|
const inboundgate = origincheckgate({ verdict: originverdict });
|
|
@@ -21506,7 +23059,7 @@ async function handlerequest(message, sender) {
|
|
|
21506
23059
|
const livetab = session ? await chrome.tabs.get(session.tabid).catch(() => void 0) : void 0;
|
|
21507
23060
|
const waitprofile = session ? waitprofiles.find((record2) => record2.origin === session.origin) : void 0;
|
|
21508
23061
|
const livestate = { phase: livetab?.status === "loading" ? "loading" : "complete", ...navrecords[0] ? { finalurl: navrecords[0].finalurl, redirects: navrecords[0].chain } : {} };
|
|
21509
|
-
return { config: await memory.getconfig(), session, plan, progress: plan && progress?.planid === plan.id ? progress : void 0, diagnostic: await memory.getdiagnostic(), audit: await memory.getaudit(), capabilities: await refreshcapabilities(), outcomes: await memory.getoutcomes(), holds: heldkeysreport({ tabid: session?.tabid ?? 0, holds }), dialogs: await memory.getdialogs(), retries: await memory.getretries(), ...signals ? { signals: signalsreport({ signals }) } : { signals: signalsreport({}) }, banners: await memory.getbanners(), mutationevents: await memory.getmutationevents(), focusevents: await memory.getfocusevents(), diffs: await memory.getdiffs(), selectors: await memory.getselectors(), ...a11y ? { a11y } : {}, ...reader ? { reader } : {}, ...map ? { map } : {}, trail: trailreport({ ...session ? { sessionid: session.id } : {}, trail }), navrecords, ratestates, safeties, curated, waitprofiles, auths, navcontrol, navqueues, artifacts, navstate: livestate, ...waitprofile ? { waitprofile } : {}, offline: !navigator.onLine, tabs, windows, layouts: layoutreport({ layouts }), tabgroups, tabmetas, badges, snapshots, closedtabs, tabwatchevents, clones, tasktabgauge: taskgauge, ...controltab ? { controltab } : {}, tabreport: report, profiles, tickets, wizards: wizardreport({ ...session ? { sessionid: session.id } : {}, wizards, picks }), picks, errorreports, captchas, detections, ...codeentry !== void 0 ? { codeentry: true } : {}, datasets, imports, extractsessions, streams, exports, provenances, taskrules, sheetendpoints: sheetgrants, downloads, netlogs, clipconsents, clips, quarantines, cleanuprules, cleanupruns, capturecounters, inventory, mimefilters, scanhooks, captures: capturemetadata, capturepairs, capturepolicy: runsettings?.capturepolicy ?? "manual", media: mediarecords, imagebatches, recordingconsents, recordingactive: [...activerecordings.values()].map((active) => ({ id: active.record.id, kind: active.record.kind, scope: active.record.scope, startedat: active.record.startedat, stopat: active.stopat })), recordingwindow: runsettings?.recordingwindow, calls, endpoints, fetchconsents, apikeys, callretention: runsettings?.callretention, fetchesactive: activefetches.size, exchanges, channels, subscriptions, apimap, messages: messagecount, webrequestgrant: runsettings?.webrequestgrant === true, bodyretention: runsettings?.bodyretention, timelineretention: runsettings?.timelineretention, timeline, consoleconsents: await memory.getconsoleconsents(), rotationtargets: await memory.getrotationtargets(), levelsummaries: await memory.getlevelsummaries(), cdpsessions: await memory.getcdpsessions(), cdpcommands: await memory.getcdpcommands(), cdpeventrules: await memory.getcdpeventrules(), breakpoints: await memory.getbreakpoints(), pauses: await memory.getpauses(), watchexpressions: await memory.getwatchexpressions(), scriptoverrides: await memory.getscriptoverrides(), debuggergrants: await memory.getdebuggergrants(), pauseretention: runsettings?.pauseretention, breakpointceiling: runsettings?.breakpointceiling, cdpattached: [...activecdpsessions.values()].filter((active) => active.session.detachedat === void 0).length, profileretention: runsettings?.profileretention, traceceiling: runsettings?.traceceiling, profile: profilereport({ flows: await memory.getflowmetrics(), heaps: await memory.getheaprecords(), samples: await memory.getgrowsamples(), trends: await memory.gettrends(), profiles: await memory.getcpuprofiles(), shifts: await memory.getshiftentries(), traces: await memory.gettracerecords(), sourcemaps: await memory.getsourcemaps(), consents: await memory.getsourcemapconsents() }), profileactive: activememorytrackers.size + activeprofiletargets.size, profiletargets: [...activeprofiletargets.values()].flatMap((entry) => entry.targets), socketsactive: activesockets.size, emulation: emulationreport({ ...plan && await loademulationstate(plan.id) !== void 0 ? { state: await loademulationstate(plan.id) } : {}, devices: await memory.getdevicepresets(), networks: await memory.getnetworkpresets(), locations: await memory.getlocationpresets(), agents: await memory.getagentpresets(), blackbox: await memory.getblackboxrules(), permissions: await memory.getpermissionoverrides(), consents: await memory.getlocationconsents() }), emulatedlayers: plan ? layernames(await loademulationstate(plan.id)) : [], emulationretention: runsettings?.emulationretention, traffic, tokens, authflows, activerules: [...activerules.values()].reduce((total, ruleset) => total + ruleset.blocks.filter((rule) => rule.revertedat === void 0).length + ruleset.mocks.filter((rule) => rule.revertedat === void 0).length + ruleset.rewrites.filter((rule) => rule.revertedat === void 0).length + (ruleset.proxy !== void 0 && ruleset.proxy.revertedat === void 0 ? 1 : 0), 0), sessionmemory: sessionreport({ records: sessionrecords, events: await memory.getsessionevents(), folders: await memory.getsessionfolders(), diffs: await memory.getsessiondiffs(), ...autosnapshot !== void 0 ? { auto: autosnapshot.interval } : {}, ...crashed ? { crashed: true } : {} }), autosnapshotstate: autosnapshot, sessionretention: runsettings?.sessionretention, trigger: triggerlist({ rules: await memory.gettriggerules(), workflows: await memory.listworkflows(), queue: await memory.gettriggerqueue() }), triggerretention: runsettings?.triggerretention, workflow: workflowreport({ workflows: await memory.listworkflows(), runs: await memory.listworkflowruns(), templates: await memory.getsteptemplates(), ...newestworkflowrun !== void 0 ? { log: await memory.getrunlog(newestworkflowrun.id), scopes: await memory.getrunscopes(newestworkflowrun.id), provenance: await memory.getworkflowprovenance(newestworkflowrun.id), control: await memory.listcontroldecisions(newestworkflowrun.id) } : {} }), runlogretention: runsettings?.runlogretention, runhistoryretention: runsettings?.runhistoryretention, editor: editorstate({ versions: await memory.listworkflowversions(), diffs: await memory.listversiondiffs(), history: await memory.gethistory(), overrides: await memory.listsiteoverrides(), imports: (await memory.listworkflowimports()).map((entry) => ({ id: entry.id, workflowid: entry.record.id, name: entry.record.name, version: entry.record.version, steps: entry.record.steps.length, risk: entry.record.risk, importedat: entry.importedat, ...entry.filename !== void 0 ? { filename: entry.filename } : {} })), backgroundruns: await memory.getbackgroundruns(), watchdog: { ...runsettings?.watchdog !== void 0 ? { config: runsettings.watchdog } : {}, events: await memory.listwatchdogevents() } }), ...taskstate !== void 0 ? { taskstate } : {}, ...stitchprogress.size > 0 ? { stitchprogress: [...stitchprogress.values()] } : {}, mcp: await mcpstateof(), llm: await llmstateof(), swarm: await swarmstateof(), environments: await environmentviewof(), security: await securityviewof(), sessionview: await sessionviewof(), sessionpreferences: { ...runsettings?.recallwindow !== void 0 ? { recallwindow: runsettings.recallwindow } : {}, ...runsettings?.noteretention !== void 0 ? { noteretention: runsettings.noteretention } : {}, ...runsettings?.scratchpadretention !== void 0 ? { scratchpadretention: runsettings.scratchpadretention } : {}, ...runsettings?.summaryretention !== void 0 ? { summaryretention: runsettings.summaryretention } : {}, ...runsettings?.correctionretention !== void 0 ? { correctionretention: runsettings.correctionretention } : {}, ...runsettings?.summarywindow !== void 0 ? { summarywindow: runsettings.summarywindow } : {}, ...runsettings?.historyindex !== void 0 ? { historyindex: runsettings.historyindex } : {}, ...runsettings?.cancelrollback !== void 0 ? { cancelrollback: runsettings.cancelrollback } : {} } };
|
|
23062
|
+
return { config: await memory.getconfig(), session, plan, progress: plan && progress?.planid === plan.id ? progress : void 0, diagnostic: await memory.getdiagnostic(), audit: await memory.getaudit(), capabilities: await refreshcapabilities(), outcomes: await memory.getoutcomes(), holds: heldkeysreport({ tabid: session?.tabid ?? 0, holds }), dialogs: await memory.getdialogs(), retries: await memory.getretries(), ...signals ? { signals: signalsreport({ signals }) } : { signals: signalsreport({}) }, banners: await memory.getbanners(), mutationevents: await memory.getmutationevents(), focusevents: await memory.getfocusevents(), diffs: await memory.getdiffs(), selectors: await memory.getselectors(), ...a11y ? { a11y } : {}, ...reader ? { reader } : {}, ...map ? { map } : {}, trail: trailreport({ ...session ? { sessionid: session.id } : {}, trail }), navrecords, ratestates, safeties, curated, waitprofiles, auths, navcontrol, navqueues, artifacts, navstate: livestate, ...waitprofile ? { waitprofile } : {}, offline: !navigator.onLine, tabs, windows, layouts: layoutreport({ layouts }), tabgroups, tabmetas, badges, snapshots, closedtabs, tabwatchevents, clones, tasktabgauge: taskgauge, ...controltab ? { controltab } : {}, tabreport: report, profiles, tickets, wizards: wizardreport({ ...session ? { sessionid: session.id } : {}, wizards, picks }), picks, errorreports, captchas, detections, ...codeentry !== void 0 ? { codeentry: true } : {}, datasets, imports, extractsessions, streams, exports, provenances, taskrules, sheetendpoints: sheetgrants, downloads, netlogs, clipconsents, clips, quarantines, cleanuprules, cleanupruns, capturecounters, inventory, mimefilters, scanhooks, captures: capturemetadata, capturepairs, capturepolicy: runsettings?.capturepolicy ?? "manual", media: mediarecords, imagebatches, recordingconsents, recordingactive: [...activerecordings.values()].map((active) => ({ id: active.record.id, kind: active.record.kind, scope: active.record.scope, startedat: active.record.startedat, stopat: active.stopat })), recordingwindow: runsettings?.recordingwindow, calls, endpoints, fetchconsents, apikeys, callretention: runsettings?.callretention, fetchesactive: activefetches.size, exchanges, channels, subscriptions, apimap, messages: messagecount, webrequestgrant: runsettings?.webrequestgrant === true, bodyretention: runsettings?.bodyretention, timelineretention: runsettings?.timelineretention, timeline, consoleconsents: await memory.getconsoleconsents(), rotationtargets: await memory.getrotationtargets(), levelsummaries: await memory.getlevelsummaries(), cdpsessions: await memory.getcdpsessions(), cdpcommands: await memory.getcdpcommands(), cdpeventrules: await memory.getcdpeventrules(), breakpoints: await memory.getbreakpoints(), pauses: await memory.getpauses(), watchexpressions: await memory.getwatchexpressions(), scriptoverrides: await memory.getscriptoverrides(), debuggergrants: await memory.getdebuggergrants(), pauseretention: runsettings?.pauseretention, breakpointceiling: runsettings?.breakpointceiling, cdpattached: [...activecdpsessions.values()].filter((active) => active.session.detachedat === void 0).length, profileretention: runsettings?.profileretention, traceceiling: runsettings?.traceceiling, profile: profilereport({ flows: await memory.getflowmetrics(), heaps: await memory.getheaprecords(), samples: await memory.getgrowsamples(), trends: await memory.gettrends(), profiles: await memory.getcpuprofiles(), shifts: await memory.getshiftentries(), traces: await memory.gettracerecords(), sourcemaps: await memory.getsourcemaps(), consents: await memory.getsourcemapconsents() }), profileactive: activememorytrackers.size + activeprofiletargets.size, profiletargets: [...activeprofiletargets.values()].flatMap((entry) => entry.targets), socketsactive: activesockets.size, emulation: emulationreport({ ...plan && await loademulationstate(plan.id) !== void 0 ? { state: await loademulationstate(plan.id) } : {}, devices: await memory.getdevicepresets(), networks: await memory.getnetworkpresets(), locations: await memory.getlocationpresets(), agents: await memory.getagentpresets(), blackbox: await memory.getblackboxrules(), permissions: await memory.getpermissionoverrides(), consents: await memory.getlocationconsents() }), emulatedlayers: plan ? layernames(await loademulationstate(plan.id)) : [], emulationretention: runsettings?.emulationretention, traffic, tokens, authflows, activerules: [...activerules.values()].reduce((total, ruleset) => total + ruleset.blocks.filter((rule) => rule.revertedat === void 0).length + ruleset.mocks.filter((rule) => rule.revertedat === void 0).length + ruleset.rewrites.filter((rule) => rule.revertedat === void 0).length + (ruleset.proxy !== void 0 && ruleset.proxy.revertedat === void 0 ? 1 : 0), 0), sessionmemory: sessionreport({ records: sessionrecords, events: await memory.getsessionevents(), folders: await memory.getsessionfolders(), diffs: await memory.getsessiondiffs(), ...autosnapshot !== void 0 ? { auto: autosnapshot.interval } : {}, ...crashed ? { crashed: true } : {} }), autosnapshotstate: autosnapshot, sessionretention: runsettings?.sessionretention, trigger: triggerlist({ rules: await memory.gettriggerules(), workflows: await memory.listworkflows(), queue: await memory.gettriggerqueue() }), triggerretention: runsettings?.triggerretention, workflow: workflowreport({ workflows: await memory.listworkflows(), runs: await memory.listworkflowruns(), templates: await memory.getsteptemplates(), ...newestworkflowrun !== void 0 ? { log: await memory.getrunlog(newestworkflowrun.id), scopes: await memory.getrunscopes(newestworkflowrun.id), provenance: await memory.getworkflowprovenance(newestworkflowrun.id), control: await memory.listcontroldecisions(newestworkflowrun.id) } : {} }), runlogretention: runsettings?.runlogretention, runhistoryretention: runsettings?.runhistoryretention, editor: editorstate({ versions: await memory.listworkflowversions(), diffs: await memory.listversiondiffs(), history: await memory.gethistory(), overrides: await memory.listsiteoverrides(), imports: (await memory.listworkflowimports()).map((entry) => ({ id: entry.id, workflowid: entry.record.id, name: entry.record.name, version: entry.record.version, steps: entry.record.steps.length, risk: entry.record.risk, importedat: entry.importedat, ...entry.filename !== void 0 ? { filename: entry.filename } : {} })), backgroundruns: await memory.getbackgroundruns(), watchdog: { ...runsettings?.watchdog !== void 0 ? { config: runsettings.watchdog } : {}, events: await memory.listwatchdogevents() } }), ...taskstate !== void 0 ? { taskstate } : {}, ...stitchprogress.size > 0 ? { stitchprogress: [...stitchprogress.values()] } : {}, mcp: await mcpstateof(), llm: await llmstateof(), swarm: await swarmstateof(), environments: await environmentviewof(), security: await securityviewof(), sessionview: await sessionviewof(), surfacepreferences: { ...runsettings?.paletterecents !== void 0 ? { paletterecents: runsettings.paletterecents } : {}, ...runsettings?.paletteshortcut !== void 0 ? { paletteshortcut: runsettings.paletteshortcut } : {}, ...runsettings?.logstreambuffer !== void 0 ? { logstreambuffer: runsettings.logstreambuffer } : {}, ...runsettings?.taskinputretention !== void 0 ? { taskinputretention: runsettings.taskinputretention } : {}, ...runsettings?.diffpreviewbytes !== void 0 ? { diffpreviewbytes: runsettings.diffpreviewbytes } : {}, ...runsettings?.recenttraydepth !== void 0 ? { recenttraydepth: runsettings.recenttraydepth } : {}, ...runsettings?.notifyconsent !== void 0 ? { notifyconsent: runsettings.notifyconsent } : {}, ...runsettings?.notifyenabled !== void 0 ? { notifyenabled: runsettings.notifyenabled } : {}, ...runsettings?.themepreference !== void 0 ? { themepreference: runsettings.themepreference } : {}, ...runsettings?.uilanguage !== void 0 ? { uilanguage: runsettings.uilanguage } : {}, ...runsettings?.toastlivecount !== void 0 ? { toastlivecount: runsettings.toastlivecount } : {} }, sessionpreferences: { ...runsettings?.recallwindow !== void 0 ? { recallwindow: runsettings.recallwindow } : {}, ...runsettings?.noteretention !== void 0 ? { noteretention: runsettings.noteretention } : {}, ...runsettings?.scratchpadretention !== void 0 ? { scratchpadretention: runsettings.scratchpadretention } : {}, ...runsettings?.summaryretention !== void 0 ? { summaryretention: runsettings.summaryretention } : {}, ...runsettings?.correctionretention !== void 0 ? { correctionretention: runsettings.correctionretention } : {}, ...runsettings?.summarywindow !== void 0 ? { summarywindow: runsettings.summarywindow } : {}, ...runsettings?.historyindex !== void 0 ? { historyindex: runsettings.historyindex } : {}, ...runsettings?.cancelrollback !== void 0 ? { cancelrollback: runsettings.cancelrollback } : {} } };
|
|
21510
23063
|
}
|
|
21511
23064
|
case "capabilities":
|
|
21512
23065
|
return refreshcapabilities();
|
|
@@ -24578,6 +26131,10 @@ async function handlerequest(message, sender) {
|
|
|
24578
26131
|
}
|
|
24579
26132
|
case "sessions":
|
|
24580
26133
|
return handlesessionscommand(message);
|
|
26134
|
+
case "surface":
|
|
26135
|
+
return handlesurfacecommand(message);
|
|
26136
|
+
case "views":
|
|
26137
|
+
return handlesurfaceviewcommand(message);
|
|
24581
26138
|
case "security": {
|
|
24582
26139
|
const input2 = message;
|
|
24583
26140
|
const now = Date.now();
|
|
@@ -25629,6 +27186,14 @@ chrome.runtime.onStartup.addListener(() => {
|
|
|
25629
27186
|
void runwatchdog().catch(() => {
|
|
25630
27187
|
});
|
|
25631
27188
|
});
|
|
27189
|
+
chrome.runtime.onInstalled.addListener((details) => {
|
|
27190
|
+
void (async () => {
|
|
27191
|
+
if (details.reason !== "install") return;
|
|
27192
|
+
await memory.setonboardingstate(onboardingstart(await memory.getonboardingstate(), Date.now()));
|
|
27193
|
+
await audit("onboarding", "Devthink installed for the first time and the onboarding walkthrough started; it walks the origin grants, the plan review, the run control and the log audit once.", {});
|
|
27194
|
+
})().catch(() => {
|
|
27195
|
+
});
|
|
27196
|
+
});
|
|
25632
27197
|
async function pauseinterruptedworkflowruns() {
|
|
25633
27198
|
for (const run of await memory.listworkflowruns()) {
|
|
25634
27199
|
if (run.state !== "running") continue;
|