@xdxer/dingtalk-agent 0.1.5-beta.10 → 0.1.5-beta.12
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/CHANGELOG.md +16 -0
- package/dist/bin/dingtalk-agent.js +6 -0
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/agent-bindings.js +4 -8
- package/dist/src/agent-bindings.js.map +1 -1
- package/dist/src/memory/candidates.js +8 -0
- package/dist/src/memory/candidates.js.map +1 -1
- package/dist/src/memory/noop-receipt.js +17 -3
- package/dist/src/memory/noop-receipt.js.map +1 -1
- package/dist/src/multica-deploy.js +77 -5
- package/dist/src/multica-deploy.js.map +1 -1
- package/dist/src/predicate-registry.js +187 -0
- package/dist/src/predicate-registry.js.map +1 -0
- package/dist/src/promotion.js +1 -1
- package/dist/src/promotion.js.map +1 -1
- package/dist/src/schedule-plan.js +27 -3
- package/dist/src/schedule-plan.js.map +1 -1
- package/dist/src/state-dir.js +120 -0
- package/dist/src/state-dir.js.map +1 -0
- package/docs/schemas/multica-deployment-plan.schema.json +14 -1
- package/docs/schemas/multica-deployment-receipt.schema.json +14 -1
- package/lab/robot-eval/suite.json +1 -1
- package/package.json +1 -1
- package/skills/core/dta-agent-compose/SKILL.md +1 -1
- package/skills/core/dta-agent-compose/references/drive-and-schedules.md +3 -1
- package/skills/core/dta-basic-behavior/SKILL.md +1 -1
- package/skills/core/dta-basic-behavior/references/task-lifecycle.md +6 -1
- package/skills/platforms/multica-dingtalk/dta-ops-multica/SKILL.md +25 -17
- package/skills/platforms/multica-dingtalk/dta-ops-multica/scripts/multica_ext.py +74 -8
|
@@ -12,6 +12,7 @@ shell proxy cannot break calls to intranet/pre endpoints.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import argparse
|
|
15
|
+
import hashlib
|
|
15
16
|
import json
|
|
16
17
|
import os
|
|
17
18
|
import re
|
|
@@ -629,14 +630,67 @@ def load_predicate_registry(manifest_path: str) -> Dict[str, Any]:
|
|
|
629
630
|
return predicates
|
|
630
631
|
|
|
631
632
|
|
|
633
|
+
PREDICATE_REGISTRY_SCHEMA = "dingtalk-agent/predicate-registry@1"
|
|
634
|
+
PREDICATE_REGISTRY_KEYS = ["$schema", "hash", "predicates", "project", "schedules"]
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
def _stable_json(value: Any) -> str:
|
|
638
|
+
"""src/events.ts stableStringify 的镜像:键排序、无空格。改一边必须改另一边——
|
|
639
|
+
两套序列化分叉就等于两个不同的 hash,投影的完整性校验会互相判错。"""
|
|
640
|
+
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def registry_hash(projection: Dict[str, Any]) -> str:
|
|
644
|
+
unsigned = {k: v for k, v in projection.items() if k != "hash"}
|
|
645
|
+
return hashlib.sha256(_stable_json(unsigned).encode("utf-8")).hexdigest()
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
def load_delivered_registry(path: str) -> Dict[str, Any]:
|
|
649
|
+
"""读 deploy 交付进 runtime 的受管 registry 投影(issue #46)。
|
|
650
|
+
|
|
651
|
+
这是运行侧真正能拿到的那份文件——manifest 不随 skill-push 进入 runtime,所以运行拍
|
|
652
|
+
读的是它。structure + 完整性 hash 都校验:文件缺失/被改/被截断一律非零退出,判据
|
|
653
|
+
解析不出来时这一拍不得使用完成措辞。hash 是无密钥完整性校验,不证签发方。"""
|
|
654
|
+
try:
|
|
655
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
656
|
+
projection = json.load(f)
|
|
657
|
+
except OSError as e:
|
|
658
|
+
fail(f"registry 投影读不到: {path} ({e})——判据未交付,本拍不得声称完成")
|
|
659
|
+
except json.JSONDecodeError as e:
|
|
660
|
+
fail(f"registry 投影不是合法 JSON: {path} ({e})")
|
|
661
|
+
if not isinstance(projection, dict):
|
|
662
|
+
fail("registry 投影必须是 JSON object")
|
|
663
|
+
if sorted(projection) != PREDICATE_REGISTRY_KEYS:
|
|
664
|
+
fail(f"registry 投影字段集必须恰为 {'/'.join(PREDICATE_REGISTRY_KEYS)}")
|
|
665
|
+
if projection.get("$schema") != PREDICATE_REGISTRY_SCHEMA:
|
|
666
|
+
fail(f"registry 投影 schema 非法: {projection.get('$schema')!r}")
|
|
667
|
+
predicates = projection.get("predicates")
|
|
668
|
+
if not isinstance(predicates, dict):
|
|
669
|
+
fail("registry 投影 predicates 必须是 object")
|
|
670
|
+
actual = registry_hash(projection)
|
|
671
|
+
if projection.get("hash") != actual:
|
|
672
|
+
fail(
|
|
673
|
+
"registry 投影 hash 与内容不一致(declared="
|
|
674
|
+
f"{str(projection.get('hash'))[:12]}, actual={actual[:12]})——"
|
|
675
|
+
"交付的判据被改过或截断,fail-closed"
|
|
676
|
+
)
|
|
677
|
+
return projection
|
|
678
|
+
|
|
679
|
+
|
|
632
680
|
LOCAL_COMMANDS = {"predicate-resolve"}
|
|
633
681
|
|
|
634
682
|
|
|
635
683
|
def cmd_predicate_resolve(ctx: Optional[Ctx], args: argparse.Namespace) -> None:
|
|
636
|
-
"""
|
|
637
|
-
|
|
684
|
+
"""判据解析:从声明侧 manifest(operator)或交付进 runtime 的受管投影(运行拍)
|
|
685
|
+
解析出判据正文。未注册 / marker 缺失 / 冲突 / 投影 hash 对不上都非零退出——判据解析
|
|
638
686
|
失败时这一拍不能假装知道怎么算完成。"""
|
|
639
|
-
|
|
687
|
+
if args.registry:
|
|
688
|
+
projection = load_delivered_registry(args.registry)
|
|
689
|
+
predicates = projection["predicates"]
|
|
690
|
+
resolved_from_registry = projection["hash"]
|
|
691
|
+
else:
|
|
692
|
+
predicates = load_predicate_registry(args.manifest)
|
|
693
|
+
resolved_from_registry = ""
|
|
640
694
|
if args.id:
|
|
641
695
|
pid = args.id
|
|
642
696
|
source = "flag"
|
|
@@ -652,8 +706,13 @@ def cmd_predicate_resolve(ctx: Optional[Ctx], args: argparse.Namespace) -> None:
|
|
|
652
706
|
source = "description-marker"
|
|
653
707
|
entry = predicates.get(pid)
|
|
654
708
|
if entry is None:
|
|
655
|
-
|
|
656
|
-
|
|
709
|
+
where = "交付的 registry 投影" if args.registry else "manifest 注册表"
|
|
710
|
+
fail(f"predicate:{pid} 未在{where}登记(registered={sorted(predicates)})")
|
|
711
|
+
out({
|
|
712
|
+
"id": pid, "resolvedFrom": source, "predicate": entry,
|
|
713
|
+
"source": "delivered-registry" if args.registry else "project-manifest",
|
|
714
|
+
**({"registryHash": resolved_from_registry} if resolved_from_registry else {}),
|
|
715
|
+
})
|
|
657
716
|
|
|
658
717
|
|
|
659
718
|
def _annotate_predicate_ref(autopilot: Any) -> Any:
|
|
@@ -1292,10 +1351,17 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1292
1351
|
p = cmd(
|
|
1293
1352
|
"predicate-resolve",
|
|
1294
1353
|
cmd_predicate_resolve,
|
|
1295
|
-
"Resolve a completion predicate
|
|
1296
|
-
"(
|
|
1354
|
+
"Resolve a completion predicate — from the delivered runtime registry projection "
|
|
1355
|
+
"(--registry, what a schedule run actually has) or from the declaring manifest "
|
|
1356
|
+
"(--manifest, operator-side against the local checkout)",
|
|
1357
|
+
)
|
|
1358
|
+
where_group = p.add_mutually_exclusive_group(required=True)
|
|
1359
|
+
where_group.add_argument("--manifest", help="path to dingtalk-agent.json (declaration side)")
|
|
1360
|
+
where_group.add_argument(
|
|
1361
|
+
"--registry",
|
|
1362
|
+
help="path to the delivered predicate-registry.json inside the skill tree "
|
|
1363
|
+
"(runtime side; schema + integrity hash are verified)",
|
|
1297
1364
|
)
|
|
1298
|
-
p.add_argument("--manifest", required=True, help="path to dingtalk-agent.json")
|
|
1299
1365
|
src_group = p.add_mutually_exclusive_group(required=True)
|
|
1300
1366
|
src_group.add_argument("--id", help="predicate id (skip marker parsing)")
|
|
1301
1367
|
src_group.add_argument("--description", help="autopilot description; the [dta-completion-predicate] marker is parsed out")
|