page-agent-sdk 4.8.1 → 4.8.2
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/page-agent-sdk.headless.js +547 -502
- package/dist/page-agent-sdk.iife.js +115 -115
- package/dist/page-agent-sdk.js +1941 -1896
- package/dist/page-agent-sdk.legacy.js +1228 -1182
- package/dist/page-agent-sdk.umd.cjs +55 -55
- package/package.json +1 -1
|
@@ -7702,6 +7702,18 @@ var Vu = class {
|
|
|
7702
7702
|
}
|
|
7703
7703
|
};
|
|
7704
7704
|
function Hu(e) {
|
|
7705
|
+
let t = e?.pendingReanchors;
|
|
7706
|
+
if (!e || !t || !t.length) return;
|
|
7707
|
+
let n = t.map(([t, n]) => ({
|
|
7708
|
+
o: t,
|
|
7709
|
+
n,
|
|
7710
|
+
spec: e.resourcesByPath.get(t)
|
|
7711
|
+
})).filter((e) => !!e.spec && e.o !== e.n);
|
|
7712
|
+
for (let t of n) e.resourcesByPath.delete(t.o);
|
|
7713
|
+
for (let t of n) e.resourcesByPath.has(t.n) || e.resourcesByPath.set(t.n, t.spec);
|
|
7714
|
+
t.length = 0;
|
|
7715
|
+
}
|
|
7716
|
+
function Uu(e) {
|
|
7705
7717
|
let { jp: t, resolved: n, resourcesByPath: r, resourceStore: i } = e;
|
|
7706
7718
|
if (!r.size) return n;
|
|
7707
7719
|
let a = !1;
|
|
@@ -7722,7 +7734,7 @@ function Hu(e) {
|
|
|
7722
7734
|
}
|
|
7723
7735
|
return o;
|
|
7724
7736
|
}
|
|
7725
|
-
function
|
|
7737
|
+
function Wu(e, t, n, r) {
|
|
7726
7738
|
if (!r) return {
|
|
7727
7739
|
code: "RESOURCE_NOT_FOUND",
|
|
7728
7740
|
message: `句柄 "${e}" 无法展开(资源池未启用)`,
|
|
@@ -7743,37 +7755,69 @@ function Uu(e, t, n, r) {
|
|
|
7743
7755
|
hint: "重新 read 该字段触发懒注册重建句柄,再写回新句柄 ⟦res:<handle>⟧"
|
|
7744
7756
|
};
|
|
7745
7757
|
}
|
|
7746
|
-
function
|
|
7758
|
+
function Gu(e, t, n) {
|
|
7759
|
+
if (n === void 0) return;
|
|
7760
|
+
let r = t.split(".");
|
|
7761
|
+
for (let i = 0; i < r.length - 1; i++) {
|
|
7762
|
+
if (!/^\d+$/.test(r[i])) continue;
|
|
7763
|
+
let a = r.slice(0, i).join("."), o = r.slice(i + 1).join("."), s = Q(e, a);
|
|
7764
|
+
if (Array.isArray(s)) for (let e = 0; e < s.length; e++) {
|
|
7765
|
+
let a = Q(s[e], o);
|
|
7766
|
+
if (a !== void 0 && zu(a, n)) {
|
|
7767
|
+
let n = [
|
|
7768
|
+
...r.slice(0, i),
|
|
7769
|
+
String(e),
|
|
7770
|
+
...r.slice(i + 1)
|
|
7771
|
+
].join(".");
|
|
7772
|
+
if (n !== t) return n;
|
|
7773
|
+
}
|
|
7774
|
+
}
|
|
7775
|
+
}
|
|
7776
|
+
}
|
|
7777
|
+
function Ku(e, t, n) {
|
|
7778
|
+
let r = n.split("."), i = r.findIndex((e) => /^\d+$/.test(e));
|
|
7779
|
+
if (i < 0) return !1;
|
|
7780
|
+
let a = r.slice(0, i).join("."), o = Number(r[i]), s = Q(e, a), c = Q(t, a);
|
|
7781
|
+
if (!Array.isArray(s) || !Array.isArray(c)) return !1;
|
|
7782
|
+
let l = s[o];
|
|
7783
|
+
if (l === void 0) return !1;
|
|
7784
|
+
for (let e = 0; e < c.length; e++) if (e !== o && zu(l, c[e])) return !0;
|
|
7785
|
+
return !1;
|
|
7786
|
+
}
|
|
7787
|
+
function qu(e, t, n) {
|
|
7747
7788
|
let r = t.getBind();
|
|
7789
|
+
t.pendingReanchors && (t.pendingReanchors.length = 0);
|
|
7748
7790
|
for (let [i, a] of t.resourcesByPath) {
|
|
7749
|
-
let o = Q(r, i), s =
|
|
7750
|
-
|
|
7791
|
+
let o = Q(r, i), s = Gu(e, i, o);
|
|
7792
|
+
s && t.pendingReanchors?.push([i, s]);
|
|
7793
|
+
let c = Q(e, s ?? i);
|
|
7794
|
+
if (c === void 0) {
|
|
7751
7795
|
if (o === void 0) continue;
|
|
7752
|
-
let
|
|
7753
|
-
if (Q(e,
|
|
7796
|
+
let s = i.split(".");
|
|
7797
|
+
if (Q(e, s.length > 1 ? s.slice(0, -1).join(".") : "") !== void 0 && !Ku(e, r, i)) {
|
|
7754
7798
|
zs(e, i, o);
|
|
7755
7799
|
continue;
|
|
7756
7800
|
}
|
|
7757
|
-
if (!(e && typeof e == "object" &&
|
|
7801
|
+
if (!(e && typeof e == "object" && s[0] in e)) {
|
|
7758
7802
|
if (n) continue;
|
|
7759
7803
|
zs(e, i, o);
|
|
7760
7804
|
continue;
|
|
7761
7805
|
}
|
|
7762
|
-
let
|
|
7806
|
+
let c = a.mode === "freeze" && !!t.isFieldRequired?.(i);
|
|
7763
7807
|
return {
|
|
7764
7808
|
ok: !1,
|
|
7765
7809
|
code: a.mode === "freeze" ? "FROZEN_FIELD" : "VERBATIM_PROTECTED",
|
|
7766
7810
|
path: i,
|
|
7767
7811
|
message: `整体替换会移除受保护字段 "${i}"(${a.mode}),已拒绝`,
|
|
7768
|
-
hint: a.mode === "freeze" ? "含冻结字段的容器不可整体清空/替换:保留包含该字段的元素(补齐其必填字段,如 type),或逐个 remove 其余元素;彻底移除该字段需集成方调整 data.resources" + (
|
|
7812
|
+
hint: a.mode === "freeze" ? "含冻结字段的容器不可整体清空/替换:保留包含该字段的元素(补齐其必填字段,如 type),或逐个 remove 其余元素;彻底移除该字段需集成方调整 data.resources" + (c ? `;⚠ 该字段("${i.split(".").pop()}")同时是 schema 必填 —— 新建同类元素会因缺它被 schema 拒,此路死锁:勿反复整体替换重试,改用增量 patch 只写非保护字段,或由集成方将保护字段设为可选/给默认值` : "") : "含 verbatim 字段的容器不可整体清空/替换:保留包含该字段的元素,或先 resource_delete({path}) 释放保护后再整体替换"
|
|
7769
7813
|
};
|
|
7770
7814
|
}
|
|
7771
7815
|
if (a.mode === "freeze") {
|
|
7772
|
-
if (
|
|
7816
|
+
if (c === Pu(i)) {
|
|
7773
7817
|
zs(e, i, o);
|
|
7774
7818
|
continue;
|
|
7775
7819
|
}
|
|
7776
|
-
if (!zu(
|
|
7820
|
+
if (!zu(c, o)) return {
|
|
7777
7821
|
ok: !1,
|
|
7778
7822
|
code: "FROZEN_FIELD",
|
|
7779
7823
|
path: i,
|
|
@@ -7781,9 +7825,9 @@ function Wu(e, t, n) {
|
|
|
7781
7825
|
hint: "该字段由系统/集成方维护,LLM 不得改动。如需展示其值用 resource_get({path}) 取真值"
|
|
7782
7826
|
};
|
|
7783
7827
|
} else {
|
|
7784
|
-
let n = Iu(
|
|
7828
|
+
let n = Iu(c);
|
|
7785
7829
|
if (n && n.type === "res") {
|
|
7786
|
-
let r =
|
|
7830
|
+
let r = Wu(n.handle, i, o, t.resourceStore);
|
|
7787
7831
|
if ("value" in r) {
|
|
7788
7832
|
zs(e, i, r.value);
|
|
7789
7833
|
continue;
|
|
@@ -7796,7 +7840,7 @@ function Wu(e, t, n) {
|
|
|
7796
7840
|
hint: r.hint
|
|
7797
7841
|
};
|
|
7798
7842
|
}
|
|
7799
|
-
if (!zu(
|
|
7843
|
+
if (!zu(c, o)) return {
|
|
7800
7844
|
ok: !1,
|
|
7801
7845
|
code: "VERBATIM_MISMATCH",
|
|
7802
7846
|
path: i,
|
|
@@ -7807,7 +7851,7 @@ function Wu(e, t, n) {
|
|
|
7807
7851
|
}
|
|
7808
7852
|
return { ok: !0 };
|
|
7809
7853
|
}
|
|
7810
|
-
function
|
|
7854
|
+
function Ju(e, t, n) {
|
|
7811
7855
|
let r = t === void 0 ? e.message : `patches[${t}]${n ? ` @ "${n}"` : ""}: ${e.message}`;
|
|
7812
7856
|
return Z({
|
|
7813
7857
|
code: e.code,
|
|
@@ -7820,22 +7864,22 @@ function Gu(e, t, n) {
|
|
|
7820
7864
|
} }
|
|
7821
7865
|
});
|
|
7822
7866
|
}
|
|
7823
|
-
function
|
|
7867
|
+
function Yu(e) {
|
|
7824
7868
|
let { value: t, ctx: n, mergeMode: r } = e;
|
|
7825
7869
|
if (!n || !n.resourcesByPath.size) return {
|
|
7826
7870
|
ok: !0,
|
|
7827
7871
|
value: t
|
|
7828
7872
|
};
|
|
7829
|
-
let i = Vs(t), a =
|
|
7873
|
+
let i = Vs(t), a = qu(i, n, r);
|
|
7830
7874
|
return a.ok ? {
|
|
7831
7875
|
ok: !0,
|
|
7832
7876
|
value: i
|
|
7833
7877
|
} : {
|
|
7834
7878
|
ok: !1,
|
|
7835
|
-
error:
|
|
7879
|
+
error: Ju(a)
|
|
7836
7880
|
};
|
|
7837
7881
|
}
|
|
7838
|
-
function
|
|
7882
|
+
function Xu(e) {
|
|
7839
7883
|
let { patches: t, clone: n, ctx: r } = e;
|
|
7840
7884
|
if (!r || !r.resourcesByPath.size) return { ok: !0 };
|
|
7841
7885
|
for (let e = 0; e < t.length; e++) {
|
|
@@ -7860,17 +7904,17 @@ function qu(e) {
|
|
|
7860
7904
|
}
|
|
7861
7905
|
}
|
|
7862
7906
|
}
|
|
7863
|
-
let i =
|
|
7907
|
+
let i = qu(n, r);
|
|
7864
7908
|
if (!i.ok) {
|
|
7865
|
-
let e =
|
|
7909
|
+
let e = Zu(i.path, t);
|
|
7866
7910
|
return {
|
|
7867
7911
|
ok: !1,
|
|
7868
|
-
error:
|
|
7912
|
+
error: Ju(i, e >= 0 ? e : void 0, e >= 0 ? t[e].jsonPath : void 0)
|
|
7869
7913
|
};
|
|
7870
7914
|
}
|
|
7871
7915
|
return { ok: !0 };
|
|
7872
7916
|
}
|
|
7873
|
-
function
|
|
7917
|
+
function Zu(e, t) {
|
|
7874
7918
|
let n = Lu(e);
|
|
7875
7919
|
for (let e = 0; e < t.length; e++) {
|
|
7876
7920
|
let r = Lu(t[e].jsonPath || "");
|
|
@@ -7880,13 +7924,13 @@ function Ju(e, t) {
|
|
|
7880
7924
|
}
|
|
7881
7925
|
//#endregion
|
|
7882
7926
|
//#region src/core/tools/dataOps.ts
|
|
7883
|
-
function
|
|
7927
|
+
function Qu(e, t) {
|
|
7884
7928
|
if (!e) return null;
|
|
7885
7929
|
let n = (t ? Uo(e, t) : e)?.shape;
|
|
7886
7930
|
return n && typeof n == "object" ? Object.keys(n) : null;
|
|
7887
7931
|
}
|
|
7888
|
-
var
|
|
7889
|
-
function
|
|
7932
|
+
var $u = (e) => e && e.length ? `(可用字段:${e.slice(0, 12).join(", ")}${e.length > 12 ? " …" : ""})` : "", ed = (e) => /[.[]/.test(e) ? e.replace(/[.[][^.[]*$/, "") : "";
|
|
7933
|
+
function td(e) {
|
|
7890
7934
|
let { schema: t, allowKeys: n, value: r, bindRef: i } = e, a = [];
|
|
7891
7935
|
if (n) {
|
|
7892
7936
|
if (typeof r != "object" || !r || Array.isArray(r)) return {
|
|
@@ -7911,7 +7955,7 @@ function Qu(e) {
|
|
|
7911
7955
|
error: Z({
|
|
7912
7956
|
code: "SCHEMA_STRIP",
|
|
7913
7957
|
message: `字段 ${r} 不在 schema 声明内,写入被拒绝(防静默丢失)`,
|
|
7914
|
-
hint: `该数据结构不支持这些字段;请只用 schema 声明的字段,或在 data.schema 中声明后重试${
|
|
7958
|
+
hint: `该数据结构不支持这些字段;请只用 schema 声明的字段,或在 data.schema 中声明后重试${$u(Qu(t, ""))}`,
|
|
7915
7959
|
path: r,
|
|
7916
7960
|
details: { stripped: [r] }
|
|
7917
7961
|
}),
|
|
@@ -7931,7 +7975,7 @@ function Qu(e) {
|
|
|
7931
7975
|
error: Z({
|
|
7932
7976
|
code: "SCHEMA_STRIP",
|
|
7933
7977
|
message: `字段 ${c.join(", ")} 不在 schema 声明内,写入被拒绝(防静默丢失)`,
|
|
7934
|
-
hint: `该数据结构不支持这些字段;请只用 schema 声明的字段,或在 data.schema 中声明后重试${
|
|
7978
|
+
hint: `该数据结构不支持这些字段;请只用 schema 声明的字段,或在 data.schema 中声明后重试${$u(Qu(t, ed(String(c[0]))))}`,
|
|
7935
7979
|
path: c[0],
|
|
7936
7980
|
details: { stripped: c }
|
|
7937
7981
|
}),
|
|
@@ -7970,7 +8014,7 @@ function Qu(e) {
|
|
|
7970
8014
|
notices: a
|
|
7971
8015
|
};
|
|
7972
8016
|
}
|
|
7973
|
-
function
|
|
8017
|
+
function nd(e) {
|
|
7974
8018
|
let { schema: t, bindRef: n, clone: r, patches: i, schemaErrorMode: a = "zod", appendCaptures: o, moveCaptures: s } = e, c = [], l = (t) => {
|
|
7975
8019
|
let n = Q(r, t);
|
|
7976
8020
|
return n === void 0 ? e.valueAt?.(t) : n;
|
|
@@ -8279,14 +8323,14 @@ function $u(e) {
|
|
|
8279
8323
|
notices: c
|
|
8280
8324
|
};
|
|
8281
8325
|
}
|
|
8282
|
-
function
|
|
8283
|
-
let { bindRef: t, schema: n, allowKeys: r, snapshots: i, maxSnapshots: a, audit: o, dryRun: s, op: c = "set", protectedCtx: l, snapshotLabel: u } = e, d = e.value, f = e.internalAfterWrite ? Vs(t) : null, p =
|
|
8326
|
+
function rd(e) {
|
|
8327
|
+
let { bindRef: t, schema: n, allowKeys: r, snapshots: i, maxSnapshots: a, audit: o, dryRun: s, op: c = "set", protectedCtx: l, snapshotLabel: u } = e, d = e.value, f = e.internalAfterWrite ? Vs(t) : null, p = ad(d);
|
|
8284
8328
|
if (p) return {
|
|
8285
8329
|
ok: !1,
|
|
8286
|
-
error:
|
|
8330
|
+
error: od(p)
|
|
8287
8331
|
};
|
|
8288
8332
|
if (l) {
|
|
8289
|
-
let e =
|
|
8333
|
+
let e = Yu({
|
|
8290
8334
|
value: d,
|
|
8291
8335
|
ctx: l,
|
|
8292
8336
|
mergeMode: !!r
|
|
@@ -8297,7 +8341,7 @@ function ed(e) {
|
|
|
8297
8341
|
};
|
|
8298
8342
|
d = e.value;
|
|
8299
8343
|
}
|
|
8300
|
-
let m =
|
|
8344
|
+
let m = td({
|
|
8301
8345
|
schema: n,
|
|
8302
8346
|
allowKeys: r,
|
|
8303
8347
|
value: d,
|
|
@@ -8334,14 +8378,14 @@ function ed(e) {
|
|
|
8334
8378
|
op: c,
|
|
8335
8379
|
value: h,
|
|
8336
8380
|
timestamp: Date.now()
|
|
8337
|
-
}), e.onWrite?.(), e.internalAfterWrite?.(t, f), {
|
|
8381
|
+
}), e.onWrite?.(), e.internalAfterWrite?.(t, f), Hu(l), {
|
|
8338
8382
|
ok: !0,
|
|
8339
8383
|
hash: e.hashFn ? e.hashFn() : qs(t),
|
|
8340
8384
|
data: h,
|
|
8341
8385
|
notices: m.notices
|
|
8342
8386
|
};
|
|
8343
8387
|
}
|
|
8344
|
-
function
|
|
8388
|
+
function id(e) {
|
|
8345
8389
|
let { bindRef: t, patches: n, schema: r, allowKeys: i, snapshots: a, maxSnapshots: o, markDataDirty: s, schemaErrorMode: c = "zod", snapshotLabel: l, dryRun: u, protectedCtx: d } = e, f = e.internalAfterWrite ? Vs(t) : null, p = Vs(t), m = [], h = [], g = [], _ = [], v = (e, t) => {
|
|
8346
8390
|
(e === "set" || e === "merge") && _.push({
|
|
8347
8391
|
jp: t,
|
|
@@ -8363,7 +8407,7 @@ function td(e) {
|
|
|
8363
8407
|
error: Z({
|
|
8364
8408
|
code: "PATH_DENIED",
|
|
8365
8409
|
message: `patches[${e}] @ "${a}" 不在 schema 声明字段内`,
|
|
8366
|
-
hint: `仅 schema 声明的 key 可写${
|
|
8410
|
+
hint: `仅 schema 声明的 key 可写${$u(Qu(r, ed(a)))}`
|
|
8367
8411
|
})
|
|
8368
8412
|
};
|
|
8369
8413
|
let o = t.op ?? "set", s;
|
|
@@ -8382,10 +8426,10 @@ function td(e) {
|
|
|
8382
8426
|
error: oi(`patches[${e}]`, t.value, n.parseError)
|
|
8383
8427
|
};
|
|
8384
8428
|
if (s = n.parsed, o !== "move") {
|
|
8385
|
-
let t =
|
|
8429
|
+
let t = ad(s);
|
|
8386
8430
|
if (t) return {
|
|
8387
8431
|
ok: !1,
|
|
8388
|
-
error:
|
|
8432
|
+
error: od(t, `patches[${e}] @ "${a}"`)
|
|
8389
8433
|
};
|
|
8390
8434
|
}
|
|
8391
8435
|
if (o === "move" && typeof s == "string" && !Vo(s, r, i)) return {
|
|
@@ -8393,7 +8437,7 @@ function td(e) {
|
|
|
8393
8437
|
error: Z({
|
|
8394
8438
|
code: "PATH_DENIED",
|
|
8395
8439
|
message: `patches[${e}] move 目标 "${s}" 不在 schema 声明字段内`,
|
|
8396
|
-
hint: `move 的 value(目标路径)也须在 schema 声明字段内${
|
|
8440
|
+
hint: `move 的 value(目标路径)也须在 schema 声明字段内${$u(Qu(r, ed(String(s))))}`
|
|
8397
8441
|
})
|
|
8398
8442
|
};
|
|
8399
8443
|
}
|
|
@@ -8421,7 +8465,7 @@ function td(e) {
|
|
|
8421
8465
|
});
|
|
8422
8466
|
}
|
|
8423
8467
|
if (d) {
|
|
8424
|
-
let e =
|
|
8468
|
+
let e = Xu({
|
|
8425
8469
|
patches: n,
|
|
8426
8470
|
clone: p,
|
|
8427
8471
|
ctx: d
|
|
@@ -8431,7 +8475,7 @@ function td(e) {
|
|
|
8431
8475
|
error: e.error
|
|
8432
8476
|
};
|
|
8433
8477
|
}
|
|
8434
|
-
let y = d ? new Set([...d.resourcesByPath.keys()].map((e) => e.split(".").pop()).filter(Boolean)) : void 0, b =
|
|
8478
|
+
let y = d ? new Set([...d.resourcesByPath.keys()].map((e) => e.split(".").pop()).filter(Boolean)) : void 0, b = nd({
|
|
8435
8479
|
schema: r,
|
|
8436
8480
|
bindRef: t,
|
|
8437
8481
|
clone: p,
|
|
@@ -8473,14 +8517,14 @@ function td(e) {
|
|
|
8473
8517
|
let n = e.jp ? Q(t, e.jp) : t;
|
|
8474
8518
|
typeof n == "string" && typeof e.str == "string" && zs(t, e.jp, n + e.str);
|
|
8475
8519
|
}
|
|
8476
|
-
return e.internalAfterWrite?.(t, f), s?.(), {
|
|
8520
|
+
return e.internalAfterWrite?.(t, f), Hu(d), s?.(), {
|
|
8477
8521
|
ok: !0,
|
|
8478
8522
|
applied: m,
|
|
8479
8523
|
clone: p,
|
|
8480
8524
|
notices: b.notices
|
|
8481
8525
|
};
|
|
8482
8526
|
}
|
|
8483
|
-
function
|
|
8527
|
+
function ad(e) {
|
|
8484
8528
|
let t = /^<[A-Za-z_][\w.-]*\s[\d.]+[KMG]?B>$/, n = (e) => {
|
|
8485
8529
|
if (typeof e == "string") return e.includes("<subtree ") || t.test(e) ? e.slice(0, 60) : null;
|
|
8486
8530
|
if (Array.isArray(e)) {
|
|
@@ -8498,30 +8542,30 @@ function nd(e) {
|
|
|
8498
8542
|
};
|
|
8499
8543
|
return n(e);
|
|
8500
8544
|
}
|
|
8501
|
-
var
|
|
8545
|
+
var od = (e, t) => Z({
|
|
8502
8546
|
code: "PLACEHOLDER_LEAK",
|
|
8503
8547
|
path: t || void 0,
|
|
8504
8548
|
message: `写入值包含摘要占位符 "${e}"(read/query 为省上下文返回的体积占位,非真实数据),已拒绝写入`,
|
|
8505
8549
|
hint: "占位符子树的真实内容需先窄读获取:read({jsonPath:\"<该子树路径>\"}) 结果根豁免返回全文;聚焦该区域可用 set_focus。基于真实值重新构造写入内容"
|
|
8506
8550
|
});
|
|
8507
|
-
function
|
|
8551
|
+
function sd(e) {
|
|
8508
8552
|
return e < 1024 ? `${e}B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(1)}KB` : `${(e / (1024 * 1024)).toFixed(1)}MB`;
|
|
8509
8553
|
}
|
|
8510
|
-
var
|
|
8511
|
-
function
|
|
8554
|
+
var cd = 3072;
|
|
8555
|
+
function ld(e) {
|
|
8512
8556
|
return typeof e == "string" ? e.length + 2 : typeof e == "number" || typeof e == "boolean" ? 8 : 4;
|
|
8513
8557
|
}
|
|
8514
|
-
function
|
|
8558
|
+
function ud(e, t, n, r, i) {
|
|
8515
8559
|
if (!t || e == null) return e;
|
|
8516
|
-
let a = new Set(n.map((e) => e.field)), o = r, s =
|
|
8560
|
+
let a = new Set(n.map((e) => e.field)), o = r, s = cd, c = i?.rootExempt ?? !1, l = i?.rootPath ?? "", u = i?.fullTextPrefixes ?? [], d = Vs(e), f = i?.onSummarized, p = (e) => u.some((t) => t && (e === t || e.startsWith(t + ".") || e.startsWith(t + "["))), m = (e, t) => {
|
|
8517
8561
|
let n = "#" + String(qs(e)).slice(0, 8);
|
|
8518
|
-
if (Array.isArray(e)) return `<subtree ${
|
|
8562
|
+
if (Array.isArray(e)) return `<subtree ${sd(t)} children:${e.length} ${n}>`;
|
|
8519
8563
|
let r = Object.keys(e), i = r.slice(0, 6).join(",") + (r.length > 6 ? ",…" : "");
|
|
8520
|
-
return `<subtree ${
|
|
8564
|
+
return `<subtree ${sd(t)} keys:[${i}] ${n}>`;
|
|
8521
8565
|
}, h = (e, t, n) => {
|
|
8522
8566
|
if (typeof e != "object" || !e) return {
|
|
8523
8567
|
node: e,
|
|
8524
|
-
eff:
|
|
8568
|
+
eff: ld(e)
|
|
8525
8569
|
};
|
|
8526
8570
|
if (p(t)) return {
|
|
8527
8571
|
node: e,
|
|
@@ -8544,7 +8588,7 @@ function sd(e, t, n, r, i) {
|
|
|
8544
8588
|
let r = 2;
|
|
8545
8589
|
for (let n of Object.keys(e)) {
|
|
8546
8590
|
let i = e[n], s = t ? `${t}.${n}` : n;
|
|
8547
|
-
if (typeof i == "string" && a.has(n) && i.length >= o && !p(s)) e[n] = `<${n} ${
|
|
8591
|
+
if (typeof i == "string" && a.has(n) && i.length >= o && !p(s)) e[n] = `<${n} ${sd(i.length)}>`, f?.(s), r += e[n].length + n.length + 2;
|
|
8548
8592
|
else {
|
|
8549
8593
|
let t = h(i, s, !1);
|
|
8550
8594
|
e[n] = t.node, r += t.eff + n.length + 2;
|
|
@@ -8560,23 +8604,23 @@ function sd(e, t, n, r, i) {
|
|
|
8560
8604
|
};
|
|
8561
8605
|
return h(d, l, !0).node;
|
|
8562
8606
|
}
|
|
8563
|
-
var
|
|
8564
|
-
function
|
|
8565
|
-
return
|
|
8607
|
+
var dd = 0;
|
|
8608
|
+
function fd() {
|
|
8609
|
+
return dd++, "c_" + Math.random().toString(36).slice(2, 8) + dd.toString(36);
|
|
8566
8610
|
}
|
|
8567
|
-
function
|
|
8611
|
+
function pd(e, t) {
|
|
8568
8612
|
if (!(!e || typeof e != "object")) for (let n of t) {
|
|
8569
8613
|
let t = Q(e, n);
|
|
8570
|
-
if (Array.isArray(t)) for (let e of t) e && typeof e == "object" && !("__pgId" in e) && (e.__pgId =
|
|
8614
|
+
if (Array.isArray(t)) for (let e of t) e && typeof e == "object" && !("__pgId" in e) && (e.__pgId = fd());
|
|
8571
8615
|
}
|
|
8572
8616
|
}
|
|
8573
|
-
function
|
|
8617
|
+
function md(e) {
|
|
8574
8618
|
(function e(t) {
|
|
8575
8619
|
if (Array.isArray(t)) t.forEach(e);
|
|
8576
8620
|
else if (t && typeof t == "object") for (let n of Object.keys(t)) n.startsWith("__pg") ? delete t[n] : e(t[n]);
|
|
8577
8621
|
})(e);
|
|
8578
8622
|
}
|
|
8579
|
-
function
|
|
8623
|
+
function hd(e, n = {}) {
|
|
8580
8624
|
let i = n.pgIdPaths ?? [], a = n.sandboxRunner ?? _a, o = i.length ? (e, t) => {
|
|
8581
8625
|
if (t && typeof t == "object") for (let n of i) {
|
|
8582
8626
|
let r = Q(t, n), i = Q(e, n);
|
|
@@ -8603,7 +8647,7 @@ function fd(e, n = {}) {
|
|
|
8603
8647
|
t && n && typeof n == "object" && !("__pgId" in n) && (n.__pgId = t, o.add(e));
|
|
8604
8648
|
}
|
|
8605
8649
|
}
|
|
8606
|
-
|
|
8650
|
+
pd(e, i);
|
|
8607
8651
|
} : void 0, s = i.length ? ms(e.schema, i).schema : e.schema, c = e.bind, l = e.description ?? "主数据对象", u = Bo(s), d = /* @__PURE__ */ new Map(), f = n.vfsStore ? new Vu(n.vfsStore) : void 0;
|
|
8608
8652
|
function p(e) {
|
|
8609
8653
|
if (d.clear(), e) for (let t of e) {
|
|
@@ -8619,6 +8663,7 @@ function fd(e, n = {}) {
|
|
|
8619
8663
|
resourcesByPath: d,
|
|
8620
8664
|
resourceStore: f,
|
|
8621
8665
|
getBind: () => c,
|
|
8666
|
+
pendingReanchors: [],
|
|
8622
8667
|
isFieldRequired: (e) => {
|
|
8623
8668
|
let t = e.split("."), n = t[t.length - 1], r = (t.length > 1 ? Uo(s, t.slice(0, -1).join(".")) : s)?.shape?.[n];
|
|
8624
8669
|
return !!r && typeof r.isOptional == "function" && !r.isOptional();
|
|
@@ -8888,7 +8933,7 @@ function fd(e, n = {}) {
|
|
|
8888
8933
|
details: { expr: e }
|
|
8889
8934
|
});
|
|
8890
8935
|
}
|
|
8891
|
-
let r = n ?? 50, s = t.slice(0, r), c = s.map((e) => `{"path":${JSON.stringify(e.path)},"index":${e.index === void 0 ? "null" : e.index},"value":${$(
|
|
8936
|
+
let r = n ?? 50, s = t.slice(0, r), c = s.map((e) => `{"path":${JSON.stringify(e.path)},"index":${e.index === void 0 ? "null" : e.index},"value":${$(ud(e.value, i === "", A, k, {
|
|
8892
8937
|
rootExempt: !1,
|
|
8893
8938
|
rootPath: String(e.path ?? ""),
|
|
8894
8939
|
fullTextPrefixes: o,
|
|
@@ -8993,7 +9038,7 @@ function fd(e, n = {}) {
|
|
|
8993
9038
|
if (l) {
|
|
8994
9039
|
let e = await re();
|
|
8995
9040
|
try {
|
|
8996
|
-
let e =
|
|
9041
|
+
let e = id({
|
|
8997
9042
|
bindRef: c,
|
|
8998
9043
|
patches: [{
|
|
8999
9044
|
op: "set",
|
|
@@ -9027,7 +9072,7 @@ function fd(e, n = {}) {
|
|
|
9027
9072
|
});
|
|
9028
9073
|
let e = await re();
|
|
9029
9074
|
try {
|
|
9030
|
-
let e =
|
|
9075
|
+
let e = id({
|
|
9031
9076
|
bindRef: c,
|
|
9032
9077
|
patches: t.patches,
|
|
9033
9078
|
schema: s,
|
|
@@ -9049,10 +9094,10 @@ function fd(e, n = {}) {
|
|
|
9049
9094
|
e.release();
|
|
9050
9095
|
}
|
|
9051
9096
|
}
|
|
9052
|
-
let n = t, r =
|
|
9053
|
-
if (r) return
|
|
9097
|
+
let n = t, r = ad(n);
|
|
9098
|
+
if (r) return od(r);
|
|
9054
9099
|
if (m) {
|
|
9055
|
-
let e =
|
|
9100
|
+
let e = Yu({
|
|
9056
9101
|
value: n,
|
|
9057
9102
|
ctx: m
|
|
9058
9103
|
});
|
|
@@ -9066,7 +9111,7 @@ function fd(e, n = {}) {
|
|
|
9066
9111
|
});
|
|
9067
9112
|
let a = o ? Vs(c) : null, d = await re();
|
|
9068
9113
|
try {
|
|
9069
|
-
let e =
|
|
9114
|
+
let e = td({
|
|
9070
9115
|
schema: s,
|
|
9071
9116
|
allowKeys: u,
|
|
9072
9117
|
value: n,
|
|
@@ -9115,12 +9160,12 @@ function fd(e, n = {}) {
|
|
|
9115
9160
|
e && (a = ns(a, e));
|
|
9116
9161
|
}
|
|
9117
9162
|
let o = a;
|
|
9118
|
-
return m && (o =
|
|
9163
|
+
return m && (o = Uu({
|
|
9119
9164
|
jp: i,
|
|
9120
9165
|
resolved: o,
|
|
9121
9166
|
resourcesByPath: m.resourcesByPath,
|
|
9122
9167
|
resourceStore: m.resourceStore
|
|
9123
|
-
})), n && n.length && (o = Ws(o, n)), r != null && (o = Gs(o, r)), o =
|
|
9168
|
+
})), n && n.length && (o = Ws(o, n)), r != null && (o = Gs(o, r)), o = ud(o, d === "", A, k, {
|
|
9124
9169
|
rootExempt: !0,
|
|
9125
9170
|
rootPath: i,
|
|
9126
9171
|
fullTextPrefixes: f,
|
|
@@ -9135,7 +9180,7 @@ function fd(e, n = {}) {
|
|
|
9135
9180
|
message: `jsonPath "${h}" 含非法段(__proto__/constructor/prototype)`,
|
|
9136
9181
|
hint: "使用正常属性路径,如 components.0.text(数组索引数字)"
|
|
9137
9182
|
});
|
|
9138
|
-
let g = (e, t) =>
|
|
9183
|
+
let g = (e, t) => Qu(s, e) ?? (t && typeof t == "object" && !Array.isArray(t) ? Object.keys(t) : []);
|
|
9139
9184
|
if (!Vo(h, s, u)) {
|
|
9140
9185
|
let e = /[.[]/.test(h) ? h.replace(/[.[][^.[]*$/, "") : "", t = g(e, e ? Q(c, e) : c), n = t.length ? `;父级 "${e || "(root)"}" 的可用字段:${t.slice(0, 12).join(", ")}${t.length > 12 ? " …" : ""}` : "";
|
|
9141
9186
|
return Z({
|
|
@@ -9163,12 +9208,12 @@ function fd(e, n = {}) {
|
|
|
9163
9208
|
e && (_ = ns(_, e));
|
|
9164
9209
|
}
|
|
9165
9210
|
let v = _;
|
|
9166
|
-
m && (v =
|
|
9211
|
+
m && (v = Uu({
|
|
9167
9212
|
jp: h,
|
|
9168
9213
|
resolved: v,
|
|
9169
9214
|
resourcesByPath: m.resourcesByPath,
|
|
9170
9215
|
resourceStore: m.resourceStore
|
|
9171
|
-
})), w(p, d), n && n.length && (v = Ws(v, n)), r != null && (v = Gs(v, r)), v =
|
|
9216
|
+
})), w(p, d), n && n.length && (v = Ws(v, n)), r != null && (v = Gs(v, r)), v = ud(v, d === "", A, k, {
|
|
9172
9217
|
rootExempt: !0,
|
|
9173
9218
|
rootPath: h,
|
|
9174
9219
|
fullTextPrefixes: f,
|
|
@@ -9255,7 +9300,7 @@ function fd(e, n = {}) {
|
|
|
9255
9300
|
op: t.op ?? "set",
|
|
9256
9301
|
jsonPath: t.jsonPath || "",
|
|
9257
9302
|
value: p
|
|
9258
|
-
}], l =
|
|
9303
|
+
}], l = id({
|
|
9259
9304
|
bindRef: c,
|
|
9260
9305
|
patches: i,
|
|
9261
9306
|
schema: s,
|
|
@@ -9277,13 +9322,13 @@ function fd(e, n = {}) {
|
|
|
9277
9322
|
timestamp: Date.now()
|
|
9278
9323
|
});
|
|
9279
9324
|
let f = ie(d);
|
|
9280
|
-
return
|
|
9325
|
+
return md(l.clone), `已 write(edit) 主数据(${l.applied.length} 个 patch)。当前值:${$(l.clone, 600)} (新 hash=${f})`;
|
|
9281
9326
|
}
|
|
9282
9327
|
let r = Us(p);
|
|
9283
9328
|
if (r.parseError) return oi("", p, r.parseError);
|
|
9284
9329
|
let l = await N("set", e, p, _);
|
|
9285
9330
|
if (l !== null) return l;
|
|
9286
|
-
let v =
|
|
9331
|
+
let v = rd({
|
|
9287
9332
|
bindRef: c,
|
|
9288
9333
|
value: r.parsed,
|
|
9289
9334
|
schema: s,
|
|
@@ -9302,7 +9347,7 @@ function fd(e, n = {}) {
|
|
|
9302
9347
|
let y = v.hash ?? O();
|
|
9303
9348
|
w(y, d);
|
|
9304
9349
|
let b = i.length ? Vs(v.data) : v.data;
|
|
9305
|
-
return
|
|
9350
|
+
return md(b), `已 write(set) 主数据 = ${$(b, 600)} (新 hash=${y})${u ? "(白名单模式:仅更新 schema 声明字段,未声明字段保留)" : ""}`;
|
|
9306
9351
|
} finally {
|
|
9307
9352
|
_.release();
|
|
9308
9353
|
}
|
|
@@ -9426,7 +9471,7 @@ function fd(e, n = {}) {
|
|
|
9426
9471
|
try {
|
|
9427
9472
|
let n = await N("set", D ? C(r) : void 0, d, f);
|
|
9428
9473
|
if (n !== null) return n;
|
|
9429
|
-
let i =
|
|
9474
|
+
let i = rd({
|
|
9430
9475
|
bindRef: c,
|
|
9431
9476
|
value: d,
|
|
9432
9477
|
schema: s,
|
|
@@ -9594,7 +9639,7 @@ function fd(e, n = {}) {
|
|
|
9594
9639
|
}
|
|
9595
9640
|
//#endregion
|
|
9596
9641
|
//#region src/core/tools/htmlValidate.ts
|
|
9597
|
-
var
|
|
9642
|
+
var gd = /* @__PURE__ */ new Set([
|
|
9598
9643
|
"area",
|
|
9599
9644
|
"base",
|
|
9600
9645
|
"br",
|
|
@@ -9609,8 +9654,8 @@ var pd = /* @__PURE__ */ new Set([
|
|
|
9609
9654
|
"source",
|
|
9610
9655
|
"track",
|
|
9611
9656
|
"wbr"
|
|
9612
|
-
]),
|
|
9613
|
-
function
|
|
9657
|
+
]), _d = /* @__PURE__ */ new Set(["script", "style"]);
|
|
9658
|
+
function vd(e) {
|
|
9614
9659
|
let t = [], n = e.length;
|
|
9615
9660
|
if (!e.trim()) return t;
|
|
9616
9661
|
let r = [0];
|
|
@@ -9687,8 +9732,8 @@ function hd(e) {
|
|
|
9687
9732
|
}
|
|
9688
9733
|
continue;
|
|
9689
9734
|
}
|
|
9690
|
-
if (!(
|
|
9691
|
-
if (
|
|
9735
|
+
if (!(gd.has(p) || m)) {
|
|
9736
|
+
if (_d.has(p)) {
|
|
9692
9737
|
let n = RegExp(`</${p}\\s*>`, "i").exec(e.slice(o));
|
|
9693
9738
|
if (!n) {
|
|
9694
9739
|
t.push({
|
|
@@ -9717,8 +9762,8 @@ function hd(e) {
|
|
|
9717
9762
|
}
|
|
9718
9763
|
//#endregion
|
|
9719
9764
|
//#region src/core/sdk/codeAssetMiddleware.ts
|
|
9720
|
-
var
|
|
9721
|
-
function
|
|
9765
|
+
var yd = "__pgTouched", bd = "__pgGenSnapshot", xd = "__pgFinalText", Sd = "__pgCodeHashes", Cd = "__pgKeepExternal", wd = "__pgNotes", Td = 200;
|
|
9766
|
+
function Ed(e) {
|
|
9722
9767
|
let t = [];
|
|
9723
9768
|
for (let n of e.split("\n")) {
|
|
9724
9769
|
let e = n.match(/^\s*[-*]?\s*\[note\]\s*(.*)$/i);
|
|
@@ -9726,27 +9771,27 @@ function Cd(e) {
|
|
|
9726
9771
|
}
|
|
9727
9772
|
return [...new Set(t)];
|
|
9728
9773
|
}
|
|
9729
|
-
function
|
|
9730
|
-
let n = Array.isArray(e[
|
|
9731
|
-
e[
|
|
9774
|
+
function Dd(e, t) {
|
|
9775
|
+
let n = Array.isArray(e[wd]) ? e[wd].filter((e) => typeof e == "string") : [];
|
|
9776
|
+
e[wd] = [.../* @__PURE__ */ new Set([...n, ...t])].map((e) => e.length > Td ? e.slice(0, Td) + "…" : e).slice(-5);
|
|
9732
9777
|
}
|
|
9733
|
-
function
|
|
9778
|
+
function Od(e) {
|
|
9734
9779
|
let t = 5381;
|
|
9735
9780
|
for (let n = 0; n < e.length; n++) t = (t << 5) + t + e.charCodeAt(n) | 0;
|
|
9736
9781
|
return (t >>> 0).toString(16);
|
|
9737
9782
|
}
|
|
9738
|
-
function
|
|
9783
|
+
function kd(e, t) {
|
|
9739
9784
|
let n = [];
|
|
9740
|
-
return
|
|
9785
|
+
return jd(e, t, (e) => {
|
|
9741
9786
|
typeof e.name == "string" && e.name && n.push(e.name);
|
|
9742
9787
|
}), n;
|
|
9743
9788
|
}
|
|
9744
|
-
function
|
|
9789
|
+
function Ad(e, t) {
|
|
9745
9790
|
if (!e.startsWith(t)) return null;
|
|
9746
9791
|
let n = e.slice(t.length), r = n.lastIndexOf(".");
|
|
9747
9792
|
return (r > 0 ? n.slice(0, r) : r === 0 ? "" : n) || null;
|
|
9748
9793
|
}
|
|
9749
|
-
function
|
|
9794
|
+
function jd(e, t, n) {
|
|
9750
9795
|
if (!(!e || typeof e != "object")) for (let r of t) {
|
|
9751
9796
|
let t = Q(e, r);
|
|
9752
9797
|
if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {
|
|
@@ -9755,7 +9800,7 @@ function Od(e, t, n) {
|
|
|
9755
9800
|
}
|
|
9756
9801
|
}
|
|
9757
9802
|
}
|
|
9758
|
-
function
|
|
9803
|
+
function Md(e, t, n) {
|
|
9759
9804
|
let r = /* @__PURE__ */ new Set();
|
|
9760
9805
|
if (!e || typeof e != "object") return r;
|
|
9761
9806
|
for (let i of t) {
|
|
@@ -9774,20 +9819,20 @@ function kd(e, t, n) {
|
|
|
9774
9819
|
}
|
|
9775
9820
|
return r;
|
|
9776
9821
|
}
|
|
9777
|
-
function
|
|
9822
|
+
function Nd(e) {
|
|
9778
9823
|
let { writablePaths: t, codeVfsPrefix: n, ext: r, codeField: i = "code", onWarning: a, getController: o, vfsStore: s, craftNotes: c = !0 } = e, l = s, u = l.__pgLastCheckout ??= /* @__PURE__ */ new Map(), d = l.__pgPendingRetry ??= /* @__PURE__ */ new Set(), f = l.__pgTouchGen ??= /* @__PURE__ */ new Map();
|
|
9779
9824
|
return {
|
|
9780
9825
|
name: "code-asset-checkout-commit",
|
|
9781
9826
|
beforeAgent: (e) => {
|
|
9782
9827
|
let c = o()?.get?.().bind;
|
|
9783
|
-
c &&
|
|
9828
|
+
c && pd(c, t);
|
|
9784
9829
|
let l = 0, p = 0, m = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map();
|
|
9785
|
-
if (
|
|
9830
|
+
if (jd(c, t, (e) => {
|
|
9786
9831
|
l++;
|
|
9787
9832
|
let t = Q(e, i);
|
|
9788
9833
|
if (typeof t == "string") {
|
|
9789
9834
|
p++;
|
|
9790
|
-
let i = e.__pgId, a =
|
|
9835
|
+
let i = e.__pgId, a = Od(t);
|
|
9791
9836
|
m.set(i, a);
|
|
9792
9837
|
let o = `${n}${i}.${r}`, c = s.files[o], l = u.get(i);
|
|
9793
9838
|
if (c && typeof c.content == "string" && c.content !== t && l === a) {
|
|
@@ -9813,24 +9858,24 @@ function Ad(e) {
|
|
|
9813
9858
|
}
|
|
9814
9859
|
return {
|
|
9815
9860
|
files: s.files,
|
|
9816
|
-
[
|
|
9817
|
-
[
|
|
9818
|
-
[
|
|
9819
|
-
[
|
|
9820
|
-
[
|
|
9861
|
+
[yd]: /* @__PURE__ */ new Set(),
|
|
9862
|
+
[xd]: { text: "" },
|
|
9863
|
+
[Sd]: m,
|
|
9864
|
+
[Cd]: [],
|
|
9865
|
+
[bd]: h
|
|
9821
9866
|
};
|
|
9822
9867
|
},
|
|
9823
9868
|
wrapModelCall: async (e, t) => {
|
|
9824
|
-
let n = await t(e), r = e.state[
|
|
9869
|
+
let n = await t(e), r = e.state[xd];
|
|
9825
9870
|
return r && !(n.toolCalls && n.toolCalls.length) && typeof n.content == "string" && n.content && (r.text = n.content), n;
|
|
9826
9871
|
},
|
|
9827
9872
|
augmentPrompt: () => {
|
|
9828
9873
|
let e = o()?.get?.().bind, i = [], a = 0;
|
|
9829
|
-
if (
|
|
9874
|
+
if (jd(e, t, (e, t, o) => {
|
|
9830
9875
|
a++;
|
|
9831
9876
|
let l = typeof e.name == "string" && e.name ? e.name : "", u = l ? `${l} [${o}]` : `(未命名 [${o}])`, d = `${n}${e.__pgId}.${r}`, f = !!s.files[d];
|
|
9832
9877
|
if (i.push(`- ${u} → ${d}${f ? "" : "(尚未检出,先 vfs_write 创建)"}`), c) {
|
|
9833
|
-
let t = Array.isArray(e[
|
|
9878
|
+
let t = Array.isArray(e[wd]) ? e[wd].filter((e) => typeof e == "string") : [];
|
|
9834
9879
|
if (t.length) {
|
|
9835
9880
|
let e = t[t.length - 1];
|
|
9836
9881
|
i.push(` 📝 笔记×${t.length}(最近):${e.length > 120 ? e.slice(0, 120) + "…" : e}`);
|
|
@@ -9852,9 +9897,9 @@ function Ad(e) {
|
|
|
9852
9897
|
if (c) {
|
|
9853
9898
|
let i = e.state.focuses;
|
|
9854
9899
|
if (i && i.length) {
|
|
9855
|
-
let e =
|
|
9900
|
+
let e = Md(o()?.get?.().bind, t, i);
|
|
9856
9901
|
if (e.size) {
|
|
9857
|
-
let t =
|
|
9902
|
+
let t = Ad(s, n);
|
|
9858
9903
|
if (t && !e.has(t)) return {
|
|
9859
9904
|
content: `PATH_DENIED · vfs 越界:当前聚焦代码文件 [${[...e].map((e) => `${n}${e}.${r}`).join(", ")}],你要改的 "${s}" 不在其中。请只改焦点组件的代码文件;如需改其他组件,请在收口回复中说明需先取消聚焦(焦点由主会话/用户管理,你无 focus 工具)后重试。`,
|
|
9860
9905
|
status: "error"
|
|
@@ -9864,9 +9909,9 @@ function Ad(e) {
|
|
|
9864
9909
|
}
|
|
9865
9910
|
let l = await i(e);
|
|
9866
9911
|
if (c) {
|
|
9867
|
-
let t = e.state[
|
|
9912
|
+
let t = e.state[yd];
|
|
9868
9913
|
t && t.add(s);
|
|
9869
|
-
let r = e.state[
|
|
9914
|
+
let r = e.state[bd], i = Ad(s, n);
|
|
9870
9915
|
if (r && i && !r.has(i)) {
|
|
9871
9916
|
let e = (f.get(i) ?? 0) + 1;
|
|
9872
9917
|
f.set(i, e), r.set(i, e);
|
|
@@ -9877,15 +9922,15 @@ function Ad(e) {
|
|
|
9877
9922
|
afterAgent: (e) => {
|
|
9878
9923
|
let a = o(), l = a?.get?.().bind;
|
|
9879
9924
|
if (!l) return;
|
|
9880
|
-
let u = e[
|
|
9925
|
+
let u = e[yd] ?? /* @__PURE__ */ new Set();
|
|
9881
9926
|
if (u.size) {
|
|
9882
|
-
let o = e[
|
|
9883
|
-
|
|
9927
|
+
let o = e[Sd] ?? /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
|
|
9928
|
+
jd(l, t, (t) => {
|
|
9884
9929
|
let a = t.__pgId;
|
|
9885
9930
|
c.add(a);
|
|
9886
9931
|
let l = `${n}${a}.${r}`;
|
|
9887
9932
|
if (!u.has(l) && !d.has(l)) return;
|
|
9888
|
-
let p = e[
|
|
9933
|
+
let p = e[bd]?.get(a);
|
|
9889
9934
|
if (p !== void 0 && f.get(a) !== p) {
|
|
9890
9935
|
console.warn(`[page-agent-sdk][code-asset] 组件 ${t.name ?? a}(${l})已有更新的委派接管,跳过本次旧代 commit(不排队不重放;新委派的 commit 为准)`);
|
|
9891
9936
|
return;
|
|
@@ -9896,14 +9941,14 @@ function Ad(e) {
|
|
|
9896
9941
|
let r = o.get(a);
|
|
9897
9942
|
if (r !== void 0) {
|
|
9898
9943
|
let n = Q(t, i);
|
|
9899
|
-
if (typeof n != "string" ||
|
|
9944
|
+
if (typeof n != "string" || Od(n) !== r) {
|
|
9900
9945
|
console.warn(`[page-agent-sdk][code-asset] 组件 ${t.name ?? a}(${l})在修改期间被外部更新,已保留外部版本(keep_external),本次子 agent 修改未提交`);
|
|
9901
|
-
let n = e[
|
|
9902
|
-
Array.isArray(n) ? n.push(r) : e[
|
|
9946
|
+
let n = e[Cd], r = String(t.name ?? a);
|
|
9947
|
+
Array.isArray(n) ? n.push(r) : e[Cd] = [r];
|
|
9903
9948
|
return;
|
|
9904
9949
|
}
|
|
9905
9950
|
}
|
|
9906
|
-
let s =
|
|
9951
|
+
let s = vd(n.content);
|
|
9907
9952
|
if (s.length) {
|
|
9908
9953
|
console.warn(`[page-agent-sdk][code-asset] 跳过 commit 未通过校验的半成品(可能 abort/timeout 未跑完 verify):${l} - ${s[0].message}(${s[0].code})`);
|
|
9909
9954
|
return;
|
|
@@ -9915,22 +9960,22 @@ function Ad(e) {
|
|
|
9915
9960
|
}
|
|
9916
9961
|
});
|
|
9917
9962
|
for (let e of u) {
|
|
9918
|
-
let t =
|
|
9963
|
+
let t = Ad(e, n);
|
|
9919
9964
|
t && !c.has(t) && (console.warn(`[page-agent-sdk][code-asset] 组件 ${t}(${e})已被外部删除,放弃 commit 并清理 vfs 工作副本(不复活组件)`), delete s.files[e]);
|
|
9920
9965
|
}
|
|
9921
9966
|
a?.markDataDirty?.(), a?.recomputeBaseline?.();
|
|
9922
9967
|
}
|
|
9923
9968
|
if (!c) return;
|
|
9924
|
-
let p =
|
|
9969
|
+
let p = Ed(e[xd]?.text ?? "");
|
|
9925
9970
|
if (!p.length) return;
|
|
9926
9971
|
let m = [];
|
|
9927
|
-
if (
|
|
9928
|
-
(u.size === 0 || u.has(`${n}${e.__pgId}.${r}`)) && m.push(e);
|
|
9972
|
+
if (jd(l, t, (e) => {
|
|
9973
|
+
typeof Q(e, i) == "string" && (u.size === 0 || u.has(`${n}${e.__pgId}.${r}`)) && m.push(e);
|
|
9929
9974
|
}), !m.length) return;
|
|
9930
9975
|
let h = !1;
|
|
9931
9976
|
for (let e of p) {
|
|
9932
9977
|
let t = m.length === 1 ? m[0] : m.find((t) => typeof t.name == "string" && !!t.name && e.includes(t.name));
|
|
9933
|
-
t && (
|
|
9978
|
+
t && (Dd(t, [e]), h = !0);
|
|
9934
9979
|
}
|
|
9935
9980
|
h && a?.markDataDirty?.();
|
|
9936
9981
|
}
|
|
@@ -9938,7 +9983,7 @@ function Ad(e) {
|
|
|
9938
9983
|
}
|
|
9939
9984
|
//#endregion
|
|
9940
9985
|
//#region src/core/sdk/componentLock.ts
|
|
9941
|
-
function
|
|
9986
|
+
function Pd() {
|
|
9942
9987
|
let e = /* @__PURE__ */ new Map();
|
|
9943
9988
|
return {
|
|
9944
9989
|
async acquire(t, n) {
|
|
@@ -9977,7 +10022,7 @@ function jd() {
|
|
|
9977
10022
|
}
|
|
9978
10023
|
};
|
|
9979
10024
|
}
|
|
9980
|
-
function
|
|
10025
|
+
function Fd(e, t) {
|
|
9981
10026
|
if (Array.isArray(e.components) && e.components.length) {
|
|
9982
10027
|
let n = new Set(t), r = [...new Set(e.components.filter((e) => typeof e == "string" && e && n.has(e)))];
|
|
9983
10028
|
if (r.length) return {
|
|
@@ -9994,12 +10039,12 @@ function Md(e, t) {
|
|
|
9994
10039
|
via: "none"
|
|
9995
10040
|
};
|
|
9996
10041
|
}
|
|
9997
|
-
function
|
|
10042
|
+
function Id(e, t, n) {
|
|
9998
10043
|
let r = new Set(n);
|
|
9999
10044
|
if (!r.size || !e || typeof e != "object") return [];
|
|
10000
10045
|
let i = [];
|
|
10001
10046
|
for (let n of t) {
|
|
10002
|
-
let t =
|
|
10047
|
+
let t = Ld(e, n);
|
|
10003
10048
|
if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {
|
|
10004
10049
|
let a = t[e];
|
|
10005
10050
|
a && typeof a == "object" && typeof a.name == "string" && r.has(a.name) && i.push(`${n}.${e}`);
|
|
@@ -10007,7 +10052,7 @@ function Nd(e, t, n) {
|
|
|
10007
10052
|
}
|
|
10008
10053
|
return i;
|
|
10009
10054
|
}
|
|
10010
|
-
function
|
|
10055
|
+
function Ld(e, t) {
|
|
10011
10056
|
let n = e;
|
|
10012
10057
|
for (let e of t.split(".")) {
|
|
10013
10058
|
if (!n || typeof n != "object") return;
|
|
@@ -10015,26 +10060,26 @@ function Pd(e, t) {
|
|
|
10015
10060
|
}
|
|
10016
10061
|
return n;
|
|
10017
10062
|
}
|
|
10018
|
-
function
|
|
10063
|
+
function Rd(e, t) {
|
|
10019
10064
|
return t.some((t) => e === t || e.startsWith(t + "."));
|
|
10020
10065
|
}
|
|
10021
|
-
function
|
|
10066
|
+
function zd(e, t) {
|
|
10022
10067
|
let n = [];
|
|
10023
10068
|
for (let { writablePaths: r, codeField: i } of t) for (let t of r) {
|
|
10024
|
-
let r =
|
|
10069
|
+
let r = Ld(e, t);
|
|
10025
10070
|
if (Array.isArray(r)) for (let e = 0; e < r.length; e++) {
|
|
10026
10071
|
let a = r[e];
|
|
10027
|
-
a && typeof a == "object" && typeof
|
|
10072
|
+
a && typeof a == "object" && typeof Ld(a, i) == "string" && n.push(`${t}.${e}.${i}`);
|
|
10028
10073
|
}
|
|
10029
10074
|
}
|
|
10030
10075
|
return n;
|
|
10031
10076
|
}
|
|
10032
|
-
function
|
|
10077
|
+
function Bd(e) {
|
|
10033
10078
|
let t = e ?? {}, n = /* @__PURE__ */ new Set();
|
|
10034
10079
|
if (typeof t.jsonPath == "string" && t.jsonPath && n.add(t.jsonPath), typeof t.path == "string" && t.path && n.add(t.path), t.patch && typeof t.patch.jsonPath == "string" && t.patch.jsonPath && n.add(t.patch.jsonPath), Array.isArray(t.patches)) for (let e of t.patches) e && typeof e.jsonPath == "string" && e.jsonPath && n.add(e.jsonPath);
|
|
10035
10080
|
return [...n];
|
|
10036
10081
|
}
|
|
10037
|
-
function
|
|
10082
|
+
function Vd(e) {
|
|
10038
10083
|
return {
|
|
10039
10084
|
name: "component-write-guard",
|
|
10040
10085
|
wrapToolCall: async (t, n) => {
|
|
@@ -10053,9 +10098,9 @@ function Rd(e) {
|
|
|
10053
10098
|
status: "error"
|
|
10054
10099
|
};
|
|
10055
10100
|
}
|
|
10056
|
-
let a = e.getLocked(), o = Object.keys(a), s = e.getCodeFieldPaths?.() ?? [], c =
|
|
10101
|
+
let a = e.getLocked(), o = Object.keys(a), s = e.getCodeFieldPaths?.() ?? [], c = Bd(i);
|
|
10057
10102
|
if (s.length) {
|
|
10058
|
-
let t = c.filter((e) =>
|
|
10103
|
+
let t = c.filter((e) => Rd(e, s));
|
|
10059
10104
|
if (t.length) return e.onReject?.({
|
|
10060
10105
|
paths: t,
|
|
10061
10106
|
lockedPrefixes: s,
|
|
@@ -10066,7 +10111,7 @@ function Rd(e) {
|
|
|
10066
10111
|
};
|
|
10067
10112
|
}
|
|
10068
10113
|
if (!o.length) return n(t);
|
|
10069
|
-
let l =
|
|
10114
|
+
let l = Id(e.getBind(), e.writablePaths, o);
|
|
10070
10115
|
if (!l.length) return n(t);
|
|
10071
10116
|
if (!c.length) return e.onReject?.({
|
|
10072
10117
|
paths: ["(整体 set)"],
|
|
@@ -10076,7 +10121,7 @@ function Rd(e) {
|
|
|
10076
10121
|
content: `COMPONENT_LOCKED · 组件 [${o.join(", ")}] 正在被子 agent 修改,整体写入会触碰它们。请改用增量 patch(write({patch:{jsonPath,...}}))只写未锁定组件,或等委派结束后再整体操作。`,
|
|
10077
10122
|
status: "error"
|
|
10078
10123
|
};
|
|
10079
|
-
let u = c.filter((e) =>
|
|
10124
|
+
let u = c.filter((e) => Rd(e, l));
|
|
10080
10125
|
return u.length ? (e.onReject?.({
|
|
10081
10126
|
paths: u,
|
|
10082
10127
|
lockedPrefixes: l,
|
|
@@ -10090,16 +10135,16 @@ function Rd(e) {
|
|
|
10090
10135
|
}
|
|
10091
10136
|
//#endregion
|
|
10092
10137
|
//#region src/core/sdk/subtreeGuard.ts
|
|
10093
|
-
function
|
|
10138
|
+
function Hd(e) {
|
|
10094
10139
|
let t = e ?? {}, n = [];
|
|
10095
10140
|
if (t.patch && typeof t.patch.jsonPath == "string" && t.patch.jsonPath && n.push(t.patch.jsonPath), Array.isArray(t.patches)) for (let e of t.patches) e && typeof e.jsonPath == "string" && e.jsonPath && n.push(e.jsonPath);
|
|
10096
10141
|
return n;
|
|
10097
10142
|
}
|
|
10098
|
-
function
|
|
10143
|
+
function Ud(e, t) {
|
|
10099
10144
|
return e === t || e.startsWith(t + ".") || e.startsWith(t + "[");
|
|
10100
10145
|
}
|
|
10101
|
-
function
|
|
10102
|
-
let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = (e, t) => t.find((t) =>
|
|
10146
|
+
function Wd(e) {
|
|
10147
|
+
let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = (e, t) => t.find((t) => Ud(e, t));
|
|
10103
10148
|
return {
|
|
10104
10149
|
name: "subtree-write-guard",
|
|
10105
10150
|
beforeAgent: () => {
|
|
@@ -10114,11 +10159,11 @@ function Vd(e) {
|
|
|
10114
10159
|
if (a.name !== "write" || (a.args ?? {}).dryRun === !0) return o(a);
|
|
10115
10160
|
let s = e.getSummarizedPaths();
|
|
10116
10161
|
if (!s.length) return o(a);
|
|
10117
|
-
let c =
|
|
10162
|
+
let c = Hd(a.args);
|
|
10118
10163
|
if (!c.length) return o(a);
|
|
10119
10164
|
for (let e of c) {
|
|
10120
10165
|
let a = i(e, s);
|
|
10121
|
-
if (a && !([...t].some((e) =>
|
|
10166
|
+
if (a && !([...t].some((e) => Ud(e, a)) || n.has(a)) && !r.has(a)) return r.add(a), {
|
|
10122
10167
|
content: `NEED_NARROW_READ · 写路径 "${e}" 的目标子树 "${a}" 此前只见摘要占位(<subtree …>/<field Nkb>,键名可见但内容未见),直接写入易凭印象猜结构错位。请先 read({jsonPath:"${a}"}) 查看实际内容(结果根豁免返回全文;若它是大数组或内容很大,加 offset/limit 分页或 fields 裁剪、或只读要写的子路径,勿整灌上下文),再基于真实值写入;聚焦该区域也可用 set_focus。若你确认已读过,请检查路径是否写错。`,
|
|
10123
10168
|
status: "error"
|
|
10124
10169
|
};
|
|
@@ -10134,7 +10179,7 @@ function Vd(e) {
|
|
|
10134
10179
|
}
|
|
10135
10180
|
//#endregion
|
|
10136
10181
|
//#region src/core/harness/delegateNudge.ts
|
|
10137
|
-
function
|
|
10182
|
+
function Gd(e, t) {
|
|
10138
10183
|
let n = e ?? {}, r = t(), i = (e) => {
|
|
10139
10184
|
let t = e.split("."), n = [], r = 0;
|
|
10140
10185
|
for (let e of t) if (n.push(e), /^\d+$/.test(e) && (r++, r >= 1)) break;
|
|
@@ -10184,10 +10229,10 @@ function Hd(e, t) {
|
|
|
10184
10229
|
kind: o
|
|
10185
10230
|
};
|
|
10186
10231
|
}
|
|
10187
|
-
function
|
|
10232
|
+
function Kd(e) {
|
|
10188
10233
|
return e === "spawn_agent" || e === "spawn_agents" || e.startsWith("use_");
|
|
10189
10234
|
}
|
|
10190
|
-
function
|
|
10235
|
+
function qd(e) {
|
|
10191
10236
|
let t = e.threshold ?? 12, n = /* @__PURE__ */ new Set(), r = 0, i = !1, a = !1, o = () => {
|
|
10192
10237
|
let t = e.getBind();
|
|
10193
10238
|
if (!t || typeof t != "object") return 0;
|
|
@@ -10215,12 +10260,12 @@ function Wd(e) {
|
|
|
10215
10260
|
].join("\n");
|
|
10216
10261
|
},
|
|
10217
10262
|
wrapToolCall: async (o, s) => {
|
|
10218
|
-
if (
|
|
10263
|
+
if (Kd(o.name) && (i = !0), o.name !== "write") return s(o);
|
|
10219
10264
|
let c = await s(o);
|
|
10220
10265
|
if ((o.args ?? {}).dryRun === !0) return c;
|
|
10221
10266
|
let l = String(c.content ?? "");
|
|
10222
10267
|
if (!(c.status !== "error" && !l.startsWith("ERROR:") && !l.includes("未写入") && !l.includes("无需删除")) || i || a) return c;
|
|
10223
|
-
let u =
|
|
10268
|
+
let u = Gd(o.args, e.getBind);
|
|
10224
10269
|
for (let e of u.scopes) n.add(e);
|
|
10225
10270
|
u.kind === "whole-set" && (r += u.count);
|
|
10226
10271
|
let d = n.size + r;
|
|
@@ -10241,7 +10286,7 @@ function Wd(e) {
|
|
|
10241
10286
|
}
|
|
10242
10287
|
//#endregion
|
|
10243
10288
|
//#region src/core/sdk/baselineGuard.ts
|
|
10244
|
-
function
|
|
10289
|
+
function Jd(e) {
|
|
10245
10290
|
return {
|
|
10246
10291
|
name: "baseline-guard",
|
|
10247
10292
|
wrapToolCall: async (t, n) => {
|
|
@@ -10261,21 +10306,21 @@ function Gd(e) {
|
|
|
10261
10306
|
}
|
|
10262
10307
|
//#endregion
|
|
10263
10308
|
//#region src/core/sdk/diagnostics.ts
|
|
10264
|
-
var
|
|
10265
|
-
function
|
|
10309
|
+
var Yd = 5e4, Xd = 6e6;
|
|
10310
|
+
function Zd(e) {
|
|
10266
10311
|
return e.replace(/([?&][^=&?]*(?:key|token|secret|password|signature)[^=&?]*=)[^&]*/gi, "$1***");
|
|
10267
10312
|
}
|
|
10268
|
-
function
|
|
10269
|
-
if (typeof e == "string") return e.length >
|
|
10270
|
-
if (Array.isArray(e)) return e.map(
|
|
10313
|
+
function Qd(e) {
|
|
10314
|
+
if (typeof e == "string") return e.length > Yd ? e.slice(0, Yd) + `…<truncated:${e.length - Yd} chars>` : e;
|
|
10315
|
+
if (Array.isArray(e)) return e.map(Qd);
|
|
10271
10316
|
if (e && typeof e == "object") {
|
|
10272
10317
|
let t = {};
|
|
10273
|
-
for (let [n, r] of Object.entries(e)) t[n] =
|
|
10318
|
+
for (let [n, r] of Object.entries(e)) t[n] = Qd(r);
|
|
10274
10319
|
return t;
|
|
10275
10320
|
}
|
|
10276
10321
|
return e;
|
|
10277
10322
|
}
|
|
10278
|
-
function
|
|
10323
|
+
function $d(e) {
|
|
10279
10324
|
let t = Array.isArray(e.debugLogs) ? e.debugLogs : [];
|
|
10280
10325
|
return {
|
|
10281
10326
|
format: "page-agent-sdk/diagnostics",
|
|
@@ -10283,23 +10328,23 @@ function Xd(e) {
|
|
|
10283
10328
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10284
10329
|
environment: {
|
|
10285
10330
|
userAgent: typeof navigator < "u" ? navigator.userAgent : "node",
|
|
10286
|
-
url: typeof location < "u" ?
|
|
10331
|
+
url: typeof location < "u" ? Zd(location.href) : null
|
|
10287
10332
|
},
|
|
10288
10333
|
sessionId: e.sessionId ?? null,
|
|
10289
10334
|
usage: e.usage ?? null,
|
|
10290
10335
|
pendingConflict: e.pendingConflict ?? null,
|
|
10291
10336
|
dataSummary: e.dataSummary ?? null,
|
|
10292
|
-
info: e.info ?
|
|
10293
|
-
messages: (e.messages ?? []).map(
|
|
10294
|
-
debugLogs: t.map(
|
|
10337
|
+
info: e.info ? Qd(e.info) : null,
|
|
10338
|
+
messages: (e.messages ?? []).map(Qd),
|
|
10339
|
+
debugLogs: t.map(Qd),
|
|
10295
10340
|
extra: e.extra ?? null
|
|
10296
10341
|
};
|
|
10297
10342
|
}
|
|
10298
|
-
function
|
|
10343
|
+
function ef(e) {
|
|
10299
10344
|
let t = JSON.stringify(e);
|
|
10300
|
-
if (t.length <=
|
|
10345
|
+
if (t.length <= Xd) return t;
|
|
10301
10346
|
let n = Array.isArray(e.debugLogs) ? e.debugLogs : [], r = 0;
|
|
10302
|
-
for (; t.length >
|
|
10347
|
+
for (; t.length > Xd && n.length > 1;) {
|
|
10303
10348
|
let i = Math.max(1, Math.floor(n.length / 2));
|
|
10304
10349
|
n.splice(0, i), r += i, t = JSON.stringify(e);
|
|
10305
10350
|
}
|
|
@@ -10309,13 +10354,13 @@ function Zd(e) {
|
|
|
10309
10354
|
data: {
|
|
10310
10355
|
stage: "diagnostics_truncated",
|
|
10311
10356
|
droppedOldestLogs: r,
|
|
10312
|
-
reason: `report > ${
|
|
10357
|
+
reason: `report > ${Xd} chars`
|
|
10313
10358
|
}
|
|
10314
10359
|
}), t = JSON.stringify(e)), t;
|
|
10315
10360
|
}
|
|
10316
10361
|
//#endregion
|
|
10317
10362
|
//#region src/core/sdk/designSkill/skillDoc.ts
|
|
10318
|
-
var Qd = "# Web Design Engineer\n\nThis skill positions the Agent as a top-tier design engineer who crafts elegant, refined Web artifacts using HTML/CSS/JavaScript/React. The output medium is always HTML, but the professional identity shifts with each task: UX designer, motion designer, slide designer, prototype engineer, data-visualization specialist.\n\nCore philosophy: **The bar is \"stunning,\" not \"functional.\" Every pixel is intentional, every interaction is deliberate. Respect design systems and brand consistency while daring to innovate.**\n\n---\n\n## Scope\n\n✅ **Applicable**: Visual front-end deliverables (pages / prototypes / slide decks / visualizations / animations / UI mockups / design systems)\n\n❌ **Not applicable**: Back-end APIs, CLI tools, data-processing scripts, pure logic development with no visual requirements, performance tuning, and other terminal tasks\n\n---\n\n## Host Environment (page-agent-sdk adaptation)\n\n> Read this first: it reinterprets every user-interaction instruction below. This guide was written for an interactive agent; you run as a **delegated sub-agent** inside page-agent-sdk. The adaptations:\n\n- **One-shot delegation**: you receive a spec'd `task`, run to completion, and return a single final report. You **cannot converse with the user mid-run**. Wherever this guide says \"ask the user\", \"wait for confirmation\", or \"checkpoint\" (Step 1 probing, Checkpoints 1–3, ambiguous feedback): pick the **conservative, defensible default**, note the assumption, keep building, and list all assumptions in your **closing report** so the main agent / user can course-correct on the next delegation.\n- **Facts**: no network tools. The delegation `task` is authoritative; see adapted Step 0.\n- **Output form**: each component is **complete, self-contained HTML** — inline `<style>` / `<script>` blocks (centralized, extractable), renderable standalone; external CDN JS/CSS only when the task calls for it. Code lands through your code-asset workflow (vfs working copy / write) and must pass `validate_code` before you finish.\n- **Scale**: usually **one component per delegation**, not a multi-file project. Treat file-management guidance below (descriptive filenames, v2 copies, `assets/` dirs, `brand-spec.md`) as moot; React patterns are kept from upstream for reference — **default to vanilla HTML/CSS/JS**, zero build steps.\n- **v0 / checkpoints**: \"show a v0 early\" translates to: state your design-system declaration (Step 3 block, condensed) in the closing report — not a mid-run pause.\n- **Verification**: you cannot open a browser console — the framework's `validate_code` / render check covers structural verification; run the Step-7 checklist mentally against the code you wrote.\n\n---\n\n## Workflow\n\n### Step 0: Verify Facts Before Anything Else\n\n> **SDK adaptation**: you have no network tools — skip the upstream WebSearch protocol. The delegation `task` is your source of facts. If it names a specific product / brand / version / dated event you cannot verify from the task or context, **do not assert specifics from training data**: implement the stated intent and flag the unverified spec in your closing report (e.g. \"assumed v2 pricing — unverified\"). Never fabricate specs, versions, release status, or stats.\n\n### Step 1: Understand the Requirements (judge the gap, then default deliberately)\n\nYou cannot ask the user — a delegation that stops to ask wastes the whole run. Instead, judge **how large the information gap** is, fill every gap with a **conservative, high-quality default**, and report the assumptions:\n\n- Task already spec'd (visual + content + interaction, like a good delegation task) → **no gap: follow it exactly**; don't re-design around it.\n- Turning an existing component / screenshot into a variant → small gap: only intent may be unclear — default conservatively, match the existing visual vocabulary.\n- \"Make it look great\" with no tone / audience / context → large gap: pick the school + recipe deliberately (Step 2 priority list below), state every assumption.\n- Genuinely vague (\"something nice\", \"I don't know what style\") → run the **Design Direction Advisor** below internally: pick 3 differentiated directions, implement the most conservative one that fits the task, mention the two alternatives in your closing report.\n\nKey areas to default consciously (mirror of upstream probing list):\n- **Product context**: What product? Target users? Existing design system / brand guidelines?\n- **Output type**: Web page / prototype / slide deck / animation / dashboard? Fidelity level?\n- **Variation dimensions**: Which dimensions should variants explore — layout, color, interaction, copy? How many?\n- **Constraints**: Responsive breakpoints? Dark/light mode? Accessibility? Fixed dimensions?\n\n### Step 2: Gather Design Context (by priority)\n\nGood design is rooted in existing context. **Never start from thin air.** Priority order:\n\n1. **Resources the user proactively provides** (screenshots / Figma / codebase / UI Kit / design system) → read them thoroughly and extract tokens\n2. **Existing pages of the user's product** → match their visual vocabulary (see \"When Adding to an Existing UI\" below)\n3. **Industry best practices** → ask which brands or products to use as reference\n4. **User names an anchor** (\"make it Linear-style\" / \"Aesop feeling\" / \"MUJI quietness\") → read the single recipe file at `references/style-recipes/<anchor>.md` (e.g., `references/style-recipes/linear.md`). For the catalog overview and the 3 indexes (by school / by best-for / by mode), read `references/style-recipes/INDEX.md` first.\n5. **Starting from scratch** → establish a temporary system based on industry best practices, or pick a recipe from `references/style-recipes/` (browse via `INDEX.md`) — and state the choice as an assumption in your closing report\n\nWhen analyzing reference materials, focus on: color system, typography scheme, spacing system, border-radius strategy, shadow hierarchy, motion style, component density, copywriting tone.\n\n> **Code ≫ Screenshots**: When the user provides both a codebase and screenshots, invest your effort in reading source code and extracting design tokens rather than guessing from screenshots — rebuilding/editing an interface from code yields far higher quality than from screenshots.\n\n#### When the Task Involves a Specific Brand — Asset Protocol\n\n**Asset > Spec.** A brand's identity is \"being recognized.\" Recognition is driven by assets in this order — **not by hex codes**:\n\n| Asset | Recognition contribution | When required |\n|---|---|---|\n| **Logo** (SVG / PNG, both light & dark variants if available) | Highest — any brand is identified by its logo | **Any brand task** — non-negotiable |\n| **Product imagery** (hero shots, detail, in-context) | Very high — physical products' \"main character\" *is* the product itself | **Physical products** (hardware, packaging, consumer goods) |\n| **UI screenshots** (latest version, real data scrubbed) | Very high — digital products' \"main character\" *is* the interface | **Digital products** (apps, SaaS, websites) |\n| Color tokens | Medium — auxiliary; without the assets above, brands collide | Auxiliary |\n| Typography | Low — needs the above to land | Auxiliary |\n\n**Hard rules**:\n\n- **Don't substitute CSS silhouettes / hand-drawn SVG for real product imagery** — the result is generic \"tech aesthetic\" any brand could wear (zero recognition value, the #1 way branded work fails)\n- **Logo is non-negotiable** — in delegation you cannot fetch one: if the task provides no logo asset, use an honest placeholder (see \"Placeholder Philosophy\") and flag the gap in your closing report — do **not** proceed with a colored rectangle as if it were a logo\n- **Color hex codes alone are not a brand** — they're the cheapest part of the identity\n- All available assets must be referenced via `<img src=\"…\">` as provided in the task / context map, not redrawn\n\n#### When Adding to an Existing UI\n\nThis is more common than designing from scratch. **Understand the visual vocabulary first, then act**:\n\n- **Color & tone**: The actual usage ratio of primary / neutral / accent colors? Does the copy feel engineer-oriented, marketing-oriented, or neutral?\n- **Interaction details**: The feedback style for hover / focus / active states (color shift / shadow / scale / translate)?\n- **Motion language**: Easing function preferences? Duration? Are transitions handled with CSS transition, CSS animation, or JS?\n- **Structural language**: How many elevation levels? Card density — sparse or dense? Border-radius uniform or hierarchical? Common layout patterns (split pane / cards / timeline / table)?\n- **Graphics & iconography**: Icon library in use? Illustration style? Image treatment?\n\nMatching the existing visual vocabulary is the prerequisite for seamless integration; newly added elements should be **indistinguishable from the originals**.\n\n### Step 3a: Position Four Questions Before Picking a System\n\n**Before listing color/typography/spacing tokens**, articulate four positioning questions for each artifact (or each slide / screen / scene):\n\n- **Narrative role**: Hero / transition / data / pull-quote / closing? (Each demands a different visual register.)\n- **Viewing distance**: 10cm phone / 1m laptop / 10m projector? (Drives type scale and information density.)\n- **Visual temperature**: Quiet / energized / authoritative / warm / somber / playful?\n- **Capacity check**: Mentally sketch the rough thumbnail — does the content fit the layout, or will it overflow / look too sparse?\n\nThe system that follows must serve these answers. Picking aesthetics in a vacuum is the root cause of generic output.\n\n### Step 3: Declare the Design System Before Writing Code\n\n**Before writing the first line of code**, articulate the design system in Markdown (in delegation: state it in your closing report — no mid-run pause):\n\n```markdown\nDesign Decisions:\n- Anchor / recipe (if any): [e.g., \"linear\" → `references/style-recipes/linear.md`, or \"custom\"]\n- Color palette: [primary / secondary / neutral / accent]\n- Typography: [heading font / body font / code font]\n- Spacing system: [base unit and multiples]\n- Border-radius strategy: [large / small / sharp]\n- Shadow hierarchy: [elevation 1–5]\n- Motion style: [easing curves / duration / trigger]\n```\n\n> If you picked a recipe from `references/style-recipes/`, paste its concrete palette / typography / spacing / radius / shadow / motion values straight into the block above — that catalog exists so you don't have to invent these on the fly, which is the leading cause of AI-default Inter + #3b82f6 mush. **Load only the one recipe file you're using**, not the whole catalog.\n\n### Step 4: Show a v0 Draft Early\n\n> **SDK adaptation**: in delegation this collapses into the closing report — include the (condensed) design-system declaration and the key structural choices there, so the main agent / user can course-correct on the next round. Build straight to the real thing; don't ship a placeholder skeleton as your final output.\n\nThe v0 mindset still applies *within* the build: lock the tone / layout direction first (design-system declaration), then flesh out content details, states, and motion.\n\n### Step 5: Full Build\n\nWrite full components, add states, and implement motion. Follow the technical specifications and design principles below.\n\n### Step 6: Verification\n\nWalk through the \"Pre-delivery Checklist\" item by item (mentally, against the code — you cannot open a browser console; `validate_code` / render check covers structure).\n\n### Step 7: Critique on Request (or as Self-Check Before Delivery)\n\nWhen the task asks \"review this\", \"is it good?\", \"score this\", \"好不好看\", or as a self-check before declaring done, run a **5-dimension critique**:\n\n| Dimension | What to evaluate |\n|---|---|\n| **Philosophy alignment** | Does every detail trace back to the chosen design direction? Or has it drifted into a generic mishmash? |\n| **Visual hierarchy** | Does the eye flow where intended? Squint test passes? Title/body ratio ≥ 2.5×? |\n| **Craft quality** | Pixel-level alignment, consistent spacing system (e.g., 8pt grid), controlled color count (≤ 4), font families ≤ 2 |\n| **Functionality** | Does each element earn its place? \"If I delete this, does the design get worse?\" If no → delete |\n| **Originality** | Avoids clichés while staying coherent? Any \"unexpected but right\" decisions, or pure template? |\n\nScore each 0–10. Output format:\n\n```markdown\n## Design Critique\n\n**Overall: X.X / 10** [Excellent (8+) / Good (6–7.9) / Needs work (4–5.9) / Failing (<4)]\n\n**By dimension**: Philosophy X / Hierarchy X / Craft X / Functionality X / Originality X\n\n### Keep\n- [Specific things done well, in design language]\n\n### Fix (sorted by severity)\n1. **[Issue name]** — ⚠️ Critical / ⚡ Important / 💡 Polish\n - Current: [what it looks like now]\n - Why: [why it's a problem]\n - Fix: [concrete change with values]\n\n### Quick Wins (top 3 if you only have 5 minutes)\n- [ ] [Highest-impact fix]\n- [ ] [Second]\n- [ ] [Third]\n```\n\n**Critique the design, not the designer.** For per-output-type weighting, common-issue catalog, and detailed scoring rubrics → see `references/critique-guide.md`.\n\n---\n\n## Fallback: Design Direction Advisor\n\n**When to trigger**:\n- The request is genuinely ambiguous (\"make something nice\", \"I don't know what style I want\", \"give me some directions\")\n- No design context exists, and no reference material is available\n- The task explicitly asks for \"a style\" / \"some directions\" / \"a vibe\"\n\n**When to skip**:\n- The task already provided brand / screenshot / style reference → go straight to the main workflow\n- The task stated a specific direction (\"make an Apple-Silicon-style launch animation\") → main workflow\n- Small tweaks → skip\n\n### Mechanism: 3 differentiated directions, not 10 questions\n\nDon't enumerate 10 generic taste questions. Instead, formulate **3 design directions** that come from clearly different schools — so the contrast is visible and the choice is meaningful. Each direction must include:\n\n- **A named designer or studio reference** (e.g., \"Pentagram-style information architecture\", not just \"minimalist\")\n- **2–3 lines of why this direction fits the task's context**\n- **Signature visual cues** (3–4 concrete details: color, typography, layout, motion)\n- **Optional**: one famous touchstone work\n\nIn delegation: implement the most conservative fitting direction, and list all three in the closing report as alternatives for the next round.\n\n### School library — pick 3 from different rows\n\n| School | Vibe | Sample anchors | Best for |\n|---|---|---|---|\n| **Information architecture** | Rational, data-driven, restrained | Pentagram, Edward Tufte, Massimo Vignelli, Bloomberg Terminal | Safe / professional / B2B / data products |\n| **Editorial / minimalist** | Whitespace, refined typography, quiet luxury | Kenya Hara (MUJI), Apple HIG, Dieter Rams, Aesop | Premium / high-end / quiet |\n| **Modern tool / Builder SaaS** | Hairline detail, warm dark, single accent, monospace chips | Linear, Vercel, Raycast, Notion | Developer tools / B2B SaaS / AI tools / infra |\n| **Motion / experimental** | Bold, generative, sensory | Field.io, Active Theory, Resn | Distinctive / launch films / brand moments |\n| **Brutalist / raw** | Anti-design, honest, unpolished | Balenciaga, Are.na, Bloomberg Businessweek covers | Differentiated / confident / counter-culture |\n| **Warm humanist** | Approachable, organic, hand-touched | Mailchimp (early), Stripe Press, Headspace | Lifestyle / education / approachable B2C / wellness |\n\n❌ **Hard rule**: never pick 3 from the same row — the contrast that makes the choice meaningful collapses.\n\n### After a direction is picked\n\nThe chosen direction becomes the design context for Step 2 onward. Surface 2–3 named recipes from that school by reading the matching files in `references/style-recipes/` (e.g., picked *Information Architecture* → read `references/style-recipes/pentagram.md`, `references/style-recipes/bloomberg-terminal.md`). Each recipe file brings concrete palette, typography, spacing, and signature moves you can paste into the Step 3 design-system declaration.\n\n> Extended philosophy library, per-school anchor tables, and AI-prompt templates → `references/design-directions.md`. Anchored recipe catalog → `references/style-recipes/INDEX.md` (catalog index + 3 indexes + cross-cutting anti-patterns) + 25 single-recipe files alongside it.\n\n---\n\n## Technical Specifications\n\n### React + Babel (Inline JSX)\n\nFor React prototypes, use **pinned-version** CDN scripts with `integrity` hashes — see the exact `<script>` tags in `references/advanced-patterns.md`. Do not change versions, do not add `type=\"module\"` (breaks the Babel transpilation pipeline). Import order: React → ReactDOM → Babel → your component files.\n\n> **SDK adaptation**: React remains upstream reference material; in page-agent-sdk components, **default to vanilla HTML/CSS/JS** (self-contained, zero build) unless the task explicitly demands React.\n\n#### Three Non-negotiable Hard Rules\n\n**1. Never use `const styles = { ... }`** — multiple component files with `styles` as a global object will silently overwrite each other. Always namespace: `const terminalStyles = { ... }`, `const headerStyles = { ... }`. Or use inline `style={{...}}` directly. **Never use `styles` as a variable name.**\n\n**2. Separate `<script type=\"text/babel\">` blocks do not share scope** — each Babel script is compiled independently. To share components across files, explicitly attach them to `window` at the end of each file: `Object.assign(window, { Terminal, Line });`\n\n**3. Do not use `scrollIntoView`** — in iframe-embedded preview environments, it disrupts outer-frame scrolling. Use `element.scrollTop = ...` or `window.scrollTo({...})` instead.\n\n### CSS Best Practices\n\n- Prefer CSS Grid + Flexbox for layout\n- Manage design tokens with CSS custom properties\n- **Prefer brand colors for palette**; when more colors are needed, derive harmonious variants using `oklch()` — **never invent new hues from scratch**\n- Use `text-wrap: pretty` for better line breaking\n- Use `clamp()` for fluid typography\n- Use `@container` queries for component-level responsiveness\n- Leverage `@media (prefers-color-scheme)` and `@media (prefers-reduced-motion)`\n\n### File Management\n\n> **SDK adaptation**: you have no filesystem and usually build one self-contained component per delegation — this section is upstream reference. Naming/versioning is handled by the host data model (component name / `__pgId`), not by you.\n\n---\n\n## Design Principles\n\n### Avoid AI-Style Clichés (the WHY matters)\n\nAnti-cliché is **not aesthetic snobbery** — it's protecting the user's brand recognition. The reasoning chain:\n\n1. The user wants their brand to be recognized\n2. AI defaults = average of training data = all brands averaged together = **no brand recognized**\n3. So AI-default output dilutes the user's identity into \"yet another AI-generated page\"\n\nThis is why the only legitimate exception to every anti-cliché rule below is **\"the brand spec uses it\"** — at that point it stops being slop and becomes a brand signature.\n\n| Pattern | Why it's slop | When it's actually fine |\n|---|---|---|\n| Aggressive purple → pink → blue gradient | The \"tech vibe\" formula AI training data converged on; on every SaaS / AI / web3 landing page | The brand itself uses it, or the task is satirizing this aesthetic |\n| Rounded card + colored left-border accent | Material/Tailwind era leftover; now visual noise in every dashboard | The user explicitly asks, or the brand spec preserves it |\n| Emoji as icon substitute | \"Not professional → slap emoji on it\" tic from training data | The brand uses emoji (Notion, Slack, early Linear), or audience is kids / casual |\n| SVG-drawn imagery (faces, scenes, objects) | AI-drawn SVG humans always have misaligned features and feel cheap | **Almost never** — use real images, AI-generated images, or honest placeholder |\n| CSS silhouette substituting for real product imagery | Generic \"tech aesthetic\" — same look across every brand | **Never** for branded work — go fetch the real product image |\n| Inter / Roboto / Arial / Fraunces / system-ui as display | Too common; reads as \"demo page\" rather than \"designed product\" | The brand spec specifies these (and usually with custom adjustments) |\n| Cyber-neon on `#0D1117` dark | GitHub-dark cosplay; baseline noise in dev-tool clones | The brand actually lives in this aesthetic |\n| Fabricated stats, fake logo walls, dummy testimonials | Damages credibility; users notice when numbers don't match reality | **Never** — use placeholders that say \"real data needed\" |\n\n### Emoji Rules\n\n**No emoji by default.** Only use emoji when the target design system/brand itself uses them (e.g., Notion, early Linear, certain consumer brands), and match their density and context precisely.\n\n- ❌ Using emoji as icon substitutes (\"I don't have an icon library, so I'll use 🚀 ⚡ ✨ as fillers\")\n- ❌ Using emoji as decorative filler (\"let's add an emoji before the heading to make it lively\")\n- ✅ No icon available → use a placeholder (see \"Placeholder Philosophy\" below) to signal that a real icon is needed\n- ✅ The brand itself uses emoji → follow the brand\n\n---\n\n### Placeholder Philosophy\n\n**When you lack icons, images, or components, a placeholder is more professional than a poorly drawn fake.**\n\n- Missing icon → square + label (e.g., `[icon]`, `▢`)\n- Missing avatar → initial-letter circle with a color fill\n- Missing image → a placeholder card with aspect-ratio info (e.g., `16:9 image`)\n- Missing data → use explicit \"real data needed\" placeholders; never fabricate\n- Missing logo → honest placeholder + flag in closing report (see Asset Protocol); never substitute \"brand name in a colored box\" for a logo on branded work\n\nA placeholder signals \"real material needed here.\" A fake signals \"I cut corners.\"\n\n### Aim to Stun\n\n- Play with proportion and whitespace to create visual rhythm\n- Bold type-size contrast (a 4–6× ratio between h1 and body text is normal)\n- Use color fills, textures, layering, and blend modes to create depth\n- Experiment with unconventional layouts, novel interaction metaphors, and thoughtful hover states\n- Use CSS animations + transitions for polished micro-interactions (button press, card hover, entry animations)\n- Use SVG filters, `backdrop-filter`, `mix-blend-mode`, `mask`, and other advanced CSS to create memorable moments\n\nCSS, HTML, JS, and SVG are far more capable than most people realize — **use them to astonish the user**.\n\n### Appropriate Scale\n\n| Context | Minimum Size |\n|---|---|\n| 1920×1080 presentations | Text ≥ 24px (ideally larger) |\n| Mobile mockups | Touch targets ≥ 44px |\n| Print documents | ≥ 12pt |\n| Web body text | Start at 16–18px |\n\n### Content Principles\n\n- **No filler content** — every element must earn its place\n- **Don't add sections unilaterally** — implement what the task specifies; if more content seems needed, note it in the closing report instead of padding\n- **Placeholders > fabricated data** — fake data damages credibility more than admitting a gap\n- **Less is more** — \"1,000 no's for every yes\"; whitespace is design\n- If the page looks empty → it's a layout problem, not a content problem. Solve it with composition, whitespace, and type-scale rhythm, not by stuffing content in\n\n---\n\n## Output Type Guidelines\n\n### Interactive Prototypes\n\n- **No title screen / cover page** — prototypes should center in the viewport or fill it (with sensible margins), letting the user see the product immediately\n- Use device frames (iPhone / Android / browser window) to enhance realism (see references file)\n- Implement key interaction paths so the user can click through them\n- Complete state coverage: default / hover / active / focus / disabled / loading / empty / error\n\n### HTML Slide Decks / Presentations\n\n- Fixed canvas at 1920×1080 (16:9), auto-fitted to any viewport via JS `transform: scale()`\n- Centered with letterbox bars; prev/next buttons placed **outside** the scaled container (to remain usable on small screens)\n- Keyboard navigation: ← → to change slides, Space for next\n- **Slide numbering is 1-indexed**: use labels like `01 Title`, `02 Agenda`, matching human speech (\"slide 5\" corresponds to label `05` — never use 0-indexed labels that cause off-by-one confusion)\n- Each slide should have a `data-screen-label` attribute for easy reference\n- Don't cram too much text — visuals lead, text supports; use at most 1–2 background colors per deck\n\n### Data Visualization Dashboards\n\n- Chart.js (simple) or D3.js (complex custom) — loaded via CDN\n- Responsive chart containers (`ResizeObserver`)\n- Provide dark/light mode toggle where it fits\n- Focus on **data-ink ratio**: remove unnecessary gridlines, 3D effects, and shadows; let the data speak\n- Color encoding should carry semantic meaning (up/down / category / time), not serve as decoration\n\n### Animation / Video Demos\n\nChoose animation approach by complexity, from simplest to heaviest — don't reach for a heavy library from the start:\n\n1. **CSS transitions / animations** — sufficient for 80% of micro-interactions (button press, card hover, fade-in entry, state toggle)\n2. **Simple state + setTimeout / requestAnimationFrame** — simple frame-by-frame or event-driven animations\n3. **Custom timeline engine** (full implementation in references) — timeline-driven video/demo scenes: scrubber, play/pause, multi-segment choreography\n4. **Fallback: Popmotion** (`https://unpkg.com/popmotion@11.0.5/dist/popmotion.min.js`) — only if the above three layers genuinely can't cover the use case\n\n> Avoid Framer Motion / GSAP / Lottie unless explicitly requested — bundle overhead and version conflicts. Always provide play/pause + scrubber, and skip \"title screen\" intros — go straight to content.\n\n### Static Visual Comparison vs. Full Flow\n\n- **Pure visual comparison** (button colors, typography, card styles) → use a design canvas to display options side by side\n- **Interactions, flows, multi-option scenarios** → build a full clickable prototype + expose options as Tweaks\n\n---\n\n## Variant Exploration Philosophy\n\nProviding multiple variants is about **exhausting possibilities so the user can mix and match**, not about delivering the perfect option.\n\nExplore \"atomic variants\" across at least these dimensions — mixing conservative, safe options with bold, novel ones:\n\n1. **Layout**: content organization (split pane / card grid / list / timeline)\n2. **Visual**: color palette, typography, texture, layering\n3. **Interaction**: motion, feedback, navigation patterns\n4. **Creative**: convention-breaking metaphors, novel UX, strong visual concepts\n\nStrategy: **Start the first few variants safely within the design system; then progressively push boundaries.** In delegation, prefer the safe-but-excellent end unless the task asks for boldness — radical exploration belongs in the reported alternatives, not in the delivered build.\n\n---\n\n## Tweaks Panel (Live Parameter Adjustment)\n\nLet users adjust design parameters in real time: theme color, font size, dark mode, spacing, component variants, content density, animation toggles, etc.\n\nDesign guidelines:\n- A floating panel in the bottom-right corner (see the reference implementation)\n- Title consistently labeled **\"Tweaks\"**\n- **Completely hidden** when closed, ensuring the design looks final during presentations\n- In multi-variant scenarios, expose variants as dropdowns/toggles within Tweaks instead of creating multiple files\n- Even if the task doesn't ask for tweaks, consider 1–2 creative ones (to expose interesting possibilities) — but skip entirely for small components where a floating panel would pollute the design\n\n---\n\n## Common CDN Resources\n\n**Default to hand-written CSS.** Only load a CDN when the scenario clearly calls for it — never include everything by default.\n\n| When clearly needed | Library |\n|---|---|\n| Charts (line / bar / pie) | Chart.js (`https://cdn.jsdelivr.net/npm/chart.js`) |\n| Complex custom visualizations | D3 v7 (`https://d3js.org/d3.v7.min.js`) |\n| Custom typography | Google Fonts (avoid Inter / Roboto / Arial / Fraunces / system-ui as display) |\n\n| Use only on explicit request or throwaway prototypes | Why |\n|---|---|\n| Tailwind CDN | Conflicts with the \"declare design tokens first\" workflow |\n| Lucide Icons CDN | Prefer placeholders over inserting icons \"to look complete\" when no icon library was specified |\n\n> React + Babel pinned CDN script tags → `references/advanced-patterns.md`. Do not change versions.\n\n---\n\n## Pre-delivery Checklist\n\nComplete the following before considering the work delivered (all items must pass):\n\n- [ ] **Facts**: any product/brand/version spec that couldn't be verified is flagged in the closing report — not asserted, not fabricated\n- [ ] **If the task is branded**: logo/product imagery come from task-provided assets via `<img src>` (or honest placeholder + flag), never CSS silhouettes or redrawn SVG for real imagery\n- [ ] Code passes `validate_code` (structure) — the framework's render check is the console-error proxy\n- [ ] Renders correctly on **target devices/viewports** (responsive web → mobile / tablet / desktop; slide decks/video with fixed dimensions → scaling container adapts without distortion)\n- [ ] **Interactive components** (buttons, links, inputs, cards, etc.) include states as appropriate: hover / focus / active / disabled / loading; empty/error states added where the scenario warrants them\n- [ ] No text overflow or truncation; `text-wrap: pretty` applied\n- [ ] All colors come from the design system declared in Step 3 — **no rogue hues introduced**\n- [ ] No use of `scrollIntoView`\n- [ ] No AI clichés (purple-pink gradients, emoji abuse, left-border accent cards, Inter/Roboto) — unless the brand spec explicitly uses them\n- [ ] No filler content, no fabricated data\n- [ ] Semantic naming, clean structure, easy to modify later\n- [ ] Visual quality at Dribbble / Behance showcase level\n- [ ] **Closing report**: condensed design-system declaration + assumptions/flags + (optionally) critique score and alternatives\n\n---\n\n## Collaborating with the User\n\n- **Report work-in-progress thinking**: your closing report carries the v0 role — design-system declaration, key decisions, assumptions\n- Explain decisions using **design language** (\"I tightened the spacing to create a tool-like feel\"), not technical language\n- When the task is ambiguous, state how you read it and what you'd do differently under another reading — the next delegation can pivot\n- Offer alternatives and creative options in the report so the user sees the boundaries of what's possible\n- When summarizing, **only mention important caveats and next steps** — don't recap what you did; the code speaks for itself\n\n---\n\n## References Routing\n\nRead on demand based on task type — don't preload everything (load via `load_skill('web-design-engineer', ref='<name>')`):\n\n| Task | Read |\n|---|---|\n| Slide engine, device frames, Tweaks panel, animation timeline, design canvas, dark mode, data viz, oklch color system, font recommendations | `references/advanced-patterns.md` |\n| Vague request → recommend 3 design directions; extended philosophy library + per-direction visual recipes + AI-prompt templates | `references/design-directions.md` |\n| Task names an anchor (\"Linear-style\" / \"Aesop feeling\") → load **only that one file** | `references/style-recipes/<anchor>.md` (e.g., `linear.md`, `aesop.md`) |\n| Browse the recipe catalog / compare options after Direction Advisor picks a school | `references/style-recipes/INDEX.md` (3 indexes + cross-cutting anti-patterns; then read 1–3 specific recipe files) |\n| Critique mode — detailed scoring rubrics, per-output-type weighting, common-issue catalog (top 10) | `references/critique-guide.md` |\n", $d = [
|
|
10363
|
+
var tf = "# Web Design Engineer\n\nThis skill positions the Agent as a top-tier design engineer who crafts elegant, refined Web artifacts using HTML/CSS/JavaScript/React. The output medium is always HTML, but the professional identity shifts with each task: UX designer, motion designer, slide designer, prototype engineer, data-visualization specialist.\n\nCore philosophy: **The bar is \"stunning,\" not \"functional.\" Every pixel is intentional, every interaction is deliberate. Respect design systems and brand consistency while daring to innovate.**\n\n---\n\n## Scope\n\n✅ **Applicable**: Visual front-end deliverables (pages / prototypes / slide decks / visualizations / animations / UI mockups / design systems)\n\n❌ **Not applicable**: Back-end APIs, CLI tools, data-processing scripts, pure logic development with no visual requirements, performance tuning, and other terminal tasks\n\n---\n\n## Host Environment (page-agent-sdk adaptation)\n\n> Read this first: it reinterprets every user-interaction instruction below. This guide was written for an interactive agent; you run as a **delegated sub-agent** inside page-agent-sdk. The adaptations:\n\n- **One-shot delegation**: you receive a spec'd `task`, run to completion, and return a single final report. You **cannot converse with the user mid-run**. Wherever this guide says \"ask the user\", \"wait for confirmation\", or \"checkpoint\" (Step 1 probing, Checkpoints 1–3, ambiguous feedback): pick the **conservative, defensible default**, note the assumption, keep building, and list all assumptions in your **closing report** so the main agent / user can course-correct on the next delegation.\n- **Facts**: no network tools. The delegation `task` is authoritative; see adapted Step 0.\n- **Output form**: each component is **complete, self-contained HTML** — inline `<style>` / `<script>` blocks (centralized, extractable), renderable standalone; external CDN JS/CSS only when the task calls for it. Code lands through your code-asset workflow (vfs working copy / write) and must pass `validate_code` before you finish.\n- **Scale**: usually **one component per delegation**, not a multi-file project. Treat file-management guidance below (descriptive filenames, v2 copies, `assets/` dirs, `brand-spec.md`) as moot; React patterns are kept from upstream for reference — **default to vanilla HTML/CSS/JS**, zero build steps.\n- **v0 / checkpoints**: \"show a v0 early\" translates to: state your design-system declaration (Step 3 block, condensed) in the closing report — not a mid-run pause.\n- **Verification**: you cannot open a browser console — the framework's `validate_code` / render check covers structural verification; run the Step-7 checklist mentally against the code you wrote.\n\n---\n\n## Workflow\n\n### Step 0: Verify Facts Before Anything Else\n\n> **SDK adaptation**: you have no network tools — skip the upstream WebSearch protocol. The delegation `task` is your source of facts. If it names a specific product / brand / version / dated event you cannot verify from the task or context, **do not assert specifics from training data**: implement the stated intent and flag the unverified spec in your closing report (e.g. \"assumed v2 pricing — unverified\"). Never fabricate specs, versions, release status, or stats.\n\n### Step 1: Understand the Requirements (judge the gap, then default deliberately)\n\nYou cannot ask the user — a delegation that stops to ask wastes the whole run. Instead, judge **how large the information gap** is, fill every gap with a **conservative, high-quality default**, and report the assumptions:\n\n- Task already spec'd (visual + content + interaction, like a good delegation task) → **no gap: follow it exactly**; don't re-design around it.\n- Turning an existing component / screenshot into a variant → small gap: only intent may be unclear — default conservatively, match the existing visual vocabulary.\n- \"Make it look great\" with no tone / audience / context → large gap: pick the school + recipe deliberately (Step 2 priority list below), state every assumption.\n- Genuinely vague (\"something nice\", \"I don't know what style\") → run the **Design Direction Advisor** below internally: pick 3 differentiated directions, implement the most conservative one that fits the task, mention the two alternatives in your closing report.\n\nKey areas to default consciously (mirror of upstream probing list):\n- **Product context**: What product? Target users? Existing design system / brand guidelines?\n- **Output type**: Web page / prototype / slide deck / animation / dashboard? Fidelity level?\n- **Variation dimensions**: Which dimensions should variants explore — layout, color, interaction, copy? How many?\n- **Constraints**: Responsive breakpoints? Dark/light mode? Accessibility? Fixed dimensions?\n\n### Step 2: Gather Design Context (by priority)\n\nGood design is rooted in existing context. **Never start from thin air.** Priority order:\n\n1. **Resources the user proactively provides** (screenshots / Figma / codebase / UI Kit / design system) → read them thoroughly and extract tokens\n2. **Existing pages of the user's product** → match their visual vocabulary (see \"When Adding to an Existing UI\" below)\n3. **Industry best practices** → ask which brands or products to use as reference\n4. **User names an anchor** (\"make it Linear-style\" / \"Aesop feeling\" / \"MUJI quietness\") → read the single recipe file at `references/style-recipes/<anchor>.md` (e.g., `references/style-recipes/linear.md`). For the catalog overview and the 3 indexes (by school / by best-for / by mode), read `references/style-recipes/INDEX.md` first.\n5. **Starting from scratch** → establish a temporary system based on industry best practices, or pick a recipe from `references/style-recipes/` (browse via `INDEX.md`) — and state the choice as an assumption in your closing report\n\nWhen analyzing reference materials, focus on: color system, typography scheme, spacing system, border-radius strategy, shadow hierarchy, motion style, component density, copywriting tone.\n\n> **Code ≫ Screenshots**: When the user provides both a codebase and screenshots, invest your effort in reading source code and extracting design tokens rather than guessing from screenshots — rebuilding/editing an interface from code yields far higher quality than from screenshots.\n\n#### When the Task Involves a Specific Brand — Asset Protocol\n\n**Asset > Spec.** A brand's identity is \"being recognized.\" Recognition is driven by assets in this order — **not by hex codes**:\n\n| Asset | Recognition contribution | When required |\n|---|---|---|\n| **Logo** (SVG / PNG, both light & dark variants if available) | Highest — any brand is identified by its logo | **Any brand task** — non-negotiable |\n| **Product imagery** (hero shots, detail, in-context) | Very high — physical products' \"main character\" *is* the product itself | **Physical products** (hardware, packaging, consumer goods) |\n| **UI screenshots** (latest version, real data scrubbed) | Very high — digital products' \"main character\" *is* the interface | **Digital products** (apps, SaaS, websites) |\n| Color tokens | Medium — auxiliary; without the assets above, brands collide | Auxiliary |\n| Typography | Low — needs the above to land | Auxiliary |\n\n**Hard rules**:\n\n- **Don't substitute CSS silhouettes / hand-drawn SVG for real product imagery** — the result is generic \"tech aesthetic\" any brand could wear (zero recognition value, the #1 way branded work fails)\n- **Logo is non-negotiable** — in delegation you cannot fetch one: if the task provides no logo asset, use an honest placeholder (see \"Placeholder Philosophy\") and flag the gap in your closing report — do **not** proceed with a colored rectangle as if it were a logo\n- **Color hex codes alone are not a brand** — they're the cheapest part of the identity\n- All available assets must be referenced via `<img src=\"…\">` as provided in the task / context map, not redrawn\n\n#### When Adding to an Existing UI\n\nThis is more common than designing from scratch. **Understand the visual vocabulary first, then act**:\n\n- **Color & tone**: The actual usage ratio of primary / neutral / accent colors? Does the copy feel engineer-oriented, marketing-oriented, or neutral?\n- **Interaction details**: The feedback style for hover / focus / active states (color shift / shadow / scale / translate)?\n- **Motion language**: Easing function preferences? Duration? Are transitions handled with CSS transition, CSS animation, or JS?\n- **Structural language**: How many elevation levels? Card density — sparse or dense? Border-radius uniform or hierarchical? Common layout patterns (split pane / cards / timeline / table)?\n- **Graphics & iconography**: Icon library in use? Illustration style? Image treatment?\n\nMatching the existing visual vocabulary is the prerequisite for seamless integration; newly added elements should be **indistinguishable from the originals**.\n\n### Step 3a: Position Four Questions Before Picking a System\n\n**Before listing color/typography/spacing tokens**, articulate four positioning questions for each artifact (or each slide / screen / scene):\n\n- **Narrative role**: Hero / transition / data / pull-quote / closing? (Each demands a different visual register.)\n- **Viewing distance**: 10cm phone / 1m laptop / 10m projector? (Drives type scale and information density.)\n- **Visual temperature**: Quiet / energized / authoritative / warm / somber / playful?\n- **Capacity check**: Mentally sketch the rough thumbnail — does the content fit the layout, or will it overflow / look too sparse?\n\nThe system that follows must serve these answers. Picking aesthetics in a vacuum is the root cause of generic output.\n\n### Step 3: Declare the Design System Before Writing Code\n\n**Before writing the first line of code**, articulate the design system in Markdown (in delegation: state it in your closing report — no mid-run pause):\n\n```markdown\nDesign Decisions:\n- Anchor / recipe (if any): [e.g., \"linear\" → `references/style-recipes/linear.md`, or \"custom\"]\n- Color palette: [primary / secondary / neutral / accent]\n- Typography: [heading font / body font / code font]\n- Spacing system: [base unit and multiples]\n- Border-radius strategy: [large / small / sharp]\n- Shadow hierarchy: [elevation 1–5]\n- Motion style: [easing curves / duration / trigger]\n```\n\n> If you picked a recipe from `references/style-recipes/`, paste its concrete palette / typography / spacing / radius / shadow / motion values straight into the block above — that catalog exists so you don't have to invent these on the fly, which is the leading cause of AI-default Inter + #3b82f6 mush. **Load only the one recipe file you're using**, not the whole catalog.\n\n### Step 4: Show a v0 Draft Early\n\n> **SDK adaptation**: in delegation this collapses into the closing report — include the (condensed) design-system declaration and the key structural choices there, so the main agent / user can course-correct on the next round. Build straight to the real thing; don't ship a placeholder skeleton as your final output.\n\nThe v0 mindset still applies *within* the build: lock the tone / layout direction first (design-system declaration), then flesh out content details, states, and motion.\n\n### Step 5: Full Build\n\nWrite full components, add states, and implement motion. Follow the technical specifications and design principles below.\n\n### Step 6: Verification\n\nWalk through the \"Pre-delivery Checklist\" item by item (mentally, against the code — you cannot open a browser console; `validate_code` / render check covers structure).\n\n### Step 7: Critique on Request (or as Self-Check Before Delivery)\n\nWhen the task asks \"review this\", \"is it good?\", \"score this\", \"好不好看\", or as a self-check before declaring done, run a **5-dimension critique**:\n\n| Dimension | What to evaluate |\n|---|---|\n| **Philosophy alignment** | Does every detail trace back to the chosen design direction? Or has it drifted into a generic mishmash? |\n| **Visual hierarchy** | Does the eye flow where intended? Squint test passes? Title/body ratio ≥ 2.5×? |\n| **Craft quality** | Pixel-level alignment, consistent spacing system (e.g., 8pt grid), controlled color count (≤ 4), font families ≤ 2 |\n| **Functionality** | Does each element earn its place? \"If I delete this, does the design get worse?\" If no → delete |\n| **Originality** | Avoids clichés while staying coherent? Any \"unexpected but right\" decisions, or pure template? |\n\nScore each 0–10. Output format:\n\n```markdown\n## Design Critique\n\n**Overall: X.X / 10** [Excellent (8+) / Good (6–7.9) / Needs work (4–5.9) / Failing (<4)]\n\n**By dimension**: Philosophy X / Hierarchy X / Craft X / Functionality X / Originality X\n\n### Keep\n- [Specific things done well, in design language]\n\n### Fix (sorted by severity)\n1. **[Issue name]** — ⚠️ Critical / ⚡ Important / 💡 Polish\n - Current: [what it looks like now]\n - Why: [why it's a problem]\n - Fix: [concrete change with values]\n\n### Quick Wins (top 3 if you only have 5 minutes)\n- [ ] [Highest-impact fix]\n- [ ] [Second]\n- [ ] [Third]\n```\n\n**Critique the design, not the designer.** For per-output-type weighting, common-issue catalog, and detailed scoring rubrics → see `references/critique-guide.md`.\n\n---\n\n## Fallback: Design Direction Advisor\n\n**When to trigger**:\n- The request is genuinely ambiguous (\"make something nice\", \"I don't know what style I want\", \"give me some directions\")\n- No design context exists, and no reference material is available\n- The task explicitly asks for \"a style\" / \"some directions\" / \"a vibe\"\n\n**When to skip**:\n- The task already provided brand / screenshot / style reference → go straight to the main workflow\n- The task stated a specific direction (\"make an Apple-Silicon-style launch animation\") → main workflow\n- Small tweaks → skip\n\n### Mechanism: 3 differentiated directions, not 10 questions\n\nDon't enumerate 10 generic taste questions. Instead, formulate **3 design directions** that come from clearly different schools — so the contrast is visible and the choice is meaningful. Each direction must include:\n\n- **A named designer or studio reference** (e.g., \"Pentagram-style information architecture\", not just \"minimalist\")\n- **2–3 lines of why this direction fits the task's context**\n- **Signature visual cues** (3–4 concrete details: color, typography, layout, motion)\n- **Optional**: one famous touchstone work\n\nIn delegation: implement the most conservative fitting direction, and list all three in the closing report as alternatives for the next round.\n\n### School library — pick 3 from different rows\n\n| School | Vibe | Sample anchors | Best for |\n|---|---|---|---|\n| **Information architecture** | Rational, data-driven, restrained | Pentagram, Edward Tufte, Massimo Vignelli, Bloomberg Terminal | Safe / professional / B2B / data products |\n| **Editorial / minimalist** | Whitespace, refined typography, quiet luxury | Kenya Hara (MUJI), Apple HIG, Dieter Rams, Aesop | Premium / high-end / quiet |\n| **Modern tool / Builder SaaS** | Hairline detail, warm dark, single accent, monospace chips | Linear, Vercel, Raycast, Notion | Developer tools / B2B SaaS / AI tools / infra |\n| **Motion / experimental** | Bold, generative, sensory | Field.io, Active Theory, Resn | Distinctive / launch films / brand moments |\n| **Brutalist / raw** | Anti-design, honest, unpolished | Balenciaga, Are.na, Bloomberg Businessweek covers | Differentiated / confident / counter-culture |\n| **Warm humanist** | Approachable, organic, hand-touched | Mailchimp (early), Stripe Press, Headspace | Lifestyle / education / approachable B2C / wellness |\n\n❌ **Hard rule**: never pick 3 from the same row — the contrast that makes the choice meaningful collapses.\n\n### After a direction is picked\n\nThe chosen direction becomes the design context for Step 2 onward. Surface 2–3 named recipes from that school by reading the matching files in `references/style-recipes/` (e.g., picked *Information Architecture* → read `references/style-recipes/pentagram.md`, `references/style-recipes/bloomberg-terminal.md`). Each recipe file brings concrete palette, typography, spacing, and signature moves you can paste into the Step 3 design-system declaration.\n\n> Extended philosophy library, per-school anchor tables, and AI-prompt templates → `references/design-directions.md`. Anchored recipe catalog → `references/style-recipes/INDEX.md` (catalog index + 3 indexes + cross-cutting anti-patterns) + 25 single-recipe files alongside it.\n\n---\n\n## Technical Specifications\n\n### React + Babel (Inline JSX)\n\nFor React prototypes, use **pinned-version** CDN scripts with `integrity` hashes — see the exact `<script>` tags in `references/advanced-patterns.md`. Do not change versions, do not add `type=\"module\"` (breaks the Babel transpilation pipeline). Import order: React → ReactDOM → Babel → your component files.\n\n> **SDK adaptation**: React remains upstream reference material; in page-agent-sdk components, **default to vanilla HTML/CSS/JS** (self-contained, zero build) unless the task explicitly demands React.\n\n#### Three Non-negotiable Hard Rules\n\n**1. Never use `const styles = { ... }`** — multiple component files with `styles` as a global object will silently overwrite each other. Always namespace: `const terminalStyles = { ... }`, `const headerStyles = { ... }`. Or use inline `style={{...}}` directly. **Never use `styles` as a variable name.**\n\n**2. Separate `<script type=\"text/babel\">` blocks do not share scope** — each Babel script is compiled independently. To share components across files, explicitly attach them to `window` at the end of each file: `Object.assign(window, { Terminal, Line });`\n\n**3. Do not use `scrollIntoView`** — in iframe-embedded preview environments, it disrupts outer-frame scrolling. Use `element.scrollTop = ...` or `window.scrollTo({...})` instead.\n\n### CSS Best Practices\n\n- Prefer CSS Grid + Flexbox for layout\n- Manage design tokens with CSS custom properties\n- **Prefer brand colors for palette**; when more colors are needed, derive harmonious variants using `oklch()` — **never invent new hues from scratch**\n- Use `text-wrap: pretty` for better line breaking\n- Use `clamp()` for fluid typography\n- Use `@container` queries for component-level responsiveness\n- Leverage `@media (prefers-color-scheme)` and `@media (prefers-reduced-motion)`\n\n### File Management\n\n> **SDK adaptation**: you have no filesystem and usually build one self-contained component per delegation — this section is upstream reference. Naming/versioning is handled by the host data model (component name / `__pgId`), not by you.\n\n---\n\n## Design Principles\n\n### Avoid AI-Style Clichés (the WHY matters)\n\nAnti-cliché is **not aesthetic snobbery** — it's protecting the user's brand recognition. The reasoning chain:\n\n1. The user wants their brand to be recognized\n2. AI defaults = average of training data = all brands averaged together = **no brand recognized**\n3. So AI-default output dilutes the user's identity into \"yet another AI-generated page\"\n\nThis is why the only legitimate exception to every anti-cliché rule below is **\"the brand spec uses it\"** — at that point it stops being slop and becomes a brand signature.\n\n| Pattern | Why it's slop | When it's actually fine |\n|---|---|---|\n| Aggressive purple → pink → blue gradient | The \"tech vibe\" formula AI training data converged on; on every SaaS / AI / web3 landing page | The brand itself uses it, or the task is satirizing this aesthetic |\n| Rounded card + colored left-border accent | Material/Tailwind era leftover; now visual noise in every dashboard | The user explicitly asks, or the brand spec preserves it |\n| Emoji as icon substitute | \"Not professional → slap emoji on it\" tic from training data | The brand uses emoji (Notion, Slack, early Linear), or audience is kids / casual |\n| SVG-drawn imagery (faces, scenes, objects) | AI-drawn SVG humans always have misaligned features and feel cheap | **Almost never** — use real images, AI-generated images, or honest placeholder |\n| CSS silhouette substituting for real product imagery | Generic \"tech aesthetic\" — same look across every brand | **Never** for branded work — go fetch the real product image |\n| Inter / Roboto / Arial / Fraunces / system-ui as display | Too common; reads as \"demo page\" rather than \"designed product\" | The brand spec specifies these (and usually with custom adjustments) |\n| Cyber-neon on `#0D1117` dark | GitHub-dark cosplay; baseline noise in dev-tool clones | The brand actually lives in this aesthetic |\n| Fabricated stats, fake logo walls, dummy testimonials | Damages credibility; users notice when numbers don't match reality | **Never** — use placeholders that say \"real data needed\" |\n\n### Emoji Rules\n\n**No emoji by default.** Only use emoji when the target design system/brand itself uses them (e.g., Notion, early Linear, certain consumer brands), and match their density and context precisely.\n\n- ❌ Using emoji as icon substitutes (\"I don't have an icon library, so I'll use 🚀 ⚡ ✨ as fillers\")\n- ❌ Using emoji as decorative filler (\"let's add an emoji before the heading to make it lively\")\n- ✅ No icon available → use a placeholder (see \"Placeholder Philosophy\" below) to signal that a real icon is needed\n- ✅ The brand itself uses emoji → follow the brand\n\n---\n\n### Placeholder Philosophy\n\n**When you lack icons, images, or components, a placeholder is more professional than a poorly drawn fake.**\n\n- Missing icon → square + label (e.g., `[icon]`, `▢`)\n- Missing avatar → initial-letter circle with a color fill\n- Missing image → a placeholder card with aspect-ratio info (e.g., `16:9 image`)\n- Missing data → use explicit \"real data needed\" placeholders; never fabricate\n- Missing logo → honest placeholder + flag in closing report (see Asset Protocol); never substitute \"brand name in a colored box\" for a logo on branded work\n\nA placeholder signals \"real material needed here.\" A fake signals \"I cut corners.\"\n\n### Aim to Stun\n\n- Play with proportion and whitespace to create visual rhythm\n- Bold type-size contrast (a 4–6× ratio between h1 and body text is normal)\n- Use color fills, textures, layering, and blend modes to create depth\n- Experiment with unconventional layouts, novel interaction metaphors, and thoughtful hover states\n- Use CSS animations + transitions for polished micro-interactions (button press, card hover, entry animations)\n- Use SVG filters, `backdrop-filter`, `mix-blend-mode`, `mask`, and other advanced CSS to create memorable moments\n\nCSS, HTML, JS, and SVG are far more capable than most people realize — **use them to astonish the user**.\n\n### Appropriate Scale\n\n| Context | Minimum Size |\n|---|---|\n| 1920×1080 presentations | Text ≥ 24px (ideally larger) |\n| Mobile mockups | Touch targets ≥ 44px |\n| Print documents | ≥ 12pt |\n| Web body text | Start at 16–18px |\n\n### Content Principles\n\n- **No filler content** — every element must earn its place\n- **Don't add sections unilaterally** — implement what the task specifies; if more content seems needed, note it in the closing report instead of padding\n- **Placeholders > fabricated data** — fake data damages credibility more than admitting a gap\n- **Less is more** — \"1,000 no's for every yes\"; whitespace is design\n- If the page looks empty → it's a layout problem, not a content problem. Solve it with composition, whitespace, and type-scale rhythm, not by stuffing content in\n\n---\n\n## Output Type Guidelines\n\n### Interactive Prototypes\n\n- **No title screen / cover page** — prototypes should center in the viewport or fill it (with sensible margins), letting the user see the product immediately\n- Use device frames (iPhone / Android / browser window) to enhance realism (see references file)\n- Implement key interaction paths so the user can click through them\n- Complete state coverage: default / hover / active / focus / disabled / loading / empty / error\n\n### HTML Slide Decks / Presentations\n\n- Fixed canvas at 1920×1080 (16:9), auto-fitted to any viewport via JS `transform: scale()`\n- Centered with letterbox bars; prev/next buttons placed **outside** the scaled container (to remain usable on small screens)\n- Keyboard navigation: ← → to change slides, Space for next\n- **Slide numbering is 1-indexed**: use labels like `01 Title`, `02 Agenda`, matching human speech (\"slide 5\" corresponds to label `05` — never use 0-indexed labels that cause off-by-one confusion)\n- Each slide should have a `data-screen-label` attribute for easy reference\n- Don't cram too much text — visuals lead, text supports; use at most 1–2 background colors per deck\n\n### Data Visualization Dashboards\n\n- Chart.js (simple) or D3.js (complex custom) — loaded via CDN\n- Responsive chart containers (`ResizeObserver`)\n- Provide dark/light mode toggle where it fits\n- Focus on **data-ink ratio**: remove unnecessary gridlines, 3D effects, and shadows; let the data speak\n- Color encoding should carry semantic meaning (up/down / category / time), not serve as decoration\n\n### Animation / Video Demos\n\nChoose animation approach by complexity, from simplest to heaviest — don't reach for a heavy library from the start:\n\n1. **CSS transitions / animations** — sufficient for 80% of micro-interactions (button press, card hover, fade-in entry, state toggle)\n2. **Simple state + setTimeout / requestAnimationFrame** — simple frame-by-frame or event-driven animations\n3. **Custom timeline engine** (full implementation in references) — timeline-driven video/demo scenes: scrubber, play/pause, multi-segment choreography\n4. **Fallback: Popmotion** (`https://unpkg.com/popmotion@11.0.5/dist/popmotion.min.js`) — only if the above three layers genuinely can't cover the use case\n\n> Avoid Framer Motion / GSAP / Lottie unless explicitly requested — bundle overhead and version conflicts. Always provide play/pause + scrubber, and skip \"title screen\" intros — go straight to content.\n\n### Static Visual Comparison vs. Full Flow\n\n- **Pure visual comparison** (button colors, typography, card styles) → use a design canvas to display options side by side\n- **Interactions, flows, multi-option scenarios** → build a full clickable prototype + expose options as Tweaks\n\n---\n\n## Variant Exploration Philosophy\n\nProviding multiple variants is about **exhausting possibilities so the user can mix and match**, not about delivering the perfect option.\n\nExplore \"atomic variants\" across at least these dimensions — mixing conservative, safe options with bold, novel ones:\n\n1. **Layout**: content organization (split pane / card grid / list / timeline)\n2. **Visual**: color palette, typography, texture, layering\n3. **Interaction**: motion, feedback, navigation patterns\n4. **Creative**: convention-breaking metaphors, novel UX, strong visual concepts\n\nStrategy: **Start the first few variants safely within the design system; then progressively push boundaries.** In delegation, prefer the safe-but-excellent end unless the task asks for boldness — radical exploration belongs in the reported alternatives, not in the delivered build.\n\n---\n\n## Tweaks Panel (Live Parameter Adjustment)\n\nLet users adjust design parameters in real time: theme color, font size, dark mode, spacing, component variants, content density, animation toggles, etc.\n\nDesign guidelines:\n- A floating panel in the bottom-right corner (see the reference implementation)\n- Title consistently labeled **\"Tweaks\"**\n- **Completely hidden** when closed, ensuring the design looks final during presentations\n- In multi-variant scenarios, expose variants as dropdowns/toggles within Tweaks instead of creating multiple files\n- Even if the task doesn't ask for tweaks, consider 1–2 creative ones (to expose interesting possibilities) — but skip entirely for small components where a floating panel would pollute the design\n\n---\n\n## Common CDN Resources\n\n**Default to hand-written CSS.** Only load a CDN when the scenario clearly calls for it — never include everything by default.\n\n| When clearly needed | Library |\n|---|---|\n| Charts (line / bar / pie) | Chart.js (`https://cdn.jsdelivr.net/npm/chart.js`) |\n| Complex custom visualizations | D3 v7 (`https://d3js.org/d3.v7.min.js`) |\n| Custom typography | Google Fonts (avoid Inter / Roboto / Arial / Fraunces / system-ui as display) |\n\n| Use only on explicit request or throwaway prototypes | Why |\n|---|---|\n| Tailwind CDN | Conflicts with the \"declare design tokens first\" workflow |\n| Lucide Icons CDN | Prefer placeholders over inserting icons \"to look complete\" when no icon library was specified |\n\n> React + Babel pinned CDN script tags → `references/advanced-patterns.md`. Do not change versions.\n\n---\n\n## Pre-delivery Checklist\n\nComplete the following before considering the work delivered (all items must pass):\n\n- [ ] **Facts**: any product/brand/version spec that couldn't be verified is flagged in the closing report — not asserted, not fabricated\n- [ ] **If the task is branded**: logo/product imagery come from task-provided assets via `<img src>` (or honest placeholder + flag), never CSS silhouettes or redrawn SVG for real imagery\n- [ ] Code passes `validate_code` (structure) — the framework's render check is the console-error proxy\n- [ ] Renders correctly on **target devices/viewports** (responsive web → mobile / tablet / desktop; slide decks/video with fixed dimensions → scaling container adapts without distortion)\n- [ ] **Interactive components** (buttons, links, inputs, cards, etc.) include states as appropriate: hover / focus / active / disabled / loading; empty/error states added where the scenario warrants them\n- [ ] No text overflow or truncation; `text-wrap: pretty` applied\n- [ ] All colors come from the design system declared in Step 3 — **no rogue hues introduced**\n- [ ] No use of `scrollIntoView`\n- [ ] No AI clichés (purple-pink gradients, emoji abuse, left-border accent cards, Inter/Roboto) — unless the brand spec explicitly uses them\n- [ ] No filler content, no fabricated data\n- [ ] Semantic naming, clean structure, easy to modify later\n- [ ] Visual quality at Dribbble / Behance showcase level\n- [ ] **Closing report**: condensed design-system declaration + assumptions/flags + (optionally) critique score and alternatives\n\n---\n\n## Collaborating with the User\n\n- **Report work-in-progress thinking**: your closing report carries the v0 role — design-system declaration, key decisions, assumptions\n- Explain decisions using **design language** (\"I tightened the spacing to create a tool-like feel\"), not technical language\n- When the task is ambiguous, state how you read it and what you'd do differently under another reading — the next delegation can pivot\n- Offer alternatives and creative options in the report so the user sees the boundaries of what's possible\n- When summarizing, **only mention important caveats and next steps** — don't recap what you did; the code speaks for itself\n\n---\n\n## References Routing\n\nRead on demand based on task type — don't preload everything (load via `load_skill('web-design-engineer', ref='<name>')`):\n\n| Task | Read |\n|---|---|\n| Slide engine, device frames, Tweaks panel, animation timeline, design canvas, dark mode, data viz, oklch color system, font recommendations | `references/advanced-patterns.md` |\n| Vague request → recommend 3 design directions; extended philosophy library + per-direction visual recipes + AI-prompt templates | `references/design-directions.md` |\n| Task names an anchor (\"Linear-style\" / \"Aesop feeling\") → load **only that one file** | `references/style-recipes/<anchor>.md` (e.g., `linear.md`, `aesop.md`) |\n| Browse the recipe catalog / compare options after Direction Advisor picks a school | `references/style-recipes/INDEX.md` (3 indexes + cross-cutting anti-patterns; then read 1–3 specific recipe files) |\n| Critique mode — detailed scoring rubrics, per-output-type weighting, common-issue catalog (top 10) | `references/critique-guide.md` |\n", nf = [
|
|
10319
10364
|
{
|
|
10320
10365
|
name: "references/advanced-patterns.md",
|
|
10321
10366
|
description: "Code templates: device frames, slide engine, animation timeline, Tweaks panel, design canvas, dark mode, data viz, oklch color system, font picks, pinned React+CDN tags",
|
|
@@ -10461,19 +10506,19 @@ var Qd = "# Web Design Engineer\n\nThis skill positions the Agent as a top-tier
|
|
|
10461
10506
|
description: "Y2K / Frutiger Aero Retrofuturism · Late-90s / early-2000s techno-optimism: chrome, glassy bubbles, jelly translucency, lens flare",
|
|
10462
10507
|
getContent: () => "\n# y2k-retrofuturism — Y2K / Frutiger Aero Retrofuturism\n\n- **School**: Specialty / Genre\n- **Vibe**: Late-90s / early-2000s techno-optimism: chrome, glassy bubbles, jelly translucency, lens flare\n- **Best for**: Fashion / music / nostalgia-coded products, creative campaigns, anything referencing 1999–2005 internet\n- **Touchstone**: late-90s Apple iMac G3 ads, Windows Vista Aero, the original iPod aqua buttons, MySpace pages\n\n**Palette**\n- Ground: electric ice blue `#A3D5FF` or chrome silver `#E0E4EA`\n- Glass accents: cyan `#5FC9F8` → magenta `#FF66C4` (the iridescent / oil-slick gradient)\n- Chrome: brushed-steel highlights at `#C4C9D2` to `#F2F4F8`\n- Acid green pops: `#A8FF00` (used sparingly)\n- Ink: `#000000` or `#FFFFFF` depending on ground\n\n**Typography**\n- Display: a chunky rounded sans with personality — Frutiger, Eurostile, or Sharp Grotesk in heavy weight; sometimes a chrome-effect treatment\n- Body: friendly humanist sans like Frutiger or Avenir at 14–16px\n- Numerals love an LCD / digital-readout treatment for hero counters\n- Underline + sparkle treatments common on link hover\n\n**Spacing**: 4 / 8 / 16 / 24 — packed but bubbly\n\n**Radius**: gummy — 16 / 24 / 32 / 9999 (full circle). Buttons are pill-shaped jelly bubbles.\n\n**Shadow**: heavy and colored — glossy reflections, drop shadows like `0 16px 32px rgba(95, 201, 248, 0.4)`. Inner highlights to simulate glass.\n\n**Motion**: bouncy springs, glow pulses, lens flare sweeps. Anything that recalls early-Flash interactions.\n\n**Signature moves**\n- Glassy translucent buttons with an inner top highlight (faking aqua / lozenge)\n- Iridescent oil-slick gradients on hero / character imagery\n- Chrome-effect type with sparkle overlays\n- Lens flare or specular highlight on any glass surface\n- 3D / dimensional UI elements (the OS-X-Aqua dock effect)\n- Floating circular orbs / bubbles drifting in the background\n\n**Avoid**\n- Sharp corners\n- Muted / earthy palettes — Y2K is bright and synthetic\n- Restrained typography — Y2K is exuberant\n- Anything that reads as \"tasteful 2020s minimalism\"\n\n**AI prompt seed**\n> Y2K retrofuturism scene, chrome silver and ice-blue iridescent gradient background, floating glass orbs with cyan and magenta oil-slick reflections, lens flare in upper right, single bright translucent pill-shaped button, late-1990s techno-optimism vibe, 16:9.\n\n**Don't use when**\n- The brand has no nostalgic / retro / playful claim\n- The audience is enterprise / professional — this recipe is consumer-fashion-music coded\n- Long-form readability matters (Y2K is for moments, not for reading)\n\n---\n\n> **Same school — Specialty / Genre**: [`mid-century-modern`](./mid-century-modern.md) \n> **Browse all 25 recipes**: [INDEX.md](./INDEX.md)\n\n"
|
|
10463
10508
|
}
|
|
10464
|
-
],
|
|
10465
|
-
function
|
|
10509
|
+
], rf = "web-design-engineer";
|
|
10510
|
+
function af() {
|
|
10466
10511
|
return {
|
|
10467
|
-
name:
|
|
10512
|
+
name: rf,
|
|
10468
10513
|
description: "Design taste & anti-cliché system: declare the design system (palette/type/spacing/motion) before coding, avoid AI-default aesthetics (purple gradients/emoji icons/Inter), 25 named style recipes (linear/apple-hig/muji/pentagram/bloomberg-terminal…), 5-dimension critique. Load BEFORE starting any design-heavy visual work.",
|
|
10469
|
-
getContent: () =>
|
|
10470
|
-
references:
|
|
10514
|
+
getContent: () => tf,
|
|
10515
|
+
references: nf
|
|
10471
10516
|
};
|
|
10472
10517
|
}
|
|
10473
10518
|
//#endregion
|
|
10474
10519
|
//#region src/core/sdk/htmlRenderCheck.ts
|
|
10475
|
-
var
|
|
10476
|
-
function
|
|
10520
|
+
var of = /SecurityError|localStorage|sessionStorage|document\.cookie|Access is denied for this document/i;
|
|
10521
|
+
function sf(e) {
|
|
10477
10522
|
if (e.noDom) return {
|
|
10478
10523
|
verdict: "pass",
|
|
10479
10524
|
problems: [],
|
|
@@ -10496,10 +10541,10 @@ function rf(e) {
|
|
|
10496
10541
|
let e = r.lineno === void 0 ? "" : `(第 ${r.lineno} 行)`;
|
|
10497
10542
|
switch (r.type) {
|
|
10498
10543
|
case "js-error":
|
|
10499
|
-
|
|
10544
|
+
of.test(r.message) ? n.push(`storage 类错误降级为观察(沙箱 opaque origin 访问 localStorage/cookie 抛 SecurityError,非代码缺陷):${r.message}${e}`) : t.push(`JS 运行时错误:${r.message}${e}${r.source ? ` [${r.source}]` : ""}`);
|
|
10500
10545
|
break;
|
|
10501
10546
|
case "console-error":
|
|
10502
|
-
|
|
10547
|
+
of.test(r.message) ? n.push(`console.error(storage 类,沙箱假阳性降观察):${r.message}`) : t.push(`console.error:${r.message}`);
|
|
10503
10548
|
break;
|
|
10504
10549
|
case "unhandledrejection":
|
|
10505
10550
|
t.push(`未捕获的异步 Promise 拒绝(unhandledrejection):${r.message}`);
|
|
@@ -10522,7 +10567,7 @@ function rf(e) {
|
|
|
10522
10567
|
metrics: e.metrics
|
|
10523
10568
|
};
|
|
10524
10569
|
}
|
|
10525
|
-
function
|
|
10570
|
+
function cf(e) {
|
|
10526
10571
|
return [
|
|
10527
10572
|
"(function(){",
|
|
10528
10573
|
`var N=${JSON.stringify(e)};`,
|
|
@@ -10549,23 +10594,23 @@ function af(e) {
|
|
|
10549
10594
|
"})();"
|
|
10550
10595
|
].join("\n");
|
|
10551
10596
|
}
|
|
10552
|
-
function
|
|
10553
|
-
let n = `<script>${
|
|
10597
|
+
function lf(e, t) {
|
|
10598
|
+
let n = `<script>${cf(t)}<\/script>`;
|
|
10554
10599
|
return /<head[^>]*>/i.test(e) ? e.replace(/<head[^>]*>/i, (e) => e + n) : /<html[^>]*>/i.test(e) ? e.replace(/<html[^>]*>/i, (e) => e + n) : n + e;
|
|
10555
10600
|
}
|
|
10556
|
-
function
|
|
10601
|
+
function uf() {
|
|
10557
10602
|
return typeof document < "u" && typeof document.createElement == "function" && document.body !== void 0 && document.body !== null;
|
|
10558
10603
|
}
|
|
10559
|
-
var
|
|
10604
|
+
var df = {
|
|
10560
10605
|
created: 0,
|
|
10561
10606
|
destroyed: 0
|
|
10562
10607
|
};
|
|
10563
|
-
function
|
|
10564
|
-
return { ...
|
|
10608
|
+
function ff() {
|
|
10609
|
+
return { ...df };
|
|
10565
10610
|
}
|
|
10566
|
-
function
|
|
10611
|
+
function pf(e, t = {}) {
|
|
10567
10612
|
let n = t.silenceMs ?? 900, r = t.hardCapMs ?? 4e3, i = t.metricsGraceMs ?? 500;
|
|
10568
|
-
if (!
|
|
10613
|
+
if (!uf()) return Promise.resolve({
|
|
10569
10614
|
handshake: !1,
|
|
10570
10615
|
signals: [],
|
|
10571
10616
|
noDom: !0
|
|
@@ -10573,9 +10618,9 @@ function uf(e, t = {}) {
|
|
|
10573
10618
|
let a = `pg_rc_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
10574
10619
|
return new Promise((t) => {
|
|
10575
10620
|
let o = [], s = !1, c, l, u, d, f, p, m = !1;
|
|
10576
|
-
|
|
10621
|
+
df.created++;
|
|
10577
10622
|
let h = () => {
|
|
10578
|
-
m || (m = !0, u && window.removeEventListener("message", u), d && clearTimeout(d), f && clearTimeout(f), p && clearTimeout(p), l && (l.remove(),
|
|
10623
|
+
m || (m = !0, u && window.removeEventListener("message", u), d && clearTimeout(d), f && clearTimeout(f), p && clearTimeout(p), l && (l.remove(), df.destroyed++));
|
|
10579
10624
|
}, g = (e = !1) => {
|
|
10580
10625
|
h(), t({
|
|
10581
10626
|
handshake: s,
|
|
@@ -10622,14 +10667,14 @@ function uf(e, t = {}) {
|
|
|
10622
10667
|
...r.source === void 0 ? {} : { source: String(r.source) },
|
|
10623
10668
|
...typeof r.lineno == "number" ? { lineno: r.lineno } : {}
|
|
10624
10669
|
}), s && _();
|
|
10625
|
-
}, window.addEventListener("message", u), f = setTimeout(() => g(!0), r), l = document.createElement("iframe"), l.setAttribute("sandbox", "allow-scripts"), l.setAttribute("aria-hidden", "true"), l.setAttribute("tabindex", "-1"), l.style.cssText = "position:fixed;left:-9999px;top:0;width:1024px;height:600px;visibility:hidden;border:0;opacity:0;pointer-events:none;", l.srcdoc =
|
|
10670
|
+
}, window.addEventListener("message", u), f = setTimeout(() => g(!0), r), l = document.createElement("iframe"), l.setAttribute("sandbox", "allow-scripts"), l.setAttribute("aria-hidden", "true"), l.setAttribute("tabindex", "-1"), l.style.cssText = "position:fixed;left:-9999px;top:0;width:1024px;height:600px;visibility:hidden;border:0;opacity:0;pointer-events:none;", l.srcdoc = lf(e, a), document.body.appendChild(l);
|
|
10626
10671
|
});
|
|
10627
10672
|
}
|
|
10628
|
-
function
|
|
10629
|
-
let t = e.vfsPrefix ?? "html/", n = e.codeField ?? "code", r = e.maxTargets ?? 4, i = typeof e.runner == "function", a = e.runner ?? ((e) =>
|
|
10673
|
+
function mf(e = {}) {
|
|
10674
|
+
let t = e.vfsPrefix ?? "html/", n = e.codeField ?? "code", r = e.maxTargets ?? 4, i = typeof e.runner == "function", a = e.runner ?? ((e) => pf(e)), o, s = e.writablePaths ?? [];
|
|
10630
10675
|
return {
|
|
10631
10676
|
check: async ({ state: e, log: c }) => {
|
|
10632
|
-
if (!i && !
|
|
10677
|
+
if (!i && !uf()) return c?.("middleware", {
|
|
10633
10678
|
stage: "render_check_skip",
|
|
10634
10679
|
reason: "no-dom"
|
|
10635
10680
|
}), { ok: !0 };
|
|
@@ -10664,7 +10709,7 @@ function df(e = {}) {
|
|
|
10664
10709
|
});
|
|
10665
10710
|
let g = [], _ = [], v = [];
|
|
10666
10711
|
for (let e of h) {
|
|
10667
|
-
let t =
|
|
10712
|
+
let t = sf(await a(e.html));
|
|
10668
10713
|
for (let n of t.problems) g.push(`${e.label}:${n}`);
|
|
10669
10714
|
for (let n of t.warnings) _.push(`${e.label}:${n}`);
|
|
10670
10715
|
t.verdict === "unavailable" && v.push(e.label), c?.("middleware", {
|
|
@@ -10704,7 +10749,7 @@ function df(e = {}) {
|
|
|
10704
10749
|
}
|
|
10705
10750
|
};
|
|
10706
10751
|
}
|
|
10707
|
-
function
|
|
10752
|
+
function hf(e, t) {
|
|
10708
10753
|
return async (n) => {
|
|
10709
10754
|
let r = await e(n);
|
|
10710
10755
|
return r.ok ? t(n) : r;
|
|
@@ -10712,7 +10757,7 @@ function ff(e, t) {
|
|
|
10712
10757
|
}
|
|
10713
10758
|
//#endregion
|
|
10714
10759
|
//#region src/core/sdk/htmlSubagent.ts
|
|
10715
|
-
function
|
|
10760
|
+
function gf(e, t, n) {
|
|
10716
10761
|
let r = "html";
|
|
10717
10762
|
return `你是纯代码组件生成专家。可用工具:vfs_write / vfs_edit / vfs_rm(写/改/删代码工作副本 vfs ${e}) / vfs_read + vfs_grep(读 vfs) / validate_code(代码格式自检) / write(写 data,writablePaths 限定;set/patch 增量或整体) / read / write_todos + update_todo(规划)。
|
|
10718
10763
|
|
|
@@ -10767,7 +10812,7 @@ ${`- 输出形态:完整、自包含的 HTML 页面(.${r},可独立成页)`}
|
|
|
10767
10812
|
- 一次想清楚 → 动手 → 验证 → 收口。**思考是手段不是目的,产出代码才是**。
|
|
10768
10813
|
8. **收口格式(必守,最后一行)**:收口回复 = 简短结果总结 + **末行交接笔记** \`[note] <一句话实现要点>\` —— 关键设计决策 / 用户偏好 / 踩坑(如「[note] 液面用 height keyframes 4.2s 循环;装饰仅灯串+光斑 2 类」)。框架只识别末尾 [note] 行存进组件、自动转交下次维护该组件的子 agent;**漏写 = 下任失去交接**(真 LLM 实测漏写率 3/4,务必末行带上)。一行内,只写可复用结论。`;
|
|
10769
10814
|
}
|
|
10770
|
-
function
|
|
10815
|
+
function _f(e, t) {
|
|
10771
10816
|
return `# HTML 完整页面生成规范
|
|
10772
10817
|
|
|
10773
10818
|
## 代码资产模型(重要)
|
|
@@ -10805,14 +10850,14 @@ function mf(e, t) {
|
|
|
10805
10850
|
- 语义化标签(button / nav / section);图片 alt;交互可键盘聚焦
|
|
10806
10851
|
- 颜色对比达标;不只用颜色传达信息`;
|
|
10807
10852
|
}
|
|
10808
|
-
function
|
|
10853
|
+
function vf(e = "components", t = "code") {
|
|
10809
10854
|
return {
|
|
10810
10855
|
name: "html-fragment",
|
|
10811
10856
|
description: "完整 HTML 页面生成规范:代码作为 data 资产 / vfs 工作副本 / 完整自包含可独立成页 / script+CSS 集中放置 / 可引外部 JS/CSS / validate_code 自检 / 安全底线 / 可访问性",
|
|
10812
|
-
getContent: () =>
|
|
10857
|
+
getContent: () => _f(e, t)
|
|
10813
10858
|
};
|
|
10814
10859
|
}
|
|
10815
|
-
function
|
|
10860
|
+
function yf(e = {}) {
|
|
10816
10861
|
let t = e.vfsPrefix ?? "html/";
|
|
10817
10862
|
return ({ state: e }) => {
|
|
10818
10863
|
let n = e.files;
|
|
@@ -10820,7 +10865,7 @@ function gf(e = {}) {
|
|
|
10820
10865
|
let r = [];
|
|
10821
10866
|
for (let [e, i] of Object.entries(n)) {
|
|
10822
10867
|
if (!e.startsWith(t)) continue;
|
|
10823
|
-
let n =
|
|
10868
|
+
let n = vd(i.content);
|
|
10824
10869
|
for (let t of n) r.push(`${e} 第 ${t.line} 行:${t.message}(${t.code})`);
|
|
10825
10870
|
}
|
|
10826
10871
|
return r.length ? {
|
|
@@ -10829,7 +10874,7 @@ function gf(e = {}) {
|
|
|
10829
10874
|
} : { ok: !0 };
|
|
10830
10875
|
};
|
|
10831
10876
|
}
|
|
10832
|
-
function
|
|
10877
|
+
function bf(e) {
|
|
10833
10878
|
let n, i, a = {
|
|
10834
10879
|
name: "html-validate-tools",
|
|
10835
10880
|
beforeAgent: (e) => {
|
|
@@ -10864,7 +10909,7 @@ function _f(e) {
|
|
|
10864
10909
|
}
|
|
10865
10910
|
let s = [];
|
|
10866
10911
|
for (let e of o) {
|
|
10867
|
-
let t =
|
|
10912
|
+
let t = vd(e.content);
|
|
10868
10913
|
t.length && s.push(`${e.path}:\n${t.map((e) => ` 第 ${e.line} 行 ${e.message}(${e.code})`).join("\n")}`);
|
|
10869
10914
|
}
|
|
10870
10915
|
return s.length ? `❌ 格式校验未通过:\n${s.join("\n")}\n请用 vfs_edit 修正后重新调用 validate_code 复查。` : `✅ 格式校验通过(${o.map((e) => e.path).join(", ")}:标签闭合等结构合法)。`;
|
|
@@ -10882,35 +10927,35 @@ function _f(e) {
|
|
|
10882
10927
|
i = e;
|
|
10883
10928
|
}, a;
|
|
10884
10929
|
}
|
|
10885
|
-
function
|
|
10930
|
+
function xf() {
|
|
10886
10931
|
return ({ state: e }) => {
|
|
10887
10932
|
let t = e.__pgFinalText?.text ?? "";
|
|
10888
|
-
return !t ||
|
|
10933
|
+
return !t || Ed(t).length ? { ok: !0 } : {
|
|
10889
10934
|
ok: !1,
|
|
10890
10935
|
feedback: "收口回复缺末行交接笔记:请在回复末行补一条 `[note] <一句话实现要点>`(关键设计决策/用户偏好/踩坑,框架会存进组件转交下次维护该组件的 agent;只追加这一行,不要重写其它内容)。"
|
|
10891
10936
|
};
|
|
10892
10937
|
};
|
|
10893
10938
|
}
|
|
10894
|
-
var
|
|
10895
|
-
function
|
|
10939
|
+
var Sf = 2;
|
|
10940
|
+
function Cf(e = {}) {
|
|
10896
10941
|
let { writablePaths: t, codeVfsPrefix: n = "html/", id: r = "html", description: i, planning: a = !0, summarization: o = !0, maxToolRounds: s = 12, temperature: c = .4, skills: l, extraTools: u, formatCheck: d = !0, codeField: f = "code", orchestratorPrompt: p = !0, craftNotes: m = !0, llm: h, thinkingMode: g, allowedTools: _, design: v } = e;
|
|
10897
10942
|
if (t !== void 0 && !Array.isArray(t)) throw Error("[page-agent-sdk][createHtmlSubagent] writablePaths 须为字符串数组(代码组件 data 区,如 [\"components\"])/ 省略以从 schema 自动推断");
|
|
10898
10943
|
let y = [];
|
|
10899
10944
|
a && y.push(so());
|
|
10900
|
-
let b = d ?
|
|
10945
|
+
let b = d ? mf({
|
|
10901
10946
|
vfsPrefix: n,
|
|
10902
10947
|
codeField: f,
|
|
10903
10948
|
writablePaths: t ?? []
|
|
10904
10949
|
}) : void 0;
|
|
10905
10950
|
if (d) {
|
|
10906
|
-
y.push(
|
|
10907
|
-
let e =
|
|
10951
|
+
y.push(bf(n));
|
|
10952
|
+
let e = yf({ vfsPrefix: n }), t = b ? hf(e, b.check) : e, r = m ? xf() : void 0, i = Hl({ check: r ? Vl(t, r) : t });
|
|
10908
10953
|
b && (i._setGetController = b.setGetController), y.push(i);
|
|
10909
10954
|
}
|
|
10910
|
-
let x = u ?? [], S = t?.[0] ?? "components", C = l === void 0, w = v === !1 ? null : v === void 0 || v === !0 ?
|
|
10955
|
+
let x = u ?? [], S = t?.[0] ?? "components", C = l === void 0, w = v === !1 ? null : v === void 0 || v === !0 ? af() : v, T = (e) => [...C ? [vf(e, f)] : l, ...w ? [w] : []], E = {
|
|
10911
10956
|
id: r,
|
|
10912
10957
|
description: i ?? `生成/修改纯代码组件(代码作为 data 资产,代码字段 ${f} 随 data 持久化;vfs 作工作副本;能规划(write_todos)+ 执行)。需写代码组件或灵活定制时委派`,
|
|
10913
|
-
systemPrompt:
|
|
10958
|
+
systemPrompt: gf(n, f, S),
|
|
10914
10959
|
...h ? { llm: h } : {},
|
|
10915
10960
|
...g ? { thinkingMode: g } : {},
|
|
10916
10961
|
writablePaths: t ?? [],
|
|
@@ -10924,7 +10969,7 @@ function bf(e = {}) {
|
|
|
10924
10969
|
],
|
|
10925
10970
|
middleware: y.length ? y : void 0,
|
|
10926
10971
|
summarization: o === !1 ? void 0 : o,
|
|
10927
|
-
maxVerifyAttempts: d ?
|
|
10972
|
+
maxVerifyAttempts: d ? Sf : void 0,
|
|
10928
10973
|
temperature: c,
|
|
10929
10974
|
skills: T(S),
|
|
10930
10975
|
maxToolRounds: s,
|
|
@@ -10939,12 +10984,12 @@ function bf(e = {}) {
|
|
|
10939
10984
|
}
|
|
10940
10985
|
};
|
|
10941
10986
|
return E._rebuildCodeAssetPaths = (e) => {
|
|
10942
|
-
E.systemPrompt =
|
|
10987
|
+
E.systemPrompt = gf(n, f, e), E.skills = T(e), b?.setWritablePaths([e]);
|
|
10943
10988
|
}, E;
|
|
10944
10989
|
}
|
|
10945
10990
|
//#endregion
|
|
10946
10991
|
//#region src/core/sdk/defineTool.ts
|
|
10947
|
-
function
|
|
10992
|
+
function wf(e) {
|
|
10948
10993
|
let t = r(async (t) => {
|
|
10949
10994
|
let n = await e.handler(t);
|
|
10950
10995
|
return typeof n == "string" ? n : JSON.stringify(n);
|
|
@@ -10957,7 +11002,7 @@ function xf(e) {
|
|
|
10957
11002
|
}
|
|
10958
11003
|
//#endregion
|
|
10959
11004
|
//#region src/core/sdk/inspectContextTool.ts
|
|
10960
|
-
var
|
|
11005
|
+
var Tf = t.object({
|
|
10961
11006
|
path: t.string().optional().describe("分类 key 过滤(如 toolResults/history/systemPrompt/dataHint);不传=全部分类"),
|
|
10962
11007
|
role: t.enum([
|
|
10963
11008
|
"user",
|
|
@@ -10967,11 +11012,11 @@ var Sf = t.object({
|
|
|
10967
11012
|
]).optional().describe("聚焦每轮首句的角色(assistant→回复摘要,user→问题摘要);不影响工具列表"),
|
|
10968
11013
|
limit: t.number().int().min(1).max(50).optional().describe("返回最近 N 轮(默认全部;超 50 自动截最近 50 防返回过大)")
|
|
10969
11014
|
});
|
|
10970
|
-
function
|
|
10971
|
-
return
|
|
11015
|
+
function Ef(e) {
|
|
11016
|
+
return wf({
|
|
10972
11017
|
name: "inspect_context",
|
|
10973
11018
|
description: "查看当前对话上下文的构成(供压缩决策)。返回:totalTokens(历史轮次 token 总和,与触发判断同口径)、occupancy(窗口占用比)、contextWindow、categories(分类占用)、rounds(每轮 token/工具/首句)。先调用本工具查看构成,再决定压缩策略。",
|
|
10974
|
-
schema:
|
|
11019
|
+
schema: Tf,
|
|
10975
11020
|
handler: (t) => {
|
|
10976
11021
|
let n = Cc(e.getMessages()), r = n.length > 50 ? n.slice(n.length - 50) : n, i = (t.limit && r.length > t.limit ? r.slice(r.length - t.limit) : r).map((e) => {
|
|
10977
11022
|
let n = Fc(e), r = Tc(e), i = t.role === "assistant" ? e.assistantMsgs[0] ?? e.userMsg : e.userMsg, a = wc(typeof i.content == "string" ? i.content : "", 60);
|
|
@@ -10994,7 +11039,7 @@ function Cf(e) {
|
|
|
10994
11039
|
}
|
|
10995
11040
|
//#endregion
|
|
10996
11041
|
//#region src/core/sdk/compressDecision.ts
|
|
10997
|
-
var
|
|
11042
|
+
var Df = t.object({
|
|
10998
11043
|
keepRounds: t.number().int().min(0).max(50).optional(),
|
|
10999
11044
|
windowRatio: t.number().min(0).max(1).optional(),
|
|
11000
11045
|
summarize: t.object({ mode: t.enum(["index", "llm"]) }),
|
|
@@ -11004,23 +11049,23 @@ var wf = t.object({
|
|
|
11004
11049
|
}).refine((e) => e.keepRounds !== void 0 || e.windowRatio !== void 0, { message: "keepRounds 与 windowRatio 至少填一个(按当前触发模式)" });
|
|
11005
11050
|
//#endregion
|
|
11006
11051
|
//#region src/core/sdk/llmResolver.ts
|
|
11007
|
-
function
|
|
11052
|
+
function Of(e) {
|
|
11008
11053
|
let t = e.find((e) => e.role === "user");
|
|
11009
11054
|
if (!t) return;
|
|
11010
11055
|
let n = t.content, r = (typeof n == "string" ? n : Array.isArray(n) ? n.map((e) => typeof e == "string" ? e : e?.text ?? "").join("") : String(n ?? "")).trim().replace(/[\n\r]+/g, " ");
|
|
11011
11056
|
if (r) return r.length > 30 ? r.slice(0, 30) + "…" : r;
|
|
11012
11057
|
}
|
|
11013
|
-
function
|
|
11058
|
+
function kf(e) {
|
|
11014
11059
|
return !!e && typeof e == "object" && typeof e.invoke == "function" && typeof e.stream == "function";
|
|
11015
11060
|
}
|
|
11016
|
-
function
|
|
11061
|
+
function Af(e) {
|
|
11017
11062
|
let t = e.content;
|
|
11018
11063
|
return typeof t == "string" ? t : Array.isArray(t) ? t.map((e) => typeof e == "string" ? e : e?.text ?? "").join("") : String(t ?? "");
|
|
11019
11064
|
}
|
|
11020
|
-
function
|
|
11065
|
+
function jf(e) {
|
|
11021
11066
|
let t = e.summaryLlm ?? e.llm;
|
|
11022
11067
|
if (!t) return;
|
|
11023
|
-
let n = e.summaryTemperature ?? .3, r = e.summaryMaxTokens ?? 2048, i = e.summaryTimeoutMs ?? 15e3, s =
|
|
11068
|
+
let n = e.summaryTemperature ?? .3, r = e.summaryMaxTokens ?? 2048, i = e.summaryTimeoutMs ?? 15e3, s = kf(t) ? t : null, c = kf(t) ? null : t;
|
|
11024
11069
|
if (c && !c.apiKey) {
|
|
11025
11070
|
e.summaryLlm && console.warn("[page-agent-sdk][summarization] summaryLlm 已配置但缺 apiKey,摘要回退主 agent 模型或零成本索引摘要");
|
|
11026
11071
|
return;
|
|
@@ -11033,16 +11078,16 @@ function Of(e) {
|
|
|
11033
11078
|
temperature: n,
|
|
11034
11079
|
maxTokens: r,
|
|
11035
11080
|
thinkingFallback: "simple"
|
|
11036
|
-
})),
|
|
11081
|
+
})), Af(await l.invoke([new o("你是对话历史压缩助手。把下面按轮次索引的对话要点,改写成一段连贯、紧凑的中文摘要,保留关键事实、用户意图与已用工具,不要编造。直接输出摘要正文。"), new a(e)], { signal: t.signal })).trim();
|
|
11037
11082
|
} finally {
|
|
11038
11083
|
clearTimeout(s);
|
|
11039
11084
|
}
|
|
11040
11085
|
};
|
|
11041
11086
|
}
|
|
11042
|
-
function
|
|
11087
|
+
function Mf(e) {
|
|
11043
11088
|
let t = e.titleLlm ?? e.summaryLlm ?? e.llm;
|
|
11044
11089
|
if (!t) return;
|
|
11045
|
-
let n =
|
|
11090
|
+
let n = kf(t) ? t : null, r = kf(t) ? null : t;
|
|
11046
11091
|
if (r && !r.apiKey) return;
|
|
11047
11092
|
let i = n;
|
|
11048
11093
|
return async (t) => {
|
|
@@ -11054,7 +11099,7 @@ function kf(e) {
|
|
|
11054
11099
|
thinkingFallback: "simple"
|
|
11055
11100
|
}));
|
|
11056
11101
|
let t = await i.invoke([new o(e.i18n?.locale === "en-US" ? "Generate a short English title (max 10 words) summarizing the conversation below. Output the title text only, no quotes or punctuation." : "根据以下对话的主旨,生成一个简短的中文标题(不超过15个字,不要标点和引号,直接输出标题文字)。"), new a(n)], { signal: s.signal }), c = e.i18n?.locale === "en-US" ? 60 : 20;
|
|
11057
|
-
return
|
|
11102
|
+
return Af(t).trim().replace(/^["'""「『]|["'""」』]$/g, "").split("\n")[0].slice(0, c);
|
|
11058
11103
|
} catch {
|
|
11059
11104
|
return "";
|
|
11060
11105
|
} finally {
|
|
@@ -11062,10 +11107,10 @@ function kf(e) {
|
|
|
11062
11107
|
}
|
|
11063
11108
|
};
|
|
11064
11109
|
}
|
|
11065
|
-
function
|
|
11110
|
+
function Nf() {
|
|
11066
11111
|
return `call_dec_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
11067
11112
|
}
|
|
11068
|
-
function
|
|
11113
|
+
function Pf(e) {
|
|
11069
11114
|
let t = e.match(/```(?:json)?\s*([\s\S]*?)```/), n = t ? t[1] : e, r = n.indexOf("{"), i = n.lastIndexOf("}");
|
|
11070
11115
|
if (r < 0 || i < 0 || i <= r) return null;
|
|
11071
11116
|
try {
|
|
@@ -11074,21 +11119,21 @@ function jf(e) {
|
|
|
11074
11119
|
return null;
|
|
11075
11120
|
}
|
|
11076
11121
|
}
|
|
11077
|
-
function
|
|
11122
|
+
function Ff(e) {
|
|
11078
11123
|
if (!e) return null;
|
|
11079
|
-
let t =
|
|
11124
|
+
let t = Pf(e);
|
|
11080
11125
|
if (t == null) return null;
|
|
11081
|
-
let n =
|
|
11126
|
+
let n = Df.safeParse(t);
|
|
11082
11127
|
return n.success ? n.data : null;
|
|
11083
11128
|
}
|
|
11084
|
-
async function
|
|
11129
|
+
async function If(e, t, n, r) {
|
|
11085
11130
|
let i = [...n];
|
|
11086
11131
|
for (let n = 0; n < 3; n++) {
|
|
11087
11132
|
let n = await e.invoke(i, { signal: r }), a = n?.tool_calls ?? [];
|
|
11088
|
-
if (!a.length) return
|
|
11133
|
+
if (!a.length) return Af(n).trim();
|
|
11089
11134
|
i = [...i, n];
|
|
11090
11135
|
for (let e of a) {
|
|
11091
|
-
let n = e.id ??
|
|
11136
|
+
let n = e.id ?? Nf();
|
|
11092
11137
|
try {
|
|
11093
11138
|
let r = await t.invoke(e.args ?? {}), a = typeof r == "string" ? r : r?.content ?? JSON.stringify(r);
|
|
11094
11139
|
i = [...i, new s({
|
|
@@ -11105,10 +11150,10 @@ async function Nf(e, t, n, r) {
|
|
|
11105
11150
|
}
|
|
11106
11151
|
return "";
|
|
11107
11152
|
}
|
|
11108
|
-
function
|
|
11153
|
+
function Lf(e) {
|
|
11109
11154
|
let t = e.summaryLlm ?? e.llm;
|
|
11110
11155
|
if (!t) return;
|
|
11111
|
-
let n =
|
|
11156
|
+
let n = kf(t) ? t : null, r = kf(t) ? null : t;
|
|
11112
11157
|
if (r && !r.apiKey) return;
|
|
11113
11158
|
let i = e.decisionTimeoutMs ?? 6e3, s = e.decisionMaxTokens ?? 2048, c = n;
|
|
11114
11159
|
return async (e) => {
|
|
@@ -11121,12 +11166,12 @@ function Pf(e) {
|
|
|
11121
11166
|
}));
|
|
11122
11167
|
let n = c;
|
|
11123
11168
|
if (typeof n.bindTools != "function") return null;
|
|
11124
|
-
let i =
|
|
11169
|
+
let i = Ef({
|
|
11125
11170
|
getMessages: e.getMessages,
|
|
11126
11171
|
getSnapshot: e.getSnapshot,
|
|
11127
11172
|
contextWindow: e.contextWindow
|
|
11128
11173
|
}), l = n.bindTools([i]), u = e.triggerMode === "token" ? "token 模式:必填 windowRatio(0~1 保留窗口预算比例,如 0.4);keepRounds 可选" : "轮数模式:必填 keepRounds(保留最近几轮,如 6);windowRatio 可选", d = [new o(`你是对话历史压缩决策助手。当前触发模式 = ${e.triggerMode}(${e.triggerReason})。先调用 inspect_context 查看上下文构成,再输出压缩决策 JSON。${u}。仅输出 JSON,不要多余文字/markdown。schema:{keepRounds?(int 0-50), windowRatio?(0-1), summarize:{mode:"index"|"llm"}, recallTopK?(int 0-10), preserveTools?(string[]≤10), reason?(≤200字)}。keepRounds/windowRatio 至少填一个。`), new a(`触发原因:${e.triggerReason}\n上下文窗口:${e.contextWindow ?? "未知"} tokens\n阈值比例:${e.thresholdRatio ?? "未知"}\n\n请决策压缩策略(先 inspect_context 查看,再输出 JSON)。`)];
|
|
11129
|
-
return
|
|
11174
|
+
return Ff(await If(l, i, d, t.signal)) || Ff(await If(l, i, [...d, new a("上一次输出无效(JSON 解析失败或 schema 校验不通过)。请只输出符合 schema 的压缩决策 JSON,不要多余文字/markdown 代码块。")], t.signal));
|
|
11130
11175
|
} catch {
|
|
11131
11176
|
return null;
|
|
11132
11177
|
} finally {
|
|
@@ -11134,8 +11179,8 @@ function Pf(e) {
|
|
|
11134
11179
|
}
|
|
11135
11180
|
};
|
|
11136
11181
|
}
|
|
11137
|
-
function
|
|
11138
|
-
let t = e.llm, n =
|
|
11182
|
+
function Rf(e) {
|
|
11183
|
+
let t = e.llm, n = kf(e.llm) ? void 0 : e.llm;
|
|
11139
11184
|
return {
|
|
11140
11185
|
modelCaps: v({
|
|
11141
11186
|
model: n?.model ?? t?.model ?? t?.modelName,
|
|
@@ -11143,14 +11188,14 @@ function Ff(e) {
|
|
|
11143
11188
|
maxOutputTokens: e.maxOutputTokens ?? n?.maxOutputTokens ?? t?.maxOutputTokens,
|
|
11144
11189
|
vision: n?.vision ?? t?.vision
|
|
11145
11190
|
}),
|
|
11146
|
-
summaryLlmInvoke:
|
|
11147
|
-
titleLlmInvoke:
|
|
11148
|
-
compressDecisionInvoke:
|
|
11191
|
+
summaryLlmInvoke: jf(e),
|
|
11192
|
+
titleLlmInvoke: Mf(e),
|
|
11193
|
+
compressDecisionInvoke: Lf(e)
|
|
11149
11194
|
};
|
|
11150
11195
|
}
|
|
11151
11196
|
//#endregion
|
|
11152
11197
|
//#region src/core/sdk/conflictManager.ts
|
|
11153
|
-
function
|
|
11198
|
+
function zf(e, t) {
|
|
11154
11199
|
let n = /* @__PURE__ */ Vt(null), r = 0;
|
|
11155
11200
|
function i(i, a) {
|
|
11156
11201
|
let o = t?.() ?? "ask";
|
|
@@ -11196,7 +11241,7 @@ function If(e, t) {
|
|
|
11196
11241
|
}
|
|
11197
11242
|
//#endregion
|
|
11198
11243
|
//#region src/core/utils/id.ts
|
|
11199
|
-
function
|
|
11244
|
+
function Bf() {
|
|
11200
11245
|
try {
|
|
11201
11246
|
if (typeof crypto < "u" && typeof crypto.randomUUID == "function") return crypto.randomUUID();
|
|
11202
11247
|
} catch {}
|
|
@@ -11204,7 +11249,7 @@ function Lf() {
|
|
|
11204
11249
|
}
|
|
11205
11250
|
//#endregion
|
|
11206
11251
|
//#region src/core/backends/storage.ts
|
|
11207
|
-
var
|
|
11252
|
+
var Vf = "chat-sdk", Hf = 50 * 1024 * 1024, Uf = 4 * 1024 * 1024, Wf = 10 * 1024 * 1024, Gf = .9, Kf = 500, qf = 5e3, Jf = 300, Yf = "__meta__", Xf = "v:1", Zf = [
|
|
11208
11253
|
"messages",
|
|
11209
11254
|
"vfs",
|
|
11210
11255
|
"todos",
|
|
@@ -11216,51 +11261,51 @@ var Rf = "chat-sdk", zf = 50 * 1024 * 1024, Bf = 4 * 1024 * 1024, Vf = 10 * 1024
|
|
|
11216
11261
|
"focus",
|
|
11217
11262
|
"planConfirmation"
|
|
11218
11263
|
];
|
|
11219
|
-
function
|
|
11220
|
-
return e === "local" || e === "session" ?
|
|
11264
|
+
function Qf(e) {
|
|
11265
|
+
return e === "local" || e === "session" ? Uf : Hf;
|
|
11221
11266
|
}
|
|
11222
|
-
function
|
|
11267
|
+
function $f(e) {
|
|
11223
11268
|
if (typeof e != "object" || !e) return !1;
|
|
11224
11269
|
let t = e;
|
|
11225
11270
|
return t.name === "QuotaExceededError" || t.name === "NS_ERROR_DOM_QUOTA_REACHED" || t.code === 22 || t.code === 1014;
|
|
11226
11271
|
}
|
|
11227
|
-
function
|
|
11272
|
+
function ep(e, t, n, r) {
|
|
11228
11273
|
return [
|
|
11229
|
-
|
|
11274
|
+
Xf,
|
|
11230
11275
|
e,
|
|
11231
11276
|
t,
|
|
11232
11277
|
n,
|
|
11233
11278
|
r
|
|
11234
11279
|
].join("::");
|
|
11235
11280
|
}
|
|
11236
|
-
function
|
|
11281
|
+
function tp(e, t, n) {
|
|
11237
11282
|
return [
|
|
11238
|
-
|
|
11283
|
+
Xf,
|
|
11239
11284
|
e,
|
|
11240
11285
|
t,
|
|
11241
11286
|
n
|
|
11242
11287
|
].join("::") + "::";
|
|
11243
11288
|
}
|
|
11244
|
-
function
|
|
11289
|
+
function np(e, t) {
|
|
11245
11290
|
return [
|
|
11246
|
-
|
|
11291
|
+
Xf,
|
|
11247
11292
|
e,
|
|
11248
11293
|
t
|
|
11249
11294
|
].join("::") + "::";
|
|
11250
11295
|
}
|
|
11251
|
-
function
|
|
11252
|
-
return [
|
|
11296
|
+
function rp(e) {
|
|
11297
|
+
return [Xf, e].join("::") + "::";
|
|
11253
11298
|
}
|
|
11254
|
-
var
|
|
11255
|
-
function
|
|
11256
|
-
|
|
11299
|
+
var ip = null;
|
|
11300
|
+
function ap(e) {
|
|
11301
|
+
ip ||= new TextEncoder();
|
|
11257
11302
|
try {
|
|
11258
|
-
return
|
|
11303
|
+
return ip.encode(JSON.stringify(e)).length;
|
|
11259
11304
|
} catch {
|
|
11260
11305
|
return 0;
|
|
11261
11306
|
}
|
|
11262
11307
|
}
|
|
11263
|
-
function
|
|
11308
|
+
function op(e, t, n) {
|
|
11264
11309
|
let r = e.reduce((e, t) => e + t.bytes, 0);
|
|
11265
11310
|
if (r <= t) return [];
|
|
11266
11311
|
let i = t * n, a = [...e].sort((e, t) => e.lastAccessed - t.lastAccessed), o = [];
|
|
@@ -11270,7 +11315,7 @@ function rp(e, t, n) {
|
|
|
11270
11315
|
}
|
|
11271
11316
|
return o;
|
|
11272
11317
|
}
|
|
11273
|
-
function
|
|
11318
|
+
function sp() {
|
|
11274
11319
|
let e = /* @__PURE__ */ new Map();
|
|
11275
11320
|
return {
|
|
11276
11321
|
async get(t) {
|
|
@@ -11290,7 +11335,7 @@ function ip() {
|
|
|
11290
11335
|
}
|
|
11291
11336
|
};
|
|
11292
11337
|
}
|
|
11293
|
-
function
|
|
11338
|
+
function cp(e) {
|
|
11294
11339
|
return new Promise((t, n) => {
|
|
11295
11340
|
if (typeof indexedDB > "u") {
|
|
11296
11341
|
n(/* @__PURE__ */ Error("indexedDB 不可用"));
|
|
@@ -11351,7 +11396,7 @@ function ap(e) {
|
|
|
11351
11396
|
}, r.onerror = () => n(r.error);
|
|
11352
11397
|
});
|
|
11353
11398
|
}
|
|
11354
|
-
function
|
|
11399
|
+
function lp(e) {
|
|
11355
11400
|
return {
|
|
11356
11401
|
async get(t) {
|
|
11357
11402
|
let n = e.getItem(t);
|
|
@@ -11396,24 +11441,24 @@ function op(e) {
|
|
|
11396
11441
|
}
|
|
11397
11442
|
};
|
|
11398
11443
|
}
|
|
11399
|
-
function
|
|
11444
|
+
function up(e, t, n) {
|
|
11400
11445
|
let r = (e.get(t) ?? Promise.resolve()).then(n, n);
|
|
11401
11446
|
return e.set(t, r.then(() => void 0, () => void 0)), r;
|
|
11402
11447
|
}
|
|
11403
|
-
function
|
|
11404
|
-
return
|
|
11448
|
+
function dp(e = {}) {
|
|
11449
|
+
return pp(e, typeof e.backend == "object" && e.backend ? e.backend : void 0);
|
|
11405
11450
|
}
|
|
11406
|
-
function
|
|
11407
|
-
return
|
|
11451
|
+
function fp(e, t) {
|
|
11452
|
+
return pp(e, t);
|
|
11408
11453
|
}
|
|
11409
|
-
function
|
|
11410
|
-
let n = e.dbName ??
|
|
11454
|
+
function pp(e = {}, t) {
|
|
11455
|
+
let n = e.dbName ?? Vf, r = typeof e.backend == "string" ? e.backend ?? "indexed" : "indexed", i = e.maxBytes ?? Qf(r), a = e.maxBytesPerSession ?? (i === Infinity ? Infinity : Wf), o = e.evictionWatermark ?? Gf, s = e.debounceMs ?? Kf, c = /* @__PURE__ */ new Set();
|
|
11411
11456
|
function l(e) {
|
|
11412
11457
|
for (let t of c) try {
|
|
11413
11458
|
t(e);
|
|
11414
11459
|
} catch {}
|
|
11415
11460
|
}
|
|
11416
|
-
let u =
|
|
11461
|
+
let u = sp(), d = !1, f, p = new Promise((e) => {
|
|
11417
11462
|
f = e;
|
|
11418
11463
|
});
|
|
11419
11464
|
(async () => {
|
|
@@ -11424,16 +11469,16 @@ function up(e = {}, t) {
|
|
|
11424
11469
|
}
|
|
11425
11470
|
if (r === "indexed") {
|
|
11426
11471
|
if (typeof indexedDB > "u") throw Error("indexedDB 不可用");
|
|
11427
|
-
u = await
|
|
11472
|
+
u = await cp(n), f(!0);
|
|
11428
11473
|
} else if (r === "session") {
|
|
11429
11474
|
if (typeof sessionStorage > "u") throw Error("sessionStorage 不可用");
|
|
11430
|
-
u =
|
|
11475
|
+
u = lp(sessionStorage), f(!0);
|
|
11431
11476
|
} else if (r === "local") {
|
|
11432
11477
|
if (typeof localStorage > "u") throw Error("localStorage 不可用");
|
|
11433
|
-
u =
|
|
11434
|
-
} else u =
|
|
11478
|
+
u = lp(localStorage), f(!0);
|
|
11479
|
+
} else u = sp(), f(!1);
|
|
11435
11480
|
} catch (e) {
|
|
11436
|
-
u =
|
|
11481
|
+
u = sp();
|
|
11437
11482
|
let t = e instanceof Error ? e.message : String(e);
|
|
11438
11483
|
f(!1), Promise.resolve().then(() => l({
|
|
11439
11484
|
type: "degraded",
|
|
@@ -11443,10 +11488,10 @@ function up(e = {}, t) {
|
|
|
11443
11488
|
})();
|
|
11444
11489
|
let m = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map();
|
|
11445
11490
|
function _(e, t, r, i) {
|
|
11446
|
-
let o =
|
|
11447
|
-
return
|
|
11491
|
+
let o = ep(n, r, i, Yf);
|
|
11492
|
+
return up(g, o, async () => {
|
|
11448
11493
|
let n = async () => {
|
|
11449
|
-
let n = await u.get(o), s = await u.get(e), c = s == null ? 0 :
|
|
11494
|
+
let n = await u.get(o), s = await u.get(e), c = s == null ? 0 : ap(s), d = ap(t), f = (n?.bytes ?? 0) + (d - c);
|
|
11450
11495
|
if (f > a) {
|
|
11451
11496
|
l({
|
|
11452
11497
|
type: "quota",
|
|
@@ -11468,12 +11513,12 @@ function up(e = {}, t) {
|
|
|
11468
11513
|
try {
|
|
11469
11514
|
await n();
|
|
11470
11515
|
} catch (e) {
|
|
11471
|
-
if (
|
|
11516
|
+
if ($f(e) && !d) {
|
|
11472
11517
|
d = !0;
|
|
11473
11518
|
try {
|
|
11474
11519
|
await x();
|
|
11475
11520
|
} catch {}
|
|
11476
|
-
u =
|
|
11521
|
+
u = sp(), Promise.resolve().then(() => l({
|
|
11477
11522
|
type: "degraded",
|
|
11478
11523
|
reason: "存储配额超限(QuotaExceededError),已淘汰最旧会话并降级内存"
|
|
11479
11524
|
}));
|
|
@@ -11485,7 +11530,7 @@ function up(e = {}, t) {
|
|
|
11485
11530
|
});
|
|
11486
11531
|
}
|
|
11487
11532
|
function v(e, t, r, i) {
|
|
11488
|
-
let a =
|
|
11533
|
+
let a = ep(n, e, t, r), o = m.get(a);
|
|
11489
11534
|
o && o.resolve();
|
|
11490
11535
|
let c = h.get(a);
|
|
11491
11536
|
return c && clearTimeout(c), new Promise((n) => {
|
|
@@ -11512,16 +11557,16 @@ function up(e = {}, t) {
|
|
|
11512
11557
|
function b() {
|
|
11513
11558
|
y ||= setTimeout(() => {
|
|
11514
11559
|
y = null, x();
|
|
11515
|
-
},
|
|
11560
|
+
}, Jf);
|
|
11516
11561
|
}
|
|
11517
11562
|
async function x() {
|
|
11518
11563
|
if (i !== Infinity) try {
|
|
11519
11564
|
let e = [];
|
|
11520
|
-
await u.scan(
|
|
11565
|
+
await u.scan(rp(n), (t, n) => {
|
|
11521
11566
|
t.endsWith("::__meta__") && e.push(n);
|
|
11522
11567
|
});
|
|
11523
|
-
let t =
|
|
11524
|
-
for (let e of t) await u.clearPrefix(
|
|
11568
|
+
let t = op(e, i, o);
|
|
11569
|
+
for (let e of t) await u.clearPrefix(tp(n, e.agentId, e.sessionId)), l({
|
|
11525
11570
|
type: "evicted",
|
|
11526
11571
|
agentId: e.agentId,
|
|
11527
11572
|
sessionId: e.sessionId,
|
|
@@ -11538,13 +11583,13 @@ function up(e = {}, t) {
|
|
|
11538
11583
|
ready: p,
|
|
11539
11584
|
async listSessions(e) {
|
|
11540
11585
|
let t = [];
|
|
11541
|
-
return await u.scan(
|
|
11586
|
+
return await u.scan(np(n, e), (e, n) => {
|
|
11542
11587
|
e.endsWith("::__meta__") && t.push(n);
|
|
11543
11588
|
}), t.sort((e, t) => t.lastAccessed - e.lastAccessed);
|
|
11544
11589
|
},
|
|
11545
11590
|
async load(e, t) {
|
|
11546
|
-
let r =
|
|
11547
|
-
return await
|
|
11591
|
+
let r = ep(n, e, t, Yf);
|
|
11592
|
+
return await up(g, r, async () => {
|
|
11548
11593
|
let i = await u.get(r);
|
|
11549
11594
|
if (!i) return;
|
|
11550
11595
|
let a = {
|
|
@@ -11553,8 +11598,8 @@ function up(e = {}, t) {
|
|
|
11553
11598
|
todos: [],
|
|
11554
11599
|
memory: ""
|
|
11555
11600
|
};
|
|
11556
|
-
for (let r of
|
|
11557
|
-
let i = await u.get(
|
|
11601
|
+
for (let r of Zf) {
|
|
11602
|
+
let i = await u.get(ep(n, e, t, r));
|
|
11558
11603
|
i != null && (a[r] = i);
|
|
11559
11604
|
}
|
|
11560
11605
|
i.lastAccessed = Date.now();
|
|
@@ -11566,12 +11611,12 @@ function up(e = {}, t) {
|
|
|
11566
11611
|
},
|
|
11567
11612
|
async save(e, t, n) {
|
|
11568
11613
|
let r = [];
|
|
11569
|
-
for (let i of
|
|
11614
|
+
for (let i of Zf) n[i] !== void 0 && r.push(v(e, t, i, n[i]));
|
|
11570
11615
|
await Promise.all(r);
|
|
11571
11616
|
},
|
|
11572
11617
|
async updateTitle(e, t, r) {
|
|
11573
|
-
let i =
|
|
11574
|
-
return
|
|
11618
|
+
let i = ep(n, e, t, Yf);
|
|
11619
|
+
return up(g, i, async () => {
|
|
11575
11620
|
let e = await u.get(i);
|
|
11576
11621
|
e && (e.title = r, e.lastAccessed = Date.now(), await u.set(i, e));
|
|
11577
11622
|
});
|
|
@@ -11581,7 +11626,7 @@ function up(e = {}, t) {
|
|
|
11581
11626
|
let t = h.get(e);
|
|
11582
11627
|
t && (clearTimeout(t), h.delete(e));
|
|
11583
11628
|
}
|
|
11584
|
-
let t = e.flushTimeoutMs ??
|
|
11629
|
+
let t = e.flushTimeoutMs ?? qf, n = Array.from(m.entries());
|
|
11585
11630
|
await Promise.all(n.map(([e, n]) => new Promise((r) => {
|
|
11586
11631
|
let i;
|
|
11587
11632
|
_(e, n.value, n.agentId, n.sessionId).then(() => {
|
|
@@ -11597,13 +11642,13 @@ function up(e = {}, t) {
|
|
|
11597
11642
|
}))), l({ type: "flush" }), x();
|
|
11598
11643
|
},
|
|
11599
11644
|
async deleteSession(e, t) {
|
|
11600
|
-
let r =
|
|
11645
|
+
let r = tp(n, e, t);
|
|
11601
11646
|
for (let [e, t] of m.entries()) e.startsWith(r) && (t.resolve(), m.delete(e));
|
|
11602
11647
|
for (let [e, t] of h.entries()) e.startsWith(r) && (clearTimeout(t), h.delete(e));
|
|
11603
11648
|
await u.clearPrefix(r);
|
|
11604
11649
|
},
|
|
11605
11650
|
async createSession(e, t, r) {
|
|
11606
|
-
let i = r ??
|
|
11651
|
+
let i = r ?? Bf(), a = Date.now(), o = {
|
|
11607
11652
|
agentId: e,
|
|
11608
11653
|
sessionId: i,
|
|
11609
11654
|
createdAt: a,
|
|
@@ -11612,7 +11657,7 @@ function up(e = {}, t) {
|
|
|
11612
11657
|
title: t
|
|
11613
11658
|
};
|
|
11614
11659
|
try {
|
|
11615
|
-
await u.set(
|
|
11660
|
+
await u.set(ep(n, e, i, Yf), o);
|
|
11616
11661
|
} catch {}
|
|
11617
11662
|
return i;
|
|
11618
11663
|
},
|
|
@@ -11629,15 +11674,15 @@ function up(e = {}, t) {
|
|
|
11629
11674
|
}
|
|
11630
11675
|
//#endregion
|
|
11631
11676
|
//#region src/core/sdk/optionsResolver.ts
|
|
11632
|
-
function
|
|
11633
|
-
return e === void 0 ?
|
|
11677
|
+
function mp(e) {
|
|
11678
|
+
return e === void 0 ? dp({ backend: "memory" }) : e === !1 ? null : typeof e == "string" ? dp({ backend: e }) : e.enabled === !1 ? null : dp(e);
|
|
11634
11679
|
}
|
|
11635
|
-
function
|
|
11680
|
+
function hp(e) {
|
|
11636
11681
|
return e.dialog ?? {};
|
|
11637
11682
|
}
|
|
11638
11683
|
//#endregion
|
|
11639
11684
|
//#region src/core/capabilities.ts
|
|
11640
|
-
var
|
|
11685
|
+
var gp = [
|
|
11641
11686
|
{
|
|
11642
11687
|
name: "dataOps",
|
|
11643
11688
|
defaultOn: !0
|
|
@@ -11713,13 +11758,13 @@ var pp = [
|
|
|
11713
11758
|
requires: ["summarization"]
|
|
11714
11759
|
}
|
|
11715
11760
|
];
|
|
11716
|
-
function
|
|
11761
|
+
function _p(e) {
|
|
11717
11762
|
let t = {};
|
|
11718
|
-
for (let n of
|
|
11763
|
+
for (let n of gp) {
|
|
11719
11764
|
let r = e?.[n.name];
|
|
11720
11765
|
t[n.name] = n.defaultOn ? r !== !1 : r === !0;
|
|
11721
11766
|
}
|
|
11722
|
-
for (let e of
|
|
11767
|
+
for (let e of gp) if (e.requires && t[e.name]) {
|
|
11723
11768
|
for (let n of e.requires) if (!t[n]) {
|
|
11724
11769
|
t[e.name] = !1;
|
|
11725
11770
|
break;
|
|
@@ -11729,7 +11774,7 @@ function mp(e) {
|
|
|
11729
11774
|
}
|
|
11730
11775
|
//#endregion
|
|
11731
11776
|
//#region src/core/sdk/events.ts
|
|
11732
|
-
function
|
|
11777
|
+
function vp(e) {
|
|
11733
11778
|
let t = /* @__PURE__ */ new Set(), n = (n) => {
|
|
11734
11779
|
if (n.type !== "approval_request") {
|
|
11735
11780
|
if (e) try {
|
|
@@ -11755,7 +11800,7 @@ function hp(e) {
|
|
|
11755
11800
|
}
|
|
11756
11801
|
//#endregion
|
|
11757
11802
|
//#region src/core/sdk/contextPreset.ts
|
|
11758
|
-
var
|
|
11803
|
+
var yp = {
|
|
11759
11804
|
auto: {
|
|
11760
11805
|
summaryThresholdRatio: .5,
|
|
11761
11806
|
windowRatio: .4,
|
|
@@ -11783,7 +11828,7 @@ var gp = {
|
|
|
11783
11828
|
enableRecall: !0,
|
|
11784
11829
|
enableLLMSummary: !0
|
|
11785
11830
|
}
|
|
11786
|
-
},
|
|
11831
|
+
}, bp = {
|
|
11787
11832
|
auto: ["describe_data", "read"],
|
|
11788
11833
|
conservative: ["describe_data"],
|
|
11789
11834
|
aggressive: ["describe_data", "read"],
|
|
@@ -11794,8 +11839,8 @@ var gp = {
|
|
|
11794
11839
|
"search_data"
|
|
11795
11840
|
]
|
|
11796
11841
|
};
|
|
11797
|
-
function
|
|
11798
|
-
let n =
|
|
11842
|
+
function xp(e, t) {
|
|
11843
|
+
let n = yp[e.contextPreset ?? "auto"] ?? {}, r = e.contextOptions === !1 ? {} : e.contextOptions ?? {};
|
|
11799
11844
|
return {
|
|
11800
11845
|
...n,
|
|
11801
11846
|
...r,
|
|
@@ -11805,7 +11850,7 @@ function vp(e, t) {
|
|
|
11805
11850
|
}
|
|
11806
11851
|
//#endregion
|
|
11807
11852
|
//#region src/core/sdk/middlewareStack.ts
|
|
11808
|
-
var
|
|
11853
|
+
var Sp = {
|
|
11809
11854
|
dataHint: 10,
|
|
11810
11855
|
usageHints: 20,
|
|
11811
11856
|
todos: 30,
|
|
@@ -11822,17 +11867,17 @@ var yp = {
|
|
|
11822
11867
|
subagents: 140,
|
|
11823
11868
|
augmentSystem: 150
|
|
11824
11869
|
};
|
|
11825
|
-
function
|
|
11870
|
+
function Cp(e) {
|
|
11826
11871
|
return e.map((e, t) => ({
|
|
11827
11872
|
m: e,
|
|
11828
11873
|
i: t,
|
|
11829
|
-
p:
|
|
11874
|
+
p: Sp[e.name] ?? Infinity
|
|
11830
11875
|
})).sort((e, t) => e.p - t.p || e.i - t.i).map((e) => e.m);
|
|
11831
11876
|
}
|
|
11832
11877
|
//#endregion
|
|
11833
11878
|
//#region src/core/tools/fetchDoc.ts
|
|
11834
|
-
var
|
|
11835
|
-
let n = new AbortController(), r = setTimeout(() => n.abort(),
|
|
11879
|
+
var wp = 3e4, Tp = [r(async ({ url: e, as: t }) => {
|
|
11880
|
+
let n = new AbortController(), r = setTimeout(() => n.abort(), wp);
|
|
11836
11881
|
try {
|
|
11837
11882
|
let r = await fetch(e, {
|
|
11838
11883
|
method: "GET",
|
|
@@ -11849,7 +11894,7 @@ var xp = 3e4, Sp = [r(async ({ url: e, as: t }) => {
|
|
|
11849
11894
|
].join("\n");
|
|
11850
11895
|
} catch (t) {
|
|
11851
11896
|
let r = t?.message || String(t);
|
|
11852
|
-
return n.signal.aborted ? `获取失败:请求超时(${
|
|
11897
|
+
return n.signal.aborted ? `获取失败:请求超时(${wp}ms,${e})。` : /Failed to fetch|NetworkError|CORS|blocked/i.test(r) ? `获取失败:可能是 CORS 跨域拦截或网络错误(${r})。浏览器仅能 GET 同源或服务端已配置 CORS 的资源;跨域抓取需后端代理。` : `获取失败:${r}`;
|
|
11853
11898
|
} finally {
|
|
11854
11899
|
clearTimeout(r);
|
|
11855
11900
|
}
|
|
@@ -11860,7 +11905,7 @@ var xp = 3e4, Sp = [r(async ({ url: e, as: t }) => {
|
|
|
11860
11905
|
url: t.string().describe("要抓取的 URL(同源或已配 CORS)"),
|
|
11861
11906
|
as: t.enum(["text", "markdown"]).optional().describe("返回格式标签,默认 text")
|
|
11862
11907
|
})
|
|
11863
|
-
})],
|
|
11908
|
+
})], Ep = [
|
|
11864
11909
|
"id",
|
|
11865
11910
|
"class",
|
|
11866
11911
|
"href",
|
|
@@ -11872,12 +11917,12 @@ var xp = 3e4, Sp = [r(async ({ url: e, as: t }) => {
|
|
|
11872
11917
|
"aria-label",
|
|
11873
11918
|
"name",
|
|
11874
11919
|
"type"
|
|
11875
|
-
],
|
|
11876
|
-
function
|
|
11920
|
+
], Dp = /^(value|srcdoc|formaction|on\w+)$/i, Op = /token|secret|password|passwd|api[-_]?key|auth|cred|csrf|session/i;
|
|
11921
|
+
function kp(e, t) {
|
|
11877
11922
|
if (!e) return null;
|
|
11878
|
-
let { depth: n, attrs: r, includeText: i = !0 } = t, a = r !== void 0, o = r ??
|
|
11923
|
+
let { depth: n, attrs: r, includeText: i = !0 } = t, a = r !== void 0, o = r ?? Ep, s = (e) => {
|
|
11879
11924
|
let t = {};
|
|
11880
|
-
for (let n of Array.from(e.attributes)) (a ? o.includes(n.name) : o.includes(n.name) || n.name.startsWith("data-")) && (
|
|
11925
|
+
for (let n of Array.from(e.attributes)) (a ? o.includes(n.name) : o.includes(n.name) || n.name.startsWith("data-")) && (Dp.test(n.name) || Op.test(n.name) || (t[n.name] = n.value));
|
|
11881
11926
|
return t;
|
|
11882
11927
|
}, c = (e, t) => {
|
|
11883
11928
|
let n = {
|
|
@@ -11893,10 +11938,10 @@ function Ep(e, t) {
|
|
|
11893
11938
|
};
|
|
11894
11939
|
return c(e, n);
|
|
11895
11940
|
}
|
|
11896
|
-
var
|
|
11941
|
+
var Ap = r(({ selector: e, depth: t, attrs: n, includeText: r }) => {
|
|
11897
11942
|
let i = e ? document.querySelector(e) : document.body;
|
|
11898
11943
|
if (!i) return `未找到匹配元素:selector="${e}"`;
|
|
11899
|
-
let a =
|
|
11944
|
+
let a = kp(i, {
|
|
11900
11945
|
depth: t ?? 3,
|
|
11901
11946
|
attrs: n,
|
|
11902
11947
|
includeText: r ?? !0
|
|
@@ -11911,22 +11956,22 @@ var Dp = r(({ selector: e, depth: t, attrs: n, includeText: r }) => {
|
|
|
11911
11956
|
attrs: t.array(t.string()).optional().describe("属性白名单(传了 = 严格白名单;不传 = 默认常用 + data-*)"),
|
|
11912
11957
|
includeText: t.boolean().optional().describe("是否包含直接文本(默认 true)")
|
|
11913
11958
|
})
|
|
11914
|
-
}),
|
|
11915
|
-
function
|
|
11916
|
-
if (
|
|
11959
|
+
}), jp = [Ap], Mp = /* @__PURE__ */ "display.position.visibility.opacity.color.background-color.background-image.font-size.font-weight.line-height.text-align.z-index.overflow.width.height.margin.padding.border.border-radius.box-shadow.transform.transition.animation.cursor.pointer-events.flex-direction.gap.max-width.min-height".split("."), Np = /* @__PURE__ */ new WeakMap(), Pp = !1;
|
|
11960
|
+
function Fp() {
|
|
11961
|
+
if (Pp) return;
|
|
11917
11962
|
let e = globalThis.EventTarget;
|
|
11918
11963
|
if (!e?.prototype?.addEventListener) return;
|
|
11919
|
-
|
|
11964
|
+
Pp = !0;
|
|
11920
11965
|
let t = e.prototype.addEventListener, n = e.prototype.removeEventListener;
|
|
11921
11966
|
e.prototype.addEventListener = function(e, ...n) {
|
|
11922
11967
|
try {
|
|
11923
|
-
let t =
|
|
11924
|
-
t || (t = /* @__PURE__ */ new Map(),
|
|
11968
|
+
let t = Np.get(this);
|
|
11969
|
+
t || (t = /* @__PURE__ */ new Map(), Np.set(this, t)), t.set(String(e), (t.get(String(e)) ?? 0) + 1);
|
|
11925
11970
|
} catch {}
|
|
11926
11971
|
return t.call(this, e, ...n);
|
|
11927
11972
|
}, e.prototype.removeEventListener = function(e, ...t) {
|
|
11928
11973
|
try {
|
|
11929
|
-
let t =
|
|
11974
|
+
let t = Np.get(this);
|
|
11930
11975
|
if (t) {
|
|
11931
11976
|
let n = (t.get(String(e)) ?? 1) - 1;
|
|
11932
11977
|
n <= 0 ? t.delete(String(e)) : t.set(String(e), n);
|
|
@@ -11935,10 +11980,10 @@ function Mp() {
|
|
|
11935
11980
|
return n.call(this, e, ...t);
|
|
11936
11981
|
};
|
|
11937
11982
|
}
|
|
11938
|
-
function
|
|
11939
|
-
return [...
|
|
11983
|
+
function Ip(e) {
|
|
11984
|
+
return [...Np.get(e)?.entries() ?? []].filter(([, e]) => e > 0).map(([e]) => e);
|
|
11940
11985
|
}
|
|
11941
|
-
function
|
|
11986
|
+
function Lp(e, t = 12) {
|
|
11942
11987
|
let n = [], r = e, i = 0;
|
|
11943
11988
|
for (; r && r.tagName && i < t;) {
|
|
11944
11989
|
let e = r.tagName.toLowerCase(), t = r.id;
|
|
@@ -11959,7 +12004,7 @@ function Pp(e, t = 12) {
|
|
|
11959
12004
|
}
|
|
11960
12005
|
return n.join(" > ");
|
|
11961
12006
|
}
|
|
11962
|
-
function
|
|
12007
|
+
function Rp(e, t, n = {}) {
|
|
11963
12008
|
if (!e) return {
|
|
11964
12009
|
hits: [],
|
|
11965
12010
|
total: 0,
|
|
@@ -11997,7 +12042,7 @@ function Fp(e, t, n = {}) {
|
|
|
11997
12042
|
n = r.slice(Math.max(0, i - 20), i + t.length + 40);
|
|
11998
12043
|
}
|
|
11999
12044
|
return {
|
|
12000
|
-
selector:
|
|
12045
|
+
selector: Lp(e),
|
|
12001
12046
|
tag: e.tagName.toLowerCase(),
|
|
12002
12047
|
text: n.slice(0, 120)
|
|
12003
12048
|
};
|
|
@@ -12006,7 +12051,7 @@ function Fp(e, t, n = {}) {
|
|
|
12006
12051
|
truncated: a.length > o
|
|
12007
12052
|
};
|
|
12008
12053
|
}
|
|
12009
|
-
var
|
|
12054
|
+
var zp = [
|
|
12010
12055
|
"content",
|
|
12011
12056
|
"display",
|
|
12012
12057
|
"width",
|
|
@@ -12014,14 +12059,14 @@ var Ip = [
|
|
|
12014
12059
|
"background-color",
|
|
12015
12060
|
"position"
|
|
12016
12061
|
];
|
|
12017
|
-
function
|
|
12062
|
+
function Bp(e, t = {}) {
|
|
12018
12063
|
if (!e) return null;
|
|
12019
12064
|
let n = {
|
|
12020
|
-
selector:
|
|
12065
|
+
selector: Lp(e),
|
|
12021
12066
|
tag: e.tagName.toLowerCase(),
|
|
12022
12067
|
attrs: {}
|
|
12023
12068
|
};
|
|
12024
|
-
for (let t of Array.from(e.attributes)) !(
|
|
12069
|
+
for (let t of Array.from(e.attributes)) !(Ep.includes(t.name) || t.name.startsWith("data-")) || Dp.test(t.name) || Op.test(t.name) || (n.attrs[t.name] = t.value);
|
|
12025
12070
|
let r = Array.from(e.childNodes).filter((e) => e.nodeType === 3).map((e) => e.textContent || "").join("").trim();
|
|
12026
12071
|
r && (n.text = r.slice(0, 400));
|
|
12027
12072
|
let i = String(e.innerText ?? e.textContent ?? "").trim();
|
|
@@ -12043,7 +12088,7 @@ function Lp(e, t = {}) {
|
|
|
12043
12088
|
if (typeof a != "function") return r;
|
|
12044
12089
|
try {
|
|
12045
12090
|
let i = a(e, n ?? null);
|
|
12046
|
-
for (let e of n ?
|
|
12091
|
+
for (let e of n ? zp : t.styles ?? Mp) {
|
|
12047
12092
|
let t = typeof i.getPropertyValue == "function" ? i.getPropertyValue(e) : i[e];
|
|
12048
12093
|
t && (r[e] = String(t).slice(0, 200));
|
|
12049
12094
|
}
|
|
@@ -12061,16 +12106,16 @@ function Lp(e, t = {}) {
|
|
|
12061
12106
|
n.events = {
|
|
12062
12107
|
inline: t,
|
|
12063
12108
|
vue: r ? Object.keys(r).filter((e) => /^on[A-Z]/.test(e)).map((e) => e.slice(2).toLowerCase()) : [],
|
|
12064
|
-
captured:
|
|
12109
|
+
captured: Ip(e)
|
|
12065
12110
|
};
|
|
12066
12111
|
}
|
|
12067
12112
|
return n;
|
|
12068
12113
|
}
|
|
12069
|
-
var
|
|
12070
|
-
|
|
12114
|
+
var Vp = r(({ query: e, mode: t, limit: n, root: r }) => {
|
|
12115
|
+
Fp();
|
|
12071
12116
|
let i = r ? document.querySelector(r) : document;
|
|
12072
12117
|
if (r && !i) return `未找到 root 元素:selector="${r}"`;
|
|
12073
|
-
let a =
|
|
12118
|
+
let a = Rp(i, e, {
|
|
12074
12119
|
mode: t,
|
|
12075
12120
|
limit: n
|
|
12076
12121
|
});
|
|
@@ -12087,11 +12132,11 @@ var Rp = r(({ query: e, mode: t, limit: n, root: r }) => {
|
|
|
12087
12132
|
limit: t.number().int().min(1).max(20).optional().describe("返回上限(默认 10)"),
|
|
12088
12133
|
root: t.string().optional().describe("限定搜索范围的容器选择器(默认整页)")
|
|
12089
12134
|
})
|
|
12090
|
-
}),
|
|
12091
|
-
|
|
12135
|
+
}), Hp = r(({ selector: e, styles: t, includeHtml: n, htmlLimit: r, includeEvents: i, includeRect: a, pseudo: o }) => {
|
|
12136
|
+
Fp();
|
|
12092
12137
|
let s = document.querySelector(e);
|
|
12093
12138
|
if (!s) return `未找到匹配元素:selector="${e}"(可先用 dom_search 定位)`;
|
|
12094
|
-
let c =
|
|
12139
|
+
let c = Bp(s, {
|
|
12095
12140
|
styles: t,
|
|
12096
12141
|
includeHtml: n,
|
|
12097
12142
|
htmlLimit: r,
|
|
@@ -12112,7 +12157,7 @@ var Rp = r(({ query: e, mode: t, limit: n, root: r }) => {
|
|
|
12112
12157
|
includeRect: t.boolean().optional().describe("是否含几何位置(默认 true)"),
|
|
12113
12158
|
pseudo: t.boolean().optional().describe("是否含 ::before/::after 伪元素摘要(默认 false)")
|
|
12114
12159
|
})
|
|
12115
|
-
}),
|
|
12160
|
+
}), Up = {
|
|
12116
12161
|
name: "dom-inspect",
|
|
12117
12162
|
description: "页面 DOM 深度检视工具(dom_search 搜索元素 / dom_info 读内容·计算样式·事件绑定·几何)。定位元素、验证样式落地、排查交互绑定时加载",
|
|
12118
12163
|
getContent: () => [
|
|
@@ -12129,15 +12174,15 @@ var Rp = r(({ query: e, mode: t, limit: n, root: r }) => {
|
|
|
12129
12174
|
"## 排障套路",
|
|
12130
12175
|
"1. dom_search(mode:\"text\", query:按钮文案) 定位 → 2. dom_info(styles:[\"display\",\"background-color\",\"pointer-events\"]) 验证样式/点击性 → 3. 不符则改数据(get_dom 看结构对照)"
|
|
12131
12176
|
].join("\n"),
|
|
12132
|
-
tools: [() => [
|
|
12177
|
+
tools: [() => [Vp, Hp]]
|
|
12133
12178
|
};
|
|
12134
12179
|
//#endregion
|
|
12135
12180
|
//#region src/core/tools/envTool.ts
|
|
12136
|
-
function
|
|
12181
|
+
function Wp(e) {
|
|
12137
12182
|
let t = e;
|
|
12138
12183
|
return typeof t.tagName == "string" || typeof t.nodeType == "number" && typeof t.nodeName == "string";
|
|
12139
12184
|
}
|
|
12140
|
-
function
|
|
12185
|
+
function Gp(e, t = 3, n = 2e3, r, i) {
|
|
12141
12186
|
if (e == null) return e;
|
|
12142
12187
|
if (typeof e == "string") return e.length > n ? e.slice(0, n) + "…(已截断)" : e;
|
|
12143
12188
|
if (typeof e == "number" || typeof e == "boolean") return e;
|
|
@@ -12146,14 +12191,14 @@ function Hp(e, t = 3, n = 2e3, r, i) {
|
|
|
12146
12191
|
if (typeof e == "bigint") return `${e.toString()}n`;
|
|
12147
12192
|
if (typeof e != "object") return String(e);
|
|
12148
12193
|
let a = e;
|
|
12149
|
-
if (
|
|
12194
|
+
if (Wp(a)) {
|
|
12150
12195
|
let e = a;
|
|
12151
12196
|
return e.tagName ? `[Element: <${e.tagName.toLowerCase()}>]` : `[Node: ${e.nodeName}]`;
|
|
12152
12197
|
}
|
|
12153
12198
|
if (r?.has(a)) return "[Circular]";
|
|
12154
12199
|
let o = r ?? /* @__PURE__ */ new WeakSet();
|
|
12155
12200
|
if (o.add(a), Array.isArray(e)) {
|
|
12156
|
-
let r = e.slice(0, 100).map((e) =>
|
|
12201
|
+
let r = e.slice(0, 100).map((e) => Gp(e, t - 1, n, o, i));
|
|
12157
12202
|
return e.length > 100 && r.push(`…(共 ${e.length} 项,已截断)`), r;
|
|
12158
12203
|
}
|
|
12159
12204
|
if (t < 0) return "(对象,已截断)";
|
|
@@ -12166,14 +12211,14 @@ function Hp(e, t = 3, n = 2e3, r, i) {
|
|
|
12166
12211
|
}
|
|
12167
12212
|
try {
|
|
12168
12213
|
let e = a[r];
|
|
12169
|
-
i?.test(r) ? s[r] = "[REDACTED]" : s[r] =
|
|
12214
|
+
i?.test(r) ? s[r] = "[REDACTED]" : s[r] = Gp(e, t - 1, n, o, i);
|
|
12170
12215
|
} catch {
|
|
12171
12216
|
s[r] = "(getter 抛错)";
|
|
12172
12217
|
}
|
|
12173
12218
|
}
|
|
12174
12219
|
return s;
|
|
12175
12220
|
}
|
|
12176
|
-
function
|
|
12221
|
+
function Kp(e) {
|
|
12177
12222
|
let t = e ?? (typeof window < "u" ? window : {}), n = t.navigator, r = t.location, i = t.document;
|
|
12178
12223
|
return {
|
|
12179
12224
|
location: {
|
|
@@ -12206,9 +12251,9 @@ function Up(e) {
|
|
|
12206
12251
|
} : "(无 document)"
|
|
12207
12252
|
};
|
|
12208
12253
|
}
|
|
12209
|
-
var
|
|
12254
|
+
var qp = /^(localStorage|sessionStorage|cookie|document|frames|frameElement|opener|parent|top|self|window|globalThis|closed|history|navigation|trustedTypes|origin|crossOriginIsolated)$/, Jp = /token|secret|password|passwd|api[-_]?key|auth|cred|csrf|session|ticket/i, Yp = r(({ key: e }) => {
|
|
12210
12255
|
if (e) {
|
|
12211
|
-
if (
|
|
12256
|
+
if (qp.test(e) || Jp.test(e)) return JSON.stringify({
|
|
12212
12257
|
key: e,
|
|
12213
12258
|
denied: !0,
|
|
12214
12259
|
reason: "安全:该 key 在 denylist(localStorage/sessionStorage/cookie/document 或敏感命名 token/secret/key/auth),不读取防泄漏"
|
|
@@ -12218,18 +12263,18 @@ var Wp = /^(localStorage|sessionStorage|cookie|document|frames|frameElement|open
|
|
|
12218
12263
|
key: e,
|
|
12219
12264
|
exists: t !== void 0,
|
|
12220
12265
|
type: typeof t,
|
|
12221
|
-
value:
|
|
12266
|
+
value: Gp(t, 3, 2e3, void 0, Jp)
|
|
12222
12267
|
}, null, 2);
|
|
12223
12268
|
}
|
|
12224
|
-
return JSON.stringify(
|
|
12269
|
+
return JSON.stringify(Kp(), null, 2);
|
|
12225
12270
|
}, {
|
|
12226
12271
|
name: "inspect_env",
|
|
12227
12272
|
description: "读宿主页面环境信息(排查调试)。不传参返回摘要(URL/origin、浏览器/语言、viewport、title/readyState);传 key 读指定 window 属性值(如 key:\"appConfig\")。只读,大结果自动外存 vfs。",
|
|
12228
12273
|
schema: t.object({ key: t.string().optional().describe("要读取的 window 属性名(如 \"appConfig\"/\"__DEBUG__\");不传 = 返回环境摘要") })
|
|
12229
|
-
}),
|
|
12274
|
+
}), Xp = [Yp];
|
|
12230
12275
|
//#endregion
|
|
12231
12276
|
//#region src/core/harness/budget.ts
|
|
12232
|
-
function
|
|
12277
|
+
function Zp(e, t, n) {
|
|
12233
12278
|
let r = 0;
|
|
12234
12279
|
return {
|
|
12235
12280
|
name: "budget",
|
|
@@ -12254,12 +12299,12 @@ function Jp(e, t, n) {
|
|
|
12254
12299
|
}
|
|
12255
12300
|
//#endregion
|
|
12256
12301
|
//#region src/core/sdk/actions.ts
|
|
12257
|
-
var
|
|
12258
|
-
function
|
|
12302
|
+
var Qp = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
12303
|
+
function $p(e) {
|
|
12259
12304
|
let n = [];
|
|
12260
12305
|
for (let [i, a] of Object.entries(e)) {
|
|
12261
|
-
if (!
|
|
12262
|
-
console.warn(`[page-agent-sdk][actions] 动作名 "${i}" 非法(须匹配 ${
|
|
12306
|
+
if (!Qp.test(i)) {
|
|
12307
|
+
console.warn(`[page-agent-sdk][actions] 动作名 "${i}" 非法(须匹配 ${Qp}),已跳过`);
|
|
12263
12308
|
continue;
|
|
12264
12309
|
}
|
|
12265
12310
|
let e = a.description || `宿主动作 ${i}`;
|
|
@@ -12279,9 +12324,9 @@ function Xp(e) {
|
|
|
12279
12324
|
}
|
|
12280
12325
|
return n;
|
|
12281
12326
|
}
|
|
12282
|
-
function
|
|
12327
|
+
function em(e) {
|
|
12283
12328
|
let t = {};
|
|
12284
|
-
for (let [n, r] of Object.entries(e))
|
|
12329
|
+
for (let [n, r] of Object.entries(e)) Qp.test(n) && (t[n] = {
|
|
12285
12330
|
description: r.description,
|
|
12286
12331
|
hasParams: !!r.params
|
|
12287
12332
|
});
|
|
@@ -12289,12 +12334,12 @@ function Zp(e) {
|
|
|
12289
12334
|
}
|
|
12290
12335
|
//#endregion
|
|
12291
12336
|
//#region src/core/toolsets.ts
|
|
12292
|
-
var
|
|
12293
|
-
function
|
|
12294
|
-
return
|
|
12337
|
+
var tm = Tp, nm = jp;
|
|
12338
|
+
function rm(e, t) {
|
|
12339
|
+
return hd(e, t);
|
|
12295
12340
|
}
|
|
12296
|
-
function
|
|
12297
|
-
let a =
|
|
12341
|
+
function im(e, t, n, r, i) {
|
|
12342
|
+
let a = _p(e);
|
|
12298
12343
|
return [
|
|
12299
12344
|
...a.dataOps ? t : [],
|
|
12300
12345
|
...a.fetch ? n : [],
|
|
@@ -12304,7 +12349,7 @@ function tm(e, t, n, r, i) {
|
|
|
12304
12349
|
}
|
|
12305
12350
|
//#endregion
|
|
12306
12351
|
//#region src/core/sdk/toolRegistry.ts
|
|
12307
|
-
function
|
|
12352
|
+
function am(e) {
|
|
12308
12353
|
let t = /* @__PURE__ */ new Map(), n = [];
|
|
12309
12354
|
for (let r of e) for (let e of r.tools) {
|
|
12310
12355
|
let i = t.get(e.name);
|
|
@@ -12324,15 +12369,15 @@ function nm(e) {
|
|
|
12324
12369
|
}
|
|
12325
12370
|
//#endregion
|
|
12326
12371
|
//#region src/core/harness/usageHints.ts
|
|
12327
|
-
var
|
|
12328
|
-
function
|
|
12329
|
-
let r =
|
|
12372
|
+
var om = .7;
|
|
12373
|
+
function sm(e, t, n) {
|
|
12374
|
+
let r = _p(e);
|
|
12330
12375
|
return {
|
|
12331
12376
|
name: "usageHints",
|
|
12332
12377
|
augmentPrompt: (i) => {
|
|
12333
12378
|
let a = [];
|
|
12334
12379
|
if (r.planning && (a.push("【自适应规划】按任务复杂度决定是否先规划,不要对简单任务过度编排:"), a.push(" · 简单/明确任务(改单字段、调样式、查值)→ 直接 read/write 执行,不必 write_todos。"), a.push(" · 复杂任务(多步、大改、有歧义、不可逆)→ 先 write_todos 拆解,首个任务标 in_progress,逐项推进。"), a.push(" · 执行中发现步骤要改/补/细分 → 用 update_todo({id, content?, status?}) 按 id 增量改单项,不必重传整个清单。"), a.push(" · update_todo 标 completed 时附 evidence: 本次实际写入的 jsonPath(如 \"components.2\"),供收口对账;工作经委派子 agent 完成等无主写路径时,如实写明完成方式(勿编造路径)。"), e?.humanConfirm ? a.push(" · 规划出多步方案若需用户拍板 → 先 request_human_confirmation 给方案选项,确认后再执行。") : a.push(" · 规划出多步方案若需用户拍板 → 以文字列出方案选项等用户回复,勿自行拍板。"), a.push(" · 计划修订有次数上限(maxPlanRevisions,默认 5,只计 write_todos 调用、调研轮不计):勿反复改计划而不执行,规划充分后即开始 write 落地。")), t && (a.push("改主数据前先 read({jsonPath}) 读其当前真实值(返回末尾 hash=xxx 为乐观锁标识),基于真实值改,不要凭记忆。写入是否被自动校验由集成方 conflictWatchFields 声明决定:若已声明且主数据在你 read 之后被外部改过,会触发冲突——集成方若开启人工介入,工具会挂起等用户决定(保留外部/强制覆盖/回退),你应等待工具返回后按结果继续(保留外部→重新 read 再改;强制覆盖→已写入,继续;回退→已回退到历史快照,基于回退值重写);未开启人工介入时返回 VERSION_CONFLICT 不写入,重新 read 拿最新值再改。"), a.push("读类分流:取值/结构 → read(多路径用 jsonPaths);字段约束 → schema_data;条件筛选定位 → query_data(多条一次用 queries);名字模糊找 → search_data;整体说明 → read 不传路径(= describe_data)。"), a.push("修改大对象/数组优先用 write 增量改({patch:{op,jsonPath,value}} 只发改动部分),避免 write({value}) 整体重传被 max_tokens 截断导致 JSON 不完整、校验失败。"), a.push("修改主数据出错时可用 restore_data 回退最近一次。"), a.push("在大数组里按条件筛选元素用 query_data(JSONPath,如 $.components[?(@.type==\"card\" && @.price<100)]),返回匹配元素的 path/index;定位后再 write({patch}) 改。"), a.push("找名字记不清的元素用 search_data(支持 substring/regex/fuzzy 模糊搜索)。"), a.push("需要过滤/映射/聚合/批量重写大数组时用 eval_script(沙箱脚本,入参 data);只读探查用 mode=query,批量重写用 mode=transform(返回值经校验后落地)。"), a.push("读大数组用 read({jsonPath,offset,limit}) 分页(返回 hasMore=true 时 offset+=limit 续读);一次读多个不相关子路径用 read({jsonPaths});复杂改动先 write({...,dryRun:true}) 预检不落盘。"), a.push("【省轮次·批量】≥2 个路径一律 read({jsonPaths:[...]}) 一次取回(路径互不相关也合批,禁止连续单路径 read);多条件筛选用 query_data({queries:[expr1,expr2,…]}) 一次取回(2-10 条);改多处用 write({patches:[{op:\"set\",jsonPath,value},...]}) 一次提交多改动(原子任一失败回滚),勿逐个 write 烧轮次预算。"), a.push("读到 <subtree Nkb keys:[…] #指纹> 或 <code Nkb> 占位 = 该子树键名/体积可见但内容未见:写入前先窄读全文(read({jsonPath:\"该子树路径\"}),结果根豁免返全文)或 set_focus 聚焦该区域;勿凭键名印象猜路径/猜值直写(直接写占位子树会被拦下要求先窄读)。"), a.push("对比当前与历史快照(或一段 JSON against)的差异用 diff_data({snapshotId?,against?})(返回结构化 path→from/to,verify 自纠/操作审计/\"刚才改了啥\");只读查历史快照值用 history_data({id?,jsonPath?})。")), r.subagent && a.push("独立子任务可 spawn_agent 委派(过程隔离,不占主上下文):默认只读,需要子 agent 写数据时传 writablePaths(路径前缀白名单,越界 PATH_OUT_OF_SCOPE)。多个独立子任务可 spawn_agents 并行委派(各子互不通信,结论由你汇总;并行委派不可授写权限,写操作由你收尾执行)。"), r.inspectEnv && a.push("排查页面环境(当前 URL/浏览器/视口/集成方调试变量)用 inspect_env——不传参返回环境摘要(location/navigator/viewport/document),传 key 读特定 window 属性(如 inspect_env({key:\"appConfig\"}) 读 window.appConfig)。改完数据看渲染、定位\"为何没生效\"时用它(只读,不改数据)。"), r.domInspect && a.push("改完数据想确认渲染是否生效(或定位元素/辅助 UI 设计问答)用 get_dom({selector?,depth?}) 读渲染后 DOM(结构化返回 tag/attrs/text/children,depth 控制深度防爆炸,只读)。配合宿主 actions(save_draft/publish 等)形成\"改数据→get_dom 看渲染→触发动作\"闭环。"), r.draftWrite && (a.push("生成超大 JSON(如 50+ 组件页面,单次 write 受 max_tokens 限制装不下)用 draft_write 分块构建 → draft_commit 原子提交:draft_write({draftId, chunk, mode}) mode:\"start\" 新建/\"append\" 追加(拼 JSON 片段到 drafts 池);累积完 draft_commit({draftId}) 合并 + schema 校验 + 写主数据(失败草稿保留可修后重试,成功自动清草稿)。小改仍用 write patch,只在大 JSON 从零生成时用 draft。"), a.push("⚠️ 大 JSON 分块构建是典型多轮工具调用(draft_write×N + draft_commit + read 确认 + 调研 read/query),默认 maxToolRounds=30(3.43 起;轮次预算吃紧时 system 会注入预算提示段,按提示优先收口);目标组件数很大时集成方仍可在 createChatSdk 显式上调 maxToolRounds(按 N+10 估算)。draft_commit 提交同样走乐观锁(改前 read 拿 hash,bind 被改过会触发冲突介入,不静默覆盖)。")), r.focus && (a.push("【上下文聚焦】判断任务范围,用 set_focus/add_focus/remove_focus/clear_focus 自动收敛工作范围:"), a.push(" · 局部任务(只改某一组件/区域,如「调导航栏」「改 components.3 样式」)→ 先 read 定位 jsonPath,再 set_focus({path:\"该子树路径\"}) 聚焦;聚焦后每轮只看该子树结构,写其他位置会被 PATH_DENIED 拒绝。"), a.push(" · 多个相关组件(如「同时改导航栏和页脚」)→ set_focus 聚焦首个后用 add_focus({path}) 追加其余;聚焦后可写任一焦点子树,越界仍被拒;移除单个用 remove_focus({path})。"), a.push(" · 全局任务(多处/整体结构,如「重排所有组件」「换主题」)→ 不要聚焦,保持全量视野直接写。"), a.push(" · 完成局部精修、要转向其他区域或做整体改动 → 调 clear_focus 退出聚焦(清空全部焦点),恢复全部读写权限。"), a.push(" · set_focus/add_focus 的 path 必须在 schema 内(类型校验);不确定路径先 read/describe_data 查。")), e?.subagents?.length) {
|
|
12335
|
-
let t = e.subagents.filter((e) => (e.temperature ?? 0) >=
|
|
12380
|
+
let t = e.subagents.filter((e) => (e.temperature ?? 0) >= om || /规划|创意|设计|方案|brainstorm|plan/i.test(e.description)), n = e.subagents.filter((e) => (e.temperature ?? 0) < om && /反思|审查|挑刺|校验|review|critique|reflect/i.test(e.description));
|
|
12336
12381
|
a.push("【规划-反思-执行·路由】按任务性质选模式,不要对简单任务过度编排:"), t.length && (a.push(` · 创作/设计/开放性需求(如"设计主题风格""换个感觉")→ 先调 ${t.map((e) => "use_" + e.id).join("/")} 出 2-3 套方案(高温创意),`), a.push(e?.humanConfirm ? " 不要自己拍板;拿到方案后,若需用户拍板用 request_human_confirmation 弹选项。" : " 不要自己拍板;拿到方案后以文字列出选项等用户回复(humanConfirm 未开,勿调不存在工具)。")), n.length && a.push(` · 严谨/易错/校验类 → 可先调 ${n.map((e) => "use_" + e.id).join("/")} 反思挑刺(低温审查),据反馈修订。`), a.push(" · 方案定稿后,由你(主 agent)用 write 落地成 JSON(低温度执行 + schema 校验 + 写前确认)。"), a.push(" · 简单/明确任务(如\"标题改红色\")直接执行,不必走规划-反思。");
|
|
12337
12382
|
}
|
|
12338
12383
|
e?.humanConfirm && (a.push("【人工确认·必读】以下情形必须先调 request_human_confirmation 征询用户、拿到答复后再继续,不要自行拍板:"), a.push(" 1) 用户让你「给方案/列选项/我来选/挑一个」时:把每个方案作为一个 option,调 request_human_confirmation(question=简述, options=[方案A,方案B,...], recommendation=你推荐的)。不要只回文字罗列方案让用户自己回复——要用工具把选项做成可点选按钮。"), a.push(" 2) 需求有歧义/不确定时:调工具问清楚(options 不传则用户答同意或拒绝)。"), a.push(" 3) 即将执行高风险不可逆操作(删除/覆盖/批量改动)前:调工具确认。"), a.push(" 4) 规划出多步方案需用户确认时:把整个方案(或关键分步)作为 option 调 request_human_confirmation,确认后再执行。"), a.push("用户在选项里选了哪个,就按那个方案继续;选「拒绝」则停止并询问如何调整。"));
|
|
@@ -12352,7 +12397,7 @@ function im(e, t, n) {
|
|
|
12352
12397
|
}
|
|
12353
12398
|
//#endregion
|
|
12354
12399
|
//#region src/core/harness/resourcesPin.ts
|
|
12355
|
-
function
|
|
12400
|
+
function cm(e) {
|
|
12356
12401
|
return {
|
|
12357
12402
|
name: "resourcesPin",
|
|
12358
12403
|
augmentPrompt: () => {
|
|
@@ -12366,66 +12411,66 @@ function am(e) {
|
|
|
12366
12411
|
}
|
|
12367
12412
|
//#endregion
|
|
12368
12413
|
//#region src/core/backends/skillStore.ts
|
|
12369
|
-
var
|
|
12370
|
-
function
|
|
12371
|
-
return `${
|
|
12414
|
+
var lm = "v:1::skill-store", um = "chat-sdk";
|
|
12415
|
+
function dm(e, t, n) {
|
|
12416
|
+
return `${lm}::${e}::${t}::${n}`;
|
|
12372
12417
|
}
|
|
12373
|
-
function
|
|
12374
|
-
return `${
|
|
12418
|
+
function fm(e, t) {
|
|
12419
|
+
return `${lm}::${e}::${t}::`;
|
|
12375
12420
|
}
|
|
12376
|
-
function
|
|
12377
|
-
let t = e.dbName ??
|
|
12421
|
+
function pm(e = {}) {
|
|
12422
|
+
let t = e.dbName ?? um, n = e.backend ?? "indexed", r = e.id ?? "", i, a, o = new Promise((e) => {
|
|
12378
12423
|
a = e;
|
|
12379
12424
|
});
|
|
12380
12425
|
return (async () => {
|
|
12381
12426
|
try {
|
|
12382
12427
|
if (n === "indexed") {
|
|
12383
12428
|
if (typeof indexedDB > "u") throw Error("indexedDB 不可用");
|
|
12384
|
-
i = await
|
|
12429
|
+
i = await cp(t), a(!0);
|
|
12385
12430
|
} else if (n === "session") {
|
|
12386
12431
|
if (typeof sessionStorage > "u") throw Error("sessionStorage 不可用");
|
|
12387
|
-
i =
|
|
12432
|
+
i = lp(sessionStorage), a(!0);
|
|
12388
12433
|
} else if (n === "local") {
|
|
12389
12434
|
if (typeof localStorage > "u") throw Error("localStorage 不可用");
|
|
12390
|
-
i =
|
|
12391
|
-
} else i =
|
|
12435
|
+
i = lp(localStorage), a(!0);
|
|
12436
|
+
} else i = sp(), a(!1);
|
|
12392
12437
|
} catch {
|
|
12393
|
-
i =
|
|
12438
|
+
i = sp(), a(!1);
|
|
12394
12439
|
}
|
|
12395
12440
|
})(), {
|
|
12396
12441
|
ready: o,
|
|
12397
12442
|
async list() {
|
|
12398
12443
|
let e = [];
|
|
12399
|
-
return await i.scan(
|
|
12444
|
+
return await i.scan(fm(t, r), (t, n) => {
|
|
12400
12445
|
e.push(n);
|
|
12401
12446
|
}), e;
|
|
12402
12447
|
},
|
|
12403
12448
|
async get(e) {
|
|
12404
|
-
return await i.get(
|
|
12449
|
+
return await i.get(dm(t, r, e));
|
|
12405
12450
|
},
|
|
12406
12451
|
async put(e) {
|
|
12407
12452
|
try {
|
|
12408
|
-
await i.set(
|
|
12453
|
+
await i.set(dm(t, r, e.name), e);
|
|
12409
12454
|
} catch (e) {
|
|
12410
|
-
|
|
12455
|
+
$f(e) && (i = sp());
|
|
12411
12456
|
}
|
|
12412
12457
|
},
|
|
12413
12458
|
async remove(e) {
|
|
12414
|
-
let n =
|
|
12459
|
+
let n = dm(t, r, e);
|
|
12415
12460
|
return await i.get(n) == null ? !1 : (await i.del(n), !0);
|
|
12416
12461
|
},
|
|
12417
12462
|
async clear() {
|
|
12418
|
-
await i.clearPrefix(
|
|
12463
|
+
await i.clearPrefix(fm(t, r));
|
|
12419
12464
|
},
|
|
12420
12465
|
dispose() {}
|
|
12421
12466
|
};
|
|
12422
12467
|
}
|
|
12423
|
-
var
|
|
12424
|
-
function
|
|
12468
|
+
var mm = /large_results\/[^\s"'`),]+\.txt/g;
|
|
12469
|
+
function hm(e) {
|
|
12425
12470
|
let t = /* @__PURE__ */ new Set(), n = (e) => {
|
|
12426
12471
|
if (typeof e != "string" || !e) return;
|
|
12427
12472
|
let n;
|
|
12428
|
-
for (
|
|
12473
|
+
for (mm.lastIndex = 0; (n = mm.exec(e)) !== null;) t.add(n[0]);
|
|
12429
12474
|
};
|
|
12430
12475
|
for (let r of e) {
|
|
12431
12476
|
if (n(r.content), r.steps) for (let e of r.steps) n(e.result);
|
|
@@ -12433,14 +12478,14 @@ function fm(e) {
|
|
|
12433
12478
|
}
|
|
12434
12479
|
return t;
|
|
12435
12480
|
}
|
|
12436
|
-
function
|
|
12481
|
+
function gm(e, t) {
|
|
12437
12482
|
let n = [];
|
|
12438
12483
|
for (let r of Object.keys(e)) r.startsWith("large_results/") && !t.has(r) && n.push(r);
|
|
12439
12484
|
return n;
|
|
12440
12485
|
}
|
|
12441
12486
|
//#endregion
|
|
12442
12487
|
//#region src/core/utils/serialRunner.ts
|
|
12443
|
-
function
|
|
12488
|
+
function _m() {
|
|
12444
12489
|
let e = Promise.resolve();
|
|
12445
12490
|
return function(t) {
|
|
12446
12491
|
let n = e.then(t, t);
|
|
@@ -12449,24 +12494,24 @@ function mm() {
|
|
|
12449
12494
|
}
|
|
12450
12495
|
//#endregion
|
|
12451
12496
|
//#region src/core/sdk/createChatSdk.ts
|
|
12452
|
-
var
|
|
12453
|
-
function
|
|
12497
|
+
var vm = 30, ym = /* @__PURE__ */ new Map();
|
|
12498
|
+
function bm(e, t) {
|
|
12454
12499
|
return e === "restore_data" ? "restore" : e === "write" ? t?.dryRun ? null : t?.del ? "delete" : t?.patch || t?.patches ? "edit" : "set" : e === "eval_script" ? t?.mode === "transform" ? "edit" : null : e === "draft_commit" || e === "resource_update" ? "edit" : null;
|
|
12455
12500
|
}
|
|
12456
|
-
function
|
|
12501
|
+
function xm(e) {
|
|
12457
12502
|
return e === "spawn_agent" || e === "spawn_agents" || e.startsWith("use_");
|
|
12458
12503
|
}
|
|
12459
|
-
function
|
|
12504
|
+
function Sm(e, t, n, r) {
|
|
12460
12505
|
let i = 0;
|
|
12461
12506
|
return {
|
|
12462
12507
|
name: "sdk-events",
|
|
12463
12508
|
wrapToolCall: async (t, r) => {
|
|
12464
|
-
let i = await r(t), a =
|
|
12509
|
+
let i = await r(t), a = bm(t.name, t.args), o = typeof i.content == "string" && i.content.startsWith("ERROR:");
|
|
12465
12510
|
return a && !o ? e({
|
|
12466
12511
|
type: "data_change",
|
|
12467
12512
|
operation: a,
|
|
12468
12513
|
value: n()?.bind
|
|
12469
|
-
}) : i.status === "done" && !o &&
|
|
12514
|
+
}) : i.status === "done" && !o && xm(t.name) && e({
|
|
12470
12515
|
type: "data_change",
|
|
12471
12516
|
operation: "edit",
|
|
12472
12517
|
value: n()?.bind
|
|
@@ -12494,7 +12539,7 @@ function ym(e, t, n, r) {
|
|
|
12494
12539
|
}
|
|
12495
12540
|
};
|
|
12496
12541
|
}
|
|
12497
|
-
function
|
|
12542
|
+
function Cm(e, t, n, r, i) {
|
|
12498
12543
|
if (!n) return i && console.warn(`[page-agent-sdk][focus] capabilities.focus 关闭,${t} 忽略`), {
|
|
12499
12544
|
ok: !1,
|
|
12500
12545
|
error: "capabilities.focus 关闭"
|
|
@@ -12512,12 +12557,12 @@ function bm(e, t, n, r, i) {
|
|
|
12512
12557
|
error: "当前无主数据 schema,无法聚焦"
|
|
12513
12558
|
});
|
|
12514
12559
|
}
|
|
12515
|
-
function
|
|
12560
|
+
function wm(e, n) {
|
|
12516
12561
|
let i = {
|
|
12517
12562
|
prompt_tokens: 0,
|
|
12518
12563
|
completion_tokens: 0,
|
|
12519
12564
|
total_tokens: 0
|
|
12520
|
-
}, a =
|
|
12565
|
+
}, a = zf(() => Y, () => e.conflictPolicy ?? "ask"), o = /* @__PURE__ */ Vt(0), s = mp(e.storage);
|
|
12521
12566
|
s && (e.debug && s.onEvent((e) => console.log("[page-agent-sdk][storage]", e)), s.onEvent((e) => {
|
|
12522
12567
|
e.type === "quota" && X.agent?.debugLogs?.value?.push({
|
|
12523
12568
|
timestamp: Date.now(),
|
|
@@ -12529,13 +12574,13 @@ function xm(e, n) {
|
|
|
12529
12574
|
}
|
|
12530
12575
|
});
|
|
12531
12576
|
}));
|
|
12532
|
-
let { modelCaps: c, summaryLlmInvoke: l, titleLlmInvoke: u, compressDecisionInvoke: d } =
|
|
12577
|
+
let { modelCaps: c, summaryLlmInvoke: l, titleLlmInvoke: u, compressDecisionInvoke: d } = Rf(e), f = c;
|
|
12533
12578
|
if (e.debug && console.log("[page-agent-sdk][modelCaps]", f), f.contextWindow < 2e5) throw Error(`[page-agent-sdk] 模型上下文窗口 ${f.contextWindow} 小于最小支持 ${p}(需 ≥200K 窗口模型,如 GLM-5.2/Claude/Kimi/Qwen-1M/DeepSeek-v4)`);
|
|
12534
12579
|
{
|
|
12535
|
-
let t = e.llm, n =
|
|
12580
|
+
let t = e.llm, n = kf(t) ? t.model ?? t.modelName ?? "" : t.model ?? "", r = kf(t) ? t.maxTokens ?? f.maxOutputTokens : t.maxTokens ?? h(t.model) ?? f.maxOutputTokens, i = _(n || void 0, f, r);
|
|
12536
12581
|
i && console.warn(i);
|
|
12537
12582
|
}
|
|
12538
|
-
let m =
|
|
12583
|
+
let m = xp(e, f.contextWindow), g = m.enableLLMSummary !== !1, y = (e.contextOptions && e.contextOptions.preserveLastToolResults) ?? bp[e.contextPreset ?? "auto"], b = new Set(y), x = e.llm;
|
|
12539
12584
|
e.debug && !l && console.warn("[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要");
|
|
12540
12585
|
let S = /* @__PURE__ */ kt([]), C = xu(e.vfs?.initialFiles, {
|
|
12541
12586
|
persist: s ? { save: (e) => {
|
|
@@ -12591,8 +12636,8 @@ function xm(e, n) {
|
|
|
12591
12636
|
let oe = { current: null }, M = e.data ? {
|
|
12592
12637
|
...e.data,
|
|
12593
12638
|
description: e.data.description ?? "主数据对象"
|
|
12594
|
-
} : void 0, se = !(e.subagents ?? []).some((e) => e._codeAsset) &&
|
|
12595
|
-
se && M?.schema && ts(M.schema).length && (N = [...e.subagents ?? [],
|
|
12639
|
+
} : void 0, se = !(e.subagents ?? []).some((e) => e._codeAsset) && _p(e.capabilities).subagent, N = e.subagents;
|
|
12640
|
+
se && M?.schema && ts(M.schema).length && (N = [...e.subagents ?? [], Cf()], console.info("[page-agent-sdk] 检测到 schema 含代码组件数组(如 components[].code),已自动装配 HTML 代码子 agent(委派编排 + vfs 工作副本 + 格式校验 + 增量 commit)。需定制(codeField/formatCheck/craftNotes 等)请显式传 createHtmlSubagent(...)"));
|
|
12596
12641
|
let P = (N ?? []).filter((e) => !!e._codeAsset), F = /* @__PURE__ */ new Set();
|
|
12597
12642
|
for (let e of P) {
|
|
12598
12643
|
if (e._codeAsset.writablePaths.length) continue;
|
|
@@ -12608,7 +12653,7 @@ function xm(e, n) {
|
|
|
12608
12653
|
getTodos: () => oe.current?.getState?.()?.todos ?? [],
|
|
12609
12654
|
messages: S,
|
|
12610
12655
|
maxCheckpoints: z && typeof z == "object" ? z.maxCheckpoints : void 0
|
|
12611
|
-
}) : null, de = !z || typeof z != "object" || z.auto !== !1, V =
|
|
12656
|
+
}) : null, de = !z || typeof z != "object" || z.auto !== !1, V = _p(e.capabilities), fe = V.dataOps, pe = V.draftWrite, H = V.automation, me = _u({
|
|
12612
12657
|
...e,
|
|
12613
12658
|
locale: e.i18n?.locale
|
|
12614
12659
|
});
|
|
@@ -12616,7 +12661,7 @@ function xm(e, n) {
|
|
|
12616
12661
|
let e = ce.map((e) => e._codeAsset.orchestratorPrompt).filter(Boolean).join("\n\n");
|
|
12617
12662
|
e && (me += "\n\n" + e);
|
|
12618
12663
|
} else M?.schema && es(M.schema) && (me += "\n\n" + vs.htmlDirectWriteFallback, console.warn("[page-agent-sdk] 检测到 schema 含 code 字段但未注册 html 子 agent:已自动注入「主 agent 自己写 HTML」编排(code 作普通字段直接 write,无 vfs 工作副本 / 无格式校验门禁)。如需代码资产机制(vfs + 格式校验 + 增量 commit + 主上下文 code 摘要),注册 createHtmlSubagent;若确为降级意图可忽略。"));
|
|
12619
|
-
let he = fe && M ?
|
|
12664
|
+
let he = fe && M ? hd(M, {
|
|
12620
12665
|
onAudit: e.onAudit ?? (e.debug ? (e) => console.log("[page-agent-sdk][data audit]", e) : void 0),
|
|
12621
12666
|
maxSnapshots: e.maxSnapshots,
|
|
12622
12667
|
onConflict: a.set,
|
|
@@ -12625,7 +12670,7 @@ function xm(e, n) {
|
|
|
12625
12670
|
vfsStore: pe || M?.resources?.length ? C : void 0,
|
|
12626
12671
|
...le.length ? { pgIdPaths: le } : {},
|
|
12627
12672
|
...R.length ? { largeTextPaths: R } : {}
|
|
12628
|
-
}) : [], ge = fe ? he : [], U = fe && M ? he.controller ?? null : null, _e = fe && M?.resources?.length && U?.getResourcesSnapshot ?
|
|
12673
|
+
}) : [], ge = fe ? he : [], U = fe && M ? he.controller ?? null : null, _e = fe && M?.resources?.length && U?.getResourcesSnapshot ? cm({ getResourcesSnapshot: () => U?.getResourcesSnapshot?.() ?? [] }) : void 0, W = () => U?.get() ?? M, ve = new Set(he.map((e) => e.name)), ye = e.conflictWatchFields ?? [], be = !ye.includes("*") && ye.length ? new Set(ye) : void 0, xe = U ? Jd({
|
|
12629
12674
|
getBind: () => W()?.bind,
|
|
12630
12675
|
recomputeAll: () => U.recomputeAllBaselines?.(),
|
|
12631
12676
|
hasBaselines: () => U.hasBaselines?.() ?? !1,
|
|
@@ -12642,15 +12687,15 @@ function xm(e, n) {
|
|
|
12642
12687
|
}
|
|
12643
12688
|
}), Gt(n));
|
|
12644
12689
|
}
|
|
12645
|
-
}) : void 0, G = /* @__PURE__ */ new Map(), Se =
|
|
12646
|
-
...
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
] :
|
|
12690
|
+
}) : void 0, G = /* @__PURE__ */ new Map(), Se = im(V, ge, Tp, V.domInspect && !V.skills ? [
|
|
12691
|
+
...jp,
|
|
12692
|
+
Vp,
|
|
12693
|
+
Hp
|
|
12694
|
+
] : jp, Xp);
|
|
12650
12695
|
Se.forEach((e) => G.set(e.name, "builtin"));
|
|
12651
12696
|
let K = [...e.tools || []];
|
|
12652
12697
|
K.forEach((e) => G.set(e.name, "user"));
|
|
12653
|
-
let Ce =
|
|
12698
|
+
let Ce = $p(e.actions ?? {});
|
|
12654
12699
|
Ce.forEach((e) => G.set(e.name, "action"));
|
|
12655
12700
|
let we = [], Te = !1, Ee = e.humanConfirm !== !1 && (!e.approval || e.approval.humanConfirmTool !== !1), De = Ee ? jl() : null;
|
|
12656
12701
|
De && G.set(kl, "builtin");
|
|
@@ -12723,7 +12768,7 @@ function xm(e, n) {
|
|
|
12723
12768
|
let Fe = [], Ie = /* @__PURE__ */ new Map(), q = Le();
|
|
12724
12769
|
function Le() {
|
|
12725
12770
|
Ni(K), Ni(Ce), Ni(Fe);
|
|
12726
|
-
let { tools: e, collisions: t } =
|
|
12771
|
+
let { tools: e, collisions: t } = am([
|
|
12727
12772
|
{
|
|
12728
12773
|
label: "builtin",
|
|
12729
12774
|
tools: Se
|
|
@@ -12800,7 +12845,7 @@ function xm(e, n) {
|
|
|
12800
12845
|
timeoutMs: J?.timeoutMs
|
|
12801
12846
|
}), it = I?.map((e) => {
|
|
12802
12847
|
if (!e._codeAsset) return e;
|
|
12803
|
-
let t = e._codeAsset, n =
|
|
12848
|
+
let t = e._codeAsset, n = Nd({
|
|
12804
12849
|
writablePaths: t.writablePaths,
|
|
12805
12850
|
codeVfsPrefix: t.codeVfsPrefix,
|
|
12806
12851
|
ext: t.ext,
|
|
@@ -12815,16 +12860,16 @@ function xm(e, n) {
|
|
|
12815
12860
|
...e,
|
|
12816
12861
|
middleware: r
|
|
12817
12862
|
};
|
|
12818
|
-
}), at = L && Ke ?
|
|
12863
|
+
}), at = L && Ke ? Pd() : void 0, ot = at ? Vd({
|
|
12819
12864
|
getBind: () => W()?.bind,
|
|
12820
12865
|
writablePaths: le,
|
|
12821
12866
|
getLocked: () => at.locked(),
|
|
12822
12867
|
tools: q,
|
|
12823
|
-
getCodeFieldPaths: () =>
|
|
12868
|
+
getCodeFieldPaths: () => zd(W()?.bind, ce.map((e) => ({
|
|
12824
12869
|
writablePaths: e._codeAsset.writablePaths,
|
|
12825
12870
|
codeField: e._codeAsset.codeField
|
|
12826
12871
|
})))
|
|
12827
|
-
}) : void 0, st = U?.getSummarizedPaths && U.clearSummarizedPaths ?
|
|
12872
|
+
}) : void 0, st = U?.getSummarizedPaths && U.clearSummarizedPaths ? Wd({
|
|
12828
12873
|
getSummarizedPaths: () => U.getSummarizedPaths(),
|
|
12829
12874
|
clearSummarizedPaths: () => U.clearSummarizedPaths()
|
|
12830
12875
|
}) : void 0, ct = Ke && it !== void 0 ? hl(it, {
|
|
@@ -12847,10 +12892,10 @@ function xm(e, n) {
|
|
|
12847
12892
|
timeoutMs: e.subagent?.timeoutMs,
|
|
12848
12893
|
...at ? {
|
|
12849
12894
|
componentLock: at,
|
|
12850
|
-
resolveComponents: (e) =>
|
|
12895
|
+
resolveComponents: (e) => Fd(e, kd(W()?.bind, le))
|
|
12851
12896
|
} : {}
|
|
12852
12897
|
}) : void 0, lt = ct ? ct.controller : null, ut = (t) => {
|
|
12853
|
-
let n = t.thinkingMode ?? e.subagent?.thinkingMode, r = n ?
|
|
12898
|
+
let n = t.thinkingMode ?? e.subagent?.thinkingMode, r = n ? kf(t.llm ?? e.llm) ? "instance-noop" : "applied" : "inherited";
|
|
12854
12899
|
return {
|
|
12855
12900
|
...t,
|
|
12856
12901
|
...n ? { thinkingMode: n } : {},
|
|
@@ -12871,8 +12916,8 @@ function xm(e, n) {
|
|
|
12871
12916
|
} : void 0
|
|
12872
12917
|
}) : void 0, mt = Qe ? cu({
|
|
12873
12918
|
contextWindow: f.contextWindow,
|
|
12874
|
-
thresholdRatio:
|
|
12875
|
-
}) : void 0, ht =
|
|
12919
|
+
thresholdRatio: xp(e, f.contextWindow).summaryThresholdRatio
|
|
12920
|
+
}) : void 0, ht = sm({
|
|
12876
12921
|
...V,
|
|
12877
12922
|
humanConfirm: Ee,
|
|
12878
12923
|
subagents: I?.map(ut)
|
|
@@ -12892,7 +12937,7 @@ function xm(e, n) {
|
|
|
12892
12937
|
return;
|
|
12893
12938
|
}
|
|
12894
12939
|
}
|
|
12895
|
-
} : null, vt =
|
|
12940
|
+
} : null, vt = vp(e.onEvent), Y = vt.emit, yt, bt = [], xt = (e) => ({
|
|
12896
12941
|
name: e.name,
|
|
12897
12942
|
description: e.description,
|
|
12898
12943
|
content: typeof e.getContent == "function" ? e.getContent() : ""
|
|
@@ -12900,7 +12945,7 @@ function xm(e, n) {
|
|
|
12900
12945
|
name: e.name,
|
|
12901
12946
|
description: e.description,
|
|
12902
12947
|
getContent: () => e.content
|
|
12903
|
-
}), Ct = e.skillStorage === !1 ? null :
|
|
12948
|
+
}), Ct = e.skillStorage === !1 ? null : pm({
|
|
12904
12949
|
...typeof e.skillStorage == "object" ? e.skillStorage : {},
|
|
12905
12950
|
id: e.skillStorage && typeof e.skillStorage == "object" && e.skillStorage.id ? e.skillStorage.id : `agent::${n}`
|
|
12906
12951
|
}), wt = () => {
|
|
@@ -12932,14 +12977,14 @@ function xm(e, n) {
|
|
|
12932
12977
|
decideInvoke: d,
|
|
12933
12978
|
getSnapshot: () => mt?.getSnapshot()
|
|
12934
12979
|
} : {}
|
|
12935
|
-
}) : void 0, Dt =
|
|
12980
|
+
}) : void 0, Dt = Cp([
|
|
12936
12981
|
...gt ? [gt] : [],
|
|
12937
12982
|
ht,
|
|
12938
12983
|
...ze ? [T] : [],
|
|
12939
12984
|
O,
|
|
12940
12985
|
ee,
|
|
12941
12986
|
...Re ? [w] : [],
|
|
12942
|
-
...Ve ? [yt = Sc([...V.domInspect && !(e.skills || []).some((e) => e.name ===
|
|
12987
|
+
...Ve ? [yt = Sc([...V.domInspect && !(e.skills || []).some((e) => e.name === Up.name) ? [Up] : [], ...e.skills || []], {
|
|
12943
12988
|
readVfs: He ? (e) => C.files[e]?.content : void 0,
|
|
12944
12989
|
onToolsReady: (e, t) => {
|
|
12945
12990
|
for (let n of t) {
|
|
@@ -12965,16 +13010,16 @@ function xm(e, n) {
|
|
|
12965
13010
|
...ct ? [ct] : [],
|
|
12966
13011
|
...ot ? [ot] : [],
|
|
12967
13012
|
...st ? [st] : [],
|
|
12968
|
-
...U && Ke ? [
|
|
13013
|
+
...U && Ke ? [qd({ getBind: () => W()?.bind })] : [],
|
|
12969
13014
|
..._t ? [_t] : [],
|
|
12970
13015
|
...mt ? [mt] : [],
|
|
12971
13016
|
...e.middleware || [],
|
|
12972
|
-
...H ? [
|
|
13017
|
+
...H ? [Zp(i, {
|
|
12973
13018
|
tokenBudget: e.tokenBudget,
|
|
12974
13019
|
timeBudgetMs: e.timeBudgetMs
|
|
12975
13020
|
}, Y)] : [],
|
|
12976
|
-
|
|
12977
|
-
]), Ot = e.maxMemoryRounds ??
|
|
13021
|
+
Sm(Y, S, W, i)
|
|
13022
|
+
]), Ot = e.maxMemoryRounds ?? vm;
|
|
12978
13023
|
function At(e) {
|
|
12979
13024
|
return (e) => {
|
|
12980
13025
|
e.type !== "approval_request" && Y(e);
|
|
@@ -12988,7 +13033,7 @@ function xm(e, n) {
|
|
|
12988
13033
|
e.debug && console.warn("[page-agent-sdk][persist] refreshSessions 失败(已吞):", t);
|
|
12989
13034
|
}
|
|
12990
13035
|
}
|
|
12991
|
-
let Nt =
|
|
13036
|
+
let Nt = _m(), Pt = /* @__PURE__ */ new Set();
|
|
12992
13037
|
function Ft(e) {
|
|
12993
13038
|
let t = new AbortController(), n = () => t.abort();
|
|
12994
13039
|
return e && (e.aborted ? t.abort() : e.addEventListener("abort", n, { once: !0 })), Pt.add(t), {
|
|
@@ -13097,7 +13142,7 @@ function xm(e, n) {
|
|
|
13097
13142
|
code: "IMAGE_UNSUPPORTED_MODEL"
|
|
13098
13143
|
}), Error(`[page-agent-sdk] ${e}`);
|
|
13099
13144
|
}
|
|
13100
|
-
C?.setProtectedRefs?.(
|
|
13145
|
+
C?.setProtectedRefs?.(hm(S));
|
|
13101
13146
|
let i = H ? t.maxAutoRetries ?? 1 : 0, o = 0, c = !1, l = At(t.signal);
|
|
13102
13147
|
if (t.signal) {
|
|
13103
13148
|
let e = () => a.resolve("keep_external");
|
|
@@ -13172,7 +13217,7 @@ function xm(e, n) {
|
|
|
13172
13217
|
if (await X.initDone, !e.length) return [];
|
|
13173
13218
|
if (X.refCount <= 0) throw Error("page-agent-sdk: agent 已释放(unmount),拒绝排队中的 batch");
|
|
13174
13219
|
let r = [], i = At(n);
|
|
13175
|
-
if (C?.setProtectedRefs?.(
|
|
13220
|
+
if (C?.setProtectedRefs?.(hm(S)), n) {
|
|
13176
13221
|
let e = () => a.resolve("keep_external");
|
|
13177
13222
|
n.aborted ? e() : n.addEventListener("abort", e, { once: !0 });
|
|
13178
13223
|
}
|
|
@@ -13299,7 +13344,7 @@ function xm(e, n) {
|
|
|
13299
13344
|
})), e.memory && qt({ memory: j.get() || (typeof e.memory == "string" ? e.memory : "") }), Mt(), Ut = void 0, Wt = !1, X.infoTick.value++, r;
|
|
13300
13345
|
},
|
|
13301
13346
|
resetSession: () => {
|
|
13302
|
-
It(), a.resolve("keep_external"), X.sessionId =
|
|
13347
|
+
It(), a.resolve("keep_external"), X.sessionId = Bf(), S.splice(0, S.length), C.clear?.(), w.reset([]), e.memory || j.reset(""), T.reset(), ae.reset(), A.reset(), Et?.reset(), ee.reset(), te = void 0, B && B.importStack([]), X.agent && (X.agent.debugLogs.value = [], X.agent.resetStaleReadsInvalidated?.()), s && s.createSession(X.agentId, e.session?.title, X.sessionId).catch((t) => {
|
|
13303
13348
|
e.debug && console.warn("[page-agent-sdk][persist] createSession 失败(已吞):", t);
|
|
13304
13349
|
}), Y({
|
|
13305
13350
|
type: "session_restored",
|
|
@@ -13319,7 +13364,7 @@ function xm(e, n) {
|
|
|
13319
13364
|
code: "IMAGE_UNSUPPORTED_MODEL"
|
|
13320
13365
|
}), Error(`[page-agent-sdk] ${e}`);
|
|
13321
13366
|
}
|
|
13322
|
-
C?.setProtectedRefs?.(
|
|
13367
|
+
C?.setProtectedRefs?.(hm(e));
|
|
13323
13368
|
let i = (e) => {
|
|
13324
13369
|
t?.(e), Y(e), e.type === "subagent" && (e.kind === "tool_call" || e.kind === "tool_result") && X.infoTick.value++;
|
|
13325
13370
|
};
|
|
@@ -13334,7 +13379,7 @@ function xm(e, n) {
|
|
|
13334
13379
|
if (X.refCount--, X.refCount <= 0) {
|
|
13335
13380
|
It(), Te = !0, s && (C.flush?.(), s.flush(), s.dispose()), Ct && Ct.dispose();
|
|
13336
13381
|
let e = X.mcpClosers.splice(0);
|
|
13337
|
-
e.length && Promise.allSettled(e.map((e) => e())),
|
|
13382
|
+
e.length && Promise.allSettled(e.map((e) => e())), ym.delete(n);
|
|
13338
13383
|
}
|
|
13339
13384
|
},
|
|
13340
13385
|
resolveConflict: a.resolve,
|
|
@@ -13354,14 +13399,14 @@ function xm(e, n) {
|
|
|
13354
13399
|
},
|
|
13355
13400
|
setLlm(t) {
|
|
13356
13401
|
let n;
|
|
13357
|
-
if (
|
|
13402
|
+
if (kf(t)) n = t;
|
|
13358
13403
|
else {
|
|
13359
13404
|
let e = t;
|
|
13360
13405
|
if ((e.provider ?? "openai") === "anthropic") throw Error("[page-agent-sdk][setLlm] 切换到 Anthropic 需传 BaseChatModel 实例(动态 import 无法同步);请先 const { ChatAnthropic } = await import(\"@langchain/anthropic\") 构造实例后传入");
|
|
13361
13406
|
n = E(e);
|
|
13362
13407
|
}
|
|
13363
13408
|
typeof n.bindTools != "function" && e.debug && console.warn("[page-agent-sdk][setLlm] 新模型不支持 bindTools(tool calling 会失效)"), x = t;
|
|
13364
|
-
let r =
|
|
13409
|
+
let r = kf(t) ? void 0 : t;
|
|
13365
13410
|
if (f = v({
|
|
13366
13411
|
model: r?.model ?? t.model ?? t.modelName,
|
|
13367
13412
|
contextWindow: e.contextWindow ?? r?.contextWindow,
|
|
@@ -13405,7 +13450,7 @@ function xm(e, n) {
|
|
|
13405
13450
|
return {
|
|
13406
13451
|
id: n,
|
|
13407
13452
|
sessionId: X.sessionId,
|
|
13408
|
-
model:
|
|
13453
|
+
model: kf(x) ? x.model ?? x.modelName : x.model,
|
|
13409
13454
|
systemPrompt: X.agent?.getEffectiveSystemPrompt?.() ?? me + gu(W(), e.schemaHint),
|
|
13410
13455
|
tools: (X.agent?.allTools ?? q).map((e) => ({
|
|
13411
13456
|
name: e.name,
|
|
@@ -13445,7 +13490,7 @@ function xm(e, n) {
|
|
|
13445
13490
|
workingMemory: Be ? ae.getWorkingMemory() : void 0,
|
|
13446
13491
|
focus: ke ? A.getFocus() : void 0,
|
|
13447
13492
|
focuses: ke ? A.getFocuses() : [],
|
|
13448
|
-
actions:
|
|
13493
|
+
actions: em(e.actions ?? {}),
|
|
13449
13494
|
subagent: {
|
|
13450
13495
|
enabled: !!rt,
|
|
13451
13496
|
maxDepth: e.subagent?.maxDepth ?? 1,
|
|
@@ -13505,7 +13550,7 @@ function xm(e, n) {
|
|
|
13505
13550
|
approxBytes: e
|
|
13506
13551
|
};
|
|
13507
13552
|
}
|
|
13508
|
-
return
|
|
13553
|
+
return ef($d({
|
|
13509
13554
|
debugLogs: X.agent?.debugLogs?.value ?? [],
|
|
13510
13555
|
messages: X.messages,
|
|
13511
13556
|
info: t,
|
|
@@ -13532,11 +13577,11 @@ function xm(e, n) {
|
|
|
13532
13577
|
return ke ? A.getFocuses() : [];
|
|
13533
13578
|
},
|
|
13534
13579
|
setFocus(t) {
|
|
13535
|
-
let n =
|
|
13580
|
+
let n = Cm(t, "setFocus", ke, () => W()?.schema, e.debug);
|
|
13536
13581
|
return n.ok ? (A.setFocus(t), e.debug && A.isInvokeActive() && console.info("[page-agent-sdk][focus] 在途流程进行中,聚焦将在下一次输入生效(当前流程不受影响)"), X.infoTick.value++, { ok: !0 }) : n;
|
|
13537
13582
|
},
|
|
13538
13583
|
addFocus(t) {
|
|
13539
|
-
let n =
|
|
13584
|
+
let n = Cm(t, "addFocus", ke, () => W()?.schema, e.debug);
|
|
13540
13585
|
return n.ok ? A.getFocuses().length >= 8 ? (e.debug && console.warn("[page-agent-sdk][focus] addFocus 拒绝:焦点数已达上限 8(augmentPrompt 注入每焦点子树 schema,过多致 system prompt 超预算)"), {
|
|
13541
13586
|
ok: !1,
|
|
13542
13587
|
error: "焦点数上限 8(避免 system prompt 撑爆)"
|
|
@@ -13610,14 +13655,14 @@ function xm(e, n) {
|
|
|
13610
13655
|
}
|
|
13611
13656
|
function zt(e) {
|
|
13612
13657
|
let t = {};
|
|
13613
|
-
for (let n of
|
|
13658
|
+
for (let n of hm(e)) {
|
|
13614
13659
|
let e = C.files[n];
|
|
13615
13660
|
e && (t[n] = e.content);
|
|
13616
13661
|
}
|
|
13617
13662
|
return t;
|
|
13618
13663
|
}
|
|
13619
13664
|
function Bt() {
|
|
13620
|
-
let e =
|
|
13665
|
+
let e = gm(C.files, hm(S));
|
|
13621
13666
|
for (let t of e) delete C.files[t];
|
|
13622
13667
|
}
|
|
13623
13668
|
function Ht() {
|
|
@@ -13721,7 +13766,7 @@ function xm(e, n) {
|
|
|
13721
13766
|
qt({ focus: e.length ? e : null });
|
|
13722
13767
|
}
|
|
13723
13768
|
H && B && (qt({ checkpoints: B.exportStack() }), qt({ usage: i }));
|
|
13724
|
-
let t =
|
|
13769
|
+
let t = Of(S);
|
|
13725
13770
|
if (t && t !== Ut && (Ut = t, Jt(X.sessionId, t)), e.autoTitle !== !1 && u && !Wt && S.some((e) => e.role === "user") && S.some((e) => e.role === "assistant")) {
|
|
13726
13771
|
Wt = !0;
|
|
13727
13772
|
let e = X.sessionId;
|
|
@@ -13799,7 +13844,7 @@ function xm(e, n) {
|
|
|
13799
13844
|
}
|
|
13800
13845
|
}));
|
|
13801
13846
|
})();
|
|
13802
|
-
let t =
|
|
13847
|
+
let t = kf(e.llm) ? e.llm : await D(e.llm);
|
|
13803
13848
|
X.agent = zo({
|
|
13804
13849
|
llm: t,
|
|
13805
13850
|
systemPrompt: me,
|
|
@@ -13815,7 +13860,7 @@ function xm(e, n) {
|
|
|
13815
13860
|
contextWindow: f.contextWindow,
|
|
13816
13861
|
maxOutputTokens: f.maxOutputTokens,
|
|
13817
13862
|
vision: f.vision,
|
|
13818
|
-
imageContentFormat: !
|
|
13863
|
+
imageContentFormat: !kf(e.llm) && (e.llm.provider ?? "openai") === "anthropic" ? "anthropic" : "openai",
|
|
13819
13864
|
maxVerifyAttempts: Ze ? Je : 0,
|
|
13820
13865
|
roundTokenBudget: e.roundTokenBudget ?? 0,
|
|
13821
13866
|
staleReadInvalidation: e.staleReadInvalidation,
|
|
@@ -13828,12 +13873,12 @@ function xm(e, n) {
|
|
|
13828
13873
|
});
|
|
13829
13874
|
})(), X;
|
|
13830
13875
|
}
|
|
13831
|
-
function
|
|
13832
|
-
let n = e.id ??
|
|
13876
|
+
function Tm(e, t) {
|
|
13877
|
+
let n = e.id ?? Bf();
|
|
13833
13878
|
e.id || console.warn(`[page-agent-sdk] 未传 options.id,已生成随机 id "${n}"。刷新后持久化数据无法恢复,请传稳定 id。`);
|
|
13834
|
-
let r = e.streaming ?? !0, i = e.ui ?? "default", a, o = e.shareContext ?
|
|
13835
|
-
o ? a = o : (a =
|
|
13836
|
-
let s = null, c =
|
|
13879
|
+
let r = e.streaming ?? !0, i = e.ui ?? "default", a, o = e.shareContext ? ym.get(n) : void 0;
|
|
13880
|
+
o ? a = o : (a = wm(e, n), e.shareContext && ym.set(n, a)), a.refCount++;
|
|
13881
|
+
let s = null, c = hp(e), l = null, u = null;
|
|
13837
13882
|
async function d(n) {
|
|
13838
13883
|
if (await a.initDone, s) {
|
|
13839
13884
|
s.show();
|
|
@@ -14056,7 +14101,7 @@ function Sm(e, t) {
|
|
|
14056
14101
|
}
|
|
14057
14102
|
//#endregion
|
|
14058
14103
|
//#region src/core/sdk/ragSubagent.ts
|
|
14059
|
-
function
|
|
14104
|
+
function Em(e, t, n, r, i) {
|
|
14060
14105
|
let a = [];
|
|
14061
14106
|
e && a.push("vfs_grep + vfs_read(搜预注入文档)"), t && a.push(`${r}(语义检索)`), n && a.push(`${i}(按 source 加载)`), a.push("fetch_document(公网 URL)");
|
|
14062
14107
|
let o = [];
|
|
@@ -14071,7 +14116,7 @@ function Cm(e, t, n, r, i) {
|
|
|
14071
14116
|
|
|
14072
14117
|
你是只读检索角色,不要尝试修改任何数据。不要尝试上面未列出的工具。`;
|
|
14073
14118
|
}
|
|
14074
|
-
function
|
|
14119
|
+
function Dm(e, t, n, r, i) {
|
|
14075
14120
|
let a = [], o = [];
|
|
14076
14121
|
return e && (a.push("- vfs_grep / vfs_read:搜集成方预注入 vfs 的文档(组件文档 / UI 规范)—— 快、静态,先查"), o.push("- 静态文档(组件库文档 / UI 规范):vfs_grep")), t && (a.push(`- ${r}:语义检索(retriever 向量库)—— 模糊匹配,关键词不确定 / 语义相似时用`), o.push(`- 语义相似(「瀑布流组件」「倒计时」「拼团」):${r}`)), n && (a.push(`- ${i}:按 source 精确加载(已知文档 id / URL / key)—— 精确取特定文档`), o.push(`- 已知文档 id / URL:${i}`)), a.push("- fetch_document:公网 URL —— 查公开资料"), o.push("- 公开 URL(设计规范网站 / 第三方文档):fetch_document"), `# 知识检索策略(RAG)
|
|
14077
14122
|
|
|
@@ -14088,12 +14133,12 @@ ${a.join("\n")}
|
|
|
14088
14133
|
## 何时用何源
|
|
14089
14134
|
${o.join("\n")}`;
|
|
14090
14135
|
}
|
|
14091
|
-
var
|
|
14136
|
+
var Om = {
|
|
14092
14137
|
name: "rag-search",
|
|
14093
14138
|
description: "多源知识检索策略:vfs 预注入文档 → 语义检索 → 指定文档加载 → 公网;综合结构化结论 + 溯源",
|
|
14094
|
-
getContent: () =>
|
|
14139
|
+
getContent: () => Dm(!0, !0, !0, "search_docs", "load_doc")
|
|
14095
14140
|
};
|
|
14096
|
-
function
|
|
14141
|
+
function km(e, n, i) {
|
|
14097
14142
|
let a = r(async ({ query: e, topK: t }) => {
|
|
14098
14143
|
try {
|
|
14099
14144
|
let r = await n(e, { topK: t ?? i });
|
|
@@ -14111,7 +14156,7 @@ function Em(e, n, i) {
|
|
|
14111
14156
|
});
|
|
14112
14157
|
return Ni([a]), a;
|
|
14113
14158
|
}
|
|
14114
|
-
function
|
|
14159
|
+
function Am(e, n) {
|
|
14115
14160
|
let i = r(async ({ source: e }) => {
|
|
14116
14161
|
try {
|
|
14117
14162
|
let t = await n(e), r = Array.isArray(t) ? t : [t];
|
|
@@ -14126,19 +14171,19 @@ function Dm(e, n) {
|
|
|
14126
14171
|
});
|
|
14127
14172
|
return Ni([i]), i;
|
|
14128
14173
|
}
|
|
14129
|
-
function
|
|
14174
|
+
function jm(e) {
|
|
14130
14175
|
let { retriever: t, loader: n, useVfs: r = !0, id: i = "rag", description: a, topK: o = 5, searchToolName: s = "search_docs", loadToolName: c = "load_doc", maxToolRounds: l = 8, summarization: u, skills: d, extraTools: f } = e;
|
|
14131
14176
|
if (!t && !n && r === !1) throw Error("[page-agent-sdk][createRagSubagent] 至少配一种知识源:retriever / loader / useVfs(true)");
|
|
14132
14177
|
let p = [];
|
|
14133
|
-
t && p.push(
|
|
14178
|
+
t && p.push(km(s, t, o)), n && p.push(Am(c, n)), f && p.push(...f);
|
|
14134
14179
|
let m = r ? [
|
|
14135
14180
|
"vfs_grep",
|
|
14136
14181
|
"vfs_read",
|
|
14137
14182
|
"vfs_json_read"
|
|
14138
|
-
] : void 0, h =
|
|
14183
|
+
] : void 0, h = Em(r, !!t, !!n, s, c), g = {
|
|
14139
14184
|
name: "rag-search",
|
|
14140
|
-
description:
|
|
14141
|
-
getContent: () =>
|
|
14185
|
+
description: Om.description,
|
|
14186
|
+
getContent: () => Dm(r, !!t, !!n, s, c)
|
|
14142
14187
|
};
|
|
14143
14188
|
return {
|
|
14144
14189
|
id: i,
|
|
@@ -14153,7 +14198,7 @@ function Om(e) {
|
|
|
14153
14198
|
}
|
|
14154
14199
|
//#endregion
|
|
14155
14200
|
//#region src/core/utils/clipboard.ts
|
|
14156
|
-
async function
|
|
14201
|
+
async function Mm(e) {
|
|
14157
14202
|
try {
|
|
14158
14203
|
let t = globalThis.navigator?.clipboard;
|
|
14159
14204
|
if (t && typeof t.writeText == "function") return await t.writeText(e), !0;
|
|
@@ -14171,8 +14216,8 @@ async function km(e) {
|
|
|
14171
14216
|
}
|
|
14172
14217
|
//#endregion
|
|
14173
14218
|
//#region src/core/composables/useChat.ts
|
|
14174
|
-
var
|
|
14175
|
-
function
|
|
14219
|
+
var Nm = 4e3;
|
|
14220
|
+
function Pm(e = {}) {
|
|
14176
14221
|
let { fetchResponse: t, fetchStream: n, onPersist: r, onClear: i, onQueuedCleared: a, onBeforeRegenerate: o } = e, s = /* @__PURE__ */ kt({
|
|
14177
14222
|
messages: e.messages ?? [],
|
|
14178
14223
|
loading: !1,
|
|
@@ -14252,7 +14297,7 @@ function jm(e = {}) {
|
|
|
14252
14297
|
let t = e.delta || "";
|
|
14253
14298
|
n.subReasonFull = (n.subReasonFull || "") + t;
|
|
14254
14299
|
let r = (n.subReason || "") + t;
|
|
14255
|
-
n.subReason = r.length >
|
|
14300
|
+
n.subReason = r.length > Nm ? r.slice(-4e3) : r;
|
|
14256
14301
|
break;
|
|
14257
14302
|
}
|
|
14258
14303
|
n.children ||= [];
|
|
@@ -14382,7 +14427,7 @@ function jm(e = {}) {
|
|
|
14382
14427
|
}
|
|
14383
14428
|
//#endregion
|
|
14384
14429
|
//#region src/core/components/icons.ts
|
|
14385
|
-
var
|
|
14430
|
+
var Fm = {
|
|
14386
14431
|
header: "🤖",
|
|
14387
14432
|
subagent: "🤖",
|
|
14388
14433
|
subagentProgress: "🧬",
|
|
@@ -14393,10 +14438,10 @@ var Mm = {
|
|
|
14393
14438
|
recommend: "💡",
|
|
14394
14439
|
conflict: "⚠️"
|
|
14395
14440
|
};
|
|
14396
|
-
function
|
|
14397
|
-
let t = { ...
|
|
14441
|
+
function Im(e) {
|
|
14442
|
+
let t = { ...Fm };
|
|
14398
14443
|
if (!e) return t;
|
|
14399
|
-
let n = Object.keys(
|
|
14444
|
+
let n = Object.keys(Fm);
|
|
14400
14445
|
for (let r of n) {
|
|
14401
14446
|
let n = e[r];
|
|
14402
14447
|
typeof n == "string" && (t[r] = n);
|
|
@@ -14405,7 +14450,7 @@ function Nm(e) {
|
|
|
14405
14450
|
}
|
|
14406
14451
|
//#endregion
|
|
14407
14452
|
//#region src/core/components/messages.ts
|
|
14408
|
-
var
|
|
14453
|
+
var Lm = {
|
|
14409
14454
|
defaultTitle: "AI 助手",
|
|
14410
14455
|
inputPlaceholder: "输入消息,Enter 发送...",
|
|
14411
14456
|
newSession: "新建会话",
|
|
@@ -14629,8 +14674,8 @@ var Pm = {
|
|
|
14629
14674
|
codeDemoText: "这是一段示例文字,用于展示 CSS 效果。",
|
|
14630
14675
|
codeDemoButton: "按钮",
|
|
14631
14676
|
codeDemoInput: "输入框"
|
|
14632
|
-
},
|
|
14633
|
-
"zh-CN":
|
|
14677
|
+
}, Rm = {
|
|
14678
|
+
"zh-CN": Lm,
|
|
14634
14679
|
"en-US": {
|
|
14635
14680
|
defaultTitle: "AI Assistant",
|
|
14636
14681
|
inputPlaceholder: "Type a message, Enter to send...",
|
|
@@ -14857,10 +14902,10 @@ var Pm = {
|
|
|
14857
14902
|
codeDemoInput: "Input"
|
|
14858
14903
|
}
|
|
14859
14904
|
};
|
|
14860
|
-
function
|
|
14905
|
+
function zm(e = "zh-CN", t) {
|
|
14861
14906
|
let n = {
|
|
14862
|
-
...
|
|
14863
|
-
...
|
|
14907
|
+
...Lm,
|
|
14908
|
+
...Rm[e]
|
|
14864
14909
|
};
|
|
14865
14910
|
if (!t) return n;
|
|
14866
14911
|
let r = { ...n };
|
|
@@ -14872,9 +14917,9 @@ function Im(e = "zh-CN", t) {
|
|
|
14872
14917
|
}
|
|
14873
14918
|
//#endregion
|
|
14874
14919
|
//#region src/core/composables/chatContext.ts
|
|
14875
|
-
var
|
|
14876
|
-
function
|
|
14877
|
-
let t =
|
|
14920
|
+
var Bm = Symbol("chatContext");
|
|
14921
|
+
function Vm(e = {}) {
|
|
14922
|
+
let t = Pm({
|
|
14878
14923
|
fetchResponse: e.fetchResponse,
|
|
14879
14924
|
fetchStream: e.fetchStream,
|
|
14880
14925
|
messages: e.messages,
|
|
@@ -14896,7 +14941,7 @@ function Rm(e = {}) {
|
|
|
14896
14941
|
}, h = /* @__PURE__ */ Vt({}), g = (e) => h.value[e] === !0, _ = (e) => {
|
|
14897
14942
|
h.value[e] = !g(e);
|
|
14898
14943
|
}, v = /* @__PURE__ */ Vt(!1), y = (e) => {
|
|
14899
|
-
|
|
14944
|
+
Mm(e).then((e) => {
|
|
14900
14945
|
e && (v.value = !0, setTimeout(() => {
|
|
14901
14946
|
v.value = !1;
|
|
14902
14947
|
}, 1500));
|
|
@@ -14958,7 +15003,7 @@ function Rm(e = {}) {
|
|
|
14958
15003
|
e.onClearFocus?.();
|
|
14959
15004
|
}, se = (t) => {
|
|
14960
15005
|
e.onFocusChipClick?.(t);
|
|
14961
|
-
}, N =
|
|
15006
|
+
}, N = Im(e.icons), P = e.locale ?? "zh-CN", F = zm(P, e.dialogMessages);
|
|
14962
15007
|
return {
|
|
14963
15008
|
chat: t,
|
|
14964
15009
|
inputText: o,
|
|
@@ -15000,15 +15045,15 @@ function Rm(e = {}) {
|
|
|
15000
15045
|
toolStepView: e.toolStepView
|
|
15001
15046
|
};
|
|
15002
15047
|
}
|
|
15003
|
-
function
|
|
15004
|
-
let e = Yn(
|
|
15048
|
+
function Hm() {
|
|
15049
|
+
let e = Yn(Bm);
|
|
15005
15050
|
if (!e) throw Error("useChatContext 必须在 provide(chatContextKey) 的组件子树内调用");
|
|
15006
15051
|
return e;
|
|
15007
15052
|
}
|
|
15008
15053
|
//#endregion
|
|
15009
15054
|
//#region src/core/index.headless.ts
|
|
15010
|
-
function
|
|
15011
|
-
return
|
|
15055
|
+
function Um(e) {
|
|
15056
|
+
return Tm(e);
|
|
15012
15057
|
}
|
|
15013
15058
|
//#endregion
|
|
15014
|
-
export {
|
|
15059
|
+
export { gp as CAPABILITIES, yp as CONTEXT_PRESETS, Df as CompressDecisionSchema, Mp as DEFAULT_COMPUTED_STYLES, zc as DEFAULT_PROMPT_SOFT_CAP, mu as DEFAULT_SYSTEM_PROMPT, gd as HTML_VOID_TAGS, kl as HUMAN_CONFIRM_TOOL_NAME, pi as ImageInputError, g as LOW_CAPS_HINT_BASELINE, p as MIN_CONTEXT_WINDOW, Xi as MODEL_UNAVAILABLE_GUIDANCE, Rc as SOFT_CAP_MIN_WINDOW, Mc as STOP_WORDS, Is as UNSAFE_KEYS, em as actionsToInspectInfo, $p as actionsToTools, li as agentError, su as analyzeContext, Ys as applyPatchToClone, Qs as applyPatchToLive, id as applyPatchesToBind, Yo as arrayMinLength, ci as asAgentError, cf as buildCollectorJs, Lp as buildCssPath, gu as buildDataPrompt, $d as buildDiagnosticsReport, lf as buildSandboxSrcdoc, _u as buildSystemPrompt, Bm as chatContextKey, rd as commitSetToBind, hf as composeStructureThenRender, wi as compressImage, pu as connectMcp, D as constructLlmFromConfig, E as constructOpenLlmSync, Mm as copyText, zo as createAgent, Ol as createApprovalMiddleware, Vm as createChatContext, Um as createChatSdk, zl as createCheckpointManager, Bl as createCheckpointMiddleware, zf as createConflictManager, cu as createContextInspectorMiddleware, xf as createCraftNoteCheck, hd as createDataOps, yf as createHtmlFormatCheck, mf as createHtmlRenderCheck, Cf as createHtmlSubagent, Ml as createHumanConfirmMiddleware, jl as createHumanConfirmTool, sp as createMemoryBackend, xl as createMemoryMiddleware, u as createProxyLlm, jm as createRagSubagent, ra as createSandboxRunner, vp as createSdkEvents, _m as createSerialRunner, dp as createSessionStore, fp as createSessionStoreWithBackend, pm as createSkillStore, fl as createSubagentMiddleware, Kc as createSubagentTracker, hl as createSubagentsMiddleware, sm as createUsageHintsMiddleware, Hl as createVerifyMiddleware, xu as createVfs, lp as createWebStorageBackend, Jl as createWriteBackCheck, Zi as decorateModelUnavailable, Vs as deepClone, rm as defineDataToolset, cc as defineSkill, wf as defineTool, Bs as deleteByPath, Of as deriveTitle, ls as describeSchemaNode, To as detectGarbledToolCall, nc as diffObjects, Hp as domInfoTool, Up as domInspectSkill, Vp as domSearchTool, kp as domToStructure, jp as domTools, nm as domToolsStatic, Xo as elementSchemaCandidates, Fp as ensureDomListenerRecorder, Pc as estimateMessageTokens, Fc as estimateRoundTokens, y as estimateTokens, ee as extractReasoningDelta, Ss as extractSchemaHint, lu as extractText, O as extractTextDelta, te as extractUsage, Tp as fetchDocTools, tm as fetchTools, tc as findStrippedKeys, us as formatConstraints, ii as formatZodIssues, Q as getByPath, Ap as getDomTool, Bp as getElementInfo, Kp as getEnvSummary, Ip as getRecordedListeners, ff as getSandboxLifecycle, Uo as getSchemaAtPath, Bo as getSchemaTopKeys, qs as hashValue, _s as htmlOrchestratorPrompt, Ic as indexSummarize, Yp as inspectEnvTool, Xp as inspectTools, kf as isChatModel, Ji as isContextLengthError, Yi as isModelUnavailableError, Vo as isPathAllowed, $f as isQuotaError, Ls as isUnsafePath, pa as jpEval, oi as jsonParseError, Gs as limitDepth, _ as lowCapsHint, Zd as maskUrlCredentials, Us as maybeParseValue, Gd as measureWriteScale, sf as normalizeRenderResult, re as normalizeUsage, x as offloadPassThroughChars, b as offloadThresholdChars, gs as presets, rs as projectBySchema, ns as projectBySchemaDeep, Ws as projectFields, Lc as recallRounds, pf as renderInSandbox, ds as renderSchemaHint, fs as renderSchemaOverview, hs as renderSchemaShallow, _p as resolveCapabilities, xp as resolveContextOptions, hp as resolveDialogConfig, Rf as resolveLlm, v as resolveModelCaps, Vc as resolvePromptSoftCap, Ko as resolveSchemaPath, mp as resolveStorage, ec as restoreInPlace, $s as restoreLive, si as routeError, _a as runSandboxedScript, Rs as safeMerge, Gp as safeSerialize, $ as safeStringify, Jo as schemaHasRefinement, Rp as searchDom, ha as searchJson, im as selectBuiltinTools, zs as setByPath, Hc as shouldTriggerCompression, ef as stringifyDiagnosticsReport, vs as systemPromptHelpers, h as tableMaxOutputTokens, Nc as tokenize, Z as toolError, Ho as unwrapSchema, Pm as useChat, Hm as useChatContext, qo as validateAtPath, vd as validateHtmlFormat, td as validateRootValueLocally, nd as validateWriteLocally, Js as watchFieldsHash, e as z, ai as zodError };
|