@wenathlan/extension 1.1.61 → 1.1.63
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/confirmgates.d.ts +60 -0
- package/dist/confirmgates.d.ts.map +1 -0
- package/dist/environments.d.ts +10 -0
- package/dist/environments.d.ts.map +1 -1
- package/dist/inboundguard.d.ts +86 -0
- package/dist/inboundguard.d.ts.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1299 -3
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +187 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/originpolicy.d.ts +10 -0
- package/dist/originpolicy.d.ts.map +1 -1
- package/dist/phishguard.d.ts +24 -0
- package/dist/phishguard.d.ts.map +1 -0
- package/dist/policy.d.ts +122 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +88 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/redactshots.d.ts +54 -0
- package/dist/redactshots.d.ts.map +1 -0
- package/dist/secretvault.d.ts +89 -0
- package/dist/secretvault.d.ts.map +1 -0
- package/dist/sessioninterface.d.ts +213 -0
- package/dist/sessioninterface.d.ts.map +1 -0
- package/dist/transparency.d.ts +46 -0
- package/dist/transparency.d.ts.map +1 -0
- package/dist/types.d.ts +368 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +1710 -55
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +5 -1
- package/extension/dist/offscreen.js +4 -0
- package/extension/dist/offscreen.js.map +2 -2
- package/extension/dist/pagebridge.js.map +2 -2
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +41 -0
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +462 -215
- package/extension/dist/sidepanel.js.map +3 -3
- package/extension/dist/transparencypage.html +25 -0
- package/extension/dist/transparencypage.js +198 -0
- package/extension/dist/transparencypage.js.map +7 -0
- package/extension/manifest.json +5 -1
- package/package.json +1 -1
|
@@ -4737,6 +4737,375 @@ var sessionmemory = class {
|
|
|
4737
4737
|
}
|
|
4738
4738
|
return kept;
|
|
4739
4739
|
}
|
|
4740
|
+
/**
|
|
4741
|
+
* Security part two persistence of the 1.1.62 family.
|
|
4742
|
+
* The protections for secrets, messages and money live here: the secretvault metadata with labels and scopes only and never values, scoped per profile workspace; the connectallow entries with their senders shipping empty by default; the ratelimit bucket state per origin and per session; the confirm gates with their resolution events and their human action provenance; the redactshot regions per origin and page template; the phishguard verdicts with their distance scores expiring past their freshness window; the permdiff records of each installed version; the safedefaults applications with their first seen origins; and the deferred command events waiting for their bucket reset.
|
|
4743
|
+
* The vault values never touch this seam: only metadata persists while the values stay behind the vault seam the background wires.
|
|
4744
|
+
*/
|
|
4745
|
+
/** Replaces the secretvault metadata of the profile workspaces: labels, scopes, provenance and digests only, never values. */
|
|
4746
|
+
async setsecretvault(entries) {
|
|
4747
|
+
return this.adapter.set("secretvault", entries);
|
|
4748
|
+
}
|
|
4749
|
+
/** Returns the stored secretvault metadata, oldest record first; the values live behind the vault seam and never persist. */
|
|
4750
|
+
async getsecretvault() {
|
|
4751
|
+
return await this.adapter.get("secretvault") ?? [];
|
|
4752
|
+
}
|
|
4753
|
+
/** Adds one secretvault metadata record scoped to a profile workspace; a duplicate vault id keeps its first record. */
|
|
4754
|
+
async addsecret(entry) {
|
|
4755
|
+
const entries = await this.getsecretvault();
|
|
4756
|
+
if (entries.some((candidate) => candidate.vaultid === entry.vaultid)) return;
|
|
4757
|
+
await this.setsecretvault([...entries, entry]);
|
|
4758
|
+
}
|
|
4759
|
+
/** Removes one secretvault metadata record by its vault id; the background drops the value behind the seam in the same action. */
|
|
4760
|
+
async removesecret(vaultid) {
|
|
4761
|
+
await this.setsecretvault((await this.getsecretvault()).filter((entry) => entry.vaultid !== vaultid));
|
|
4762
|
+
}
|
|
4763
|
+
/** Stamps the last use of one secretvault record: the metadata notes when the vault last released its value while the value itself stays unrecorded. */
|
|
4764
|
+
async stampsecretuse(vaultid, at) {
|
|
4765
|
+
await this.setsecretvault((await this.getsecretvault()).map((entry) => entry.vaultid === vaultid ? { ...entry, lastusedat: at } : entry));
|
|
4766
|
+
}
|
|
4767
|
+
/** Replaces the connectallow entries of external senders; the list ships empty by default with user managed entries only. */
|
|
4768
|
+
async setconnectallow(entries) {
|
|
4769
|
+
return this.adapter.set("connectallow", entries);
|
|
4770
|
+
}
|
|
4771
|
+
/** Returns the stored connectallow entries, oldest add first. */
|
|
4772
|
+
async getconnectallow() {
|
|
4773
|
+
return await this.adapter.get("connectallow") ?? [];
|
|
4774
|
+
}
|
|
4775
|
+
/** Adds one connectallow entry for an external sender; a duplicate sender id keeps its first entry. */
|
|
4776
|
+
async addconnectallow(entry) {
|
|
4777
|
+
const entries = await this.getconnectallow();
|
|
4778
|
+
if (entries.some((candidate) => candidate.senderid === entry.senderid)) return;
|
|
4779
|
+
await this.setconnectallow([...entries, entry]);
|
|
4780
|
+
}
|
|
4781
|
+
/** Removes one connectallow entry by its sender id; the origincheck drops the sender again after the removal. */
|
|
4782
|
+
async removeconnectallow(senderid) {
|
|
4783
|
+
await this.setconnectallow((await this.getconnectallow()).filter((entry) => entry.senderid !== senderid));
|
|
4784
|
+
}
|
|
4785
|
+
/** Replaces the ratelimit bucket state per origin and per session: the user configured bounds and windows with their used counts. */
|
|
4786
|
+
async setratelimitbuckets(buckets) {
|
|
4787
|
+
return this.adapter.set("ratelimitbuckets", buckets);
|
|
4788
|
+
}
|
|
4789
|
+
/** Returns the stored ratelimit buckets per origin and per session. */
|
|
4790
|
+
async getratelimitbuckets() {
|
|
4791
|
+
return await this.adapter.get("ratelimitbuckets") ?? [];
|
|
4792
|
+
}
|
|
4793
|
+
/** Upserts one ratelimit bucket: a bucket of the same origin and session replaces its state while a new pair joins the list. */
|
|
4794
|
+
async saveratelimitbucket(bucket) {
|
|
4795
|
+
const buckets = await this.getratelimitbuckets();
|
|
4796
|
+
await this.setratelimitbuckets(buckets.some((candidate) => candidate.origin === bucket.origin && candidate.sessionid === bucket.sessionid) ? buckets.map((candidate) => candidate.origin === bucket.origin && candidate.sessionid === bucket.sessionid ? bucket : candidate) : [...buckets, bucket]);
|
|
4797
|
+
}
|
|
4798
|
+
/** Removes the ratelimit bucket of one origin and session; the origin runs without a bucket because the bounds stay user choices only. */
|
|
4799
|
+
async removeratelimitbucket(origin, sessionid) {
|
|
4800
|
+
await this.setratelimitbuckets((await this.getratelimitbuckets()).filter((bucket) => !(bucket.origin === origin && bucket.sessionid === sessionid)));
|
|
4801
|
+
}
|
|
4802
|
+
/** Replaces the confirm gates with their payloads and states; a resolved or refused gate stays terminal for the audit trail. */
|
|
4803
|
+
async setgates(gates) {
|
|
4804
|
+
return this.adapter.set("confirmgates", gates);
|
|
4805
|
+
}
|
|
4806
|
+
/** Returns the stored confirm gates, newest open first. */
|
|
4807
|
+
async getgates() {
|
|
4808
|
+
return await this.adapter.get("confirmgates") ?? [];
|
|
4809
|
+
}
|
|
4810
|
+
/** Upserts one confirm gate: a gate of the same step keeps its latest record because one gated step carries one live gate. */
|
|
4811
|
+
async savegate(gate) {
|
|
4812
|
+
const gates = await this.getgates();
|
|
4813
|
+
await this.setgates(gates.some((candidate) => candidate.stepid === gate.stepid && candidate.kind === gate.kind) ? gates.map((candidate) => candidate.stepid === gate.stepid && candidate.kind === gate.kind ? gate : candidate) : [gate, ...gates]);
|
|
4814
|
+
}
|
|
4815
|
+
/** Records one gate resolution event with its human action provenance; the resolution history stays visible for the audit trail. */
|
|
4816
|
+
async addgateresolution(resolution) {
|
|
4817
|
+
await this.adapter.set("gateresolutions", [resolution, ...await this.adapter.get("gateresolutions") ?? []].slice(0, 500));
|
|
4818
|
+
}
|
|
4819
|
+
/** Returns the recorded gate resolution events with their human action provenance, newest first. */
|
|
4820
|
+
async getgateresolutions() {
|
|
4821
|
+
return await this.adapter.get("gateresolutions") ?? [];
|
|
4822
|
+
}
|
|
4823
|
+
/** Replaces the redactshot regions per origin and page template. */
|
|
4824
|
+
async setredactregions(regions) {
|
|
4825
|
+
return this.adapter.set("redactregions", regions);
|
|
4826
|
+
}
|
|
4827
|
+
/** Returns the stored redactshot regions per origin and page template, oldest rule first. */
|
|
4828
|
+
async getredactregions() {
|
|
4829
|
+
return await this.adapter.get("redactregions") ?? [];
|
|
4830
|
+
}
|
|
4831
|
+
/** Adds one redactshot region, derived from a field shape or drawn by the user. */
|
|
4832
|
+
async addredactregion(region) {
|
|
4833
|
+
await this.setredactregions([...await this.getredactregions(), region]);
|
|
4834
|
+
}
|
|
4835
|
+
/** Removes one redactshot region by its id. */
|
|
4836
|
+
async removeredactregion(id) {
|
|
4837
|
+
await this.setredactregions((await this.getredactregions()).filter((region) => region.id !== id));
|
|
4838
|
+
}
|
|
4839
|
+
/** Records one phishguard verdict with its distance score; the records stay for the audit trail while the freshness window governs the live set. */
|
|
4840
|
+
async addphishverdict(verdict) {
|
|
4841
|
+
await this.adapter.set("phishverdicts", [verdict, ...(await this.adapter.get("phishverdicts") ?? []).filter((candidate) => candidate.origin !== verdict.origin)].slice(0, 500));
|
|
4842
|
+
}
|
|
4843
|
+
/** Returns the stored phishguard verdicts with their distance scores, newest first. */
|
|
4844
|
+
async getphishverdicts() {
|
|
4845
|
+
return await this.adapter.get("phishverdicts") ?? [];
|
|
4846
|
+
}
|
|
4847
|
+
/** Expires the phishguard verdicts past the user configured freshness window: the expired verdicts keep their records for the audit trail while the guard recomputes the next login step. */
|
|
4848
|
+
async expirephishverdicts(freshness, now) {
|
|
4849
|
+
const verdicts = await this.getphishverdicts();
|
|
4850
|
+
if (freshness === void 0) return verdicts;
|
|
4851
|
+
return verdicts.filter((verdict) => now - verdict.at < freshness);
|
|
4852
|
+
}
|
|
4853
|
+
/** Records one permdiff between two installed permission versions; the record of each installed update stays for the audit trail. */
|
|
4854
|
+
async addpermdiff(diff) {
|
|
4855
|
+
await this.adapter.set("permdiffs", [diff, ...await this.adapter.get("permdiffs") ?? []].slice(0, 500));
|
|
4856
|
+
}
|
|
4857
|
+
/** Returns the recorded permdiffs of each installed update, newest first. */
|
|
4858
|
+
async getpermdiffs() {
|
|
4859
|
+
return await this.adapter.get("permdiffs") ?? [];
|
|
4860
|
+
}
|
|
4861
|
+
/** Stores the last installed permission set the permdiff of the next update compares against. */
|
|
4862
|
+
async setlastpermissions(permissions, version) {
|
|
4863
|
+
await this.adapter.set("lastpermissions", { permissions, version });
|
|
4864
|
+
}
|
|
4865
|
+
/** Returns the last installed permission set with its version; an absent record returns undefined. */
|
|
4866
|
+
async getlastpermissions() {
|
|
4867
|
+
return this.adapter.get("lastpermissions");
|
|
4868
|
+
}
|
|
4869
|
+
/** Records one safedefaults application with its first seen origin; the first visit of an unknown origin stays visible. */
|
|
4870
|
+
async addsafedefaultapplication(application) {
|
|
4871
|
+
const applications = await this.adapter.get("safedefaults") ?? [];
|
|
4872
|
+
if (applications.some((candidate) => candidate.origin === application.origin)) return;
|
|
4873
|
+
await this.adapter.set("safedefaults", [...applications, application]);
|
|
4874
|
+
}
|
|
4875
|
+
/** Returns the recorded safedefaults applications with their first seen origins, oldest first. */
|
|
4876
|
+
async getsafedefaultapplications() {
|
|
4877
|
+
return await this.adapter.get("safedefaults") ?? [];
|
|
4878
|
+
}
|
|
4879
|
+
/** Records one deferred command event with the reset time it waits for. */
|
|
4880
|
+
async adddeferredevent(event) {
|
|
4881
|
+
await this.adapter.set("deferredevents", [event, ...await this.adapter.get("deferredevents") ?? []].slice(0, 500));
|
|
4882
|
+
}
|
|
4883
|
+
/** Returns the recorded deferred command events, newest first. */
|
|
4884
|
+
async getdeferredevents() {
|
|
4885
|
+
return await this.adapter.get("deferredevents") ?? [];
|
|
4886
|
+
}
|
|
4887
|
+
/** Serves the transparency data of the transparencypage in one read: every active grant with its origin, scope and boundary, every consent window ever granted with its expiry, the connectallow entries with their senders, the permdiff records of each installed update, the safedefaults applications and the secretvault metadata with labels and scopes only. */
|
|
4888
|
+
async gettransparencyview() {
|
|
4889
|
+
return {
|
|
4890
|
+
allowlist: await this.getautomationallowlist(),
|
|
4891
|
+
profiles: await this.getoriginprofiles(),
|
|
4892
|
+
windows: await this.getconsentwindows(),
|
|
4893
|
+
connectallow: await this.getconnectallow(),
|
|
4894
|
+
permdiffs: await this.getpermdiffs(),
|
|
4895
|
+
safedefaults: await this.getsafedefaultapplications(),
|
|
4896
|
+
vault: await this.getsecretvault(),
|
|
4897
|
+
gates: await this.getgates(),
|
|
4898
|
+
resolutions: await this.getgateresolutions(),
|
|
4899
|
+
deferred: await this.getdeferredevents(),
|
|
4900
|
+
phishverdicts: await this.getphishverdicts()
|
|
4901
|
+
};
|
|
4902
|
+
}
|
|
4903
|
+
/**
|
|
4904
|
+
* Session interface persistence of the 1.1.63 family.
|
|
4905
|
+
* The five session stores live here, scoped per profile workspace: the sitenotes per origin with sensitive bodies sealed at rest, the append only scratchpad entries per task with their step provenance, the distilled runsummaries per run and origin, the correctionmemory entries per origin and kind captured from plan review, and the consentmemory entries per origin with every grant, denial, expiry and revocation carrying its boundary; beside them the semanticrecall index with fingerprint deduplication answers ranked queries inside the run scope, the incremental historysearch corpus indexes session metadata, notes and summaries as they are written, the errorsurface payloads of failed steps keep their retry hints with the policy verdict, the per tab session references isolate parallel tabs, and the export bundles notes, summaries and corrections as one audit bundle.
|
|
4906
|
+
* The recall seam stays documented: the local fingerprint index answers every query today while a future remote recall backend can take the same shapes behind the seam without touching the callers.
|
|
4907
|
+
*/
|
|
4908
|
+
/** Replaces the stored site notes; a sensitive note carries its sealedbody only so the plain body never persists. */
|
|
4909
|
+
async setsitenotes(notes) {
|
|
4910
|
+
return this.adapter.set("sitenotes", notes);
|
|
4911
|
+
}
|
|
4912
|
+
/** Returns the stored site notes, oldest update first. */
|
|
4913
|
+
async getsitenotes() {
|
|
4914
|
+
return await this.adapter.get("sitenotes") ?? [];
|
|
4915
|
+
}
|
|
4916
|
+
/** Reads the site notes of one origin only; the read gate keeps the origin inside the session grants. */
|
|
4917
|
+
async readsitenotes(origin) {
|
|
4918
|
+
return (await this.getsitenotes()).filter((note) => note.origin === origin);
|
|
4919
|
+
}
|
|
4920
|
+
/** Writes one site note: a note of the same id keeps its latest edit while a new note joins the store. */
|
|
4921
|
+
async writesitenote(note) {
|
|
4922
|
+
const notes = await this.getsitenotes();
|
|
4923
|
+
await this.setsitenotes(notes.some((candidate) => candidate.id === note.id) ? notes.map((candidate) => candidate.id === note.id ? note : candidate) : [...notes, note]);
|
|
4924
|
+
}
|
|
4925
|
+
/** Removes one site note by its id. */
|
|
4926
|
+
async removesitenote(id) {
|
|
4927
|
+
await this.setsitenotes((await this.getsitenotes()).filter((note) => note.id !== id));
|
|
4928
|
+
}
|
|
4929
|
+
/** Expires the site notes past the user configured window; an absent window keeps every note. */
|
|
4930
|
+
async expiresitenotes(retention, now) {
|
|
4931
|
+
if (retention === void 0) return await this.getsitenotes();
|
|
4932
|
+
const kept = (await this.getsitenotes()).filter((note) => now - note.updatedat < retention);
|
|
4933
|
+
await this.setsitenotes(kept);
|
|
4934
|
+
return kept;
|
|
4935
|
+
}
|
|
4936
|
+
/** Replaces the stored scratchpad entries per task. */
|
|
4937
|
+
async setscratchpad(entries) {
|
|
4938
|
+
return this.adapter.set("scratchpad", entries);
|
|
4939
|
+
}
|
|
4940
|
+
/** Returns every stored scratchpad entry, newest first. */
|
|
4941
|
+
async getscratchpadall() {
|
|
4942
|
+
return await this.adapter.get("scratchpad") ?? [];
|
|
4943
|
+
}
|
|
4944
|
+
/** Appends one scratchpad entry: the pad stays append only so no later write rewrites an earlier entry. */
|
|
4945
|
+
async appendscratchentry(entry) {
|
|
4946
|
+
await this.setscratchpad([entry, ...await this.getscratchpadall()]);
|
|
4947
|
+
}
|
|
4948
|
+
/** Reads the scratchpad of one task session, newest first; entries of another task never cross the boundary. */
|
|
4949
|
+
async readscratchpad(taskid, sessionid) {
|
|
4950
|
+
return (await this.getscratchpadall()).filter((entry) => entry.taskid === taskid && entry.sessionid === sessionid);
|
|
4951
|
+
}
|
|
4952
|
+
/** Prunes the scratchpad entries past the user configured window; an absent window keeps every entry. */
|
|
4953
|
+
async prunescratchentries(window2, now) {
|
|
4954
|
+
if (window2 === void 0) return await this.getscratchpadall();
|
|
4955
|
+
const kept = (await this.getscratchpadall()).filter((entry) => now - entry.at < window2);
|
|
4956
|
+
await this.setscratchpad(kept);
|
|
4957
|
+
return kept;
|
|
4958
|
+
}
|
|
4959
|
+
/** Stores one distilled run summary of a completed run. */
|
|
4960
|
+
async setrunsummary(summary) {
|
|
4961
|
+
return this.adapter.set(`runsummary:${summary.runid}`, summary);
|
|
4962
|
+
}
|
|
4963
|
+
/** Returns the stored run summary of one run; an absent summary returns undefined. */
|
|
4964
|
+
async getrunsummary(runid) {
|
|
4965
|
+
return this.adapter.get(`runsummary:${runid}`);
|
|
4966
|
+
}
|
|
4967
|
+
/** Lists the stored run summaries, oldest distillation first, optionally filtered by origin. */
|
|
4968
|
+
async listrunsummaries(origin) {
|
|
4969
|
+
const index = await this.adapter.get("runsummaryindex") ?? [];
|
|
4970
|
+
const summaries = [];
|
|
4971
|
+
for (const runid of index) {
|
|
4972
|
+
const summary = await this.getrunsummary(runid);
|
|
4973
|
+
if (summary) summaries.push(summary);
|
|
4974
|
+
}
|
|
4975
|
+
const filtered = origin === void 0 ? summaries : summaries.filter((summary) => summary.origins.includes(origin));
|
|
4976
|
+
return filtered.sort((one, two) => one.distilledat - two.distilledat);
|
|
4977
|
+
}
|
|
4978
|
+
/** Tracks one run in the run summary index so the listing reads every stored summary. */
|
|
4979
|
+
async trackrunsummary(runid) {
|
|
4980
|
+
const index = await this.adapter.get("runsummaryindex") ?? [];
|
|
4981
|
+
if (!index.includes(runid)) await this.adapter.set("runsummaryindex", [...index, runid]);
|
|
4982
|
+
}
|
|
4983
|
+
/** Expires the run summaries past the user configured window; an absent window keeps every summary. */
|
|
4984
|
+
async expirerunsummaries(retention, now) {
|
|
4985
|
+
const summaries = await this.listrunsummaries();
|
|
4986
|
+
if (retention === void 0) return summaries;
|
|
4987
|
+
const kept = [];
|
|
4988
|
+
for (const summary of summaries) {
|
|
4989
|
+
if (now - summary.distilledat > retention) await this.adapter.set(`runsummary:${summary.runid}`, { ...summary, steps: [], kinds: [], origins: summary.origins });
|
|
4990
|
+
else kept.push(summary);
|
|
4991
|
+
}
|
|
4992
|
+
return kept;
|
|
4993
|
+
}
|
|
4994
|
+
/** Replaces the semantic recall index with its fingerprint deduplicated entries. */
|
|
4995
|
+
async setrecallindex(index) {
|
|
4996
|
+
return this.adapter.set("recallindex", index);
|
|
4997
|
+
}
|
|
4998
|
+
/** Returns the stored semantic recall index entries, newest first. */
|
|
4999
|
+
async getrecallindex() {
|
|
5000
|
+
return await this.adapter.get("recallindex") ?? [];
|
|
5001
|
+
}
|
|
5002
|
+
/** Adds one recall index entry with fingerprint deduplication: a repeated extraction keeps its first entry. */
|
|
5003
|
+
async addrecallentry(entry) {
|
|
5004
|
+
const index = await this.getrecallindex();
|
|
5005
|
+
if (index.some((candidate) => candidate.fingerprint === entry.fingerprint && candidate.origin === entry.origin)) return;
|
|
5006
|
+
await this.setrecallindex([entry, ...index]);
|
|
5007
|
+
}
|
|
5008
|
+
/** Answers one semantic recall query across the extraction stores: the local index ranks by text similarity inside the run scope and returns the provenance of every match. */
|
|
5009
|
+
async semanticrecall(query, scope, rank) {
|
|
5010
|
+
return rank(await this.getrecallindex(), query, scope);
|
|
5011
|
+
}
|
|
5012
|
+
/** Expires the recall index entries past the user configured window; the extraction records themselves stay for the audit trail. */
|
|
5013
|
+
async expirerecallentries(window2, now) {
|
|
5014
|
+
if (window2 === void 0) return await this.getrecallindex();
|
|
5015
|
+
const kept = (await this.getrecallindex()).filter((entry) => now - entry.at < window2);
|
|
5016
|
+
await this.setrecallindex(kept);
|
|
5017
|
+
return kept;
|
|
5018
|
+
}
|
|
5019
|
+
/** Replaces the stored correction memory entries per origin and kind. */
|
|
5020
|
+
async setcorrections(corrections) {
|
|
5021
|
+
return this.adapter.set("corrections", corrections);
|
|
5022
|
+
}
|
|
5023
|
+
/** Returns the stored correction memory entries, newest first, optionally filtered by origin and kind. */
|
|
5024
|
+
async getcorrections(filter) {
|
|
5025
|
+
const entries = await this.adapter.get("corrections") ?? [];
|
|
5026
|
+
return entries.filter((entry) => (filter?.origin === void 0 || entry.origin === filter.origin) && (filter?.kind === void 0 || entry.kind === filter.kind));
|
|
5027
|
+
}
|
|
5028
|
+
/** Records one correction memory entry captured from a plan review edit or rejection. */
|
|
5029
|
+
async addcorrection(entry) {
|
|
5030
|
+
await this.setcorrections([entry, ...await this.adapter.get("corrections") ?? []]);
|
|
5031
|
+
}
|
|
5032
|
+
/** Expires the correction memory entries past the user configured window; an absent window keeps every correction. */
|
|
5033
|
+
async expirecorrectionentries(window2, now) {
|
|
5034
|
+
if (window2 === void 0) return await this.getcorrections();
|
|
5035
|
+
const kept = (await this.getcorrections()).filter((entry) => now - entry.at < window2);
|
|
5036
|
+
await this.setcorrections(kept);
|
|
5037
|
+
return kept;
|
|
5038
|
+
}
|
|
5039
|
+
/** Replaces the stored consent memory entries per origin. */
|
|
5040
|
+
async setconsentmemory(entries) {
|
|
5041
|
+
return this.adapter.set("consentmemory", entries);
|
|
5042
|
+
}
|
|
5043
|
+
/** Returns the stored consent memory entries, newest first, optionally filtered by origin. */
|
|
5044
|
+
async getconsentmemory(origin) {
|
|
5045
|
+
const entries = await this.adapter.get("consentmemory") ?? [];
|
|
5046
|
+
return origin === void 0 ? entries : entries.filter((entry) => entry.origin === origin);
|
|
5047
|
+
}
|
|
5048
|
+
/** Records one consent memory entry per origin: every grant, denial, expiry and revocation lands with its boundary and kinds. */
|
|
5049
|
+
async addconsentmemoryentry(entry) {
|
|
5050
|
+
await this.setconsentmemory([entry, ...await this.adapter.get("consentmemory") ?? []]);
|
|
5051
|
+
}
|
|
5052
|
+
/** Replaces the stored error surface payloads of failed steps. */
|
|
5053
|
+
async seterrorsurfaces(surfaces) {
|
|
5054
|
+
return this.adapter.set("errorsurfaces", surfaces);
|
|
5055
|
+
}
|
|
5056
|
+
/** Returns the stored error surface payloads, newest first, optionally filtered by step. */
|
|
5057
|
+
async geterrorsurfaces(stepid) {
|
|
5058
|
+
const surfaces = await this.adapter.get("errorsurfaces") ?? [];
|
|
5059
|
+
return stepid === void 0 ? surfaces : surfaces.filter((surface) => surface.stepid === stepid);
|
|
5060
|
+
}
|
|
5061
|
+
/** Records one error surface payload of a failed step with its retry hint and the policy verdict. */
|
|
5062
|
+
async adderrorsurface(surface) {
|
|
5063
|
+
await this.seterrorsurfaces([surface, ...await this.adapter.get("errorsurfaces") ?? []].slice(0, 500));
|
|
5064
|
+
}
|
|
5065
|
+
/** Replaces the incremental history search corpus of session metadata, notes and run summaries. */
|
|
5066
|
+
async sethistoryindex(corpus) {
|
|
5067
|
+
return this.adapter.set("historyindex", corpus);
|
|
5068
|
+
}
|
|
5069
|
+
/** Returns the incremental history search corpus, newest entry first. */
|
|
5070
|
+
async gethistoryindex() {
|
|
5071
|
+
return await this.adapter.get("historyindex") ?? [];
|
|
5072
|
+
}
|
|
5073
|
+
/** Adds one corpus entry to the incremental history index on each store write. */
|
|
5074
|
+
async addhistoryentry(entry) {
|
|
5075
|
+
const corpus = await this.gethistoryindex();
|
|
5076
|
+
await this.sethistoryindex([entry, ...corpus.filter((candidate) => !(candidate.source === entry.source && candidate.id === entry.id))]);
|
|
5077
|
+
}
|
|
5078
|
+
/** Answers one history search query against the incremental corpus with the matched terms highlighted. */
|
|
5079
|
+
async historysearch(query, search) {
|
|
5080
|
+
return search(await this.gethistoryindex(), query);
|
|
5081
|
+
}
|
|
5082
|
+
/** Stores one per tab session reference so parallel tabs never collide inside the session stores. */
|
|
5083
|
+
async settabsession(ref) {
|
|
5084
|
+
return this.adapter.set(`tabsession:${ref.tabid}`, ref);
|
|
5085
|
+
}
|
|
5086
|
+
/** Returns the per tab session reference of one tab; an absent reference returns undefined. */
|
|
5087
|
+
async gettabsession(tabid2) {
|
|
5088
|
+
return this.adapter.get(`tabsession:${tabid2}`);
|
|
5089
|
+
}
|
|
5090
|
+
/** Lists every per tab session reference so the sessiongrid reads the per tab lock state of concurrent sessions. */
|
|
5091
|
+
async listtabsessions() {
|
|
5092
|
+
const tabs = await this.adapter.get("tabsessionindex") ?? [];
|
|
5093
|
+
const refs = [];
|
|
5094
|
+
for (const tabid2 of tabs) {
|
|
5095
|
+
const ref = await this.gettabsession(tabid2);
|
|
5096
|
+
if (ref) refs.push(ref);
|
|
5097
|
+
}
|
|
5098
|
+
return refs;
|
|
5099
|
+
}
|
|
5100
|
+
/** Tracks one tab in the per tab session index so the listing reads every isolated reference. */
|
|
5101
|
+
async tracktabsession(tabid2) {
|
|
5102
|
+
const tabs = await this.adapter.get("tabsessionindex") ?? [];
|
|
5103
|
+
if (!tabs.includes(tabid2)) await this.adapter.set("tabsessionindex", [...tabs, tabid2]);
|
|
5104
|
+
}
|
|
5105
|
+
/** Exports the site notes, the run summaries and the correction memory as one audit bundle: sensitive note bodies stay sealed in the export. */
|
|
5106
|
+
async exportsessionbundle(exportedat) {
|
|
5107
|
+
return { kind: "sessionbundle", notes: await this.getsitenotes(), summaries: await this.listrunsummaries(), corrections: await this.getcorrections(), exportedat };
|
|
5108
|
+
}
|
|
4740
5109
|
};
|
|
4741
5110
|
function mediakindof(record2) {
|
|
4742
5111
|
if ("pages" in record2) return "pdf";
|
|
@@ -5018,6 +5387,11 @@ function isolatedinjection(step) {
|
|
|
5018
5387
|
}
|
|
5019
5388
|
return { world: "ISOLATED", code: step.value, args };
|
|
5020
5389
|
}
|
|
5390
|
+
var runsummarytask = "runsummary";
|
|
5391
|
+
function summaryrequestof(input) {
|
|
5392
|
+
if (input.payload.trim() === "") throw new Error("The runsummary request needs its payload reference.");
|
|
5393
|
+
return { id: input.id, runid: input.runid, stepid: input.sessionid, task: runsummarytask, payload: input.payload, transferables: [], sentat: input.sentat };
|
|
5394
|
+
}
|
|
5021
5395
|
|
|
5022
5396
|
// toolcatalog.ts
|
|
5023
5397
|
var toolcatalogversion = 1;
|
|
@@ -6673,6 +7047,226 @@ function consolediff(input) {
|
|
|
6673
7047
|
return { base: input.baseid, target: input.targetid, lines, added: added.length, removed: removed.length, repeated: repeated.length, at: input.now };
|
|
6674
7048
|
}
|
|
6675
7049
|
|
|
7050
|
+
// inboundguard.ts
|
|
7051
|
+
function shapeof(value) {
|
|
7052
|
+
if (typeof value === "string") return "string";
|
|
7053
|
+
if (typeof value === "number") return "number";
|
|
7054
|
+
if (typeof value === "boolean") return "boolean";
|
|
7055
|
+
if (Array.isArray(value)) return "array";
|
|
7056
|
+
return "object";
|
|
7057
|
+
}
|
|
7058
|
+
function schemacheck(input) {
|
|
7059
|
+
const errors = [];
|
|
7060
|
+
for (const [field, value] of Object.entries(input.command)) {
|
|
7061
|
+
const expected = input.schema[field];
|
|
7062
|
+
if (expected === void 0) {
|
|
7063
|
+
errors.push({ path: field, expected: "absent", found: shapeof(value), reason: `The ${field} field sits absent from the declared grammar of the command; schemastrict refuses unknown fields before dispatch.` });
|
|
7064
|
+
continue;
|
|
7065
|
+
}
|
|
7066
|
+
if (expected === "absent") {
|
|
7067
|
+
errors.push({ path: field, expected: "absent", found: shapeof(value), reason: `The ${field} field carries no value under the declared grammar; schemastrict refuses it before dispatch.` });
|
|
7068
|
+
continue;
|
|
7069
|
+
}
|
|
7070
|
+
if (shapeof(value) !== expected) errors.push({ path: field, expected, found: shapeof(value), reason: `The ${field} field expects a ${expected} while the command carries a ${shapeof(value)}; schemastrict refuses the shape mismatch before dispatch.` });
|
|
7071
|
+
}
|
|
7072
|
+
for (const field of input.required ?? []) {
|
|
7073
|
+
if (input.command[field] === void 0) errors.push({ path: field, expected: input.schema[field] ?? "string", found: "absent", reason: `The ${field} field is required by the declared grammar and the command carries no value; schemastrict refuses the incomplete command before dispatch.` });
|
|
7074
|
+
}
|
|
7075
|
+
return { valid: errors.length === 0, errors };
|
|
7076
|
+
}
|
|
7077
|
+
function origincheckof(input) {
|
|
7078
|
+
const sender = input.senderid ?? "an unknown sender";
|
|
7079
|
+
const origin = input.senderorigin ?? "";
|
|
7080
|
+
if (input.senderid === input.extensionid) return { accepted: true, sender, origin, reason: "The sender is this extension itself; the internal surface accepts." };
|
|
7081
|
+
if (input.senderid !== void 0 && input.connectallow.some((entry) => entry.senderid === input.senderid && (entry.origin === void 0 || entry.origin === origin))) {
|
|
7082
|
+
return { accepted: true, sender, origin, reason: `The sender ${sender} sits in the connectallow list the user manages${origin !== "" ? ` for ${origin}` : ""}; the message accepts.` };
|
|
7083
|
+
}
|
|
7084
|
+
if (input.senderid === void 0) return { accepted: false, sender, origin, reason: "The message carries no sender identity; the guard drops it before any handler runs." };
|
|
7085
|
+
return { accepted: false, sender, origin, reason: `The sender ${sender} sits absent from the connectallow list; the guard drops the message without handler execution.` };
|
|
7086
|
+
}
|
|
7087
|
+
function portaccept(input) {
|
|
7088
|
+
const verdict = origincheckof(input);
|
|
7089
|
+
if (!verdict.accepted) return { ...verdict, reason: `The port ${input.portname} closes at its handshake: ${verdict.reason}` };
|
|
7090
|
+
return { ...verdict, reason: `The port ${input.portname} accepted its handshake: ${verdict.reason}` };
|
|
7091
|
+
}
|
|
7092
|
+
function connectallowentryof(input) {
|
|
7093
|
+
if (input.senderid.trim() === "") throw new Error("The connectallow entry needs its sender id.");
|
|
7094
|
+
if (input.displayname.trim() === "") throw new Error("The connectallow entry needs its display name.");
|
|
7095
|
+
return { senderid: input.senderid.trim(), displayname: input.displayname.trim(), ...input.origin !== void 0 && input.origin.trim() !== "" ? { origin: input.origin.trim() } : {}, addedat: input.now };
|
|
7096
|
+
}
|
|
7097
|
+
function bucketboundsvalid(limit, window2) {
|
|
7098
|
+
if (!Number.isFinite(limit) || limit <= 0) return { valid: false, reason: "The ratelimit bucket limit stays a positive user value; no hidden ceiling exists." };
|
|
7099
|
+
if (!Number.isFinite(window2) || window2 <= 0) return { valid: false, reason: "The ratelimit bucket window stays a positive user value in milliseconds; the window reset stays the user's choice." };
|
|
7100
|
+
return { valid: true, reason: `The bucket bound of ${limit} commands per ${window2} milliseconds stays the user configured choice with no hidden ceiling.` };
|
|
7101
|
+
}
|
|
7102
|
+
function bucketof(input) {
|
|
7103
|
+
const bounds = bucketboundsvalid(input.limit, input.window);
|
|
7104
|
+
if (!bounds.valid) throw new Error(bounds.reason);
|
|
7105
|
+
return { origin: input.origin, sessionid: input.sessionid, limit: input.limit, window: input.window, used: 0, windowstartedat: input.now, resetsat: input.now + input.window };
|
|
7106
|
+
}
|
|
7107
|
+
function bucketconsume(input) {
|
|
7108
|
+
if (input.now >= input.bucket.resetsat) {
|
|
7109
|
+
const fresh = { ...input.bucket, used: 0, windowstartedat: input.now, resetsat: input.now + input.bucket.window };
|
|
7110
|
+
return { allowed: true, deferred: false, bucket: { ...fresh, used: 1 }, resetsat: fresh.resetsat, reason: `The bucket window of ${input.bucket.origin} reset and the command consumes the first slot of ${fresh.limit}.` };
|
|
7111
|
+
}
|
|
7112
|
+
if (input.bucket.used < input.bucket.limit) {
|
|
7113
|
+
return { allowed: true, deferred: false, bucket: { ...input.bucket, used: input.bucket.used + 1 }, resetsat: input.bucket.resetsat, reason: `The command consumes slot ${input.bucket.used + 1} of ${input.bucket.limit} in the bucket of ${input.bucket.origin}.` };
|
|
7114
|
+
}
|
|
7115
|
+
return { allowed: false, deferred: true, bucket: input.bucket, resetsat: input.bucket.resetsat, reason: `The bucket of ${input.bucket.origin} holds its ${input.bucket.limit} command bound; the command defers until the window resets at ${input.bucket.resetsat}.` };
|
|
7116
|
+
}
|
|
7117
|
+
function deferredeventof(input) {
|
|
7118
|
+
if (input.stepid.trim() === "" || input.kind.trim() === "") throw new Error("The deferred event needs its step and kind.");
|
|
7119
|
+
return { id: input.id ?? randomid(), stepid: input.stepid, kind: input.kind, origin: input.origin, reason: input.reason, resetsat: input.resetsat, at: input.now };
|
|
7120
|
+
}
|
|
7121
|
+
|
|
7122
|
+
// confirmgates.ts
|
|
7123
|
+
function stepoptions2(step) {
|
|
7124
|
+
if (!step.options) return {};
|
|
7125
|
+
try {
|
|
7126
|
+
const parsed = JSON.parse(step.options);
|
|
7127
|
+
return Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
7128
|
+
} catch {
|
|
7129
|
+
return {};
|
|
7130
|
+
}
|
|
7131
|
+
}
|
|
7132
|
+
function gatekindfor(classes) {
|
|
7133
|
+
if (classes.includes("payment")) return "confirmpay";
|
|
7134
|
+
if (classes.includes("delete")) return "confirmdelete";
|
|
7135
|
+
if (classes.includes("credential")) return "confirmcreds";
|
|
7136
|
+
return void 0;
|
|
7137
|
+
}
|
|
7138
|
+
function paypayload(input) {
|
|
7139
|
+
const payload = { payeeorigin: input.payeeorigin };
|
|
7140
|
+
if (input.amount !== void 0 && input.amount.trim() !== "") payload.amount = input.amount.trim();
|
|
7141
|
+
if (input.target !== void 0 && input.target.trim() !== "") payload.target = input.target.trim();
|
|
7142
|
+
return payload;
|
|
7143
|
+
}
|
|
7144
|
+
function deletepayload(input) {
|
|
7145
|
+
const payload = { scope: input.scope, irreversibility: input.irreversibility };
|
|
7146
|
+
if (input.target !== void 0 && input.target.trim() !== "") payload.target = input.target.trim();
|
|
7147
|
+
return payload;
|
|
7148
|
+
}
|
|
7149
|
+
function credspayload(label) {
|
|
7150
|
+
if (label.trim() === "") throw new Error("The confirmcreds gate names its credential label; the value never appears.");
|
|
7151
|
+
return { label: label.trim() };
|
|
7152
|
+
}
|
|
7153
|
+
function opengate(input) {
|
|
7154
|
+
if (input.stepid.trim() === "" || input.runid.trim() === "" || input.origin.trim() === "") throw new Error("The confirm gate needs its step, run and origin.");
|
|
7155
|
+
if (Object.keys(input.payload).length === 0) throw new Error("The confirm gate carries the payload the human reviews.");
|
|
7156
|
+
return { gateid: input.gateid ?? randomid(), kind: input.kind, stepid: input.stepid, runid: input.runid, origin: input.origin, payload: { ...input.payload }, state: "open", openedat: input.now };
|
|
7157
|
+
}
|
|
7158
|
+
function gatestateof(gates, stepid) {
|
|
7159
|
+
const gate = [...gates].reverse().find((candidate) => candidate.stepid === stepid);
|
|
7160
|
+
if (gate === void 0) return { state: "none" };
|
|
7161
|
+
return { state: gate.state, gate };
|
|
7162
|
+
}
|
|
7163
|
+
function resolvegate(input) {
|
|
7164
|
+
if (input.actor.trim() === "") throw new Error("The gate resolution names its acting user; only a human resolves a gate.");
|
|
7165
|
+
const gate = input.gates.find((candidate) => candidate.gateid === input.gateid);
|
|
7166
|
+
if (gate === void 0) return { gates: input.gates };
|
|
7167
|
+
if (gate.state !== "open") return { gates: input.gates };
|
|
7168
|
+
const resolution = { gateid: gate.gateid, kind: gate.kind, stepid: gate.stepid, decision: input.decision, actor: input.actor, at: input.now };
|
|
7169
|
+
return { gates: input.gates.map((candidate) => candidate.gateid === input.gateid ? { ...candidate, state: input.decision, resolvedat: input.now, actor: input.actor } : candidate), resolution };
|
|
7170
|
+
}
|
|
7171
|
+
function gateprompttext(gate) {
|
|
7172
|
+
if (gate.kind === "confirmpay") {
|
|
7173
|
+
const amount = gate.payload.amount !== void 0 ? `the amount ${gate.payload.amount}` : "an amount the step options name";
|
|
7174
|
+
const target = gate.payload.target !== void 0 ? ` on ${gate.payload.target}` : "";
|
|
7175
|
+
return `Approve the payment of ${amount} to ${gate.payload.payeeorigin}${target}? The step dispatches only after this distinct human action.`;
|
|
7176
|
+
}
|
|
7177
|
+
if (gate.kind === "confirmdelete") {
|
|
7178
|
+
const target = gate.payload.target !== void 0 ? ` on ${gate.payload.target}` : "";
|
|
7179
|
+
return `Approve the destructive delete${target} scoped to ${gate.payload.scope}? ${gate.payload.irreversibility} The step dispatches only after this distinct human action.`;
|
|
7180
|
+
}
|
|
7181
|
+
return `Approve the use of the credential ${gate.payload.label} on ${gate.origin}? The value stays behind the vault; the label is everything this prompt shows.`;
|
|
7182
|
+
}
|
|
7183
|
+
function gateforstep(input) {
|
|
7184
|
+
const kind = gatekindfor(input.classes);
|
|
7185
|
+
if (kind === void 0) return void 0;
|
|
7186
|
+
const options = stepoptions2(input.step);
|
|
7187
|
+
if (kind === "confirmpay") {
|
|
7188
|
+
const amount = typeof options.amount === "string" ? options.amount : typeof options.value === "string" ? options.value : void 0;
|
|
7189
|
+
return opengate({ kind, stepid: input.step.id, runid: input.runid, origin: input.origin, payload: paypayload({ ...amount !== void 0 && amount !== "" ? { amount } : {}, payeeorigin: String(options.payeeorigin ?? input.origin), ...input.step.target !== void 0 && input.step.target !== "" ? { target: input.step.target } : {} }), now: input.now });
|
|
7190
|
+
}
|
|
7191
|
+
if (kind === "confirmdelete") {
|
|
7192
|
+
return opengate({ kind, stepid: input.step.id, runid: input.runid, origin: input.origin, payload: deletepayload({ ...input.step.target !== void 0 && input.step.target !== "" ? { target: input.step.target } : {}, scope: String(options.scope ?? input.origin), irreversibility: String(options.irreversibility ?? "A destructive delete destroys state the page cannot restore.") }), now: input.now });
|
|
7193
|
+
}
|
|
7194
|
+
if (input.credentiallabel === void 0 || input.credentiallabel.trim() === "") return void 0;
|
|
7195
|
+
return opengate({ kind, stepid: input.step.id, runid: input.runid, origin: input.origin, payload: credspayload(input.credentiallabel), now: input.now });
|
|
7196
|
+
}
|
|
7197
|
+
|
|
7198
|
+
// phishguard.ts
|
|
7199
|
+
function stepoptions3(step) {
|
|
7200
|
+
if (!step.options) return {};
|
|
7201
|
+
try {
|
|
7202
|
+
const parsed = JSON.parse(step.options);
|
|
7203
|
+
return Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
7204
|
+
} catch {
|
|
7205
|
+
return {};
|
|
7206
|
+
}
|
|
7207
|
+
}
|
|
7208
|
+
function credentialstep(step) {
|
|
7209
|
+
const credentialkinds2 = /* @__PURE__ */ new Set(["consentpassword", "saveapikey", "handleauth", "authflow", "fillcard", "fillcode"]);
|
|
7210
|
+
if (credentialkinds2.has(step.kind)) return true;
|
|
7211
|
+
const options = stepoptions3(step);
|
|
7212
|
+
const fields = Array.isArray(options.fields) ? options.fields.filter((item) => Boolean(item) && typeof item === "object") : [];
|
|
7213
|
+
const names = [...fields.map((field) => typeof field.name === "string" ? field.name : ""), typeof options.field === "string" ? options.field : "", step.target ?? ""].map((name) => name.toLowerCase());
|
|
7214
|
+
return names.some((name) => name.includes("password") || name.includes("passwd") || name.includes("passphrase") || name.includes("token") || name.includes("secret") || name.includes("apikey"));
|
|
7215
|
+
}
|
|
7216
|
+
function originlabels(origin) {
|
|
7217
|
+
const host = origin.trim().replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").split("/")[0] ?? "";
|
|
7218
|
+
return host.split(".").filter((label) => label !== "").reverse();
|
|
7219
|
+
}
|
|
7220
|
+
function labeldistance(one, two) {
|
|
7221
|
+
const rows = one.length + 1;
|
|
7222
|
+
const columns = two.length + 1;
|
|
7223
|
+
let previous = Array.from({ length: columns }, (_, index) => index);
|
|
7224
|
+
for (let row = 1; row < rows; row += 1) {
|
|
7225
|
+
const current = [row, ...Array.from({ length: columns - 1 }, () => 0)];
|
|
7226
|
+
for (let column = 1; column < columns; column += 1) {
|
|
7227
|
+
const substitution = (previous[column - 1] ?? 0) + (one[row - 1] === two[column - 1] ? 0 : 1);
|
|
7228
|
+
current[column] = Math.min((previous[column] ?? 0) + 1, (current[column - 1] ?? 0) + 1, substitution);
|
|
7229
|
+
}
|
|
7230
|
+
previous = current;
|
|
7231
|
+
}
|
|
7232
|
+
return previous[columns - 1] ?? Math.max(one.length, two.length);
|
|
7233
|
+
}
|
|
7234
|
+
function lookalikedistance(one, two) {
|
|
7235
|
+
if (one.trim() === "" || two.trim() === "") return 1;
|
|
7236
|
+
if (one === two) return 0;
|
|
7237
|
+
const first = originlabels(one);
|
|
7238
|
+
const second = originlabels(two);
|
|
7239
|
+
const edits = labeldistance(first, second);
|
|
7240
|
+
const longest = Math.max(first.length, second.length);
|
|
7241
|
+
if (longest === 0) return 1;
|
|
7242
|
+
const distance = edits / longest;
|
|
7243
|
+
return Math.min(1, Math.max(0, distance));
|
|
7244
|
+
}
|
|
7245
|
+
function phishthresholdvalid(threshold) {
|
|
7246
|
+
if (!Number.isFinite(threshold) || threshold <= 0 || threshold >= 1) return { valid: false, reason: "The phishguard threshold stays a user choice between zero and one; the lookalike line never defaults." };
|
|
7247
|
+
return { valid: true, reason: `The lookalike threshold ${threshold} stays the user configured line a login origin crosses at its own risk.` };
|
|
7248
|
+
}
|
|
7249
|
+
function phishverdictof(input) {
|
|
7250
|
+
const threshold = phishthresholdvalid(input.threshold);
|
|
7251
|
+
if (!threshold.valid) throw new Error(threshold.reason);
|
|
7252
|
+
if (input.granted.includes(input.origin)) {
|
|
7253
|
+
return { origin: input.origin, distance: 0, threshold: input.threshold, blocked: false, reason: `The login origin ${input.origin} sits among the granted origins; no lookalike watch applies.`, at: input.now };
|
|
7254
|
+
}
|
|
7255
|
+
let matchedorigin;
|
|
7256
|
+
let distance = 1;
|
|
7257
|
+
for (const granted of input.granted) {
|
|
7258
|
+
const candidate = lookalikedistance(input.origin, granted);
|
|
7259
|
+
if (candidate < distance) {
|
|
7260
|
+
distance = candidate;
|
|
7261
|
+
matchedorigin = granted;
|
|
7262
|
+
}
|
|
7263
|
+
}
|
|
7264
|
+
if (matchedorigin !== void 0 && distance <= input.threshold) {
|
|
7265
|
+
return { origin: input.origin, matchedorigin, distance, threshold: input.threshold, blocked: true, reason: `The login origin ${input.origin} sits ${distance} away from the granted origin ${matchedorigin} and crosses the user threshold ${input.threshold}; the credential step blocks and the deny event names ${matchedorigin}.`, at: input.now };
|
|
7266
|
+
}
|
|
7267
|
+
return { origin: input.origin, ...matchedorigin !== void 0 ? { matchedorigin } : {}, distance, threshold: input.threshold, blocked: false, reason: matchedorigin !== void 0 ? `The login origin ${input.origin} sits ${distance} away from its closest granted origin ${matchedorigin} and stays under the user threshold ${input.threshold}.` : `The login origin ${input.origin} carries no granted origin to resemble; the watch records the first visit.`, at: input.now };
|
|
7268
|
+
}
|
|
7269
|
+
|
|
6676
7270
|
// policy.ts
|
|
6677
7271
|
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps", "emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "restoresession", "exportsessions", "importsessions", "runworkflow", "visitrule", "urlrule", "menurule", "keyrule", "buttonrule", "cronrule", "intervalrule", "urllistrule", "webhookrule", "eventrule"]);
|
|
6678
7272
|
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies", "setbreakpoint", "stepcode", "watchexpr", "loop", "repeatuntil", "whileloop", "foreach", "parallel", "trycatch"]);
|
|
@@ -9923,6 +10517,106 @@ function logreadgate(input) {
|
|
|
9923
10517
|
if (!input.valid) return { allowed: false, reason: input.brokenat !== void 0 ? `The log chain breaks at entry ${input.brokenat}; the audit accessor refuses the read of a forged record.` : "The log chain fails its verification; the audit accessor refuses the read of a forged record." };
|
|
9924
10518
|
return { allowed: true, reason: "The log chain verifies from the genesis hash to the last entry; the audit accessor serves the entries." };
|
|
9925
10519
|
}
|
|
10520
|
+
function schemaguardgate(input) {
|
|
10521
|
+
if (input.errors.length === 0) return { allowed: true, reason: "The inbound command matches its declared schemastrict grammar field by field." };
|
|
10522
|
+
const first = input.errors[0];
|
|
10523
|
+
return { allowed: false, reason: `${input.errors.length} schema error${input.errors.length === 1 ? "" : "s"} refuse the command before dispatch: ${input.errors.map((error) => error.reason).join(" ")}${first !== void 0 ? ` The first error sits at ${first.path} expecting ${first.expected}.` : ""}` };
|
|
10524
|
+
}
|
|
10525
|
+
function origincheckgate(input) {
|
|
10526
|
+
if (!input.verdict.accepted) return { allowed: false, reason: input.verdict.reason };
|
|
10527
|
+
return { allowed: true, reason: input.verdict.reason };
|
|
10528
|
+
}
|
|
10529
|
+
function ratelimitboundsvalid(limit, window2) {
|
|
10530
|
+
const bounds = bucketboundsvalid(limit, window2);
|
|
10531
|
+
if (!bounds.valid) return { allowed: false, reason: bounds.reason };
|
|
10532
|
+
return { allowed: true, reason: bounds.reason };
|
|
10533
|
+
}
|
|
10534
|
+
function confirmpaygate(input) {
|
|
10535
|
+
const kind = gatekindfor(input.classes);
|
|
10536
|
+
if (kind !== "confirmpay") return { allowed: true, reason: "The step carries no payment class and needs no confirmpay gate." };
|
|
10537
|
+
if (input.state === "resolved") return { allowed: true, reason: "The human resolved the confirmpay gate of the payment step; the step dispatches with its reviewed amount, payee origin and target." };
|
|
10538
|
+
if (input.state === "refused") return { allowed: false, reason: "The human refused the confirmpay gate of the payment step; the payment never dispatches." };
|
|
10539
|
+
if (input.state === "open") return { allowed: false, reason: "The confirmpay gate of the payment step stays open with the amount, the payee origin and the target element; the executor pauses until the human resolves it and no timeout ever resolves a gate." };
|
|
10540
|
+
return { allowed: false, reason: "The payment step opens its confirmpay gate with the amount, the payee origin and the target element; the executor pauses until one distinct human action resolves it." };
|
|
10541
|
+
}
|
|
10542
|
+
function confirmdeletegate(input) {
|
|
10543
|
+
const kind = gatekindfor(input.classes);
|
|
10544
|
+
if (kind !== "confirmdelete") return { allowed: true, reason: "The step carries no delete class and needs no confirmdelete gate." };
|
|
10545
|
+
if (input.state === "resolved") return { allowed: true, reason: "The human resolved the confirmdelete gate of the destructive step; the step dispatches with its reviewed target, scope and irreversibility." };
|
|
10546
|
+
if (input.state === "refused") return { allowed: false, reason: "The human refused the confirmdelete gate of the destructive step; the deletion never dispatches." };
|
|
10547
|
+
if (input.state === "open") return { allowed: false, reason: "The confirmdelete gate of the destructive step stays open with the target, the scope and the irreversibility; the executor pauses until the human resolves it and no timeout ever resolves a gate." };
|
|
10548
|
+
return { allowed: false, reason: "The destructive step opens its confirmdelete gate with the target, the scope and the irreversibility; the executor pauses until one distinct human action resolves it." };
|
|
10549
|
+
}
|
|
10550
|
+
function confirmcredsgate(input) {
|
|
10551
|
+
const kind = gatekindfor(input.classes);
|
|
10552
|
+
if (kind !== "confirmcreds") return { allowed: true, reason: "The step carries no credential class and needs no confirmcreds gate." };
|
|
10553
|
+
if (input.state === "resolved") return { allowed: true, reason: "The human resolved the confirmcreds gate of the credential step; the step reads its value from the vault at the last possible moment and no log records it." };
|
|
10554
|
+
if (input.state === "refused") return { allowed: false, reason: "The human refused the confirmcreds gate of the credential step; the credential never dispatches." };
|
|
10555
|
+
if (input.state === "open") return { allowed: false, reason: "The confirmcreds gate of the credential step stays open with its credential label only; the executor pauses until the human resolves it and no timeout ever resolves a gate." };
|
|
10556
|
+
return { allowed: false, reason: "The credential step opens its confirmcreds gate with its credential label only; the executor pauses until one distinct human action resolves it." };
|
|
10557
|
+
}
|
|
10558
|
+
function phishthresholdgate(threshold) {
|
|
10559
|
+
const verdict = phishthresholdvalid(threshold);
|
|
10560
|
+
if (!verdict.valid) return { allowed: false, reason: verdict.reason };
|
|
10561
|
+
return { allowed: true, reason: verdict.reason };
|
|
10562
|
+
}
|
|
10563
|
+
function phishguardgate(input) {
|
|
10564
|
+
if (input.verdict.blocked) return { allowed: false, reason: input.verdict.reason };
|
|
10565
|
+
return { allowed: true, reason: input.verdict.reason };
|
|
10566
|
+
}
|
|
10567
|
+
function safedefaultsgate(input) {
|
|
10568
|
+
if (input.profile !== void 0) return { allowed: true, reason: `The origin profile of ${input.profile.origin} exists; the safedefaults posture stays out of the decision.` };
|
|
10569
|
+
if (!input.sensitive) return { allowed: true, reason: "The non-sensitive step rides the reads only baseline of the safedefaults posture; the first visit grants reads alone." };
|
|
10570
|
+
return { allowed: false, reason: `No origin profile exists and the safedefaults posture denies the sensitive ${input.classes.length > 0 ? input.classes.join(" and ") : "by default"} step; open the originprofile editor to widen the profile the user controls.` };
|
|
10571
|
+
}
|
|
10572
|
+
function vaultsecretgate(input) {
|
|
10573
|
+
if (input.leaks.length > 0) return { allowed: false, reason: `The plan carries ${input.leaks.length} plaintext secret value${input.leaks.length === 1 ? "" : "s"} that digest to vault records; secrets never ride step options, variables or plan texts, only the vault holds them.` };
|
|
10574
|
+
if (input.carries) return { allowed: false, reason: "The step types a raw value into a masked field shape; credential steps read their value from the vault at the last possible moment and never carry it in the options." };
|
|
10575
|
+
return { allowed: true, reason: "The step and the plan carry no secret outside the vault; the values stay behind the seam." };
|
|
10576
|
+
}
|
|
10577
|
+
function untrustedrendergate(input) {
|
|
10578
|
+
if (input.environment === "sandboxframe") return { allowed: true, reason: "The extracted markup renders inside the sandboxframe under its nonce with scripts and handlers stripped; the untrusted content never reenters the page context." };
|
|
10579
|
+
return { allowed: false, reason: `The extracted markup grades untrusted and refuses to render inside the ${input.environment}; every untrusted render routes through the sandboxframe.` };
|
|
10580
|
+
}
|
|
10581
|
+
function sitenotesreadgate(input) {
|
|
10582
|
+
if (input.grants.includes(input.origin)) return { allowed: true, reason: `The session granted ${input.origin}, so the site notes of the origin read.` };
|
|
10583
|
+
return { allowed: false, reason: `The session never granted ${input.origin}; the site notes of the origin refuse the read.` };
|
|
10584
|
+
}
|
|
10585
|
+
function sitenoteswritegate(input) {
|
|
10586
|
+
if (!input.consent) return { allowed: false, reason: `The site note write for ${input.origin} needs the explicit consent of the user; no note lands without a reviewed write.` };
|
|
10587
|
+
return { allowed: true, reason: `The user consented to the site note write for ${input.origin}; the note keeps its author provenance and its timestamps.` };
|
|
10588
|
+
}
|
|
10589
|
+
function scratchpadscopegate(input) {
|
|
10590
|
+
if (input.taskid !== input.entrytaskid || input.sessionid !== input.entrysessionid) return { allowed: false, reason: `The scratchpad entry belongs to the task ${input.entrytaskid} of the session ${input.entrysessionid}; the task ${input.taskid} of the session ${input.sessionid} never crosses that boundary.` };
|
|
10591
|
+
return { allowed: true, reason: `The scratchpad entry belongs to the task ${input.taskid} of the session ${input.sessionid} that asks for it.` };
|
|
10592
|
+
}
|
|
10593
|
+
function memoryreadscopegate(input) {
|
|
10594
|
+
if (input.phase === "planning" || input.phase === "prompting") return { allowed: true, reason: `The ${input.phase} phase reads the correction and consent memory so the proposal and the prompt carry the prior decisions.` };
|
|
10595
|
+
return { allowed: false, reason: `The ${input.phase} phase reads no correction or consent memory; the history serves the planning and the prompting alone.` };
|
|
10596
|
+
}
|
|
10597
|
+
function semanticrecallscopegate(input) {
|
|
10598
|
+
if (input.origin === void 0) return { allowed: true, reason: `The recall query names no origin, so it ranks the ${input.scope.length} origin${input.scope.length === 1 ? "" : "s"} of the run scope only.` };
|
|
10599
|
+
if (!input.scope.includes(input.origin)) return { allowed: false, reason: `The recall query asks for ${input.origin} while the run scope holds ${input.scope.length > 0 ? input.scope.join(", ") : "no origin"}; a recall across origins outside the run scope refuses.` };
|
|
10600
|
+
return { allowed: true, reason: `The recall query asks for ${input.origin} inside the run scope; the ranking stays scoped.` };
|
|
10601
|
+
}
|
|
10602
|
+
function summarywindowvalid(window2) {
|
|
10603
|
+
if (window2 === void 0) return { allowed: true, reason: "No runsummary window is configured, so the distillation keeps every step with no fixed cap." };
|
|
10604
|
+
if (!Number.isInteger(window2) || window2 < 0) return { allowed: false, reason: "The runsummary window stays a whole number of steps the user chose; no engine cap exists." };
|
|
10605
|
+
return { allowed: true, reason: `The runsummary window of ${window2} step${window2 === 1 ? "" : "s"} stays the user configured choice; no engine cap exists.` };
|
|
10606
|
+
}
|
|
10607
|
+
function sessionretentionvalid(window2) {
|
|
10608
|
+
if (window2 === void 0) return { allowed: true, reason: "No retention window is configured, so the session store keeps every record forever." };
|
|
10609
|
+
if (!Number.isFinite(window2) || window2 <= 0) return { allowed: false, reason: "The retention window stays a positive user value in milliseconds; no engine boundary expires a record." };
|
|
10610
|
+
return { allowed: true, reason: `The retention window of ${window2} milliseconds stays the user configured choice.` };
|
|
10611
|
+
}
|
|
10612
|
+
function cancelrungate(input) {
|
|
10613
|
+
if (input.rollbackscope === "none") return { allowed: true, reason: `The cancelrun stops the run with no rollback; the ${input.queuedstepids.length} queued step${input.queuedstepids.length === 1 ? "" : "s"} stay as the run left them and the ${input.executedstepids.length} executed step${input.executedstepids.length === 1 ? "" : "s"} stay in the sealed log.` };
|
|
10614
|
+
return { allowed: true, reason: `The cancelrun rolls the ${input.queuedstepids.length} queued step${input.queuedstepids.length === 1 ? "" : "s"} back${input.queuedstepids.length > 0 ? ` (${input.queuedstepids.join(", ")})` : ""} while the ${input.executedstepids.length} executed step${input.executedstepids.length === 1 ? "" : "s"} stay untouched in the sealed log.` };
|
|
10615
|
+
}
|
|
10616
|
+
function retrydispatchgate(input) {
|
|
10617
|
+
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
|
+
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
|
+
}
|
|
9926
10620
|
|
|
9927
10621
|
// progress.ts
|
|
9928
10622
|
function emptyprogress(planid, now) {
|
|
@@ -9945,6 +10639,10 @@ function recordturnaround2(progress, planid, stepid, milliseconds, now) {
|
|
|
9945
10639
|
const base = progress && progress.planid === planid ? progress : emptyprogress(planid, now);
|
|
9946
10640
|
return { ...base, turnarounds: { ...base.turnarounds ?? {}, [stepid]: milliseconds }, updatedat: now };
|
|
9947
10641
|
}
|
|
10642
|
+
function recordgatewait(progress, planid, stepid, entry, now) {
|
|
10643
|
+
const base = progress && progress.planid === planid ? progress : emptyprogress(planid, now);
|
|
10644
|
+
return { ...base, gatewaits: { ...base.gatewaits ?? {}, [stepid]: entry }, updatedat: now };
|
|
10645
|
+
}
|
|
9948
10646
|
function iscomplete(progress, plan) {
|
|
9949
10647
|
if (!progress || progress.planid !== plan.id) return false;
|
|
9950
10648
|
const required = plan.steps.map((step) => step.id);
|
|
@@ -10169,7 +10867,7 @@ function maskexport(record2, shapes) {
|
|
|
10169
10867
|
}
|
|
10170
10868
|
|
|
10171
10869
|
// version.ts
|
|
10172
|
-
var packageversion = "1.1.
|
|
10870
|
+
var packageversion = "1.1.63";
|
|
10173
10871
|
|
|
10174
10872
|
// types.ts
|
|
10175
10873
|
var protocolversion = packageversion;
|
|
@@ -11143,6 +11841,9 @@ function environmentreport(input) {
|
|
|
11143
11841
|
...input.keepalive !== void 0 ? { keepalive: input.keepalive } : {}
|
|
11144
11842
|
};
|
|
11145
11843
|
}
|
|
11844
|
+
function transparencyreport(input) {
|
|
11845
|
+
return { version: protocolversion, posture: "denydefault", grants: input.grants, windows: input.windows, connectallow: input.connectallow, permdiffs: input.permdiffs, safedefaults: input.safedefaults, vault: input.vault };
|
|
11846
|
+
}
|
|
11146
11847
|
|
|
11147
11848
|
// capture.ts
|
|
11148
11849
|
var capturekinds = ["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"];
|
|
@@ -11646,7 +12347,7 @@ async function readcapabilities() {
|
|
|
11646
12347
|
]);
|
|
11647
12348
|
return { tabs, downloads, clipboardread, clipboardwrite, reportedat: Date.now() };
|
|
11648
12349
|
}
|
|
11649
|
-
function
|
|
12350
|
+
function stepoptions4(step) {
|
|
11650
12351
|
if (!step.options) return {};
|
|
11651
12352
|
try {
|
|
11652
12353
|
const parsed = JSON.parse(step.options);
|
|
@@ -11659,7 +12360,7 @@ function tabid(step) {
|
|
|
11659
12360
|
return Number.parseInt(step.value ?? "", 10);
|
|
11660
12361
|
}
|
|
11661
12362
|
async function runbrowseraction(step, sessiontabid, windowid) {
|
|
11662
|
-
const options =
|
|
12363
|
+
const options = stepoptions4(step);
|
|
11663
12364
|
switch (step.kind) {
|
|
11664
12365
|
case "tablist": {
|
|
11665
12366
|
const tabs = await chrome.tabs.query({});
|
|
@@ -12285,6 +12986,200 @@ function endcall(input) {
|
|
|
12285
12986
|
return { contexts: input.contexts.map((candidate) => candidate.callid === input.callid ? context : candidate), context };
|
|
12286
12987
|
}
|
|
12287
12988
|
|
|
12989
|
+
// sessioninterface.ts
|
|
12990
|
+
function textfingerprint(text2) {
|
|
12991
|
+
let hash = 2166136261;
|
|
12992
|
+
for (let index = 0; index < text2.length; index += 1) {
|
|
12993
|
+
hash ^= text2.charCodeAt(index);
|
|
12994
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
12995
|
+
}
|
|
12996
|
+
return hash.toString(16).padStart(8, "0");
|
|
12997
|
+
}
|
|
12998
|
+
function keystreambyte(id, position) {
|
|
12999
|
+
let hash = 2166136261;
|
|
13000
|
+
const source = `${id}:${position}`;
|
|
13001
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
13002
|
+
hash ^= source.charCodeAt(index);
|
|
13003
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
13004
|
+
}
|
|
13005
|
+
return hash & 255;
|
|
13006
|
+
}
|
|
13007
|
+
function sealnotebody(id, body) {
|
|
13008
|
+
const sealed = Array.from(body, (character, index) => String.fromCharCode(character.charCodeAt(0) ^ keystreambyte(id, index))).join("");
|
|
13009
|
+
return `sealed:${btoa(sealed)}`;
|
|
13010
|
+
}
|
|
13011
|
+
function opennotebody(id, sealedbody) {
|
|
13012
|
+
if (!sealedbody.startsWith("sealed:")) return "";
|
|
13013
|
+
try {
|
|
13014
|
+
const sealed = atob(sealedbody.slice("sealed:".length));
|
|
13015
|
+
return Array.from(sealed, (character, index) => String.fromCharCode(character.charCodeAt(0) ^ keystreambyte(id, index))).join("");
|
|
13016
|
+
} catch {
|
|
13017
|
+
return "";
|
|
13018
|
+
}
|
|
13019
|
+
}
|
|
13020
|
+
function sitenoteof(input) {
|
|
13021
|
+
if (input.origin.trim() === "") throw new Error("The site note needs its origin.");
|
|
13022
|
+
if (input.title.trim() === "") throw new Error("The site note needs its title.");
|
|
13023
|
+
if (input.body.trim() === "") throw new Error("The site note needs its body.");
|
|
13024
|
+
const id = input.id ?? randomid();
|
|
13025
|
+
if (input.sensitive === true) return { id, origin: input.origin, title: input.title.trim(), sealedbody: sealnotebody(id, input.body), author: input.author, sensitive: true, createdat: input.now, updatedat: input.now };
|
|
13026
|
+
return { id, origin: input.origin, title: input.title.trim(), body: input.body, author: input.author, sensitive: false, createdat: input.now, updatedat: input.now };
|
|
13027
|
+
}
|
|
13028
|
+
function notebodyof(note) {
|
|
13029
|
+
if (note.sensitive) return note.sealedbody !== void 0 ? opennotebody(note.id, note.sealedbody) : "";
|
|
13030
|
+
return note.body ?? "";
|
|
13031
|
+
}
|
|
13032
|
+
function editnote(note, input) {
|
|
13033
|
+
if (input.title.trim() === "") throw new Error("The site note keeps a non empty title.");
|
|
13034
|
+
if (input.body.trim() === "") throw new Error("The site note keeps a non empty body.");
|
|
13035
|
+
if (note.sensitive) return { ...note, title: input.title.trim(), sealedbody: sealnotebody(note.id, input.body), updatedat: input.now, author: input.author };
|
|
13036
|
+
return { ...note, title: input.title.trim(), body: input.body, updatedat: input.now, author: input.author };
|
|
13037
|
+
}
|
|
13038
|
+
function scratchentryof(input) {
|
|
13039
|
+
if (input.taskid.trim() === "") throw new Error("The scratchpad entry needs its task.");
|
|
13040
|
+
if (input.text.trim() === "") throw new Error("The scratchpad entry needs its text.");
|
|
13041
|
+
return { id: input.id ?? randomid(), taskid: input.taskid, sessionid: input.sessionid, text: input.text, ...input.stepid !== void 0 && input.stepid.trim() !== "" ? { stepid: input.stepid } : {}, author: input.author, at: input.now };
|
|
13042
|
+
}
|
|
13043
|
+
function distillrunsummary(input) {
|
|
13044
|
+
const steps = input.outcomes.map((outcome) => {
|
|
13045
|
+
const step = input.plan.steps.find((candidate) => candidate.id === outcome.stepid);
|
|
13046
|
+
return { stepid: outcome.stepid, kind: step?.kind ?? "unknown", ok: outcome.ok, summary: outcome.summary };
|
|
13047
|
+
});
|
|
13048
|
+
const windowed = input.window !== void 0 && Number.isInteger(input.window) && input.window >= 0 ? steps.slice(Math.max(0, steps.length - input.window)) : steps;
|
|
13049
|
+
const kinds = [...new Set(windowed.map((step) => step.kind))];
|
|
13050
|
+
return { runid: input.plan.id, sessionid: input.sessionid, origins: [...new Set(input.origins)], kinds, steps: windowed, ...input.window !== void 0 && Number.isInteger(input.window) && input.window >= 0 ? { window: input.window } : {}, task: "runsummary", provenance: input.provenance, distilledat: input.now };
|
|
13051
|
+
}
|
|
13052
|
+
function summaryhistoryentry(summary) {
|
|
13053
|
+
return { source: "summary", id: summary.runid, title: `Run summary of ${summary.runid}`, text: `${summary.origins.join(" ")} ${summary.kinds.join(" ")} ${summary.steps.map((step) => step.summary).join(" ")}`, outcome: summary.steps.every((step) => step.ok) ? "completed" : "failed", at: summary.distilledat };
|
|
13054
|
+
}
|
|
13055
|
+
function notehistoryentry(note) {
|
|
13056
|
+
return { source: "note", id: note.id, ...note.origin !== "" ? { origin: note.origin } : {}, title: note.title, text: note.sensitive ? note.title : `${note.title} ${note.body ?? ""}`, at: note.updatedat };
|
|
13057
|
+
}
|
|
13058
|
+
function recallentryof(input) {
|
|
13059
|
+
if (input.text.trim() === "") throw new Error("The recall index entry needs its text.");
|
|
13060
|
+
if (input.stepid.trim() === "" || input.runid.trim() === "") throw new Error("The recall index entry needs its run and step provenance.");
|
|
13061
|
+
const normalized = input.text.trim().replace(/\s+/g, " ");
|
|
13062
|
+
return { fingerprint: textfingerprint(normalized), origin: input.origin, runid: input.runid, stepid: input.stepid, text: normalized, at: input.at };
|
|
13063
|
+
}
|
|
13064
|
+
function termsof(text2) {
|
|
13065
|
+
return new Set(text2.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 1));
|
|
13066
|
+
}
|
|
13067
|
+
function rankrecall(index, query, scope) {
|
|
13068
|
+
if (query.text.trim() === "") return [];
|
|
13069
|
+
const terms = termsof(query.text);
|
|
13070
|
+
const scoped = query.origin !== void 0 && query.origin.trim() !== "" ? [query.origin] : scope.origins;
|
|
13071
|
+
const matches = [];
|
|
13072
|
+
for (const entry of index) {
|
|
13073
|
+
if (!scoped.includes(entry.origin)) continue;
|
|
13074
|
+
const entryterms = termsof(entry.text);
|
|
13075
|
+
let shared = 0;
|
|
13076
|
+
for (const term of terms) if (entryterms.has(term)) shared += 1;
|
|
13077
|
+
const union = (/* @__PURE__ */ new Set([...terms, ...entryterms])).size;
|
|
13078
|
+
const score = union === 0 ? 0 : shared / union;
|
|
13079
|
+
if (score <= 0) continue;
|
|
13080
|
+
matches.push({ entry, score, reason: `The extraction of ${entry.origin} shares ${shared} term${shared === 1 ? "" : "s"} with the query at the score ${score.toFixed(3)}; the match carries the run ${entry.runid} and the step ${entry.stepid}.` });
|
|
13081
|
+
}
|
|
13082
|
+
const ranked = matches.sort((one, two) => two.score - one.score);
|
|
13083
|
+
return query.limit !== void 0 && Number.isInteger(query.limit) && query.limit >= 0 ? ranked.slice(0, query.limit) : ranked;
|
|
13084
|
+
}
|
|
13085
|
+
function editedcorrectionof(input) {
|
|
13086
|
+
if (input.stepid.trim() === "" || input.kind.trim() === "") throw new Error("The correction needs its step and kind.");
|
|
13087
|
+
if (input.original === input.corrected) throw new Error("The correction needs a changed step shape.");
|
|
13088
|
+
return { id: input.id ?? randomid(), origin: input.origin, kind: input.kind, stepid: input.stepid, source: "edited", original: input.original, corrected: input.corrected, reason: input.reason, at: input.now };
|
|
13089
|
+
}
|
|
13090
|
+
function rejectedcorrectionof(input) {
|
|
13091
|
+
if (input.stepid.trim() === "" || input.reason.trim() === "") throw new Error("The rejected correction needs its step and its rejection reason.");
|
|
13092
|
+
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
|
+
}
|
|
13094
|
+
function consentmemoryof(input) {
|
|
13095
|
+
if (input.origin.trim() === "") throw new Error("The consent memory entry needs its origin.");
|
|
13096
|
+
if (input.boundary.trim() === "") throw new Error("The consent memory entry needs the boundary the prompt named.");
|
|
13097
|
+
return { id: input.id ?? randomid(), origin: input.origin, decision: input.decision, boundary: input.boundary, kinds: [...new Set(input.kinds)], at: input.now, ...input.expiresat !== void 0 ? { expiresat: input.expiresat } : {} };
|
|
13098
|
+
}
|
|
13099
|
+
function consentadvisoryverdict(entries, origin, kind) {
|
|
13100
|
+
const matching = entries.filter((entry) => entry.origin === origin && entry.kinds.includes(kind));
|
|
13101
|
+
const latest = matching[matching.length - 1];
|
|
13102
|
+
if (latest === void 0) return { advisory: false, reason: `No prior decision exists for the ${kind} kind on ${origin}; the prompt opens fresh.` };
|
|
13103
|
+
if (latest.decision === "deny") return { advisory: true, reason: `The consent memory holds a prior denial of the ${kind} kind on ${origin} from ${new Date(latest.at).toISOString()}; the denial carries the same weight as a grant and the record stays advisory only.` };
|
|
13104
|
+
return { advisory: true, reason: `The consent memory holds a prior ${latest.decision} of the ${kind} kind on ${origin} with the boundary ${latest.boundary}; the record advises the new prompt and never auto grants.` };
|
|
13105
|
+
}
|
|
13106
|
+
function rollbacksplit(plan, progress) {
|
|
13107
|
+
const executed = progress && progress.planid === plan?.id ? progress.completedsteps : [];
|
|
13108
|
+
const executedset = new Set(executed);
|
|
13109
|
+
const queued = (plan?.steps ?? []).map((step) => step.id).filter((id) => !executedset.has(id));
|
|
13110
|
+
return { executedstepids: executed, queuedstepids: queued };
|
|
13111
|
+
}
|
|
13112
|
+
function rollbackof(plan, progress, preference) {
|
|
13113
|
+
const split = rollbacksplit(plan, progress);
|
|
13114
|
+
if (preference === "none") return { scope: "none", label: `Stop the run ${plan?.id ?? ""} without a rollback; the ${split.queuedstepids.length} queued step${split.queuedstepids.length === 1 ? "" : "s"} stay as the run left them.`, queuedstepids: split.queuedstepids };
|
|
13115
|
+
return { scope: "queued", label: `Cancel the run ${plan?.id ?? ""} and roll its ${split.queuedstepids.length} queued step${split.queuedstepids.length === 1 ? "" : "s"} back${split.queuedstepids.length > 0 ? ` (${split.queuedstepids.join(", ")})` : ""} while the ${split.executedstepids.length} executed step${split.executedstepids.length === 1 ? "" : "s"} stay untouched in the sealed log.`, queuedstepids: split.queuedstepids };
|
|
13116
|
+
}
|
|
13117
|
+
function cancelrunactionof(input) {
|
|
13118
|
+
return { runid: input.runid, sessionid: input.sessionid, rollback: rollbackof(input.plan, input.progress, input.preference) };
|
|
13119
|
+
}
|
|
13120
|
+
function errorsurfaceof(input) {
|
|
13121
|
+
if (input.message.trim() === "") throw new Error("The error surface needs its message in plain language.");
|
|
13122
|
+
return { stepid: input.stepid, runid: input.runid, cause: input.cause, message: input.message, retry: { allowed: input.retryallowed, reason: input.retryreason }, context: input.context, at: input.now };
|
|
13123
|
+
}
|
|
13124
|
+
function classifyfailure(input) {
|
|
13125
|
+
if (input.gatewait) return "gate";
|
|
13126
|
+
if (input.policyrefused) return "policy";
|
|
13127
|
+
if (/\b(network|offline|timeout|timed out|fetch failed|socket|dns|connection)\b/i.test(input.message)) return "network";
|
|
13128
|
+
return "page";
|
|
13129
|
+
}
|
|
13130
|
+
function sessiongridrows(input) {
|
|
13131
|
+
const rows = [];
|
|
13132
|
+
if (input.session && input.plan && ["pending", "approved"].includes(input.plan.state)) {
|
|
13133
|
+
const split = rollbacksplit(input.plan, input.progress);
|
|
13134
|
+
const held = input.locks.some((lock) => lock.runid === input.plan?.id);
|
|
13135
|
+
const origins = [.../* @__PURE__ */ new Set([input.session.origin, ...input.session.grants ?? []])];
|
|
13136
|
+
const actions = ["cancelrun"];
|
|
13137
|
+
if (input.session.pausedat !== void 0) actions.push("resume");
|
|
13138
|
+
rows.push({ sessionid: input.session.id, runid: input.plan.id, origins, state: "live", outcome: `${split.executedstepids.length} of ${input.plan.steps.length} reviewed steps executed`, steps: input.plan.steps.length, completed: split.executedstepids.length, lock: held ? "held" : "free", tabid: input.session.tabid, updatedat: input.plan.createdat, actions });
|
|
13139
|
+
}
|
|
13140
|
+
for (const log of input.logs) {
|
|
13141
|
+
const summary = input.summaries.find((candidate) => candidate.runid === log.runid);
|
|
13142
|
+
const tabsession = input.tabsessions.find((candidate) => candidate.runid === log.runid);
|
|
13143
|
+
const held = input.locks.some((lock) => lock.runid === log.runid);
|
|
13144
|
+
rows.push({ sessionid: log.sessionid, runid: log.runid, origins: [...new Set(log.entries.map((entry) => entry.origin).filter((origin) => origin !== ""))], state: "saved", outcome: summary !== void 0 ? summary.steps.every((step) => step.ok) ? "completed" : "failed" : log.seal !== void 0 ? "sealed" : "open", steps: summary?.steps.length ?? log.entries.filter((entry) => entry.kind === "step").length, completed: summary?.steps.filter((step) => step.ok).length ?? log.entries.filter((entry) => entry.kind === "step").length, lock: held ? "held" : "free", ...log.seal !== void 0 ? { sealhash: log.seal.sealhash.current } : {}, ...tabsession !== void 0 ? { tabid: tabsession.tabid } : {}, updatedat: log.updatedat, actions: ["reopen"] });
|
|
13145
|
+
}
|
|
13146
|
+
return rows.sort((one, two) => two.updatedat - one.updatedat);
|
|
13147
|
+
}
|
|
13148
|
+
function historyqueryof(value) {
|
|
13149
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
13150
|
+
const candidate = value;
|
|
13151
|
+
if (typeof candidate.text !== "string" || candidate.text.trim() === "") return void 0;
|
|
13152
|
+
const origin = typeof candidate.origin === "string" && candidate.origin.trim() !== "" ? candidate.origin.trim() : void 0;
|
|
13153
|
+
const from = typeof candidate.from === "number" && Number.isFinite(candidate.from) ? candidate.from : void 0;
|
|
13154
|
+
const to = typeof candidate.to === "number" && Number.isFinite(candidate.to) ? candidate.to : void 0;
|
|
13155
|
+
if (from !== void 0 && to !== void 0 && from > to) return void 0;
|
|
13156
|
+
const outcome = typeof candidate.outcome === "string" && candidate.outcome.trim() !== "" ? candidate.outcome.trim() : void 0;
|
|
13157
|
+
return { text: candidate.text.trim(), ...origin !== void 0 ? { origin } : {}, ...from !== void 0 ? { from } : {}, ...to !== void 0 ? { to } : {}, ...outcome !== void 0 ? { outcome } : {} };
|
|
13158
|
+
}
|
|
13159
|
+
function historysearch(corpus, query) {
|
|
13160
|
+
const terms = query.text.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 1);
|
|
13161
|
+
const hits = [];
|
|
13162
|
+
for (const entry of corpus) {
|
|
13163
|
+
if (query.origin !== void 0 && entry.origin !== query.origin) continue;
|
|
13164
|
+
if (query.from !== void 0 && entry.at < query.from) continue;
|
|
13165
|
+
if (query.to !== void 0 && entry.at > query.to) continue;
|
|
13166
|
+
if (query.outcome !== void 0 && entry.outcome !== query.outcome) continue;
|
|
13167
|
+
const haystack = `${entry.title} ${entry.text}`.toLowerCase();
|
|
13168
|
+
const matched = terms.filter((term) => haystack.includes(term));
|
|
13169
|
+
if (matched.length === 0) continue;
|
|
13170
|
+
const position = haystack.indexOf(matched[0] ?? "");
|
|
13171
|
+
const start = Math.max(0, position - 40);
|
|
13172
|
+
const excerpt = `${start > 0 ? "\u2026" : ""}${`${entry.title} ${entry.text}`.slice(start, start + 160)}${start + 160 < `${entry.title} ${entry.text}`.length ? "\u2026" : ""}`;
|
|
13173
|
+
hits.push({ source: entry.source, id: entry.id, title: entry.title, excerpt, highlights: [...new Set(matched)], ...entry.origin !== void 0 ? { origin: entry.origin } : {}, ...entry.outcome !== void 0 ? { outcome: entry.outcome } : {}, at: entry.at });
|
|
13174
|
+
}
|
|
13175
|
+
return hits.sort((one, two) => two.at - one.at);
|
|
13176
|
+
}
|
|
13177
|
+
function tabsessionrefof(input) {
|
|
13178
|
+
if (!Number.isInteger(input.tabid) || input.tabid < 0) throw new Error("The per tab session reference needs its tab.");
|
|
13179
|
+
if (input.sessionid.trim() === "") throw new Error("The per tab session reference needs its session.");
|
|
13180
|
+
return { tabid: input.tabid, sessionid: input.sessionid, ...input.runid !== void 0 && input.runid.trim() !== "" ? { runid: input.runid } : {}, origin: input.origin, updatedat: input.now };
|
|
13181
|
+
}
|
|
13182
|
+
|
|
12288
13183
|
// llm.ts
|
|
12289
13184
|
var defaultrefusalmarkers = ["i cannot", "i can't", "i'm unable", "refusal:", "cannot comply"];
|
|
12290
13185
|
function buildrequest(input) {
|
|
@@ -13119,6 +14014,144 @@ function acceptrenderresult(input) {
|
|
|
13119
14014
|
return { accepted: true, result, reason: `The render result of the step ${render.stepid} answers the nonce of its render; the text stays inside the frame.` };
|
|
13120
14015
|
}
|
|
13121
14016
|
|
|
14017
|
+
// secretvault.ts
|
|
14018
|
+
var vaultdigestprefix = "sha256:";
|
|
14019
|
+
async function vaultdigestof(value) {
|
|
14020
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
|
|
14021
|
+
return vaultdigestprefix + [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
14022
|
+
}
|
|
14023
|
+
function vaultentryof(input) {
|
|
14024
|
+
if (input.label.trim() === "") throw new Error("The vault record needs its label; the surfaces show the label only.");
|
|
14025
|
+
if (input.scope.trim() === "") throw new Error("The vault record needs its exact origin scope; a secret never rides every origin.");
|
|
14026
|
+
if (!input.digest.startsWith(vaultdigestprefix)) throw new Error("The vault record carries its sha-256 digest, never its value.");
|
|
14027
|
+
return { vaultid: input.vaultid ?? randomid(), label: input.label.trim(), scope: input.scope.trim(), profileid: input.profileid, provenance: input.provenance, algorithm: "sha-256", digest: input.digest, createdat: input.now };
|
|
14028
|
+
}
|
|
14029
|
+
function inmemoryvault() {
|
|
14030
|
+
const values = /* @__PURE__ */ new Map();
|
|
14031
|
+
return {
|
|
14032
|
+
put: async (vaultid, value) => {
|
|
14033
|
+
values.set(vaultid, value);
|
|
14034
|
+
},
|
|
14035
|
+
fetch: async (vaultid) => values.get(vaultid),
|
|
14036
|
+
drop: async (vaultid) => {
|
|
14037
|
+
values.delete(vaultid);
|
|
14038
|
+
}
|
|
14039
|
+
};
|
|
14040
|
+
}
|
|
14041
|
+
async function vaultstore(input) {
|
|
14042
|
+
if (input.value === "") throw new Error("The vault stores a secret value the user supplied; an empty value stores nothing.");
|
|
14043
|
+
const entry = vaultentryof({ label: input.label, scope: input.scope, profileid: input.profileid, provenance: input.provenance, digest: await vaultdigestof(input.value), now: input.now });
|
|
14044
|
+
await input.seam.put(entry.vaultid, input.value);
|
|
14045
|
+
return entry;
|
|
14046
|
+
}
|
|
14047
|
+
async function vaultvaluefor(input) {
|
|
14048
|
+
const value = await input.seam.fetch(input.entry.vaultid);
|
|
14049
|
+
if (value === void 0) return { ok: false, reason: `The vault holds no value behind the label ${input.entry.label}; add the secret again.` };
|
|
14050
|
+
return { ok: true, value, reason: `The vault released the value behind the label ${input.entry.label} at the last possible moment; the value reaches the credential field only and no log records it.` };
|
|
14051
|
+
}
|
|
14052
|
+
async function vaultdelete(input) {
|
|
14053
|
+
await input.seam.drop(input.entry.vaultid);
|
|
14054
|
+
return { dropped: true, label: input.entry.label, reason: `The vault dropped the secret ${input.entry.label} of ${input.entry.scope}; no value and no copy remains behind the seam.` };
|
|
14055
|
+
}
|
|
14056
|
+
async function secretleakscan(input) {
|
|
14057
|
+
const leaks = [];
|
|
14058
|
+
for (const candidate of input.candidates) {
|
|
14059
|
+
if (candidate.trim() === "") continue;
|
|
14060
|
+
const digest = await vaultdigestof(candidate);
|
|
14061
|
+
if (input.entries.some((entry) => entry.digest === digest)) leaks.push(candidate);
|
|
14062
|
+
}
|
|
14063
|
+
if (leaks.length > 0) return { leaks, reason: `The plan carries ${leaks.length} plaintext value${leaks.length === 1 ? "" : "s"} that digest to vault records; secrets never ride step options, variables or plan texts, only the vault holds them.` };
|
|
14064
|
+
return { leaks: [], reason: "No candidate value digests to a vault record; the plan carries no leaked secret." };
|
|
14065
|
+
}
|
|
14066
|
+
function stepoptions5(step) {
|
|
14067
|
+
if (!step.options) return {};
|
|
14068
|
+
try {
|
|
14069
|
+
const parsed = JSON.parse(step.options);
|
|
14070
|
+
return Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
14071
|
+
} catch {
|
|
14072
|
+
return {};
|
|
14073
|
+
}
|
|
14074
|
+
}
|
|
14075
|
+
function secretshapecarrying(step) {
|
|
14076
|
+
const options = stepoptions5(step);
|
|
14077
|
+
const fields = Array.isArray(options.fields) ? options.fields.filter((item) => Boolean(item) && typeof item === "object") : [];
|
|
14078
|
+
const rawfield = fields.find((field) => typeof field.name === "string" && typeof field.value === "string" && field.value !== "" && maskingfield(field.name, []));
|
|
14079
|
+
if (rawfield !== void 0) return { carries: true, reason: `The ${step.kind} step types a raw value into the ${String(rawfield.name)} field; credential steps read their value from the vault at the last possible moment and never carry it in the options.` };
|
|
14080
|
+
if (typeof options.field === "string" && maskingfield(options.field, []) && step.value !== void 0 && step.value !== "") return { carries: true, reason: `The ${step.kind} step types a raw value into the ${options.field} field; credential steps read their value from the vault at the last possible moment and never carry it in the options.` };
|
|
14081
|
+
return { carries: false, reason: "The step carries no raw value behind a masked field shape." };
|
|
14082
|
+
}
|
|
14083
|
+
function vaultview(entries) {
|
|
14084
|
+
return entries.map((entry) => ({ vaultid: entry.vaultid, label: entry.label, scope: entry.scope, provenance: entry.provenance, createdat: entry.createdat, ...entry.lastusedat !== void 0 ? { lastusedat: entry.lastusedat } : {} }));
|
|
14085
|
+
}
|
|
14086
|
+
|
|
14087
|
+
// redactshots.ts
|
|
14088
|
+
function regionof(input) {
|
|
14089
|
+
if (input.origin.trim() === "" || input.template.trim() === "") throw new Error("The redact region needs its origin and its page template.");
|
|
14090
|
+
for (const value of [input.x, input.y, input.width, input.height]) {
|
|
14091
|
+
if (!Number.isFinite(value) || value < 0) throw new Error("The redact region needs finite, non-negative geometry in css pixels.");
|
|
14092
|
+
}
|
|
14093
|
+
if (input.width <= 0 || input.height <= 0) throw new Error("The redact region needs a positive width and height so the mask covers a real area.");
|
|
14094
|
+
if (input.reason.trim() === "") throw new Error("The redact region names its reason in plain language.");
|
|
14095
|
+
return { id: input.id ?? randomid(), origin: input.origin.trim(), template: input.template.trim(), x: input.x, y: input.y, width: input.width, height: input.height, reason: input.reason.trim(), source: input.source, createdat: input.now };
|
|
14096
|
+
}
|
|
14097
|
+
function regionsfor(regions, origin, template) {
|
|
14098
|
+
return regions.filter((region) => region.origin === origin && region.template === template);
|
|
14099
|
+
}
|
|
14100
|
+
function templateof(step) {
|
|
14101
|
+
if (step.options) {
|
|
14102
|
+
try {
|
|
14103
|
+
const parsed = JSON.parse(step.options);
|
|
14104
|
+
if (Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
14105
|
+
const template = parsed.template;
|
|
14106
|
+
if (typeof template === "string" && template.trim() !== "") return template.trim();
|
|
14107
|
+
}
|
|
14108
|
+
} catch {
|
|
14109
|
+
}
|
|
14110
|
+
}
|
|
14111
|
+
return step.kind;
|
|
14112
|
+
}
|
|
14113
|
+
function redactedshot(record2, regions) {
|
|
14114
|
+
if (regions.length === 0) return record2;
|
|
14115
|
+
return { ...record2, redacted: true, redactedregions: regions.length };
|
|
14116
|
+
}
|
|
14117
|
+
function redactionsummary(regions) {
|
|
14118
|
+
if (regions.length === 0) return "No redact region covered the capture; the stored bytes carry everything the surface saw.";
|
|
14119
|
+
const sources = { fieldshape: 0, userdrawn: 0 };
|
|
14120
|
+
for (const region of regions) sources[region.source] += 1;
|
|
14121
|
+
return `${regions.length} redact region${regions.length === 1 ? "" : "s"} covered the capture before storage: ${sources.fieldshape} derived from sensitive field shapes and ${sources.userdrawn} drawn by the user (${regions.map((region) => region.reason).join("; ")}).`;
|
|
14122
|
+
}
|
|
14123
|
+
|
|
14124
|
+
// transparency.ts
|
|
14125
|
+
function permissiondiff(input) {
|
|
14126
|
+
if (input.fromversion.trim() === "" || input.toversion.trim() === "") throw new Error("The permdiff names the two versions it compares.");
|
|
14127
|
+
const added = [...new Set(input.to.filter((permission) => !input.from.includes(permission)))];
|
|
14128
|
+
const removed = [...new Set(input.from.filter((permission) => !input.to.includes(permission)))];
|
|
14129
|
+
return { fromversion: input.fromversion, toversion: input.toversion, added, removed, computedat: input.now };
|
|
14130
|
+
}
|
|
14131
|
+
function permdiffchanged(diff) {
|
|
14132
|
+
return diff.added.length > 0 || diff.removed.length > 0;
|
|
14133
|
+
}
|
|
14134
|
+
function permdiffsummary(diff) {
|
|
14135
|
+
if (!permdiffchanged(diff)) return `The update from ${diff.fromversion} to ${diff.toversion} changed no permission.`;
|
|
14136
|
+
const parts = [];
|
|
14137
|
+
if (diff.added.length > 0) parts.push(`added ${diff.added.join(", ")}`);
|
|
14138
|
+
if (diff.removed.length > 0) parts.push(`removed ${diff.removed.join(", ")}`);
|
|
14139
|
+
return `The update from ${diff.fromversion} to ${diff.toversion} ${parts.join(" and ")}.`;
|
|
14140
|
+
}
|
|
14141
|
+
function transparencygrants(input) {
|
|
14142
|
+
const grants = input.allowlist.map((entry) => ({ origin: entry.origin, scope: `automation allowlist of the profile workspace ${entry.profileid}`, boundary: "the user revokes the entry or the profile workspace", grantedat: entry.grantedat }));
|
|
14143
|
+
for (const profile of input.profiles) {
|
|
14144
|
+
grants.push({ origin: profile.origin, scope: `origin profile with ${profile.grants.length} granted and ${profile.denials.length} denied kinds`, boundary: "the user edits or revokes the profile", grantedat: profile.createdat });
|
|
14145
|
+
}
|
|
14146
|
+
return grants;
|
|
14147
|
+
}
|
|
14148
|
+
function windowhistory(windows) {
|
|
14149
|
+
return windows.map((window2) => ({ id: window2.id, origin: window2.origin, state: window2.state, boundary: window2.boundary, startedat: window2.startedat, expiresat: window2.expiresat }));
|
|
14150
|
+
}
|
|
14151
|
+
function connectallowlist(entries) {
|
|
14152
|
+
return entries.map((entry) => ({ senderid: entry.senderid, displayname: entry.displayname, ...entry.origin !== void 0 ? { origin: entry.origin } : {}, addedat: entry.addedat }));
|
|
14153
|
+
}
|
|
14154
|
+
|
|
13122
14155
|
// modelroute.ts
|
|
13123
14156
|
function routevalid(route) {
|
|
13124
14157
|
if (route.kind.trim() === "") return { allowed: false, reason: "The model route needs its task kind." };
|
|
@@ -14325,13 +15358,28 @@ var chromestorage = {
|
|
|
14325
15358
|
}
|
|
14326
15359
|
};
|
|
14327
15360
|
var memory = new sessionmemory(chromestorage);
|
|
15361
|
+
var vaultseamstore = (() => {
|
|
15362
|
+
const session = chrome.storage?.session;
|
|
15363
|
+
if (session) {
|
|
15364
|
+
return {
|
|
15365
|
+
put: async (vaultid, value) => {
|
|
15366
|
+
await session.set({ [`vault:${vaultid}`]: value });
|
|
15367
|
+
},
|
|
15368
|
+
fetch: async (vaultid) => (await session.get(`vault:${vaultid}`))[`vault:${vaultid}`],
|
|
15369
|
+
drop: async (vaultid) => {
|
|
15370
|
+
await session.remove(`vault:${vaultid}`);
|
|
15371
|
+
}
|
|
15372
|
+
};
|
|
15373
|
+
}
|
|
15374
|
+
return inmemoryvault();
|
|
15375
|
+
})();
|
|
14328
15376
|
function extensionpage(sender) {
|
|
14329
15377
|
return sender.id === chrome.runtime.id && Boolean(sender.url?.startsWith(chrome.runtime.getURL("")));
|
|
14330
15378
|
}
|
|
14331
15379
|
async function audit(kind, summary, extra = {}) {
|
|
14332
15380
|
await memory.addaudi({ id: randomid(), kind, at: Date.now(), summary, ...extra });
|
|
14333
15381
|
}
|
|
14334
|
-
function
|
|
15382
|
+
function stepoptions6(step) {
|
|
14335
15383
|
try {
|
|
14336
15384
|
return parseoptions(step);
|
|
14337
15385
|
} catch {
|
|
@@ -14556,6 +15604,12 @@ async function securitystepgate(step, session, origin, settings) {
|
|
|
14556
15604
|
const allowverdict = automationallowlistgate({ origin, allowlist: await memory.getautomationallowlist(), session });
|
|
14557
15605
|
if (!allowverdict.allowed) return { allowed: false, suspended: false, reason: allowverdict.reason ?? "", classification };
|
|
14558
15606
|
const profile = (await memory.getoriginprofiles()).find((candidate) => candidate.origin === origin);
|
|
15607
|
+
if (profile === void 0) {
|
|
15608
|
+
await memory.addsafedefaultapplication({ origin, firstseenat: now }).catch(() => {
|
|
15609
|
+
});
|
|
15610
|
+
const safedefaultverdict = safedefaultsgate({ profile, classes: classification.classes, sensitive: classification.sensitive });
|
|
15611
|
+
if (!safedefaultverdict.allowed) return { allowed: false, suspended: false, reason: safedefaultverdict.reason ?? "", classification };
|
|
15612
|
+
}
|
|
14559
15613
|
const profileverdict = originprofilegate({ profile, kind: step.kind, sensitive: classification.sensitive });
|
|
14560
15614
|
if (!profileverdict.allowed) return { allowed: false, suspended: false, reason: profileverdict.reason ?? "", classification };
|
|
14561
15615
|
const windows = await memory.expireconsentwindows(now);
|
|
@@ -14568,8 +15622,115 @@ async function securitystepgate(step, session, origin, settings) {
|
|
|
14568
15622
|
const revocation = plan === void 0 ? void 0 : (await memory.getrevocations()).find((candidate) => candidate.sessionid === session.id && candidate.runid === plan.id);
|
|
14569
15623
|
const revokeverdict = revokerungate({ revocation, sessionid: session.id, runid: plan?.id ?? "" });
|
|
14570
15624
|
if (!revokeverdict.allowed) return { allowed: false, suspended: false, reason: revokeverdict.reason ?? "", classification };
|
|
15625
|
+
const confirmverdict = await confirmgatechain(step, session, plan, origin, classification, now);
|
|
15626
|
+
if (confirmverdict !== void 0) return { allowed: confirmverdict.allowed, suspended: false, reason: confirmverdict.reason, classification };
|
|
14571
15627
|
return { allowed: true, suspended: false, reason: `${classification.reason} ${allowverdict.reason ?? ""} ${windowverdict.reason ?? ""} ${consentverdict.reason ?? ""}`, classification };
|
|
14572
15628
|
}
|
|
15629
|
+
async function confirmgatechain(step, session, plan, origin, classification, now) {
|
|
15630
|
+
if (!session || !plan) return void 0;
|
|
15631
|
+
const kind = gatekindfor(classification.classes);
|
|
15632
|
+
if (kind !== void 0) {
|
|
15633
|
+
const gates = await memory.getgates();
|
|
15634
|
+
const state = gatestateof(gates, step.id);
|
|
15635
|
+
if (state.state === "none") {
|
|
15636
|
+
const vaultentries2 = await memory.getsecretvault();
|
|
15637
|
+
const vaultlabel = vaultentries2.find((entry) => entry.scope === origin)?.label;
|
|
15638
|
+
const gate = gateforstep({ step, classes: classification.classes, runid: plan.id, origin, credentiallabel: vaultlabel ?? `the credential the ${step.kind} step reviews`, now });
|
|
15639
|
+
if (gate) {
|
|
15640
|
+
await memory.savegate(gate);
|
|
15641
|
+
await appendrunevent("gate", `The ${gate.kind} gate opened for the ${step.kind} step ${step.id} on ${origin}: ${gateprompttext(gate)}`, session, origin, step.id).catch(() => {
|
|
15642
|
+
});
|
|
15643
|
+
await audit("gate", `The ${gate.kind} gate opened for the ${step.kind} step ${step.id} on ${origin}; the executor pauses until one distinct human action resolves it and no timeout ever resolves a gate.`, { sessionid: session.id, planid: plan.id, stepid: step.id });
|
|
15644
|
+
return { allowed: false, reason: `The ${gate.kind} gate opened for the ${step.kind} step ${step.id} on ${origin}: ${gateprompttext(gate)} The executor pauses until the human resolves it.` };
|
|
15645
|
+
}
|
|
15646
|
+
}
|
|
15647
|
+
const gateverdict = kind === "confirmpay" ? confirmpaygate({ classes: classification.classes, state: state.state }) : kind === "confirmdelete" ? confirmdeletegate({ classes: classification.classes, state: state.state }) : confirmcredsgate({ classes: classification.classes, state: state.state });
|
|
15648
|
+
if (!gateverdict.allowed) return { allowed: false, reason: gateverdict.reason ?? "" };
|
|
15649
|
+
if (state.state === "resolved" && state.gate !== void 0 && state.gate.resolvedat !== void 0) {
|
|
15650
|
+
await memory.setprogress(recordgatewait(await memory.getprogress(), plan.id, step.id, { gateid: state.gate.gateid, kind: state.gate.kind, openedat: state.gate.openedat, resolvedat: state.gate.resolvedat, waitedms: Math.max(0, state.gate.resolvedat - state.gate.openedat) }, now)).catch(() => {
|
|
15651
|
+
});
|
|
15652
|
+
}
|
|
15653
|
+
}
|
|
15654
|
+
if (credentialstep(step)) {
|
|
15655
|
+
const settings = await memory.getsettings();
|
|
15656
|
+
const threshold = settings?.phishdistance;
|
|
15657
|
+
if (threshold !== void 0) {
|
|
15658
|
+
const thresholdgate = phishthresholdgate(threshold);
|
|
15659
|
+
if (!thresholdgate.allowed) return { allowed: false, reason: thresholdgate.reason ?? "" };
|
|
15660
|
+
const live = await memory.expirephishverdicts(settings?.phishfreshness, now);
|
|
15661
|
+
const stored = live.find((verdict2) => verdict2.origin === origin);
|
|
15662
|
+
const verdict = stored ?? phishverdictof({ origin, granted: [.../* @__PURE__ */ new Set([...(await memory.getautomationallowlist()).map((entry) => entry.origin), session.origin])], threshold, now });
|
|
15663
|
+
if (stored === void 0) await memory.addphishverdict(verdict);
|
|
15664
|
+
const phishgate = phishguardgate({ verdict });
|
|
15665
|
+
if (!phishgate.allowed) {
|
|
15666
|
+
await appendrunevent("phish", `The phishguard blocked the credential step ${step.id} on ${origin}: ${verdict.reason}`, session, origin, step.id).catch(() => {
|
|
15667
|
+
});
|
|
15668
|
+
await audit("phish", `The phishguard blocked the ${step.kind} step ${step.id} on ${origin}: ${verdict.reason}`, { sessionid: session.id, planid: plan.id, stepid: step.id });
|
|
15669
|
+
return { allowed: false, reason: phishgate.reason ?? "" };
|
|
15670
|
+
}
|
|
15671
|
+
}
|
|
15672
|
+
}
|
|
15673
|
+
const buckets = await memory.getratelimitbuckets();
|
|
15674
|
+
const bucket = buckets.find((candidate) => candidate.origin === origin && candidate.sessionid === session.id);
|
|
15675
|
+
if (bucket !== void 0) {
|
|
15676
|
+
const consumed = bucketconsume({ bucket, now });
|
|
15677
|
+
if (!consumed.allowed) {
|
|
15678
|
+
const deferred = deferredeventof({ stepid: step.id, kind: step.kind, origin, reason: consumed.reason, resetsat: consumed.resetsat, now });
|
|
15679
|
+
await memory.adddeferredevent(deferred);
|
|
15680
|
+
await appendrunevent("suspend", `The ratelimit bucket of ${origin} deferred the ${step.kind} step ${step.id} until the window resets at ${deferred.resetsat}: ${consumed.reason}`, session, origin, step.id).catch(() => {
|
|
15681
|
+
});
|
|
15682
|
+
await audit("defer", `The ratelimit bucket of ${origin} deferred the ${step.kind} step ${step.id} until the window resets at ${deferred.resetsat}; the bounds stay user configured choices with no hidden ceiling.`, { sessionid: session.id, planid: plan.id, stepid: step.id });
|
|
15683
|
+
return { allowed: false, reason: consumed.reason };
|
|
15684
|
+
}
|
|
15685
|
+
await memory.saveratelimitbucket(consumed.bucket);
|
|
15686
|
+
}
|
|
15687
|
+
const vaultentries = await memory.getsecretvault();
|
|
15688
|
+
const options = stepoptions6(step);
|
|
15689
|
+
const candidates = [step.value ?? "", ...Object.values(options).filter((value) => typeof value === "string")];
|
|
15690
|
+
const leakscan = await secretleakscan({ candidates, entries: vaultentries });
|
|
15691
|
+
const secretverdict = vaultsecretgate({ leaks: leakscan.leaks, carries: secretshapecarrying(step).carries });
|
|
15692
|
+
if (!secretverdict.allowed) {
|
|
15693
|
+
await audit("vault", `The vault secret scan refused the ${step.kind} step ${step.id} on ${origin}: ${secretverdict.reason}`, { sessionid: session.id, planid: plan.id, stepid: step.id });
|
|
15694
|
+
return { allowed: false, reason: secretverdict.reason ?? "" };
|
|
15695
|
+
}
|
|
15696
|
+
return void 0;
|
|
15697
|
+
}
|
|
15698
|
+
async function resolvevaultvalues(step, session) {
|
|
15699
|
+
void session;
|
|
15700
|
+
const marker = /^vault:[A-Za-z0-9-]+$/;
|
|
15701
|
+
if (step.options === void 0 || !step.options.includes("vault:")) return step;
|
|
15702
|
+
const entries = await memory.getsecretvault();
|
|
15703
|
+
let options = step.options;
|
|
15704
|
+
try {
|
|
15705
|
+
const parsed = JSON.parse(step.options);
|
|
15706
|
+
if (Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
15707
|
+
const record2 = parsed;
|
|
15708
|
+
const resolvevalue = async (value) => {
|
|
15709
|
+
if (!marker.test(value)) return value;
|
|
15710
|
+
const entry = entries.find((candidate) => candidate.vaultid === value.slice("vault:".length));
|
|
15711
|
+
if (!entry) return value;
|
|
15712
|
+
const fetched = await vaultvaluefor({ seam: vaultseamstore, entry });
|
|
15713
|
+
if (fetched.ok && fetched.value !== void 0) {
|
|
15714
|
+
await memory.stampsecretuse(entry.vaultid, Date.now());
|
|
15715
|
+
return fetched.value;
|
|
15716
|
+
}
|
|
15717
|
+
return value;
|
|
15718
|
+
};
|
|
15719
|
+
for (const [key, value] of Object.entries(record2)) if (typeof value === "string") record2[key] = await resolvevalue(value);
|
|
15720
|
+
if (Array.isArray(record2.fields)) {
|
|
15721
|
+
for (const field of record2.fields) {
|
|
15722
|
+
if (!Boolean(field) || typeof field !== "object" || Array.isArray(field)) continue;
|
|
15723
|
+
const fieldrecord = field;
|
|
15724
|
+
if (typeof fieldrecord.value === "string") fieldrecord.value = await resolvevalue(fieldrecord.value);
|
|
15725
|
+
}
|
|
15726
|
+
}
|
|
15727
|
+
options = JSON.stringify(record2);
|
|
15728
|
+
}
|
|
15729
|
+
} catch {
|
|
15730
|
+
}
|
|
15731
|
+
if (options === step.options) return step;
|
|
15732
|
+
return { ...step, options };
|
|
15733
|
+
}
|
|
14573
15734
|
async function sealsessionrunlog(sessionid) {
|
|
14574
15735
|
const log = await memory.getimmutablelog(sessionid);
|
|
14575
15736
|
if (!log || log.seal !== void 0 || log.entries.length === 0) return;
|
|
@@ -14593,10 +15754,19 @@ async function securityviewof() {
|
|
|
14593
15754
|
maskrules: await memory.getmaskrules(),
|
|
14594
15755
|
chain,
|
|
14595
15756
|
posture: "denydefault",
|
|
15757
|
+
gates: await memory.getgates(),
|
|
15758
|
+
resolutions: await memory.getgateresolutions(),
|
|
15759
|
+
deferred: await memory.getdeferredevents(),
|
|
15760
|
+
phishverdicts: await memory.getphishverdicts(),
|
|
15761
|
+
vault: await memory.getsecretvault(),
|
|
15762
|
+
connectallow: await memory.getconnectallow(),
|
|
15763
|
+
safedefaults: await memory.getsafedefaultapplications(),
|
|
15764
|
+
redactregions: await memory.getredactregions(),
|
|
14596
15765
|
...session ? { sessionorigin: session.origin } : {},
|
|
14597
15766
|
...settings?.consentduration !== void 0 ? { promptduration: settings.consentduration } : {},
|
|
14598
15767
|
...settings?.logretention !== void 0 ? { logretention: settings.logretention } : {},
|
|
14599
|
-
...settings?.maskshapes !== void 0 ? { maskshapes: settings.maskshapes } : {}
|
|
15768
|
+
...settings?.maskshapes !== void 0 ? { maskshapes: settings.maskshapes } : {},
|
|
15769
|
+
...settings?.phishdistance !== void 0 ? { phishdistance: settings.phishdistance } : {}
|
|
14600
15770
|
};
|
|
14601
15771
|
}
|
|
14602
15772
|
async function executeisolatedevaluate(step, tabid2, origin) {
|
|
@@ -14618,9 +15788,11 @@ async function executeisolatedevaluate(step, tabid2, origin) {
|
|
|
14618
15788
|
return result[0]?.result ?? { ok: false, summary: "The isolated world returned no result." };
|
|
14619
15789
|
}
|
|
14620
15790
|
async function executesandboxrender(step, session, plan, origin) {
|
|
14621
|
-
const options =
|
|
15791
|
+
const options = stepoptions6(step);
|
|
14622
15792
|
const markup = typeof options.markup === "string" ? options.markup : "";
|
|
14623
15793
|
const sourceorigin = typeof options.sourceorigin === "string" ? options.sourceorigin : origin;
|
|
15794
|
+
const rendergate = untrustedrendergate({ environment: "sandboxframe" });
|
|
15795
|
+
if (!rendergate.allowed) throw new Error(rendergate.reason);
|
|
14624
15796
|
const settings = await memory.getsettings();
|
|
14625
15797
|
const origingate = sandboxorigingate({ origin: sourceorigin, allowed: settings?.sandboxorigins ?? [] });
|
|
14626
15798
|
if (!origingate.allowed) throw new Error(origingate.reason);
|
|
@@ -14652,7 +15824,7 @@ async function offloadparsetoworker(step, output, session, plan, origin) {
|
|
|
14652
15824
|
const ready = await ensureoffscreendocument(runid);
|
|
14653
15825
|
if (!ready) return { output, turnaround: void 0 };
|
|
14654
15826
|
const payload = JSON.stringify({ summary: output?.summary ?? "", details: output?.details ?? {} });
|
|
14655
|
-
const request = workerrequestof({ id: randomid(), runid, stepid: step.id, kind: step.kind, payload, options:
|
|
15827
|
+
const request = workerrequestof({ id: randomid(), runid, stepid: step.id, kind: step.kind, payload, options: stepoptions6(step), sentat: Date.now() });
|
|
14656
15828
|
const started = Date.now();
|
|
14657
15829
|
let answer;
|
|
14658
15830
|
try {
|
|
@@ -14743,6 +15915,10 @@ async function startsession() {
|
|
|
14743
15915
|
const { tab, origin } = await activecontext();
|
|
14744
15916
|
const session = { id: randomid(), tabid: tab.id, origin, startedat: Date.now(), expiresat: Date.now() + sessionduration, grants: [origin] };
|
|
14745
15917
|
await memory.setsession(session);
|
|
15918
|
+
await memory.settabsession(tabsessionrefof({ tabid: session.tabid, sessionid: session.id, origin, now: session.startedat }));
|
|
15919
|
+
await memory.tracktabsession(session.tabid);
|
|
15920
|
+
await memory.addconsentmemoryentry(consentmemoryof({ origin, decision: "grant", boundary: `the session expiry at ${new Date(session.expiresat).toISOString()}`, kinds: ["observe"], now: session.startedat }));
|
|
15921
|
+
if ((await memory.getsettings())?.historyindex !== false) await memory.addhistoryentry({ source: "session", id: session.id, origin, title: `Session of ${origin}`, text: `session ${origin} started ${new Date(session.startedat).toISOString()}`, at: session.startedat });
|
|
14746
15922
|
await memory.addallowlistorigin({ origin, profileid: runstateprofile, grantedat: session.startedat });
|
|
14747
15923
|
const scope = scopegrantof({ origin, kinds: ["observe"], boundary: `the session expiry at ${new Date(session.expiresat).toISOString()}`, now: session.startedat });
|
|
14748
15924
|
let runlog = openrunlog({ runid: session.id, sessionid: session.id, now: session.startedat });
|
|
@@ -14855,7 +16031,7 @@ function stepauditkind(step, ok) {
|
|
|
14855
16031
|
return ok ? "action" : "error";
|
|
14856
16032
|
}
|
|
14857
16033
|
function resolvedinnerstep(step, plan) {
|
|
14858
|
-
const options =
|
|
16034
|
+
const options = stepoptions6(step);
|
|
14859
16035
|
if (typeof options.stepid === "string" && options.stepid.trim()) {
|
|
14860
16036
|
return plan.steps.find((candidate) => candidate.id === options.stepid) ?? null;
|
|
14861
16037
|
}
|
|
@@ -14864,7 +16040,7 @@ function resolvedinnerstep(step, plan) {
|
|
|
14864
16040
|
async function executekeyhold(step, session, plan, tabid2, origin) {
|
|
14865
16041
|
const output = await dispatchpagestep(step, tabid2, origin, plan);
|
|
14866
16042
|
if (!output?.ok) return output ?? { ok: false, summary: "The key hold was not delivered." };
|
|
14867
|
-
const options =
|
|
16043
|
+
const options = stepoptions6(step);
|
|
14868
16044
|
const holdid = typeof options.holdid === "string" && options.holdid.trim() ? options.holdid : randomid();
|
|
14869
16045
|
const modifiers = Array.isArray(options.modifiers) ? options.modifiers.filter((item) => typeof item === "string") : [];
|
|
14870
16046
|
const hold = { holdid, key: step.value ?? "", ...modifiers.length > 0 ? { modifiers } : {}, tabid: tabid2, stepid: step.id, pressedat: Date.now() };
|
|
@@ -14897,7 +16073,7 @@ async function executedismissdialog(step, session, plan, tabid2, origin) {
|
|
|
14897
16073
|
return { ok: true, summary: `Dialog handler armed${answer} for the next confirm, alert or prompt.` };
|
|
14898
16074
|
}
|
|
14899
16075
|
async function executeretryaction(step, session, plan, tabid2, origin) {
|
|
14900
|
-
const rule =
|
|
16076
|
+
const rule = stepoptions6(step).retryrule;
|
|
14901
16077
|
const inner = resolvedinnerstep(step, plan);
|
|
14902
16078
|
if (!inner) throw new Error("The reviewed wrapper step could not be resolved.");
|
|
14903
16079
|
const innergate = validatestep(inner, origin);
|
|
@@ -14933,8 +16109,8 @@ async function executeenterframe(step, plan, tabid2, origin) {
|
|
|
14933
16109
|
if (!inner) throw new Error("The reviewed frame wrapper step could not be resolved.");
|
|
14934
16110
|
const innergate = validatestep(inner, origin);
|
|
14935
16111
|
if (!innergate.allowed) throw new Error(`The wrapped step is not allowed: ${innergate.reason}`);
|
|
14936
|
-
const options =
|
|
14937
|
-
const inneroptions = inner.options ?
|
|
16112
|
+
const options = stepoptions6(step);
|
|
16113
|
+
const inneroptions = inner.options ? stepoptions6(inner) : void 0;
|
|
14938
16114
|
const derived = { ...step, options: JSON.stringify({ ...options, kind: inner.kind, ...inner.target ? { target: inner.target } : {}, ...inner.value ? { value: inner.value } : {}, ...inneroptions ? { options: inneroptions } : {} }) };
|
|
14939
16115
|
return dispatchpagestep(derived, tabid2, origin, plan);
|
|
14940
16116
|
}
|
|
@@ -14946,7 +16122,7 @@ function detailarray(details, key) {
|
|
|
14946
16122
|
return Array.isArray(value) ? value : [];
|
|
14947
16123
|
}
|
|
14948
16124
|
async function executediffsnapshots(step, session, plan, tabid2, origin) {
|
|
14949
|
-
const options =
|
|
16125
|
+
const options = stepoptions6(step);
|
|
14950
16126
|
const versions = Array.isArray(options.versions) ? options.versions.filter((item) => typeof item === "number") : [];
|
|
14951
16127
|
const baseversion = versions[0];
|
|
14952
16128
|
const targetversion = versions[1];
|
|
@@ -14969,7 +16145,7 @@ async function executediffsnapshots(step, session, plan, tabid2, origin) {
|
|
|
14969
16145
|
return { ok: Boolean(output.ok), summary: output.summary, details: { ...output.details ?? {}, versions: [baseversion, targetversion] } };
|
|
14970
16146
|
}
|
|
14971
16147
|
async function executewatchstep(step, session, plan, tabid2, origin) {
|
|
14972
|
-
const options =
|
|
16148
|
+
const options = stepoptions6(step);
|
|
14973
16149
|
const watchid = typeof options.watchid === "string" && options.watchid.trim() ? options.watchid : randomid();
|
|
14974
16150
|
const scopes = Array.isArray(options.scopes) ? options.scopes.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
|
|
14975
16151
|
const events = Array.isArray(options.events) ? options.events.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
|
|
@@ -15651,7 +16827,7 @@ function commandtabids(step, options) {
|
|
|
15651
16827
|
return listed.length > 0 ? listed : single;
|
|
15652
16828
|
}
|
|
15653
16829
|
async function executetabscommand(step, session, plan, sessiontabid) {
|
|
15654
|
-
const options =
|
|
16830
|
+
const options = stepoptions6(step);
|
|
15655
16831
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
15656
16832
|
const windowid = step.value && /^\d+$/.test(step.value) ? Number.parseInt(step.value, 10) : 0;
|
|
15657
16833
|
const layoutgate = layoutmutationgranted(session, Date.now());
|
|
@@ -15927,7 +17103,7 @@ async function executetabscommand(step, session, plan, sessiontabid) {
|
|
|
15927
17103
|
}
|
|
15928
17104
|
}
|
|
15929
17105
|
async function executesaveprofiles(step, session, origin) {
|
|
15930
|
-
const options =
|
|
17106
|
+
const options = stepoptions6(step);
|
|
15931
17107
|
const record2 = parseformrecord(options.formrecord);
|
|
15932
17108
|
const name = typeof options.name === "string" ? options.name : "";
|
|
15933
17109
|
if (!name || !record2) throw new Error("A reviewed profile name and form record are required.");
|
|
@@ -15947,7 +17123,7 @@ async function executeasksubmit(step, session, plan, tabid2, origin) {
|
|
|
15947
17123
|
return { ok: true, summary: `Asksubmit prompt opened for form ${ticket.form || "the reviewed form"}; the submission waits for your approval.`, details: { ticket, values } };
|
|
15948
17124
|
}
|
|
15949
17125
|
async function executesubmitform(step, session, plan, tabid2, origin) {
|
|
15950
|
-
const consentref = typeof
|
|
17126
|
+
const consentref = typeof stepoptions6(step).consentref === "string" ? stepoptions6(step).consentref : "";
|
|
15951
17127
|
const ticket = (await memory.gettickets()).find((item) => item.approved === true && (item.consentref === consentref || item.id === consentref));
|
|
15952
17128
|
if (!ticket) throw new Error("No approved asksubmit ticket matches the reviewed consent ref; approve the submission in the review panel first.");
|
|
15953
17129
|
const output = await dispatchpagestep(step, tabid2, origin, plan) ?? { ok: false, summary: "The form submission returned no result." };
|
|
@@ -15971,7 +17147,7 @@ async function executeretryform(step, session, plan, tabid2, origin) {
|
|
|
15971
17147
|
return { ok: Boolean(output?.ok), summary: output?.summary ?? "The retried submission returned no result.", details: { attempts, windows, ok: Boolean(output?.ok) } };
|
|
15972
17148
|
}
|
|
15973
17149
|
async function executeconsentpassword(step, session, plan, tabid2, origin) {
|
|
15974
|
-
const consentref = typeof
|
|
17150
|
+
const consentref = typeof stepoptions6(step).consentref === "string" ? stepoptions6(step).consentref : "";
|
|
15975
17151
|
const gate = passwordconsentgranted(step);
|
|
15976
17152
|
if (!gate.allowed) throw new Error(gate.reason ?? "A password fill requires a reviewed consent ref.");
|
|
15977
17153
|
const output = await dispatchpagestep(step, tabid2, origin, plan);
|
|
@@ -15983,7 +17159,7 @@ async function executeattachfile(step, session, plan, tabid2, origin) {
|
|
|
15983
17159
|
const artifacts = await memory.getartifacts();
|
|
15984
17160
|
const artifact = artifacts.find((item) => item.name === name || item.id === name);
|
|
15985
17161
|
if (!artifact) throw new Error(`No generated artifact named ${name} exists in the run store yet.`);
|
|
15986
|
-
const derived = { ...step, options: JSON.stringify({ ...
|
|
17162
|
+
const derived = { ...step, options: JSON.stringify({ ...stepoptions6(step), artifact: artifact.id, artifactname: artifact.name }) };
|
|
15987
17163
|
const output = await dispatchpagestep(derived, tabid2, origin, plan);
|
|
15988
17164
|
await audit("fill", `Artifact ${artifact.name} of kind ${artifact.kind} attached to the reviewed file input inside the form submission.`, { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id });
|
|
15989
17165
|
return { ...output ?? { ok: false, summary: "The artifact attachment returned no result." }, details: { ...output?.details ?? {}, artifact } };
|
|
@@ -16016,7 +17192,7 @@ async function executeformstep(step, session, plan, tabid2, origin) {
|
|
|
16016
17192
|
return executecaptchahandoff(step, session, plan, tabid2, origin);
|
|
16017
17193
|
case "fillcode": {
|
|
16018
17194
|
const stored = await memory.getcodevalue();
|
|
16019
|
-
const source = typeof
|
|
17195
|
+
const source = typeof stepoptions6(step).source === "string" ? stepoptions6(step).source : "";
|
|
16020
17196
|
const derived = stored !== void 0 && source === "reviewed" ? { ...step, value: stored } : step;
|
|
16021
17197
|
const output = await dispatchpagestep(derived, tabid2, origin, plan);
|
|
16022
17198
|
await audit("fill", `One time code typed from the reviewed source ${source}${stored !== void 0 ? " through the consent gated code entry" : ""}.`, { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id });
|
|
@@ -16087,7 +17263,7 @@ async function storeexport(stepid, datasetvalue, format, delimiter, session, pla
|
|
|
16087
17263
|
return artifact;
|
|
16088
17264
|
}
|
|
16089
17265
|
async function executedatastep(step, session, plan, tabid2, origin) {
|
|
16090
|
-
const options =
|
|
17266
|
+
const options = stepoptions6(step);
|
|
16091
17267
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
16092
17268
|
switch (step.kind) {
|
|
16093
17269
|
case "scrapetable": {
|
|
@@ -16317,7 +17493,7 @@ async function verifyonerecord(record2, expected, extra) {
|
|
|
16317
17493
|
return { ok: verification.ok, summary: verification.summary, details: { verification: { ...verification.matches, state: record2.state, path: record2.path, checksum: record2.checksum, bytes: record2.bytes } } };
|
|
16318
17494
|
}
|
|
16319
17495
|
async function executefilesstep(step, session, plan, tabid2, origin) {
|
|
16320
|
-
const options =
|
|
17496
|
+
const options = stepoptions6(step);
|
|
16321
17497
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
16322
17498
|
switch (step.kind) {
|
|
16323
17499
|
case "batchdownload": {
|
|
@@ -16546,7 +17722,7 @@ reconcilmimefilter().catch(() => {
|
|
|
16546
17722
|
});
|
|
16547
17723
|
var stitchprogress = /* @__PURE__ */ new Map();
|
|
16548
17724
|
function stepcaptureoptions(step) {
|
|
16549
|
-
return captureoptionsof(
|
|
17725
|
+
return captureoptionsof(stepoptions6(step).capture);
|
|
16550
17726
|
}
|
|
16551
17727
|
async function blobtodataurl(blob) {
|
|
16552
17728
|
const buffer = new Uint8Array(await blob.arrayBuffer());
|
|
@@ -16670,7 +17846,7 @@ async function encodecanvas(width, height, draw, options) {
|
|
|
16670
17846
|
return canvasdataurl(canvas, options.format, options.quality);
|
|
16671
17847
|
}
|
|
16672
17848
|
async function capturenamefor(step, plan, kind, format) {
|
|
16673
|
-
const naming =
|
|
17849
|
+
const naming = stepoptions6(step).naming;
|
|
16674
17850
|
const rule = naming && typeof naming === "object" && !Array.isArray(naming) ? naming : { run: true, step: true, sequence: true, kind: true };
|
|
16675
17851
|
const counters = (await memory.getcapturecounters()).find((item) => item.taskid === plan.id);
|
|
16676
17852
|
const advanced = advancecounter(counters?.counters ?? {}, step.id);
|
|
@@ -16710,13 +17886,62 @@ async function grabstateshot(step, session, plan, tabid2, phase) {
|
|
|
16710
17886
|
return record2;
|
|
16711
17887
|
}
|
|
16712
17888
|
async function storecapture(record2, session, plan, step, origin) {
|
|
17889
|
+
const template = templateof(step);
|
|
17890
|
+
const regions = regionsfor(await memory.getredactregions(), origin, template);
|
|
17891
|
+
record2 = redactedshot(record2, regions);
|
|
16713
17892
|
await memory.addcapture(record2);
|
|
17893
|
+
if (regions.length > 0) await audit("capture", `The capture of ${origin} on the template ${template} stored with its sensitive regions masked: ${redactionsummary(regions)}`, { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id });
|
|
16714
17894
|
const routed = await routecapture(record2, session, plan, step, origin);
|
|
16715
17895
|
await memory.setprogress(recordcapture(await memory.getprogress(), plan.id, step.id, record2, Date.now()));
|
|
16716
17896
|
await refreshbadge();
|
|
16717
17897
|
return { record: record2, routed };
|
|
16718
17898
|
}
|
|
17899
|
+
var activeredactregions = [];
|
|
17900
|
+
async function drawredactoverlays(tabid2) {
|
|
17901
|
+
if (activeredactregions.length === 0) return;
|
|
17902
|
+
const rects = activeredactregions.map((region) => ({ x: region.x, y: region.y, width: region.width, height: region.height }));
|
|
17903
|
+
await chrome.scripting.executeScript({ target: { tabId: tabid2 }, func: (overlays) => {
|
|
17904
|
+
let host = document.getElementById("devthinkredacthost");
|
|
17905
|
+
if (!host) {
|
|
17906
|
+
host = document.createElement("div");
|
|
17907
|
+
host.id = "devthinkredacthost";
|
|
17908
|
+
host.style.position = "fixed";
|
|
17909
|
+
host.style.inset = "0";
|
|
17910
|
+
host.style.zIndex = "2147483647";
|
|
17911
|
+
host.style.pointerEvents = "none";
|
|
17912
|
+
document.documentElement.appendChild(host);
|
|
17913
|
+
}
|
|
17914
|
+
for (const overlay of overlays) {
|
|
17915
|
+
const rect = document.createElement("div");
|
|
17916
|
+
rect.style.position = "fixed";
|
|
17917
|
+
rect.style.left = `${overlay.x}px`;
|
|
17918
|
+
rect.style.top = `${overlay.y}px`;
|
|
17919
|
+
rect.style.width = `${overlay.width}px`;
|
|
17920
|
+
rect.style.height = `${overlay.height}px`;
|
|
17921
|
+
rect.style.background = "#000";
|
|
17922
|
+
host.appendChild(rect);
|
|
17923
|
+
}
|
|
17924
|
+
}, args: [rects] }).catch(() => {
|
|
17925
|
+
});
|
|
17926
|
+
}
|
|
17927
|
+
async function clearredactoverlays(tabid2) {
|
|
17928
|
+
if (activeredactregions.length === 0) return;
|
|
17929
|
+
await chrome.scripting.executeScript({ target: { tabId: tabid2 }, func: () => {
|
|
17930
|
+
document.getElementById("devthinkredacthost")?.remove();
|
|
17931
|
+
} }).catch(() => {
|
|
17932
|
+
});
|
|
17933
|
+
}
|
|
16719
17934
|
async function executecapturestep(step, session, plan, tabid2, origin) {
|
|
17935
|
+
activeredactregions = regionsfor(await memory.getredactregions(), origin, templateof(step));
|
|
17936
|
+
await drawredactoverlays(tabid2);
|
|
17937
|
+
try {
|
|
17938
|
+
return await executecapturestepinner(step, session, plan, tabid2, origin);
|
|
17939
|
+
} finally {
|
|
17940
|
+
await clearredactoverlays(tabid2);
|
|
17941
|
+
activeredactregions = [];
|
|
17942
|
+
}
|
|
17943
|
+
}
|
|
17944
|
+
async function executecapturestepinner(step, session, plan, tabid2, origin) {
|
|
16720
17945
|
const options = stepcaptureoptions(step);
|
|
16721
17946
|
const format = options.format ?? "png";
|
|
16722
17947
|
const ratio = options.pixelratio ?? 1;
|
|
@@ -16739,7 +17964,7 @@ async function executecapturestep(step, session, plan, tabid2, origin) {
|
|
|
16739
17964
|
return { ok: true, summary: `Captured the visible viewport at ${record2.width} by ${record2.height} pixels.`, details: { capture: { id: record2.id, kind: record2.kind, format: record2.format, width: record2.width, height: record2.height, bytes: (record2.bytes ?? "").length, exporttarget: stored.routed.target } } };
|
|
16740
17965
|
}
|
|
16741
17966
|
if (step.kind === "shotfullpage") {
|
|
16742
|
-
const rawoptions =
|
|
17967
|
+
const rawoptions = stepoptions6(step);
|
|
16743
17968
|
const settle2 = typeof rawoptions.settle === "number" ? rawoptions.settle : 150;
|
|
16744
17969
|
const overlap = typeof rawoptions.overlap === "number" ? rawoptions.overlap : 0;
|
|
16745
17970
|
const wait = typeof rawoptions.wait === "number" ? rawoptions.wait : void 0;
|
|
@@ -16776,7 +18001,7 @@ async function executecapturestep(step, session, plan, tabid2, origin) {
|
|
|
16776
18001
|
}
|
|
16777
18002
|
if (step.kind === "shotelement") {
|
|
16778
18003
|
const selector = step.target ?? "";
|
|
16779
|
-
const settle2 = typeof
|
|
18004
|
+
const settle2 = typeof stepoptions6(step).settle === "number" ? stepoptions6(step).settle : 150;
|
|
16780
18005
|
const measured = await bridgecall(tabid2, "measurepage");
|
|
16781
18006
|
const targetinfo = await bridgecall(tabid2, "elementrect", selector);
|
|
16782
18007
|
if (!targetinfo.ok || !targetinfo.rect) throw new Error(targetinfo.summary);
|
|
@@ -16817,7 +18042,7 @@ async function executecapturestep(step, session, plan, tabid2, origin) {
|
|
|
16817
18042
|
}
|
|
16818
18043
|
}
|
|
16819
18044
|
if (step.kind === "shotregion") {
|
|
16820
|
-
const rawoptions =
|
|
18045
|
+
const rawoptions = stepoptions6(step);
|
|
16821
18046
|
const rect = rawoptions.regionrect;
|
|
16822
18047
|
if (!rect) throw new Error("A reviewed regionrect is required in options.");
|
|
16823
18048
|
const container = typeof rawoptions.container === "string" ? rawoptions.container : void 0;
|
|
@@ -16858,7 +18083,7 @@ async function executecapturestep(step, session, plan, tabid2, origin) {
|
|
|
16858
18083
|
}
|
|
16859
18084
|
}
|
|
16860
18085
|
if (step.kind === "contactsheet") {
|
|
16861
|
-
const rawoptions =
|
|
18086
|
+
const rawoptions = stepoptions6(step);
|
|
16862
18087
|
const elements = (Array.isArray(rawoptions.elements) ? rawoptions.elements : []).filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
16863
18088
|
const layout = rawoptions.sheet && typeof rawoptions.sheet === "object" && !Array.isArray(rawoptions.sheet) ? rawoptions.sheet : { cellsize: 240, columns: 3, label: "both" };
|
|
16864
18089
|
const measured = await bridgecall(tabid2, "measurepage");
|
|
@@ -16969,7 +18194,7 @@ async function thumbonecapture(source, directive, plan, step) {
|
|
|
16969
18194
|
return { id: randomid(), runid: plan.id, stepid: step.id, kind: "makethumbs", format, width: geometry.width, height: geometry.height, capturedat: Date.now(), bytes: dataurl, name, target: source.id };
|
|
16970
18195
|
}
|
|
16971
18196
|
async function executemediastep(step, session, plan, tabid2, origin) {
|
|
16972
|
-
const options =
|
|
18197
|
+
const options = stepoptions6(step);
|
|
16973
18198
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
16974
18199
|
const gate = mediagate(session, tabid2, origin, Date.now());
|
|
16975
18200
|
if (!gate.allowed) throw new Error(gate.reason ?? "The media capture needs the active session tab grant.");
|
|
@@ -17228,7 +18453,7 @@ async function attachapikeys(names, origin) {
|
|
|
17228
18453
|
return { headers, keys: attached };
|
|
17229
18454
|
}
|
|
17230
18455
|
async function executehttpstep(step, session, plan, tabid2, origin) {
|
|
17231
|
-
const options =
|
|
18456
|
+
const options = stepoptions6(step);
|
|
17232
18457
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
17233
18458
|
if (step.kind === "fetchurl") {
|
|
17234
18459
|
const request = fetchrequestof(options.fetch);
|
|
@@ -17493,7 +18718,7 @@ async function closechannelsforrun(runid) {
|
|
|
17493
18718
|
channelbuses.clear();
|
|
17494
18719
|
}
|
|
17495
18720
|
async function executesocketstep(step, session, plan, tabid2, origin) {
|
|
17496
|
-
const options =
|
|
18721
|
+
const options = stepoptions6(step);
|
|
17497
18722
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
17498
18723
|
if (step.kind === "opensocket") {
|
|
17499
18724
|
const channel = channeloptionsof(options.socket);
|
|
@@ -17627,7 +18852,7 @@ async function executesocketstep(step, session, plan, tabid2, origin) {
|
|
|
17627
18852
|
throw new Error("Unsupported socket observation kind.");
|
|
17628
18853
|
}
|
|
17629
18854
|
async function executenetwatchstep(step, session, plan, tabid2, origin) {
|
|
17630
|
-
const options =
|
|
18855
|
+
const options = stepoptions6(step);
|
|
17631
18856
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
17632
18857
|
if (step.kind === "watchrequests") {
|
|
17633
18858
|
const watch = options.watch && typeof options.watch === "object" && !Array.isArray(options.watch) ? options.watch : {};
|
|
@@ -17779,7 +19004,7 @@ function timelinedetail(entry, runid) {
|
|
|
17779
19004
|
return { id: randomid(), runid, stepid: record2.stepid, time: record2.time, level: record2.level, source: record2.source, message: record2.message };
|
|
17780
19005
|
}
|
|
17781
19006
|
async function executetimelinestep(step, session, plan, tabid2, origin) {
|
|
17782
|
-
const options =
|
|
19007
|
+
const options = stepoptions6(step);
|
|
17783
19008
|
const watch = options.watch && typeof options.watch === "object" && !Array.isArray(options.watch) ? options.watch : {};
|
|
17784
19009
|
const watchwindow = typeof watch.window === "number" && Number.isFinite(watch.window) && watch.window >= 0 ? watch.window : 0;
|
|
17785
19010
|
const extra = { sessionid: session.id, planid: plan.id, stepid: step.id };
|
|
@@ -17934,7 +19159,7 @@ function pauseframes(entry) {
|
|
|
17934
19159
|
});
|
|
17935
19160
|
}
|
|
17936
19161
|
async function executecdpstep(step, session, plan, tabid2, origin) {
|
|
17937
|
-
const options =
|
|
19162
|
+
const options = stepoptions6(step);
|
|
17938
19163
|
const extra = { sessionid: session.id, planid: plan.id, stepid: step.id };
|
|
17939
19164
|
const debuggatecheck = debuggate(session, tabid2, origin, Date.now());
|
|
17940
19165
|
if (!debuggatecheck.allowed) throw new Error(debuggatecheck.reason ?? "The devtools protocol step stays outside the debug gate.");
|
|
@@ -18168,7 +19393,7 @@ async function sampleheapforstep(tracker, stepid, tabid2, origin, plan) {
|
|
|
18168
19393
|
if (trend.flaggedsteps.includes(stepid)) await memory.addtimelineentry({ id: randomid(), runid: tracker.runid, stepid, time: now, level: "warn", source: "longtask", message: `Heap growth of step ${stepid} exceeds the reviewed slope of ${tracker.slope} bytes per millisecond; the step is flagged in the memory trend.` });
|
|
18169
19394
|
}
|
|
18170
19395
|
async function executeprofilestep(step, session, plan, tabid2, origin) {
|
|
18171
|
-
const options =
|
|
19396
|
+
const options = stepoptions6(step);
|
|
18172
19397
|
const extra = { sessionid: session.id, planid: plan.id, stepid: step.id };
|
|
18173
19398
|
const targets = profiletargetsof(options);
|
|
18174
19399
|
const grants = await memory.getdebuggergrants();
|
|
@@ -18497,7 +19722,7 @@ async function controlledfetch(runid, url, init, controller, window2, streamstat
|
|
|
18497
19722
|
return response;
|
|
18498
19723
|
}
|
|
18499
19724
|
async function executenetcontrolstep(step, session, plan, tabid2, origin) {
|
|
18500
|
-
const options =
|
|
19725
|
+
const options = stepoptions6(step);
|
|
18501
19726
|
const extra = { ...session ? { sessionid: session.id } : {}, planid: plan.id, stepid: step.id };
|
|
18502
19727
|
const ruleset = rulesetof(plan.id);
|
|
18503
19728
|
if (step.kind === "blockrequest") {
|
|
@@ -18744,7 +19969,7 @@ async function enforcewindowreview(step, session, plan) {
|
|
|
18744
19969
|
const progress = plan ? await memory.getprogress() : void 0;
|
|
18745
19970
|
const tasktabids = plan ? trackedtasktabs(progress, plan.id) : [];
|
|
18746
19971
|
const count = tasktabsinwindow(await livetabs(), windowid, tasktabids);
|
|
18747
|
-
const gate = windowclosegate(count,
|
|
19972
|
+
const gate = windowclosegate(count, stepoptions6(step).reviewed === true);
|
|
18748
19973
|
if (!gate.allowed) throw new Error(gate.reason ?? "The window close needs explicit review.");
|
|
18749
19974
|
if (session && count > 0) await audit("window", `Window ${windowid} closes while holding ${count} task tab${count === 1 ? "" : "s"} under the explicit reviewed flag.`, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid: step.id });
|
|
18750
19975
|
}
|
|
@@ -18830,7 +20055,7 @@ async function revertemulationforrun(runid, reason, tabid2) {
|
|
|
18830
20055
|
}
|
|
18831
20056
|
}
|
|
18832
20057
|
async function executeemulationstep(step, session, plan, tabid2, origin) {
|
|
18833
|
-
const options =
|
|
20058
|
+
const options = stepoptions6(step);
|
|
18834
20059
|
const extra = { sessionid: session.id, planid: plan.id, stepid: step.id };
|
|
18835
20060
|
const revertplan = revertplanof(options.revertplan) ?? [];
|
|
18836
20061
|
const family = familyofkind(step.kind) ?? "device";
|
|
@@ -18962,7 +20187,7 @@ async function performrestore(record2, restore, session) {
|
|
|
18962
20187
|
return { restored, skippedorigins: grantscheck.skippedorigins };
|
|
18963
20188
|
}
|
|
18964
20189
|
async function executesessionstep(step, session, plan, tabid2, origin) {
|
|
18965
|
-
const options =
|
|
20190
|
+
const options = stepoptions6(step);
|
|
18966
20191
|
const extra = { sessionid: session.id, planid: plan.id, stepid: step.id };
|
|
18967
20192
|
if (step.kind === "persiststate") {
|
|
18968
20193
|
const progress = await memory.getprogress();
|
|
@@ -19107,7 +20332,7 @@ async function dispatchworkflowstep(step, context) {
|
|
|
19107
20332
|
return { ok: Boolean(output.ok), summary: output.summary, ...output.details !== void 0 ? { details: output.details } : {} };
|
|
19108
20333
|
}
|
|
19109
20334
|
async function executedelaystep(step) {
|
|
19110
|
-
const options =
|
|
20335
|
+
const options = stepoptions6({ id: step.id, kind: step.kind, summary: step.label, risk: "read", ...step.options !== void 0 ? { options: step.options } : {} });
|
|
19111
20336
|
const delay = delayof(options.delay);
|
|
19112
20337
|
const sampled = delayjitter(delay, hashseed(`${step.id}:${Date.now()}`));
|
|
19113
20338
|
const transport = await sleepreviewed(sampled, step.id);
|
|
@@ -19154,7 +20379,7 @@ async function sleepreviewed(sampled, stepid) {
|
|
|
19154
20379
|
return "timer";
|
|
19155
20380
|
}
|
|
19156
20381
|
async function executewaitelement(step, tabid2) {
|
|
19157
|
-
const options =
|
|
20382
|
+
const options = stepoptions6({ id: step.id, kind: step.kind, summary: step.label, risk: "read", ...step.target !== void 0 ? { target: step.target } : {}, ...step.options !== void 0 ? { options: step.options } : {} });
|
|
19158
20383
|
const wait = waitof(options.wait, step.target);
|
|
19159
20384
|
const startedat = Date.now();
|
|
19160
20385
|
const starttab = await chrome.tabs.get(tabid2).catch(() => void 0);
|
|
@@ -19182,7 +20407,7 @@ function waitof(value, target) {
|
|
|
19182
20407
|
return { selector, timeout, poll };
|
|
19183
20408
|
}
|
|
19184
20409
|
async function executecomputestep(step, session) {
|
|
19185
|
-
const options =
|
|
20410
|
+
const options = stepoptions6({ id: step.id, kind: step.kind, summary: step.label, risk: "read", ...step.options !== void 0 ? { options: step.options } : {} });
|
|
19186
20411
|
const expression = options.expression;
|
|
19187
20412
|
if (!expression || typeof expression !== "object") throw new Error("The compute step needs a reviewed expression.");
|
|
19188
20413
|
const scopes = runscopes(options.variables);
|
|
@@ -19191,7 +20416,7 @@ async function executecomputestep(step, session) {
|
|
|
19191
20416
|
return { ok: true, summary: `Computed ${expression.result} = ${typeof value === "string" ? `"${value}"` : String(value)} through the ${expression.operator} operator.`, details: { result: expression.result, kind: expression.resultkind, value } };
|
|
19192
20417
|
}
|
|
19193
20418
|
async function executeextractvarsstep(step, session) {
|
|
19194
|
-
const options =
|
|
20419
|
+
const options = stepoptions6({ id: step.id, kind: step.kind, summary: step.label, risk: "read", ...step.value !== void 0 ? { value: step.value } : {}, ...step.options !== void 0 ? { options: step.options } : {} });
|
|
19195
20420
|
const rule = options.rule;
|
|
19196
20421
|
if (!rule || typeof rule !== "object" || typeof rule.pattern !== "string") throw new Error("The variable extraction needs a reviewed regex rule.");
|
|
19197
20422
|
const text2 = typeof options.text === "string" ? options.text : step.value ?? "";
|
|
@@ -19204,7 +20429,7 @@ async function executeextractvarsstep(step, session) {
|
|
|
19204
20429
|
return { ok: true, summary: `Captured ${extraction.variables.length} variable${extraction.variables.length === 1 ? "" : "s"} from the reviewed text.`, details: { matched: true, variables: extraction.variables } };
|
|
19205
20430
|
}
|
|
19206
20431
|
async function executeworkflowstep(step, session, plan, tabid2, origin) {
|
|
19207
|
-
const options =
|
|
20432
|
+
const options = stepoptions6(step);
|
|
19208
20433
|
if (step.kind === "composeworkflow") {
|
|
19209
20434
|
const payload = options.workflow;
|
|
19210
20435
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new Error("The workflow composition needs the reviewed workflow payload.");
|
|
@@ -19260,7 +20485,7 @@ function workflowstepofentry(value) {
|
|
|
19260
20485
|
return blockinvocationof(value);
|
|
19261
20486
|
}
|
|
19262
20487
|
async function executeworkflowrun(step, session, plan, tabid2, origin, dry) {
|
|
19263
|
-
const options =
|
|
20488
|
+
const options = stepoptions6(step);
|
|
19264
20489
|
const workflowid = typeof options.workflowid === "string" ? options.workflowid : "";
|
|
19265
20490
|
const storedrecord = await memory.getworkflowrecord(workflowid);
|
|
19266
20491
|
if (!storedrecord) throw new Error(`No composed workflow matches ${workflowid || "the reviewed id"}.`);
|
|
@@ -19423,7 +20648,7 @@ async function storetimeoutabort(run, step, message, budget) {
|
|
|
19423
20648
|
return { run: aborted, log: [entry] };
|
|
19424
20649
|
}
|
|
19425
20650
|
async function executetriggerstep(step, session, plan, tabid2, origin) {
|
|
19426
|
-
const options =
|
|
20651
|
+
const options = stepoptions6(step);
|
|
19427
20652
|
const family = triggerfamilyof(step.kind);
|
|
19428
20653
|
if (!family) throw new Error(`The ${step.kind} step is not a reviewed trigger kind.`);
|
|
19429
20654
|
const workflowid = typeof options.workflowid === "string" ? options.workflowid : "";
|
|
@@ -19643,12 +20868,15 @@ async function executeaction(step, session, plan, tabid2, origin, settings, verd
|
|
|
19643
20868
|
}
|
|
19644
20869
|
await audit("deny", `The ${step.kind} step ${step.id} on ${origin} was denied without navigation: ${securityverdict.reason}`, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid: step.id });
|
|
19645
20870
|
if (securityverdict.suspended && session) {
|
|
20871
|
+
await memory.addconsentmemoryentry(consentmemoryof({ origin, decision: "expire", boundary: "the consent window boundary that expired mid step", kinds: [step.kind], now: Date.now() })).catch(() => {
|
|
20872
|
+
});
|
|
19646
20873
|
await appendrunevent("expiry", `The consent window of ${origin} expired mid step and the run suspended at the step ${step.id}; a new explicit prompt renews it.`, session, origin, step.id).catch(() => {
|
|
19647
20874
|
});
|
|
19648
20875
|
await audit("expiry", `The consent window of ${origin} expired mid step and the run suspended at the step ${step.id}; the executor refuses to resume without a new explicit prompt.`, { sessionid: session.id, ...plan ? { planid: plan.id } : {}, stepid: step.id });
|
|
19649
20876
|
}
|
|
19650
20877
|
throw new Error(securityverdict.reason);
|
|
19651
20878
|
}
|
|
20879
|
+
step = await resolvevaultvalues(step, session);
|
|
19652
20880
|
if (session && plan && plan.state === "approved" && mode === "plan") await openplanrun(session, plan);
|
|
19653
20881
|
if (plan && plan.state === "approved") await markpendingstep(plan, step.id);
|
|
19654
20882
|
if (routing.environment === "sandboxframe") return executesandboxrender(step, session, plan, origin);
|
|
@@ -19781,6 +21009,17 @@ async function executeaction(step, session, plan, tabid2, origin, settings, verd
|
|
|
19781
21009
|
const auditkind = stepauditkind(step, Boolean(output?.ok));
|
|
19782
21010
|
await audit(auditkind, summary, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid: step.id });
|
|
19783
21011
|
await memory.addoutcome(outcome);
|
|
21012
|
+
if (session && plan) await memory.appendscratchentry(scratchentryof({ taskid: plan.id, sessionid: session.id, text: `${step.kind} ${step.id} ${outcome.ok ? "completed" : "failed"}: ${summary}`, stepid: step.id, author: "agent", now: Date.now() })).catch(() => {
|
|
21013
|
+
});
|
|
21014
|
+
if (plan) await memory.addrecallentry(recallentryof({ origin, runid: plan.id, stepid: step.id, text: summary, at: Date.now() })).catch(() => {
|
|
21015
|
+
});
|
|
21016
|
+
let stepretry;
|
|
21017
|
+
if (!outcome.ok && plan) {
|
|
21018
|
+
const surface = errorsurfaceof({ stepid: step.id, runid: plan.id, message: summary, cause: classifyfailure({ message: summary, policyrefused: false, gatewait: false }), retryallowed: true, retryreason: "The failed step may dispatch again through the full consent gate chain.", context: { origin, kind: step.kind, environment: routing.environment }, now: Date.now() });
|
|
21019
|
+
await memory.adderrorsurface(surface).catch(() => {
|
|
21020
|
+
});
|
|
21021
|
+
stepretry = { allowed: true, reason: `The ${surface.cause} failure of the step ${step.id} may retry through a new reviewed dispatch; the retry rides the full consent gate chain and never bypasses the review.` };
|
|
21022
|
+
}
|
|
19784
21023
|
if (session) await appendrunevent("step", `The ${step.kind} step ${step.id} ${outcome.ok ? "completed" : "failed"} on ${origin}: ${summary}${securityverdict.classification.sensitive ? ` The step grades ${securityverdict.classification.reason}` : ""}`, session, origin, step.id).catch(() => {
|
|
19785
21024
|
});
|
|
19786
21025
|
if (output?.ok && plan && mode === "plan") {
|
|
@@ -19812,11 +21051,36 @@ async function executeaction(step, session, plan, tabid2, origin, settings, verd
|
|
|
19812
21051
|
const done = { ...plan, state: "completed", completedat: Date.now() };
|
|
19813
21052
|
await memory.setplan(done);
|
|
19814
21053
|
await closeplanrun(done.id, session?.id ?? "");
|
|
21054
|
+
await distillcompletedrun(done, tracked, session, settings).catch(() => {
|
|
21055
|
+
});
|
|
19815
21056
|
await audit("complete", "Every reviewed step of the approved plan has executed.", { ...session ? { sessionid: session.id } : {}, planid: done.id });
|
|
19816
21057
|
}
|
|
19817
21058
|
}
|
|
21059
|
+
if (stepretry !== void 0 && output !== void 0) return { ...output, retry: stepretry };
|
|
21060
|
+
if (stepretry !== void 0) return { ok: false, summary, retry: stepretry };
|
|
19818
21061
|
return output ?? { ok: false, summary };
|
|
19819
21062
|
}
|
|
21063
|
+
async function distillcompletedrun(plan, progress, session, settings) {
|
|
21064
|
+
const log = await memory.getimmutablelog(plan.id);
|
|
21065
|
+
const origins = [.../* @__PURE__ */ new Set([session?.origin ?? "", ...(log?.entries ?? []).map((entry) => entry.origin).filter((entryorigin) => entryorigin !== "")])].filter((entryorigin) => entryorigin !== "");
|
|
21066
|
+
let provenance = "inline";
|
|
21067
|
+
const inline = distillrunsummary({ plan, outcomes: progress.outcomes ?? [], origins, sessionid: session?.id ?? "", ...settings?.summarywindow !== void 0 ? { window: settings.summarywindow } : {}, provenance: "inline", now: Date.now() });
|
|
21068
|
+
const ready = await ensureoffscreendocument(plan.id).catch(() => false);
|
|
21069
|
+
if (ready) {
|
|
21070
|
+
const request = summaryrequestof({ id: randomid(), runid: plan.id, sessionid: session?.id ?? "", payload: JSON.stringify({ runid: plan.id, steps: inline.steps.length, window: settings?.summarywindow }), sentat: Date.now() });
|
|
21071
|
+
try {
|
|
21072
|
+
const answer = await chrome.runtime.sendMessage({ kind: "offscreen", action: "summary", request: { id: request.id, runid: request.runid, stepid: request.stepid, task: runsummarytask, payload: request.payload, transferables: [] } });
|
|
21073
|
+
if (answer && answer.ok !== false) provenance = "offscreenworker";
|
|
21074
|
+
} catch {
|
|
21075
|
+
}
|
|
21076
|
+
}
|
|
21077
|
+
const summary = { ...inline, provenance };
|
|
21078
|
+
await memory.setrunsummary(summary);
|
|
21079
|
+
await memory.trackrunsummary(plan.id);
|
|
21080
|
+
if (settings?.historyindex !== false) await memory.addhistoryentry(summaryhistoryentry(summary));
|
|
21081
|
+
await audit("summary", `The run summary of ${plan.id} distilled ${summary.steps.length} step outcome${summary.steps.length === 1 ? "" : "s"} across ${summary.origins.length} origin${summary.origins.length === 1 ? "" : "s"} as one ${provenance === "offscreenworker" ? "offscreen worker task" : "inline distillation"}${summary.window !== void 0 ? ` inside the user configured window of ${summary.window} steps` : " with no window cap"}.`, { ...session ? { sessionid: session.id } : {}, planid: plan.id });
|
|
21082
|
+
return summary;
|
|
21083
|
+
}
|
|
19820
21084
|
async function previewstep(stepid) {
|
|
19821
21085
|
const session = await memory.getsession();
|
|
19822
21086
|
const plan = await memory.getplan();
|
|
@@ -19825,7 +21089,7 @@ async function previewstep(stepid) {
|
|
|
19825
21089
|
if (!step) throw new Error("Reviewed step was not found.");
|
|
19826
21090
|
const gate = canpreview({ session, plan, step, tabid: tab.id, origin });
|
|
19827
21091
|
if (!gate.allowed) throw new Error(gate.reason);
|
|
19828
|
-
if (!step.target && !
|
|
21092
|
+
if (!step.target && !stepoptions6(step).targetref) throw new Error("Only a target-based step can be previewed.");
|
|
19829
21093
|
const result = await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: (action, expectedorigin) => {
|
|
19830
21094
|
const bridge = globalThis.devthinkbridge;
|
|
19831
21095
|
if (!bridge) throw new Error("Devthink page bridge is unavailable.");
|
|
@@ -19876,8 +21140,253 @@ async function extractionreportValue() {
|
|
|
19876
21140
|
async function provenancereportValue() {
|
|
19877
21141
|
return provenancereport({ records: await memory.getprovenances() });
|
|
19878
21142
|
}
|
|
21143
|
+
var commandschemas = {
|
|
21144
|
+
security: { allowlist: "object", profile: "object", consent: "object", revoke: "object", mask: "object", read: "object", export: "object", settings: "object", gate: "object", vault: "object", connectallow: "object", ratelimit: "object", redact: "object" },
|
|
21145
|
+
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
|
+
environments: { action: "string", grants: "array", requestcapability: "boolean", pool: "object", offscreenclose: "boolean", sandbox: "object", settings: "object", render: "object", sandboxhost: "object" },
|
|
21147
|
+
transparency: {},
|
|
21148
|
+
execute: { stepid: "string" },
|
|
21149
|
+
configure: { endpoint: "string" }
|
|
21150
|
+
};
|
|
21151
|
+
function schemavalidation(message) {
|
|
21152
|
+
if (!Boolean(message) || typeof message !== "object" || Array.isArray(message)) return [{ path: "message", expected: "object", found: Array.isArray(message) ? "array" : typeof message, reason: "Every inbound command travels as one plain object; schemastrict refuses the carrier before dispatch." }];
|
|
21153
|
+
const command = message;
|
|
21154
|
+
if (typeof command.kind !== "string" || command.kind.trim() === "") return [{ path: "kind", expected: "string", found: typeof command.kind, reason: "Every inbound command names its kind as a non-empty string; a kindless command never dispatches." }];
|
|
21155
|
+
const schema = commandschemas[command.kind];
|
|
21156
|
+
if (schema === void 0) return [];
|
|
21157
|
+
return schemacheck({ command, schema }).errors;
|
|
21158
|
+
}
|
|
21159
|
+
async function sessionviewof() {
|
|
21160
|
+
const session = await memory.getsession();
|
|
21161
|
+
const plan = await memory.getplan();
|
|
21162
|
+
const settings = await memory.getsettings();
|
|
21163
|
+
const progress = await memory.getprogress();
|
|
21164
|
+
const notes = await memory.getsitenotes();
|
|
21165
|
+
const scratch = plan && session ? await memory.readscratchpad(plan.id, session.id) : [];
|
|
21166
|
+
const summaries = await memory.listrunsummaries();
|
|
21167
|
+
const corrections = await memory.getcorrections();
|
|
21168
|
+
const consentmemory = await memory.getconsentmemory();
|
|
21169
|
+
const index = await memory.getrecallindex();
|
|
21170
|
+
const scope = session ? [.../* @__PURE__ */ new Set([session.origin, ...session.grants ?? []])] : [];
|
|
21171
|
+
const recall = rankrecall(index, { text: plan?.objective ?? session?.origin ?? "" }, { origins: scope }).slice(0, 5);
|
|
21172
|
+
const errors = (await memory.geterrorsurfaces()).slice(0, 20);
|
|
21173
|
+
const rows = sessiongridrows({ ...session !== void 0 ? { session } : {}, ...plan !== void 0 ? { plan } : {}, ...progress !== void 0 ? { progress } : {}, logs: await memory.listimmutablelogs(), summaries, locks: await memory.getrunlocks(), tabsessions: await memory.listtabsessions() });
|
|
21174
|
+
return {
|
|
21175
|
+
grid: rows.map((row) => ({ sessionid: row.sessionid, runid: row.runid, origins: row.origins, state: row.state, outcome: row.outcome, steps: row.steps, completed: row.completed, lock: row.lock, ...row.tabid !== void 0 ? { tabid: row.tabid } : {}, ...row.sealhash !== void 0 ? { sealhash: row.sealhash } : {}, updatedat: row.updatedat, actions: row.actions })),
|
|
21176
|
+
notes: notes.map((note) => ({ id: note.id, origin: note.origin, title: note.title, body: notebodyof(note), author: note.author, sensitive: note.sensitive, updatedat: note.updatedat })),
|
|
21177
|
+
scratchpad: scratch.map((entry) => ({ id: entry.id, taskid: entry.taskid, text: entry.text, ...entry.stepid !== void 0 ? { stepid: entry.stepid } : {}, author: entry.author, at: entry.at })),
|
|
21178
|
+
summaries: summaries.map((summary) => ({ runid: summary.runid, origins: summary.origins, kinds: summary.kinds, steps: summary.steps.length, provenance: summary.provenance, distilledat: summary.distilledat })),
|
|
21179
|
+
corrections: corrections.slice(0, 20).map((entry) => ({ id: entry.id, origin: entry.origin, kind: entry.kind, stepid: entry.stepid, source: entry.source, reason: entry.reason, at: entry.at })),
|
|
21180
|
+
consentmemory: consentmemory.slice(0, 20).map((entry) => ({ id: entry.id, origin: entry.origin, decision: entry.decision, boundary: entry.boundary, kinds: entry.kinds, at: entry.at, ...entry.expiresat !== void 0 ? { expiresat: entry.expiresat } : {} })),
|
|
21181
|
+
recall: recall.map((match) => ({ origin: match.entry.origin, runid: match.entry.runid, stepid: match.entry.stepid, score: match.score, reason: match.reason })),
|
|
21182
|
+
errors: errors.map((surface) => ({ stepid: surface.stepid, runid: surface.runid, cause: surface.cause, message: surface.message, retry: surface.retry, at: surface.at })),
|
|
21183
|
+
emptystates: [
|
|
21184
|
+
{ surface: "sessiongrid", message: rows.length === 0 ? "No session exists yet; start the first run by describing an objective and reviewing the plan the agent proposes." : "" },
|
|
21185
|
+
{ surface: "historysearch", message: "No history matches yet; start with a first query such as an origin, a note title or a kind the runs executed." },
|
|
21186
|
+
{ surface: "sitenotes", message: notes.length === 0 ? `No site note exists${session ? ` for ${session.origin}` : ""} yet; write the first note with a title and a body and the note flow keeps it per origin with its author provenance.` : "" },
|
|
21187
|
+
{ surface: "scratchpad", message: scratch.length === 0 ? "The scratchpad holds no entry yet; the agent appends its per task notes here while the reviewed steps run, and every entry carries its step provenance." : "" }
|
|
21188
|
+
].filter((state) => state.message !== ""),
|
|
21189
|
+
...settings?.cancelrollback !== void 0 ? { cancelrollback: settings.cancelrollback } : {},
|
|
21190
|
+
historyindex: settings?.historyindex !== false
|
|
21191
|
+
};
|
|
21192
|
+
}
|
|
21193
|
+
async function handlesessionscommand(message) {
|
|
21194
|
+
const input = message;
|
|
21195
|
+
const now = Date.now();
|
|
21196
|
+
const session = await memory.getsession();
|
|
21197
|
+
const plan = await memory.getplan();
|
|
21198
|
+
const settings = await memory.getsettings();
|
|
21199
|
+
if (input.note !== void 0) {
|
|
21200
|
+
if (input.note.add !== void 0) {
|
|
21201
|
+
const origin = input.note.add.origin?.trim() || session?.origin || "";
|
|
21202
|
+
if (origin === "") throw new Error("The site note needs its origin.");
|
|
21203
|
+
const writegate = sitenoteswritegate({ consent: input.note.add.consent === true, origin });
|
|
21204
|
+
if (!writegate.allowed) throw new Error(writegate.reason);
|
|
21205
|
+
const note = sitenoteof({ origin, title: input.note.add.title ?? "", body: input.note.add.body ?? "", author: "user", ...input.note.add.sensitive === true ? { sensitive: true } : {}, now });
|
|
21206
|
+
await memory.writesitenote(note);
|
|
21207
|
+
if (settings?.historyindex !== false) await memory.addhistoryentry(notehistoryentry(note));
|
|
21208
|
+
await audit("notes", `The user wrote the site note ${note.id} for ${origin}${note.sensitive ? " with its body sealed at rest" : ""}; the note keeps its author provenance and its timestamps.`, { ...session ? { sessionid: session.id } : {} });
|
|
21209
|
+
return { ...await sessionviewof(), note };
|
|
21210
|
+
}
|
|
21211
|
+
if (input.note.edit !== void 0) {
|
|
21212
|
+
const id = input.note.edit.id?.trim() ?? "";
|
|
21213
|
+
const note = (await memory.getsitenotes()).find((candidate) => candidate.id === id);
|
|
21214
|
+
if (!note) throw new Error(`No site note ${id} exists to edit.`);
|
|
21215
|
+
const writegate = sitenoteswritegate({ consent: true, origin: note.origin });
|
|
21216
|
+
if (!writegate.allowed) throw new Error(writegate.reason);
|
|
21217
|
+
const edited = editnote(note, { title: input.note.edit.title ?? note.title, body: input.note.edit.body ?? notebodyof(note), author: "user", now });
|
|
21218
|
+
await memory.writesitenote(edited);
|
|
21219
|
+
if (settings?.historyindex !== false) await memory.addhistoryentry(notehistoryentry(edited));
|
|
21220
|
+
await audit("notes", `The user edited the site note ${edited.id} of ${edited.origin}; the edit keeps the created timestamp and names its author.`, { ...session ? { sessionid: session.id } : {} });
|
|
21221
|
+
return { ...await sessionviewof(), note: edited };
|
|
21222
|
+
}
|
|
21223
|
+
if (input.note.remove !== void 0) {
|
|
21224
|
+
const id = input.note.remove.id?.trim() ?? "";
|
|
21225
|
+
await memory.removesitenote(id);
|
|
21226
|
+
await audit("notes", `The user removed the site note ${id}.`, { ...session ? { sessionid: session.id } : {} });
|
|
21227
|
+
return { ...await sessionviewof(), removed: id };
|
|
21228
|
+
}
|
|
21229
|
+
if (input.note.list !== void 0) {
|
|
21230
|
+
const origin = input.note.list.origin?.trim() || session?.origin || "";
|
|
21231
|
+
if (origin === "") throw new Error("The site note read needs its origin.");
|
|
21232
|
+
const readgate = sitenotesreadgate({ origin, grants: session ? [.../* @__PURE__ */ new Set([session.origin, ...session.grants ?? []])] : [] });
|
|
21233
|
+
if (!readgate.allowed) throw new Error(readgate.reason);
|
|
21234
|
+
return { notes: (await memory.readsitenotes(origin)).map((note) => ({ id: note.id, origin: note.origin, title: note.title, body: notebodyof(note), author: note.author, sensitive: note.sensitive, updatedat: note.updatedat })) };
|
|
21235
|
+
}
|
|
21236
|
+
}
|
|
21237
|
+
if (input.scratch !== void 0) {
|
|
21238
|
+
if (!session || !plan) throw new Error("The scratchpad serves the running task of an active session.");
|
|
21239
|
+
const taskid = input.scratch.append?.taskid?.trim() || input.scratch.read?.taskid?.trim() || plan.id;
|
|
21240
|
+
const scopegate2 = scratchpadscopegate({ taskid, sessionid: session.id, entrytaskid: taskid, entrysessionid: session.id });
|
|
21241
|
+
if (!scopegate2.allowed) throw new Error(scopegate2.reason);
|
|
21242
|
+
if (input.scratch.append !== void 0) {
|
|
21243
|
+
const entry = scratchentryof({ taskid, sessionid: session.id, text: input.scratch.append.text ?? "", ...input.scratch.append.stepid !== void 0 && input.scratch.append.stepid.trim() !== "" ? { stepid: input.scratch.append.stepid } : {}, author: "user", now });
|
|
21244
|
+
await memory.appendscratchentry(entry);
|
|
21245
|
+
await audit("scratchpad", `The user appended one scratchpad entry to the task ${taskid}${entry.stepid !== void 0 ? ` beside the step ${entry.stepid}` : ""}; the pad stays append only.`, { sessionid: session.id, planid: taskid });
|
|
21246
|
+
return { ...await sessionviewof(), entry };
|
|
21247
|
+
}
|
|
21248
|
+
if (input.scratch.read !== void 0) return { scratchpad: await memory.readscratchpad(taskid, session.id) };
|
|
21249
|
+
}
|
|
21250
|
+
if (input.summary !== void 0) {
|
|
21251
|
+
if (input.summary.read !== void 0) {
|
|
21252
|
+
const runid = input.summary.read.runid?.trim() || plan?.id || "";
|
|
21253
|
+
const summary = await memory.getrunsummary(runid);
|
|
21254
|
+
if (!summary) throw new Error(`No run summary exists for the run ${runid}.`);
|
|
21255
|
+
return { summary };
|
|
21256
|
+
}
|
|
21257
|
+
if (input.summary.list !== void 0) return { summaries: await memory.listrunsummaries(input.summary.list.origin?.trim() || void 0) };
|
|
21258
|
+
}
|
|
21259
|
+
if (input.recall !== void 0 && input.recall.query !== void 0) {
|
|
21260
|
+
const text2 = input.recall.query.text?.trim() ?? "";
|
|
21261
|
+
if (text2 === "") throw new Error("The semantic recall query needs its text.");
|
|
21262
|
+
const scope = session ? [.../* @__PURE__ */ new Set([session.origin, ...session.grants ?? []])] : [];
|
|
21263
|
+
const scopegate2 = semanticrecallscopegate({ origin: input.recall.query.origin?.trim() || void 0, scope });
|
|
21264
|
+
if (!scopegate2.allowed) throw new Error(scopegate2.reason);
|
|
21265
|
+
const matches = await memory.semanticrecall({ text: text2, ...input.recall.query.origin !== void 0 && input.recall.query.origin.trim() !== "" ? { origin: input.recall.query.origin.trim() } : {}, ...input.recall.query.limit !== void 0 ? { limit: input.recall.query.limit } : {} }, { origins: scope }, rankrecall);
|
|
21266
|
+
await audit("recall", `The semantic recall ranked ${matches.length} past extraction${matches.length === 1 ? "" : "s"} by text similarity inside the ${scope.length} origin scope${scope.length === 1 ? "" : "s"} of the run; every match carries its run and step provenance.`, { ...session ? { sessionid: session.id } : {} });
|
|
21267
|
+
return { matches };
|
|
21268
|
+
}
|
|
21269
|
+
if (input.correction !== void 0 && input.correction.list !== void 0) {
|
|
21270
|
+
const readgate = memoryreadscopegate({ phase: plan && plan.state === "pending" ? "planning" : "prompting" });
|
|
21271
|
+
if (!readgate.allowed) throw new Error(readgate.reason);
|
|
21272
|
+
return { corrections: await memory.getcorrections({ ...input.correction.list.origin !== void 0 ? { origin: input.correction.list.origin } : {}, ...input.correction.list.kind !== void 0 ? { kind: input.correction.list.kind } : {} }) };
|
|
21273
|
+
}
|
|
21274
|
+
if (input.consent !== void 0 && input.consent.list !== void 0) {
|
|
21275
|
+
const readgate = memoryreadscopegate({ phase: "prompting" });
|
|
21276
|
+
if (!readgate.allowed) throw new Error(readgate.reason);
|
|
21277
|
+
const origin = input.consent.list.origin?.trim() || session?.origin || "";
|
|
21278
|
+
const entries = await memory.getconsentmemory(origin === "" ? void 0 : origin);
|
|
21279
|
+
const advisory = consentadvisoryverdict(entries, origin, "observe");
|
|
21280
|
+
return { entries, advisory: advisory.reason };
|
|
21281
|
+
}
|
|
21282
|
+
if (input.grid !== void 0) {
|
|
21283
|
+
if (input.grid.rows !== void 0) return { grid: (await sessionviewof()).grid };
|
|
21284
|
+
if (input.grid.open !== void 0) {
|
|
21285
|
+
const runid = input.grid.open.runid?.trim() ?? "";
|
|
21286
|
+
const view = await sessionviewof();
|
|
21287
|
+
const row = view.grid.find((candidate) => candidate.runid === runid);
|
|
21288
|
+
if (!row) throw new Error(`No session grid row exists for the run ${runid}.`);
|
|
21289
|
+
if (row.tabid !== void 0) await chrome.sidePanel.open({ tabId: row.tabid }).catch(() => {
|
|
21290
|
+
});
|
|
21291
|
+
await audit("session", `The user opened the session grid row of the run ${runid} from the interface deep link.`, { ...session ? { sessionid: session.id } : {}, planid: runid });
|
|
21292
|
+
return { opened: runid };
|
|
21293
|
+
}
|
|
21294
|
+
if (input.grid.resume !== void 0) {
|
|
21295
|
+
const runid = input.grid.resume.runid?.trim() ?? "";
|
|
21296
|
+
if (!session) throw new Error("The resume needs its active session.");
|
|
21297
|
+
if (session.pausedat === void 0) throw new Error("The session of the run stays active; nothing to resume.");
|
|
21298
|
+
const { pausedat, ...resumedsession } = session;
|
|
21299
|
+
void pausedat;
|
|
21300
|
+
await memory.setsession(resumedsession);
|
|
21301
|
+
await audit("resume", `The user resumed the paused session of the run ${runid} from the session grid.`, { sessionid: session.id, planid: runid });
|
|
21302
|
+
return { ...await sessionviewof(), resumed: runid };
|
|
21303
|
+
}
|
|
21304
|
+
if (input.grid.reopen !== void 0) {
|
|
21305
|
+
const runid = input.grid.reopen.runid?.trim() ?? "";
|
|
21306
|
+
const log = await memory.getimmutablelog(runid);
|
|
21307
|
+
if (!log) throw new Error(`No sealed run exists for the run ${runid}.`);
|
|
21308
|
+
const read = await readverifiedlog(log);
|
|
21309
|
+
if (!read.ok) throw new Error(read.reason);
|
|
21310
|
+
await audit("session", `The user reopened the sealed run ${runid} from the session grid; the chain verification passed and the log link stays intact.`, { ...session ? { sessionid: session.id } : {}, planid: runid });
|
|
21311
|
+
return { reopened: runid, entries: read.entries.length, ...log.seal !== void 0 ? { sealhash: log.seal.sealhash.current } : {} };
|
|
21312
|
+
}
|
|
21313
|
+
}
|
|
21314
|
+
if (input.search !== void 0 && input.search.query !== void 0) {
|
|
21315
|
+
if (settings?.historyindex === false) throw new Error("The historysearch index building stays off in the user preferences; the search box needs the index on.");
|
|
21316
|
+
const query = historyqueryof(input.search.query);
|
|
21317
|
+
if (!query) throw new Error("The history search needs its text with a coherent time range.");
|
|
21318
|
+
const hits = await memory.historysearch(query, historysearch);
|
|
21319
|
+
await audit("search", `The history search matched ${hits.length} entr${hits.length === 1 ? "y" : "ies"} of the corpus${query.origin !== void 0 ? ` for ${query.origin}` : ""}${query.outcome !== void 0 ? ` with the outcome ${query.outcome}` : ""}; every hit highlights its matched terms.`, { ...session ? { sessionid: session.id } : {} });
|
|
21320
|
+
return { hits };
|
|
21321
|
+
}
|
|
21322
|
+
if (input.cancel !== void 0) {
|
|
21323
|
+
const runid = input.cancel.runid?.trim() || plan?.id || "";
|
|
21324
|
+
if (runid === "") throw new Error("The cancelrun needs its run.");
|
|
21325
|
+
const progress = await memory.getprogress();
|
|
21326
|
+
const preference = input.cancel.rollback === "none" ? "none" : input.cancel.rollback === "queued" ? "queued" : settings?.cancelrollback;
|
|
21327
|
+
const action = cancelrunactionof({ runid, sessionid: session?.id ?? "", plan: plan && plan.id === runid ? plan : void 0, progress, preference });
|
|
21328
|
+
const split = rollbacksplit(plan && plan.id === runid ? plan : void 0, progress);
|
|
21329
|
+
const cancelgate = cancelrungate({ queuedstepids: action.rollback.queuedstepids, executedstepids: split.executedstepids, rollbackscope: action.rollback.scope });
|
|
21330
|
+
if (!cancelgate.allowed) throw new Error(cancelgate.reason);
|
|
21331
|
+
if (plan && plan.id === runid && ["pending", "approved"].includes(plan.state)) await memory.setplan({ ...plan, state: "cancelled" });
|
|
21332
|
+
if (session) await appendrunevent("cancel", `The user cancelled the run ${runid}: ${action.rollback.label}`, session, session.origin).catch(() => {
|
|
21333
|
+
});
|
|
21334
|
+
await audit("cancel", `The user cancelled the run ${runid}: ${action.rollback.label}`, { ...session ? { sessionid: session.id } : {}, planid: runid });
|
|
21335
|
+
return { ...await sessionviewof(), cancelled: action };
|
|
21336
|
+
}
|
|
21337
|
+
if (input.retry !== void 0) {
|
|
21338
|
+
const stepid = input.retry.stepid?.trim() ?? "";
|
|
21339
|
+
if (stepid === "") throw new Error("The retry needs its step.");
|
|
21340
|
+
const retrygate = retrydispatchgate({ reviewed: true, stepid });
|
|
21341
|
+
if (!retrygate.allowed) throw new Error(retrygate.reason);
|
|
21342
|
+
const output = await executestep(stepid);
|
|
21343
|
+
await audit("retry", `The user retried the step ${stepid} through a new reviewed dispatch: ${output.summary}`, { ...session ? { sessionid: session.id } : {}, ...plan ? { planid: plan.id } : {}, stepid });
|
|
21344
|
+
return output;
|
|
21345
|
+
}
|
|
21346
|
+
if (input.error !== void 0) return { errors: await memory.geterrorsurfaces(input.error.stepid?.trim() || void 0) };
|
|
21347
|
+
if (input.settings !== void 0) {
|
|
21348
|
+
const patch = { ...settings };
|
|
21349
|
+
for (const field of ["noteretention", "scratchpadretention", "summaryretention", "correctionretention", "recallwindow"]) {
|
|
21350
|
+
const value = input.settings[field];
|
|
21351
|
+
if (value === void 0) continue;
|
|
21352
|
+
const gate = sessionretentionvalid(value);
|
|
21353
|
+
if (!gate.allowed) throw new Error(gate.reason);
|
|
21354
|
+
patch[field] = value;
|
|
21355
|
+
}
|
|
21356
|
+
if (input.settings.summarywindow !== void 0) {
|
|
21357
|
+
const windowgate = summarywindowvalid(input.settings.summarywindow);
|
|
21358
|
+
if (!windowgate.allowed) throw new Error(windowgate.reason);
|
|
21359
|
+
patch.summarywindow = input.settings.summarywindow;
|
|
21360
|
+
}
|
|
21361
|
+
if (input.settings.historyindex !== void 0) patch.historyindex = input.settings.historyindex === true;
|
|
21362
|
+
if (input.settings.cancelrollback !== void 0) patch.cancelrollback = input.settings.cancelrollback === "none" ? "none" : "queued";
|
|
21363
|
+
await memory.setsettings(patch);
|
|
21364
|
+
await audit("configure", `The user updated the session interface preferences: notes retention ${patch.noteretention !== void 0 ? `${patch.noteretention} milliseconds` : "every note stays"}, scratchpad retention ${patch.scratchpadretention !== void 0 ? `${patch.scratchpadretention} milliseconds` : "every entry stays"}, summaries retention ${patch.summaryretention !== void 0 ? `${patch.summaryretention} milliseconds` : "every summary stays"}, corrections retention ${patch.correctionretention !== void 0 ? `${patch.correctionretention} milliseconds` : "every correction stays"}, recall window ${patch.recallwindow !== void 0 ? `${patch.recallwindow} milliseconds` : "the whole index"}, summary window ${patch.summarywindow !== void 0 ? `${patch.summarywindow} steps` : "no cap"}, historysearch index ${patch.historyindex !== false ? "on" : "off"} and cancelrun rollback ${patch.cancelrollback ?? "queued"}.`, {});
|
|
21365
|
+
return { ...await sessionviewof(), configured: true };
|
|
21366
|
+
}
|
|
21367
|
+
if (input.bundle !== void 0 && input.bundle.export === true) {
|
|
21368
|
+
const bundle = await memory.exportsessionbundle(now);
|
|
21369
|
+
await audit("export", `The user exported the session audit bundle: ${bundle.notes.length} note${bundle.notes.length === 1 ? "" : "s"}, ${bundle.summaries.length} run summar${bundle.summaries.length === 1 ? "y" : "ies"} and ${bundle.corrections.length} correction${bundle.corrections.length === 1 ? "" : "s"}; sensitive note bodies stay sealed in the export.`, { ...session ? { sessionid: session.id } : {} });
|
|
21370
|
+
return { bundle };
|
|
21371
|
+
}
|
|
21372
|
+
throw new Error("The sessions command carries no note, scratch, summary, recall, correction, consent, grid, search, cancel, retry, error, settings or bundle action.");
|
|
21373
|
+
}
|
|
19879
21374
|
async function handlerequest(message, sender) {
|
|
19880
|
-
|
|
21375
|
+
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
|
+
const inboundgate = origincheckgate({ verdict: originverdict });
|
|
21377
|
+
if (!inboundgate.allowed) {
|
|
21378
|
+
await audit("inbound", `The origincheck dropped an inbound message from ${originverdict.sender}${originverdict.origin !== "" ? ` of ${originverdict.origin}` : ""} without handler execution: ${inboundgate.reason}`, {}).catch(() => {
|
|
21379
|
+
});
|
|
21380
|
+
throw new Error(inboundgate.reason);
|
|
21381
|
+
}
|
|
21382
|
+
if (sender.id === chrome.runtime.id && !extensionpage(sender)) throw new Error("Requests are accepted only from Devthink extension pages.");
|
|
21383
|
+
const schemaerrors = schemavalidation(message);
|
|
21384
|
+
const schemagate = schemaguardgate({ errors: schemaerrors });
|
|
21385
|
+
if (!schemagate.allowed) {
|
|
21386
|
+
await audit("schema", `The schemastrict validation refused an inbound command with ${schemaerrors.length} schema error${schemaerrors.length === 1 ? "" : "s"} at ${schemaerrors.map((error) => error.path).join(", ")}; the refusal echoes no payload.`, {}).catch(() => {
|
|
21387
|
+
});
|
|
21388
|
+
throw new Error(schemagate.reason);
|
|
21389
|
+
}
|
|
19881
21390
|
const input = message;
|
|
19882
21391
|
switch (input.kind) {
|
|
19883
21392
|
case "configure": {
|
|
@@ -19997,7 +21506,7 @@ async function handlerequest(message, sender) {
|
|
|
19997
21506
|
const livetab = session ? await chrome.tabs.get(session.tabid).catch(() => void 0) : void 0;
|
|
19998
21507
|
const waitprofile = session ? waitprofiles.find((record2) => record2.origin === session.origin) : void 0;
|
|
19999
21508
|
const livestate = { phase: livetab?.status === "loading" ? "loading" : "complete", ...navrecords[0] ? { finalurl: navrecords[0].finalurl, redirects: navrecords[0].chain } : {} };
|
|
20000
|
-
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() };
|
|
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 } : {} } };
|
|
20001
21510
|
}
|
|
20002
21511
|
case "capabilities":
|
|
20003
21512
|
return refreshcapabilities();
|
|
@@ -20026,7 +21535,12 @@ async function handlerequest(message, sender) {
|
|
|
20026
21535
|
const rejected = { ...plan, state: "rejected" };
|
|
20027
21536
|
await memory.setplan(rejected);
|
|
20028
21537
|
const current = await memory.getsession();
|
|
21538
|
+
for (const step of plan.steps) {
|
|
21539
|
+
await memory.addcorrection(rejectedcorrectionof({ origin: current?.origin ?? "", kind: step.kind, stepid: step.id, original: JSON.stringify({ kind: step.kind, target: step.target, value: step.value, summary: step.summary }), reason: "The user rejected the reviewed plan during plan review.", now: Date.now() })).catch(() => {
|
|
21540
|
+
});
|
|
21541
|
+
}
|
|
20029
21542
|
await audit("approval", "The user rejected the plan.", { ...current ? { sessionid: current.id } : {}, planid: rejected.id });
|
|
21543
|
+
await audit("correction", `The rejection captured ${plan.steps.length} correction entr${plan.steps.length === 1 ? "y" : "ies"} in the correction memory, one per rejected step with its rejection reason.`, { ...current ? { sessionid: current.id } : {}, planid: rejected.id });
|
|
20030
21544
|
return rejected;
|
|
20031
21545
|
}
|
|
20032
21546
|
case "preview":
|
|
@@ -22383,6 +23897,14 @@ async function handlerequest(message, sender) {
|
|
|
22383
23897
|
await memory.setplan(plan);
|
|
22384
23898
|
await memory.setprogress(resetforplan(await memory.getprogress(), plan, Date.now()));
|
|
22385
23899
|
await memory.setreplans(replans.map((candidate) => candidate.id === replan.id ? { ...candidate, state: "approved" } : candidate));
|
|
23900
|
+
const originaltail = draft.steps.filter((step) => !replan.completedstepids.includes(step.id));
|
|
23901
|
+
for (let index = 0; index < originaltail.length && index < replan.tail.length; index += 1) {
|
|
23902
|
+
const before = originaltail[index];
|
|
23903
|
+
const after = replan.tail[index];
|
|
23904
|
+
if (before === void 0 || after === void 0) continue;
|
|
23905
|
+
await memory.addcorrection(editedcorrectionof({ origin: session?.origin ?? "", kind: after.kind, stepid: after.id, original: JSON.stringify({ kind: before.kind, target: before.target, value: before.value, summary: before.summary }), corrected: JSON.stringify({ kind: after.kind, target: after.target, value: after.value, summary: after.summary }), reason: `The plan review replaced the failed tail step ${before.id} with the revised step ${after.id} of the replan ${replan.id}.`, now: Date.now() })).catch(() => {
|
|
23906
|
+
});
|
|
23907
|
+
}
|
|
22386
23908
|
await audit("model", `The user approved the fresh review of the replan ${replan.id}: ${completed.length} completed step${completed.length === 1 ? "" : "s"} stay and the ${replan.tail.length} revised step${replan.tail.length === 1 ? "" : "s"} became the changed tail of a pending plan that still passes the same plan review.`, { planid: plan.id, ...session ? { sessionid: session.id } : {} });
|
|
22387
23909
|
return llmstateof();
|
|
22388
23910
|
}
|
|
@@ -23048,6 +24570,14 @@ async function handlerequest(message, sender) {
|
|
|
23048
24570
|
}
|
|
23049
24571
|
throw new Error("The swarm merge request carries no merge, report, export, compare, lesson, costs, timeline, replay or snapshot action.");
|
|
23050
24572
|
}
|
|
24573
|
+
case "transparency": {
|
|
24574
|
+
const view = await memory.gettransparencyview();
|
|
24575
|
+
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) });
|
|
24576
|
+
await audit("transparency", `The transparencypage read its transparency report in one memory read: ${report.grants.length} grant row${report.grants.length === 1 ? "" : "s"} with revoke actions, ${report.windows.length} consent window${report.windows.length === 1 ? "" : "s"}, ${report.connectallow.length} connectallow entr${report.connectallow.length === 1 ? "y" : "ies"}, ${report.permdiffs.length} permdiff record${report.permdiffs.length === 1 ? "" : "s"} and ${report.vault.length} vault label${report.vault.length === 1 ? "" : "s"}.`, {});
|
|
24577
|
+
return report;
|
|
24578
|
+
}
|
|
24579
|
+
case "sessions":
|
|
24580
|
+
return handlesessionscommand(message);
|
|
23051
24581
|
case "security": {
|
|
23052
24582
|
const input2 = message;
|
|
23053
24583
|
const now = Date.now();
|
|
@@ -23078,6 +24608,8 @@ async function handlerequest(message, sender) {
|
|
|
23078
24608
|
const existing = profiles.find((candidate) => candidate.origin === origin);
|
|
23079
24609
|
const updated = profilekind({ profile: existing ?? originprofileof({ origin, now }), kind, decision, now });
|
|
23080
24610
|
await memory.saveoriginprofile(updated);
|
|
24611
|
+
if (decision === "deny") await memory.addconsentmemoryentry(consentmemoryof({ origin, decision: "deny", boundary: "the origin profile the user edits", kinds: [kind], now })).catch(() => {
|
|
24612
|
+
});
|
|
23081
24613
|
await audit("grant", `The origin profile of ${origin} now ${decision === "grant" ? "grants" : "denies"} the ${kind} kind the user reviewed; ${updated.grants.length} grant${updated.grants.length === 1 ? "" : "s"} and ${updated.denials.length} denial${updated.denials.length === 1 ? "" : "s"} on the origin.`, { ...session ? { sessionid: session.id } : {} });
|
|
23082
24614
|
return { ...await securityviewof(), profile: updated };
|
|
23083
24615
|
}
|
|
@@ -23092,6 +24624,8 @@ async function handlerequest(message, sender) {
|
|
|
23092
24624
|
const kinds = (input2.consent.open.kinds ?? []).map((kind) => kind.trim()).filter((kind) => kind !== "");
|
|
23093
24625
|
const window2 = openconsentwindow({ sessionid: session.id, origin, duration, kinds: kinds.length > 0 ? kinds : ["observe"], now });
|
|
23094
24626
|
await memory.setconsentwindows([window2, ...(await memory.getconsentwindows()).map((candidate) => candidate.sessionid === session.id && candidate.origin === origin && candidate.state === "active" ? { ...candidate, state: "closed", closedat: now } : candidate)]);
|
|
24627
|
+
await memory.addconsentmemoryentry(consentmemoryof({ origin, decision: "grant", boundary: window2.boundary, kinds: window2.kinds, expiresat: window2.expiresat, now })).catch(() => {
|
|
24628
|
+
});
|
|
23095
24629
|
await appendrunevent("grant", `The consent prompt opened the window ${window2.id} for ${origin} with the boundary ${window2.boundary}.`, session, origin).catch(() => {
|
|
23096
24630
|
});
|
|
23097
24631
|
await audit("grant", `The user answered the consent prompt for ${origin} with the window ${window2.id} and the boundary ${window2.boundary}; no grant ever outlives its named boundary.`, { sessionid: session.id });
|
|
@@ -23108,6 +24642,8 @@ async function handlerequest(message, sender) {
|
|
|
23108
24642
|
if (!durationgate.allowed) throw new Error(durationgate.reason);
|
|
23109
24643
|
const { renewed, closed } = renewconsentwindow({ window: current, duration, kinds: current.kinds, now });
|
|
23110
24644
|
await memory.setconsentwindows([renewed, closed, ...(await memory.getconsentwindows()).filter((candidate) => candidate.id !== windowid)]);
|
|
24645
|
+
await memory.addconsentmemoryentry(consentmemoryof({ origin: current.origin, decision: "grant", boundary: renewed.boundary, kinds: renewed.kinds, expiresat: renewed.expiresat, now })).catch(() => {
|
|
24646
|
+
});
|
|
23111
24647
|
await appendrunevent("grant", `The consent window of ${current.origin} renewed through a new explicit prompt with the boundary ${renewed.boundary}; the old window stays closed in the history.`, session, current.origin).catch(() => {
|
|
23112
24648
|
});
|
|
23113
24649
|
await audit("grant", `The user renewed the consent window of ${current.origin} through a new explicit prompt with the boundary ${renewed.boundary}.`, { sessionid: session.id });
|
|
@@ -23136,6 +24672,8 @@ async function handlerequest(message, sender) {
|
|
|
23136
24672
|
const queued = (plan2?.steps ?? []).map((step) => step.id).filter((id) => !completed.has(id));
|
|
23137
24673
|
const revocation = revokerun({ sessionid: session.id, runid, ...pendingstepid !== void 0 ? { pendingstepid } : {}, ...queued.length > 0 ? { queuedstepids: queued } : {}, actor: "user", ...input2.revoke.reason !== void 0 ? { reason: input2.revoke.reason } : {}, now });
|
|
23138
24674
|
await memory.addrevocation(revocation);
|
|
24675
|
+
await memory.addconsentmemoryentry(consentmemoryof({ origin: session.origin, decision: "revoke", boundary: "the mid run revocation of the user", kinds: ["observe"], now })).catch(() => {
|
|
24676
|
+
});
|
|
23139
24677
|
if (plan2 && plan2.id === runid && ["pending", "approved"].includes(plan2.state)) await memory.setplan({ ...plan2, state: "cancelled" });
|
|
23140
24678
|
if (plan2 && plan2.id === runid && pendingstepid !== void 0) await memory.setprogress(recordrevocation(progress, runid, pendingstepid, { haltedstepids: revocation.haltedstepids, revokedstepid: pendingstepid, reason: revocation.reason }, now));
|
|
23141
24679
|
await appendrunevent("revoke", `The user revoked the run ${runid}: the pending step ${pendingstepid ?? "none"} and every queued step halted without executing (${revocation.haltedstepids.join(", ")}).`, session, session.origin, pendingstepid).catch(() => {
|
|
@@ -23185,10 +24723,103 @@ async function handlerequest(message, sender) {
|
|
|
23185
24723
|
}
|
|
23186
24724
|
if (input2.settings.logretention !== void 0) patch.logretention = input2.settings.logretention;
|
|
23187
24725
|
if (input2.settings.maskshapes !== void 0) patch.maskshapes = input2.settings.maskshapes.map((shape) => shape.trim().toLowerCase()).filter((shape) => shape !== "");
|
|
24726
|
+
if (input2.settings.phishdistance !== void 0) {
|
|
24727
|
+
const thresholdgate = phishthresholdgate(input2.settings.phishdistance);
|
|
24728
|
+
if (!thresholdgate.allowed) throw new Error(thresholdgate.reason);
|
|
24729
|
+
patch.phishdistance = input2.settings.phishdistance;
|
|
24730
|
+
}
|
|
24731
|
+
if (input2.settings.phishfreshness !== void 0) patch.phishfreshness = input2.settings.phishfreshness;
|
|
23188
24732
|
await memory.setsettings(patch);
|
|
23189
24733
|
await audit("configure", `The user updated the security settings: consent duration ${patch.consentduration !== void 0 ? `${patch.consentduration} milliseconds` : "the prompt asks every time"}, log retention ${patch.logretention !== void 0 ? `${patch.logretention} milliseconds` : "every sealed log stays"}, mask shapes ${patch.maskshapes?.length ?? 0} configured.`, {});
|
|
23190
24734
|
return { ...await securityviewof(), configured: true };
|
|
23191
24735
|
}
|
|
24736
|
+
if (input2.gate !== void 0 && input2.gate.resolve !== void 0) {
|
|
24737
|
+
const gateid = input2.gate.resolve.gateid?.trim() ?? "";
|
|
24738
|
+
const decision = input2.gate.resolve.decision === "refused" ? "refused" : "resolved";
|
|
24739
|
+
if (gateid === "") throw new Error("The gate resolution names its single gate.");
|
|
24740
|
+
const resolved = resolvegate({ gates: await memory.getgates(), gateid, decision, actor: "user", now });
|
|
24741
|
+
if (resolved.resolution === void 0 || resolved.gates === void 0) throw new Error(`No open gate ${gateid} exists to resolve; a gate resolution stays a distinct human action on one gate.`);
|
|
24742
|
+
await memory.setgates(resolved.gates);
|
|
24743
|
+
await memory.addgateresolution(resolved.resolution);
|
|
24744
|
+
const gateplan = await memory.getplan();
|
|
24745
|
+
const gate = resolved.gates.find((candidate) => candidate.gateid === gateid);
|
|
24746
|
+
if (gateplan && gate?.resolvedat !== void 0) await memory.setprogress(recordgatewait(await memory.getprogress(), gateplan.id, gate.stepid, { gateid: gate.gateid, kind: gate.kind, openedat: gate.openedat, resolvedat: gate.resolvedat, waitedms: Math.max(0, gate.resolvedat - gate.openedat) }, now)).catch(() => {
|
|
24747
|
+
});
|
|
24748
|
+
if (session) await appendrunevent("gate", `The user ${decision === "resolved" ? "resolved" : "refused"} the ${resolved.resolution.kind} gate ${gateid} of the step ${resolved.resolution.stepid} through one distinct human action; no timeout resolved it and no batch approved it.`, session, gate?.origin ?? session.origin, resolved.resolution.stepid).catch(() => {
|
|
24749
|
+
});
|
|
24750
|
+
await audit("gate", `The user ${decision === "resolved" ? "resolved" : "refused"} the ${resolved.resolution.kind} gate ${gateid} of the step ${resolved.resolution.stepid} through one distinct human action; no timeout resolved it and no batch approved it.`, { ...session ? { sessionid: session.id } : {}, ...gateplan ? { planid: gateplan.id } : {}, stepid: resolved.resolution.stepid });
|
|
24751
|
+
return { ...await securityviewof(), gate };
|
|
24752
|
+
}
|
|
24753
|
+
if (input2.vault !== void 0) {
|
|
24754
|
+
if (input2.vault.add !== void 0) {
|
|
24755
|
+
const label = input2.vault.add.label?.trim() ?? "";
|
|
24756
|
+
const scope = input2.vault.add.scope?.trim() !== "" && input2.vault.add.scope !== void 0 ? input2.vault.add.scope.trim() : session?.origin ?? "";
|
|
24757
|
+
const value = input2.vault.add.value ?? "";
|
|
24758
|
+
if (label === "" || scope === "" || value === "") throw new Error("The vault entry needs its label, its exact origin scope and its value; the value stays behind the vault seam.");
|
|
24759
|
+
const entry = await vaultstore({ seam: vaultseamstore, label, scope, profileid: runstateprofile, provenance: input2.vault.add.provenance === "session" ? "session" : "user", value, now });
|
|
24760
|
+
await memory.addsecret(entry);
|
|
24761
|
+
await audit("vault", `The user stored the secret ${entry.label} for ${entry.scope} behind the vault seam; the metadata keeps the label, the scope, the provenance and the digest while no plaintext value persists anywhere.`, { ...session ? { sessionid: session.id } : {} });
|
|
24762
|
+
return { ...await securityviewof(), secret: { vaultid: entry.vaultid, label: entry.label, scope: entry.scope } };
|
|
24763
|
+
}
|
|
24764
|
+
if (input2.vault.delete !== void 0) {
|
|
24765
|
+
const vaultid = input2.vault.delete.vaultid?.trim() ?? "";
|
|
24766
|
+
const entry = (await memory.getsecretvault()).find((candidate) => candidate.vaultid === vaultid);
|
|
24767
|
+
if (!entry) throw new Error(`No vault entry ${vaultid} exists.`);
|
|
24768
|
+
const dropped = await vaultdelete({ seam: vaultseamstore, entry });
|
|
24769
|
+
await memory.removesecret(vaultid);
|
|
24770
|
+
await audit("vault", `The user deleted the secret ${dropped.label} of ${entry.scope}: ${dropped.reason}`, { ...session ? { sessionid: session.id } : {} });
|
|
24771
|
+
return { ...await securityviewof(), removedsecret: vaultid };
|
|
24772
|
+
}
|
|
24773
|
+
}
|
|
24774
|
+
if (input2.connectallow !== void 0) {
|
|
24775
|
+
if (input2.connectallow.add !== void 0) {
|
|
24776
|
+
const entry = connectallowentryof({ senderid: input2.connectallow.add.senderid?.trim() ?? "", displayname: input2.connectallow.add.displayname?.trim() ?? "", ...input2.connectallow.add.origin !== void 0 && input2.connectallow.add.origin.trim() !== "" ? { origin: input2.connectallow.add.origin.trim() } : {}, now });
|
|
24777
|
+
await memory.addconnectallow(entry);
|
|
24778
|
+
await audit("inbound", `The user allowed the external sender ${entry.displayname} (${entry.senderid})${entry.origin !== void 0 ? ` of ${entry.origin}` : ""}; the connectallow list ships empty by default and holds user managed entries only.`, { ...session ? { sessionid: session.id } : {} });
|
|
24779
|
+
return { ...await securityviewof(), allowedsender: entry };
|
|
24780
|
+
}
|
|
24781
|
+
if (input2.connectallow.remove !== void 0) {
|
|
24782
|
+
const senderid = input2.connectallow.remove.senderid?.trim() ?? "";
|
|
24783
|
+
await memory.removeconnectallow(senderid);
|
|
24784
|
+
await audit("inbound", `The user removed the external sender ${senderid} from the connectallow list; the origincheck drops its messages and ports again.`, { ...session ? { sessionid: session.id } : {} });
|
|
24785
|
+
return { ...await securityviewof(), removedsender: senderid };
|
|
24786
|
+
}
|
|
24787
|
+
}
|
|
24788
|
+
if (input2.ratelimit !== void 0) {
|
|
24789
|
+
if (input2.ratelimit.set !== void 0) {
|
|
24790
|
+
const origin = input2.ratelimit.set.origin?.trim() ?? "";
|
|
24791
|
+
const limit = input2.ratelimit.set.limit ?? 0;
|
|
24792
|
+
const window2 = input2.ratelimit.set.window ?? 0;
|
|
24793
|
+
if (origin === "") throw new Error("The ratelimit bucket needs its exact origin.");
|
|
24794
|
+
const bounds = ratelimitboundsvalid(limit, window2);
|
|
24795
|
+
if (!bounds.allowed) throw new Error(bounds.reason);
|
|
24796
|
+
const bucket = bucketof({ origin, sessionid: session?.id ?? "global", limit, window: window2, now });
|
|
24797
|
+
await memory.saveratelimitbucket(bucket);
|
|
24798
|
+
await audit("rate", `The user configured the ratelimit bucket of ${origin} at ${limit} command${limit === 1 ? "" : "s"} per ${window2} milliseconds; the bounds stay user choices with no hidden ceiling.`, { ...session ? { sessionid: session.id } : {} });
|
|
24799
|
+
return { ...await securityviewof(), bucket };
|
|
24800
|
+
}
|
|
24801
|
+
if (input2.ratelimit.remove !== void 0) {
|
|
24802
|
+
const origin = input2.ratelimit.remove.origin?.trim() ?? "";
|
|
24803
|
+
const buckets = await memory.getratelimitbuckets();
|
|
24804
|
+
for (const bucket of buckets.filter((candidate) => candidate.origin === origin)) await memory.removeratelimitbucket(bucket.origin, bucket.sessionid);
|
|
24805
|
+
await audit("rate", `The user removed the ratelimit bucket of ${origin}; the origin runs without a bucket because the bounds stay user choices only.`, { ...session ? { sessionid: session.id } : {} });
|
|
24806
|
+
return { ...await securityviewof(), removedbucket: origin };
|
|
24807
|
+
}
|
|
24808
|
+
}
|
|
24809
|
+
if (input2.redact !== void 0) {
|
|
24810
|
+
if (input2.redact.add !== void 0) {
|
|
24811
|
+
const region = regionof({ origin: input2.redact.add.origin?.trim() !== "" && input2.redact.add.origin !== void 0 ? input2.redact.add.origin.trim() : session?.origin ?? "", template: input2.redact.add.template?.trim() !== "" && input2.redact.add.template !== void 0 ? input2.redact.add.template.trim() : "page", x: input2.redact.add.x ?? 0, y: input2.redact.add.y ?? 0, width: input2.redact.add.width ?? 0, height: input2.redact.add.height ?? 0, reason: input2.redact.add.reason?.trim() !== "" && input2.redact.add.reason !== void 0 ? input2.redact.add.reason.trim() : "The user drew the mask on the capture surface.", source: "userdrawn", now });
|
|
24812
|
+
await memory.addredactregion(region);
|
|
24813
|
+
await audit("capture", `The user drew the redact region ${region.id} at ${region.x},${region.y} of ${region.width}x${region.height} on ${region.origin}/${region.template}: ${region.reason}`, { ...session ? { sessionid: session.id } : {} });
|
|
24814
|
+
return { ...await securityviewof(), region };
|
|
24815
|
+
}
|
|
24816
|
+
if (input2.redact.remove !== void 0) {
|
|
24817
|
+
const id = input2.redact.remove.id?.trim() ?? "";
|
|
24818
|
+
await memory.removeredactregion(id);
|
|
24819
|
+
await audit("capture", `The user removed the redact region ${id}.`, { ...session ? { sessionid: session.id } : {} });
|
|
24820
|
+
return { ...await securityviewof(), removedregion: id };
|
|
24821
|
+
}
|
|
24822
|
+
}
|
|
23192
24823
|
const plan = await memory.getplan();
|
|
23193
24824
|
const pending = [];
|
|
23194
24825
|
if (session && plan && ["pending", "approved"].includes(plan.state)) {
|
|
@@ -23646,7 +25277,7 @@ async function raiseremoteapproval(clientid, toolname, params, step) {
|
|
|
23646
25277
|
return { content: `The approval gate ${request.id} holds the ${toolname} call; it executes once the user approves it in the panel.`, payload: { approvalid: request.id, state: "pending", ...request.timeoutat !== void 0 ? { timeoutat: request.timeoutat } : {} }, iserror: false };
|
|
23647
25278
|
}
|
|
23648
25279
|
async function executelistruns(step, session) {
|
|
23649
|
-
const options =
|
|
25280
|
+
const options = stepoptions6(step);
|
|
23650
25281
|
const statefilter = typeof options.state === "string" && options.state.trim() !== "" ? options.state : void 0;
|
|
23651
25282
|
const runs = await memory.listworkflowruns();
|
|
23652
25283
|
const selected = statefilter !== void 0 ? runs.filter((run) => run.state === statefilter) : runs;
|
|
@@ -24021,7 +25652,7 @@ async function maybeautosnapshot() {
|
|
|
24021
25652
|
await audit("session", `The reviewed auto snapshot interval stopped after ${state.interval.maxsnapshots} snapshot${state.interval.maxsnapshots === 1 ? "" : "s"}; the retention window of ${state.interval.expiry} millisecond${state.interval.expiry === 1 ? "" : "s"} expires them by user choice.`, { sessionid: session.id, planid: plan.id });
|
|
24022
25653
|
return;
|
|
24023
25654
|
}
|
|
24024
|
-
const options =
|
|
25655
|
+
const options = stepoptions6(step);
|
|
24025
25656
|
const snapshot2 = snapshotplanof(options.snapshot);
|
|
24026
25657
|
if (!snapshot2) return;
|
|
24027
25658
|
const record2 = await capturesessionrecord({ ...snapshot2, ...snapshot2.auto !== void 0 ? { auto: snapshot2.auto } : {} }, session, plan.id).catch(() => void 0);
|
|
@@ -24066,10 +25697,22 @@ async function restoreemulationstate() {
|
|
|
24066
25697
|
restoreemulationstate().catch(() => {
|
|
24067
25698
|
});
|
|
24068
25699
|
chrome.runtime.onConnect.addListener((port) => {
|
|
24069
|
-
|
|
24070
|
-
|
|
24071
|
-
|
|
24072
|
-
|
|
25700
|
+
void (async () => {
|
|
25701
|
+
const handshake = portaccept({ portname: port.name, ...port.sender?.id !== void 0 ? { senderid: port.sender.id } : {}, ...port.sender?.origin !== void 0 ? { senderorigin: port.sender.origin } : {}, extensionid: chrome.runtime.id, connectallow: await memory.getconnectallow() });
|
|
25702
|
+
if (!handshake.accepted) {
|
|
25703
|
+
await audit("inbound", `The port ${port.name} closed at its handshake: ${handshake.reason}`, {}).catch(() => {
|
|
25704
|
+
});
|
|
25705
|
+
port.disconnect();
|
|
25706
|
+
return;
|
|
25707
|
+
}
|
|
25708
|
+
if (port.name !== "devthinksidepanel" || port.sender?.id !== chrome.runtime.id || !port.sender.url?.startsWith(chrome.runtime.getURL(""))) {
|
|
25709
|
+
port.disconnect();
|
|
25710
|
+
return;
|
|
25711
|
+
}
|
|
25712
|
+
port.onMessage.addListener((message) => {
|
|
25713
|
+
handlerequest(message, port.sender ?? {}).then((value) => port.postMessage({ ok: true, value })).catch((error) => port.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) }));
|
|
25714
|
+
});
|
|
25715
|
+
})();
|
|
24073
25716
|
});
|
|
24074
25717
|
{
|
|
24075
25718
|
const webnavigation = chrome.webNavigation;
|
|
@@ -24155,4 +25798,16 @@ restoretriggers().catch(() => {
|
|
|
24155
25798
|
});
|
|
24156
25799
|
restorerunstates().catch(() => {
|
|
24157
25800
|
});
|
|
25801
|
+
async function recordinstalledpermdiff() {
|
|
25802
|
+
const manifest = chrome.runtime.getManifest();
|
|
25803
|
+
const permissions = [...(manifest.permissions ?? []).map((permission) => `required:${permission}`), ...(manifest.optional_permissions ?? []).map((permission) => `optional:${permission}`), ...(manifest.optional_host_permissions ?? []).map((host) => `optionalhost:${host}`)];
|
|
25804
|
+
const last = await memory.getlastpermissions();
|
|
25805
|
+
if (last !== void 0 && last.version === manifest.version) return;
|
|
25806
|
+
const diff = permissiondiff({ from: last?.permissions ?? [], to: permissions, fromversion: last?.version ?? "none", toversion: manifest.version, now: Date.now() });
|
|
25807
|
+
await memory.addpermdiff(diff);
|
|
25808
|
+
await memory.setlastpermissions(permissions, manifest.version);
|
|
25809
|
+
await audit("transparency", `The installed update to ${manifest.version} recorded its permdiff: ${permdiffsummary(diff)}`, {});
|
|
25810
|
+
}
|
|
25811
|
+
recordinstalledpermdiff().catch(() => {
|
|
25812
|
+
});
|
|
24158
25813
|
//# sourceMappingURL=background.js.map
|