@webskill/sdk 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +3 -3
- package/dist/agent.js +3 -3
- package/dist/browser.d.ts +29 -6
- package/dist/browser.js +629 -75
- package/dist/{catalogComponents-BFoqpT1v-CjUBZ3bc.js → catalogComponents-BgAJN0p8-CYEXSk45.js} +606 -926
- package/dist/{dist-DTHZS2k1.js → dist-DqcL6jKO.js} +155 -39
- package/dist/{dist-B-cOu08W.js → dist-ExSQky4C.js} +754 -69
- package/dist/{dist-qnlI2Iup.js → dist-GK6dtjRv.js} +222 -9
- package/dist/{echarts-DhNm2ene.js → echarts-De78wXqV.js} +599 -61
- package/dist/governance.d.ts +3 -3
- package/dist/{index-DACk2_XZ.d.ts → index-C3XdItd_.d.ts} +92 -8
- package/dist/{index-D3mONFHD.d.ts → index-DkvBhJQy.d.ts} +187 -6
- package/dist/{index-DWbs58LF.d.ts → index-iBm9tJL_.d.ts} +122 -23
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/mcp.d.ts +47 -3
- package/dist/mcp.js +79 -2
- package/dist/node.d.ts +3 -3
- package/dist/node.js +9 -3
- package/dist/{openUiLibrary-D5u8oIvx-BLOAQCho.js → openUiLibrary-BKXW7Iwx-CWWBVOkE.js} +3 -3
- package/dist/processSandboxEntry.js +2 -1
- package/dist/sandboxWorkerEntry.js +2 -1
- package/dist/{skillVersionStore-D-qHk9ZE-BcmFLykd.d.ts → skillVersionStore-D-qHk9ZE-DheTIwAB.d.ts} +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{types-C26b05fW-CdrRCRDb.d.ts → types-DLctJep_-B5G4uk2u.d.ts} +3 -2
- package/dist/ui-react.d.ts +13 -4
- package/dist/ui-react.js +77 -259
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui-vue.js +1 -1
- package/dist/ui.d.ts +4 -4
- package/dist/ui.js +3 -3
- package/dist/{webskillLitCatalog-DME6PBkV-CmYNLlIT.js → webskillLitCatalog-D_zCqeQF-C9lrvvMr.js} +2 -2
- package/package.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { M as messageOf, P as parseSkillMarkdown, g as assertRemoteUrlAllowed, h as WebSkillError, k as isValidSkillName } from "./dist-Bev6i6Ip.js";
|
|
2
|
-
import { f as DEFAULT_MAX_DATA_SOURCE_BYTES } from "./dist-
|
|
2
|
+
import { f as DEFAULT_MAX_DATA_SOURCE_BYTES } from "./dist-ExSQky4C.js";
|
|
3
3
|
|
|
4
4
|
//#region ../agent/dist/index.js
|
|
5
5
|
const STATUSES = [
|
|
@@ -108,7 +108,7 @@ const TODO_SYSTEM_PROMPT = [
|
|
|
108
108
|
"2. `update` an item to `in-progress` right before you start it, and to `completed` right after it succeeds.",
|
|
109
109
|
"3. Only one item may be `in-progress`; the runtime demotes the others automatically, so never rely on marking several.",
|
|
110
110
|
"4. Never mark an item `completed` before its work actually succeeded. If a step fails, keep it `in-progress` and explain.",
|
|
111
|
-
"5. `clear` the list once the whole request is answered, or when the user abandons it.",
|
|
111
|
+
"5. Settle every remaining item first (rule 4 still applies), then `clear` the list once the whole request is answered, or when the user abandons it.",
|
|
112
112
|
"",
|
|
113
113
|
"Skip the list for single-step requests, plain questions and trivial lookups — it only adds noise there."
|
|
114
114
|
].join("\n");
|
|
@@ -259,6 +259,7 @@ function createTodoToolSource(options = {}) {
|
|
|
259
259
|
inputSchema: INPUT_SCHEMA$4
|
|
260
260
|
}]),
|
|
261
261
|
canHandle: (name) => name === MANAGE_TODO_TOOL,
|
|
262
|
+
argCaptureTrust: (name) => name === "manage_todo" ? { tier: "reviewed" } : void 0,
|
|
262
263
|
call
|
|
263
264
|
};
|
|
264
265
|
}
|
|
@@ -313,6 +314,69 @@ function previewOf(draft) {
|
|
|
313
314
|
return sections.join("\n\n");
|
|
314
315
|
}
|
|
315
316
|
/**
|
|
317
|
+
* 工具名硬校(FR-30.4 / AC-30.8)。
|
|
318
|
+
*
|
|
319
|
+
* 只做**集合包含**:不比次数、不比顺序(AC-30.9),也不比参数(AC-30.10)。
|
|
320
|
+
* 模型把参数泛化成占位符是正常的技能写法,机械比对会把正确的技能判失败。
|
|
321
|
+
* 代价见需求 §7:工具名对、参数编得不对的情形本层拦不住,由确认卡兜底。
|
|
322
|
+
*/
|
|
323
|
+
function assertStepsAreBackedByTrace(draft, records) {
|
|
324
|
+
const claimed = draft.steps ?? [];
|
|
325
|
+
if (claimed.length === 0) return;
|
|
326
|
+
const executed = new Set(records.map((r) => r.tool));
|
|
327
|
+
const unknown = [...new Set(claimed.map((s) => s.tool).filter((tool) => !executed.has(tool)))];
|
|
328
|
+
if (unknown.length === 0) return;
|
|
329
|
+
fail(`The skill claims tools that were never called in this session: ${unknown.join(", ")}. Tools actually called: ${executed.size === 0 ? "(none)" : [...executed].sort().join(", ")}. Rewrite the skill using only the tools above.`, {
|
|
330
|
+
claimed: unknown,
|
|
331
|
+
executed: [...executed].sort()
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 超限步骤拒收(FR-30.2 / AC-30.3)。
|
|
336
|
+
*
|
|
337
|
+
* 留存超过体积上限时 `args` 是空的,只剩一个工具名。放它过去等于产出一个
|
|
338
|
+
* 「知道调了什么、不知道传了什么」的步骤——那比没有这一步更糟,因为它看起来是完整的。
|
|
339
|
+
* 同名工具只要还有一条没超限的记录就不算超限:那条记录足以说明参数长什么样。
|
|
340
|
+
*/
|
|
341
|
+
function assertStepsAreNotTruncated(draft, records) {
|
|
342
|
+
const claimed = draft.steps ?? [];
|
|
343
|
+
if (claimed.length === 0) return;
|
|
344
|
+
const usable = new Set(records.filter((r) => r.truncated !== true).map((r) => r.tool));
|
|
345
|
+
const truncated = [...new Set(claimed.map((s) => s.tool).filter((tool) => !usable.has(tool)))];
|
|
346
|
+
if (truncated.length === 0) return;
|
|
347
|
+
fail(`The arguments of these tool calls were too large to record, so the skill cannot state them: ${truncated.join(", ")}. Rewrite the skill without these steps.`, { truncated });
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* 确认卡证据(AC-30.12 / AC-30.13):逐条列出模型**写进技能的**步骤,
|
|
351
|
+
* 并标注它是否有轨迹背书。轨迹里有而模型没写的步骤不出现在这里,
|
|
352
|
+
* 也不会被补进 `SKILL.md`——生成的是模型的技能,不是会话的录像(AC-30.11)。
|
|
353
|
+
*
|
|
354
|
+
* 校验通过后每一步都有背书,所以 `'model'` 只会出现在**轨迹读不到**时:
|
|
355
|
+
* 那种情况下不能把存储故障当成「模型在撞骗」而拦截,但必须在卡上说清楚
|
|
356
|
+
* 这些步骤一步都没背书,否则用户会把未校验的草稿当成已核实的。
|
|
357
|
+
*/
|
|
358
|
+
function buildTraceEvidence(draft, records) {
|
|
359
|
+
const claimed = draft.steps ?? [];
|
|
360
|
+
if (claimed.length === 0) return void 0;
|
|
361
|
+
const byTool = /* @__PURE__ */ new Map();
|
|
362
|
+
for (const record of records ?? []) {
|
|
363
|
+
if (record.truncated === true || byTool.has(record.tool)) continue;
|
|
364
|
+
byTool.set(record.tool, record);
|
|
365
|
+
}
|
|
366
|
+
return { steps: claimed.map((step) => {
|
|
367
|
+
const record = byTool.get(step.tool);
|
|
368
|
+
return {
|
|
369
|
+
tool: step.tool,
|
|
370
|
+
evidence: record === void 0 ? "model" : "trace",
|
|
371
|
+
...record !== void 0 ? {
|
|
372
|
+
traceArgs: record.args,
|
|
373
|
+
redacted: record.redacted
|
|
374
|
+
} : {},
|
|
375
|
+
...step.args !== void 0 ? { draftArgs: step.args } : {}
|
|
376
|
+
};
|
|
377
|
+
}) };
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
316
380
|
* 技能自动生成策略。生成动作是策略而不是内核:它不进入 `AgentLoop`,
|
|
317
381
|
* 而是经既有的 `ExternalToolSource` 扩展点接入(设计 02 §0)。
|
|
318
382
|
*
|
|
@@ -337,18 +401,27 @@ var SkillGenerator = class {
|
|
|
337
401
|
if (!sink) throw new WebSkillError("SKILL_GENERATION_DISABLED", "Skill generation is enabled but this host did not provide a candidate store");
|
|
338
402
|
if (this.#used >= this.#maxPerSession) throw new WebSkillError("SKILL_GENERATION_LIMIT_EXCEEDED", `This session already generated ${this.#maxPerSession} skills, which is the configured limit`);
|
|
339
403
|
validateDraft(draft);
|
|
404
|
+
const sessionId = this.#options.sessionId?.();
|
|
405
|
+
const trace = await this.#readSteps(sessionId);
|
|
406
|
+
if (trace.available && trace.records !== void 0) {
|
|
407
|
+
assertStepsAreBackedByTrace(draft, trace.records);
|
|
408
|
+
assertStepsAreNotTruncated(draft, trace.records);
|
|
409
|
+
}
|
|
340
410
|
this.#used += 1;
|
|
411
|
+
const evidence = trace.available ? buildTraceEvidence(draft, trace.records) : void 0;
|
|
341
412
|
this.#requestSeq += 1;
|
|
342
413
|
const response = await this.#options.ui.request({
|
|
343
414
|
type: "authorize",
|
|
344
415
|
id: `skill-generation-${this.#requestSeq}`,
|
|
345
416
|
capability: "confirm",
|
|
346
417
|
message: this.#options.messages?.confirmSkill?.(draft) ?? defaultConfirmSkill(draft),
|
|
347
|
-
details: {
|
|
418
|
+
details: {
|
|
419
|
+
preview: previewOf(draft),
|
|
420
|
+
...evidence !== void 0 ? { traceEvidence: evidence } : {}
|
|
421
|
+
}
|
|
348
422
|
});
|
|
349
423
|
if (response.cancelled === true || response.value === false) return { status: "declined" };
|
|
350
424
|
const confirmedAt = (this.#options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
351
|
-
const sessionId = this.#options.sessionId?.();
|
|
352
425
|
const { id } = await sink.submit({
|
|
353
426
|
draft,
|
|
354
427
|
confirmedAt,
|
|
@@ -360,6 +433,24 @@ var SkillGenerator = class {
|
|
|
360
433
|
name: draft.name
|
|
361
434
|
};
|
|
362
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* 读不到轨迹(存储故障 / 没有会话号)时 `records` 为 `undefined`,含义是**不校验**,
|
|
438
|
+
* 而不是空数组(= 全部判失败):存储故障不该表现成「模型在撒谎」。
|
|
439
|
+
* 真正跑了零个工具的会话由 `[]` 表达,那种情况该拦就拦。
|
|
440
|
+
*/
|
|
441
|
+
async #readSteps(sessionId) {
|
|
442
|
+
const reader = this.#options.steps;
|
|
443
|
+
if (reader === void 0) return { available: false };
|
|
444
|
+
if (sessionId === void 0) return { available: true };
|
|
445
|
+
try {
|
|
446
|
+
return {
|
|
447
|
+
available: true,
|
|
448
|
+
records: await reader.listBySession(sessionId)
|
|
449
|
+
};
|
|
450
|
+
} catch {
|
|
451
|
+
return { available: true };
|
|
452
|
+
}
|
|
453
|
+
}
|
|
363
454
|
};
|
|
364
455
|
/**
|
|
365
456
|
* 技能自动生成的系统提示词。默认不注册工具,因此这段提示词只在
|
|
@@ -419,6 +510,25 @@ const INPUT_SCHEMA$3 = {
|
|
|
419
510
|
required: ["path", "content"],
|
|
420
511
|
additionalProperties: false
|
|
421
512
|
}
|
|
513
|
+
},
|
|
514
|
+
steps: {
|
|
515
|
+
type: "array",
|
|
516
|
+
description: "The tool calls this skill performs, in the order the SKILL.md describes them",
|
|
517
|
+
items: {
|
|
518
|
+
type: "object",
|
|
519
|
+
properties: {
|
|
520
|
+
tool: {
|
|
521
|
+
type: "string",
|
|
522
|
+
description: "The exact tool name, as it appeared in this conversation"
|
|
523
|
+
},
|
|
524
|
+
args: {
|
|
525
|
+
type: "object",
|
|
526
|
+
description: "The arguments this step passes to the tool"
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
required: ["tool"],
|
|
530
|
+
additionalProperties: false
|
|
531
|
+
}
|
|
422
532
|
}
|
|
423
533
|
},
|
|
424
534
|
required: [
|
|
@@ -441,11 +551,14 @@ function toolError$3(code, message) {
|
|
|
441
551
|
function readDraft(args) {
|
|
442
552
|
const { name, description, content } = args;
|
|
443
553
|
if (typeof name !== "string" || typeof description !== "string" || typeof content !== "string") return "The \"name\", \"description\" and \"content\" arguments are required and must be strings";
|
|
554
|
+
const steps = readSteps(args["steps"]);
|
|
555
|
+
if (typeof steps === "string") return steps;
|
|
444
556
|
const rawFiles = args["files"];
|
|
445
557
|
if (rawFiles === void 0) return {
|
|
446
558
|
name,
|
|
447
559
|
description,
|
|
448
|
-
content
|
|
560
|
+
content,
|
|
561
|
+
...steps
|
|
449
562
|
};
|
|
450
563
|
if (!Array.isArray(rawFiles)) return "The \"files\" argument must be an array";
|
|
451
564
|
const files = [];
|
|
@@ -462,9 +575,28 @@ function readDraft(args) {
|
|
|
462
575
|
name,
|
|
463
576
|
description,
|
|
464
577
|
content,
|
|
465
|
-
files
|
|
578
|
+
files,
|
|
579
|
+
...steps
|
|
466
580
|
};
|
|
467
581
|
}
|
|
582
|
+
function readSteps(raw) {
|
|
583
|
+
if (raw === void 0) return {};
|
|
584
|
+
if (!Array.isArray(raw)) return "The \"steps\" argument must be an array";
|
|
585
|
+
const steps = [];
|
|
586
|
+
for (const entry of raw) {
|
|
587
|
+
if (typeof entry !== "object" || entry === null) return "Every entry in \"steps\" must be an object";
|
|
588
|
+
const record = entry;
|
|
589
|
+
const tool = record["tool"];
|
|
590
|
+
if (typeof tool !== "string" || tool.trim() === "") return "Every step needs a non-empty \"tool\" name";
|
|
591
|
+
const stepArgs = record["args"];
|
|
592
|
+
if (stepArgs !== void 0 && (typeof stepArgs !== "object" || stepArgs === null || Array.isArray(stepArgs))) return "A step's \"args\" must be an object";
|
|
593
|
+
steps.push({
|
|
594
|
+
tool,
|
|
595
|
+
...stepArgs !== void 0 ? { args: stepArgs } : {}
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
return { steps };
|
|
599
|
+
}
|
|
468
600
|
/**
|
|
469
601
|
* 把技能自动生成接到既有的工具协议上(设计 02 §1.3)。
|
|
470
602
|
*
|
|
@@ -511,6 +643,7 @@ function createSkillGenerationToolSource(options) {
|
|
|
511
643
|
inputSchema: INPUT_SCHEMA$3
|
|
512
644
|
}]),
|
|
513
645
|
canHandle: (name) => name === GENERATE_SKILL_TOOL,
|
|
646
|
+
argCaptureTrust: (name) => name === "generate_skill" ? { tier: "reviewed" } : void 0,
|
|
514
647
|
call
|
|
515
648
|
};
|
|
516
649
|
}
|
|
@@ -713,6 +846,7 @@ function createDelegationToolSource(options) {
|
|
|
713
846
|
inputSchema: INPUT_SCHEMA$2
|
|
714
847
|
}]),
|
|
715
848
|
canHandle: (name) => name === DELEGATE_TASK_TOOL,
|
|
849
|
+
argCaptureTrust: (name) => name === "delegate_task" ? { tier: "reviewed" } : void 0,
|
|
716
850
|
call
|
|
717
851
|
};
|
|
718
852
|
}
|
|
@@ -741,6 +875,30 @@ function withDelegationOrigin(bridge, origin) {
|
|
|
741
875
|
};
|
|
742
876
|
}
|
|
743
877
|
/**
|
|
878
|
+
* 帧指称的展示形式(分册 18 FR-18.2)。
|
|
879
|
+
*
|
|
880
|
+
* 感知与操作两侧各自声明自己的 scope 类型(那是刻意的,见各自 types.ts),
|
|
881
|
+
* 但「一条帧路径写成给人看的字符串」只能有一份实现——
|
|
882
|
+
* 两处各写一遍,审计里的帧名和确认卡里的帧名就会慢慢对不上。
|
|
883
|
+
*/
|
|
884
|
+
/**
|
|
885
|
+
* 帧路径的稳定展示串:`'self'` / `'#a'` / `'#a >>> #b'`。
|
|
886
|
+
*
|
|
887
|
+
* `>>>` **只是展示分隔符**:CSS 选择器里可以合法出现任意字符,
|
|
888
|
+
* 反向解析这个串取回路径是不成立的,实现层一律传原始形状(D-18-1)。
|
|
889
|
+
* @experimental
|
|
890
|
+
*/
|
|
891
|
+
function frameLabel(frame) {
|
|
892
|
+
if (typeof frame === "string") return frame;
|
|
893
|
+
if (frame.length === 0) return "self";
|
|
894
|
+
return frame.join(" >>> ");
|
|
895
|
+
}
|
|
896
|
+
/** 把两种形状归一成逐层选择器数组;`'self'` 与空数组都归一成空数组 @experimental */
|
|
897
|
+
function frameSteps(frame) {
|
|
898
|
+
if (typeof frame === "string") return frame === "self" ? [] : [frame];
|
|
899
|
+
return frame;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
744
902
|
* 两种形状归一成帧列表;旧形状等价于一条 `frame:'self'`(FR-24.1)。
|
|
745
903
|
*
|
|
746
904
|
* **这是判别的单一来源。** 散在各处写 `'frames' in scope` 会让
|
|
@@ -803,7 +961,7 @@ var PagePerceptionPolicy = class {
|
|
|
803
961
|
at: this.#options.now?.() ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
804
962
|
include: frames.flatMap((frame) => [...frame.include]),
|
|
805
963
|
exclude: frames.flatMap((frame) => [...frame.exclude ?? []]),
|
|
806
|
-
...frames.length > 1 || frames[0]
|
|
964
|
+
...frames.length > 1 || frames[0] !== void 0 && frameLabel(frames[0].frame) !== "self" ? { frames: frames.map((frame) => frameLabel(frame.frame)) } : {},
|
|
807
965
|
nodeCount: nodes.length,
|
|
808
966
|
...capture?.images === true ? {
|
|
809
967
|
images: {
|
|
@@ -894,13 +1052,15 @@ function createPagePerceptionToolSource(options) {
|
|
|
894
1052
|
}] : []),
|
|
895
1053
|
systemPrompt: () => Promise.resolve(policy.enabled ? PERCEPTION_SYSTEM_PROMPT : void 0),
|
|
896
1054
|
canHandle: (name) => name === PERCEIVE_PAGE_TOOL,
|
|
1055
|
+
argCaptureTrust: (name) => name === "perceive_page" ? { tier: "reviewed" } : void 0,
|
|
897
1056
|
call: async () => {
|
|
898
1057
|
try {
|
|
899
1058
|
const budget = await options.imageCapture?.();
|
|
900
1059
|
const capture = {
|
|
901
1060
|
images: budget?.enabled === true,
|
|
902
1061
|
maxImageBytes: budget?.maxImageBytes ?? 0,
|
|
903
|
-
maxImages: budget?.maxImages ?? 0
|
|
1062
|
+
maxImages: budget?.maxImages ?? 0,
|
|
1063
|
+
minImageArea: budget?.minImageArea ?? 0
|
|
904
1064
|
};
|
|
905
1065
|
const { nodes, images, imagesOmitted, record } = await policy.perceive(capture);
|
|
906
1066
|
const data = {
|
|
@@ -1082,6 +1242,8 @@ const PAGE_ACTION_KINDS = [
|
|
|
1082
1242
|
"attach"
|
|
1083
1243
|
];
|
|
1084
1244
|
const declineReason = "Page action was declined by the user.";
|
|
1245
|
+
/** 目标记忆的上限;它在 `act()` 之后立刻就被读走,容量只为防无界增长 */
|
|
1246
|
+
const TARGET_MEMO_LIMIT = 200;
|
|
1085
1247
|
/**
|
|
1086
1248
|
* 页面操作策略(需求 23)。
|
|
1087
1249
|
*
|
|
@@ -1093,6 +1255,7 @@ var PageActionPolicy = class {
|
|
|
1093
1255
|
#options;
|
|
1094
1256
|
#records = [];
|
|
1095
1257
|
#seq = 0;
|
|
1258
|
+
#targetByRef = /* @__PURE__ */ new Map();
|
|
1096
1259
|
constructor(options) {
|
|
1097
1260
|
this.#options = options;
|
|
1098
1261
|
}
|
|
@@ -1107,6 +1270,35 @@ var PageActionPolicy = class {
|
|
|
1107
1270
|
get records() {
|
|
1108
1271
|
return this.#records;
|
|
1109
1272
|
}
|
|
1273
|
+
/**
|
|
1274
|
+
* 目标是不是密码类控件(分册 30)。与确认卡上把值打成掩码用的是**同一个判定**,
|
|
1275
|
+
* 不另立一套敏感字段清单。
|
|
1276
|
+
*
|
|
1277
|
+
* 读的是 `act()` 当时记下的结论而不是事后重查:提交或重绘后句柄会失效,
|
|
1278
|
+
* 重查就会把一次普通填写误判成敏感、把内容丢掉。没操作过的句柄才现查,
|
|
1279
|
+
* 查不到按敏感:不知道就别留存。
|
|
1280
|
+
*/
|
|
1281
|
+
isSecretTarget(ref) {
|
|
1282
|
+
const remembered = this.#targetByRef.get(ref);
|
|
1283
|
+
if (remembered !== void 0) return remembered.secret === true;
|
|
1284
|
+
const target = this.#options.executor.describe(ref);
|
|
1285
|
+
return target === void 0 || target.secret === true;
|
|
1286
|
+
}
|
|
1287
|
+
/**
|
|
1288
|
+
* `act()` 当时看到的目标身份(分册 30)。句柄只在本次感知内有效,
|
|
1289
|
+
* 只留句柄等于留了一个换次运行就失效的引用;角色与可访问名才是可重放的那部分。
|
|
1290
|
+
*/
|
|
1291
|
+
rememberedTarget(ref) {
|
|
1292
|
+
return this.#targetByRef.get(ref);
|
|
1293
|
+
}
|
|
1294
|
+
#rememberTarget(ref, target) {
|
|
1295
|
+
this.#targetByRef.delete(ref);
|
|
1296
|
+
this.#targetByRef.set(ref, target);
|
|
1297
|
+
if (this.#targetByRef.size > TARGET_MEMO_LIMIT) {
|
|
1298
|
+
const oldest = this.#targetByRef.keys().next();
|
|
1299
|
+
if (oldest.done !== true) this.#targetByRef.delete(oldest.value);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1110
1302
|
async act(request) {
|
|
1111
1303
|
if (!this.enabled) throw new WebSkillError("PAGE_ACTION_OUT_OF_SCOPE", "Page actions are not enabled: the host declared no actionable regions.");
|
|
1112
1304
|
const target = this.#options.executor.describe(request.ref);
|
|
@@ -1120,6 +1312,7 @@ var PageActionPolicy = class {
|
|
|
1120
1312
|
}, false);
|
|
1121
1313
|
throw new WebSkillError("PAGE_ACTION_DECLINED", declineReason);
|
|
1122
1314
|
}
|
|
1315
|
+
this.#rememberTarget(request.ref, target);
|
|
1123
1316
|
const outcome = await this.#options.executor.execute(request);
|
|
1124
1317
|
await this.#record(request, outcome, approved);
|
|
1125
1318
|
return outcome;
|
|
@@ -1242,6 +1435,26 @@ function createPageActionToolSource(options) {
|
|
|
1242
1435
|
}] : []),
|
|
1243
1436
|
systemPrompt: () => Promise.resolve(policy.enabled ? PAGE_ACTION_SYSTEM_PROMPT : void 0),
|
|
1244
1437
|
canHandle: (name) => name === PAGE_ACTION_TOOL,
|
|
1438
|
+
argCaptureTrust: (name, args) => {
|
|
1439
|
+
if (name !== "act_on_page") return void 0;
|
|
1440
|
+
const ref = args["ref"];
|
|
1441
|
+
if (typeof ref !== "string") return { tier: "untrusted" };
|
|
1442
|
+
return policy.isSecretTarget(ref) ? { tier: "untrusted" } : { tier: "reviewed" };
|
|
1443
|
+
},
|
|
1444
|
+
captureArgs: (name, args) => {
|
|
1445
|
+
if (name !== "act_on_page") return void 0;
|
|
1446
|
+
const ref = args["ref"];
|
|
1447
|
+
const target = typeof ref === "string" ? policy.rememberedTarget(ref) : void 0;
|
|
1448
|
+
if (target === void 0) return void 0;
|
|
1449
|
+
return {
|
|
1450
|
+
...args,
|
|
1451
|
+
target: {
|
|
1452
|
+
role: target.role,
|
|
1453
|
+
...target.name !== void 0 ? { name: target.name } : {},
|
|
1454
|
+
...target.frame !== void 0 ? { frame: target.frame } : {}
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
},
|
|
1245
1458
|
call: async (_name, args) => {
|
|
1246
1459
|
const ref = args["ref"];
|
|
1247
1460
|
const action = args["action"];
|
|
@@ -1277,4 +1490,4 @@ function createPageActionToolSource(options) {
|
|
|
1277
1490
|
}
|
|
1278
1491
|
|
|
1279
1492
|
//#endregion
|
|
1280
|
-
export { createTodoToolSource as C,
|
|
1493
|
+
export { createTodoToolSource as C, toFrameScopes as D, toActionFrameScopes as E, withDelegationOrigin as O, createSkillGenerationToolSource as S, frameSteps as T, TodoStore as _, GENERATE_SKILL_TOOL as a, createPageActionToolSource as b, PAGE_ACTION_SYSTEM_PROMPT as c, PERCEPTION_SYSTEM_PROMPT as d, PageActionPolicy as f, TODO_SYSTEM_PROMPT as g, SkillGenerator as h, DelegationOrchestrator as i, PAGE_ACTION_TOOL as l, SKILL_GENERATION_SYSTEM_PROMPT as m, DELEGATION_SYSTEM_PROMPT as n, MANAGE_TODO_TOOL as o, PagePerceptionPolicy as p, DataSourcePolicy as r, PAGE_ACTION_KINDS as s, DELEGATE_TASK_TOOL as t, PERCEIVE_PAGE_TOOL as u, createDelegationToolSource as v, frameLabel as w, createPagePerceptionToolSource as x, createHttpDataSourceTransport as y };
|