crann 1.0.49 → 2.0.2
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 +353 -594
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/react.js +2 -0
- package/dist/cjs/react.js.map +7 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +4 -4
- package/dist/esm/react.js +2 -0
- package/dist/esm/react.js.map +7 -0
- package/dist/types/__mocks__/uuid.d.ts +10 -0
- package/dist/types/__tests__/integration.test.d.ts +7 -0
- package/dist/types/agent/Agent.d.ts +77 -0
- package/dist/types/agent/__tests__/Agent.test.d.ts +1 -0
- package/dist/types/agent/__tests__/setup.d.ts +4 -0
- package/dist/types/agent/index.d.ts +7 -0
- package/dist/types/agent/types.d.ts +73 -0
- package/dist/types/crann.d.ts +1 -2
- package/dist/types/errors.d.ts +59 -0
- package/dist/types/model/crann.model.d.ts +1 -1
- package/dist/types/react/__tests__/hooks.test.d.ts +6 -0
- package/dist/types/react/hooks.d.ts +44 -0
- package/dist/types/react/index.d.ts +13 -0
- package/dist/types/react/types.d.ts +74 -0
- package/dist/types/rpc/adapter.d.ts +1 -1
- package/dist/types/rpc/types.d.ts +1 -1
- package/dist/types/store/ActionExecutor.d.ts +35 -0
- package/dist/types/store/AgentRegistry.d.ts +49 -0
- package/dist/types/store/Persistence.d.ts +59 -0
- package/dist/types/store/StateManager.d.ts +65 -0
- package/dist/types/store/Store.d.ts +188 -0
- package/dist/types/store/__tests__/ActionExecutor.test.d.ts +1 -0
- package/dist/types/store/__tests__/AgentRegistry.test.d.ts +1 -0
- package/dist/types/store/__tests__/Persistence.test.d.ts +6 -0
- package/dist/types/store/__tests__/StateManager.test.d.ts +1 -0
- package/dist/types/store/__tests__/setup.d.ts +4 -0
- package/dist/types/store/__tests__/types.test.d.ts +1 -0
- package/dist/types/store/index.d.ts +10 -0
- package/dist/types/store/types.d.ts +169 -0
- package/dist/types/transport/core/PorterAgent.d.ts +46 -0
- package/dist/types/transport/core/PorterSource.d.ts +40 -0
- package/dist/types/transport/index.d.ts +6 -0
- package/dist/types/transport/managers/AgentConnectionManager.d.ts +42 -0
- package/dist/types/transport/managers/AgentManager.d.ts +40 -0
- package/dist/types/transport/managers/AgentMessageHandler.d.ts +17 -0
- package/dist/types/transport/managers/ConnectionManager.d.ts +14 -0
- package/dist/types/transport/managers/MessageHandler.d.ts +29 -0
- package/dist/types/transport/managers/MessageQueue.d.ts +19 -0
- package/dist/types/transport/porter.model.d.ts +71 -0
- package/dist/types/transport/porter.utils.d.ts +44 -0
- package/dist/types/transport/react/index.d.ts +1 -0
- package/dist/types/transport/react/usePorter.d.ts +17 -0
- package/dist/types/utils/agent.d.ts +1 -1
- package/package.json +28 -2
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/crann.ts", "../../src/model/crann.model.ts", "../../src/utils/
|
|
4
|
-
"sourcesContent": ["import browser from \"webextension-polyfill\";\nimport {\n DerivedInstanceState,\n DerivedServiceState,\n ConfigItem,\n DerivedState,\n Partition,\n CrannOptions,\n ActionDefinition,\n AnyConfig,\n isStateItem,\n isActionItem,\n SetStateCallback,\n SetStateFunction,\n StateChangeListener,\n StateChanges,\n MergeStateTypes,\n} from \"./model/crann.model\";\nimport { AgentInfo, source, Agent } from \"porter-source\";\nimport { deepEqual } from \"./utils/deepEqual\";\nimport { BrowserLocation } from \"porter-source\";\nimport { trackStateChange } from \"./utils/tracking\";\nimport { DebugManager } from \"./utils/debug\";\nimport { createCrannRPCAdapter } from \"./rpc/adapter\";\nimport { Logger } from \"./utils/logger\";\nimport { getAgentTag } from \"./utils/agent\";\n\nexport class Crann<TConfig extends AnyConfig> {\n private static instance: Crann<any> | null = null;\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultServiceState: DerivedServiceState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private serviceState: DerivedServiceState<TConfig>;\n private stateChangeListeners: Array<StateChangeListener<TConfig>> = [];\n private instanceReadyListeners: Array<\n (instanceId: string, agent: AgentInfo) => void\n > = [];\n private storagePrefix = \"crann_\";\n private porter = source(\"crann\", { debug: false });\n private rpcEndpoint: ReturnType<typeof createCrannRPCAdapter>;\n private logger: Logger;\n\n constructor(private config: TConfig, options?: CrannOptions) {\n // Set the debug flag globally\n if (options?.debug) {\n DebugManager.setDebug(true);\n Logger.setDebug(true);\n }\n this.storagePrefix = options?.storagePrefix ?? this.storagePrefix;\n\n // Set up the core logger\n this.logger = Logger.forContext(\"Core\");\n this.logger.log(\"Constructing Crann with new logger\");\n\n // Hydrate the initial state from the config defaults and from storage\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultServiceState = this.serviceState =\n this.initializeServiceDefault();\n this.hydrate();\n\n // Set up the message handlers\n this.logger.log(\"Crann constructed, setting initial message handlers\");\n this.porter.on({\n setState: (message, info) => {\n if (!info) {\n this.logger.warn(\"setState message heard from unknown agent\");\n return;\n }\n\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"Setting state:\", message);\n this.set(message.payload.state, info.id);\n },\n });\n\n // Track which agents we've already sent initialState to\n const agentsInitialized = new Set<string>();\n\n // Once the agents are connected and have set up their listeners, send them the initial state\n this.porter.onMessagesSet((info: AgentInfo) => {\n if (!info) {\n this.logger.error(\"Messages set but no agent info.\", { info });\n return;\n }\n\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"onMessagesSet received for agent:\", {\n id: info.id,\n context: info.location.context,\n tabId: info.location.tabId,\n frameId: info.location.frameId,\n alreadyInitialized: agentsInitialized.has(info.id),\n });\n\n // Skip sending initialState if we've already sent it to this agent\n if (agentsInitialized.has(info.id)) {\n this.logger\n .withTag(agentTag)\n .log(\"Already sent initialState to agent, skipping:\", info.id);\n return;\n }\n\n // Add the agent to the set of agents we've already sent initialState to\n agentsInitialized.add(info.id);\n\n this.logger\n .withTag(agentTag)\n .log(\"Messages set received. Sending initial state.\", { info });\n const fullState = this.get(info.id);\n this.porter.post(\n {\n action: \"initialState\",\n payload: { state: fullState, info },\n },\n info.location\n );\n\n this.notifyInstanceReady(info.id, info);\n });\n\n // Handle agent connection and disconnection\n this.porter.onConnect((info: AgentInfo) => {\n if (!info) {\n this.logger.error(\"Agent connected but no agent info.\", { info });\n return;\n }\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"Agent connected\", { info });\n this.addInstance(info.id, agentTag);\n this.porter.onDisconnect((info: AgentInfo) => {\n this.logger\n .withTag(getAgentTag(info))\n .log(\n \"Agent disconnect heard. Connection type, context and location:\",\n { info }\n );\n this.removeInstance(info.id);\n });\n });\n\n const setStateCallback: SetStateCallback<TConfig> = ((\n state: any,\n key?: string\n ) => {\n if (key !== undefined) {\n return this.set(state, key);\n } else {\n return this.set(state);\n }\n }) as SetStateCallback<TConfig>;\n\n // Cast to the generic version when passing to RPC adapter\n const genericSetState = setStateCallback as SetStateFunction<\n DerivedState<TConfig>\n >;\n\n // Initialize RPC with actions\n const actions = this.extractActions(config);\n\n const stateGetter = () => {\n const currentState = this.get();\n this.logger.log(\n \"State getter called, returning current state:\",\n currentState\n );\n return currentState;\n };\n\n this.rpcEndpoint = createCrannRPCAdapter(\n stateGetter,\n actions,\n this.porter,\n genericSetState\n );\n }\n\n public static getInstance<TConfig extends AnyConfig>(\n config: TConfig,\n options?: CrannOptions\n ): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, options);\n } else if (options?.debug) {\n const logger = Logger.forContext(\"Core\");\n logger.log(\"Instance requested and already existed, returning\");\n }\n return Crann.instance;\n }\n\n /**\n * Add an instance to the Crann instance.\n * @param key The key of the instance to add.\n * @param agentTag The tag of the agent that is adding the instance, for logging.\n */\n private async addInstance(key: string, agentTag: string): Promise<void> {\n if (!this.instances.has(key)) {\n this.logger.withTag(agentTag).log(\"Adding instance from agent key\");\n const initialInstanceState = {\n ...this.defaultInstanceState,\n } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n this.logger\n .withTag(agentTag)\n .log(\"Instance was already registered, ignoring request from key\");\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.logger.withTag(key).log(\"Remove instance requested\");\n this.instances.delete(key);\n } else {\n this.logger\n .withTag(key)\n .log(\"Remove instance requested but it did not exist!\");\n }\n }\n\n @trackStateChange\n public async setServiceState(\n state: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.logger.log(\"Request to set service state with update:\", state);\n this.logger.log(\"Existing service state was \", this.serviceState);\n const update = { ...this.serviceState, ...state };\n if (!deepEqual(this.serviceState, update)) {\n this.logger.log(\n \"Confirmed new state was different than existing so proceeding to persist then notify all connected instances.\"\n );\n this.serviceState = update;\n await this.persist(state);\n this.notify(state as StateChanges<TConfig>);\n } else {\n this.logger.log(\"New state seems to be the same as existing, skipping\");\n }\n }\n\n @trackStateChange\n public async setInstanceState(\n key: string,\n state: Partial<DerivedInstanceState<TConfig>>\n ): Promise<void> {\n this.logger\n .withTag(key)\n .log(\"Request to update instance state, update:\", state);\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.logger\n .withTag(key)\n .log(\"Instance state update is different, updating and notifying.\");\n this.instances.set(key, update);\n this.notify(state as StateChanges<TConfig>, key);\n } else {\n this.logger\n .withTag(key)\n .log(\"Instance state update is not different, skipping update.\");\n }\n }\n\n // If we pass in specific state to persist, it only persists that state.\n // Otherwise persists all of the worker state.\n private async persist(\n state?: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.logger.log(\"Persisting state\");\n let wasPersisted = false;\n for (const key in state || this.serviceState) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || \"none\";\n const value = state\n ? state[key as keyof DerivedServiceState<TConfig>]\n : this.serviceState[key];\n switch (persistence) {\n case \"session\":\n await browser.storage.session.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n case \"local\":\n await browser.storage.local.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n default:\n break;\n }\n }\n if (wasPersisted) {\n this.logger.log(\"State was persisted\");\n } else {\n this.logger.log(\"Nothing to persist\");\n }\n }\n\n public async clear(): Promise<void> {\n this.logger.log(\"Clearing state\");\n this.serviceState = this.defaultServiceState;\n this.instances.forEach((_, key) => {\n this.instances.set(key, this.defaultInstanceState);\n });\n await this.persist();\n this.notify({} as StateChanges<TConfig>);\n }\n\n public subscribe(listener: StateChangeListener<TConfig>): void {\n this.logger.log(\"Subscribing to state\");\n this.stateChangeListeners.push(listener);\n }\n\n // Right now we notify the instance even if the state change came from the instance.\n // This should probably be skipped for instance state, since it already knows.\n private notify(changes: StateChanges<TConfig>, key?: string): void {\n const agent = key ? this.porter.getAgentById(key) : undefined;\n const state = key ? this.get(key) : this.get();\n\n if (this.stateChangeListeners.length > 0) {\n this.logger.log(\"Notifying state change listeners in source\");\n this.stateChangeListeners.forEach((listener) => {\n listener(state, changes, agent?.info);\n });\n }\n\n if (key && agent?.info.location) {\n this.logger.withTag(key).log(\"Notifying of state change.\");\n this.porter.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n agent.info.location\n );\n } else {\n this.logger.log(\"Notifying everyone\");\n // for every key of this.instances, post the state update to the corresponding key\n this.instances.forEach((_, key) => {\n this.porter.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n key\n );\n });\n }\n }\n\n public get(): DerivedState<TConfig>;\n public get(\n key: string\n ): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n public get(\n key?: string\n ): DerivedServiceState<TConfig> | DerivedState<TConfig> {\n if (!key) {\n return { ...this.serviceState, ...({} as DerivedInstanceState<TConfig>) };\n }\n return { ...this.serviceState, ...this.instances.get(key) };\n }\n\n // Todo: Should we return the instance data? What is the point of this.\n public findInstance(location: BrowserLocation): string | null {\n const agent = this.porter.getAgentByLocation(location);\n if (!agent) {\n this.logger.log(\"Could not find agent for location:\", { location });\n return null;\n }\n for (const [key, instance] of this.instances) {\n if (key === agent.info.id) {\n this.logger.log(\"Found instance for key:\", key);\n return key;\n }\n }\n this.logger.log(\"Could not find instance for context and location:\", {\n location,\n });\n return null;\n }\n\n // Convenience re-export of the porter-source queryAgents method.\n public queryAgents(query: Partial<BrowserLocation>): Agent[] {\n return this.porter.queryAgents(query);\n }\n\n public async set(state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n public async set(\n state: Partial<\n MergeStateTypes<\n DerivedInstanceState<TConfig>,\n DerivedServiceState<TConfig>\n >\n >,\n key: string\n ): Promise<void>;\n public async set(\n state:\n | Partial<DerivedServiceState<TConfig>>\n | Partial<\n MergeStateTypes<\n DerivedInstanceState<TConfig>,\n DerivedServiceState<TConfig>\n >\n >,\n key?: string\n ): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedServiceState<TConfig>>;\n\n for (const itemKey in state) {\n const item = this.config[itemKey as keyof TConfig];\n if (isConfigItem(item)) {\n if (item.partition === \"instance\") {\n const instanceItemKey =\n itemKey as keyof DerivedInstanceState<TConfig>;\n const instanceState = state as Partial<DerivedInstanceState<TConfig>>;\n instance[instanceItemKey] = instanceState[instanceItemKey];\n } else if (!item.partition || item.partition === Partition.Service) {\n const serviceItemKey = itemKey as keyof DerivedServiceState<TConfig>;\n const serviceState = state as Partial<DerivedServiceState<TConfig>>;\n worker[serviceItemKey] = serviceState[serviceItemKey]!;\n }\n }\n }\n\n if (key && Object.keys(instance).length > 0) {\n this.logger.withTag(key).log(\"Setting instance state:\", instance);\n this.setInstanceState(key, instance);\n }\n if (Object.keys(worker).length > 0) {\n this.logger.log(\"Setting service state:\", worker);\n this.setServiceState(worker);\n }\n }\n\n private async hydrate(): Promise<void> {\n this.logger.log(\"Hydrating state from storage.\");\n const local = await browser.storage.local.get(null);\n const session = await browser.storage.session.get(null);\n const combined = { ...local, ...session };\n\n this.logger.log(\"Storage data is:\", { local, session, combined });\n\n const update: Partial<DerivedServiceState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\n let hadItems = false;\n for (const prefixedKey in combined) {\n const key = this.removePrefix(prefixedKey);\n this.logger.log(`Checking storage key ${prefixedKey} -> ${key}`);\n\n if (this.config.hasOwnProperty(key)) {\n const value = combined[prefixedKey];\n\n this.logger.log(`Found storage value for ${key}:`, value);\n update[key as keyof DerivedServiceState<TConfig>] = value;\n hadItems = true;\n }\n }\n if (hadItems) {\n this.logger.log(\"Hydrated some items.\");\n } else {\n this.logger.log(\"No items found in storage.\");\n }\n this.serviceState = { ...this.defaultServiceState, ...update };\n }\n\n private removePrefix(key: string): string {\n if (key.startsWith(this.storagePrefix)) {\n return key.replace(this.storagePrefix, \"\");\n }\n return key;\n }\n\n private initializeInstanceDefault(): DerivedInstanceState<TConfig> {\n const instanceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item = this.config[key];\n if (isStateItem(item) && item.partition === \"instance\") {\n instanceState[key] = item.default;\n }\n });\n return instanceState;\n }\n\n private initializeServiceDefault(): DerivedServiceState<TConfig> {\n this.logger.log(\"Initializing service default state\");\n this.logger.log(\"Config is:\", this.config);\n\n const serviceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item = this.config[key];\n this.logger.log(\"Item is:\", item);\n if (\n isStateItem(item) &&\n (!item.partition || item.partition === Partition.Service)\n ) {\n serviceState[key] = item.default;\n this.logger.log(\n \"Setting service state for key:\",\n key,\n \"to\",\n item.default\n );\n }\n });\n this.logger.log(\"Final service state is:\", serviceState);\n return serviceState;\n }\n\n public subscribeToInstanceReady(\n listener: (instanceId: string, agent: AgentInfo) => void\n ): () => void {\n this.logger.log(\"Subscribing to instance ready events\");\n this.instanceReadyListeners.push(listener);\n\n this.instances.forEach((_, instanceId) => {\n const agent = this.porter.getAgentById(instanceId);\n if (agent?.info) {\n listener(instanceId, agent.info);\n }\n });\n\n return () => {\n this.logger.log(\"Unsubscribing from instance ready events\");\n const index = this.instanceReadyListeners.indexOf(listener);\n if (index !== -1) {\n this.instanceReadyListeners.splice(index, 1);\n }\n };\n }\n\n private notifyInstanceReady(instanceId: string, info: AgentInfo): void {\n if (this.instanceReadyListeners.length > 0) {\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"Notifying instance ready listeners\");\n this.instanceReadyListeners.forEach((listener) => {\n listener(instanceId, info);\n });\n }\n }\n\n private extractActions(\n config: TConfig\n ): Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>> {\n return Object.entries(config)\n .filter(([_, value]) => isActionItem(value))\n .reduce<\n Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>>\n >((acc, [key, value]) => {\n const action = value as ActionDefinition<\n DerivedState<TConfig>,\n any[],\n any\n >;\n return {\n ...acc,\n [key]: action,\n };\n }, {});\n }\n}\n\n// Define an interface for the API returned by create()\nexport interface CrannAPI<TConfig extends AnyConfig> {\n get: {\n (): DerivedState<TConfig>;\n (key: string): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n };\n set: {\n (state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n (\n state: Partial<\n MergeStateTypes<\n DerivedInstanceState<TConfig>,\n DerivedServiceState<TConfig>\n >\n >,\n key: string\n ): Promise<void>;\n };\n subscribe: (listener: StateChangeListener<TConfig>) => void;\n onInstanceReady: (\n listener: (instanceId: string, agent: AgentInfo) => void\n ) => () => void;\n findInstance: (location: BrowserLocation) => string | null;\n queryAgents: (query: Partial<BrowserLocation>) => Agent[];\n clear: () => Promise<void>;\n}\n\nexport function create<TConfig extends AnyConfig>(\n config: TConfig,\n options?: CrannOptions\n): CrannAPI<TConfig> {\n const instance = Crann.getInstance(config, options);\n\n return {\n get: instance.get.bind(instance),\n set: instance.set.bind(instance),\n subscribe: instance.subscribe.bind(instance),\n onInstanceReady: instance.subscribeToInstanceReady.bind(instance),\n findInstance: instance.findInstance.bind(instance),\n queryAgents: instance.queryAgents.bind(instance),\n clear: instance.clear.bind(instance),\n };\n}\n\nfunction isConfigItem(item: any): item is ConfigItem<any> {\n return item && typeof item === \"object\" && \"default\" in item;\n}\n", "import { AgentInfo, BrowserLocation } from \"porter-source\";\n\nexport const Partition = {\n Instance: \"instance\" as const,\n Service: \"service\" as const,\n};\n\nexport const Persistence = {\n Session: \"session\" as const,\n Local: \"local\" as const,\n None: \"none\" as const,\n};\n\nexport type ActionHandler<TState, TArgs extends any[], TResult> = (\n state: TState,\n setState: SetStateFunction<TState>,\n target: BrowserLocation,\n ...args: TArgs\n) => Promise<TResult>;\n\nexport type ActionDefinition<TState, TArgs extends any[], TResult> = {\n handler: ActionHandler<TState, TArgs, TResult>;\n validate?: (...args: TArgs) => void;\n};\n\nexport type ActionsConfig<TState> = {\n [K: string]: ActionDefinition<TState, any[], Partial<TState>>;\n};\n\n// The following \"SetState\" types are used to define the types for the setState function in the RPC adapter.\n// To prevent a cirucular dependency with TConfig, we define a specific and a generic version.\n\n// This is the type that the RPC adapter expects\nexport type SetStateFunction<TState> = {\n (state: Partial<TState>): Promise<void>;\n (state: Partial<TState>, key: string): Promise<void>;\n};\n\n// This is the more specific type that the Crann instance expects\nexport type SetStateCallback<TConfig extends AnyConfig> = {\n (state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n (state: Partial<DerivedInstanceState<TConfig>>, key: string): Promise<void>;\n};\n\n// Input types (what users provide in their config)\nexport type ConfigItem<T> = {\n default: T;\n partition?: (typeof Partition)[keyof typeof Partition];\n persist?: (typeof Persistence)[keyof typeof Persistence];\n};\n\nexport type AnyConfig = Record<\n string,\n ConfigItem<any> | ActionDefinition<any, any[], any>\n>;\n\n// Helper type to extract just the state items from a config\nexport type StateConfig<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<any> ? T[P] : never;\n};\n\n// Helper type to extract just the action items from a config\nexport type ActionConfig<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ActionDefinition<any, any[], any> ? T[P] : never;\n};\n\n// Update DerivedState to use the internal types\nexport type DerivedState<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<infer DefaultType>\n ? DefaultType\n : never;\n};\n\n// Update DerivedInstanceState to use the internal types\nexport type DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<infer DefaultType> & {\n partition: \"instance\";\n }\n ? DefaultType\n : never;\n};\n\n// Update DerivedServiceState to use the internal types\nexport type DerivedServiceState<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<infer DefaultType>\n ? T[P] extends { partition: \"instance\" }\n ? never\n : DefaultType\n : never;\n};\n\n// Remove never properties from a type\ntype OmitNever<T> = {\n [K in keyof T as T[K] extends never ? never : K]: T[K];\n};\n\n// Merge by taking all non-never properties from both types\nexport type MergeStateTypes<TInstance, TService> = OmitNever<TInstance> &\n OmitNever<TService>;\n\n// Type guards\nexport const isStateItem = <T>(\n item: ConfigItem<T> | ActionDefinition<any, any[], any>\n): item is ConfigItem<T> => {\n return !(\"handler\" in item);\n};\n\nexport const isActionItem = <TState, TArgs extends any[], TResult>(\n item: ConfigItem<any> | ActionDefinition<TState, TArgs, TResult>\n): item is ActionDefinition<TState, TArgs, TResult> => {\n return \"handler\" in item;\n};\n\ntype StateSubscriber<TConfig extends AnyConfig> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n};\n\ntype CrannAgent<TConfig extends AnyConfig> = {\n get: () => DerivedState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (\n callback: (changes: StateUpdate<TConfig>) => void,\n keys?: Array<keyof TConfig>\n ) => () => void;\n getAgentInfo: () => AgentInfo;\n onReady: (callback: (info: ConnectionStatus) => void) => () => void;\n};\n\ntype UseCrann<TConfig extends AnyConfig> = <\n K extends keyof DerivedState<TConfig>\n>(\n key: K\n) => [\n DerivedState<TConfig>[K],\n (value: DerivedState<TConfig>[K]) => void,\n (callback: (update: StateChangeUpdate<TConfig, K>) => void) => () => void\n];\n\ntype ConnectReturn<TConfig extends AnyConfig> = {\n useCrann: UseCrann<TConfig>;\n get: CrannAgent<TConfig>[\"get\"];\n set: CrannAgent<TConfig>[\"set\"];\n subscribe: CrannAgent<TConfig>[\"subscribe\"];\n getAgentInfo: CrannAgent<TConfig>[\"getAgentInfo\"];\n onReady: CrannAgent<TConfig>[\"onReady\"];\n callAction: (name: string, ...args: any[]) => Promise<any>;\n onDisconnect: (callback: () => void) => () => void;\n onReconnect: (callback: (info: AgentInfo) => void) => () => void;\n};\n\nexport type StateChanges<T extends AnyConfig> = {\n [K in keyof DerivedState<T>]?: NonNullable<DerivedState<T>[K]>;\n};\n\ntype StateChangeUpdate<\n TConfig extends AnyConfig,\n K extends keyof DerivedState<TConfig>\n> = {\n current: DerivedState<TConfig>[K];\n previous: DerivedState<TConfig>[K];\n state: DerivedState<TConfig>;\n};\n\nexport type StateChangeListener<TConfig extends AnyConfig> = (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: StateChanges<TConfig>,\n agent?: AgentInfo\n) => void;\n\ntype AgentSubscription<TConfig extends AnyConfig> = {\n (\n callback: (changes: StateUpdate<TConfig>) => void,\n key?: keyof DerivedState<TConfig>\n ): number;\n};\n\ntype StateUpdate<TConfig extends AnyConfig> = StateChanges<TConfig>;\n\nexport type CrannOptions = {\n debug?: boolean;\n storagePrefix?: string;\n};\n\ntype ConnectionStatus = {\n connected: boolean;\n agent?: AgentInfo;\n};\n\nexport type CrannConfig<TState> = {\n [K: string]: ConfigItem<any> | ActionsConfig<TState>;\n};\n\nexport {\n StateSubscriber,\n CrannAgent,\n AgentSubscription,\n StateUpdate,\n DerivedState as State,\n ConnectReturn,\n UseCrann,\n ConnectionStatus,\n StateChangeUpdate,\n};\n", "export function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n keysA.sort();\n keysB.sort();\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i];\n if (key !== keysB[i] || !deepEqual(a[key], b[key])) return false;\n }\n return true;\n}", "// Create a global debug state manager\nexport class DebugManager {\n private static _debug: boolean = false;\n\n static setDebug(value: boolean): void {\n DebugManager._debug = value;\n }\n\n static isDebugEnabled(): boolean {\n return DebugManager._debug;\n }\n}\n\n// Export a convenience function\nexport function isDebugEnabled(): boolean {\n return DebugManager.isDebugEnabled();\n}\n", "import { isDebugEnabled } from \"./debug\";\n\nexport type StateChangeMetadata = {\n source: string;\n timestamp: number;\n changes: any;\n instanceKey?: string;\n};\n\nexport function trackStateChange(\n target: any,\n propertyKey: string,\n descriptor: PropertyDescriptor\n): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n // Only log if debugging is enabled\n if (isDebugEnabled()) {\n // Get the stack trace to find the actual caller\n const stack = new Error().stack;\n const lines = stack?.split(\"\\n\") || [];\n const callerMatch = lines[3]?.match(/at\\s+(\\S+)\\s+/);\n const caller = callerMatch ? callerMatch[1] : \"unknown\";\n\n const changes = args.length > 1 ? args[1] : undefined;\n\n const metadata: StateChangeMetadata = {\n source: caller,\n timestamp: Date.now(),\n instanceKey: args[0],\n changes,\n };\n\n console.log(`Crann State Change:`, metadata);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n}\n", "import { source, AgentInfo, connect, Message, AgentAPI } from \"porter-source\";\nimport { createEndpoint } from \"./endpoint\";\nimport { MessageEndpoint, CallMessage, RPCMessage } from \"./types\";\nimport {\n ActionDefinition,\n AnyConfig,\n DerivedState,\n SetStateCallback,\n SetStateFunction,\n} from \"../model/crann.model\";\nimport { Logger } from \"../utils/logger\";\nimport { getAgentTag } from \"../utils/agent\";\n\nexport function createCrannRPCAdapter<TConfig extends AnyConfig>(\n stateGetter: () => DerivedState<TConfig>,\n actions: Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>>,\n porter?: ReturnType<typeof source> | ReturnType<typeof connect>,\n setState?: SetStateFunction<DerivedState<TConfig>>\n) {\n const porterInstance = porter || source(\"crann\");\n\n // Determine if this is a service worker instance (source) or content script instance (connect)\n const isServiceWorker = !(porterInstance.type === \"agent\");\n\n // Set up logger with the appropriate context\n const logger = Logger.forContext(isServiceWorker ? \"Core:RPC\" : \"Agent:RPC\");\n\n const messageEndpoint: MessageEndpoint = {\n postMessage: (message, transferables) => {\n if (isServiceWorker) {\n logger.debug(\"Posting message from service worker:\", {\n message,\n transferables,\n });\n // In service worker, we need to respond to the specific target\n const [, rpcPayload] = message;\n const target = getTargetFromMessage(rpcPayload);\n if (!target) {\n logger.warn(\"No target specified for RPC response in service worker\");\n return;\n }\n porterInstance.post(\n {\n action: \"rpc\",\n payload: {\n message,\n transferables: transferables || [],\n },\n },\n target\n );\n } else {\n // In content script (agent) context\n // Get the agent info only when needed\n const agentInfo = (porterInstance as AgentAPI).getAgentInfo();\n\n if (!agentInfo) {\n logger.warn(\"No agent info found for posting message\", { agentInfo });\n return;\n }\n\n // Get the agent tag for logging\n const myTag = getAgentTag(agentInfo);\n\n // Destructure the tuple, skipping the messageId which we don't need\n const [, rpcPayload] = message;\n\n // Use type guard to check if it's a call message\n if (\"call\" in rpcPayload) {\n // Add the target info to the call message\n rpcPayload.call.target = agentInfo?.location;\n }\n\n logger.withTag(myTag).debug(\"Sending RPC message from agent:\", {\n rpcPayload,\n message,\n });\n // In content script, target is automatically the service worker\n porterInstance.post({\n action: \"rpc\",\n payload: {\n message,\n transferables: transferables || [],\n },\n });\n }\n },\n addEventListener: (event, listener) => {\n porterInstance.on({\n rpc: (message: Message<string>, info?: AgentInfo) => {\n try {\n if (!info) {\n logger.debug(\"RPC message received:\", {\n message,\n event,\n });\n } else {\n // Get the agent tag for logging\n const myTag = getAgentTag(info);\n logger.withTag(myTag).debug(\"RPC message received:\", {\n message,\n event,\n });\n }\n\n const { payload } = message;\n const { message: originalMessage, transferables = [] } = payload;\n const rpcEvent = new MessageEvent(\"message\", {\n data: originalMessage,\n ports:\n (transferables.filter(\n (t: unknown) => t instanceof MessagePort\n ) as MessagePort[]) || [],\n });\n listener(rpcEvent);\n } catch (e) {\n logger.error(\"Failed to parse RPC message payload:\", e);\n }\n },\n });\n },\n removeEventListener: () => {\n // Porter-source doesn't support removing listeners\n },\n // Add context information\n context: {\n isServiceWorker,\n agentInfo: !isServiceWorker\n ? (porterInstance as AgentAPI).getAgentInfo()\n : undefined,\n },\n };\n\n return createEndpoint(messageEndpoint, stateGetter, actions, setState);\n}\n\n// Don't love this being here. Let's move it sometime soon,\n// or find another way to do this.\nfunction getTargetFromMessage(payload: RPCMessage): any {\n if (\"result\" in payload) return payload.result.target;\n if (\"error\" in payload) return payload.error.target;\n if (\"call\" in payload) return payload.call.target;\n if (\"release\" in payload) return payload.release.target;\n return undefined;\n}\n", "export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport class Logger {\n private static debug = false;\n private static prefix = \"CrannLogger\";\n private static noOp = function () {};\n\n private context: string;\n private tag: string | null = null;\n\n /**\n * Create a new Logger instance with a specific context\n */\n constructor(context: string) {\n this.context = context;\n }\n\n static setDebug(value: boolean): void {\n Logger.debug = value;\n }\n\n static setPrefix(value: string): void {\n Logger.prefix = value;\n }\n\n /**\n * Set a persistent tag for this Logger instance\n */\n setTag(tag: string | null): void {\n this.tag = tag;\n }\n\n /**\n * Create a temporary logger with a specific tag\n * This doesn't modify the original logger instance\n */\n withTag(tag: string) {\n const tempLogger = new Logger(this.context);\n tempLogger.setTag(tag);\n return tempLogger;\n }\n\n /**\n * Get the full context string including tag if present\n */\n private getFullContext(): string {\n if (this.tag) {\n return `${this.context}:${this.tag}`;\n }\n return this.context;\n }\n\n /**\n * Create the log methods bound to the current context and tag\n */\n private createLogMethods() {\n const fullContext = this.getFullContext();\n const formatString = `%c${Logger.prefix}%c [%c${fullContext}%c]`;\n\n // Styles for the prefix and context - updated for better readability on dark backgrounds\n const prefixStyle = \"color: #3fcbff; font-weight: bold\"; // Bright cyan\n const contextStyle = \"color: #d58cff; font-weight: bold\"; // Bright purple\n const resetStyle = \"\";\n\n if (Logger.debug) {\n return {\n debug: console.log.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n log: console.log.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n info: console.info.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n warn: console.warn.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n error: console.error.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n };\n } else {\n return {\n debug: Logger.noOp,\n log: Logger.noOp,\n info: Logger.noOp,\n warn: Logger.noOp,\n error: Logger.noOp,\n };\n }\n }\n\n /**\n * Log methods that are dynamically created based on current context and tag\n */\n get debug() {\n return this.createLogMethods().debug;\n }\n get log() {\n return this.createLogMethods().log;\n }\n get info() {\n return this.createLogMethods().info;\n }\n get warn() {\n return this.createLogMethods().warn;\n }\n get error() {\n return this.createLogMethods().error;\n }\n\n /**\n * Static helper to create a logger with a specific context\n */\n static forContext(context: string, tag?: string): Logger {\n const logger = new Logger(context);\n if (tag) {\n logger.setTag(tag);\n }\n return logger;\n }\n}\n", "import { AgentInfo } from \"porter-source\";\n\n/**\n * Formats an agent tag based on the agent information\n * @param agent Agent information\n * @param options Configuration options\n * @returns Formatted agent tag string\n */\nexport function getAgentTag(\n agent: AgentInfo,\n options: { terse?: boolean } = { terse: true }\n): string {\n const formatTabId = (tabId: number | string): string => {\n const tabIdStr = String(tabId);\n if (tabIdStr.length >= 4) {\n return tabIdStr.slice(-4);\n } else {\n return tabIdStr.padStart(4, \"0\");\n }\n };\n\n const formattedTabId = formatTabId(agent.location.tabId);\n\n if (options?.terse) {\n return `${formattedTabId}:${agent.location.frameId}`;\n }\n return `${agent.location.context}:${formattedTabId}:${agent.location.frameId}`;\n}\n", "import { createBasicEncoder } from \"./encoding\";\nimport type {\n MessageEndpoint,\n RemoteCallable,\n EncodingStrategy,\n EncodingStrategyApi,\n Retainer,\n CallMessage,\n ResultMessage,\n ErrorMessage,\n RPCMessage,\n} from \"./types\";\nimport { ActionsConfig, SetStateFunction } from \"../model/crann.model\";\nimport { Logger } from \"../utils/logger\";\nimport { getAgentTag } from \"../utils/agent\";\n\nconst CALL = 0;\nconst RESULT = 1;\nconst TERMINATE = 2;\nconst RELEASE = 3;\nconst FUNCTION_APPLY = 5;\nconst FUNCTION_RESULT = 6;\n\ntype AnyFunction = (...args: any[]) => any;\n\nexport interface CreateEndpointOptions<T = unknown> {\n uuid?(): string;\n createEncoder?(api: EncodingStrategyApi): EncodingStrategy;\n callable?: (keyof T)[];\n}\n\nexport interface Endpoint<T> {\n readonly call: RemoteCallable<T>;\n replace(messenger: MessageEndpoint): void;\n expose(api: Record<string, AnyFunction | undefined>): void;\n callable(...methods: string[]): void;\n terminate(): void;\n}\n\n/**\n * An endpoint wraps around a messenger, acting as the intermediary for all\n * messages both send from, and received by, that messenger. The endpoint sends\n * all messages as arrays, where the first element is the message type, and the\n * second is the arguments for that message (as an array). For messages that send\n * meaningful content across the wire (e.g., arguments to function calls, return\n * results), the endpoint first encodes these values.\n *\n * Encoding is done using a CBOR-like encoding scheme. The value is encoded into\n * an array buffer, and is paired with an additional array buffer that contains all\n * the strings used in that message (in the encoded value, strings are encoded as\n * their index in the \"strings\" encoding to reduce the cost of heavily-duplicated\n * strings, which is more likely in payloads containing UI). This encoding also takes\n * care of encoding functions: it uses a \"tagged\" item in CBOR to represent a\n * function as a string ID, which the opposite endpoint will be capable of turning\n * into a consistent, memory-manageable function proxy.\n *\n * The main CBOR encoding is entirely take from the [cbor.js package](https://github.com/paroga/cbor-js).\n * The special behavior for encoding strings and functions was then added in to the\n * encoder and decoder. For additional details on CBOR:\n *\n * @see https://tools.ietf.org/html/rfc7049\n */\nexport function createEndpoint<TState, TActions extends ActionsConfig<TState>>(\n messenger: MessageEndpoint,\n stateGetter: () => TState,\n actions: TActions,\n setState?: SetStateFunction<TState>,\n encodingStrategy?: EncodingStrategy\n): RemoteCallable<TActions> {\n const callbacks = new Map<number, (result: unknown) => void>();\n const retainedObjects = new Map<string, Set<Retainer>>();\n\n // Create logger - will be used in Service Worker or Agent context based on the messenger's context\n const contextPrefix = messenger.context?.isServiceWorker ? \"Core\" : \"Agent\";\n const logger = Logger.forContext(`${contextPrefix}:RPC`);\n\n // If we have agent info, set the tag\n if (messenger.context?.agentInfo) {\n logger.setTag(getAgentTag(messenger.context.agentInfo));\n }\n\n messenger.addEventListener(\"message\", (event) => {\n logger.debug(\"Message received:\", event);\n const [id, message] = event.data as [number, RPCMessage];\n\n if (\"call\" in message && \"args\" in message.call) {\n logger.debug(\"Processing call message:\", message);\n const callMessage = message.call;\n const { id: callId, args, target } = callMessage;\n const action = actions[callId];\n if (!action) {\n messenger.postMessage([\n id,\n {\n error: { id: callId, error: \"Action not found\", target },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n return;\n }\n\n try {\n if (action.validate) {\n action.validate(...args);\n }\n\n // Ensure we have a target - if not provided, we need to handle this case\n if (!target) {\n messenger.postMessage([\n id,\n {\n error: {\n id: callId,\n error: \"No target provided for action call\",\n target,\n },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n return;\n }\n\n const currentState = stateGetter();\n logger.debug(\"Executing action with most current state:\", currentState);\n\n // Handle both synchronous and asynchronous results\n Promise.resolve(\n action.handler(currentState, setState!, target, ...args)\n ).then(\n (result: unknown) => {\n logger.debug(\"Action handler result:\", {\n result,\n target,\n });\n messenger.postMessage([\n id,\n { result: { id: callId, result, target } },\n ] as [number, ResultMessage]);\n },\n (error: Error) => {\n messenger.postMessage([\n id,\n {\n error: { id: callId, error: error.message, target },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n }\n );\n } catch (error) {\n if (error instanceof Error) {\n messenger.postMessage([\n id,\n { error: { id: callId, error: error.message, target } },\n ] as [number, ErrorMessage]);\n } else {\n messenger.postMessage([\n id,\n {\n error: { id: callId, error: \"Unknown error occurred\", target },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n }\n }\n } else if (\"result\" in message) {\n const resultMessage = message.result;\n const callback = callbacks.get(id);\n if (callback) {\n callback(resultMessage.result);\n callbacks.delete(id);\n }\n } else if (\"error\" in message) {\n const errorMessage = message.error;\n const callback = callbacks.get(id);\n if (callback) {\n callback(Promise.reject(new Error(errorMessage.error)));\n callbacks.delete(id);\n }\n } else if (\"release\" in message) {\n const releaseMessage = message.release;\n const retainers = retainedObjects.get(releaseMessage.id);\n if (retainers) {\n retainers.clear();\n retainedObjects.delete(releaseMessage.id);\n }\n }\n });\n\n const proxy = new Proxy({} as RemoteCallable<TActions>, {\n get(_, prop: string) {\n return (...args: unknown[]) => {\n const id = Math.random();\n return new Promise((resolve, reject) => {\n callbacks.set(id, (result) => {\n if (result instanceof Promise) {\n result.then(resolve, reject);\n } else {\n resolve(result);\n }\n });\n messenger.postMessage([id, { call: { id: prop, args } }] as [\n number,\n CallMessage\n ]);\n });\n };\n },\n });\n\n return proxy;\n}\n\nfunction defaultUuid() {\n return `${uuidSegment()}-${uuidSegment()}-${uuidSegment()}-${uuidSegment()}`;\n}\n\nfunction uuidSegment() {\n return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16);\n}\n\nfunction createCallable<T>(\n handlerForCall: (\n property: string | number | symbol\n ) => AnyFunction | undefined,\n callable?: (keyof T)[]\n): RemoteCallable<T> {\n let call: any;\n\n if (callable == null) {\n if (typeof Proxy !== \"function\") {\n throw new Error(\n `You must pass an array of callable methods in environments without Proxies.`\n );\n }\n\n const cache = new Map<string | number | symbol, AnyFunction | undefined>();\n\n call = new Proxy(\n {},\n {\n get(_target, property) {\n if (cache.has(property)) {\n return cache.get(property);\n }\n\n const handler = handlerForCall(property);\n cache.set(property, handler);\n return handler;\n },\n }\n );\n } else {\n call = {};\n\n for (const method of callable) {\n Object.defineProperty(call, method, {\n value: handlerForCall(method),\n writable: false,\n configurable: true,\n enumerable: true,\n });\n }\n }\n\n return call;\n}\n", "import {\n ConfigItem,\n DerivedState,\n StateSubscriber,\n ConnectReturn,\n UseCrann,\n ConnectionStatus,\n StateChangeUpdate,\n ActionDefinition,\n AnyConfig,\n isStateItem,\n isActionItem,\n StateChanges,\n} from \"./model/crann.model\";\nimport { AgentInfo, connect as connectPorter } from \"porter-source\";\nimport { createCrannRPCAdapter } from \"./rpc/adapter\";\nimport { Logger } from \"./utils/logger\";\nimport { getAgentTag } from \"./utils/agent\";\n\nlet connectionStatus: ConnectionStatus = { connected: false };\nlet crannInstance: unknown = null;\n\n// Callbacks for disconnect/reconnect events\nconst disconnectCallbacks = new Set<() => void>();\nconst reconnectCallbacks = new Set<(info: AgentInfo) => void>();\n\nexport function connect<TConfig extends AnyConfig>(\n config: TConfig,\n options?: { context?: string; debug?: boolean }\n): ConnectReturn<TConfig> {\n const debug = options?.debug || false;\n const context = options?.context;\n\n // Set up logger\n if (debug) {\n Logger.setDebug(true);\n }\n const logger = Logger.forContext(\"Agent\");\n\n let _myInfo: AgentInfo;\n let _myTag = \"unset\";\n const readyCallbacks = new Set<(info: ConnectionStatus) => void>();\n\n logger.log(\n \"Initializing Crann Agent\" + (context ? ` with context: ${context}` : \"\")\n );\n if (crannInstance && connectionStatus.connected) {\n logger.log(\"We had an instance already and it's connected, returning\");\n\n logger.log(\"Connect, calling onReady callback\");\n setTimeout(() => {\n readyCallbacks.forEach((callback) => callback(connectionStatus));\n }, 0);\n return crannInstance as ConnectReturn<TConfig>;\n }\n\n if (crannInstance && !connectionStatus.connected) {\n logger.log(\"We had an instance but it's disconnected, creating new connection\");\n // Reset the instance to allow reconnection\n crannInstance = null;\n }\n\n logger.log(\"No existing instance, creating a new one\");\n const porter = connectPorter({\n namespace: \"crann\",\n debug: false,\n });\n\n logger.log(\"Porter connection created\");\n\n // Handle Porter disconnect/reconnect events\n porter.onDisconnect(() => {\n logger.log(\"Porter connection lost, updating connection status\");\n connectionStatus = { connected: false };\n \n // Notify disconnect callbacks\n disconnectCallbacks.forEach((callback) => {\n try {\n callback();\n } catch (error) {\n logger.error(\"Error in disconnect callback:\", error);\n }\n });\n \n // Notify onReady callbacks about disconnection\n readyCallbacks.forEach((callback) => {\n try {\n callback(connectionStatus);\n } catch (error) {\n logger.error(\"Error in onReady callback during disconnect:\", error);\n }\n });\n });\n\n porter.onReconnect((info: AgentInfo) => {\n logger.log(\"Porter reconnected, updating connection status\", info);\n connectionStatus = { connected: true, agent: info };\n \n // Update agent info\n _myInfo = info;\n _myTag = getAgentTag(info);\n logger.setTag(_myTag);\n \n // Notify reconnect callbacks\n reconnectCallbacks.forEach((callback) => {\n try {\n callback(info);\n } catch (error) {\n logger.error(\"Error in reconnect callback:\", error);\n }\n });\n \n // Notify onReady callbacks about reconnection\n readyCallbacks.forEach((callback) => {\n try {\n callback(connectionStatus);\n } catch (error) {\n logger.error(\"Error in onReady callback during reconnect:\", error);\n }\n });\n });\n\n // Initialize RPC with empty actions since this is the client side\n const actions = Object.entries(config)\n .filter(([_, value]) => isActionItem(value))\n .reduce<\n Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>>\n >((acc, [key, value]) => {\n const action = value as ActionDefinition<\n DerivedState<TConfig>,\n any[],\n any\n >;\n return {\n ...acc,\n [key]: {\n type: \"action\",\n handler: action.handler,\n validate: action.validate,\n },\n };\n }, {});\n\n const rpcEndpoint = createCrannRPCAdapter(\n () => getDerivedState(config),\n actions,\n porter\n );\n\n let initialStateReceived = false;\n\n porter.on({\n initialState: (message) => {\n logger.log(\"initialState received\", {\n alreadyReceived: initialStateReceived,\n payload: message.payload,\n });\n\n if (initialStateReceived) {\n logger.log(\"Ignoring duplicate initialState message\");\n return;\n }\n\n initialStateReceived = true;\n\n _state = message.payload.state;\n _myInfo = message.payload.info;\n _myTag = getAgentTag(_myInfo);\n connectionStatus = { connected: true, agent: _myInfo };\n\n // Update logger with the agent tag once we have it\n logger.setTag(_myTag);\n logger.log(\n `Initial state received and ${listeners.size} listeners notified`,\n {\n message,\n }\n );\n readyCallbacks.forEach((callback) => {\n logger.log(\"Calling onReady callbacks\");\n callback(connectionStatus);\n });\n listeners.forEach((listener) => {\n listener.callback(_state as StateChanges<TConfig>);\n });\n },\n stateUpdate: (message) => {\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n logger.log(\"State updated:\", { message, changes, _state });\n if (!changes) return;\n\n listeners.forEach((listener) => {\n if (listener.keys === undefined) {\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some((key) => key in changes!);\n if (matchFound) {\n listener.callback(changes!);\n }\n }\n });\n },\n });\n logger.log(\"Porter connected. Setting up state and listeners\");\n let _state = getDerivedState(config);\n let changes: StateChanges<TConfig> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n\n logger.log(\"Completed setup, returning instance\");\n\n const get = () => _state;\n const set = (newState: StateChanges<TConfig>) => {\n logger.log(\"Calling post with setState\", newState);\n porter.post({ action: \"setState\", payload: { state: newState } });\n };\n\n const subscribe = (\n callback: (changes: StateChanges<TConfig>) => void,\n keys?: Array<keyof DerivedState<TConfig>>\n ): (() => void) => {\n const listener = { keys, callback };\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n const useCrann: UseCrann<TConfig> = <K extends keyof DerivedState<TConfig>>(\n key: K\n ) => {\n const getValue = () => {\n const value = get()[key];\n return value as TConfig[K] extends ConfigItem<any>\n ? TConfig[K][\"default\"]\n : never;\n };\n\n const setValue = (\n value: TConfig[K] extends ConfigItem<any> ? TConfig[K][\"default\"] : never\n ) => set({ [key]: value } as StateChanges<TConfig>);\n\n const subscribeToChanges = (\n callback: (update: StateChangeUpdate<TConfig, K>) => void\n ) => {\n let previousValue = getValue();\n\n return subscribe(\n (changes) => {\n if (key in changes) {\n const currentValue = getValue();\n const fullState = get();\n callback({\n current: currentValue,\n previous: previousValue,\n state: fullState,\n } as StateChangeUpdate<TConfig, K>);\n previousValue = currentValue;\n }\n },\n [key]\n );\n };\n\n return [getValue(), setValue, subscribeToChanges];\n };\n\n const onReady = (callback: (info: ConnectionStatus) => void) => {\n logger.log(\"onReady callback added\");\n readyCallbacks.add(callback);\n if (connectionStatus.connected) {\n logger.log(\"calling onReady callback\");\n setTimeout(() => {\n callback(connectionStatus);\n }, 0);\n }\n return () => readyCallbacks.delete(callback);\n };\n\n const getAgentInfo = () => _myInfo;\n\n const callAction = async (name: string, ...args: any[]) => {\n logger.log(\"Calling action\", name, args);\n return (rpcEndpoint as any)[name](...args);\n };\n\n const onDisconnect = (callback: () => void): (() => void) => {\n logger.log(\"onDisconnect callback added\");\n disconnectCallbacks.add(callback);\n return () => {\n disconnectCallbacks.delete(callback);\n };\n };\n\n const onReconnect = (callback: (info: AgentInfo) => void): (() => void) => {\n logger.log(\"onReconnect callback added\");\n reconnectCallbacks.add(callback);\n return () => {\n reconnectCallbacks.delete(callback);\n };\n };\n\n const instance = {\n useCrann,\n get,\n set,\n subscribe,\n getAgentInfo,\n onReady,\n callAction,\n onDisconnect,\n onReconnect,\n };\n\n crannInstance = instance;\n\n return crannInstance as ConnectReturn<TConfig>;\n}\n\nexport function connected(): boolean {\n return crannInstance !== null;\n}\n\nfunction getDerivedState<TConfig extends AnyConfig>(\n config: TConfig\n): DerivedState<TConfig> {\n const state: any = {};\n Object.keys(config).forEach((key) => {\n const item = config[key];\n if (isStateItem(item)) {\n state[key] = item.default;\n }\n });\n return state;\n}\n", "import { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport {\n AnyConfig,\n ConfigItem,\n DerivedState,\n StateChanges,\n StateUpdate,\n} from \"../model/crann.model\";\nimport { connect } from \"../crannAgent\";\n\nexport function createCrannStateHook<TConfig extends AnyConfig>(\n config: TConfig\n) {\n return function useCrannState(context?: string) {\n const { useCrann, get, set, subscribe, callAction } = useMemo(() => {\n const instance = connect(config);\n return instance;\n }, [context]);\n\n const useStateItem = useCallback(\n <K extends keyof DerivedState<TConfig>>(key: K) => {\n const [value, setValue] = useState<DerivedState<TConfig>[K]>(\n get()[key]\n );\n const valueRef = useRef(value);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n setValue(get()[key]);\n const unsubscribe = subscribe(\n (changes: StateUpdate<TConfig>) => {\n if (key in changes) {\n setValue(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n return unsubscribe;\n }, [key]);\n\n const updateValue = useCallback(\n (newValue: DerivedState<TConfig>[K]) => {\n set({ [key]: newValue } as StateChanges<TConfig>);\n },\n [key]\n );\n\n return [value, updateValue] as const;\n },\n [get, set, subscribe]\n );\n\n const getState = useCallback(() => get(), [get]);\n\n const setState = useCallback(\n (newState: StateChanges<TConfig>) => {\n set(newState);\n },\n [set]\n );\n\n return {\n useStateItem,\n getState,\n setState,\n useCrann,\n callAction,\n };\n };\n}\n", "import { AnyConfig } from \"../model/crann.model\";\n\nexport function createConfig<T extends AnyConfig>(config: T): T {\n return config;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["browser", "Partition", "Persistence", "isStateItem", "item", "isActionItem", "source", "deepEqual", "a", "b", "keysA", "keysB", "i", "key", "_DebugManager", "value", "DebugManager", "isDebugEnabled", "trackStateChange", "target", "propertyKey", "descriptor", "originalMethod", "args", "_a", "isDebugEnabled", "stack", "callerMatch", "caller", "changes", "metadata", "
|
|
3
|
+
"sources": ["../../src/crann.ts", "../../src/model/crann.model.ts", "../../src/transport/core/PorterSource.ts", "../../src/transport/porter.model.ts", "../../src/transport/porter.utils.ts", "../../src/transport/managers/AgentManager.ts", "../../src/transport/managers/ConnectionManager.ts", "../../src/transport/managers/MessageHandler.ts", "../../src/transport/managers/AgentConnectionManager.ts", "../../src/transport/managers/MessageQueue.ts", "../../src/transport/managers/AgentMessageHandler.ts", "../../src/transport/core/PorterAgent.ts", "../../src/transport/react/usePorter.ts", "../../src/utils/deepEqual.ts", "../../src/utils/debug.ts", "../../src/utils/tracking.ts", "../../src/utils/logger.ts", "../../src/utils/agent.ts", "../../src/rpc/endpoint.ts", "../../src/rpc/adapter.ts", "../../src/crannAgent.ts", "../../src/hooks/useCrannState.ts", "../../src/utils/config.ts"],
|
|
4
|
+
"sourcesContent": ["import browser from \"webextension-polyfill\";\nimport {\n DerivedInstanceState,\n DerivedServiceState,\n ConfigItem,\n DerivedState,\n Partition,\n CrannOptions,\n ActionDefinition,\n AnyConfig,\n isStateItem,\n isActionItem,\n SetStateCallback,\n SetStateFunction,\n StateChangeListener,\n StateChanges,\n MergeStateTypes,\n} from \"./model/crann.model\";\nimport { AgentInfo, source, Agent, BrowserLocation } from \"./transport\";\nimport { deepEqual } from \"./utils/deepEqual\";\nimport { trackStateChange } from \"./utils/tracking\";\nimport { DebugManager } from \"./utils/debug\";\nimport { createCrannRPCAdapter } from \"./rpc/adapter\";\nimport { Logger } from \"./utils/logger\";\nimport { getAgentTag } from \"./utils/agent\";\n\nexport class Crann<TConfig extends AnyConfig> {\n private static instance: Crann<any> | null = null;\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultServiceState: DerivedServiceState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private serviceState: DerivedServiceState<TConfig>;\n private stateChangeListeners: Array<StateChangeListener<TConfig>> = [];\n private instanceReadyListeners: Array<\n (instanceId: string, agent: AgentInfo) => void\n > = [];\n private storagePrefix = \"crann_\";\n private porter = source(\"crann\", { debug: false });\n private rpcEndpoint: ReturnType<typeof createCrannRPCAdapter>;\n private logger: Logger;\n\n constructor(private config: TConfig, options?: CrannOptions) {\n // Set the debug flag globally\n if (options?.debug) {\n DebugManager.setDebug(true);\n Logger.setDebug(true);\n }\n this.storagePrefix = options?.storagePrefix ?? this.storagePrefix;\n\n // Set up the core logger\n this.logger = Logger.forContext(\"Core\");\n this.logger.log(\"Constructing Crann with new logger\");\n\n // Hydrate the initial state from the config defaults and from storage\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultServiceState = this.serviceState =\n this.initializeServiceDefault();\n this.hydrate();\n\n // Set up the message handlers\n this.logger.log(\"Crann constructed, setting initial message handlers\");\n this.porter.on({\n setState: (message, info) => {\n if (!info) {\n this.logger.warn(\"setState message heard from unknown agent\");\n return;\n }\n\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"Setting state:\", message);\n this.set(message.payload.state, info.id);\n },\n });\n\n // Track which agents we've already sent initialState to\n const agentsInitialized = new Set<string>();\n\n // Once the agents are connected and have set up their listeners, send them the initial state\n this.porter.onMessagesSet((info: AgentInfo) => {\n if (!info) {\n this.logger.error(\"Messages set but no agent info.\", { info });\n return;\n }\n\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"onMessagesSet received for agent:\", {\n id: info.id,\n context: info.location.context,\n tabId: info.location.tabId,\n frameId: info.location.frameId,\n alreadyInitialized: agentsInitialized.has(info.id),\n });\n\n // Skip sending initialState if we've already sent it to this agent\n if (agentsInitialized.has(info.id)) {\n this.logger\n .withTag(agentTag)\n .log(\"Already sent initialState to agent, skipping:\", info.id);\n return;\n }\n\n // Add the agent to the set of agents we've already sent initialState to\n agentsInitialized.add(info.id);\n\n this.logger\n .withTag(agentTag)\n .log(\"Messages set received. Sending initial state.\", { info });\n const fullState = this.get(info.id);\n this.porter.post(\n {\n action: \"initialState\",\n payload: { state: fullState, info },\n },\n info.location\n );\n\n this.notifyInstanceReady(info.id, info);\n });\n\n // Handle agent connection and disconnection\n this.porter.onConnect((info: AgentInfo) => {\n if (!info) {\n this.logger.error(\"Agent connected but no agent info.\", { info });\n return;\n }\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"Agent connected\", { info });\n this.addInstance(info.id, agentTag);\n this.porter.onDisconnect((info: AgentInfo) => {\n this.logger\n .withTag(getAgentTag(info))\n .log(\n \"Agent disconnect heard. Connection type, context and location:\",\n { info }\n );\n this.removeInstance(info.id);\n });\n });\n\n const setStateCallback: SetStateCallback<TConfig> = ((\n state: any,\n key?: string\n ) => {\n if (key !== undefined) {\n return this.set(state, key);\n } else {\n return this.set(state);\n }\n }) as SetStateCallback<TConfig>;\n\n // Cast to the generic version when passing to RPC adapter\n const genericSetState = setStateCallback as SetStateFunction<\n DerivedState<TConfig>\n >;\n\n // Initialize RPC with actions\n const actions = this.extractActions(config);\n\n const stateGetter = () => {\n const currentState = this.get();\n this.logger.log(\n \"State getter called, returning current state:\",\n currentState\n );\n return currentState;\n };\n\n this.rpcEndpoint = createCrannRPCAdapter(\n stateGetter,\n actions,\n this.porter,\n genericSetState\n );\n }\n\n public static getInstance<TConfig extends AnyConfig>(\n config: TConfig,\n options?: CrannOptions\n ): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, options);\n } else if (options?.debug) {\n const logger = Logger.forContext(\"Core\");\n logger.log(\"Instance requested and already existed, returning\");\n }\n return Crann.instance;\n }\n\n /**\n * Add an instance to the Crann instance.\n * @param key The key of the instance to add.\n * @param agentTag The tag of the agent that is adding the instance, for logging.\n */\n private async addInstance(key: string, agentTag: string): Promise<void> {\n if (!this.instances.has(key)) {\n this.logger.withTag(agentTag).log(\"Adding instance from agent key\");\n const initialInstanceState = {\n ...this.defaultInstanceState,\n } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n this.logger\n .withTag(agentTag)\n .log(\"Instance was already registered, ignoring request from key\");\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.logger.withTag(key).log(\"Remove instance requested\");\n this.instances.delete(key);\n } else {\n this.logger\n .withTag(key)\n .log(\"Remove instance requested but it did not exist!\");\n }\n }\n\n @trackStateChange\n public async setServiceState(\n state: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.logger.log(\"Request to set service state with update:\", state);\n this.logger.log(\"Existing service state was \", this.serviceState);\n const update = { ...this.serviceState, ...state };\n if (!deepEqual(this.serviceState, update)) {\n this.logger.log(\n \"Confirmed new state was different than existing so proceeding to persist then notify all connected instances.\"\n );\n this.serviceState = update;\n await this.persist(state);\n this.notify(state as StateChanges<TConfig>);\n } else {\n this.logger.log(\"New state seems to be the same as existing, skipping\");\n }\n }\n\n @trackStateChange\n public async setInstanceState(\n key: string,\n state: Partial<DerivedInstanceState<TConfig>>\n ): Promise<void> {\n this.logger\n .withTag(key)\n .log(\"Request to update instance state, update:\", state);\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.logger\n .withTag(key)\n .log(\"Instance state update is different, updating and notifying.\");\n this.instances.set(key, update);\n this.notify(state as StateChanges<TConfig>, key);\n } else {\n this.logger\n .withTag(key)\n .log(\"Instance state update is not different, skipping update.\");\n }\n }\n\n // If we pass in specific state to persist, it only persists that state.\n // Otherwise persists all of the worker state.\n private async persist(\n state?: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.logger.log(\"Persisting state\");\n let wasPersisted = false;\n for (const key in state || this.serviceState) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || \"none\";\n const value = state\n ? state[key as keyof DerivedServiceState<TConfig>]\n : this.serviceState[key];\n switch (persistence) {\n case \"session\":\n await browser.storage.session.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n case \"local\":\n await browser.storage.local.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n default:\n break;\n }\n }\n if (wasPersisted) {\n this.logger.log(\"State was persisted\");\n } else {\n this.logger.log(\"Nothing to persist\");\n }\n }\n\n public async clear(): Promise<void> {\n this.logger.log(\"Clearing state\");\n this.serviceState = this.defaultServiceState;\n this.instances.forEach((_, key) => {\n this.instances.set(key, this.defaultInstanceState);\n });\n await this.persist();\n this.notify({} as StateChanges<TConfig>);\n }\n\n public subscribe(listener: StateChangeListener<TConfig>): void {\n this.logger.log(\"Subscribing to state\");\n this.stateChangeListeners.push(listener);\n }\n\n // Right now we notify the instance even if the state change came from the instance.\n // This should probably be skipped for instance state, since it already knows.\n private notify(changes: StateChanges<TConfig>, key?: string): void {\n const agent = key ? this.porter.getAgentById(key) : undefined;\n const state = key ? this.get(key) : this.get();\n\n if (this.stateChangeListeners.length > 0) {\n this.logger.log(\"Notifying state change listeners in source\");\n this.stateChangeListeners.forEach((listener) => {\n listener(state, changes, agent?.info);\n });\n }\n\n if (key && agent?.info.location) {\n this.logger.withTag(key).log(\"Notifying of state change.\");\n this.porter.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n agent.info.location\n );\n } else {\n this.logger.log(\"Notifying everyone\");\n // for every key of this.instances, post the state update to the corresponding key\n this.instances.forEach((_, key) => {\n this.porter.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n key\n );\n });\n }\n }\n\n public get(): DerivedState<TConfig>;\n public get(\n key: string\n ): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n public get(\n key?: string\n ): DerivedServiceState<TConfig> | DerivedState<TConfig> {\n if (!key) {\n return { ...this.serviceState, ...({} as DerivedInstanceState<TConfig>) };\n }\n return { ...this.serviceState, ...this.instances.get(key) };\n }\n\n // Todo: Should we return the instance data? What is the point of this.\n public findInstance(location: BrowserLocation): string | null {\n const agent = this.porter.getAgentByLocation(location);\n if (!agent) {\n this.logger.log(\"Could not find agent for location:\", { location });\n return null;\n }\n for (const [key, instance] of this.instances) {\n if (key === agent.info.id) {\n this.logger.log(\"Found instance for key:\", key);\n return key;\n }\n }\n this.logger.log(\"Could not find instance for context and location:\", {\n location,\n });\n return null;\n }\n\n // Convenience re-export of the porter-source queryAgents method.\n public queryAgents(query: Partial<BrowserLocation>): Agent[] {\n return this.porter.queryAgents(query);\n }\n\n public async set(state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n public async set(\n state: Partial<\n MergeStateTypes<\n DerivedInstanceState<TConfig>,\n DerivedServiceState<TConfig>\n >\n >,\n key: string\n ): Promise<void>;\n public async set(\n state:\n | Partial<DerivedServiceState<TConfig>>\n | Partial<\n MergeStateTypes<\n DerivedInstanceState<TConfig>,\n DerivedServiceState<TConfig>\n >\n >,\n key?: string\n ): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedServiceState<TConfig>>;\n\n for (const itemKey in state) {\n const item = this.config[itemKey as keyof TConfig];\n if (isConfigItem(item)) {\n if (item.partition === \"instance\") {\n const instanceItemKey =\n itemKey as keyof DerivedInstanceState<TConfig>;\n const instanceState = state as Partial<DerivedInstanceState<TConfig>>;\n instance[instanceItemKey] = instanceState[instanceItemKey];\n } else if (!item.partition || item.partition === Partition.Service) {\n const serviceItemKey = itemKey as keyof DerivedServiceState<TConfig>;\n const serviceState = state as Partial<DerivedServiceState<TConfig>>;\n worker[serviceItemKey] = serviceState[serviceItemKey]!;\n }\n }\n }\n\n if (key && Object.keys(instance).length > 0) {\n this.logger.withTag(key).log(\"Setting instance state:\", instance);\n this.setInstanceState(key, instance);\n }\n if (Object.keys(worker).length > 0) {\n this.logger.log(\"Setting service state:\", worker);\n this.setServiceState(worker);\n }\n }\n\n private async hydrate(): Promise<void> {\n this.logger.log(\"Hydrating state from storage.\");\n const local = await browser.storage.local.get(null);\n const session = await browser.storage.session.get(null);\n const combined = { ...local, ...session };\n\n this.logger.log(\"Storage data is:\", { local, session, combined });\n\n const update: Partial<DerivedServiceState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\n let hadItems = false;\n for (const prefixedKey in combined) {\n const key = this.removePrefix(prefixedKey);\n this.logger.log(`Checking storage key ${prefixedKey} -> ${key}`);\n\n if (this.config.hasOwnProperty(key)) {\n const value = combined[prefixedKey];\n\n this.logger.log(`Found storage value for ${key}:`, value);\n update[key as keyof DerivedServiceState<TConfig>] = value;\n hadItems = true;\n }\n }\n if (hadItems) {\n this.logger.log(\"Hydrated some items.\");\n } else {\n this.logger.log(\"No items found in storage.\");\n }\n this.serviceState = { ...this.defaultServiceState, ...update };\n }\n\n private removePrefix(key: string): string {\n if (key.startsWith(this.storagePrefix)) {\n return key.replace(this.storagePrefix, \"\");\n }\n return key;\n }\n\n private initializeInstanceDefault(): DerivedInstanceState<TConfig> {\n const instanceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item = this.config[key];\n if (isStateItem(item) && item.partition === \"instance\") {\n instanceState[key] = item.default;\n }\n });\n return instanceState;\n }\n\n private initializeServiceDefault(): DerivedServiceState<TConfig> {\n this.logger.log(\"Initializing service default state\");\n this.logger.log(\"Config is:\", this.config);\n\n const serviceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item = this.config[key];\n this.logger.log(\"Item is:\", item);\n if (\n isStateItem(item) &&\n (!item.partition || item.partition === Partition.Service)\n ) {\n serviceState[key] = item.default;\n this.logger.log(\n \"Setting service state for key:\",\n key,\n \"to\",\n item.default\n );\n }\n });\n this.logger.log(\"Final service state is:\", serviceState);\n return serviceState;\n }\n\n public subscribeToInstanceReady(\n listener: (instanceId: string, agent: AgentInfo) => void\n ): () => void {\n this.logger.log(\"Subscribing to instance ready events\");\n this.instanceReadyListeners.push(listener);\n\n this.instances.forEach((_, instanceId) => {\n const agent = this.porter.getAgentById(instanceId);\n if (agent?.info) {\n listener(instanceId, agent.info);\n }\n });\n\n return () => {\n this.logger.log(\"Unsubscribing from instance ready events\");\n const index = this.instanceReadyListeners.indexOf(listener);\n if (index !== -1) {\n this.instanceReadyListeners.splice(index, 1);\n }\n };\n }\n\n private notifyInstanceReady(instanceId: string, info: AgentInfo): void {\n if (this.instanceReadyListeners.length > 0) {\n const agentTag = getAgentTag(info);\n this.logger.withTag(agentTag).log(\"Notifying instance ready listeners\");\n this.instanceReadyListeners.forEach((listener) => {\n listener(instanceId, info);\n });\n }\n }\n\n private extractActions(\n config: TConfig\n ): Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>> {\n return Object.entries(config)\n .filter(([_, value]) => isActionItem(value))\n .reduce<\n Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>>\n >((acc, [key, value]) => {\n const action = value as ActionDefinition<\n DerivedState<TConfig>,\n any[],\n any\n >;\n return {\n ...acc,\n [key]: action,\n };\n }, {});\n }\n}\n\n// Define an interface for the API returned by create()\nexport interface CrannAPI<TConfig extends AnyConfig> {\n get: {\n (): DerivedState<TConfig>;\n (key: string): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n };\n set: {\n (state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n (\n state: Partial<\n MergeStateTypes<\n DerivedInstanceState<TConfig>,\n DerivedServiceState<TConfig>\n >\n >,\n key: string\n ): Promise<void>;\n };\n subscribe: (listener: StateChangeListener<TConfig>) => void;\n onInstanceReady: (\n listener: (instanceId: string, agent: AgentInfo) => void\n ) => () => void;\n findInstance: (location: BrowserLocation) => string | null;\n queryAgents: (query: Partial<BrowserLocation>) => Agent[];\n clear: () => Promise<void>;\n}\n\nexport function create<TConfig extends AnyConfig>(\n config: TConfig,\n options?: CrannOptions\n): CrannAPI<TConfig> {\n const instance = Crann.getInstance(config, options);\n\n return {\n get: instance.get.bind(instance),\n set: instance.set.bind(instance),\n subscribe: instance.subscribe.bind(instance),\n onInstanceReady: instance.subscribeToInstanceReady.bind(instance),\n findInstance: instance.findInstance.bind(instance),\n queryAgents: instance.queryAgents.bind(instance),\n clear: instance.clear.bind(instance),\n };\n}\n\nfunction isConfigItem(item: any): item is ConfigItem<any> {\n return item && typeof item === \"object\" && \"default\" in item;\n}\n", "import { AgentInfo, BrowserLocation } from \"../transport\";\n\nexport const Partition = {\n Instance: \"instance\" as const,\n Service: \"service\" as const,\n};\n\nexport const Persistence = {\n Session: \"session\" as const,\n Local: \"local\" as const,\n None: \"none\" as const,\n};\n\nexport type ActionHandler<TState, TArgs extends any[], TResult> = (\n state: TState,\n setState: SetStateFunction<TState>,\n target: BrowserLocation,\n ...args: TArgs\n) => Promise<TResult>;\n\nexport type ActionDefinition<TState, TArgs extends any[], TResult> = {\n handler: ActionHandler<TState, TArgs, TResult>;\n validate?: (...args: TArgs) => void;\n};\n\nexport type ActionsConfig<TState> = {\n [K: string]: ActionDefinition<TState, any[], Partial<TState>>;\n};\n\n// The following \"SetState\" types are used to define the types for the setState function in the RPC adapter.\n// To prevent a cirucular dependency with TConfig, we define a specific and a generic version.\n\n// This is the type that the RPC adapter expects\nexport type SetStateFunction<TState> = {\n (state: Partial<TState>): Promise<void>;\n (state: Partial<TState>, key: string): Promise<void>;\n};\n\n// This is the more specific type that the Crann instance expects\nexport type SetStateCallback<TConfig extends AnyConfig> = {\n (state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n (state: Partial<DerivedInstanceState<TConfig>>, key: string): Promise<void>;\n};\n\n// Input types (what users provide in their config)\nexport type ConfigItem<T> = {\n default: T;\n partition?: (typeof Partition)[keyof typeof Partition];\n persist?: (typeof Persistence)[keyof typeof Persistence];\n};\n\nexport type AnyConfig = Record<\n string,\n ConfigItem<any> | ActionDefinition<any, any[], any>\n>;\n\n// Helper type to extract just the state items from a config\nexport type StateConfig<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<any> ? T[P] : never;\n};\n\n// Helper type to extract just the action items from a config\nexport type ActionConfig<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ActionDefinition<any, any[], any> ? T[P] : never;\n};\n\n// Update DerivedState to use the internal types\nexport type DerivedState<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<infer DefaultType>\n ? DefaultType\n : never;\n};\n\n// Update DerivedInstanceState to use the internal types\nexport type DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<infer DefaultType> & {\n partition: \"instance\";\n }\n ? DefaultType\n : never;\n};\n\n// Update DerivedServiceState to use the internal types\nexport type DerivedServiceState<T extends AnyConfig> = {\n [P in keyof T]: T[P] extends ConfigItem<infer DefaultType>\n ? T[P] extends { partition: \"instance\" }\n ? never\n : DefaultType\n : never;\n};\n\n// Remove never properties from a type\ntype OmitNever<T> = {\n [K in keyof T as T[K] extends never ? never : K]: T[K];\n};\n\n// Merge by taking all non-never properties from both types\nexport type MergeStateTypes<TInstance, TService> = OmitNever<TInstance> &\n OmitNever<TService>;\n\n// Type guards\nexport const isStateItem = <T>(\n item: ConfigItem<T> | ActionDefinition<any, any[], any>\n): item is ConfigItem<T> => {\n return !(\"handler\" in item);\n};\n\nexport const isActionItem = <TState, TArgs extends any[], TResult>(\n item: ConfigItem<any> | ActionDefinition<TState, TArgs, TResult>\n): item is ActionDefinition<TState, TArgs, TResult> => {\n return \"handler\" in item;\n};\n\ntype StateSubscriber<TConfig extends AnyConfig> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n};\n\ntype CrannAgent<TConfig extends AnyConfig> = {\n get: () => DerivedState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (\n callback: (changes: StateUpdate<TConfig>) => void,\n keys?: Array<keyof TConfig>\n ) => () => void;\n getAgentInfo: () => AgentInfo;\n onReady: (callback: (info: ConnectionStatus) => void) => () => void;\n};\n\ntype UseCrann<TConfig extends AnyConfig> = <\n K extends keyof DerivedState<TConfig>\n>(\n key: K\n) => [\n DerivedState<TConfig>[K],\n (value: DerivedState<TConfig>[K]) => void,\n (callback: (update: StateChangeUpdate<TConfig, K>) => void) => () => void\n];\n\ntype ConnectReturn<TConfig extends AnyConfig> = {\n useCrann: UseCrann<TConfig>;\n get: CrannAgent<TConfig>[\"get\"];\n set: CrannAgent<TConfig>[\"set\"];\n subscribe: CrannAgent<TConfig>[\"subscribe\"];\n getAgentInfo: CrannAgent<TConfig>[\"getAgentInfo\"];\n onReady: CrannAgent<TConfig>[\"onReady\"];\n callAction: (name: string, ...args: any[]) => Promise<any>;\n onDisconnect: (callback: () => void) => () => void;\n onReconnect: (callback: (info: AgentInfo) => void) => () => void;\n};\n\nexport type StateChanges<T extends AnyConfig> = {\n [K in keyof DerivedState<T>]?: NonNullable<DerivedState<T>[K]>;\n};\n\ntype StateChangeUpdate<\n TConfig extends AnyConfig,\n K extends keyof DerivedState<TConfig>\n> = {\n current: DerivedState<TConfig>[K];\n previous: DerivedState<TConfig>[K];\n state: DerivedState<TConfig>;\n};\n\nexport type StateChangeListener<TConfig extends AnyConfig> = (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: StateChanges<TConfig>,\n agent?: AgentInfo\n) => void;\n\ntype AgentSubscription<TConfig extends AnyConfig> = {\n (\n callback: (changes: StateUpdate<TConfig>) => void,\n key?: keyof DerivedState<TConfig>\n ): number;\n};\n\ntype StateUpdate<TConfig extends AnyConfig> = StateChanges<TConfig>;\n\nexport type CrannOptions = {\n debug?: boolean;\n storagePrefix?: string;\n};\n\ntype ConnectionStatus = {\n connected: boolean;\n agent?: AgentInfo;\n};\n\nexport type CrannConfig<TState> = {\n [K: string]: ConfigItem<any> | ActionsConfig<TState>;\n};\n\nexport {\n StateSubscriber,\n CrannAgent,\n AgentSubscription,\n StateUpdate,\n DerivedState as State,\n ConnectReturn,\n UseCrann,\n ConnectionStatus,\n StateChangeUpdate,\n};\n", "import browser, { Runtime } from 'webextension-polyfill';\nimport {\n AgentInfo,\n Listener,\n Message,\n MessageConfig,\n PorterError,\n PorterErrorType,\n BrowserLocation,\n Unsubscribe,\n AgentId,\n MessageTarget,\n} from '../porter.model';\nimport { Agent } from '../porter.model';\nimport { isServiceWorker } from '../porter.utils';\nimport { Logger } from '../porter.utils';\nimport { AgentManager } from '../managers/AgentManager';\nimport { ConnectionManager } from '../managers/ConnectionManager';\nimport { MessageHandler } from '../managers/MessageHandler';\n\nexport interface PorterSourceOptions {\n namespace?: string;\n debug?: boolean;\n}\n\nexport class PorterSource {\n private static instances: Map<string, PorterSource> = new Map();\n private readonly agentManager: AgentManager;\n private readonly messageHandler: MessageHandler;\n private readonly connectionManager: ConnectionManager;\n private readonly logger: Logger;\n private static staticLogger = Logger.getLogger('SW');\n private namespace: string;\n\n private constructor(namespace?: string, options?: PorterSourceOptions) {\n // Configure logger if debug option is provided\n if (options?.debug !== undefined) {\n Logger.configure({ enabled: options.debug });\n }\n\n this.logger = Logger.getLogger(`SW`);\n this.namespace = namespace || 'porter';\n if (!namespace) {\n this.logger.error('No namespace provided, defaulting to \"porter\"');\n }\n\n this.agentManager = new AgentManager(this.logger);\n this.messageHandler = new MessageHandler(this.agentManager, this.logger);\n this.connectionManager = new ConnectionManager(\n this.agentManager,\n this.namespace,\n this.logger\n );\n this.logger.info(`Constructing Porter with namespace: ${this.namespace}`);\n\n if (!isServiceWorker()) {\n throw new PorterError(\n PorterErrorType.INVALID_CONTEXT,\n 'Can only create in a service worker'\n );\n }\n\n // Wire up event handlers\n this.agentManager.on(\n 'agentMessage',\n (message: any, metadata: AgentInfo) => {\n this.messageHandler.handleIncomingMessage(message, metadata);\n }\n );\n\n this.agentManager.on('agentDisconnect', (metadata: AgentInfo) => {\n this.messageHandler.handleDisconnect(metadata);\n });\n\n this.agentManager.on('agentSetup', (agent: Agent) => {\n this.logger.debug(`Handling agent setup`, { agent });\n this.messageHandler.handleConnect(agent.info);\n this.connectionManager.confirmConnection(agent);\n });\n\n browser.runtime.onConnect.addListener(\n this.connectionManager.handleConnection.bind(this.connectionManager)\n );\n }\n\n public static getInstance(\n namespace: string = 'porter',\n options?: PorterSourceOptions\n ): PorterSource {\n PorterSource.staticLogger.debug(\n `Getting instance for namespace: ${namespace}`\n );\n if (!PorterSource.instances.has(namespace)) {\n PorterSource.staticLogger.info(\n `Creating new instance for namespace: ${namespace}`\n );\n PorterSource.instances.set(\n namespace,\n new PorterSource(namespace, options)\n );\n } else if (options?.debug !== undefined) {\n // If instance exists but debug setting changed, configure logger\n Logger.configure({ enabled: options.debug });\n }\n return PorterSource.instances.get(namespace)!;\n }\n\n // Public API methods that will be exposed via the source function\n public post(message: Message<any>, target?: MessageTarget): Promise<void> {\n return this.messageHandler.post(message, target);\n }\n\n public onMessage(config: MessageConfig): Unsubscribe {\n return this.messageHandler.onMessage(config);\n }\n\n public on(config: MessageConfig): Unsubscribe {\n return this.messageHandler.on(config);\n }\n\n public onConnect(listener: Listener<'onConnect'>): Unsubscribe {\n return this.messageHandler.onConnect(listener);\n }\n\n public onDisconnect(listener: Listener<'onDisconnect'>): Unsubscribe {\n return this.messageHandler.onDisconnect(listener);\n }\n\n public onMessagesSet(listener: Listener<'onMessagesSet'>): Unsubscribe {\n return this.messageHandler.onMessagesSet(listener);\n }\n\n // Utility methods that might be needed externally\n public getInfo(key: string): AgentInfo | null {\n return this.agentManager.getAgentById(key)?.info || null;\n }\n\n // Utility methods that might be needed externally\n public getAgentById(agentId: AgentId): Agent | null {\n return this.agentManager.getAgentById(agentId);\n }\n\n public getAgentByLocation(location: BrowserLocation): Agent | null {\n return this.agentManager.getAgentByLocation(location);\n }\n\n public queryAgents(location: Partial<BrowserLocation>): Agent[] {\n return this.agentManager.queryAgents(location);\n }\n}\n\nexport interface PorterAPI {\n type: 'source';\n post: (message: Message<any>, target?: MessageTarget) => Promise<void>;\n onMessage: (config: MessageConfig) => Unsubscribe;\n on: (config: MessageConfig) => Unsubscribe;\n onConnect: (listener: Listener<'onConnect'>) => Unsubscribe;\n onDisconnect: (listener: Listener<'onDisconnect'>) => Unsubscribe;\n onMessagesSet: (listener: Listener<'onMessagesSet'>) => Unsubscribe;\n getAgentById: (id: AgentId) => Agent | null;\n getAgentByLocation: (location: BrowserLocation) => Agent | null;\n queryAgents: (location: Partial<BrowserLocation>) => Agent[];\n}\n\nexport function source(\n namespace: string = 'porter',\n options?: PorterSourceOptions\n): PorterAPI {\n const instance = PorterSource.getInstance(namespace, options);\n return {\n type: 'source',\n post: instance.post.bind(instance),\n onMessage: instance.onMessage.bind(instance),\n on: instance.on.bind(instance),\n onConnect: instance.onConnect.bind(instance),\n onDisconnect: instance.onDisconnect.bind(instance),\n onMessagesSet: instance.onMessagesSet.bind(instance),\n getAgentById: instance.getAgentById.bind(instance),\n getAgentByLocation: instance.getAgentByLocation.bind(instance),\n queryAgents: instance.queryAgents.bind(instance),\n };\n}\n", "import browser from 'webextension-polyfill';\n\nexport type AgentId = string;\n\nexport enum PorterContext {\n ContentScript = 'contentscript',\n Extension = 'extension',\n Popup = 'popup',\n Sidepanel = 'sidepanel',\n Devtools = 'devtools',\n Options = 'options',\n Unknown = 'unknown',\n}\n\n// Describes how the connection was established\nexport enum ConnectionType {\n NewTab = 'new-tab',\n NewFrame = 'new-frame',\n Refresh = 'refresh',\n NewExtensionContext = 'new-extension-context',\n}\n\n// export interface AgentLocation {\n// context: PorterContext;\n// tabId?: number;\n// frameId?: number;\n// customIdentifier?: string;\n// }\n\nexport interface AgentInfo {\n id: AgentId;\n location: BrowserLocation;\n createdAt: number;\n lastActiveAt: number;\n}\n\nexport type Agent = {\n port?: browser.Runtime.Port;\n info: AgentInfo;\n};\n\n// export type AgentTarget = {\n// id?: AgentId;\n// context?: PorterContext;\n// location?: AgentLocation;\n// };\n\nexport type BrowserLocation = {\n context: PorterContext;\n tabId: number;\n frameId: number;\n};\n\nexport type MessageTarget =\n | BrowserLocation // Target a specific location\n | PorterContext // Target all agents in a specific context\n | string // Target agent by unique id (advanced)\n | number; // Target a content script by tabId (all frames)\n\nexport type Unsubscribe = () => void;\n\nexport type Message<K extends keyof MessageAction> = {\n action: K;\n target?: MessageTarget;\n payload?: MessageAction[K];\n};\n\nexport type MessageAction = {\n [key: string]: any;\n};\n\nexport type Listener<T extends keyof PorterEvent> = (\n arg: PorterEvent[T]\n) => void;\n\nexport type MessageListener = {\n config: MessageConfig;\n listener: Listener<'onMessage'>;\n};\n\nexport type MessageConfig = {\n [K in keyof MessageAction]: (message: Message<K>, info?: AgentInfo) => void;\n};\n\n// export type GetAgentOptions = {\n// context?: PorterContext;\n// index?: number;\n// subIndex?: number;\n// };\n\nexport interface PorterEvent {\n onConnect: AgentInfo;\n onDisconnect: AgentInfo;\n onMessagesSet: AgentInfo;\n onMessage: AgentInfo & { message: Message<any> };\n}\n\nexport enum PorterErrorType {\n CONNECTION_FAILED = 'connection-failed',\n CONNECTION_TIMEOUT = 'connection-timeout',\n INVALID_TARGET = 'invalid-target',\n MESSAGE_FAILED = 'message-failed',\n INVALID_CONTEXT = 'invalid-context',\n INVALID_PORT = 'invalid-port',\n}\n\nexport class PorterError extends Error {\n constructor(\n public type: PorterErrorType,\n message: string,\n public details?: any\n ) {\n super(message);\n this.name = 'PorterError';\n }\n}\n", "import { Runtime } from 'webextension-polyfill';\n\nfunction isServiceWorker() {\n return (\n typeof ServiceWorkerGlobalScope !== 'undefined' &&\n self instanceof ServiceWorkerGlobalScope\n );\n}\n\nfunction isValidPort(port: Runtime.Port): port is Runtime.Port & {\n sender: Runtime.MessageSender & { tab: { id: number }; frameId: number };\n} {\n return !!port && !!port.sender && isValidSender(port.sender);\n}\n\nfunction isValidSender(\n sender: Runtime.MessageSender\n): sender is Runtime.MessageSender & { tab: { id: number }; frameId: number } {\n return !(\n !sender ||\n !sender.tab ||\n sender.frameId === undefined ||\n sender.tab.id === undefined\n );\n}\n\nexport enum LogLevel {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n TRACE = 4,\n}\n\nexport interface LoggerOptions {\n level?: LogLevel;\n enabled?: boolean;\n}\n\nexport class Logger {\n private static level: LogLevel = Logger.getLevel();\n private static enabled: boolean = false;\n private static instances: Map<string, Logger> = new Map();\n private static globalOptions?: LoggerOptions;\n\n private static getLevel(): LogLevel {\n if (Logger.globalOptions?.level !== undefined) {\n return Logger.globalOptions.level;\n }\n const isProd =\n typeof process !== 'undefined' &&\n (process.env?.NODE_ENV === 'production' ||\n process.env?.PORTER_ENV === 'production');\n return isProd ? LogLevel.WARN : LogLevel.TRACE;\n }\n // Add a configure method to set global options\n static configure(options: LoggerOptions) {\n Logger.globalOptions = options;\n if (options.level !== undefined) {\n Logger.level = options.level;\n }\n if (options.enabled !== undefined) {\n Logger.enabled = options.enabled;\n }\n }\n\n // Factory method to get or create logger instance\n static getLogger(context: string): Logger {\n if (!this.instances.has(context)) {\n this.instances.set(context, new Logger(context));\n }\n return this.instances.get(context)!;\n }\n\n private constructor(private context: string) {}\n\n error(message: string, ...args: any[]) {\n if (!Logger.enabled) return;\n if (Logger.level >= LogLevel.ERROR) {\n console.error(`[Porter:${this.context}] ${message}`, ...args);\n }\n }\n\n warn(message: string, ...args: any[]) {\n if (!Logger.enabled) return;\n if (Logger.level >= LogLevel.WARN) {\n console.warn(`[Porter:${this.context}] ${message}`, ...args);\n }\n }\n\n info(message: string, ...args: any[]) {\n if (!Logger.enabled) return;\n if (Logger.level >= LogLevel.INFO) {\n console.info(`[Porter:${this.context}] ${message}`, ...args);\n }\n }\n\n debug(message: string, ...args: any[]) {\n if (!Logger.enabled) return;\n if (Logger.level >= LogLevel.DEBUG) {\n console.debug(`[Porter:${this.context}] ${message}`, ...args);\n }\n }\n\n trace(message: string, ...args: any[]) {\n if (!Logger.enabled) return;\n if (Logger.level >= LogLevel.TRACE) {\n console.trace(`[Porter:${this.context}] ${message}`, ...args);\n }\n }\n}\n\nexport { isValidPort, isValidSender, isServiceWorker };\n", "import browser, { Runtime } from 'webextension-polyfill';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Agent,\n AgentInfo,\n ConnectionType,\n PorterContext,\n MessageTarget,\n AgentId,\n BrowserLocation,\n} from '../porter.model';\nimport { Logger } from '../porter.utils';\n\nexport interface AgentOperations {\n addAgent(port: Runtime.Port, context?: PorterContext): AgentId | undefined;\n queryAgents(location: Partial<BrowserLocation>): Agent[];\n getAgentById(id: AgentId): Agent | null;\n getAgentsByContext(context: PorterContext): Agent[];\n getAgentByLocation(location: BrowserLocation): Agent | null;\n getAllAgents(): Agent[];\n getAllAgentsInfo(): AgentInfo[];\n hasPort(port: Runtime.Port): boolean;\n removeAgent(agentId: AgentId): void;\n printAgents(): void;\n}\n\nexport interface AgentEventEmitter {\n on(event: 'agentSetup', handler: (agent: Agent) => void): void;\n on(\n event: 'agentMessage',\n handler: (message: any, info: AgentInfo) => void\n ): void;\n on(event: 'agentDisconnect', handler: (info: AgentInfo) => void): void;\n}\n\nexport class AgentManager implements AgentOperations, AgentEventEmitter {\n private agents: Map<AgentId, Runtime.Port> = new Map();\n private agentsInfo: Map<AgentId, AgentInfo> = new Map();\n private eventHandlers: Map<string, Set<Function>> = new Map();\n\n constructor(private logger: Logger) {\n this.eventHandlers.set('agentSetup', new Set());\n this.eventHandlers.set('agentMessage', new Set());\n this.eventHandlers.set('agentDisconnect', new Set());\n }\n\n public addAgent(\n port: Runtime.Port,\n context?: PorterContext\n ): AgentId | undefined {\n this.logger.debug(`Adding agent`, { context, port });\n const connectionSource = this.identifyConnectionSource(port);\n if (!connectionSource) {\n this.logger.error(`Cannot add agent that did not have a sender`);\n return;\n }\n\n const determinedContext = connectionSource.context;\n const tabId = connectionSource.tabId || -1;\n const frameId = connectionSource.frameId || 0;\n\n this.logger.debug(`Determined context for new agent`, {\n determinedContext,\n tabId,\n frameId,\n });\n // Find agents in the same tab or under the same extension context\n const tabAgentsInfo = Array.from(this.agentsInfo.values()).filter(\n (info) => {\n return (\n info.location.context === determinedContext &&\n info.location.tabId === tabId &&\n info.location.frameId === frameId\n );\n }\n );\n\n if (tabAgentsInfo.length > 0) {\n this.logger.debug('Adding agent: Found existing similar agent.', {\n tabAgentsInfo,\n });\n }\n\n const agentId =\n this.getAgentByLocation({ context: determinedContext, tabId, frameId })\n ?.info?.id || (uuidv4() as AgentId);\n\n this.logger.debug(`Adding agent with id: ${agentId}`);\n\n this.agents.set(agentId, port);\n\n const agentInfo: AgentInfo = {\n id: agentId,\n location: { context: determinedContext, tabId, frameId },\n createdAt: Date.now(),\n lastActiveAt: Date.now(),\n };\n this.agentsInfo.set(agentId, agentInfo);\n\n this.logger.debug(`Constructed agent info: ${JSON.stringify(agentInfo)}`);\n port.onMessage.addListener((message: any) =>\n this.emit('agentMessage', message, agentInfo)\n );\n\n const agent: Agent = { port, info: agentInfo };\n port.onDisconnect.addListener(() => {\n this.emit('agentDisconnect', agentInfo);\n this.logger.debug('Agent disconnected, removing from manager. ', {\n agentInfo,\n });\n this.removeAgent(agentId);\n });\n\n this.emit('agentSetup', agent);\n this.logger.debug('Setup complete for adding agent. ', {\n agentInfo,\n });\n return agentId;\n }\n\n public getAgentByLocation(location: BrowserLocation): Agent | null {\n const { context, tabId, frameId } = location;\n\n const infoEntry: [AgentId, AgentInfo] | undefined = Array.from(\n this.agentsInfo.entries()\n ).find(\n ([key, info]) =>\n info.location.context === context &&\n info.location.tabId === tabId &&\n info.location.frameId === frameId\n );\n if (infoEntry === undefined) {\n this.logger.error('No agent found for location. ', {\n location,\n });\n return null;\n }\n const agentId = infoEntry[0];\n let port = this.agents.get(agentId);\n let info = this.agentsInfo.get(agentId);\n if (!port || !info) {\n this.logger.error('No agent found for location. ', {\n location,\n });\n return null;\n }\n return { port, info };\n }\n\n public getAgentsByContext(context: PorterContext): Agent[] {\n let infoForAgents = Array.from(this.agentsInfo.entries()).filter(\n ([key, value]) => value.location.context === context\n );\n return infoForAgents.map(([key, value]) => ({\n port: this.agents.get(key),\n info: value,\n }));\n }\n\n public getAllAgents(): Agent[] {\n let allInfo = Array.from(this.agentsInfo.entries());\n return allInfo.map(([key, value]) => ({\n port: this.agents.get(key),\n info: value,\n }));\n }\n\n public queryAgents(location: Partial<BrowserLocation>): Agent[] {\n let infoForAgents = Array.from(this.agentsInfo.entries()).filter(\n ([key, value]) => {\n const hasContext = location.context\n ? value.location.context === location.context\n : true;\n const hasTabId = location.tabId\n ? value.location.tabId === location.tabId\n : true;\n const hasFrameId = location.frameId\n ? value.location.frameId === location.frameId\n : true;\n return hasContext && hasTabId && hasFrameId;\n }\n );\n return infoForAgents.map(([key, value]) => ({\n port: this.agents.get(key),\n info: value,\n }));\n }\n\n public getAgentById(id: AgentId): Agent | null {\n let port = this.agents.get(id);\n let info = this.agentsInfo.get(id);\n if (!port || !info) {\n this.logger.error('No agent found for agentId. ', {\n id,\n });\n return null;\n }\n return { port, info };\n }\n\n public getAllAgentsInfo(): AgentInfo[] {\n return Array.from(this.agentsInfo.values());\n }\n\n public hasPort(port: Runtime.Port): boolean {\n const matchingPort = Array.from(this.agents.values()).find(\n (p) => p.name === port.name\n );\n return !!matchingPort;\n }\n\n public removeAgent(agentId: AgentId) {\n if (this.agents.has(agentId) && this.agentsInfo.has(agentId)) {\n this.agents.delete(agentId);\n this.agentsInfo.delete(agentId);\n } else {\n this.logger.error('No agent found to remove. ', {\n agentId,\n });\n }\n }\n\n public printAgents() {\n const allAgents = Array.from(this.agents.entries());\n const allAgentsInfo = Array.from(this.agentsInfo.entries());\n this.logger.debug('Current agents:', {\n allAgents,\n allAgentsInfo,\n });\n }\n\n // private isContentScript(port: Runtime.Port) {\n // if (!port.sender) return false;\n // const hasFrame =\n // port.sender.tab &&\n // port.sender.tab.id !== undefined &&\n // port.sender.frameId !== undefined;\n // if (!hasFrame) return false;\n // if (!(port.sender as any).origin) return false;\n\n // const contentPage =\n // !(port.sender as any)!.origin.startsWith('chrome-extension://') &&\n // !(port.sender as any)!.tab!.url?.startsWith('moz-extension://');\n // return contentPage;\n // }\n\n public on(event: string, handler: Function) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.add(handler);\n }\n }\n\n private emit(event: string, ...args: any[]) {\n const handlers = this.eventHandlers.get(event);\n handlers?.forEach((handler) => handler(...args));\n }\n\n private identifyConnectionSource(port: Runtime.Port): {\n context: PorterContext;\n tabId?: number;\n frameId?: number;\n url?: string;\n portName?: string;\n } | null {\n const sender = port.sender;\n if (!sender) {\n this.logger.error(`Cannot add agent that did not have a sender`);\n return null;\n }\n // Cache the manifest data\n const manifest = browser.runtime.getManifest();\n\n // Extract page URLs from manifest\n const sidePanel = (manifest as any)?.side_panel?.default_path || '';\n const optionsPage = (manifest as any).options_page || '';\n const popupPage = (manifest as any).action?.default_popup || '';\n const devtoolsPage = (manifest as any).devtools_page || '';\n const newTabOverride = (manifest as any).chrome_url_overrides?.newtab || '';\n const bookmarksOverride =\n (manifest as any).chrome_url_overrides?.bookmarks || '';\n const historyOverride =\n (manifest as any).chrome_url_overrides?.history || '';\n\n // Create URL endings for matching\n // (handles both full paths and just filenames)\n const pageMatchers = {\n sidepanel: sidePanel ? sidePanel.split('/').pop() : 'sidepanel.html',\n options: optionsPage ? optionsPage.split('/').pop() : 'options.html',\n popup: popupPage ? popupPage.split('/').pop() : 'popup.html',\n devtools: devtoolsPage ? devtoolsPage.split('/').pop() : 'devtools.html',\n newtab: newTabOverride ? newTabOverride.split('/').pop() : 'newtab.html',\n bookmarks: bookmarksOverride\n ? bookmarksOverride.split('/').pop()\n : 'bookmarks.html',\n history: historyOverride\n ? historyOverride.split('/').pop()\n : 'history.html',\n };\n\n // Content scripts (web pages)\n if (sender.tab && sender.url && !sender.url.includes('extension://')) {\n return {\n context: PorterContext.ContentScript,\n tabId: sender.tab.id,\n frameId: sender.frameId || 0,\n url: sender.url,\n portName: port.name,\n };\n }\n\n // Extension pages\n if (sender.url && sender.url.includes('extension://')) {\n const urlPath = new URL(sender.url).pathname;\n const filename = urlPath.split('/').pop();\n\n // Check against our manifest-derived page matchers\n for (const [pageType, pageMatcher] of Object.entries(pageMatchers)) {\n if (filename === pageMatcher) {\n // It's a main extension page\n // Different handling based on presence of tab\n\n return {\n context: pageType as PorterContext,\n tabId: sender.tab?.id || 0,\n frameId: sender.frameId || 0,\n url: sender.url,\n portName: port.name,\n };\n }\n }\n\n // It's some other extension page not specifically listed in our matchers\n\n return {\n context: PorterContext.Unknown,\n tabId: sender.tab?.id || 0,\n frameId: sender.frameId || 0,\n url: sender.url,\n portName: port.name,\n };\n }\n\n // Fallback for unknown sources\n return {\n context: PorterContext.Unknown,\n tabId: 0,\n url: sender.url,\n portName: port.name,\n };\n }\n}\n", "import { Runtime } from 'webextension-polyfill';\nimport { AgentOperations } from './AgentManager';\nimport {\n Agent,\n AgentInfo,\n PorterError,\n PorterErrorType,\n} from '../porter.model';\nimport { Logger } from '../porter.utils';\n\nexport class ConnectionManager {\n constructor(\n private agentOperations: AgentOperations,\n private namespace: string,\n private logger: Logger\n ) {}\n\n public handleConnection(port: Runtime.Port) {\n try {\n this.logger.info('New connection request:', port.name);\n if (!port.name) {\n throw new PorterError(\n PorterErrorType.INVALID_CONTEXT,\n 'Port name not provided'\n );\n }\n\n if (!port.name || !port.name.startsWith(this.namespace + ':')) {\n throw new PorterError(\n PorterErrorType.INVALID_CONTEXT,\n `Invalid namespace or port name format. port name was ${port?.name || 'port undefined'} but namespace is ${this.namespace}`\n );\n }\n\n port.onMessage.addListener(this.handleInitMessage.bind(this, port));\n\n setTimeout(() => {\n if (!this.agentOperations.hasPort(port)) {\n try {\n port.disconnect();\n } catch (e) {\n this.logger.error('Failed to disconnect port:', e);\n }\n }\n }, 5000);\n } catch (error) {\n this.handleConnectionError(port, error as Error);\n }\n }\n\n private handleInitMessage(port: Runtime.Port, message: any): void {\n // Process only the init message\n if (message.action !== 'porter-init') {\n return;\n }\n\n try {\n // Remove this listener since we only need it once\n port.onMessage.removeListener(this.handleInitMessage.bind(this, port));\n\n const { connectionId } = message.payload;\n\n if (!connectionId) {\n throw new PorterError(\n PorterErrorType.INVALID_CONTEXT,\n 'Missing context or connection ID. Message was: ' +\n JSON.stringify(message)\n );\n }\n\n // Now add the agent with the provided context\n const agentId = this.agentOperations.addAgent(port);\n\n if (!agentId) {\n throw new PorterError(\n PorterErrorType.INVALID_CONTEXT,\n 'Failed to add agent'\n );\n }\n\n // Get the agent info to send back\n const agent = this.agentOperations.getAgentById(agentId);\n\n if (agent) {\n this.confirmConnection(agent);\n }\n\n this.agentOperations.printAgents();\n } catch (error) {\n this.handleConnectionError(port, error as Error);\n }\n }\n\n private handleConnectionError(port: Runtime.Port, error: Error): void {\n const porterError =\n error instanceof PorterError\n ? error\n : new PorterError(\n PorterErrorType.CONNECTION_FAILED,\n error instanceof Error ? error.message : 'Unknown connection error',\n { originalError: error }\n );\n this.logger.error('Connection handling failed: ', {\n porterError,\n });\n try {\n port.postMessage({\n action: 'porter-error',\n payload: { error: porterError },\n });\n } catch (e) {\n this.logger.error('Failed to send error message: ', {\n error: e,\n });\n }\n\n try {\n port.disconnect();\n } catch (e) {\n this.logger.error('Failed to disconnect port: ', {\n error: e,\n });\n }\n }\n\n public confirmConnection(agent: Agent) {\n this.logger.debug('Sending confirmation message back to initiator ', {\n agent,\n });\n if (!agent.port) {\n throw new PorterError(\n PorterErrorType.INVALID_PORT,\n 'Agent port is undefined when confirming connection'\n );\n }\n agent.port.postMessage({\n action: 'porter-handshake',\n payload: {\n info: agent.info,\n currentConnections: this.agentOperations.getAllAgentsInfo(),\n },\n });\n }\n}\n", "import { Runtime } from 'webextension-polyfill';\nimport { AgentOperations } from './AgentManager';\nimport {\n PorterEvent,\n Listener,\n MessageListener,\n Message,\n PorterErrorType,\n MessageConfig,\n PorterContext,\n PorterError,\n AgentInfo,\n MessageTarget,\n BrowserLocation,\n AgentId,\n} from '../porter.model';\nimport { Logger } from '../porter.utils';\n\nexport class MessageHandler {\n private eventListeners: Map<\n keyof PorterEvent,\n Set<Listener<keyof PorterEvent>>\n > = new Map();\n private messageListeners: Set<MessageListener> = new Set();\n private initializationHandler: MessageConfig;\n\n constructor(\n private agentOperations: AgentOperations,\n private logger: Logger\n ) {\n this.initializationHandler = {\n 'porter-messages-established': (\n message: Message<any>,\n agent?: AgentInfo\n ) => {\n if (!agent || !agent.id) return;\n const agentInfo = this.agentOperations.getAgentById(agent.id)?.info;\n if (!agentInfo) {\n this.logger.error('No agent info found for agent id: ', agent.id);\n return;\n }\n this.logger.debug(\n 'internalHandlers, established message received: ',\n agent.id,\n message\n );\n this.emitEvent('onMessagesSet', agentInfo);\n },\n };\n }\n\n public async post(\n message: Message<any>,\n target?: MessageTarget\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n this.logger.debug('Post request received:', {\n action: message.action,\n target,\n });\n\n const timeoutId = setTimeout(() => {\n const error = new Error('Message posting timed out');\n this.logger.error('Post timeout:', error);\n reject(error);\n }, 5000);\n\n if (target === undefined) {\n this.broadcastMessage(message);\n // how to tell if target is BrowserLocation type?\n } else if (isBrowserLocation(target)) {\n this.postToLocation(message, target);\n } else if (isPorterContext(target)) {\n this.postToContext(message, target);\n } else if (typeof target === 'string') {\n this.postToId(message, target);\n } else {\n this.postToTab(message, target);\n }\n\n clearTimeout(timeoutId);\n resolve();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n this.logger.error('Failed to post message:', errorMessage);\n reject(new Error(`Failed to post message: ${errorMessage}`));\n }\n });\n }\n\n private broadcastMessage(message: Message<any>): void {\n this.logger.info('Broadcasting message to all agents: ', message);\n this.agentOperations.getAllAgents().forEach((agent) => {\n if (agent.port) {\n agent.port.postMessage(message);\n }\n });\n }\n\n // Post to all frames in a tab\n private postToTab(message: Message<any>, tabId: number): void {\n // const key = `${PorterContext.ContentScript}:${tabId}:0`;\n const agents = this.agentOperations.queryAgents({\n context: PorterContext.ContentScript,\n tabId,\n });\n if (agents.length === 0) {\n this.logger.warn('post: No agents found for tab: ', tabId);\n throw new PorterError(\n PorterErrorType.MESSAGE_FAILED,\n `Failed to post message to tabId ${tabId}`,\n { originalError: message }\n );\n return;\n }\n agents.forEach((agent) => {\n if (agent.port) {\n this.postToPort(message, agent.port);\n }\n });\n }\n\n private postToLocation(\n message: Message<any>,\n location: BrowserLocation\n ): void {\n const agents = this.agentOperations.queryAgents(location);\n agents.forEach((agent) => {\n if (!agent.port) {\n throw new PorterError(\n PorterErrorType.INVALID_TARGET,\n `No port found for agent`,\n { agentInfo: agent.info }\n );\n return;\n }\n this.postToPort(message, agent.port);\n });\n }\n\n private postToContext(message: Message<any>, context: PorterContext): void {\n const agents = this.agentOperations.queryAgents({\n context,\n });\n agents.forEach((agent) => {\n if (!agent.port) {\n throw new PorterError(\n PorterErrorType.INVALID_TARGET,\n `No port found for agent`,\n { agentInfo: agent.info }\n );\n return;\n }\n this.postToPort(message, agent.port);\n });\n }\n\n private postToPort(message: Message<any>, port: Runtime.Port): void {\n try {\n port.postMessage(message);\n } catch (error) {\n throw new PorterError(\n PorterErrorType.MESSAGE_FAILED,\n `Failed to post message to port`,\n { originalError: error, message }\n );\n }\n }\n\n private postToId(message: Message<any>, agentId: AgentId): void {\n const agent = this.agentOperations.getAgentById(agentId);\n if (!agent?.port) {\n throw new PorterError(\n PorterErrorType.INVALID_TARGET,\n `No agent found for key: ${agentId}`\n );\n }\n this.postToPort(message, agent.port);\n }\n\n public onMessage(config: MessageConfig) {\n // Optionally: Check for existing listeners with same config\n const existingListener = Array.from(this.messageListeners).find(\n (listener) => JSON.stringify(listener.config) === JSON.stringify(config)\n );\n\n if (existingListener) {\n this.logger.warn(\n `Listener with same config already exists: ${JSON.stringify(config)}`\n );\n }\n\n const messageListener: MessageListener = {\n config,\n listener: (event: PorterEvent['onMessage']) => {\n const handler = config[event.message.action];\n if (handler) {\n this.logger.debug('onMessage, calling handler ', { event });\n const { message, ...info } = event;\n handler(message, info);\n } else {\n this.logger.debug('onMessage, no handler found ', { event });\n }\n },\n };\n this.messageListeners.add(messageListener);\n\n return () => {\n this.messageListeners.delete(messageListener);\n };\n }\n\n // Adding new 'on' method that works the same way as onMessage\n public on(config: MessageConfig) {\n return this.onMessage(config);\n }\n\n // Handles messages incomng from ports\n public handleIncomingMessage(message: any, info: AgentInfo) {\n this.logger.debug(`Received message`, {\n message,\n info,\n });\n\n this.emitMessage({ ...info, message });\n }\n\n private emitEvent<T extends keyof PorterEvent>(\n event: T,\n arg: PorterEvent[T]\n ) {\n this.logger.debug('emitting event: ', event, arg);\n this.eventListeners\n .get(event)\n ?.forEach((listener) => (listener as Listener<T>)(arg));\n }\n\n // Dispatches incoming messages, either to a registered listener on the source, or to a specific agent\n // if a target was specified (calling this a relay)\n private emitMessage(messageEvent: PorterEvent['onMessage']) {\n this.logger.debug('Dispatching incoming message to subscribers', {\n messageEvent,\n });\n\n if (messageEvent.message.action.startsWith('porter-')) {\n const handler = this.initializationHandler[messageEvent.message.action];\n if (handler) {\n this.logger.debug('Internal message being handled', {\n messageEvent,\n });\n const { message, ...info } = messageEvent;\n handler(message, info);\n return;\n }\n }\n\n // Handle relaying to a target\n if (!!messageEvent.message.target) {\n this.logger.debug(\n 'Relaying message to target:',\n messageEvent.message.target\n );\n this.post(messageEvent.message, messageEvent.message.target);\n }\n\n let handlerCount = 0;\n\n this.logger.trace('Processing message with registered handlers');\n for (const { listener, config } of this.messageListeners) {\n if (config[messageEvent.message.action]) {\n listener(messageEvent as PorterEvent['onMessage']);\n handlerCount++;\n this.logger.debug('Message handled by registered listener: ', {\n listener,\n config,\n });\n }\n }\n\n if (handlerCount === 0) {\n this.logger.warn(\n 'No handler found for message:',\n messageEvent.message.action\n );\n } else {\n this.logger.debug(\n `Message handled by ${handlerCount} registered listeners`\n );\n }\n }\n\n public addListener<T extends keyof PorterEvent>(\n event: T,\n listener: Listener<T>\n ) {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners\n .get(event)!\n .add(listener as Listener<keyof PorterEvent>);\n\n return () => {\n this.eventListeners\n .get(event)\n ?.delete(listener as Listener<keyof PorterEvent>);\n };\n }\n\n public handleDisconnect(info: AgentInfo) {\n // Remove all message listeners for this agent\n this.messageListeners.forEach((messageListener) => {\n if (messageListener.config[info.id]) {\n this.messageListeners.delete(messageListener);\n }\n });\n this.logger.info('Agent disconnected:', { info });\n this.emitEvent('onDisconnect', info);\n }\n\n public handleConnect(info: AgentInfo) {\n this.logger.info('Agent connected:', { info });\n this.emitEvent('onConnect', info);\n }\n\n public onConnect(listener: Listener<'onConnect'>) {\n return this.addListener('onConnect', listener);\n }\n\n public onMessagesSet(listener: Listener<'onMessagesSet'>) {\n return this.addListener('onMessagesSet', listener);\n }\n\n public onDisconnect(listener: Listener<'onDisconnect'>) {\n return this.addListener('onDisconnect', listener);\n }\n}\n\n// Type guard for BrowserLocation\nfunction isBrowserLocation(target: MessageTarget): target is BrowserLocation {\n return (\n typeof target === 'object' &&\n target !== null &&\n 'context' in target &&\n 'tabId' in target &&\n 'frameId' in target\n );\n}\n\nfunction isPorterContext(target: MessageTarget): target is PorterContext {\n return (\n typeof target === 'string' &&\n Object.values(PorterContext).includes(target as PorterContext)\n );\n}\n", "import browser, { Runtime } from 'webextension-polyfill';\nimport { AgentInfo, PorterError, PorterErrorType } from '../porter.model';\nimport { Logger } from '../porter.utils';\nimport { MessageQueue } from './MessageQueue';\n\nexport type DisconnectCallback = () => void;\nexport type ReconnectCallback = (info: AgentInfo) => void;\n\nexport class AgentConnectionManager {\n private readonly CONNECTION_TIMEOUT = 5000;\n private readonly RECONNECT_INTERVAL = 1000; // 1 second\n private connectionTimer: NodeJS.Timeout | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private agentInfo: AgentInfo | null = null;\n private port: Runtime.Port | null = null;\n private readonly logger: Logger;\n private readonly connectionId: string;\n private readonly messageQueue: MessageQueue;\n private isReconnecting: boolean = false;\n private reconnectAttemptCount: number = 0;\n\n // Event callbacks\n private disconnectCallbacks: Set<DisconnectCallback> = new Set();\n private reconnectCallbacks: Set<ReconnectCallback> = new Set();\n\n constructor(\n private readonly namespace: string,\n logger: Logger\n ) {\n this.connectionId = `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n this.logger = logger;\n this.messageQueue = new MessageQueue(logger);\n }\n\n /**\n * Register a callback to be called when the connection is lost\n * @returns Unsubscribe function\n */\n public onDisconnect(callback: DisconnectCallback): () => void {\n this.disconnectCallbacks.add(callback);\n return () => {\n this.disconnectCallbacks.delete(callback);\n };\n }\n\n /**\n * Register a callback to be called when reconnection succeeds\n * @returns Unsubscribe function\n */\n public onReconnect(callback: ReconnectCallback): () => void {\n this.reconnectCallbacks.add(callback);\n return () => {\n this.reconnectCallbacks.delete(callback);\n };\n }\n\n private emitDisconnect(): void {\n this.logger.debug('Emitting disconnect event', {\n callbackCount: this.disconnectCallbacks.size,\n });\n this.disconnectCallbacks.forEach((callback) => {\n try {\n callback();\n } catch (error) {\n this.logger.error('Error in disconnect callback:', error);\n }\n });\n }\n\n private emitReconnect(info: AgentInfo): void {\n this.logger.debug('Emitting reconnect event', {\n callbackCount: this.reconnectCallbacks.size,\n info,\n });\n this.reconnectCallbacks.forEach((callback) => {\n try {\n callback(info);\n } catch (error) {\n this.logger.error('Error in reconnect callback:', error);\n }\n });\n }\n\n public async initializeConnection(): Promise<void> {\n try {\n if (this.connectionTimer) {\n clearTimeout(this.connectionTimer);\n }\n\n const portName = `${this.namespace}:${this.connectionId}`;\n this.logger.debug('Connecting new port with name: ', { portName });\n this.port = browser.runtime.connect({ name: portName });\n\n const handshakePromise = new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(\n () =>\n reject(\n new PorterError(\n PorterErrorType.CONNECTION_TIMEOUT,\n 'Connection timed out waiting for handshake'\n )\n ),\n this.CONNECTION_TIMEOUT\n );\n\n const onMessage = (message: any) => {\n if (message.action === 'porter-handshake') {\n this.logger.debug('Received handshake:', message);\n clearTimeout(timeout);\n this.agentInfo = message.payload.info;\n this.logger.debug('Handshake agent info:', {\n agentInfo: this.agentInfo,\n });\n this.port?.onMessage.removeListener(onMessage);\n resolve();\n } else if (message.action === 'porter-error') {\n clearTimeout(timeout);\n this.port?.onMessage.removeListener(onMessage);\n this.logger.error('Error:', message);\n reject(\n new PorterError(\n message.payload.type,\n message.payload.message,\n message.payload.details\n )\n );\n }\n };\n\n this.port?.onMessage.addListener(onMessage);\n });\n\n this.port?.postMessage({\n action: 'porter-init',\n payload: {\n info: this.agentInfo,\n connectionId: this.connectionId,\n },\n });\n\n await handshakePromise;\n\n // After successful connection, process any queued messages\n await this.processQueuedMessages();\n } catch (error) {\n this.logger.error('Connection initialization failed:', error);\n this.handleDisconnect(this.port!);\n throw error;\n }\n }\n\n private async processQueuedMessages(): Promise<void> {\n if (!this.port || this.messageQueue.isEmpty()) {\n return;\n }\n\n const messages = this.messageQueue.dequeue();\n this.logger.info(\n `Processing ${messages.length} queued messages after reconnection`\n );\n\n for (const { message, target } of messages) {\n try {\n // Send message in the same format as normal messages\n const messageToSend = { ...message };\n if (target) {\n messageToSend.target = target;\n }\n this.port.postMessage(messageToSend);\n this.logger.debug('Successfully resent queued message:', {\n message: messageToSend,\n });\n } catch (error) {\n this.logger.error('Failed to process queued message:', error);\n // Re-queue the message if it fails\n this.messageQueue.enqueue(message, target);\n this.logger.debug('Re-queued failed message for retry');\n }\n }\n }\n\n public getPort(): Runtime.Port | null {\n return this.port;\n }\n\n public getAgentInfo(): AgentInfo | null {\n return this.agentInfo;\n }\n\n public getNamespace(): string {\n return this.namespace;\n }\n\n public handleDisconnect(port: Runtime.Port) {\n this.logger.info('Port disconnected', {\n portName: port.name,\n connectionId: this.connectionId,\n queuedMessages: this.messageQueue.isEmpty() ? 0 : 'some',\n });\n this.port = null;\n this.agentInfo = null;\n\n // Notify listeners of disconnection\n this.emitDisconnect();\n\n // Start reconnection attempts if not already reconnecting\n if (!this.isReconnecting) {\n this.startReconnectionAttempts();\n }\n }\n\n private startReconnectionAttempts(): void {\n this.isReconnecting = true;\n this.reconnectAttemptCount = 0;\n\n if (this.reconnectTimer) {\n clearInterval(this.reconnectTimer);\n }\n\n this.logger.info('Starting reconnection attempts', {\n interval: this.RECONNECT_INTERVAL,\n queuedMessages: this.messageQueue.isEmpty() ? 0 : 'some',\n });\n\n this.reconnectTimer = setInterval(async () => {\n this.reconnectAttemptCount++;\n try {\n this.logger.debug(`Reconnection attempt ${this.reconnectAttemptCount}`);\n await this.initializeConnection();\n this.isReconnecting = false;\n if (this.reconnectTimer) {\n clearInterval(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.logger.info('Reconnection successful', {\n attempts: this.reconnectAttemptCount,\n queuedMessages: this.messageQueue.isEmpty() ? 0 : 'some',\n });\n\n // Notify listeners of successful reconnection\n if (this.agentInfo) {\n this.emitReconnect(this.agentInfo);\n }\n } catch (error) {\n this.logger.debug(\n `Reconnection attempt ${this.reconnectAttemptCount} failed:`,\n error\n );\n }\n }, this.RECONNECT_INTERVAL);\n }\n\n public queueMessage(message: any, target?: any): void {\n this.messageQueue.enqueue(message, target);\n this.logger.debug('Message queued for retry', {\n message,\n target,\n queueSize: this.messageQueue.isEmpty() ? 0 : 'some',\n });\n }\n}\n", "import { Message, BrowserLocation } from '../porter.model';\nimport { Logger } from '../porter.utils';\n\ninterface QueuedMessage {\n message: Message<any>;\n target?: BrowserLocation;\n timestamp: number;\n}\n\nexport class MessageQueue {\n private queue: QueuedMessage[] = [];\n private readonly logger: Logger;\n private readonly maxQueueSize: number = 1000; // Prevent memory issues\n private readonly maxMessageAge: number = 5 * 60 * 1000; // 5 minutes\n\n constructor(logger: Logger) {\n this.logger = logger;\n this.logger.debug('MessageQueue initialized', {\n maxQueueSize: this.maxQueueSize,\n maxMessageAge: `${this.maxMessageAge / 1000} seconds`,\n });\n }\n\n public enqueue(message: Message<any>, target?: BrowserLocation): void {\n // Remove old messages\n const oldCount = this.queue.length;\n this.cleanup();\n if (oldCount !== this.queue.length) {\n this.logger.debug(\n `Cleaned up ${oldCount - this.queue.length} old messages`\n );\n }\n\n // Check if queue is full\n if (this.queue.length >= this.maxQueueSize) {\n this.logger.warn('Message queue is full, dropping oldest message', {\n queueSize: this.queue.length,\n maxSize: this.maxQueueSize,\n });\n this.queue.shift();\n }\n\n this.queue.push({\n message,\n target,\n timestamp: Date.now(),\n });\n\n this.logger.debug('Message queued', {\n queueSize: this.queue.length,\n message,\n target,\n timestamp: new Date().toISOString(),\n });\n }\n\n public dequeue(): QueuedMessage[] {\n const messages = [...this.queue];\n this.queue = [];\n this.logger.info(`Dequeued ${messages.length} messages`, {\n oldestMessage: messages[0]\n ? new Date(messages[0].timestamp).toISOString()\n : null,\n newestMessage: messages[messages.length - 1]\n ? new Date(messages[messages.length - 1].timestamp).toISOString()\n : null,\n });\n return messages;\n }\n\n public isEmpty(): boolean {\n return this.queue.length === 0;\n }\n\n private cleanup(): void {\n const now = Date.now();\n const oldCount = this.queue.length;\n this.queue = this.queue.filter(\n (item) => now - item.timestamp < this.maxMessageAge\n );\n if (oldCount !== this.queue.length) {\n this.logger.debug(\n `Cleaned up ${oldCount - this.queue.length} expired messages`,\n {\n remaining: this.queue.length,\n maxAge: `${this.maxMessageAge / 1000} seconds`,\n }\n );\n }\n }\n}\n", "import { Runtime } from 'webextension-polyfill';\nimport {\n BrowserLocation,\n Message,\n MessageConfig,\n PorterError,\n PorterErrorType,\n} from '../porter.model';\nimport { Logger } from '../porter.utils';\n\nexport class AgentMessageHandler {\n private readonly MAX_QUEUE_SIZE = 1000;\n private readonly MESSAGE_TIMEOUT = 30000;\n private messageQueue: Array<{ message: Message<any>; timestamp: number }> =\n [];\n private handlers: Map<string, Array<Function>> = new Map();\n\n constructor(private readonly logger: Logger) {}\n\n public handleMessage(port: Runtime.Port, message: any) {\n this.logger.debug('handleMessage, message: ', message);\n if (this.handlers.size === 0) {\n if (this.messageQueue.length >= this.MAX_QUEUE_SIZE) {\n this.logger.warn('Message queue full, dropping message:', message);\n return;\n }\n this.logger.warn(\n 'No message handlers configured yet, queueing message: ',\n message\n );\n this.messageQueue.push({ message, timestamp: Date.now() });\n return;\n }\n this.processMessage(port, message);\n }\n\n // Legacy method - internally uses the new system\n public onMessage(config: MessageConfig) {\n this.logger.debug('Setting message handlers from config: ', config);\n // Clear previous handlers to maintain backward compatibility\n this.handlers.clear();\n this.on(config);\n\n this.processQueuedMessages();\n }\n\n public on(config: MessageConfig) {\n this.logger.debug('Adding message handlers from config: ', config);\n\n Object.entries(config).forEach(([action, handler]) => {\n if (!this.handlers.has(action)) {\n this.handlers.set(action, []);\n }\n this.handlers.get(action)!.push(handler);\n });\n\n this.processQueuedMessages();\n }\n\n private processQueuedMessages() {\n while (this.messageQueue.length > 0) {\n const item = this.messageQueue[0];\n if (Date.now() - item.timestamp > this.MESSAGE_TIMEOUT) {\n this.logger.warn(\n 'Message timeout, dropping message: ',\n this.messageQueue.shift()\n );\n continue;\n }\n this.processMessage(null!, item.message);\n this.messageQueue.shift();\n }\n }\n\n private processMessage(port: Runtime.Port, message: any) {\n const action = message.action;\n const actionHandlers = this.handlers.get(action) || [];\n\n if (actionHandlers.length > 0) {\n this.logger.debug(\n `Found ${actionHandlers.length} handlers for action: ${action}`\n );\n actionHandlers.forEach((handler) => handler(message));\n } else {\n this.logger.debug(`No handlers for message with action: ${action}`);\n }\n }\n\n public post(\n port: Runtime.Port,\n message: Message<any>,\n target?: BrowserLocation\n ) {\n this.logger.debug(`Sending message`, {\n action: message.action,\n target,\n hasPayload: !!message.payload,\n });\n\n try {\n if (target) {\n message.target = target;\n }\n port.postMessage(message);\n } catch (error) {\n throw new PorterError(\n PorterErrorType.MESSAGE_FAILED,\n 'Failed to post message',\n { originalError: error, message, target }\n );\n }\n }\n}\n", "import {\n AgentInfo,\n BrowserLocation,\n Message,\n MessageConfig,\n PorterContext,\n Unsubscribe,\n} from '../porter.model';\nimport {\n AgentConnectionManager,\n DisconnectCallback,\n ReconnectCallback,\n} from '../managers/AgentConnectionManager';\nimport { AgentMessageHandler } from '../managers/AgentMessageHandler';\nimport { Logger } from '../porter.utils';\n\nexport interface AgentAPI {\n type: 'agent';\n post: (message: Message<any>, target?: BrowserLocation) => void;\n onMessage: (config: MessageConfig) => void;\n on: (config: MessageConfig) => void;\n getAgentInfo: () => AgentInfo | null;\n onDisconnect: (callback: DisconnectCallback) => Unsubscribe;\n onReconnect: (callback: ReconnectCallback) => Unsubscribe;\n}\n\nexport interface PorterAgentOptions {\n agentContext?: PorterContext;\n namespace?: string;\n debug?: boolean;\n}\n\nexport class PorterAgent {\n private static instance: PorterAgent | null = null;\n private readonly connectionManager: AgentConnectionManager;\n private readonly messageHandler: AgentMessageHandler;\n private readonly logger: Logger;\n\n private constructor(options: PorterAgentOptions = {}) {\n const namespace = options.namespace ?? 'porter';\n const context = options.agentContext ?? this.determineContext();\n\n if (options.debug !== undefined) {\n Logger.configure({ enabled: options.debug });\n }\n\n this.logger = Logger.getLogger('Agent');\n\n this.connectionManager = new AgentConnectionManager(namespace, this.logger);\n this.messageHandler = new AgentMessageHandler(this.logger);\n\n // Listen for reconnection events to re-wire port listeners\n this.connectionManager.onReconnect((info) => {\n this.logger.info('Reconnected, re-wiring port listeners', { info });\n this.setupPortListeners();\n });\n\n this.logger.info('Initializing with options: ', { options, context });\n this.initializeConnection();\n }\n\n public static getInstance(options: PorterAgentOptions = {}): PorterAgent {\n if (\n !PorterAgent.instance ||\n PorterAgent.instance.connectionManager.getNamespace() !==\n options.namespace\n ) {\n PorterAgent.instance = new PorterAgent(options);\n } else if (options.debug !== undefined) {\n Logger.configure({ enabled: options.debug });\n }\n return PorterAgent.instance;\n }\n\n private async initializeConnection(): Promise<void> {\n await this.connectionManager.initializeConnection();\n this.setupPortListeners();\n }\n\n /**\n * Set up message and disconnect listeners on the current port.\n * Called after initial connection and after each reconnection.\n */\n private setupPortListeners(): void {\n const port = this.connectionManager.getPort();\n if (port) {\n this.logger.debug('Setting up port listeners');\n port.onMessage.addListener((message: any) =>\n this.messageHandler.handleMessage(port, message)\n );\n port.onDisconnect.addListener((p) =>\n this.connectionManager.handleDisconnect(p)\n );\n } else {\n this.logger.warn('Cannot setup port listeners: no port available');\n }\n }\n\n public onMessage(config: MessageConfig) {\n this.messageHandler.onMessage(config);\n const port = this.connectionManager.getPort();\n port?.postMessage({ action: 'porter-messages-established' });\n }\n\n public on(config: MessageConfig) {\n this.messageHandler.on(config);\n const port = this.connectionManager.getPort();\n port?.postMessage({ action: 'porter-messages-established' });\n }\n\n public post(message: Message<any>, target?: BrowserLocation) {\n const port = this.connectionManager.getPort();\n this.logger.debug('Posting message', { message, target, port });\n\n if (port) {\n try {\n this.messageHandler.post(port, message, target);\n } catch (error) {\n this.logger.error('Failed to post message, queueing for retry', {\n error,\n });\n this.connectionManager.queueMessage(message, target);\n }\n } else {\n this.logger.debug('No port found, queueing message', { message, target });\n this.connectionManager.queueMessage(message, target);\n }\n }\n\n private determineContext(): PorterContext {\n if (!window.location.protocol.includes('extension')) {\n return PorterContext.ContentScript;\n }\n return PorterContext.Extension;\n }\n\n public getAgentInfo(): AgentInfo | null {\n return this.connectionManager.getAgentInfo() || null;\n }\n\n /**\n * Register a callback to be called when the connection to the service worker is lost\n * @returns Unsubscribe function\n */\n public onDisconnect(callback: DisconnectCallback): Unsubscribe {\n return this.connectionManager.onDisconnect(callback);\n }\n\n /**\n * Register a callback to be called when reconnection to the service worker succeeds\n * @returns Unsubscribe function\n */\n public onReconnect(callback: ReconnectCallback): Unsubscribe {\n return this.connectionManager.onReconnect(callback);\n }\n}\n\nexport function connect(options?: PorterAgentOptions): AgentAPI {\n const porterInstance = PorterAgent.getInstance(options);\n return {\n type: 'agent',\n post: porterInstance.post.bind(porterInstance),\n onMessage: porterInstance.onMessage.bind(porterInstance),\n on: porterInstance.on.bind(porterInstance),\n getAgentInfo: porterInstance.getAgentInfo.bind(porterInstance),\n onDisconnect: porterInstance.onDisconnect.bind(porterInstance),\n onReconnect: porterInstance.onReconnect.bind(porterInstance),\n };\n}\n", "import { useState, useEffect, useCallback, useRef, useMemo } from 'react';\nimport { connect, AgentAPI } from '../core/PorterAgent';\nimport {\n AgentInfo,\n Message,\n MessageConfig,\n PorterContext,\n Unsubscribe,\n} from '../porter.model';\n\ninterface UsePorterResult {\n post: (message: Message<any>) => void;\n on: (handlers: MessageConfig) => void;\n isConnected: boolean;\n isReconnecting: boolean;\n error: Error | null;\n agentInfo: AgentInfo | null;\n}\n\nexport function usePorter(options?: {\n agentContext?: PorterContext;\n namespace?: string;\n debug?: boolean;\n onDisconnect?: () => void;\n onReconnect?: (info: AgentInfo) => void;\n}): UsePorterResult {\n const [isConnected, setIsConnected] = useState<boolean>(false);\n const [isReconnecting, setIsReconnecting] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n const [agentInfo, setAgentInfo] = useState<AgentInfo | null>(null);\n const postRef = useRef<((message: Message<any>) => void) | null>(null);\n const onRef = useRef<((handlers: MessageConfig) => void) | null>(null);\n const getAgentInfoRef = useRef<(() => AgentInfo | null) | null>(null);\n const unsubscribeRefs = useRef<Unsubscribe[]>([]);\n\n const memoizedOptions = useMemo(\n () => ({\n agentContext: options?.agentContext,\n namespace: options?.namespace,\n debug: options?.debug,\n }),\n [options?.agentContext, options?.namespace, options?.debug]\n );\n\n // Store callbacks in refs to avoid re-running effect when they change\n const onDisconnectRef = useRef(options?.onDisconnect);\n const onReconnectRef = useRef(options?.onReconnect);\n onDisconnectRef.current = options?.onDisconnect;\n onReconnectRef.current = options?.onReconnect;\n\n useEffect(() => {\n let isMounted = true;\n\n const initializePorter = async () => {\n try {\n const { post, on, getAgentInfo, onDisconnect, onReconnect } =\n connect(memoizedOptions);\n\n if (isMounted) {\n postRef.current = post;\n onRef.current = on;\n getAgentInfoRef.current = getAgentInfo;\n setIsConnected(true);\n setIsReconnecting(false);\n setError(null);\n\n // Set up disconnect handler\n const unsubDisconnect = onDisconnect(() => {\n if (isMounted) {\n setIsConnected(false);\n setIsReconnecting(true);\n setAgentInfo(null);\n onDisconnectRef.current?.();\n }\n });\n unsubscribeRefs.current.push(unsubDisconnect);\n\n // Set up reconnect handler\n const unsubReconnect = onReconnect((info: AgentInfo) => {\n if (isMounted) {\n setIsConnected(true);\n setIsReconnecting(false);\n setAgentInfo(info);\n onReconnectRef.current?.(info);\n }\n });\n unsubscribeRefs.current.push(unsubReconnect);\n\n // Set up internal porter-handshake handler\n on({\n 'porter-handshake': (message: Message<any>) => {\n if (isMounted) {\n setAgentInfo(message.payload.info);\n }\n },\n });\n }\n } catch (err) {\n if (isMounted) {\n console.error('[PORTER] initializePorter error ', err);\n setError(\n err instanceof Error\n ? err\n : new Error('Failed to connect to Porter')\n );\n setIsConnected(false);\n setIsReconnecting(false);\n }\n }\n };\n\n initializePorter();\n\n return () => {\n isMounted = false;\n // Clean up all subscriptions\n unsubscribeRefs.current.forEach((unsub) => unsub());\n unsubscribeRefs.current = [];\n };\n }, [memoizedOptions]);\n\n const post = useCallback((message: Message<any>) => {\n if (postRef.current) {\n try {\n postRef.current(message);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error('Failed to send message')\n );\n }\n } else {\n setError(new Error('Porter is not connected'));\n }\n }, []);\n\n const on = useCallback((handlers: MessageConfig) => {\n if (onRef.current) {\n try {\n onRef.current(handlers);\n } catch (err) {\n setError(\n err instanceof Error\n ? err\n : new Error('Failed to set message handlers')\n );\n }\n } else {\n setError(new Error('Porter is not connected'));\n }\n }, []);\n\n return { post, on, isConnected, isReconnecting, error, agentInfo };\n}\n", "export function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n keysA.sort();\n keysB.sort();\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i];\n if (key !== keysB[i] || !deepEqual(a[key], b[key])) return false;\n }\n return true;\n}", "// Create a global debug state manager\nexport class DebugManager {\n private static _debug: boolean = false;\n\n static setDebug(value: boolean): void {\n DebugManager._debug = value;\n }\n\n static isDebugEnabled(): boolean {\n return DebugManager._debug;\n }\n}\n\n// Export a convenience function\nexport function isDebugEnabled(): boolean {\n return DebugManager.isDebugEnabled();\n}\n", "import { isDebugEnabled } from \"./debug\";\n\nexport type StateChangeMetadata = {\n source: string;\n timestamp: number;\n changes: any;\n instanceKey?: string;\n};\n\nexport function trackStateChange(\n target: any,\n propertyKey: string,\n descriptor: PropertyDescriptor\n): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n // Only log if debugging is enabled\n if (isDebugEnabled()) {\n // Get the stack trace to find the actual caller\n const stack = new Error().stack;\n const lines = stack?.split(\"\\n\") || [];\n const callerMatch = lines[3]?.match(/at\\s+(\\S+)\\s+/);\n const caller = callerMatch ? callerMatch[1] : \"unknown\";\n\n const changes = args.length > 1 ? args[1] : undefined;\n\n const metadata: StateChangeMetadata = {\n source: caller,\n timestamp: Date.now(),\n instanceKey: args[0],\n changes,\n };\n\n console.log(`Crann State Change:`, metadata);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n}\n", "export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport class Logger {\n private static debug = false;\n private static prefix = \"CrannLogger\";\n private static noOp = function () {};\n\n private context: string;\n private tag: string | null = null;\n\n /**\n * Create a new Logger instance with a specific context\n */\n constructor(context: string) {\n this.context = context;\n }\n\n static setDebug(value: boolean): void {\n Logger.debug = value;\n }\n\n static setPrefix(value: string): void {\n Logger.prefix = value;\n }\n\n /**\n * Set a persistent tag for this Logger instance\n */\n setTag(tag: string | null): void {\n this.tag = tag;\n }\n\n /**\n * Create a temporary logger with a specific tag\n * This doesn't modify the original logger instance\n */\n withTag(tag: string) {\n const tempLogger = new Logger(this.context);\n tempLogger.setTag(tag);\n return tempLogger;\n }\n\n /**\n * Get the full context string including tag if present\n */\n private getFullContext(): string {\n if (this.tag) {\n return `${this.context}:${this.tag}`;\n }\n return this.context;\n }\n\n /**\n * Create the log methods bound to the current context and tag\n */\n private createLogMethods() {\n const fullContext = this.getFullContext();\n const formatString = `%c${Logger.prefix}%c [%c${fullContext}%c]`;\n\n // Styles for the prefix and context - updated for better readability on dark backgrounds\n const prefixStyle = \"color: #3fcbff; font-weight: bold\"; // Bright cyan\n const contextStyle = \"color: #d58cff; font-weight: bold\"; // Bright purple\n const resetStyle = \"\";\n\n if (Logger.debug) {\n return {\n debug: console.log.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n log: console.log.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n info: console.info.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n warn: console.warn.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n error: console.error.bind(\n console,\n formatString,\n prefixStyle,\n resetStyle,\n contextStyle,\n resetStyle\n ),\n };\n } else {\n return {\n debug: Logger.noOp,\n log: Logger.noOp,\n info: Logger.noOp,\n warn: Logger.noOp,\n error: Logger.noOp,\n };\n }\n }\n\n /**\n * Log methods that are dynamically created based on current context and tag\n */\n get debug() {\n return this.createLogMethods().debug;\n }\n get log() {\n return this.createLogMethods().log;\n }\n get info() {\n return this.createLogMethods().info;\n }\n get warn() {\n return this.createLogMethods().warn;\n }\n get error() {\n return this.createLogMethods().error;\n }\n\n /**\n * Static helper to create a logger with a specific context\n */\n static forContext(context: string, tag?: string): Logger {\n const logger = new Logger(context);\n if (tag) {\n logger.setTag(tag);\n }\n return logger;\n }\n}\n", "import { AgentInfo } from \"../transport\";\n\n/**\n * Formats an agent tag based on the agent information\n * @param agent Agent information\n * @param options Configuration options\n * @returns Formatted agent tag string\n */\nexport function getAgentTag(\n agent: AgentInfo,\n options: { terse?: boolean } = { terse: true }\n): string {\n const formatTabId = (tabId: number | string): string => {\n const tabIdStr = String(tabId);\n if (tabIdStr.length >= 4) {\n return tabIdStr.slice(-4);\n } else {\n return tabIdStr.padStart(4, \"0\");\n }\n };\n\n const formattedTabId = formatTabId(agent.location.tabId);\n\n if (options?.terse) {\n return `${formattedTabId}:${agent.location.frameId}`;\n }\n return `${agent.location.context}:${formattedTabId}:${agent.location.frameId}`;\n}\n", "import { createBasicEncoder } from \"./encoding\";\nimport type {\n MessageEndpoint,\n RemoteCallable,\n EncodingStrategy,\n EncodingStrategyApi,\n Retainer,\n CallMessage,\n ResultMessage,\n ErrorMessage,\n RPCMessage,\n} from \"./types\";\nimport { ActionsConfig, SetStateFunction } from \"../model/crann.model\";\nimport { Logger } from \"../utils/logger\";\nimport { getAgentTag } from \"../utils/agent\";\n\nconst CALL = 0;\nconst RESULT = 1;\nconst TERMINATE = 2;\nconst RELEASE = 3;\nconst FUNCTION_APPLY = 5;\nconst FUNCTION_RESULT = 6;\n\ntype AnyFunction = (...args: any[]) => any;\n\nexport interface CreateEndpointOptions<T = unknown> {\n uuid?(): string;\n createEncoder?(api: EncodingStrategyApi): EncodingStrategy;\n callable?: (keyof T)[];\n}\n\nexport interface Endpoint<T> {\n readonly call: RemoteCallable<T>;\n replace(messenger: MessageEndpoint): void;\n expose(api: Record<string, AnyFunction | undefined>): void;\n callable(...methods: string[]): void;\n terminate(): void;\n}\n\n/**\n * An endpoint wraps around a messenger, acting as the intermediary for all\n * messages both send from, and received by, that messenger. The endpoint sends\n * all messages as arrays, where the first element is the message type, and the\n * second is the arguments for that message (as an array). For messages that send\n * meaningful content across the wire (e.g., arguments to function calls, return\n * results), the endpoint first encodes these values.\n *\n * Encoding is done using a CBOR-like encoding scheme. The value is encoded into\n * an array buffer, and is paired with an additional array buffer that contains all\n * the strings used in that message (in the encoded value, strings are encoded as\n * their index in the \"strings\" encoding to reduce the cost of heavily-duplicated\n * strings, which is more likely in payloads containing UI). This encoding also takes\n * care of encoding functions: it uses a \"tagged\" item in CBOR to represent a\n * function as a string ID, which the opposite endpoint will be capable of turning\n * into a consistent, memory-manageable function proxy.\n *\n * The main CBOR encoding is entirely take from the [cbor.js package](https://github.com/paroga/cbor-js).\n * The special behavior for encoding strings and functions was then added in to the\n * encoder and decoder. For additional details on CBOR:\n *\n * @see https://tools.ietf.org/html/rfc7049\n */\nexport function createEndpoint<TState, TActions extends ActionsConfig<TState>>(\n messenger: MessageEndpoint,\n stateGetter: () => TState,\n actions: TActions,\n setState?: SetStateFunction<TState>,\n encodingStrategy?: EncodingStrategy\n): RemoteCallable<TActions> {\n const callbacks = new Map<number, (result: unknown) => void>();\n const retainedObjects = new Map<string, Set<Retainer>>();\n\n // Create logger - will be used in Service Worker or Agent context based on the messenger's context\n const contextPrefix = messenger.context?.isServiceWorker ? \"Core\" : \"Agent\";\n const logger = Logger.forContext(`${contextPrefix}:RPC`);\n\n // If we have agent info, set the tag\n if (messenger.context?.agentInfo) {\n logger.setTag(getAgentTag(messenger.context.agentInfo));\n }\n\n messenger.addEventListener(\"message\", (event) => {\n logger.debug(\"Message received:\", event);\n const [id, message] = event.data as [number, RPCMessage];\n\n if (\"call\" in message && \"args\" in message.call) {\n logger.debug(\"Processing call message:\", message);\n const callMessage = message.call;\n const { id: callId, args, target } = callMessage;\n const action = actions[callId];\n if (!action) {\n messenger.postMessage([\n id,\n {\n error: { id: callId, error: \"Action not found\", target },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n return;\n }\n\n try {\n if (action.validate) {\n action.validate(...args);\n }\n\n // Ensure we have a target - if not provided, we need to handle this case\n if (!target) {\n messenger.postMessage([\n id,\n {\n error: {\n id: callId,\n error: \"No target provided for action call\",\n target,\n },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n return;\n }\n\n const currentState = stateGetter();\n logger.debug(\"Executing action with most current state:\", currentState);\n\n // Handle both synchronous and asynchronous results\n Promise.resolve(\n action.handler(currentState, setState!, target, ...args)\n ).then(\n (result: unknown) => {\n logger.debug(\"Action handler result:\", {\n result,\n target,\n });\n messenger.postMessage([\n id,\n { result: { id: callId, result, target } },\n ] as [number, ResultMessage]);\n },\n (error: Error) => {\n messenger.postMessage([\n id,\n {\n error: { id: callId, error: error.message, target },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n }\n );\n } catch (error) {\n if (error instanceof Error) {\n messenger.postMessage([\n id,\n { error: { id: callId, error: error.message, target } },\n ] as [number, ErrorMessage]);\n } else {\n messenger.postMessage([\n id,\n {\n error: { id: callId, error: \"Unknown error occurred\", target },\n } as ErrorMessage,\n ] as [number, ErrorMessage]);\n }\n }\n } else if (\"result\" in message) {\n const resultMessage = message.result;\n const callback = callbacks.get(id);\n if (callback) {\n callback(resultMessage.result);\n callbacks.delete(id);\n }\n } else if (\"error\" in message) {\n const errorMessage = message.error;\n const callback = callbacks.get(id);\n if (callback) {\n callback(Promise.reject(new Error(errorMessage.error)));\n callbacks.delete(id);\n }\n } else if (\"release\" in message) {\n const releaseMessage = message.release;\n const retainers = retainedObjects.get(releaseMessage.id);\n if (retainers) {\n retainers.clear();\n retainedObjects.delete(releaseMessage.id);\n }\n }\n });\n\n const proxy = new Proxy({} as RemoteCallable<TActions>, {\n get(_, prop: string) {\n return (...args: unknown[]) => {\n const id = Math.random();\n return new Promise((resolve, reject) => {\n callbacks.set(id, (result) => {\n if (result instanceof Promise) {\n result.then(resolve, reject);\n } else {\n resolve(result);\n }\n });\n messenger.postMessage([id, { call: { id: prop, args } }] as [\n number,\n CallMessage\n ]);\n });\n };\n },\n });\n\n return proxy;\n}\n\nfunction defaultUuid() {\n return `${uuidSegment()}-${uuidSegment()}-${uuidSegment()}-${uuidSegment()}`;\n}\n\nfunction uuidSegment() {\n return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16);\n}\n\nfunction createCallable<T>(\n handlerForCall: (\n property: string | number | symbol\n ) => AnyFunction | undefined,\n callable?: (keyof T)[]\n): RemoteCallable<T> {\n let call: any;\n\n if (callable == null) {\n if (typeof Proxy !== \"function\") {\n throw new Error(\n `You must pass an array of callable methods in environments without Proxies.`\n );\n }\n\n const cache = new Map<string | number | symbol, AnyFunction | undefined>();\n\n call = new Proxy(\n {},\n {\n get(_target, property) {\n if (cache.has(property)) {\n return cache.get(property);\n }\n\n const handler = handlerForCall(property);\n cache.set(property, handler);\n return handler;\n },\n }\n );\n } else {\n call = {};\n\n for (const method of callable) {\n Object.defineProperty(call, method, {\n value: handlerForCall(method),\n writable: false,\n configurable: true,\n enumerable: true,\n });\n }\n }\n\n return call;\n}\n", "import { source, AgentInfo, connect, Message, AgentAPI } from \"../transport\";\nimport { createEndpoint } from \"./endpoint\";\nimport { MessageEndpoint, CallMessage, RPCMessage } from \"./types\";\nimport {\n ActionDefinition,\n AnyConfig,\n DerivedState,\n SetStateCallback,\n SetStateFunction,\n} from \"../model/crann.model\";\nimport { Logger } from \"../utils/logger\";\nimport { getAgentTag } from \"../utils/agent\";\n\nexport function createCrannRPCAdapter<TConfig extends AnyConfig>(\n stateGetter: () => DerivedState<TConfig>,\n actions: Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>>,\n porter?: ReturnType<typeof source> | ReturnType<typeof connect>,\n setState?: SetStateFunction<DerivedState<TConfig>>\n) {\n const porterInstance = porter || source(\"crann\");\n\n // Determine if this is a service worker instance (source) or content script instance (connect)\n const isServiceWorker = !(porterInstance.type === \"agent\");\n\n // Set up logger with the appropriate context\n const logger = Logger.forContext(isServiceWorker ? \"Core:RPC\" : \"Agent:RPC\");\n\n const messageEndpoint: MessageEndpoint = {\n postMessage: (message, transferables) => {\n if (isServiceWorker) {\n logger.debug(\"Posting message from service worker:\", {\n message,\n transferables,\n });\n // In service worker, we need to respond to the specific target\n const [, rpcPayload] = message;\n const target = getTargetFromMessage(rpcPayload);\n if (!target) {\n logger.warn(\"No target specified for RPC response in service worker\");\n return;\n }\n porterInstance.post(\n {\n action: \"rpc\",\n payload: {\n message,\n transferables: transferables || [],\n },\n },\n target\n );\n } else {\n // In content script (agent) context\n // Get the agent info only when needed\n const agentInfo = (porterInstance as AgentAPI).getAgentInfo();\n\n if (!agentInfo) {\n logger.warn(\"No agent info found for posting message\", { agentInfo });\n return;\n }\n\n // Get the agent tag for logging\n const myTag = getAgentTag(agentInfo);\n\n // Destructure the tuple, skipping the messageId which we don't need\n const [, rpcPayload] = message;\n\n // Use type guard to check if it's a call message\n if (\"call\" in rpcPayload) {\n // Add the target info to the call message\n rpcPayload.call.target = agentInfo?.location;\n }\n\n logger.withTag(myTag).debug(\"Sending RPC message from agent:\", {\n rpcPayload,\n message,\n });\n // In content script, target is automatically the service worker\n porterInstance.post({\n action: \"rpc\",\n payload: {\n message,\n transferables: transferables || [],\n },\n });\n }\n },\n addEventListener: (event, listener) => {\n porterInstance.on({\n rpc: (message: Message<string>, info?: AgentInfo) => {\n try {\n if (!info) {\n logger.debug(\"RPC message received:\", {\n message,\n event,\n });\n } else {\n // Get the agent tag for logging\n const myTag = getAgentTag(info);\n logger.withTag(myTag).debug(\"RPC message received:\", {\n message,\n event,\n });\n }\n\n const { payload } = message;\n const { message: originalMessage, transferables = [] } = payload;\n const rpcEvent = new MessageEvent(\"message\", {\n data: originalMessage,\n ports:\n (transferables.filter(\n (t: unknown) => t instanceof MessagePort\n ) as MessagePort[]) || [],\n });\n listener(rpcEvent);\n } catch (e) {\n logger.error(\"Failed to parse RPC message payload:\", e);\n }\n },\n });\n },\n removeEventListener: () => {\n // Porter-source doesn't support removing listeners\n },\n // Add context information\n context: {\n isServiceWorker,\n agentInfo: !isServiceWorker\n ? (porterInstance as AgentAPI).getAgentInfo()\n : undefined,\n },\n };\n\n return createEndpoint(messageEndpoint, stateGetter, actions, setState);\n}\n\n// Don't love this being here. Let's move it sometime soon,\n// or find another way to do this.\nfunction getTargetFromMessage(payload: RPCMessage): any {\n if (\"result\" in payload) return payload.result.target;\n if (\"error\" in payload) return payload.error.target;\n if (\"call\" in payload) return payload.call.target;\n if (\"release\" in payload) return payload.release.target;\n return undefined;\n}\n", "import {\n ConfigItem,\n DerivedState,\n StateSubscriber,\n ConnectReturn,\n UseCrann,\n ConnectionStatus,\n StateChangeUpdate,\n ActionDefinition,\n AnyConfig,\n isStateItem,\n isActionItem,\n StateChanges,\n} from \"./model/crann.model\";\nimport { AgentInfo, connect as connectPorter } from \"./transport\";\nimport { createCrannRPCAdapter } from \"./rpc/adapter\";\nimport { Logger } from \"./utils/logger\";\nimport { getAgentTag } from \"./utils/agent\";\n\nlet connectionStatus: ConnectionStatus = { connected: false };\nlet crannInstance: unknown = null;\n\n// Callbacks for disconnect/reconnect events\nconst disconnectCallbacks = new Set<() => void>();\nconst reconnectCallbacks = new Set<(info: AgentInfo) => void>();\n\nexport function connect<TConfig extends AnyConfig>(\n config: TConfig,\n options?: { context?: string; debug?: boolean }\n): ConnectReturn<TConfig> {\n const debug = options?.debug || false;\n const context = options?.context;\n\n // Set up logger\n if (debug) {\n Logger.setDebug(true);\n }\n const logger = Logger.forContext(\"Agent\");\n\n let _myInfo: AgentInfo;\n let _myTag = \"unset\";\n const readyCallbacks = new Set<(info: ConnectionStatus) => void>();\n\n logger.log(\n \"Initializing Crann Agent\" + (context ? ` with context: ${context}` : \"\")\n );\n if (crannInstance && connectionStatus.connected) {\n logger.log(\"We had an instance already and it's connected, returning\");\n\n logger.log(\"Connect, calling onReady callback\");\n setTimeout(() => {\n readyCallbacks.forEach((callback) => callback(connectionStatus));\n }, 0);\n return crannInstance as ConnectReturn<TConfig>;\n }\n\n if (crannInstance && !connectionStatus.connected) {\n logger.log(\"We had an instance but it's disconnected, creating new connection\");\n // Reset the instance to allow reconnection\n crannInstance = null;\n }\n\n logger.log(\"No existing instance, creating a new one\");\n const porter = connectPorter({\n namespace: \"crann\",\n debug: false,\n });\n\n logger.log(\"Porter connection created\");\n\n // Handle Porter disconnect/reconnect events\n porter.onDisconnect(() => {\n logger.log(\"Porter connection lost, updating connection status\");\n connectionStatus = { connected: false };\n \n // Notify disconnect callbacks\n disconnectCallbacks.forEach((callback) => {\n try {\n callback();\n } catch (error) {\n logger.error(\"Error in disconnect callback:\", error);\n }\n });\n \n // Notify onReady callbacks about disconnection\n readyCallbacks.forEach((callback) => {\n try {\n callback(connectionStatus);\n } catch (error) {\n logger.error(\"Error in onReady callback during disconnect:\", error);\n }\n });\n });\n\n porter.onReconnect((info: AgentInfo) => {\n logger.log(\"Porter reconnected, updating connection status\", info);\n connectionStatus = { connected: true, agent: info };\n \n // Update agent info\n _myInfo = info;\n _myTag = getAgentTag(info);\n logger.setTag(_myTag);\n \n // Notify reconnect callbacks\n reconnectCallbacks.forEach((callback) => {\n try {\n callback(info);\n } catch (error) {\n logger.error(\"Error in reconnect callback:\", error);\n }\n });\n \n // Notify onReady callbacks about reconnection\n readyCallbacks.forEach((callback) => {\n try {\n callback(connectionStatus);\n } catch (error) {\n logger.error(\"Error in onReady callback during reconnect:\", error);\n }\n });\n });\n\n // Initialize RPC with empty actions since this is the client side\n const actions = Object.entries(config)\n .filter(([_, value]) => isActionItem(value))\n .reduce<\n Record<string, ActionDefinition<DerivedState<TConfig>, any[], any>>\n >((acc, [key, value]) => {\n const action = value as ActionDefinition<\n DerivedState<TConfig>,\n any[],\n any\n >;\n return {\n ...acc,\n [key]: {\n type: \"action\",\n handler: action.handler,\n validate: action.validate,\n },\n };\n }, {});\n\n const rpcEndpoint = createCrannRPCAdapter(\n () => getDerivedState(config),\n actions,\n porter\n );\n\n let initialStateReceived = false;\n\n porter.on({\n initialState: (message) => {\n logger.log(\"initialState received\", {\n alreadyReceived: initialStateReceived,\n payload: message.payload,\n });\n\n if (initialStateReceived) {\n logger.log(\"Ignoring duplicate initialState message\");\n return;\n }\n\n initialStateReceived = true;\n\n _state = message.payload.state;\n _myInfo = message.payload.info;\n _myTag = getAgentTag(_myInfo);\n connectionStatus = { connected: true, agent: _myInfo };\n\n // Update logger with the agent tag once we have it\n logger.setTag(_myTag);\n logger.log(\n `Initial state received and ${listeners.size} listeners notified`,\n {\n message,\n }\n );\n readyCallbacks.forEach((callback) => {\n logger.log(\"Calling onReady callbacks\");\n callback(connectionStatus);\n });\n listeners.forEach((listener) => {\n listener.callback(_state as StateChanges<TConfig>);\n });\n },\n stateUpdate: (message) => {\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n logger.log(\"State updated:\", { message, changes, _state });\n if (!changes) return;\n\n listeners.forEach((listener) => {\n if (listener.keys === undefined) {\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some((key) => key in changes!);\n if (matchFound) {\n listener.callback(changes!);\n }\n }\n });\n },\n });\n logger.log(\"Porter connected. Setting up state and listeners\");\n let _state = getDerivedState(config);\n let changes: StateChanges<TConfig> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n\n logger.log(\"Completed setup, returning instance\");\n\n const get = () => _state;\n const set = (newState: StateChanges<TConfig>) => {\n logger.log(\"Calling post with setState\", newState);\n porter.post({ action: \"setState\", payload: { state: newState } });\n };\n\n const subscribe = (\n callback: (changes: StateChanges<TConfig>) => void,\n keys?: Array<keyof DerivedState<TConfig>>\n ): (() => void) => {\n const listener = { keys, callback };\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n const useCrann: UseCrann<TConfig> = <K extends keyof DerivedState<TConfig>>(\n key: K\n ) => {\n const getValue = () => {\n const value = get()[key];\n return value as TConfig[K] extends ConfigItem<any>\n ? TConfig[K][\"default\"]\n : never;\n };\n\n const setValue = (\n value: TConfig[K] extends ConfigItem<any> ? TConfig[K][\"default\"] : never\n ) => set({ [key]: value } as StateChanges<TConfig>);\n\n const subscribeToChanges = (\n callback: (update: StateChangeUpdate<TConfig, K>) => void\n ) => {\n let previousValue = getValue();\n\n return subscribe(\n (changes) => {\n if (key in changes) {\n const currentValue = getValue();\n const fullState = get();\n callback({\n current: currentValue,\n previous: previousValue,\n state: fullState,\n } as StateChangeUpdate<TConfig, K>);\n previousValue = currentValue;\n }\n },\n [key]\n );\n };\n\n return [getValue(), setValue, subscribeToChanges];\n };\n\n const onReady = (callback: (info: ConnectionStatus) => void) => {\n logger.log(\"onReady callback added\");\n readyCallbacks.add(callback);\n if (connectionStatus.connected) {\n logger.log(\"calling onReady callback\");\n setTimeout(() => {\n callback(connectionStatus);\n }, 0);\n }\n return () => readyCallbacks.delete(callback);\n };\n\n const getAgentInfo = () => _myInfo;\n\n const callAction = async (name: string, ...args: any[]) => {\n logger.log(\"Calling action\", name, args);\n return (rpcEndpoint as any)[name](...args);\n };\n\n const onDisconnect = (callback: () => void): (() => void) => {\n logger.log(\"onDisconnect callback added\");\n disconnectCallbacks.add(callback);\n return () => {\n disconnectCallbacks.delete(callback);\n };\n };\n\n const onReconnect = (callback: (info: AgentInfo) => void): (() => void) => {\n logger.log(\"onReconnect callback added\");\n reconnectCallbacks.add(callback);\n return () => {\n reconnectCallbacks.delete(callback);\n };\n };\n\n const instance = {\n useCrann,\n get,\n set,\n subscribe,\n getAgentInfo,\n onReady,\n callAction,\n onDisconnect,\n onReconnect,\n };\n\n crannInstance = instance;\n\n return crannInstance as ConnectReturn<TConfig>;\n}\n\nexport function connected(): boolean {\n return crannInstance !== null;\n}\n\nfunction getDerivedState<TConfig extends AnyConfig>(\n config: TConfig\n): DerivedState<TConfig> {\n const state: any = {};\n Object.keys(config).forEach((key) => {\n const item = config[key];\n if (isStateItem(item)) {\n state[key] = item.default;\n }\n });\n return state;\n}\n", "import { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport {\n AnyConfig,\n ConfigItem,\n DerivedState,\n StateChanges,\n StateUpdate,\n} from \"../model/crann.model\";\nimport { connect } from \"../crannAgent\";\n\nexport function createCrannStateHook<TConfig extends AnyConfig>(\n config: TConfig\n) {\n return function useCrannState(context?: string) {\n const { useCrann, get, set, subscribe, callAction } = useMemo(() => {\n const instance = connect(config);\n return instance;\n }, [context]);\n\n const useStateItem = useCallback(\n <K extends keyof DerivedState<TConfig>>(key: K) => {\n const [value, setValue] = useState<DerivedState<TConfig>[K]>(\n get()[key]\n );\n const valueRef = useRef(value);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n setValue(get()[key]);\n const unsubscribe = subscribe(\n (changes: StateUpdate<TConfig>) => {\n if (key in changes) {\n setValue(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n return unsubscribe;\n }, [key]);\n\n const updateValue = useCallback(\n (newValue: DerivedState<TConfig>[K]) => {\n set({ [key]: newValue } as StateChanges<TConfig>);\n },\n [key]\n );\n\n return [value, updateValue] as const;\n },\n [get, set, subscribe]\n );\n\n const getState = useCallback(() => get(), [get]);\n\n const setState = useCallback(\n (newState: StateChanges<TConfig>) => {\n set(newState);\n },\n [set]\n );\n\n return {\n useStateItem,\n getState,\n setState,\n useCrann,\n callAction,\n };\n };\n}\n", "import { AnyConfig } from \"../model/crann.model\";\n\nexport function createConfig<T extends AnyConfig>(config: T): T {\n return config;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["browser", "Partition", "Persistence", "isStateItem", "item", "isActionItem", "browser", "PorterContext", "PorterError", "type", "message", "details", "isServiceWorker", "_Logger", "context", "_a", "_b", "_c", "options", "message", "args", "Logger", "browser", "uuidv4", "AgentManager", "logger", "port", "context", "_a", "_b", "connectionSource", "determinedContext", "tabId", "frameId", "tabAgentsInfo", "info", "agentId", "uuidv4", "agentInfo", "message", "agent", "location", "infoEntry", "key", "value", "hasContext", "hasTabId", "hasFrameId", "id", "p", "allAgents", "allAgentsInfo", "event", "handler", "handlers", "args", "_c", "_d", "_e", "_f", "_g", "sender", "manifest", "browser", "sidePanel", "optionsPage", "popupPage", "devtoolsPage", "newTabOverride", "bookmarksOverride", "historyOverride", "pageMatchers", "filename", "pageType", "pageMatcher", "ConnectionManager", "agentOperations", "namespace", "logger", "port", "PorterError", "e", "error", "message", "connectionId", "agentId", "agent", "porterError", "MessageHandler", "agentOperations", "logger", "message", "agent", "_a", "agentInfo", "target", "resolve", "reject", "timeoutId", "error", "isBrowserLocation", "isPorterContext", "errorMessage", "tabId", "agents", "PorterError", "location", "context", "port", "agentId", "config", "listener", "messageListener", "event", "handler", "info", "arg", "messageEvent", "handlerCount", "PorterContext", "_PorterSource", "namespace", "options", "Logger", "AgentManager", "MessageHandler", "ConnectionManager", "isServiceWorker", "PorterError", "message", "metadata", "agent", "browser", "target", "config", "listener", "key", "_a", "agentId", "location", "PorterSource", "source", "instance", "browser", "MessageQueue", "logger", "message", "target", "oldCount", "messages", "now", "item", "AgentConnectionManager", "namespace", "logger", "MessageQueue", "callback", "error", "info", "_a", "portName", "browser", "handshakePromise", "resolve", "reject", "timeout", "PorterError", "onMessage", "message", "_b", "messages", "target", "messageToSend", "port", "AgentMessageHandler", "logger", "port", "message", "config", "action", "handler", "item", "actionHandlers", "target", "error", "PorterError", "_PorterAgent", "options", "_a", "_b", "namespace", "context", "Logger", "AgentConnectionManager", "AgentMessageHandler", "info", "port", "message", "p", "config", "target", "error", "callback", "PorterAgent", "connect", "porterInstance", "useState", "useEffect", "useCallback", "useRef", "useMemo", "deepEqual", "a", "b", "keysA", "keysB", "i", "key", "_DebugManager", "value", "DebugManager", "isDebugEnabled", "trackStateChange", "target", "propertyKey", "descriptor", "originalMethod", "args", "_a", "isDebugEnabled", "stack", "callerMatch", "caller", "changes", "metadata", "_Logger", "context", "value", "tag", "tempLogger", "fullContext", "formatString", "prefixStyle", "contextStyle", "resetStyle", "logger", "Logger", "getAgentTag", "agent", "options", "formattedTabId", "tabId", "tabIdStr", "createEndpoint", "messenger", "stateGetter", "actions", "setState", "encodingStrategy", "_a", "_b", "callbacks", "retainedObjects", "contextPrefix", "logger", "Logger", "getAgentTag", "event", "id", "message", "callMessage", "callId", "args", "target", "action", "currentState", "result", "error", "resultMessage", "callback", "errorMessage", "releaseMessage", "retainers", "_", "prop", "resolve", "reject", "createCrannRPCAdapter", "stateGetter", "actions", "porter", "setState", "porterInstance", "source", "isServiceWorker", "logger", "Logger", "messageEndpoint", "message", "transferables", "rpcPayload", "target", "getTargetFromMessage", "agentInfo", "myTag", "getAgentTag", "event", "listener", "info", "payload", "originalMessage", "rpcEvent", "t", "e", "createEndpoint", "_Crann", "config", "options", "source", "_a", "DebugManager", "Logger", "message", "info", "agentTag", "getAgentTag", "agentsInitialized", "fullState", "genericSetState", "state", "key", "actions", "stateGetter", "currentState", "createCrannRPCAdapter", "initialInstanceState", "update", "deepEqual", "wasPersisted", "persistence", "value", "browser", "_", "listener", "changes", "agent", "location", "instance", "query", "worker", "itemKey", "item", "isConfigItem", "instanceItemKey", "instanceState", "Partition", "serviceItemKey", "serviceState", "local", "session", "combined", "hadItems", "prefixedKey", "isStateItem", "instanceId", "index", "isActionItem", "acc", "action", "__decorateClass", "trackStateChange", "Crann", "create", "connectionStatus", "crannInstance", "disconnectCallbacks", "reconnectCallbacks", "connect", "config", "options", "debug", "context", "Logger", "logger", "_myInfo", "_myTag", "readyCallbacks", "callback", "porter", "error", "info", "getAgentTag", "actions", "_", "value", "isActionItem", "acc", "key", "action", "rpcEndpoint", "createCrannRPCAdapter", "getDerivedState", "initialStateReceived", "message", "_state", "listeners", "listener", "changes", "get", "set", "newState", "subscribe", "keys", "getValue", "setValue", "subscribeToChanges", "previousValue", "currentValue", "fullState", "name", "args", "connected", "state", "item", "isStateItem", "useState", "useEffect", "useCallback", "useMemo", "useRef", "createCrannStateHook", "config", "context", "useCrann", "get", "set", "subscribe", "callAction", "useMemo", "connect", "useStateItem", "useCallback", "key", "value", "setValue", "useState", "valueRef", "useRef", "useEffect", "changes", "updateValue", "newValue", "getState", "setState", "newState", "createConfig", "config"]
|
|
7
7
|
}
|