@passioncode-ai/fabric-agent-adapter 0.39.1 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +9 -3
  3. package/package.json +1 -1
  4. package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
  5. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +1 -1
  6. package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +15 -4
  7. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md +64 -0
  8. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/config.example.json +15 -0
  9. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/knowledge.example.json +13 -0
  10. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/support_agent.py +264 -0
  11. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/connectors.md +93 -0
  12. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/estate-record.md +3 -2
  13. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +128 -0
  14. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/usage.md +2 -0
  15. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +10 -183
  16. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_rules.py +204 -0
  17. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-auth.mjs +286 -0
  18. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs +327 -0
  19. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-base.mjs +47 -0
  20. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-fixture.mjs +79 -0
  21. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-session.mjs +840 -0
  22. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-shapes.mjs +340 -0
  23. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board.mjs +42 -1237
  24. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-ceremonies.mjs +1 -16
  25. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-crypto.mjs +41 -0
  26. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +13 -45
  27. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +387 -0
  28. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs +8 -67
  29. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-events.mjs +52 -0
  30. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs +231 -0
  31. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs +2 -2
  32. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-jsvalue.mjs +67 -0
  33. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-lock.mjs +202 -0
  34. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-logs.mjs +136 -0
  35. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-openrouter.mjs +335 -0
  36. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs +2 -12
  37. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-paths.mjs +69 -0
  38. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-platform.mjs +164 -0
  39. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-profiles.mjs +1 -32
  40. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +122 -0
  41. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +177 -2541
  42. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-share.mjs +1 -8
  43. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +400 -0
  44. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-time.mjs +46 -0
  45. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-usage.mjs +458 -0
  46. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_auth.py +402 -0
  47. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py +399 -0
  48. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_base.py +78 -0
  49. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board.py +64 -1398
  50. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_fixture.py +116 -0
  51. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_session.py +902 -0
  52. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_shapes.py +457 -0
  53. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_ceremonies.py +36 -38
  54. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_crypto.py +289 -0
  55. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +15 -180
  56. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +586 -0
  57. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate.py +39 -400
  58. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_events.py +137 -0
  59. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_http.py +402 -0
  60. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +1 -6
  61. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_jsvalue.py +310 -0
  62. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_kit.py +243 -0
  63. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_lock.py +308 -0
  64. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_logs.py +202 -0
  65. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_openrouter.py +431 -0
  66. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package.py +21 -43
  67. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_paths.py +102 -0
  68. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_platform.py +338 -0
  69. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_profiles.py +31 -38
  70. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +173 -0
  71. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +298 -3450
  72. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_share.py +8 -8
  73. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +412 -0
  74. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_time.py +120 -0
  75. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_usage.py +697 -0
  76. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +1526 -0
  77. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +1 -1
  78. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/models-and-providers.md +3 -0
  79. package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
  80. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session.py +116 -1392
  81. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_cli.py +270 -0
  82. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +508 -0
  83. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_hosts.py +265 -0
  84. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mail.py +155 -0
  85. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mcp.py +335 -0
  86. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/host_hooks.py +1 -0
@@ -31,6 +31,21 @@ from typing import Any, Callable, Dict, List, Mapping, Optional, Tuple
31
31
  import urllib.error
32
32
  import urllib.parse
33
33
  import urllib.request
34
+ import sys as _sys # noqa: E402
35
+ from pathlib import Path as _Path # noqa: E402
36
+ if str(_Path(__file__).resolve().parent) not in _sys.path: # the kit loads from any working directory (FAA-65)
37
+ _sys.path.insert(0, str(_Path(__file__).resolve().parent))
38
+ from fabric_crypto import ( # noqa: E402 - the core (FAA-65)
39
+ SMALL_ORDER_ENCODINGS,
40
+ _ED_P as _P,
41
+ _ed_decode_point as _decode_point,
42
+ b64url_decode as _b64decode,
43
+ ed25519_verify,
44
+ is_small_order_key,
45
+ )
46
+ from fabric_jsvalue import ( # noqa: E402 - the core (FAA-65)
47
+ jcs,
48
+ )
34
49
 
35
50
  REFUSAL_CODES = (
36
51
  "unauthenticated", "token-expired", "wrong-audience", "scope-not-granted", "effect-above-ceiling", "no-grant",
@@ -85,24 +100,9 @@ _URI = re.compile(r"^[A-Za-z][A-Za-z0-9+.-]*:\S+$")
85
100
  _JTI = re.compile(r"^[A-Za-z0-9._~-]{16,128}$")
86
101
  _SCOPE = re.compile(r"^[a-z][a-z0-9._-]{1,127}( [a-z][a-z0-9._-]{1,127})*$")
87
102
  _SPEND_WINDOWS = ("total", "task", "project", "day", "week", "month")
88
- # The small-order points of edwards25519 and their non-canonical encodings, sign bit cleared (the contract's
89
- # src/ed25519.ts; libsodium's has_small_order list).
90
- SMALL_ORDER_ENCODINGS = (
91
- "0000000000000000000000000000000000000000000000000000000000000000", "0100000000000000000000000000000000000000000000000000000000000000",
92
- "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a",
93
- "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
94
- "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
95
- )
96
103
  _MISSING = object()
97
104
 
98
105
 
99
- def is_small_order_key(raw: bytes) -> bool:
100
- """Whether a 32-byte Ed25519 public key is a point of small order, in any encoding (CT-29)."""
101
- if len(raw) != 32:
102
- return True
103
- return (raw[:31] + bytes([raw[31] & 0x7F])).hex() in SMALL_ORDER_ENCODINGS
104
-
105
-
106
106
  def _full(pattern: "re.Pattern[str]", value: Any) -> bool:
107
107
  return isinstance(value, str) and pattern.fullmatch(value) is not None
108
108
 
@@ -128,90 +128,9 @@ def _is_time(value: Any) -> bool:
128
128
 
129
129
  # --- Ed25519 (RFC 8032 §5.1) ----------------------------------------------------------------------------
130
130
 
131
- _P = 2 ** 255 - 19
132
- _L = 2 ** 252 + 27742317777372353535851937790883648493
133
- _D = (-121665 * pow(121666, _P - 2, _P)) % _P
134
- _SQRT_M1 = pow(2, (_P - 1) // 4, _P)
135
-
136
-
137
- def _add(a: Tuple[int, int, int, int], b: Tuple[int, int, int, int]) -> Tuple[int, int, int, int]:
138
- x1, y1, z1, t1 = a
139
- x2, y2, z2, t2 = b
140
- aa = (y1 - x1) * (y2 - x2) % _P
141
- bb = (y1 + x1) * (y2 + x2) % _P
142
- cc = 2 * t1 * t2 * _D % _P
143
- dd = 2 * z1 * z2 % _P
144
- e, f, g, h = bb - aa, dd - cc, dd + cc, bb + aa
145
- return (e * f % _P, g * h % _P, f * g % _P, e * h % _P)
146
-
147
-
148
- def _mul(scalar: int, point: Tuple[int, int, int, int]) -> Tuple[int, int, int, int]:
149
- result = (0, 1, 1, 0)
150
- while scalar:
151
- if scalar & 1:
152
- result = _add(result, point)
153
- point = _add(point, point)
154
- scalar >>= 1
155
- return result
156
-
157
-
158
- def _decode_point(data: bytes) -> Optional[Tuple[int, int, int, int]]:
159
- if len(data) != 32:
160
- return None
161
- y = int.from_bytes(data, "little")
162
- sign = y >> 255
163
- y &= (1 << 255) - 1
164
- if y >= _P:
165
- return None
166
- x2 = (y * y - 1) * pow(_D * y * y + 1, _P - 2, _P) % _P
167
- if x2 == 0:
168
- if sign:
169
- return None
170
- return (0, y, 1, 0)
171
- x = pow(x2, (_P + 3) // 8, _P)
172
- if (x * x - x2) % _P:
173
- x = x * _SQRT_M1 % _P
174
- if (x * x - x2) % _P:
175
- return None
176
- if x & 1 != sign:
177
- x = _P - x
178
- return (x, y, 1, x * y % _P)
179
-
180
-
181
- def _encode_point(point: Tuple[int, int, int, int]) -> bytes:
182
- x, y, z, _ = point
183
- zi = pow(z, _P - 2, _P)
184
- x, y = x * zi % _P, y * zi % _P
185
- return (y | ((x & 1) << 255)).to_bytes(32, "little")
186
-
187
-
188
- _G = _decode_point(bytes.fromhex("5866666666666666666666666666666666666666666666666666666666666666"))
189
- _IDENTITY = (1).to_bytes(32, "little")
190
-
191
-
192
- def ed25519_verify(public_key: bytes, message: bytes, signature: bytes) -> bool:
193
- """RFC 8032 §5.1.7, cofactorless: [S]B == R + [k]A, compared by R's encoding. False, never an exception."""
194
- if len(public_key) != 32 or len(signature) != 64:
195
- return False
196
- s = int.from_bytes(signature[32:], "little")
197
- if s >= _L:
198
- return False
199
- a = _decode_point(public_key)
200
- if a is None or _encode_point(_mul(8, a)) == _IDENTITY:
201
- return False # a small-order key would accept R = [S]B for a quarter or more of all messages; OpenSSL refuses it
202
- k = int.from_bytes(hashlib.sha512(signature[:32] + public_key + message).digest(), "little") % _L
203
- neg_a = ((-a[0]) % _P, a[1], a[2], (-a[3]) % _P)
204
- return secrets.compare_digest(_encode_point(_add(_mul(s, _G), _mul(k, neg_a))), signature[:32])
205
-
206
131
 
207
132
  # --- the compact document ------------------------------------------------------------------------------
208
133
 
209
- def _b64decode(segment: str) -> bytes:
210
- """Base64url without padding, as Node reads it: a dangling sixth bit group is ignored."""
211
- if len(segment) % 4 == 1:
212
- segment = segment[:-1]
213
- return base64.urlsafe_b64decode(segment + "=" * (-len(segment) % 4))
214
-
215
134
 
216
135
  class _Duplicate(ValueError):
217
136
  pass
@@ -681,90 +600,6 @@ def read_delegation_token(headers: Any) -> Optional[Dict[str, str]]:
681
600
 
682
601
  # --- RFC 8785 canonical JSON --------------------------------------------------------------------------------
683
602
 
684
- def _number(value: float) -> str:
685
- """ECMAScript Number::toString, which RFC 8785 §3.2.2.3 prescribes."""
686
- if value == 0:
687
- return "0"
688
- if value < 0:
689
- return "-" + _number(-value)
690
- digits, exponent = _shortest(value)
691
- k, n = len(digits), len(digits) + exponent
692
- if k <= n <= 21:
693
- return digits + "0" * (n - k)
694
- if 0 < n <= 21:
695
- return digits[:n] + "." + digits[n:]
696
- if -6 < n <= 0:
697
- return "0." + "0" * (-n) + digits
698
- e = n - 1
699
- mantissa = digits if k == 1 else digits[0] + "." + digits[1:]
700
- return "%se%s%d" % (mantissa, "+" if e >= 0 else "-", abs(e))
701
-
702
-
703
- def _shortest(value: float) -> Tuple[str, int]:
704
- """The shortest round-trip digits of a positive finite double (Python's repr is shortest round-trip)."""
705
- text = repr(value)
706
- mantissa, _, exp = text.partition("e")
707
- whole, _, frac = mantissa.partition(".")
708
- digits = (whole + frac).lstrip("0")
709
- exponent = (int(exp) if exp else 0) - len(frac)
710
- if not digits:
711
- return "0", 0
712
- stripped = digits.rstrip("0")
713
- exponent += len(digits) - len(stripped)
714
- return stripped, exponent
715
-
716
-
717
- _ESCAPES = {'"': '\\"', "\\": "\\\\", "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", "\t": "\\t"}
718
-
719
-
720
- def _string(value: str) -> str:
721
- out = ['"']
722
- for ch in value:
723
- code = ord(ch)
724
- if 0xD800 <= code <= 0xDFFF:
725
- raise TypeError("a lone surrogate has no canonical form")
726
- if ch in _ESCAPES:
727
- out.append(_ESCAPES[ch])
728
- elif code < 0x20:
729
- out.append("\\u%04x" % code)
730
- else:
731
- out.append(ch)
732
- out.append('"')
733
- return "".join(out)
734
-
735
-
736
- def jcs(value: Any) -> str:
737
- """RFC 8785: members sorted by UTF-16 code units, numbers in ECMAScript form, strings as JSON.stringify
738
- escapes them. Refuses what has no canonical form: a non-finite number, a lone surrogate, a non-JSON value.
739
- A JSON number is a double: an integer beyond 2**53 is written as JavaScript would write it."""
740
- if value is None:
741
- return "null"
742
- if value is True:
743
- return "true"
744
- if value is False:
745
- return "false"
746
- if isinstance(value, int):
747
- if abs(value) < 2 ** 53:
748
- return str(value)
749
- try:
750
- return _number(float(value))
751
- except OverflowError:
752
- raise TypeError("a number beyond a double has no canonical form") from None
753
- if isinstance(value, float):
754
- if not math.isfinite(value):
755
- raise TypeError("a non-finite number has no canonical form")
756
- return _number(value)
757
- if isinstance(value, str):
758
- return _string(value)
759
- if isinstance(value, list):
760
- return "[" + ",".join(jcs(item) for item in value) + "]"
761
- if isinstance(value, dict):
762
- if not all(isinstance(key, str) for key in value):
763
- raise TypeError("only string member names have a canonical form")
764
- keys = sorted(value, key=lambda key: key.encode("utf-16-be", "surrogatepass"))
765
- return "{" + ",".join(_string(key) + ":" + jcs(value[key]) for key in keys) + "}"
766
- raise TypeError("%s has no canonical form" % type(value).__name__)
767
-
768
603
 
769
604
  def action_digest(action: Any) -> str:
770
605
  """The digest an approval binds: sha256: and the hex SHA-256 of the action's RFC 8785 form."""