@aalis/core 0.1.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 (217) hide show
  1. package/README.md +21 -0
  2. package/dist/app.d.ts +166 -0
  3. package/dist/app.d.ts.map +1 -0
  4. package/dist/app.js +348 -0
  5. package/dist/app.js.map +1 -0
  6. package/dist/config.d.ts +174 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +377 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/constants.d.ts +31 -0
  11. package/dist/constants.d.ts.map +1 -0
  12. package/dist/constants.js +36 -0
  13. package/dist/constants.js.map +1 -0
  14. package/dist/context.d.ts +328 -0
  15. package/dist/context.d.ts.map +1 -0
  16. package/dist/context.js +521 -0
  17. package/dist/context.js.map +1 -0
  18. package/dist/disposable-chain.d.ts +31 -0
  19. package/dist/disposable-chain.d.ts.map +1 -0
  20. package/dist/disposable-chain.js +66 -0
  21. package/dist/disposable-chain.js.map +1 -0
  22. package/dist/events.d.ts +64 -0
  23. package/dist/events.d.ts.map +1 -0
  24. package/dist/events.js +145 -0
  25. package/dist/events.js.map +1 -0
  26. package/dist/hooks.d.ts +49 -0
  27. package/dist/hooks.d.ts.map +1 -0
  28. package/dist/hooks.js +102 -0
  29. package/dist/hooks.js.map +1 -0
  30. package/dist/i18n.d.ts +6 -0
  31. package/dist/i18n.d.ts.map +1 -0
  32. package/dist/i18n.js +26 -0
  33. package/dist/i18n.js.map +1 -0
  34. package/dist/identity.d.ts +26 -0
  35. package/dist/identity.d.ts.map +1 -0
  36. package/dist/identity.js +36 -0
  37. package/dist/identity.js.map +1 -0
  38. package/dist/index.d.ts +17 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +29 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/init.d.ts +20 -0
  43. package/dist/init.d.ts.map +1 -0
  44. package/dist/init.js +455 -0
  45. package/dist/init.js.map +1 -0
  46. package/dist/llm-router.d.ts.map +1 -0
  47. package/dist/llm-router.js +123 -0
  48. package/dist/llm-router.js.map +1 -0
  49. package/dist/logger.d.ts +76 -0
  50. package/dist/logger.d.ts.map +1 -0
  51. package/dist/logger.js +187 -0
  52. package/dist/logger.js.map +1 -0
  53. package/dist/marketplace-bootstrap.d.ts +54 -0
  54. package/dist/marketplace-bootstrap.d.ts.map +1 -0
  55. package/dist/marketplace-bootstrap.js +132 -0
  56. package/dist/marketplace-bootstrap.js.map +1 -0
  57. package/dist/mixin-registry.d.ts +34 -0
  58. package/dist/mixin-registry.d.ts.map +1 -0
  59. package/dist/mixin-registry.js +60 -0
  60. package/dist/mixin-registry.js.map +1 -0
  61. package/dist/model-ref.d.ts +22 -0
  62. package/dist/model-ref.d.ts.map +1 -0
  63. package/dist/model-ref.js +46 -0
  64. package/dist/model-ref.js.map +1 -0
  65. package/dist/pending-buffer.d.ts +46 -0
  66. package/dist/pending-buffer.d.ts.map +1 -0
  67. package/dist/pending-buffer.js +131 -0
  68. package/dist/pending-buffer.js.map +1 -0
  69. package/dist/platform-registry.d.ts +40 -0
  70. package/dist/platform-registry.d.ts.map +1 -0
  71. package/dist/platform-registry.js +64 -0
  72. package/dist/platform-registry.js.map +1 -0
  73. package/dist/plugin-activation.d.ts +43 -0
  74. package/dist/plugin-activation.d.ts.map +1 -0
  75. package/dist/plugin-activation.js +172 -0
  76. package/dist/plugin-activation.js.map +1 -0
  77. package/dist/plugin-topology.d.ts +40 -0
  78. package/dist/plugin-topology.d.ts.map +1 -0
  79. package/dist/plugin-topology.js +126 -0
  80. package/dist/plugin-topology.js.map +1 -0
  81. package/dist/plugin.d.ts +184 -0
  82. package/dist/plugin.d.ts.map +1 -0
  83. package/dist/plugin.js +549 -0
  84. package/dist/plugin.js.map +1 -0
  85. package/dist/providers.d.ts +85 -0
  86. package/dist/providers.d.ts.map +1 -0
  87. package/dist/providers.js +2 -0
  88. package/dist/providers.js.map +1 -0
  89. package/dist/semver-mini.d.ts +20 -0
  90. package/dist/semver-mini.d.ts.map +1 -0
  91. package/dist/semver-mini.js +94 -0
  92. package/dist/semver-mini.js.map +1 -0
  93. package/dist/service-helpers.d.ts +34 -0
  94. package/dist/service-helpers.d.ts.map +1 -0
  95. package/dist/service-helpers.js +68 -0
  96. package/dist/service-helpers.js.map +1 -0
  97. package/dist/service.d.ts +145 -0
  98. package/dist/service.d.ts.map +1 -0
  99. package/dist/service.js +279 -0
  100. package/dist/service.js.map +1 -0
  101. package/dist/types/agent.d.ts +51 -0
  102. package/dist/types/agent.d.ts.map +1 -0
  103. package/dist/types/agent.js +3 -0
  104. package/dist/types/agent.js.map +1 -0
  105. package/dist/types/app.d.ts +74 -0
  106. package/dist/types/app.d.ts.map +1 -0
  107. package/dist/types/app.js +3 -0
  108. package/dist/types/app.js.map +1 -0
  109. package/dist/types/archive.d.ts +59 -0
  110. package/dist/types/archive.d.ts.map +1 -0
  111. package/dist/types/archive.js +16 -0
  112. package/dist/types/archive.js.map +1 -0
  113. package/dist/types/authority.d.ts +63 -0
  114. package/dist/types/authority.d.ts.map +1 -0
  115. package/dist/types/authority.js +3 -0
  116. package/dist/types/authority.js.map +1 -0
  117. package/dist/types/capabilities.d.ts +53 -0
  118. package/dist/types/capabilities.d.ts.map +1 -0
  119. package/dist/types/capabilities.js +87 -0
  120. package/dist/types/capabilities.js.map +1 -0
  121. package/dist/types/cli.d.ts +14 -0
  122. package/dist/types/cli.d.ts.map +1 -0
  123. package/dist/types/cli.js +3 -0
  124. package/dist/types/cli.js.map +1 -0
  125. package/dist/types/commands.d.ts +98 -0
  126. package/dist/types/commands.d.ts.map +1 -0
  127. package/dist/types/commands.js +3 -0
  128. package/dist/types/commands.js.map +1 -0
  129. package/dist/types/core.d.ts +117 -0
  130. package/dist/types/core.d.ts.map +1 -0
  131. package/dist/types/core.js +6 -0
  132. package/dist/types/core.js.map +1 -0
  133. package/dist/types/disposable-service.d.ts +31 -0
  134. package/dist/types/disposable-service.d.ts.map +1 -0
  135. package/dist/types/disposable-service.js +3 -0
  136. package/dist/types/disposable-service.js.map +1 -0
  137. package/dist/types/embedding.d.ts +7 -0
  138. package/dist/types/embedding.d.ts.map +1 -0
  139. package/dist/types/embedding.js +3 -0
  140. package/dist/types/embedding.js.map +1 -0
  141. package/dist/types/flow-control.d.ts +51 -0
  142. package/dist/types/flow-control.d.ts.map +1 -0
  143. package/dist/types/flow-control.js +12 -0
  144. package/dist/types/flow-control.js.map +1 -0
  145. package/dist/types/gateway.d.ts +24 -0
  146. package/dist/types/gateway.d.ts.map +1 -0
  147. package/dist/types/gateway.js +15 -0
  148. package/dist/types/gateway.js.map +1 -0
  149. package/dist/types/hooks.d.ts +3 -0
  150. package/dist/types/hooks.d.ts.map +1 -0
  151. package/dist/types/hooks.js +18 -0
  152. package/dist/types/hooks.js.map +1 -0
  153. package/dist/types/image-recognition.d.ts +123 -0
  154. package/dist/types/image-recognition.d.ts.map +1 -0
  155. package/dist/types/image-recognition.js +31 -0
  156. package/dist/types/image-recognition.js.map +1 -0
  157. package/dist/types/index.d.ts +8 -0
  158. package/dist/types/index.d.ts.map +1 -0
  159. package/dist/types/index.js +17 -0
  160. package/dist/types/index.js.map +1 -0
  161. package/dist/types/llm.d.ts +146 -0
  162. package/dist/types/llm.d.ts.map +1 -0
  163. package/dist/types/llm.js +27 -0
  164. package/dist/types/llm.js.map +1 -0
  165. package/dist/types/memory.d.ts +62 -0
  166. package/dist/types/memory.d.ts.map +1 -0
  167. package/dist/types/memory.js +22 -0
  168. package/dist/types/memory.js.map +1 -0
  169. package/dist/types/persona.d.ts +45 -0
  170. package/dist/types/persona.d.ts.map +1 -0
  171. package/dist/types/persona.js +3 -0
  172. package/dist/types/persona.js.map +1 -0
  173. package/dist/types/platform.d.ts +126 -0
  174. package/dist/types/platform.d.ts.map +1 -0
  175. package/dist/types/platform.js +5 -0
  176. package/dist/types/platform.js.map +1 -0
  177. package/dist/types/plugin.d.ts +84 -0
  178. package/dist/types/plugin.d.ts.map +1 -0
  179. package/dist/types/plugin.js +24 -0
  180. package/dist/types/plugin.js.map +1 -0
  181. package/dist/types/service.d.ts +43 -0
  182. package/dist/types/service.d.ts.map +1 -0
  183. package/dist/types/service.js +38 -0
  184. package/dist/types/service.js.map +1 -0
  185. package/dist/types/services.d.ts +17 -0
  186. package/dist/types/services.d.ts.map +1 -0
  187. package/dist/types/services.js +41 -0
  188. package/dist/types/services.js.map +1 -0
  189. package/dist/types/session.d.ts +153 -0
  190. package/dist/types/session.d.ts.map +1 -0
  191. package/dist/types/session.js +19 -0
  192. package/dist/types/session.js.map +1 -0
  193. package/dist/types/storage.d.ts +100 -0
  194. package/dist/types/storage.d.ts.map +1 -0
  195. package/dist/types/storage.js +29 -0
  196. package/dist/types/storage.js.map +1 -0
  197. package/dist/types/tools.d.ts +39 -0
  198. package/dist/types/tools.d.ts.map +1 -0
  199. package/dist/types/tools.js +3 -0
  200. package/dist/types/tools.js.map +1 -0
  201. package/dist/types/trigger-policy.d.ts +16 -0
  202. package/dist/types/trigger-policy.d.ts.map +1 -0
  203. package/dist/types/trigger-policy.js +6 -0
  204. package/dist/types/trigger-policy.js.map +1 -0
  205. package/dist/types/vectorstore.d.ts +23 -0
  206. package/dist/types/vectorstore.d.ts.map +1 -0
  207. package/dist/types/vectorstore.js +3 -0
  208. package/dist/types/vectorstore.js.map +1 -0
  209. package/dist/types/web-search.d.ts +88 -0
  210. package/dist/types/web-search.d.ts.map +1 -0
  211. package/dist/types/web-search.js +23 -0
  212. package/dist/types/web-search.js.map +1 -0
  213. package/dist/types/webui.d.ts +137 -0
  214. package/dist/types/webui.d.ts.map +1 -0
  215. package/dist/types/webui.js +3 -0
  216. package/dist/types/webui.js.map +1 -0
  217. package/package.json +22 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 轻量级 semver range 校验
3
+ *
4
+ * 仅支持 Aalis 插件市场常用的 range 形态,足够用于 manifest.engines.aalis 校验:
5
+ * - 精确:`1.2.3`
6
+ * - 比较器:`>=1.2.3` / `>1.2.3` / `<=1.2.3` / `<1.2.3` / `=1.2.3`
7
+ * - caret:`^1.2.3`(允许 1.x.x,不允许 2.0.0)
8
+ * - tilde:`~1.2.3`(允许 1.2.x,不允许 1.3.0)
9
+ * - 多个比较器以空格连接,需全部满足:`>=1.2.0 <2.0.0`
10
+ * - `*` / 空字符串:任意版本
11
+ *
12
+ * 不支持:`||` 或运算、prerelease 标签的精细比较(统一忽略 prerelease)。
13
+ * 这些限制对 manifest 校验场景是可接受的。
14
+ */
15
+ /**
16
+ * 判断 version 是否落在 range 范围内。
17
+ * range 中的多个比较器以空白分隔,需全部满足(AND 关系)。
18
+ */
19
+ export declare function satisfies(version: string, range: string | undefined): boolean;
20
+ //# sourceMappingURL=semver-mini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver-mini.d.ts","sourceRoot":"","sources":["../src/semver-mini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA2DH;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAU7E"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * 轻量级 semver range 校验
3
+ *
4
+ * 仅支持 Aalis 插件市场常用的 range 形态,足够用于 manifest.engines.aalis 校验:
5
+ * - 精确:`1.2.3`
6
+ * - 比较器:`>=1.2.3` / `>1.2.3` / `<=1.2.3` / `<1.2.3` / `=1.2.3`
7
+ * - caret:`^1.2.3`(允许 1.x.x,不允许 2.0.0)
8
+ * - tilde:`~1.2.3`(允许 1.2.x,不允许 1.3.0)
9
+ * - 多个比较器以空格连接,需全部满足:`>=1.2.0 <2.0.0`
10
+ * - `*` / 空字符串:任意版本
11
+ *
12
+ * 不支持:`||` 或运算、prerelease 标签的精细比较(统一忽略 prerelease)。
13
+ * 这些限制对 manifest 校验场景是可接受的。
14
+ */
15
+ /** 解析 `major.minor.patch[-prerelease]` 为 [maj, min, pat],prerelease 忽略。 */
16
+ function parseVersion(v) {
17
+ const trimmed = v.trim().replace(/^v/, '');
18
+ const m = trimmed.match(/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/);
19
+ if (!m)
20
+ return null;
21
+ return [Number(m[1]), Number(m[2]), Number(m[3])];
22
+ }
23
+ /** 比较两个版本:返回负数 / 0 / 正数。 */
24
+ function cmp(a, b) {
25
+ for (let i = 0; i < 3; i++) {
26
+ if (a[i] !== b[i])
27
+ return a[i] - b[i];
28
+ }
29
+ return 0;
30
+ }
31
+ /** 判断单个比较器是否满足版本。 */
32
+ function checkComparator(version, comp) {
33
+ comp = comp.trim();
34
+ if (!comp || comp === '*' || comp === 'x')
35
+ return true;
36
+ // caret ^x.y.z: >=x.y.z <(x+1).0.0(x>0),或 >=0.y.z <0.(y+1).0(x=0,y>0),或 >=0.0.z <0.0.(z+1)(x=y=0)
37
+ if (comp.startsWith('^')) {
38
+ const base = parseVersion(comp.slice(1));
39
+ if (!base)
40
+ return false;
41
+ if (cmp(version, base) < 0)
42
+ return false;
43
+ const [maj, min] = base;
44
+ if (maj > 0)
45
+ return version[0] === maj;
46
+ if (min > 0)
47
+ return version[0] === 0 && version[1] === min;
48
+ return version[0] === 0 && version[1] === 0 && version[2] === base[2];
49
+ }
50
+ // tilde ~x.y.z: >=x.y.z <x.(y+1).0
51
+ if (comp.startsWith('~')) {
52
+ const base = parseVersion(comp.slice(1));
53
+ if (!base)
54
+ return false;
55
+ if (cmp(version, base) < 0)
56
+ return false;
57
+ return version[0] === base[0] && version[1] === base[1];
58
+ }
59
+ // 比较运算符
60
+ const opMatch = comp.match(/^(>=|<=|>|<|=)?\s*(.+)$/);
61
+ if (!opMatch)
62
+ return false;
63
+ const op = opMatch[1] || '=';
64
+ const target = parseVersion(opMatch[2]);
65
+ if (!target)
66
+ return false;
67
+ const c = cmp(version, target);
68
+ switch (op) {
69
+ case '>=': return c >= 0;
70
+ case '<=': return c <= 0;
71
+ case '>': return c > 0;
72
+ case '<': return c < 0;
73
+ case '=': return c === 0;
74
+ default: return false;
75
+ }
76
+ }
77
+ /**
78
+ * 判断 version 是否落在 range 范围内。
79
+ * range 中的多个比较器以空白分隔,需全部满足(AND 关系)。
80
+ */
81
+ export function satisfies(version, range) {
82
+ if (!range || !range.trim())
83
+ return true;
84
+ const v = parseVersion(version);
85
+ if (!v)
86
+ return false;
87
+ // 简化:不支持 `||`,命中任意 `||` 直接放行(避免误拒),并发出隐式 warning 由调用方处理
88
+ if (range.includes('||')) {
89
+ return range.split('||').some(part => satisfies(version, part));
90
+ }
91
+ const comparators = range.split(/\s+/).filter(Boolean);
92
+ return comparators.every(c => checkComparator(v, c));
93
+ }
94
+ //# sourceMappingURL=semver-mini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver-mini.js","sourceRoot":"","sources":["../src/semver-mini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { EventBus } from './events.js';
2
+ import type { Logger } from './logger.js';
3
+ import type { ServiceContainer } from './service.js';
4
+ /**
5
+ * provide() 的 dev-mode 校验集合:
6
+ * 1. entryId 必须以 ctxId 为前缀(否则 plugin 卸载时清理不到)
7
+ * 2. 声明的 capabilities 必须能在 instance 上探测到对应方法
8
+ * 3. 同一上下文重复 provide 同一服务名静默失效(容器路由按 contextId)
9
+ * 4. priority 应使用 ServicePriority enum 而非裸数字
10
+ *
11
+ * 参数 explicitEntryId 区分"调用方有意覆盖 entryId"vs"使用 ctxId 默认值"——
12
+ * 前者才触发 entryId 前缀检查与抑制重复 provide warn(有意拆粒度的语义)。
13
+ *
14
+ * 失败模式:
15
+ * - capabilities 不匹配 → throw(写错的代码不该跑起来)
16
+ * - 其它 → warn(提示但不阻断)
17
+ */
18
+ export declare function validateProvide(args: {
19
+ ctxId: string;
20
+ name: string;
21
+ instance: unknown;
22
+ capabilities: readonly string[];
23
+ entryId: string;
24
+ explicitEntryId: boolean;
25
+ priority?: number;
26
+ services: ServiceContainer;
27
+ logger: Logger;
28
+ }): void;
29
+ /**
30
+ * 异步发射 service:registered 事件,捕获并 warn 任何监听器抛错。
31
+ * 抽出为函数主要让 provide() 主体看起来更短。
32
+ */
33
+ export declare function emitServiceRegistered(events: EventBus, logger: Logger, name: string, capabilities: readonly string[]): void;
34
+ //# sourceMappingURL=service-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-helpers.d.ts","sourceRoot":"","sources":["../src/service-helpers.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIrD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAyCP;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,IAAI,CAIN"}
@@ -0,0 +1,68 @@
1
+ // ============================================================
2
+ // service-helpers.ts — Context 的服务子系统辅助
3
+ //
4
+ // 从 context.ts 拆出来的纯函数,消除 Context 类自身对"如何包装/校验服务"的细节
5
+ // 知识,留下 Context 作为编排者:路由参数 → 调 helper → 登记 disposable。
6
+ //
7
+ // 这里不持有任何状态,所有副作用(注册/警告/事件)都通过参数传入的 services/
8
+ // logger/events 反映出去。便于单元测试(mock 即可)。
9
+ // ============================================================
10
+ import { probeCapability } from './types/capabilities.js';
11
+ import { ServicePriority } from './types/service.js';
12
+ /**
13
+ * provide() 的 dev-mode 校验集合:
14
+ * 1. entryId 必须以 ctxId 为前缀(否则 plugin 卸载时清理不到)
15
+ * 2. 声明的 capabilities 必须能在 instance 上探测到对应方法
16
+ * 3. 同一上下文重复 provide 同一服务名静默失效(容器路由按 contextId)
17
+ * 4. priority 应使用 ServicePriority enum 而非裸数字
18
+ *
19
+ * 参数 explicitEntryId 区分"调用方有意覆盖 entryId"vs"使用 ctxId 默认值"——
20
+ * 前者才触发 entryId 前缀检查与抑制重复 provide warn(有意拆粒度的语义)。
21
+ *
22
+ * 失败模式:
23
+ * - capabilities 不匹配 → throw(写错的代码不该跑起来)
24
+ * - 其它 → warn(提示但不阻断)
25
+ */
26
+ export function validateProvide(args) {
27
+ const { ctxId, name, instance, capabilities, entryId, explicitEntryId, priority, services, logger } = args;
28
+ if (explicitEntryId && entryId !== ctxId && !entryId.startsWith(`${ctxId}/`)) {
29
+ logger.warn(`服务 "${name}" 的 entryId "${entryId}" 不以 "${ctxId}/" 为前缀。` +
30
+ `违反约定后 plugin 卸载时可能遗漏清理。` +
31
+ `推荐格式:\`\${ctx.id}/\${子粒度标识}\`。`);
32
+ }
33
+ const failures = [];
34
+ for (const cap of capabilities) {
35
+ const result = probeCapability(name, cap, instance);
36
+ if (typeof result === 'string')
37
+ failures.push(` - [${cap}] ${result}`);
38
+ }
39
+ if (failures.length > 0) {
40
+ throw new Error(`服务 "${name}" 声明的能力与实例实现不符(provide 拒绝注册):\n${failures.join('\n')}`);
41
+ }
42
+ if (!explicitEntryId && services.hasByContext(name, ctxId)) {
43
+ logger.warn(`服务 "${name}" 已被当前上下文 "${ctxId}" provide 过一次。容器允许多 entry,` +
44
+ `但下游按 contextId 路由时仅能命中首个,后续注册将静默失效。` +
45
+ `如需多实例(如多套 API key),请在插件 module 上声明 reusable=true,` +
46
+ `然后在 config 中用 "<name>:<suffix>" 形式注册多份。` +
47
+ `若是有意拆出多个子粒度 entry(如 per-model LLM),请传入 options.entryId。`);
48
+ }
49
+ if (priority !== undefined) {
50
+ const standard = Object.values(ServicePriority);
51
+ if (!standard.includes(priority)) {
52
+ // 裸数字作为细粒度预留滩位是合理设计(如 priority=10 在 Backend 与 Override 之间插入),
53
+ // 不强制使用 enum。但保留 debug 日志,方便排查「谁是默认胜者」问题。
54
+ logger.debug(`服务 "${name}" 使用裸数字 priority=${priority}(非 ServicePriority enum:Backend=0/Override=50/System=200)。` +
55
+ `这是允许的,但插件作者须自行记载该数值含义以便下游推断胜者。`);
56
+ }
57
+ }
58
+ }
59
+ /**
60
+ * 异步发射 service:registered 事件,捕获并 warn 任何监听器抛错。
61
+ * 抽出为函数主要让 provide() 主体看起来更短。
62
+ */
63
+ export function emitServiceRegistered(events, logger, name, capabilities) {
64
+ events.emit('service:registered', name, [...capabilities]).catch(err => {
65
+ logger.warn(`服务注册事件发射失败 [${name}]:`, err);
66
+ });
67
+ }
68
+ //# sourceMappingURL=service-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-helpers.js","sourceRoot":"","sources":["../src/service-helpers.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wCAAwC;AACxC,EAAE;AACF,qDAAqD;AACrD,uDAAuD;AACvD,EAAE;AACF,8CAA8C;AAC9C,sCAAsC;AACtC,+DAA+D;AAK/D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,IAU/B;IACC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE3G,IAAI,eAAe,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QAC7E,MAAM,CAAC,IAAI,CACT,OAAO,IAAI,gBAAgB,OAAO,SAAS,KAAK,SAAS;YACvD,yBAAyB;YACzB,gCAAgC,CACnC,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QACpD,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,kCAAkC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,eAAe,IAAI,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,CAAC,IAAI,CACT,OAAO,IAAI,cAAc,KAAK,4BAA4B;YACxD,qCAAqC;YACrC,mDAAmD;YACnD,yCAAyC;YACzC,yDAAyD,CAC5D,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAa,CAAC;QAC5D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,8DAA8D;YAC9D,0CAA0C;YAC1C,MAAM,CAAC,KAAK,CACV,OAAO,IAAI,oBAAoB,QAAQ,4DAA4D;gBACjG,gCAAgC,CACnC,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAgB,EAChB,MAAc,EACd,IAAY,EACZ,YAA+B;IAE/B,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;QACrE,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,145 @@
1
+ import { type NormalizedDependency, normalizeDependency, type ServiceEntry, ServicePriority, type ServicePriorityValue } from './types/service.js';
2
+ export type { NormalizedDependency, ServiceEntry, ServicePriorityValue };
3
+ export { normalizeDependency, ServicePriority };
4
+ /**
5
+ * 服务容器 —— 支持同名多实现 + 能力匹配
6
+ *
7
+ * 设计要点:
8
+ * - 同一个服务名可以有多个提供者(不同能力集)
9
+ * - 获取服务时可指定所需能力, 容器会匹配满足所有能力的最高优先级提供者
10
+ * - 每个注册都关联 contextId, 以便在插件卸载时批量清理
11
+ */
12
+ export declare class ServiceContainer {
13
+ private entries;
14
+ /** 服务偏好:service name → preferred contextId(preferred 永远胜过 priority) */
15
+ private preferences;
16
+ /**
17
+ * 注册一个服务实例
18
+ *
19
+ * @returns 刚插入的 ServiceEntry,调用方可以该引用调用 {@link unregisterEntry} 精确删除这一条。
20
+ */
21
+ register(name: string, instance: unknown, capabilities?: string[], priority?: number, contextId?: string, label?: string): ServiceEntry;
22
+ /**
23
+ * 按解析顺序返回某服务的所有 entry:
24
+ *
25
+ * 1. 用户偏好的 entry(如有,且仍存在)
26
+ * 2. 其余 entry,按 priority 降序 + 注册顺序
27
+ *
28
+ * 这是 get/getEntries/getAll 的共同基础——保证「偏好 > 优先级 > 注册顺序」语义在所有读路径一致。
29
+ */
30
+ private resolveEntries;
31
+ /**
32
+ * 获取一个满足能力要求的服务实例
33
+ */
34
+ get<T>(name: string, requiredCapabilities?: readonly string[]): T | undefined;
35
+ /**
36
+ * 检查某个服务是否存在(并且满足指定能力)
37
+ */
38
+ has(name: string, requiredCapabilities?: readonly string[]): boolean;
39
+ /**
40
+ * 检查指定 contextId 是否注册了某个服务。
41
+ *
42
+ * "拥有" 语义:同时匹配 `contextId === ownerId` 和 per-entry 拆粒度的
43
+ * `contextId` 以 `ownerId + '/'` 为前缀的子 entry(如 `@aalis/plugin-ollama:main/llama3`)。
44
+ */
45
+ hasByContext(name: string, contextId: string): boolean;
46
+ /**
47
+ * 获取某个服务的所有能力列表(合并所有提供者)
48
+ */
49
+ getCapabilities(name: string): string[];
50
+ /**
51
+ * 按 entry 引用精确删除某个提供者(推荐)
52
+ *
53
+ * 避免 "同一 contextId 多次 register" 场景下按 contextId 删除会命中错误条目的 footgun。
54
+ * @returns 是否成功删除
55
+ */
56
+ unregisterEntry(name: string, entry: ServiceEntry): boolean;
57
+ /**
58
+ * 按 contextId 移除该上下文拥有的所有服务 entry,返回被移除的服务名列表。
59
+ *
60
+ * "拥有" 同 hasByContext:包括 `contextId === id` 和以 `id + '/'` 为前缀的 per-entry 子 entry。
61
+ * 这是插件 unload 时清理多 entry 注册(per-model LLM / per-root storage / …)的路径。
62
+ */
63
+ unregisterByContext(contextId: string): string[];
64
+ /**
65
+ * 列出所有已注册的服务名
66
+ */
67
+ getServiceNames(): string[];
68
+ /**
69
+ * 获取某个服务的所有 entry(给 API 暴露用)
70
+ *
71
+ * 返回顺序遵循「偏好 > 优先级 > 注册顺序」。
72
+ */
73
+ getEntries(name: string): ServiceEntry[];
74
+ /**
75
+ * 获取某个服务的所有实例(带提供者信息)
76
+ *
77
+ * 可选 requiredCapabilities 过滤:只返回满足所有所需能力的提供者。
78
+ * 返回顺序遵循「偏好 > 优先级 > 注册顺序」。
79
+ */
80
+ getAll<T>(name: string, requiredCapabilities?: readonly string[]): Array<{
81
+ instance: T;
82
+ contextId: string;
83
+ capabilities: string[];
84
+ label?: string;
85
+ }>;
86
+ /**
87
+ * 设置某服务的偏好 provider(按 contextId)
88
+ *
89
+ * 语义:偏好 > 优先级 > 注册顺序。即偏好 entry 总会被 `get()` 第一个返回,
90
+ * 哪怕它的 priority 数值低于 router 等其他 entry。
91
+ *
92
+ * @returns true 表示偏好已记录(即使目标 entry 当下尚未注册也会接受——一旦注册即生效)
93
+ * @internal 公开 API 走 `ctx.preferService()`(额外 emit service:preference-changed
94
+ * 触发 whenService 重挂);本方法仅供 Context 内部转发,插件勿直接调用。
95
+ */
96
+ prefer(name: string, contextId: string): boolean;
97
+ /**
98
+ * 清除某服务的偏好(恢复 priority + 注册顺序解析)
99
+ * @internal 公开 API 走 `ctx.unpreferService()`;本方法仅供 Context 内部转发。
100
+ */
101
+ unprefer(name: string): boolean;
102
+ /**
103
+ * 读取某服务当前的偏好 contextId(无偏好返回 undefined)
104
+ * @internal 公开 API 走 `ctx.getPreferredService()`;本方法仅供 Context 内部转发。
105
+ */
106
+ getPreferred(name: string): string | undefined;
107
+ /**
108
+ * 创建作用域子容器
109
+ *
110
+ * 子容器读取时先查本地,miss 则 fallback 到父容器;
111
+ * 写入(register)仅影响子容器自身。
112
+ *
113
+ * 适用于沙盒/会话隔离场景:每个沙盒拥有独立的服务覆盖,
114
+ * 同时继承全局公共服务(如 authority、commands)。
115
+ *
116
+ * @example
117
+ * const scoped = container.createScope();
118
+ * scoped.register('agent', sandboxAgent); // 仅沙盒可见
119
+ * scoped.get('authority'); // fallback 到父容器
120
+ */
121
+ createScope(): ScopedServiceContainer;
122
+ }
123
+ /**
124
+ * 作用域服务容器 —— ServiceContainer 的子容器
125
+ *
126
+ * - get / has / getEntries / getServiceNames: 先查本地,miss 则 fallback 到父容器
127
+ * - register / unregisterEntry: 仅操作本地,不影响父容器
128
+ * - 支持多层嵌套: ScopedServiceContainer.createScope() 返回更深层的子容器
129
+ */
130
+ export declare class ScopedServiceContainer extends ServiceContainer {
131
+ readonly parent: ServiceContainer;
132
+ constructor(parent: ServiceContainer);
133
+ get<T>(name: string, requiredCapabilities?: readonly string[]): T | undefined;
134
+ has(name: string, requiredCapabilities?: readonly string[]): boolean;
135
+ getCapabilities(name: string): string[];
136
+ getServiceNames(): string[];
137
+ getEntries(name: string): ServiceEntry[];
138
+ getAll<T>(name: string, requiredCapabilities?: readonly string[]): Array<{
139
+ instance: T;
140
+ contextId: string;
141
+ capabilities: string[];
142
+ label?: string;
143
+ }>;
144
+ }
145
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,279 @@
1
+ import { normalizeDependency, ServicePriority, } from './types/service.js';
2
+ // 类型与纯辅助 re-export,保留同名旧导入路径
3
+ export { normalizeDependency, ServicePriority };
4
+ /**
5
+ * 服务容器 —— 支持同名多实现 + 能力匹配
6
+ *
7
+ * 设计要点:
8
+ * - 同一个服务名可以有多个提供者(不同能力集)
9
+ * - 获取服务时可指定所需能力, 容器会匹配满足所有能力的最高优先级提供者
10
+ * - 每个注册都关联 contextId, 以便在插件卸载时批量清理
11
+ */
12
+ export class ServiceContainer {
13
+ entries = new Map();
14
+ /** 服务偏好:service name → preferred contextId(preferred 永远胜过 priority) */
15
+ preferences = new Map();
16
+ /**
17
+ * 注册一个服务实例
18
+ *
19
+ * @returns 刚插入的 ServiceEntry,调用方可以该引用调用 {@link unregisterEntry} 精确删除这一条。
20
+ */
21
+ register(name, instance, capabilities = [], priority = 0, contextId = 'root', label) {
22
+ let list = this.entries.get(name);
23
+ if (!list) {
24
+ list = [];
25
+ this.entries.set(name, list);
26
+ }
27
+ const entry = {
28
+ instance,
29
+ capabilities: new Set(capabilities),
30
+ priority,
31
+ contextId,
32
+ label,
33
+ };
34
+ list.push(entry);
35
+ // 按优先级降序排列(稳定排序:同优先级先注册者在前)
36
+ list.sort((a, b) => b.priority - a.priority);
37
+ return entry;
38
+ }
39
+ /**
40
+ * 按解析顺序返回某服务的所有 entry:
41
+ *
42
+ * 1. 用户偏好的 entry(如有,且仍存在)
43
+ * 2. 其余 entry,按 priority 降序 + 注册顺序
44
+ *
45
+ * 这是 get/getEntries/getAll 的共同基础——保证「偏好 > 优先级 > 注册顺序」语义在所有读路径一致。
46
+ */
47
+ resolveEntries(name) {
48
+ const list = this.entries.get(name);
49
+ if (!list || list.length === 0)
50
+ return [];
51
+ const preferredCtxId = this.preferences.get(name);
52
+ if (!preferredCtxId)
53
+ return list;
54
+ const preferred = list.find(e => e.contextId === preferredCtxId);
55
+ if (!preferred)
56
+ return list;
57
+ return [preferred, ...list.filter(e => e !== preferred)];
58
+ }
59
+ /**
60
+ * 获取一个满足能力要求的服务实例
61
+ */
62
+ get(name, requiredCapabilities) {
63
+ const list = this.resolveEntries(name);
64
+ if (list.length === 0)
65
+ return undefined;
66
+ for (const entry of list) {
67
+ if (requiredCapabilities && requiredCapabilities.length > 0) {
68
+ const satisfied = requiredCapabilities.every(c => entry.capabilities.has(c));
69
+ if (!satisfied)
70
+ continue;
71
+ }
72
+ return entry.instance;
73
+ }
74
+ return undefined;
75
+ }
76
+ /**
77
+ * 检查某个服务是否存在(并且满足指定能力)
78
+ */
79
+ has(name, requiredCapabilities) {
80
+ return this.get(name, requiredCapabilities) !== undefined;
81
+ }
82
+ /**
83
+ * 检查指定 contextId 是否注册了某个服务。
84
+ *
85
+ * "拥有" 语义:同时匹配 `contextId === ownerId` 和 per-entry 拆粒度的
86
+ * `contextId` 以 `ownerId + '/'` 为前缀的子 entry(如 `@aalis/plugin-ollama:main/llama3`)。
87
+ */
88
+ hasByContext(name, contextId) {
89
+ const list = this.entries.get(name);
90
+ if (!list)
91
+ return false;
92
+ const prefix = `${contextId}/`;
93
+ return list.some(e => e.contextId === contextId || e.contextId.startsWith(prefix));
94
+ }
95
+ /**
96
+ * 获取某个服务的所有能力列表(合并所有提供者)
97
+ */
98
+ getCapabilities(name) {
99
+ const list = this.entries.get(name);
100
+ if (!list)
101
+ return [];
102
+ const caps = new Set();
103
+ for (const entry of list) {
104
+ for (const c of entry.capabilities)
105
+ caps.add(c);
106
+ }
107
+ return [...caps];
108
+ }
109
+ /**
110
+ * 按 entry 引用精确删除某个提供者(推荐)
111
+ *
112
+ * 避免 "同一 contextId 多次 register" 场景下按 contextId 删除会命中错误条目的 footgun。
113
+ * @returns 是否成功删除
114
+ */
115
+ unregisterEntry(name, entry) {
116
+ const list = this.entries.get(name);
117
+ if (!list)
118
+ return false;
119
+ const idx = list.indexOf(entry);
120
+ if (idx < 0)
121
+ return false;
122
+ list.splice(idx, 1);
123
+ if (list.length === 0)
124
+ this.entries.delete(name);
125
+ return true;
126
+ }
127
+ /**
128
+ * 按 contextId 移除该上下文拥有的所有服务 entry,返回被移除的服务名列表。
129
+ *
130
+ * "拥有" 同 hasByContext:包括 `contextId === id` 和以 `id + '/'` 为前缀的 per-entry 子 entry。
131
+ * 这是插件 unload 时清理多 entry 注册(per-model LLM / per-root storage / …)的路径。
132
+ */
133
+ unregisterByContext(contextId) {
134
+ const removed = [];
135
+ const prefix = `${contextId}/`;
136
+ for (const [name, list] of this.entries) {
137
+ const before = list.length;
138
+ const filtered = list.filter(e => e.contextId !== contextId && !e.contextId.startsWith(prefix));
139
+ if (filtered.length < before) {
140
+ removed.push(name);
141
+ }
142
+ if (filtered.length === 0) {
143
+ this.entries.delete(name);
144
+ }
145
+ else {
146
+ this.entries.set(name, filtered);
147
+ }
148
+ }
149
+ return removed;
150
+ }
151
+ /**
152
+ * 列出所有已注册的服务名
153
+ */
154
+ getServiceNames() {
155
+ return [...this.entries.keys()];
156
+ }
157
+ /**
158
+ * 获取某个服务的所有 entry(给 API 暴露用)
159
+ *
160
+ * 返回顺序遵循「偏好 > 优先级 > 注册顺序」。
161
+ */
162
+ getEntries(name) {
163
+ return this.resolveEntries(name);
164
+ }
165
+ /**
166
+ * 获取某个服务的所有实例(带提供者信息)
167
+ *
168
+ * 可选 requiredCapabilities 过滤:只返回满足所有所需能力的提供者。
169
+ * 返回顺序遵循「偏好 > 优先级 > 注册顺序」。
170
+ */
171
+ getAll(name, requiredCapabilities) {
172
+ const list = this.resolveEntries(name);
173
+ if (list.length === 0)
174
+ return [];
175
+ const result = [];
176
+ for (const entry of list) {
177
+ if (requiredCapabilities && requiredCapabilities.length > 0) {
178
+ const satisfied = requiredCapabilities.every(c => entry.capabilities.has(c));
179
+ if (!satisfied)
180
+ continue;
181
+ }
182
+ result.push({
183
+ instance: entry.instance,
184
+ contextId: entry.contextId,
185
+ capabilities: [...entry.capabilities],
186
+ label: entry.label,
187
+ });
188
+ }
189
+ return result;
190
+ }
191
+ /**
192
+ * 设置某服务的偏好 provider(按 contextId)
193
+ *
194
+ * 语义:偏好 > 优先级 > 注册顺序。即偏好 entry 总会被 `get()` 第一个返回,
195
+ * 哪怕它的 priority 数值低于 router 等其他 entry。
196
+ *
197
+ * @returns true 表示偏好已记录(即使目标 entry 当下尚未注册也会接受——一旦注册即生效)
198
+ * @internal 公开 API 走 `ctx.preferService()`(额外 emit service:preference-changed
199
+ * 触发 whenService 重挂);本方法仅供 Context 内部转发,插件勿直接调用。
200
+ */
201
+ prefer(name, contextId) {
202
+ this.preferences.set(name, contextId);
203
+ return true;
204
+ }
205
+ /**
206
+ * 清除某服务的偏好(恢复 priority + 注册顺序解析)
207
+ * @internal 公开 API 走 `ctx.unpreferService()`;本方法仅供 Context 内部转发。
208
+ */
209
+ unprefer(name) {
210
+ return this.preferences.delete(name);
211
+ }
212
+ /**
213
+ * 读取某服务当前的偏好 contextId(无偏好返回 undefined)
214
+ * @internal 公开 API 走 `ctx.getPreferredService()`;本方法仅供 Context 内部转发。
215
+ */
216
+ getPreferred(name) {
217
+ return this.preferences.get(name);
218
+ }
219
+ /**
220
+ * 创建作用域子容器
221
+ *
222
+ * 子容器读取时先查本地,miss 则 fallback 到父容器;
223
+ * 写入(register)仅影响子容器自身。
224
+ *
225
+ * 适用于沙盒/会话隔离场景:每个沙盒拥有独立的服务覆盖,
226
+ * 同时继承全局公共服务(如 authority、commands)。
227
+ *
228
+ * @example
229
+ * const scoped = container.createScope();
230
+ * scoped.register('agent', sandboxAgent); // 仅沙盒可见
231
+ * scoped.get('authority'); // fallback 到父容器
232
+ */
233
+ createScope() {
234
+ return new ScopedServiceContainer(this);
235
+ }
236
+ }
237
+ /**
238
+ * 作用域服务容器 —— ServiceContainer 的子容器
239
+ *
240
+ * - get / has / getEntries / getServiceNames: 先查本地,miss 则 fallback 到父容器
241
+ * - register / unregisterEntry: 仅操作本地,不影响父容器
242
+ * - 支持多层嵌套: ScopedServiceContainer.createScope() 返回更深层的子容器
243
+ */
244
+ export class ScopedServiceContainer extends ServiceContainer {
245
+ parent;
246
+ constructor(parent) {
247
+ super();
248
+ this.parent = parent;
249
+ }
250
+ get(name, requiredCapabilities) {
251
+ const local = super.get(name, requiredCapabilities);
252
+ if (local !== undefined)
253
+ return local;
254
+ return this.parent.get(name, requiredCapabilities);
255
+ }
256
+ has(name, requiredCapabilities) {
257
+ return super.has(name, requiredCapabilities) || this.parent.has(name, requiredCapabilities);
258
+ }
259
+ getCapabilities(name) {
260
+ const local = super.getCapabilities(name);
261
+ const parent = this.parent.getCapabilities(name);
262
+ return [...new Set([...local, ...parent])];
263
+ }
264
+ getServiceNames() {
265
+ return [...new Set([...super.getServiceNames(), ...this.parent.getServiceNames()])];
266
+ }
267
+ getEntries(name) {
268
+ const local = super.getEntries(name);
269
+ const parent = this.parent.getEntries(name);
270
+ // 本地条目优先(在前),父容器条目在后
271
+ return [...local, ...parent];
272
+ }
273
+ getAll(name, requiredCapabilities) {
274
+ const local = super.getAll(name, requiredCapabilities);
275
+ const parent = this.parent.getAll(name, requiredCapabilities);
276
+ return [...local, ...parent];
277
+ }
278
+ }
279
+ //# sourceMappingURL=service.js.map