@shanepadgett/tau-agent 0.46.0 → 0.46.1

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 (2) hide show
  1. package/package.json +2 -2
  2. package/shared/events.ts +20 -44
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shanepadgett/tau-agent",
3
- "version": "0.46.0",
3
+ "version": "0.46.1",
4
4
  "description": "Tau is a custom agentic harness built with pi extensions",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "@ast-grep/wasm": "0.45.3",
38
- "@shanepadgett/tau-tui": "0.46.0",
38
+ "@shanepadgett/tau-tui": "0.46.1",
39
39
  "@vscode/tree-sitter-wasm": "0.3.1",
40
40
  "image-size": "2.0.4",
41
41
  "smol-toml": "1.8.0",
package/shared/events.ts CHANGED
@@ -81,19 +81,14 @@ interface TauEventAPI extends EmitEventAPI {
81
81
 
82
82
  type TauEventHandler<Name extends keyof TauAgentEvents> = (data: TauAgentEvents[Name]) => void | Promise<void>;
83
83
 
84
- interface TauEventSubscription {
85
- stop(): void;
86
- }
87
-
88
- type TauEventSubscriptionRegistry = WeakMap<
89
- ExtensionAPI["events"],
90
- Map<string, Map<keyof TauAgentEvents, TauEventSubscription>>
91
- >;
84
+ // `pi.events` is a fresh wrapper per extension, so subscriptions are matched through the shared bus itself.
85
+ // Each copy of this module (global and project installs) announces its subscription and stops any older one.
86
+ const CLAIM_CHANNEL = "tau:subscription.claim";
92
87
 
93
- // Global and project installs load separate module instances but share one pi.events bus.
94
- const registryKey = Symbol.for("tau-agent.eventSubscriptions");
95
- const registryHost = globalThis as typeof globalThis & { [registryKey]?: TauEventSubscriptionRegistry };
96
- const tauEventSubscriptions: TauEventSubscriptionRegistry = (registryHost[registryKey] ??= new WeakMap());
88
+ interface TauSubscriptionClaim {
89
+ owner: string;
90
+ name: string;
91
+ }
97
92
 
98
93
  export function emitTauEvent<Name extends keyof TauAgentEvents>(
99
94
  pi: EmitEventAPI,
@@ -130,25 +125,21 @@ function subscribeToTauEvent<Name extends keyof TauAgentEvents>(
130
125
  ): () => void {
131
126
  if (owner.length === 0) throw new Error("Tau event owner is required.");
132
127
 
133
- const subscriptions = getOwnerSubscriptions(pi.events, owner);
134
- subscriptions.get(name)?.stop();
135
-
136
128
  let unsubscribe: (() => void) | undefined;
137
129
  let disposed = false;
130
+ const claim: TauSubscriptionClaim = { owner, name };
138
131
 
139
132
  function detach(): void {
140
133
  unsubscribe?.();
141
134
  unsubscribe = undefined;
142
135
  }
143
136
 
144
- const subscription: TauEventSubscription = {
145
- stop() {
146
- if (disposed) return;
147
- disposed = true;
148
- detach();
149
- if (subscriptions.get(name) === subscription) subscriptions.delete(name);
150
- },
151
- };
137
+ function stop(): void {
138
+ if (disposed) return;
139
+ disposed = true;
140
+ detach();
141
+ stopClaimListener();
142
+ }
152
143
 
153
144
  function attach(): void {
154
145
  if (disposed) return;
@@ -156,32 +147,17 @@ function subscribeToTauEvent<Name extends keyof TauAgentEvents>(
156
147
  unsubscribe = pi.events.on(name, handler as (data: unknown) => void);
157
148
  }
158
149
 
159
- subscriptions.set(name, subscription);
150
+ pi.events.emit(CLAIM_CHANNEL, claim);
151
+ const stopClaimListener = pi.events.on(CLAIM_CHANNEL, (other) => {
152
+ const { owner: otherOwner, name: otherName } = other as TauSubscriptionClaim;
153
+ if (other !== claim && otherOwner === owner && otherName === name) stop();
154
+ });
160
155
  if (attachImmediately) attach();
161
156
  pi.on("session_start", attach);
162
157
  pi.on("session_shutdown", detach);
163
- return subscription.stop;
158
+ return stop;
164
159
  }
165
160
 
166
161
  export function setTauFooterItem(pi: EmitEventAPI, item: TauFooterItem): void {
167
162
  emitTauEvent(pi, "tau:footer-item", item);
168
163
  }
169
-
170
- function getOwnerSubscriptions(
171
- events: ExtensionAPI["events"],
172
- owner: string,
173
- ): Map<keyof TauAgentEvents, TauEventSubscription> {
174
- let busSubscriptions = tauEventSubscriptions.get(events);
175
- if (!busSubscriptions) {
176
- busSubscriptions = new Map();
177
- tauEventSubscriptions.set(events, busSubscriptions);
178
- }
179
-
180
- let ownerSubscriptions = busSubscriptions.get(owner);
181
- if (!ownerSubscriptions) {
182
- ownerSubscriptions = new Map();
183
- busSubscriptions.set(owner, ownerSubscriptions);
184
- }
185
-
186
- return ownerSubscriptions;
187
- }