@aalis/api-hooks 0.2.0 → 0.4.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.
package/README.md CHANGED
@@ -10,18 +10,13 @@
10
10
 
11
11
  ## 顺序
12
12
 
13
- 链内按登记顺序执行。登记序是每条登记自带的序号,提供者按它排链:以更高优先级换上另一个提供者时,各插件的登记整批重挂,链序不变。提供者重启时,依赖它的插件随之重启并重新登记,链序即重新激活的次序,与冷启动相同。相位内的 handler 应与顺序无关。
13
+ 链内按登记方的位次排:宿主自己登记的最前,插件按实例 id 的码元序,同一个插件登记的几条按登记先后。链序不看登记发生的时刻:插件重启、提供者重启或换人都不改变它。相位内的 handler 应与顺序无关。
14
14
 
15
- 自己实现提供者时,`register` 须按 `order` 升序插入。
15
+ 自己实现提供者时,`register` 须按(`seat`,`order`)插入:先比 `seat` 的码元序,同一 `seat` 按 `order` 升序;交给每个中间件的 `next` 只许调一次,再调须拒绝。
16
16
 
17
17
  ## 运行中换提供者的已知现状
18
18
 
19
- 以更高优先级上线第二个钩子提供者,或在 WebUI 设置「系统」的服务偏好里切换 hooks 时,有两种情形会让截停者暂时缺席:
20
-
21
- - 换人那一刻正在执行的链会跳过已移到新提供者的中间件。被跳过的若是截停者,默认动作照样执行。
22
- - 胜者在容器里同步换人,各插件的登记要逐个重挂到新提供者上。重挂完成前新发起的链,只能看到已经搬过来的中间件。
23
-
24
- 两种情形都只发生在运行中换提供者的那一刻。第一方部署只有 `@aalis/plugin-hooks` 一个提供者,不会遇到。
19
+ 以更高优先级上线第二个钩子提供者,或在 WebUI 设置「系统」的服务偏好里切换 hooks 时,换人那一刻正在执行的链会跳过已移到新提供者的中间件。被跳过的若是截停者,默认动作照样执行。第一方部署只有 `@aalis/plugin-hooks` 一个提供者,不会遇到。
25
20
 
26
21
  ## 安装
27
22
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** 钩子扩展点(空接口;由各 -api 包经 declaration merging 注入「钩子名 → 中间件上下文」) */
2
2
  export interface HookContextMap {
3
3
  }
4
- /** 中间件 next:把控制交给下一个中间件或默认动作 */
4
+ /** 中间件 next:把控制交给下一个中间件或默认动作。一个中间件里只能调一次,再调返回被拒的 Promise */
5
5
  export type MiddlewareNext = () => Promise<void>;
6
6
  /** 中间件:可改 data(引用传递),调 next() 继续,不调即截停(含默认动作) */
7
7
  export type MiddlewareFn<T> = (data: T, next: MiddlewareNext) => Promise<void>;
@@ -16,16 +16,17 @@ export interface RunOptions {
16
16
  */
17
17
  export interface HookRegistry {
18
18
  /**
19
- * 按 order 升序插入该钩子链。order 是门面在登记时分配的登记序(进程内全部 api-hooks 副本共用一个计数器,单调递增),换提供者重挂时原样带过来,
20
- * 提供者据它还原原来的交错次序。contextId 供卡链告警点名。返回退订(幂等,只撤这一条)
19
+ * 按(seat,order)插入该钩子链:先比 seat 的码元序,同一 seat 按 order 升序。seat 是登记方的位次(宿主的根是空串,
20
+ * 插件是它的实例 id),order 是门面在登记时分配的登记序(进程内全部 api-hooks 副本共用一个计数器,单调递增)。
21
+ * 两者在换提供者重挂时原样带过来,次序不看登记发生的时刻。contextId 供卡链告警点名。返回退订(幂等,只撤这一条)
21
22
  */
22
- register(hook: string, fn: MiddlewareFn<unknown>, contextId: string, order: number): () => void;
23
+ register(hook: string, fn: MiddlewareFn<unknown>, contextId: string, order: number, seat: string): () => void;
23
24
  /** 驱动一条钩子链;true = 走到底(含执行了默认动作或本就没有 handler),false = 被截停 */
24
25
  run(hook: string, data: unknown, defaultAction?: () => Promise<void>, opts?: RunOptions): Promise<boolean>;
25
26
  }
26
27
  /** `hooks` 的绑定接口 */
27
28
  export interface Hooks {
28
- /** 注册中间件(洋葱模型,按登记顺序);返回退订,随这次激活撤回 */
29
+ /** 注册中间件(洋葱模型,按登记方的位次,同一登记方按登记先后);返回退订,随这次激活撤回 */
29
30
  middleware<K extends string & keyof HookContextMap>(hook: K, fn: MiddlewareFn<HookContextMap[K]>): () => void;
30
31
  /** 驱动一条钩子链;返回 false 表示被某个中间件截停 */
31
32
  run<K extends string & keyof HookContextMap>(hook: K, data: HookContextMap[K], defaultAction?: () => Promise<void>, opts?: RunOptions): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkBA,iEAAiE;AACjE,MAAM,WAAW,cAAc;CAAG;AAElC,gCAAgC;AAChC,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjD,iDAAiD;AACjD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/E,gBAAgB;AAChB,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAChG,4DAA4D;IAC5D,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5G;AAED,oBAAoB;AACpB,MAAM,WAAW,KAAK;IACpB,qCAAqC;IACrC,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,cAAc,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAC9G,kCAAkC;IAClC,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,cAAc,EACzC,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACnC,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAWD,eAAO,MAAM,KAAK,8DAYhB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,iEAAiE;AACjE,MAAM,WAAW,cAAc;CAAG;AAElC,4DAA4D;AAC5D,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjD,iDAAiD;AACjD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/E,gBAAgB;AAChB,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC9G,4DAA4D;IAC5D,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5G;AAED,oBAAoB;AACpB,MAAM,WAAW,KAAK;IACpB,kDAAkD;IAClD,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,cAAc,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAC9G,kCAAkC;IAClC,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,cAAc,EACzC,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACnC,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAWD,eAAO,MAAM,KAAK,8DAYhB,CAAC"}
package/dist/index.js CHANGED
@@ -2,10 +2,9 @@
2
2
  // @aalis/api-hooks — 钩子契约
3
3
  //
4
4
  // 每个钩子键代表一个语义清晰的生命周期事件(如 inbound:command / agent:llm:before),
5
- // handler 在事件内部按**登记顺序**串行执行洋葱模型(next 交棒)。不用数字 priority:
6
- // 相位之间的次序由调度方显式表达;相位内部的 handler 应顺序无关,或由相位拥有方约定。
7
- // 登记序是每条登记自带的序号,提供者按它排链:换提供者时各账本整批重挂,链序不变;
8
- // 提供者重启时依赖方随之重启、重新登记,链序即重新激活的次序(与冷启动相同)。
5
+ // handler 在事件内部串行执行洋葱模型(next 交棒),按登记方的位次排(宿主的根最前,插件按实例 id 的码元序),同一登记方的几条按登记先后。
6
+ // 不用数字 priority:相位之间的次序由调度方显式表达;相位内部的 handler 应顺序无关,或由相位拥有方约定。
7
+ // 链序不看登记发生的时刻:插件重启、提供者重启或换人都不改变它。
9
8
  // 默认提供者:@aalis/plugin-hooks。没有提供者时 run 返回被拒的 Promise(不执行默认动作)。
10
9
  //
11
10
  // 钩子键由各 -api 包经 declaration merging 注入 HookContextMap:
@@ -16,18 +15,18 @@
16
15
  import { defineService } from '@aalis/core';
17
16
  /**
18
17
  * 登记序计数器:进程内全部 api-hooks 副本共用一个(经全局符号表取同一个对象),登记即取号。
19
- * 契约包可能装了两份,各自从 0 计数的话序号不可比,提供者按序排链就会把后登记的排到前面。
18
+ * 契约包可能装了两份:各自计数的话,同一个登记方经两份登记的几条序号不可比,提供者排链时会把后登记的排到前面。
20
19
  */
21
20
  const ORDER = Symbol.for('@aalis/api-hooks.order');
22
21
  const shared = globalThis;
23
22
  shared[ORDER] ??= { n: 0 };
24
23
  const orderCounter = shared[ORDER];
25
24
  export const hooks = defineService('hooks', port => {
26
- // 每次登记一个独立账目:同一激活可在同一钩子上挂多个 handler,没有「同键替换」。登记序全局唯一,
27
- // 用作账本键不会撞;键带钩子名,关闭后登记的告警能点名
25
+ // 每次登记一个独立条目:同一激活可在同一钩子上挂多个 handler,没有「同键替换」。登记序全局唯一,
26
+ // 用作归属表的键不会撞;键带钩子名,关闭后登记的告警能点名
28
27
  const ledger = port.registrar({
29
28
  key: ({ hook, order }) => `${hook}#${order}`,
30
- register: (registry, { hook, fn, order }) => registry.register(hook, fn, port.id, order),
29
+ register: (registry, { hook, fn, order }) => registry.register(hook, fn, port.id, order, port.seat),
31
30
  });
32
31
  return {
33
32
  middleware: (hook, fn) => ledger.add({ hook, fn: fn, order: ++orderCounter.n }),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,0BAA0B;AAC1B,EAAE;AACF,8DAA8D;AAC9D,yDAAyD;AACzD,iDAAiD;AACjD,2CAA2C;AAC3C,yCAAyC;AACzC,+DAA+D;AAC/D,EAAE;AACF,uDAAuD;AACvD,wCAAwC;AACxC,wEAAwE;AACxE,MAAM;AACN,+DAA+D;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA4C5C;;;GAGG;AACH,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AACnD,MAAM,MAAM,GAAG,UAAuD,CAAC;AACvE,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3B,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AAEnC,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAsB,OAAO,EAAE,IAAI,CAAC,EAAE;IACtE,sDAAsD;IACtD,6BAA6B;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAA6D;QACxF,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE;QAC5C,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC;KACzF,CAAC,CAAC;IACH,OAAO;QACL,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAA2B,EAAE,KAAK,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QACxG,yDAAyD;QACzD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC;KACnG,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,0BAA0B;AAC1B,EAAE;AACF,8DAA8D;AAC9D,+EAA+E;AAC/E,+DAA+D;AAC/D,kCAAkC;AAClC,+DAA+D;AAC/D,EAAE;AACF,uDAAuD;AACvD,wCAAwC;AACxC,wEAAwE;AACxE,MAAM;AACN,+DAA+D;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA6C5C;;;GAGG;AACH,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AACnD,MAAM,MAAM,GAAG,UAAuD,CAAC;AACvE,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3B,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AAEnC,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAsB,OAAO,EAAE,IAAI,CAAC,EAAE;IACtE,sDAAsD;IACtD,+BAA+B;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAA6D;QACxF,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE;QAC5C,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC;KACpG,CAAC,CAAC;IACH,OAAO;QACL,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAA2B,EAAE,KAAK,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QACxG,yDAAyD;QACzD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC;KACnG,CAAC;AACJ,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aalis/api-hooks",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,10 +21,10 @@
21
21
  "devDependencies": {
22
22
  "@types/node": "^22.0.0",
23
23
  "typescript": "^5.7.0",
24
- "@aalis/core": "0.20.0"
24
+ "@aalis/core": "0.22.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@aalis/core": ">=0.20.0 <1.0.0"
27
+ "@aalis/core": ">=0.22.0 <1.0.0"
28
28
  },
29
29
  "keywords": [
30
30
  "aalis",