@passioncode-ai/passioncode 0.2.38 → 0.2.39
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 +8 -0
- package/family.json +1 -1
- package/package.json +1 -1
- package/payload/.claude-plugin/marketplace.json +2 -2
- package/payload/manifest.json +8 -8
- package/payload/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +29 -11
- package/payload/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/dashboard-links.md +53 -3
- package/payload/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/operator-channel-and-repository.md +11 -3
- package/payload/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +47 -12
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-button.js +5 -4
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/kit.json +9 -4
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md +3 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-links.md +53 -3
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard.md +13 -4
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +10 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +99 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +1 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +5 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/settings-backups.md +2 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/surfaces-and-auth.md +5 -3
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +45 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_rules.py +325 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-actions.mjs +246 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs +3 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +22 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +18 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop-rules.mjs +45 -3
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs +2 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +1 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_actions.py +302 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py +2 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +22 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +22 -3
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +154 -8
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop_rules.py +45 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +9 -0
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +124 -16
- package/payload/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +29 -11
- package/payload/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/dashboard-links.md +53 -3
- package/payload/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/operator-channel-and-repository.md +11 -3
- package/payload/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +41 -9
- package/payload/plugins/fabric-agent-adapter/skills/working-with-fabric/references/project-board.md +2 -0
- package/payload/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
- package/payload/plugins/passioncode/.claude-plugin/plugin.json +1 -1
|
@@ -24,11 +24,14 @@ from pathlib import Path
|
|
|
24
24
|
import re
|
|
25
25
|
import secrets
|
|
26
26
|
import sys
|
|
27
|
+
import time
|
|
27
28
|
from typing import Any, Callable, Dict, List, Optional
|
|
28
29
|
|
|
29
30
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
30
31
|
import fabric_service as _fs # noqa: E402
|
|
31
32
|
from fabric_base import store_lock # noqa: E402 - one lock per store path (R3)
|
|
33
|
+
from fabric_actions import action_caller, readable_action # noqa: E402 - DEC-0121
|
|
34
|
+
from fabric_time import format_rfc3339 # noqa: E402 - the core's (FAA-65)
|
|
32
35
|
|
|
33
36
|
from fabric_interop_rules import ( # noqa: E402,F401 - the rule layer (FAA-92)
|
|
34
37
|
_days_from_civil,
|
|
@@ -77,6 +80,8 @@ from fabric_interop_rules import ( # noqa: E402,F401 - the rule layer (FAA-92)
|
|
|
77
80
|
intent_idempotency_key,
|
|
78
81
|
reads_null_usage,
|
|
79
82
|
request_meta,
|
|
83
|
+
action_gate,
|
|
84
|
+
action_refusal_tool_result,
|
|
80
85
|
usage_findings,
|
|
81
86
|
usage_toward,
|
|
82
87
|
_job_findings,
|
|
@@ -430,16 +435,26 @@ class JobStore:
|
|
|
430
435
|
# --- a minimal MCP tool server (streamable HTTP, JSON responses) ------------------------
|
|
431
436
|
|
|
432
437
|
class CallContext:
|
|
433
|
-
"""What a tool handler gets: the child span it runs in, and a way to start a job.
|
|
438
|
+
"""What a tool handler gets: the child span it runs in, and a way to start a job.
|
|
439
|
+
|
|
440
|
+
DEC-0121: `tier` is the caller's (DL-25), `caller` the identity the service authenticated (decision D9), `meta`
|
|
441
|
+
the request's `_meta`. For a tool registered with an action, `record` is action_decision's recordAs: "caller"
|
|
442
|
+
(the caller's own act) or {by, via, caller}, the act to put in the service's audit record, and `decision` the
|
|
443
|
+
operator's decision it took (its `instruction` stays in that record, never in events or a page another party
|
|
444
|
+
reads), else None. `input_records` maps each answered input request to its record when input_actions is on."""
|
|
434
445
|
|
|
435
446
|
def __init__(self, server: "McpToolServer", tool: str, arguments: Any, traceparent: str,
|
|
436
|
-
delegation: Optional[Dict[str, Any]] = None
|
|
447
|
+
delegation: Optional[Dict[str, Any]] = None, *, tier: Optional[str] = None, caller: Optional[str] = None,
|
|
448
|
+
meta: Optional[Dict[str, Any]] = None, record: Any = None, decision: Optional[Dict[str, Any]] = None,
|
|
449
|
+
input_records: Optional[Dict[str, Any]] = None):
|
|
437
450
|
self.server = server
|
|
438
451
|
self.tool = tool
|
|
439
452
|
self.arguments = arguments
|
|
440
453
|
self.traceparent = traceparent
|
|
441
454
|
# DEC-0039: the accepted delegation (principal, caller, chain, claims) when the server has a gate.
|
|
442
455
|
self.delegation = delegation
|
|
456
|
+
self.tier, self.caller, self.meta = tier, caller, {} if meta is None else meta
|
|
457
|
+
self.record, self.decision, self.input_records = record, decision, input_records
|
|
443
458
|
|
|
444
459
|
def start_job(self, poll_interval_ms: Optional[int] = None) -> Dict[str, Any]:
|
|
445
460
|
if self.server.jobs is None:
|
|
@@ -547,11 +562,26 @@ class McpToolServer:
|
|
|
547
562
|
def __init__(self, name: str, version: str, jobs: Optional[JobStore] = None,
|
|
548
563
|
on_job_started: Optional[Callable[[str, CallContext], None]] = None,
|
|
549
564
|
on_input: Optional[OnInput] = None,
|
|
550
|
-
authorize: Optional[Callable[[str, Any], Dict[str, Any]]] = None
|
|
565
|
+
authorize: Optional[Callable[[str, Any], Dict[str, Any]]] = None, *,
|
|
566
|
+
identify: Optional[Callable[[Any, str], Optional[str]]] = None,
|
|
567
|
+
approve: Optional[Callable[[str, Dict[str, Any], Any, str], Optional[Dict[str, Any]]]] = None,
|
|
568
|
+
elicited: Optional[Callable[[str, Dict[str, Any], Optional[str]], bool]] = None,
|
|
569
|
+
input_actions: bool = False, clock: Callable[[], float] = time.time,
|
|
570
|
+
on_fault: Optional[Callable[[str, str], None]] = None):
|
|
551
571
|
# authorize(tool, headers, tier=) runs before every handler (fabric_delegation.delegation_gate, DEC-0039):
|
|
552
572
|
# a refusal is answered in the DL-19 shape and the handler never runs. The built-in job tools are
|
|
553
573
|
# gated by the job's own capability, and answered only for the principal and caller that started it.
|
|
574
|
+
# DEC-0121: a tool added with an action runs action_gate after authorize and before its handler.
|
|
575
|
+
# identify(headers, tier) names the caller the service authenticated when no delegation did (D9; else
|
|
576
|
+
# local:T0 / local:T1); approve(tool, arguments, headers, digest) answers verify_approval's outcome for an
|
|
577
|
+
# approval the call presented, or None; elicited(tool, arguments, caller) is True only on the service's own
|
|
578
|
+
# record of an accepted elicitation. input_actions=True gates each answered input request as an action (D8).
|
|
579
|
+
# on_fault(tool, fault) hears a service fault the caller only sees as unknown-state (e.g. caller-missing: an
|
|
580
|
+
# action-gated server needs a tier, identify or authorize that names who calls).
|
|
554
581
|
self._authorize = authorize
|
|
582
|
+
self._identify, self._approve, self._elicited = identify, approve, elicited
|
|
583
|
+
self.input_actions, self._clock, self._on_fault = input_actions is True, clock, on_fault
|
|
584
|
+
self.actions: Dict[str, Dict[str, Any]] = {}
|
|
555
585
|
self.info = {"name": name, "version": version}
|
|
556
586
|
self.jobs = jobs
|
|
557
587
|
self.tools: List[Dict[str, Any]] = []
|
|
@@ -559,14 +589,101 @@ class McpToolServer:
|
|
|
559
589
|
self._on_job_started = on_job_started
|
|
560
590
|
self._on_input = on_input
|
|
561
591
|
|
|
562
|
-
def add_tool(self, tool: Dict[str, Any], handler: Handler
|
|
592
|
+
def add_tool(self, tool: Dict[str, Any], handler: Handler, action: Optional[Dict[str, Any]] = None, *,
|
|
593
|
+
target: Any = None, human_step_url: Optional[str] = None) -> None:
|
|
594
|
+
"""Serve a tool. `action` (DEC-0121 AP-1) is the declared action this tool performs, {id, title, tool, gate,
|
|
595
|
+
humanStep?}, its `tool` this tool's name: the server runs action_gate before the handler. `target` names the
|
|
596
|
+
object a call acts on: an argument's name, or a function of the arguments; `human_step_url` is the link of a
|
|
597
|
+
`human` action's step (an https URL or a path on the service's origin, AP-4)."""
|
|
563
598
|
if tool["name"] in self.handlers:
|
|
564
599
|
raise InteropError("Tool %s is served twice." % tool["name"])
|
|
565
600
|
if "outputSchema" in tool:
|
|
566
601
|
require_object_root(tool["name"], tool["outputSchema"])
|
|
602
|
+
if action is not None:
|
|
603
|
+
if not readable_action(action) or action["tool"] != tool["name"]:
|
|
604
|
+
raise InteropError("Tool %s: its action is not a declared action of this tool (DEC-0121)." % tool["name"])
|
|
605
|
+
if action["id"] in {a["action"]["id"] for a in self.actions.values()}:
|
|
606
|
+
raise InteropError("Action %s is declared twice." % action["id"])
|
|
607
|
+
if action["gate"] == "human" and not (isinstance(human_step_url, str) and re.match(r"https://|/", human_step_url)):
|
|
608
|
+
raise InteropError("Tool %s: a human step needs its link, an https URL or a path (DEC-0121 AP-4)." % tool["name"])
|
|
609
|
+
if not (target is None or isinstance(target, str) or callable(target)):
|
|
610
|
+
raise InteropError("Tool %s: target is an argument's name or a function of the arguments." % tool["name"])
|
|
611
|
+
self.actions[tool["name"]] = {"action": dict(action), "target": target, "url": human_step_url}
|
|
567
612
|
self.tools.append(tool)
|
|
568
613
|
self.handlers[tool["name"]] = handler
|
|
569
614
|
|
|
615
|
+
def action_table(self) -> List[Dict[str, Any]]:
|
|
616
|
+
"""The declared actions in the order they were added: build_well_known(actions=) writes them (DEC-0121 AP-1)."""
|
|
617
|
+
return [dict(entry["action"]) for entry in self.actions.values()]
|
|
618
|
+
|
|
619
|
+
def _caller(self, headers: Any, tier: str, verdict: Optional[Dict[str, Any]]) -> Optional[str]:
|
|
620
|
+
"""D9: the delegation's caller when a gate accepted a token, else identify(headers, tier), else the local floor."""
|
|
621
|
+
authenticated = (verdict or {}).get("caller")
|
|
622
|
+
if not authenticated and self._identify is not None:
|
|
623
|
+
authenticated = self._identify(headers, tier)
|
|
624
|
+
return action_caller(tier, authenticated)
|
|
625
|
+
|
|
626
|
+
def _gate_action(self, action: Dict[str, Any], name: str, arguments: Dict[str, Any], target: Any, url: Any,
|
|
627
|
+
headers: Any, tier: str, meta: Dict[str, Any], caller: Optional[str]) -> Dict[str, Any]:
|
|
628
|
+
"""action_gate for one call: the approval the call presented, the digest of {tool, arguments}, the clock."""
|
|
629
|
+
digest, approval = None, None
|
|
630
|
+
if action["gate"] == "relayed":
|
|
631
|
+
import fabric_delegation as _fd # noqa: E402 - only an action-gated server needs it
|
|
632
|
+
try:
|
|
633
|
+
digest = _fd.action_digest({"tool": name, "arguments": arguments})
|
|
634
|
+
except (TypeError, ValueError, RecursionError): # no canonical form (a lone surrogate, a non-finite number,
|
|
635
|
+
# nesting past the recursion limit), as intent_digest reads it: no digest to bind
|
|
636
|
+
return {"ok": False, "invalid": "Invalid params: the arguments have no canonical form."}
|
|
637
|
+
outcome = self._approve(name, arguments, headers, digest) if self._approve is not None else None
|
|
638
|
+
if isinstance(outcome, dict) and outcome.get("ok") is True:
|
|
639
|
+
approval = outcome
|
|
640
|
+
elif isinstance(outcome, dict) and outcome.get("code") not in (None, "approval-required"):
|
|
641
|
+
# DL-18: the presented approval's own refusal; an outcome that is not verify_approval's is the service's.
|
|
642
|
+
readable = outcome.get("code") in _fd.REFUSAL_CODES and isinstance(outcome.get("detail"), str) and outcome["detail"]
|
|
643
|
+
if readable:
|
|
644
|
+
return {"ok": False, "refusal": outcome}
|
|
645
|
+
return {"ok": False, "refusal": {"ok": False, "code": "unknown-state", "detail": "service-fault"},
|
|
646
|
+
"fault": "approval-outcome-unreadable"}
|
|
647
|
+
elicited = action["gate"] == "relayed" and self._elicited is not None and self._elicited(name, arguments, caller) is True
|
|
648
|
+
return action_gate(action, tier=tier, caller=caller, meta=meta, target=target, elicited=elicited, approval=approval,
|
|
649
|
+
action_digest=digest, human_step_url=url, now=format_rfc3339(self._clock() * 1000))
|
|
650
|
+
|
|
651
|
+
def _gate_inputs(self, arguments: Dict[str, Any], headers: Any, tier: str, meta: Dict[str, Any],
|
|
652
|
+
caller: Optional[str]) -> Dict[str, Any]:
|
|
653
|
+
"""D8: each input request an answer would take is an action (id its key, tool fabric.job.get, gate relayed),
|
|
654
|
+
one decision per call; the first refusal refuses the call and nothing is applied."""
|
|
655
|
+
job_id = str(arguments.get("id", ""))
|
|
656
|
+
job = self.jobs.get(job_id)
|
|
657
|
+
asked = job.get("inputRequests", {}) if job["status"] == "input_required" else {}
|
|
658
|
+
records: Dict[str, Any] = {}
|
|
659
|
+
for key, value in arguments["inputResponses"].items():
|
|
660
|
+
if key not in asked or not isinstance(value, dict) or value.get("action") not in ("accept", "decline", "cancel"):
|
|
661
|
+
continue
|
|
662
|
+
action = {"id": key, "title": "Answer %s" % key, "tool": "fabric.job.get", "gate": "relayed"}
|
|
663
|
+
gated = self._gate_action(action, "fabric.job.get", {"id": job_id, "inputResponses": {key: value}}, None, None,
|
|
664
|
+
headers, tier, meta, caller)
|
|
665
|
+
if not gated["ok"]:
|
|
666
|
+
return gated
|
|
667
|
+
records[key] = gated["record"]
|
|
668
|
+
return {"ok": True, "records": records}
|
|
669
|
+
|
|
670
|
+
def _fault(self, tool: str, gated: Dict[str, Any]) -> None:
|
|
671
|
+
"""Hand a service fault to on_fault; the caller saw only unknown-state. A hook that raises is the service's."""
|
|
672
|
+
if gated.get("fault") and self._on_fault is not None:
|
|
673
|
+
try:
|
|
674
|
+
self._on_fault(tool, str(gated["fault"]))
|
|
675
|
+
except Exception: # noqa: BLE001 - logging must not change the answer
|
|
676
|
+
pass
|
|
677
|
+
|
|
678
|
+
@staticmethod
|
|
679
|
+
def _target(target: Any, arguments: Dict[str, Any]) -> Optional[str]:
|
|
680
|
+
"""The object a call acts on: the named argument, or what the service's function answers; a string or None."""
|
|
681
|
+
try:
|
|
682
|
+
value = target(arguments) if callable(target) else arguments.get(target) if isinstance(target, str) else None
|
|
683
|
+
except Exception: # noqa: BLE001 - a function that cannot read this call names no object
|
|
684
|
+
return None
|
|
685
|
+
return value if isinstance(value, str) else None
|
|
686
|
+
|
|
570
687
|
def job_started(self, job_id: str, ctx: CallContext) -> None:
|
|
571
688
|
if self._on_job_started:
|
|
572
689
|
self._on_job_started(job_id, ctx)
|
|
@@ -641,7 +758,21 @@ class McpToolServer:
|
|
|
641
758
|
if not verdict.get("ok"):
|
|
642
759
|
import fabric_delegation as _fd # noqa: E402 - only a gated server needs it
|
|
643
760
|
return {"jsonrpc": "2.0", "id": rid, "result": _fd.refusal_tool_result(verdict, traceparent=span)}
|
|
644
|
-
|
|
761
|
+
caller, inputs = self._caller(headers, tier, verdict), None
|
|
762
|
+
responses = arguments.get("inputResponses")
|
|
763
|
+
if name == "fabric.job.get" and self.input_actions and isinstance(responses, dict) and responses:
|
|
764
|
+
try:
|
|
765
|
+
inputs = self._gate_inputs(arguments, headers, tier, meta, caller)
|
|
766
|
+
except UnknownJob:
|
|
767
|
+
return {"jsonrpc": "2.0", "id": rid, "result": unknown_job_result(str(arguments.get("id", "")), traceparent=span)}
|
|
768
|
+
if not inputs["ok"] and "invalid" in inputs:
|
|
769
|
+
return self._error(rid, -32602, inputs["invalid"])
|
|
770
|
+
if not inputs["ok"]:
|
|
771
|
+
self._fault(name, inputs)
|
|
772
|
+
import fabric_delegation as _fd # noqa: E402 - DL-19
|
|
773
|
+
return {"jsonrpc": "2.0", "id": rid, "result": _fd.refusal_tool_result(inputs["refusal"], traceparent=span)}
|
|
774
|
+
context = {"tier": tier, "caller": caller, "meta": meta, "input_records": inputs["records"] if inputs else None}
|
|
775
|
+
return {"jsonrpc": "2.0", "id": rid, "result": self._job_call(name, arguments, span, verdict, context)}
|
|
645
776
|
handler = self.handlers.get(name)
|
|
646
777
|
if handler is None:
|
|
647
778
|
return self._error(rid, -32602, "Unknown tool: %s." % name)
|
|
@@ -652,14 +783,26 @@ class McpToolServer:
|
|
|
652
783
|
import fabric_delegation as _fd # noqa: E402 - only a gated server needs it
|
|
653
784
|
return {"jsonrpc": "2.0", "id": rid, "result": _fd.refusal_tool_result(verdict, traceparent=span)}
|
|
654
785
|
delegation = verdict
|
|
786
|
+
caller, gated, entry = self._caller(headers, tier, delegation), {"record": None, "decision": None}, self.actions.get(name)
|
|
787
|
+
if entry is not None: # DEC-0121: after the authorize gate, before the handler
|
|
788
|
+
gated = self._gate_action(entry["action"], name, arguments, self._target(entry["target"], arguments), entry["url"],
|
|
789
|
+
headers, tier, meta, caller)
|
|
790
|
+
if not gated["ok"] and "invalid" in gated:
|
|
791
|
+
return self._error(rid, -32602, gated["invalid"])
|
|
792
|
+
if not gated["ok"]:
|
|
793
|
+
self._fault(name, gated)
|
|
794
|
+
import fabric_delegation as _fd # noqa: E402 - DL-19
|
|
795
|
+
return {"jsonrpc": "2.0", "id": rid, "result": _fd.refusal_tool_result(gated["refusal"], traceparent=span)}
|
|
796
|
+
context = CallContext(self, name, arguments, span, delegation, tier=tier, caller=caller, meta=meta,
|
|
797
|
+
record=gated["record"], decision=gated["decision"])
|
|
655
798
|
try:
|
|
656
|
-
structured = handler(arguments,
|
|
799
|
+
structured = handler(arguments, context)
|
|
657
800
|
except InteropError as exc:
|
|
658
801
|
return {"jsonrpc": "2.0", "id": rid, "result": tool_result({"error": {"code": "tool-error", "message": str(exc)}}, is_error=True, traceparent=span)}
|
|
659
802
|
return {"jsonrpc": "2.0", "id": rid, "result": tool_result(structured, traceparent=span)}
|
|
660
803
|
|
|
661
804
|
def _job_call(self, name: str, arguments: Dict[str, Any], span: str,
|
|
662
|
-
delegation: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
805
|
+
delegation: Optional[Dict[str, Any]] = None, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
663
806
|
job_id = str(arguments.get("id", ""))
|
|
664
807
|
try:
|
|
665
808
|
job_span = self.jobs.traceparent(job_id) or span
|
|
@@ -674,11 +817,14 @@ class McpToolServer:
|
|
|
674
817
|
state = self.jobs.get(job_id)
|
|
675
818
|
return tool_result({"job": state}, traceparent=job_span)
|
|
676
819
|
responses = arguments.get("inputResponses")
|
|
820
|
+
context = context or {}
|
|
821
|
+
if responses and context.get("input_records") is not None: # D8: only the keys the action gate took
|
|
822
|
+
responses = {key: responses[key] for key in context["input_records"]}
|
|
677
823
|
if responses:
|
|
678
824
|
matched = self.jobs.answer(job_id, responses)
|
|
679
825
|
if matched and self._on_input:
|
|
680
826
|
private = self.jobs.private(job_id)
|
|
681
|
-
self._on_input(job_id, matched, CallContext(self, private["capability"], private["input"], job_span, delegation))
|
|
827
|
+
self._on_input(job_id, matched, CallContext(self, private["capability"], private["input"], job_span, delegation, **context))
|
|
682
828
|
return tool_result({"job": self.jobs.get(job_id)}, traceparent=job_span)
|
|
683
829
|
except UnknownJob:
|
|
684
830
|
return unknown_job_result(job_id, traceparent=span)
|
|
@@ -17,6 +17,7 @@ if str(_Path(__file__).resolve().parent) not in _sys.path: # the kit loads from
|
|
|
17
17
|
_sys.path.insert(0, str(_Path(__file__).resolve().parent))
|
|
18
18
|
|
|
19
19
|
from fabric_base import ServiceError # noqa: E402
|
|
20
|
+
from fabric_actions import action_decision, decision_shape # noqa: E402 - DEC-0121
|
|
20
21
|
|
|
21
22
|
PROTOCOL = "fabric-interop/0.1"
|
|
22
23
|
EXTENSION_KEY = "https://fabric.passioncode.ai/agent-contract/extensions/interop/0.1"
|
|
@@ -288,14 +289,56 @@ def reads_null_usage(request_meta: Any) -> bool:
|
|
|
288
289
|
return isinstance(protocols, list) and INTEROP_NULL_USAGE in protocols
|
|
289
290
|
|
|
290
291
|
|
|
291
|
-
def request_meta(traceparent: Optional[str] = None) -> Dict[str, Any]:
|
|
292
|
-
"""A request's `_meta` from this kit as a caller: its trace,
|
|
292
|
+
def request_meta(traceparent: Optional[str] = None, decision: Any = None) -> Dict[str, Any]:
|
|
293
|
+
"""A request's `_meta` from this kit as a caller: its trace, the interop revisions it reads (DEC-0087) and, for a
|
|
294
|
+
relayed action, the operator's decision (DEC-0121 AP-2; build one with fabric_actions.operator_decision). A
|
|
295
|
+
decision travels here only, never in a tool's arguments; one decision.schema.json refuses raises InteropError."""
|
|
293
296
|
meta: Dict[str, Any] = {"protocols": list(PROTOCOLS_READ)}
|
|
294
297
|
if parse_traceparent(traceparent):
|
|
295
298
|
meta["traceparent"] = traceparent
|
|
299
|
+
if decision is not None:
|
|
300
|
+
if not decision_shape(decision):
|
|
301
|
+
raise InteropError("The decision is not one decision.schema.json reads; it is not sent.")
|
|
302
|
+
meta["decision"] = dict(decision)
|
|
296
303
|
return meta
|
|
297
304
|
|
|
298
305
|
|
|
306
|
+
def action_gate(action: Any, *, tier: Any, caller: Any, meta: Any = None, target: Optional[str] = None,
|
|
307
|
+
elicited: bool = False, approval: Any = None, action_digest: Optional[str] = None,
|
|
308
|
+
human_step_url: Optional[str] = None, now: Any = None) -> Dict[str, Any]:
|
|
309
|
+
"""One call of a declared action, before its handler runs (DEC-0121 AP-2, AP-4): fabric_actions.action_decision over
|
|
310
|
+
the call's `_meta.decision` (read from `meta` only, never from arguments, decision D11), the service's authenticated
|
|
311
|
+
`caller` (fabric_actions.action_caller), `target` (the object the call acts on), `elicited` (the service's own
|
|
312
|
+
record of an accepted elicitation), `approval` (verify_approval's accepted outcome), `action_digest`,
|
|
313
|
+
`human_step_url` and `now` (RFC 3339). Answers {ok: True, record, decision}, `decision` being the one taken as the
|
|
314
|
+
operator's (None otherwise), or {ok: False, refusal} in the DL-19 form (fabric_delegation.refusal_tool_result
|
|
315
|
+
sends it); a service's own fault is the refusal unknown-state with `fault` beside it for the service's log."""
|
|
316
|
+
import fabric_delegation as _fd # noqa: E402 - beside this file: DL-19
|
|
317
|
+
inputs: Dict[str, Any] = {"action": action, "tier": tier, "caller": caller, "elicited": elicited is True, "now": now}
|
|
318
|
+
if isinstance(meta, dict) and "decision" in meta:
|
|
319
|
+
inputs["decision"] = meta["decision"]
|
|
320
|
+
for name, value in (("target", target), ("approval", approval), ("actionDigest", action_digest), ("humanStepUrl", human_step_url)):
|
|
321
|
+
if value is not None:
|
|
322
|
+
inputs[name] = value
|
|
323
|
+
answer = action_decision(inputs)
|
|
324
|
+
if answer.get("ok") is True:
|
|
325
|
+
record = answer["recordAs"]
|
|
326
|
+
taken = isinstance(record, dict) and record.get("via") == "relayed-instruction"
|
|
327
|
+
return {"ok": True, "record": record, "decision": inputs["decision"] if taken else None}
|
|
328
|
+
out: Dict[str, Any] = {"ok": False, "refusal": _fd.refusal_from_action(answer)}
|
|
329
|
+
if "fault" in answer:
|
|
330
|
+
out["fault"] = answer["fault"]
|
|
331
|
+
return out
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def action_refusal_tool_result(answer: Any, traceparent: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
335
|
+
"""The tools/call result a service's own MCP server answers for an action_decision answer: None when the action
|
|
336
|
+
takes the call, else DL-19's refusal as structuredContent with isError true (DEC-0121)."""
|
|
337
|
+
import fabric_delegation as _fd # noqa: E402 - beside this file: DL-19
|
|
338
|
+
refusal = _fd.refusal_from_action(answer)
|
|
339
|
+
return None if refusal is None else _fd.refusal_tool_result(refusal, traceparent=traceparent)
|
|
340
|
+
|
|
341
|
+
|
|
299
342
|
def usage_findings(usage: Any, at: str) -> List[Dict[str, str]]:
|
|
300
343
|
"""FAC-SEM-119 on a usage: partial false asserts every number known, so it stands beside no null."""
|
|
301
344
|
if not isinstance(usage, dict) or usage.get("partial", _ABSENT) is not False:
|
|
@@ -15,7 +15,7 @@ if str(_Path(__file__).resolve().parent) not in _sys.path: # the kit loads from
|
|
|
15
15
|
PROTOCOL_REVISIONS: Dict[str, Tuple[str, ...]] = {
|
|
16
16
|
"access-log": ("1",), "approval": ("1",), "activity-summary": ("1",), "agent-directory": ("1",), "call-record": ("1",), "coding-agents": ("1",), "credential-decision": ("1",), "credential-request": ("1",), "credential-revocation": ("1",), "enroll-token": ("1",), "entitlement": ("1",),
|
|
17
17
|
"entitlement-key-set": ("1",), "estate-record": ("1",), "execution-packet": ("1",),
|
|
18
|
-
"fabric-activity": ("0.1",), "fabric-agent-call": ("1",), "fabric-connections": ("0.1",), "fabric-credential-envelope": ("1",), "fabric-load": ("0.1",), "fabric-dashboard": ("0.1",), "fabric-delegation": ("0.1",), "fabric-device": ("0.1",),
|
|
18
|
+
"fabric-actions": ("0.1",), "fabric-activity": ("0.1",), "fabric-agent-call": ("1",), "fabric-connections": ("0.1",), "fabric-credential-envelope": ("1",), "fabric-load": ("0.1",), "fabric-dashboard": ("0.1",), "fabric-delegation": ("0.1",), "fabric-device": ("0.1",),
|
|
19
19
|
"fabric-interop": ("0.1", "0.2"), "fabric-local-channel": ("0.1",), "fabric-local-runner": ("0.1",),
|
|
20
20
|
"fabric-operator-channel": ("0.1",), "fabric-package": ("1",), "fabric-project-comms": ("0.1",), "fabric-proposal": ("1",),
|
|
21
21
|
"fabric-provider": ("0.1",), "fabric-relay": ("0.1",), "fabric-secret-envelope": ("1",), "fabric-service": ("0.1",),
|
|
@@ -181,6 +181,15 @@ from fabric_backups import ( # noqa: F401
|
|
|
181
181
|
newest_intact_backup,
|
|
182
182
|
restore_plan,
|
|
183
183
|
)
|
|
184
|
+
from fabric_actions import ( # noqa: F401
|
|
185
|
+
ACTIONS_EXTENSION_KEY,
|
|
186
|
+
action_decision,
|
|
187
|
+
action_rules,
|
|
188
|
+
actions_extension,
|
|
189
|
+
actions_extension_rules,
|
|
190
|
+
actions_view,
|
|
191
|
+
decision_shape,
|
|
192
|
+
)
|
|
184
193
|
from fabric_connections import ( # noqa: F401
|
|
185
194
|
CONNECTIONS_EXTENSION_KEY,
|
|
186
195
|
connections_extension,
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabric-service-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"about": "The service kit's modules in dependency order: a module imports only modules listed before it. Written by fabric_kit.py build; edit the order and layers by hand, never the digests.",
|
|
5
5
|
"python": [
|
|
6
6
|
{
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"fabric_jsvalue",
|
|
90
90
|
"fabric_paths"
|
|
91
91
|
],
|
|
92
|
-
"sha256": "
|
|
92
|
+
"sha256": "f6c135126d2b9f6ff0c93f2947be1aa03d99460cb759495f51fe86f3edf481b3"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"module": "fabric_share",
|
|
@@ -150,7 +150,18 @@
|
|
|
150
150
|
"imports": [
|
|
151
151
|
"fabric_secrets"
|
|
152
152
|
],
|
|
153
|
-
"sha256": "
|
|
153
|
+
"sha256": "4e78c4004d5d8eb26d1a6e40d6ab75f68af2a7f9165d386f9a62e79e69dcae19"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"module": "fabric_actions",
|
|
157
|
+
"file": "fabric_actions.py",
|
|
158
|
+
"layer": "L3",
|
|
159
|
+
"imports": [
|
|
160
|
+
"fabric_base",
|
|
161
|
+
"fabric_jsvalue",
|
|
162
|
+
"fabric_time"
|
|
163
|
+
],
|
|
164
|
+
"sha256": "44feb5e70bd9894c5ed1fa23bf8df55989ec99acb934b24bf97ddd7295891251"
|
|
154
165
|
},
|
|
155
166
|
{
|
|
156
167
|
"module": "fabric_connections",
|
|
@@ -195,13 +206,14 @@
|
|
|
195
206
|
"fabric_paths",
|
|
196
207
|
"fabric_usage"
|
|
197
208
|
],
|
|
198
|
-
"sha256": "
|
|
209
|
+
"sha256": "1f3f0d7ecf361b29e9101e07f1c53e5dc304d598bf26fd59ec89f16b9fed2420"
|
|
199
210
|
},
|
|
200
211
|
{
|
|
201
212
|
"module": "fabric_descriptor",
|
|
202
213
|
"file": "fabric_descriptor.py",
|
|
203
214
|
"layer": "L3",
|
|
204
215
|
"imports": [
|
|
216
|
+
"fabric_actions",
|
|
205
217
|
"fabric_base",
|
|
206
218
|
"fabric_connections",
|
|
207
219
|
"fabric_paths",
|
|
@@ -209,7 +221,7 @@
|
|
|
209
221
|
"fabric_secrets",
|
|
210
222
|
"fabric_usage"
|
|
211
223
|
],
|
|
212
|
-
"sha256": "
|
|
224
|
+
"sha256": "361610f7c5bc94642a26a6dd7e4b6a5849efa0bd2aa814a8e2034eaed30368b6"
|
|
213
225
|
},
|
|
214
226
|
{
|
|
215
227
|
"module": "fabric_auth",
|
|
@@ -261,6 +273,7 @@
|
|
|
261
273
|
"file": "fabric_service.py",
|
|
262
274
|
"layer": "L3",
|
|
263
275
|
"imports": [
|
|
276
|
+
"fabric_actions",
|
|
264
277
|
"fabric_auth",
|
|
265
278
|
"fabric_backups",
|
|
266
279
|
"fabric_base",
|
|
@@ -277,7 +290,7 @@
|
|
|
277
290
|
"fabric_time",
|
|
278
291
|
"fabric_usage"
|
|
279
292
|
],
|
|
280
|
-
"sha256": "
|
|
293
|
+
"sha256": "a2e813469a47d4d3eea996628635c8903007498bdb6a1ae032a7a5ce6f49fe2f"
|
|
281
294
|
},
|
|
282
295
|
{
|
|
283
296
|
"module": "fabric_profiles",
|
|
@@ -297,23 +310,26 @@
|
|
|
297
310
|
"file": "fabric_interop_rules.py",
|
|
298
311
|
"layer": "L3",
|
|
299
312
|
"imports": [
|
|
313
|
+
"fabric_actions",
|
|
300
314
|
"fabric_base",
|
|
301
315
|
"fabric_delegation",
|
|
302
316
|
"fabric_time"
|
|
303
317
|
],
|
|
304
|
-
"sha256": "
|
|
318
|
+
"sha256": "33dfb0841077df5379df425e288c1e01ae03c22344e6870024b5f4231ad89e75"
|
|
305
319
|
},
|
|
306
320
|
{
|
|
307
321
|
"module": "fabric_interop",
|
|
308
322
|
"file": "fabric_interop.py",
|
|
309
323
|
"layer": "L3",
|
|
310
324
|
"imports": [
|
|
325
|
+
"fabric_actions",
|
|
311
326
|
"fabric_base",
|
|
312
327
|
"fabric_delegation",
|
|
313
328
|
"fabric_interop_rules",
|
|
314
|
-
"fabric_service"
|
|
329
|
+
"fabric_service",
|
|
330
|
+
"fabric_time"
|
|
315
331
|
],
|
|
316
|
-
"sha256": "
|
|
332
|
+
"sha256": "0999ded29d908c8a55d13061f0b501887a5ea259dbf7d2251a90c04018761fbb"
|
|
317
333
|
},
|
|
318
334
|
{
|
|
319
335
|
"module": "fabric_hub",
|
|
@@ -485,7 +501,7 @@
|
|
|
485
501
|
"fabric-jsvalue",
|
|
486
502
|
"fabric-paths"
|
|
487
503
|
],
|
|
488
|
-
"sha256": "
|
|
504
|
+
"sha256": "fab1efdc1a9a0a9a00768905dded538fe185ca1b63c115dc4273717efc8e81f6"
|
|
489
505
|
},
|
|
490
506
|
{
|
|
491
507
|
"module": "fabric-share",
|
|
@@ -544,7 +560,18 @@
|
|
|
544
560
|
"imports": [
|
|
545
561
|
"fabric-secrets"
|
|
546
562
|
],
|
|
547
|
-
"sha256": "
|
|
563
|
+
"sha256": "acd32d9d05cf1a0319e84ad77cede479ef9b6337011e2cf7726e0e8aa590a9e0"
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"module": "fabric-actions",
|
|
567
|
+
"file": "fabric-actions.mjs",
|
|
568
|
+
"layer": "L3",
|
|
569
|
+
"imports": [
|
|
570
|
+
"fabric-base",
|
|
571
|
+
"fabric-jsvalue",
|
|
572
|
+
"fabric-time"
|
|
573
|
+
],
|
|
574
|
+
"sha256": "66f9ca7d1da31c89eeedffe7b78ff2230361d375d44c3aa90d9c60b66dfe5cbe"
|
|
548
575
|
},
|
|
549
576
|
{
|
|
550
577
|
"module": "fabric-connections",
|
|
@@ -590,13 +617,14 @@
|
|
|
590
617
|
"fabric-protocols",
|
|
591
618
|
"fabric-usage"
|
|
592
619
|
],
|
|
593
|
-
"sha256": "
|
|
620
|
+
"sha256": "cfd8c9085e3d597a783099c2bd2ffe2f3faa0daaadab46dedd30523894cfeb06"
|
|
594
621
|
},
|
|
595
622
|
{
|
|
596
623
|
"module": "fabric-descriptor",
|
|
597
624
|
"file": "fabric-descriptor.mjs",
|
|
598
625
|
"layer": "L3",
|
|
599
626
|
"imports": [
|
|
627
|
+
"fabric-actions",
|
|
600
628
|
"fabric-base",
|
|
601
629
|
"fabric-connections",
|
|
602
630
|
"fabric-paths",
|
|
@@ -604,7 +632,7 @@
|
|
|
604
632
|
"fabric-secrets",
|
|
605
633
|
"fabric-usage"
|
|
606
634
|
],
|
|
607
|
-
"sha256": "
|
|
635
|
+
"sha256": "c1ccaa9dff5edf90b82d6d77e2e5189a5d0f677fd48cc0aed3cccb83ad2a1f12"
|
|
608
636
|
},
|
|
609
637
|
{
|
|
610
638
|
"module": "fabric-auth",
|
|
@@ -657,6 +685,7 @@
|
|
|
657
685
|
"file": "fabric-service.mjs",
|
|
658
686
|
"layer": "L3",
|
|
659
687
|
"imports": [
|
|
688
|
+
"fabric-actions",
|
|
660
689
|
"fabric-auth",
|
|
661
690
|
"fabric-backups",
|
|
662
691
|
"fabric-base",
|
|
@@ -671,7 +700,7 @@
|
|
|
671
700
|
"fabric-supervisors",
|
|
672
701
|
"fabric-usage"
|
|
673
702
|
],
|
|
674
|
-
"sha256": "
|
|
703
|
+
"sha256": "6aa673657427211b491a9b63f94b9847a7e6aa3ee1b7353e1af11f46469803a3"
|
|
675
704
|
},
|
|
676
705
|
{
|
|
677
706
|
"module": "fabric-profiles",
|
|
@@ -690,11 +719,12 @@
|
|
|
690
719
|
"file": "fabric-interop-rules.mjs",
|
|
691
720
|
"layer": "L3",
|
|
692
721
|
"imports": [
|
|
722
|
+
"fabric-actions",
|
|
693
723
|
"fabric-base",
|
|
694
724
|
"fabric-delegation",
|
|
695
725
|
"fabric-jsvalue"
|
|
696
726
|
],
|
|
697
|
-
"sha256": "
|
|
727
|
+
"sha256": "fc8f3044afe209a1b23ddb3bc9b3993f4831913fa66bfd6e7855f1be80428e43"
|
|
698
728
|
},
|
|
699
729
|
{
|
|
700
730
|
"module": "fabric-interop",
|
|
@@ -705,7 +735,7 @@
|
|
|
705
735
|
"fabric-interop-rules",
|
|
706
736
|
"fabric-service"
|
|
707
737
|
],
|
|
708
|
-
"sha256": "
|
|
738
|
+
"sha256": "8f1ca418112d7129402783376bb9cbc9d2607f2aceec2a6796e703591a88f535"
|
|
709
739
|
},
|
|
710
740
|
{
|
|
711
741
|
"module": "fabric-hub",
|
|
@@ -3179,6 +3209,84 @@
|
|
|
3179
3209
|
"fabric-openrouter.mjs": "ab6c4c7251d563980d895061ee19976bde2f364c21b6354efdd9a9027b1ea139",
|
|
3180
3210
|
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
3181
3211
|
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
3212
|
+
},
|
|
3213
|
+
"0.50.0": {
|
|
3214
|
+
"fabric_jsvalue.py": "12888a2c934a885d35999ac9782eaedc8d04946d9775213344a235a8814d3d28",
|
|
3215
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
3216
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
3217
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
3218
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
3219
|
+
"fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
|
|
3220
|
+
"fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
|
|
3221
|
+
"fabric_paths.py": "6c92af34292baddf7e10d3134d0a5b0bb23387741812a9f79c409cf1628bad23",
|
|
3222
|
+
"fabric_estate.py": "a0ddc49d748c1efb1830de176998d6c8eac30f77d387c71eae12549c52aaab27",
|
|
3223
|
+
"fabric_delegation.py": "f6c135126d2b9f6ff0c93f2947be1aa03d99460cb759495f51fe86f3edf481b3",
|
|
3224
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
3225
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
3226
|
+
"fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
|
|
3227
|
+
"fabric_package.py": "ff533f1b3f92b4ea0f532fcec50b68c610d47549930eef8ad5247692a64dfb3c",
|
|
3228
|
+
"fabric_protocols.py": "4e78c4004d5d8eb26d1a6e40d6ab75f68af2a7f9165d386f9a62e79e69dcae19",
|
|
3229
|
+
"fabric_actions.py": "44feb5e70bd9894c5ed1fa23bf8df55989ec99acb934b24bf97ddd7295891251",
|
|
3230
|
+
"fabric_connections.py": "77d3ccf863c70e9209d21ef45c46a6db9c06237019bc20d54f8d3946873f3f11",
|
|
3231
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
3232
|
+
"fabric_usage.py": "b1f335cab4625171a616cf68cf3fd892b18bdadcf4baec3a3a0fdcf12785c170",
|
|
3233
|
+
"fabric_backups.py": "1f3f0d7ecf361b29e9101e07f1c53e5dc304d598bf26fd59ec89f16b9fed2420",
|
|
3234
|
+
"fabric_descriptor.py": "361610f7c5bc94642a26a6dd7e4b6a5849efa0bd2aa814a8e2034eaed30368b6",
|
|
3235
|
+
"fabric_auth.py": "71115d18c67b7b806cb57b64b77e01ad97fc0e63e6f49ee850f778123617d905",
|
|
3236
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
3237
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
3238
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
3239
|
+
"fabric_service.py": "a2e813469a47d4d3eea996628635c8903007498bdb6a1ae032a7a5ce6f49fe2f",
|
|
3240
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
3241
|
+
"fabric_interop_rules.py": "33dfb0841077df5379df425e288c1e01ae03c22344e6870024b5f4231ad89e75",
|
|
3242
|
+
"fabric_interop.py": "0999ded29d908c8a55d13061f0b501887a5ea259dbf7d2251a90c04018761fbb",
|
|
3243
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
3244
|
+
"fabric_board_shapes.py": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e",
|
|
3245
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
3246
|
+
"fabric_board_session.py": "2845d7d758b06ac4588bdf825a471c201a46ce535a631805697b1e35495fead6",
|
|
3247
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
3248
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
3249
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
3250
|
+
"fabric_openrouter.py": "309f588f9c976b1061323f3161e35d86248afd5b59b16391afbfc4e1099ecd65",
|
|
3251
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
3252
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
3253
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
3254
|
+
"fabric-secrets.mjs": "6ad8ab18ac899ecc2384e8ec6a3fb689b92be3b9a5ce3a59b92a37d52da5d766",
|
|
3255
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
3256
|
+
"fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
|
|
3257
|
+
"fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
|
|
3258
|
+
"fabric-paths.mjs": "2201b4ed7126f260931b63e8386377b4317d8dcad419d109bf22c683e44b7f29",
|
|
3259
|
+
"fabric-estate.mjs": "b6610aaad9d00d8a7f42955627fb81725950841455bcedfc050abb0e079f0f93",
|
|
3260
|
+
"fabric-delegation.mjs": "fab1efdc1a9a0a9a00768905dded538fe185ca1b63c115dc4273717efc8e81f6",
|
|
3261
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
3262
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
3263
|
+
"fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
|
|
3264
|
+
"fabric-package.mjs": "13913ea6d12056c3a31b8222b6c4aab8395941fe519913692e1a06d8672e1c88",
|
|
3265
|
+
"fabric-protocols.mjs": "acd32d9d05cf1a0319e84ad77cede479ef9b6337011e2cf7726e0e8aa590a9e0",
|
|
3266
|
+
"fabric-actions.mjs": "66f9ca7d1da31c89eeedffe7b78ff2230361d375d44c3aa90d9c60b66dfe5cbe",
|
|
3267
|
+
"fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
|
|
3268
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
3269
|
+
"fabric-usage.mjs": "1c4d18004639409624ac3516a02f2b60bbf55abdb612e9a96c37e83666eb87a7",
|
|
3270
|
+
"fabric-backups.mjs": "cfd8c9085e3d597a783099c2bd2ffe2f3faa0daaadab46dedd30523894cfeb06",
|
|
3271
|
+
"fabric-descriptor.mjs": "c1ccaa9dff5edf90b82d6d77e2e5189a5d0f677fd48cc0aed3cccb83ad2a1f12",
|
|
3272
|
+
"fabric-auth.mjs": "782c2aa732f8320f604194660117640a7ea145e12b8155c04e88cef7c516a5b3",
|
|
3273
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
3274
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
3275
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
3276
|
+
"fabric-service.mjs": "6aa673657427211b491a9b63f94b9847a7e6aa3ee1b7353e1af11f46469803a3",
|
|
3277
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
3278
|
+
"fabric-interop-rules.mjs": "fc8f3044afe209a1b23ddb3bc9b3993f4831913fa66bfd6e7855f1be80428e43",
|
|
3279
|
+
"fabric-interop.mjs": "8f1ca418112d7129402783376bb9cbc9d2607f2aceec2a6796e703591a88f535",
|
|
3280
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
3281
|
+
"fabric-board-shapes.mjs": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7",
|
|
3282
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
3283
|
+
"fabric-board-session.mjs": "26c9b0b2818a4cedc5248b08ea6732e2ee4ee81e31f6fee2b572a019db813c93",
|
|
3284
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
3285
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
3286
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
3287
|
+
"fabric-openrouter.mjs": "ab6c4c7251d563980d895061ee19976bde2f364c21b6354efdd9a9027b1ea139",
|
|
3288
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
3289
|
+
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
3182
3290
|
}
|
|
3183
3291
|
},
|
|
3184
3292
|
"data": {
|