@memberjunction/ng-conversations 5.30.1 → 5.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts +2 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +9 -6
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts +2 -1
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.js +9 -6
- package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.js +8 -5
- package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.js +9 -6
- package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
- package/dist/lib/components/collection/collection-view.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +12 -10
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts +2 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.js +18 -12
- package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +2 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +22 -11
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/library/library-full-view.component.d.ts +2 -1
- package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/library/library-full-view.component.js +8 -5
- package/dist/lib/components/library/library-full-view.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts +2 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +9 -7
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +2 -1
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +12 -5
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +6 -1
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts +2 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.js +6 -6
- package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.d.ts +2 -1
- package/dist/lib/components/project/project-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.js +6 -5
- package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
- package/dist/lib/components/project/project-selector.component.d.ts +2 -1
- package/dist/lib/components/project/project-selector.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-selector.component.js +8 -6
- package/dist/lib/components/project/project-selector.component.js.map +1 -1
- package/dist/lib/components/share/share-modal.component.d.ts +2 -1
- package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/share/share-modal.component.js +11 -9
- package/dist/lib/components/share/share-modal.component.js.map +1 -1
- package/dist/lib/components/shared/user-picker.component.d.ts +2 -1
- package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
- package/dist/lib/components/shared/user-picker.component.js +6 -4
- package/dist/lib/components/shared/user-picker.component.js.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts +2 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.js +9 -8
- package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +5 -0
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.d.ts +2 -1
- package/dist/lib/components/thread/thread-panel.component.d.ts.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.js +7 -4
- package/dist/lib/components/thread/thread-panel.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +8 -4
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/models/lazy-artifact-info.js +1 -1
- package/dist/lib/models/lazy-artifact-info.js.map +1 -1
- package/dist/lib/services/active-tasks.service.d.ts +7 -1
- package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
- package/dist/lib/services/active-tasks.service.js +12 -2
- package/dist/lib/services/active-tasks.service.js.map +1 -1
- package/dist/lib/services/agent-state.service.d.ts +7 -1
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +12 -2
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/artifact-permission.service.d.ts +8 -1
- package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-permission.service.js +21 -7
- package/dist/lib/services/artifact-permission.service.js.map +1 -1
- package/dist/lib/services/artifact-state.service.d.ts +8 -1
- package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +25 -11
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/artifact-use-tracking.service.d.ts +7 -1
- package/dist/lib/services/artifact-use-tracking.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-use-tracking.service.js +12 -2
- package/dist/lib/services/artifact-use-tracking.service.js.map +1 -1
- package/dist/lib/services/collection-permission.service.d.ts +7 -1
- package/dist/lib/services/collection-permission.service.d.ts.map +1 -1
- package/dist/lib/services/collection-permission.service.js +19 -9
- package/dist/lib/services/collection-permission.service.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +8 -0
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +15 -3
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts +7 -1
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js +12 -2
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/data-cache.service.d.ts +7 -1
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +16 -7
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/export.service.d.ts +7 -1
- package/dist/lib/services/export.service.d.ts.map +1 -1
- package/dist/lib/services/export.service.js +12 -2
- package/dist/lib/services/export.service.js.map +1 -1
- package/dist/lib/services/search.service.d.ts +7 -1
- package/dist/lib/services/search.service.d.ts.map +1 -1
- package/dist/lib/services/search.service.js +16 -6
- package/dist/lib/services/search.service.js.map +1 -1
- package/package.json +22 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-tasks.service.js","sourceRoot":"","sources":["../../../src/lib/services/active-tasks.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { RunView, UserInfo } from '@memberjunction/core';\nimport { MJAIAgentRunEntity } from '@memberjunction/core-entities';\nimport { ConversationEngine } from '@memberjunction/core-entities';\n\n/**\n * Represents an active agent task that is currently running\n */\nexport interface ActiveTask {\n id: string;\n agentName: string;\n agentId?: string; // The agent ID for looking up icon/metadata\n agentRunId?: string; // The AIAgentRun ID for finding task on completion\n status: string;\n relatedMessageId: string;\n conversationDetailId?: string; // The ConversationDetail that tracks this task\n conversationId?: string; // The conversation this task belongs to\n conversationName?: string | null; // Display name of the conversation\n startTime: number;\n}\n\n/**\n * Service for tracking active agent tasks across the application.\n * Maintains a live list of running agents and their status.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ActiveTasksService {\n private _tasks$ = new BehaviorSubject<Map<string, ActiveTask>>(new Map());\n private _conversationIdsWithTasks$ = new BehaviorSubject<Set<string>>(new Set());\n private engine = ConversationEngine.Instance;\n\n /**\n * Observable of all active tasks as an array\n */\n public readonly tasks$: Observable<ActiveTask[]> = this._tasks$.pipe(\n map(taskMap => Array.from(taskMap.values()))\n );\n\n /**\n * Observable of the count of active tasks\n */\n public readonly taskCount$: Observable<number> = this.tasks$.pipe(\n map(tasks => tasks.length)\n );\n\n /**\n * Observable of conversation IDs that have 1+ active tasks\n * Use this for quick lookups in conversation lists\n */\n public readonly conversationIdsWithTasks$: Observable<Set<string>> = this._conversationIdsWithTasks$.asObservable();\n\n /**\n * Observable of tasks grouped by conversation ID\n * Returns Map<conversationId, ActiveTask[]>\n */\n public readonly tasksByConversationId$: Observable<Map<string, ActiveTask[]>> = this.tasks$.pipe(\n map(tasks => {\n const grouped = new Map<string, ActiveTask[]>();\n for (const task of tasks) {\n if (task.conversationId) {\n const existing = grouped.get(task.conversationId) || [];\n existing.push(task);\n grouped.set(task.conversationId, existing);\n }\n }\n return grouped;\n })\n );\n\n /**\n * Add a new active task\n * @param task Task details (without id and startTime)\n * @returns The generated task ID\n */\n add(task: Omit<ActiveTask, 'id' | 'startTime'>): string {\n const id = `task-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n const fullTask = {\n ...task,\n id,\n startTime: Date.now()\n };\n const current = this._tasks$.value;\n current.set(id, fullTask);\n this._tasks$.next(new Map(current));\n\n // Update conversation IDs set\n if (fullTask.conversationId) {\n this.updateConversationIdsSet();\n }\n\n console.log(`➕ Task added:`, {id, conversationId: fullTask.conversationId, agentName: fullTask.agentName});\n console.log(`📊 Total tasks:`, this._tasks$.value.size);\n console.log(`🗂️ Conversation IDs with tasks:`, Array.from(this._conversationIdsWithTasks$.value));\n\n return id;\n }\n\n /**\n * Remove an active task\n * @param id The task ID to remove\n */\n remove(id: string): void {\n const current = this._tasks$.value;\n const task = current.get(id);\n current.delete(id);\n this._tasks$.next(new Map(current));\n\n // Update conversation IDs set if this was the last task for a conversation\n if (task?.conversationId) {\n this.updateConversationIdsSet();\n }\n\n console.log(`➖ Task removed:`, {id, conversationId: task?.conversationId, agentName: task?.agentName});\n console.log(`📊 Total tasks remaining:`, this._tasks$.value.size);\n console.log(`🗂️ Conversation IDs with tasks:`, Array.from(this._conversationIdsWithTasks$.value));\n }\n\n /**\n * Update the set of conversation IDs with active tasks\n * @private\n */\n private updateConversationIdsSet(): void {\n const conversationIds = new Set<string>();\n for (const task of this._tasks$.value.values()) {\n if (task.conversationId) {\n conversationIds.add(task.conversationId);\n }\n }\n this._conversationIdsWithTasks$.next(conversationIds);\n }\n\n /**\n * Update the status of an active task\n * @param id The task ID\n * @param status The new status text\n */\n updateStatus(id: string, status: string): void {\n const current = this._tasks$.value;\n const task = current.get(id);\n if (task) {\n task.status = status;\n this._tasks$.next(new Map(current));\n }\n }\n\n /**\n * Get an active task by its conversation detail ID\n * @param conversationDetailId The conversation detail ID\n * @returns The task if found, undefined otherwise\n */\n getByConversationDetailId(conversationDetailId: string): ActiveTask | undefined {\n const tasks = Array.from(this._tasks$.value.values());\n return tasks.find(task => task.conversationDetailId === conversationDetailId);\n }\n\n /**\n * Update the status of a task by its conversation detail ID\n * @param conversationDetailId The conversation detail ID\n * @param status The new status text\n * @returns true if task was found and updated, false otherwise\n */\n updateStatusByConversationDetailId(conversationDetailId: string, status: string): boolean {\n const task = this.getByConversationDetailId(conversationDetailId);\n if (task) {\n this.updateStatus(task.id, status);\n return true;\n }\n return false;\n }\n\n /**\n * Get an active task by its agent run ID\n * @param agentRunId The AIAgentRun ID\n * @returns The task if found, undefined otherwise\n */\n getByAgentRunId(agentRunId: string): ActiveTask | undefined {\n const tasks = Array.from(this._tasks$.value.values());\n return tasks.find(task => task.agentRunId === agentRunId);\n }\n\n /**\n * Remove a task by its agent run ID\n * @param agentRunId The AIAgentRun ID\n * @returns true if task was found and removed, false otherwise\n */\n removeByAgentRunId(agentRunId: string): boolean {\n const task = this.getByAgentRunId(agentRunId);\n if (task) {\n this.remove(task.id);\n return true;\n }\n return false;\n }\n\n /**\n * Clear all active tasks\n */\n clear(): void {\n this._tasks$.next(new Map());\n }\n\n /**\n * Restore active tasks from database by querying running agent runs.\n * Call this on app initialization to restore state after browser refresh.\n * @param currentUser The current user to filter agent runs by\n */\n async restoreFromDatabase(currentUser: UserInfo): Promise<void> {\n try {\n const rv = new RunView();\n\n // Query for running agent runs owned by this user\n // Only restore parent agents (those with ConversationDetailID) - child agents don't have one\n // This matches normal behavior where we only track parent agents, not child agents\n const result = await rv.RunView<MJAIAgentRunEntity>({\n EntityName: 'MJ: AI Agent Runs',\n Fields: [\"ID\", \"ConversationID\", \"AgentID\", \"Agent\", \"ConversationDetailID\"], // narrow field scope to not pull back JSON blobs - much faster\n ExtraFilter: `Status='Running' AND UserID='${currentUser.ID}' AND ConversationDetailID IS NOT NULL`,\n ResultType: 'simple' // no need for entity-object here we aren't mutating\n }, currentUser);\n\n if (!result.Success || !result.Results || result.Results.length === 0) {\n // No running tasks or query failed - nothing to restore\n return;\n }\n\n // Get conversation names from cached ConversationEngine\n const conversationNames = new Map<string, string>();\n for (const agentRun of result.Results) {\n if (agentRun.ConversationID) {\n const conv = this.engine.GetConversation(agentRun.ConversationID);\n if (conv?.Name) {\n conversationNames.set(agentRun.ConversationID, conv.Name);\n }\n }\n }\n\n // Add each running agent to ActiveTasksService\n let restoredCount = 0;\n for (const agentRun of result.Results) {\n // Skip if already tracked (prevents duplicates)\n if (agentRun.ConversationDetailID &&\n this.getByConversationDetailId(agentRun.ConversationDetailID)) {\n continue;\n }\n\n this.add({\n agentName: agentRun.Agent || 'Unknown Agent',\n agentId: agentRun.AgentID,\n agentRunId: agentRun.ID, // For finding task on completion\n status: 'Reconnecting...',\n relatedMessageId: agentRun.ConversationDetailID || agentRun.ID,\n conversationDetailId: agentRun.ConversationDetailID || undefined,\n conversationId: agentRun.ConversationID || undefined,\n conversationName: agentRun.ConversationID\n ? conversationNames.get(agentRun.ConversationID) || null\n : null\n });\n restoredCount++;\n }\n\n if (restoredCount > 0) {\n console.log(`✅ Restored ${restoredCount} active task(s) from database`);\n }\n } catch (error) {\n console.error('Failed to restore active tasks from database:', error);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"active-tasks.service.js","sourceRoot":"","sources":["../../../src/lib/services/active-tasks.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { RunView, UserInfo, Metadata, IMetadataProvider } from '@memberjunction/core';\nimport { MJAIAgentRunEntity } from '@memberjunction/core-entities';\nimport { ConversationEngine } from '@memberjunction/core-entities';\n\n/**\n * Represents an active agent task that is currently running\n */\nexport interface ActiveTask {\n id: string;\n agentName: string;\n agentId?: string; // The agent ID for looking up icon/metadata\n agentRunId?: string; // The AIAgentRun ID for finding task on completion\n status: string;\n relatedMessageId: string;\n conversationDetailId?: string; // The ConversationDetail that tracks this task\n conversationId?: string; // The conversation this task belongs to\n conversationName?: string | null; // Display name of the conversation\n startTime: number;\n}\n\n/**\n * Service for tracking active agent tasks across the application.\n * Maintains a live list of running agents and their status.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ActiveTasksService {\n private _tasks$ = new BehaviorSubject<Map<string, ActiveTask>>(new Map());\n private _conversationIdsWithTasks$ = new BehaviorSubject<Set<string>>(new Set());\n private engine = ConversationEngine.Instance;\n private _provider: IMetadataProvider | null = null;\n\n /**\n * Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.\n */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n /**\n * Observable of all active tasks as an array\n */\n public readonly tasks$: Observable<ActiveTask[]> = this._tasks$.pipe(\n map(taskMap => Array.from(taskMap.values()))\n );\n\n /**\n * Observable of the count of active tasks\n */\n public readonly taskCount$: Observable<number> = this.tasks$.pipe(\n map(tasks => tasks.length)\n );\n\n /**\n * Observable of conversation IDs that have 1+ active tasks\n * Use this for quick lookups in conversation lists\n */\n public readonly conversationIdsWithTasks$: Observable<Set<string>> = this._conversationIdsWithTasks$.asObservable();\n\n /**\n * Observable of tasks grouped by conversation ID\n * Returns Map<conversationId, ActiveTask[]>\n */\n public readonly tasksByConversationId$: Observable<Map<string, ActiveTask[]>> = this.tasks$.pipe(\n map(tasks => {\n const grouped = new Map<string, ActiveTask[]>();\n for (const task of tasks) {\n if (task.conversationId) {\n const existing = grouped.get(task.conversationId) || [];\n existing.push(task);\n grouped.set(task.conversationId, existing);\n }\n }\n return grouped;\n })\n );\n\n /**\n * Add a new active task\n * @param task Task details (without id and startTime)\n * @returns The generated task ID\n */\n add(task: Omit<ActiveTask, 'id' | 'startTime'>): string {\n const id = `task-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n const fullTask = {\n ...task,\n id,\n startTime: Date.now()\n };\n const current = this._tasks$.value;\n current.set(id, fullTask);\n this._tasks$.next(new Map(current));\n\n // Update conversation IDs set\n if (fullTask.conversationId) {\n this.updateConversationIdsSet();\n }\n\n console.log(`➕ Task added:`, {id, conversationId: fullTask.conversationId, agentName: fullTask.agentName});\n console.log(`📊 Total tasks:`, this._tasks$.value.size);\n console.log(`🗂️ Conversation IDs with tasks:`, Array.from(this._conversationIdsWithTasks$.value));\n\n return id;\n }\n\n /**\n * Remove an active task\n * @param id The task ID to remove\n */\n remove(id: string): void {\n const current = this._tasks$.value;\n const task = current.get(id);\n current.delete(id);\n this._tasks$.next(new Map(current));\n\n // Update conversation IDs set if this was the last task for a conversation\n if (task?.conversationId) {\n this.updateConversationIdsSet();\n }\n\n console.log(`➖ Task removed:`, {id, conversationId: task?.conversationId, agentName: task?.agentName});\n console.log(`📊 Total tasks remaining:`, this._tasks$.value.size);\n console.log(`🗂️ Conversation IDs with tasks:`, Array.from(this._conversationIdsWithTasks$.value));\n }\n\n /**\n * Update the set of conversation IDs with active tasks\n * @private\n */\n private updateConversationIdsSet(): void {\n const conversationIds = new Set<string>();\n for (const task of this._tasks$.value.values()) {\n if (task.conversationId) {\n conversationIds.add(task.conversationId);\n }\n }\n this._conversationIdsWithTasks$.next(conversationIds);\n }\n\n /**\n * Update the status of an active task\n * @param id The task ID\n * @param status The new status text\n */\n updateStatus(id: string, status: string): void {\n const current = this._tasks$.value;\n const task = current.get(id);\n if (task) {\n task.status = status;\n this._tasks$.next(new Map(current));\n }\n }\n\n /**\n * Get an active task by its conversation detail ID\n * @param conversationDetailId The conversation detail ID\n * @returns The task if found, undefined otherwise\n */\n getByConversationDetailId(conversationDetailId: string): ActiveTask | undefined {\n const tasks = Array.from(this._tasks$.value.values());\n return tasks.find(task => task.conversationDetailId === conversationDetailId);\n }\n\n /**\n * Update the status of a task by its conversation detail ID\n * @param conversationDetailId The conversation detail ID\n * @param status The new status text\n * @returns true if task was found and updated, false otherwise\n */\n updateStatusByConversationDetailId(conversationDetailId: string, status: string): boolean {\n const task = this.getByConversationDetailId(conversationDetailId);\n if (task) {\n this.updateStatus(task.id, status);\n return true;\n }\n return false;\n }\n\n /**\n * Get an active task by its agent run ID\n * @param agentRunId The AIAgentRun ID\n * @returns The task if found, undefined otherwise\n */\n getByAgentRunId(agentRunId: string): ActiveTask | undefined {\n const tasks = Array.from(this._tasks$.value.values());\n return tasks.find(task => task.agentRunId === agentRunId);\n }\n\n /**\n * Remove a task by its agent run ID\n * @param agentRunId The AIAgentRun ID\n * @returns true if task was found and removed, false otherwise\n */\n removeByAgentRunId(agentRunId: string): boolean {\n const task = this.getByAgentRunId(agentRunId);\n if (task) {\n this.remove(task.id);\n return true;\n }\n return false;\n }\n\n /**\n * Clear all active tasks\n */\n clear(): void {\n this._tasks$.next(new Map());\n }\n\n /**\n * Restore active tasks from database by querying running agent runs.\n * Call this on app initialization to restore state after browser refresh.\n * @param currentUser The current user to filter agent runs by\n */\n async restoreFromDatabase(currentUser: UserInfo): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Query for running agent runs owned by this user\n // Only restore parent agents (those with ConversationDetailID) - child agents don't have one\n // This matches normal behavior where we only track parent agents, not child agents\n const result = await rv.RunView<MJAIAgentRunEntity>({\n EntityName: 'MJ: AI Agent Runs',\n Fields: [\"ID\", \"ConversationID\", \"AgentID\", \"Agent\", \"ConversationDetailID\"], // narrow field scope to not pull back JSON blobs - much faster\n ExtraFilter: `Status='Running' AND UserID='${currentUser.ID}' AND ConversationDetailID IS NOT NULL`,\n ResultType: 'simple' // no need for entity-object here we aren't mutating\n }, currentUser);\n\n if (!result.Success || !result.Results || result.Results.length === 0) {\n // No running tasks or query failed - nothing to restore\n return;\n }\n\n // Get conversation names from cached ConversationEngine\n const conversationNames = new Map<string, string>();\n for (const agentRun of result.Results) {\n if (agentRun.ConversationID) {\n const conv = this.engine.GetConversation(agentRun.ConversationID);\n if (conv?.Name) {\n conversationNames.set(agentRun.ConversationID, conv.Name);\n }\n }\n }\n\n // Add each running agent to ActiveTasksService\n let restoredCount = 0;\n for (const agentRun of result.Results) {\n // Skip if already tracked (prevents duplicates)\n if (agentRun.ConversationDetailID &&\n this.getByConversationDetailId(agentRun.ConversationDetailID)) {\n continue;\n }\n\n this.add({\n agentName: agentRun.Agent || 'Unknown Agent',\n agentId: agentRun.AgentID,\n agentRunId: agentRun.ID, // For finding task on completion\n status: 'Reconnecting...',\n relatedMessageId: agentRun.ConversationDetailID || agentRun.ID,\n conversationDetailId: agentRun.ConversationDetailID || undefined,\n conversationId: agentRun.ConversationID || undefined,\n conversationName: agentRun.ConversationID\n ? conversationNames.get(agentRun.ConversationID) || null\n : null\n });\n restoredCount++;\n }\n\n if (restoredCount > 0) {\n console.log(`✅ Restored ${restoredCount} active task(s) from database`);\n }\n } catch (error) {\n console.error('Failed to restore active tasks from database:', error);\n }\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OnDestroy } from '@angular/core';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
|
-
import { UserInfo } from '@memberjunction/core';
|
|
3
|
+
import { UserInfo, IMetadataProvider } from '@memberjunction/core';
|
|
4
4
|
import { MJAIAgentRunEntity } from '@memberjunction/core-entities';
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
export type AgentStatus = 'acknowledging' | 'working' | 'completing' | 'completed' | 'error';
|
|
@@ -23,7 +23,13 @@ export declare class AgentStateService implements OnDestroy {
|
|
|
23
23
|
* when fire-and-forget ACK returns before the server creates the agent run record. */
|
|
24
24
|
private readonly minimumPollCycles;
|
|
25
25
|
readonly activeAgents$: Observable<AgentWithStatus[]>;
|
|
26
|
+
private _provider;
|
|
26
27
|
constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.
|
|
30
|
+
*/
|
|
31
|
+
set Provider(value: IMetadataProvider | null);
|
|
32
|
+
get Provider(): IMetadataProvider;
|
|
27
33
|
ngOnDestroy(): void;
|
|
28
34
|
/**
|
|
29
35
|
* Starts polling for active agents
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-state.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/agent-state.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAmB,UAAU,EAA0B,MAAM,MAAM,CAAC;AAE3E,OAAO,EAAwB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-state.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/agent-state.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAmB,UAAU,EAA0B,MAAM,MAAM,CAAC;AAE3E,OAAO,EAAwB,QAAQ,EAAY,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEnG,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;;AAEnE,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAE7F,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,kBAAkB,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAGa,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,gBAAgB,CAAC,CAAe;IACxC,OAAO,CAAC,WAAW,CAAC,CAAW;IAC/B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,cAAc,CAAK;IAC3B;2FACuF;IACvF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAK;IAGvC,SAAgB,aAAa,gCAAsC;IAEnE,OAAO,CAAC,SAAS,CAAkC;;IAInD;;OAEG;IACH,IAAW,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAElD;IAED,IAAW,QAAQ,IAAI,iBAAiB,CAEvC;IAED,WAAW,IAAI,IAAI;IAInB;;;;OAIG;IACH,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI;IAclE;;OAEG;IACH,WAAW,IAAI,IAAI;IAOnB;;;OAGG;IACH,eAAe,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC,eAAe,EAAE,CAAC;IAUvE;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIzD;;;OAGG;IACG,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD;;OAEG;YACW,gBAAgB;IAiD9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqC5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;;OAGG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BvD;;;OAGG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;yCA3PhC,iBAAiB;6CAAjB,iBAAiB;CAmQ7B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core';
|
|
2
2
|
import { BehaviorSubject, interval } from 'rxjs';
|
|
3
3
|
import { map, shareReplay, switchMap } from 'rxjs/operators';
|
|
4
|
-
import { LogStatusEx, RunView } from '@memberjunction/core';
|
|
4
|
+
import { LogStatusEx, RunView, Metadata } from '@memberjunction/core';
|
|
5
5
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
7
|
/**
|
|
@@ -19,7 +19,17 @@ export class AgentStateService {
|
|
|
19
19
|
minimumPollCycles = 3;
|
|
20
20
|
// Public observable streams
|
|
21
21
|
activeAgents$ = this._activeAgents$.asObservable();
|
|
22
|
+
_provider = null;
|
|
22
23
|
constructor() { }
|
|
24
|
+
/**
|
|
25
|
+
* Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.
|
|
26
|
+
*/
|
|
27
|
+
set Provider(value) {
|
|
28
|
+
this._provider = value;
|
|
29
|
+
}
|
|
30
|
+
get Provider() {
|
|
31
|
+
return this._provider ?? Metadata.Provider;
|
|
32
|
+
}
|
|
23
33
|
ngOnDestroy() {
|
|
24
34
|
this.stopPolling();
|
|
25
35
|
}
|
|
@@ -83,7 +93,7 @@ export class AgentStateService {
|
|
|
83
93
|
const timestamp = new Date().toISOString();
|
|
84
94
|
LogStatusEx({ message: `[${timestamp}] 🤖 AgentStateService.loadActiveAgents - Polling for active agents (conversation: ${conversationId || 'ALL'}, cycle: ${this.pollCycleCount})`, verboseOnly: true });
|
|
85
95
|
try {
|
|
86
|
-
const rv =
|
|
96
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
87
97
|
// Valid statuses: Running, Completed, Paused, Failed, Cancelled
|
|
88
98
|
let filter = `Status IN ('Running', 'Paused')`;
|
|
89
99
|
if (conversationId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-state.service.js","sourceRoot":"","sources":["../../../src/lib/services/agent-state.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, Observable, interval, Subscription } from 'rxjs';\nimport { map, shareReplay, switchMap } from 'rxjs/operators';\nimport { LogStatusEx, RunView, UserInfo } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJAIAgentRunEntity } from '@memberjunction/core-entities';\n\nexport type AgentStatus = 'acknowledging' | 'working' | 'completing' | 'completed' | 'error';\n\nexport interface AgentWithStatus {\n run: MJAIAgentRunEntity;\n status: AgentStatus;\n confidence: number | null;\n}\n\n/**\n * Manages agent state and provides real-time updates for active agents\n * Polls for agent status changes and provides reactive streams\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AgentStateService implements OnDestroy {\n private _activeAgents$ = new BehaviorSubject<AgentWithStatus[]>([]);\n private pollSubscription?: Subscription;\n private currentUser?: UserInfo;\n private pollInterval: number = 30000; // Poll every 30 seconds (reduced from 3s to minimize DB load)\n private pollCycleCount = 0;\n /** Minimum poll cycles before allowing auto-stop. Prevents premature shutdown\n * when fire-and-forget ACK returns before the server creates the agent run record. */\n private readonly minimumPollCycles = 3;\n\n // Public observable streams\n public readonly activeAgents$ = this._activeAgents$.asObservable();\n\n constructor() {}\n\n ngOnDestroy(): void {\n this.stopPolling();\n }\n\n /**\n * Starts polling for active agents\n * @param currentUser The current user context\n * @param conversationId Optional conversation ID to filter by\n */\n startPolling(currentUser: UserInfo, conversationId?: string): void {\n this.currentUser = currentUser;\n this.stopPolling();\n this.pollCycleCount = 0;\n\n // Initial load\n this.loadActiveAgents(conversationId);\n\n // Start polling\n this.pollSubscription = interval(this.pollInterval)\n .pipe(switchMap(() => this.loadActiveAgents(conversationId)))\n .subscribe();\n }\n\n /**\n * Stops polling for active agents\n */\n stopPolling(): void {\n if (this.pollSubscription) {\n this.pollSubscription.unsubscribe();\n this.pollSubscription = undefined;\n }\n }\n\n /**\n * Gets active agents as an observable\n * @param conversationId Optional conversation ID to filter by\n */\n getActiveAgents(conversationId?: string): Observable<AgentWithStatus[]> {\n if (conversationId) {\n return this.activeAgents$.pipe(\n map(agents => agents.filter(a => UUIDsEqual(a.run.ConversationID, conversationId))),\n shareReplay(1)\n );\n }\n return this.activeAgents$;\n }\n\n /**\n * Gets a specific agent by ID\n * @param agentRunId The agent run ID\n */\n getAgent(agentRunId: string): AgentWithStatus | undefined {\n return this._activeAgents$.value.find(a => UUIDsEqual(a.run.ID, agentRunId));\n }\n\n /**\n * Manually refreshes active agents\n * @param conversationId Optional conversation ID to filter by\n */\n async refresh(conversationId?: string): Promise<void> {\n await this.loadActiveAgents(conversationId);\n }\n\n /**\n * Loads active agents from the database\n */\n private async loadActiveAgents(conversationId?: string): Promise<void> {\n if (!this.currentUser) {\n return;\n }\n\n this.pollCycleCount++;\n const timestamp = new Date().toISOString();\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService.loadActiveAgents - Polling for active agents (conversation: ${conversationId || 'ALL'}, cycle: ${this.pollCycleCount})`, verboseOnly: true});\n\n try {\n const rv = new RunView();\n // Valid statuses: Running, Completed, Paused, Failed, Cancelled\n let filter = `Status IN ('Running', 'Paused')`;\n\n if (conversationId) {\n filter += ` AND ConversationID='${conversationId}'`;\n }\n\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService - Executing RunView for AI Agent Runs`, verboseOnly: true});\n const result = await rv.RunView<MJAIAgentRunEntity>(\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: filter,\n OrderBy: 'StartedAt DESC',\n MaxRows: 50,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (result.Success) {\n const runs = result.Results || [];\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService - Found ${runs.length} active agent(s)`, verboseOnly: true});\n const agentsWithStatus = runs.map(run => this.mapRunToAgentWithStatus(run));\n this._activeAgents$.next(agentsWithStatus);\n\n // Stop polling if no active agents AND minimum cycles met (optimization to reduce DB load).\n // The minimum cycle guard prevents premature shutdown when fire-and-forget returns\n // before the server has created the agent run record.\n if (runs.length === 0 && this.pollSubscription && this.pollCycleCount >= this.minimumPollCycles) {\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService - No active agents after ${this.pollCycleCount} cycles, stopping polling`, verboseOnly: true});\n this.stopPolling();\n }\n }\n } catch (error) {\n console.error('Failed to load active agents:', error);\n }\n }\n\n /**\n * Maps an agent run to include status and confidence information\n */\n private mapRunToAgentWithStatus(run: MJAIAgentRunEntity): AgentWithStatus {\n const status = this.determineAgentStatus(run);\n const confidence = this.extractConfidence(run);\n\n return {\n run,\n status,\n confidence\n };\n }\n\n /**\n * Determines the agent status based on the run entity\n */\n private determineAgentStatus(run: MJAIAgentRunEntity): AgentStatus {\n const status = run.Status?.toLowerCase() || 'running';\n\n // Check for errors\n if (status === 'error' || status === 'failed') {\n return 'error';\n }\n\n // Check for completion\n if (status === 'completed' || status === 'complete' || status === 'success') {\n return 'completed';\n }\n\n // Determine stage based on progress or elapsed time\n if (run.StartedAt) {\n const elapsed = Date.now() - new Date(run.StartedAt).getTime();\n const seconds = elapsed / 1000;\n\n // First 5 seconds: acknowledging\n if (seconds < 5) {\n return 'acknowledging';\n }\n\n // Check if nearing completion (has results or output)\n if (run.Result || run.Status === 'Completed') {\n // If there's output, likely completing\n return 'completing';\n }\n\n // Otherwise, working\n return 'working';\n }\n\n // Default to acknowledging if just started\n return 'acknowledging';\n }\n\n /**\n * Extracts confidence score from agent run if available\n */\n private extractConfidence(run: MJAIAgentRunEntity): number | null {\n // Try to parse confidence from Result or other fields\n // This is a placeholder - adjust based on actual data structure\n try {\n if (run.Result) {\n const result = typeof run.Result === 'string' ? JSON.parse(run.Result) : run.Result;\n if (result.confidence != null) {\n return parseFloat(result.confidence);\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return null;\n }\n\n /**\n * Cancels an agent run\n * @param agentRunId The agent run ID to cancel\n */\n async cancelAgent(agentRunId: string): Promise<boolean> {\n if (!this.currentUser) {\n return false;\n }\n\n try {\n const agent = this.getAgent(agentRunId);\n if (!agent) {\n return false;\n }\n\n agent.run.Status = 'Cancelled';\n const saved = await agent.run.Save();\n\n if (saved) {\n // Refresh the active agents list\n await this.refresh();\n return true;\n }\n } catch (error) {\n console.error('Failed to cancel agent:', error);\n }\n\n return false;\n }\n\n /**\n * Updates the poll interval\n * @param milliseconds The new poll interval in milliseconds\n */\n setPollInterval(milliseconds: number): void {\n this.pollInterval = milliseconds;\n\n // Restart polling if currently active\n if (this.pollSubscription && this.currentUser) {\n this.startPolling(this.currentUser);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent-state.service.js","sourceRoot":"","sources":["../../../src/lib/services/agent-state.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, Observable, interval, Subscription } from 'rxjs';\nimport { map, shareReplay, switchMap } from 'rxjs/operators';\nimport { LogStatusEx, RunView, UserInfo, Metadata, IMetadataProvider } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJAIAgentRunEntity } from '@memberjunction/core-entities';\n\nexport type AgentStatus = 'acknowledging' | 'working' | 'completing' | 'completed' | 'error';\n\nexport interface AgentWithStatus {\n run: MJAIAgentRunEntity;\n status: AgentStatus;\n confidence: number | null;\n}\n\n/**\n * Manages agent state and provides real-time updates for active agents\n * Polls for agent status changes and provides reactive streams\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AgentStateService implements OnDestroy {\n private _activeAgents$ = new BehaviorSubject<AgentWithStatus[]>([]);\n private pollSubscription?: Subscription;\n private currentUser?: UserInfo;\n private pollInterval: number = 30000; // Poll every 30 seconds (reduced from 3s to minimize DB load)\n private pollCycleCount = 0;\n /** Minimum poll cycles before allowing auto-stop. Prevents premature shutdown\n * when fire-and-forget ACK returns before the server creates the agent run record. */\n private readonly minimumPollCycles = 3;\n\n // Public observable streams\n public readonly activeAgents$ = this._activeAgents$.asObservable();\n\n private _provider: IMetadataProvider | null = null;\n\n constructor() {}\n\n /**\n * Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.\n */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n ngOnDestroy(): void {\n this.stopPolling();\n }\n\n /**\n * Starts polling for active agents\n * @param currentUser The current user context\n * @param conversationId Optional conversation ID to filter by\n */\n startPolling(currentUser: UserInfo, conversationId?: string): void {\n this.currentUser = currentUser;\n this.stopPolling();\n this.pollCycleCount = 0;\n\n // Initial load\n this.loadActiveAgents(conversationId);\n\n // Start polling\n this.pollSubscription = interval(this.pollInterval)\n .pipe(switchMap(() => this.loadActiveAgents(conversationId)))\n .subscribe();\n }\n\n /**\n * Stops polling for active agents\n */\n stopPolling(): void {\n if (this.pollSubscription) {\n this.pollSubscription.unsubscribe();\n this.pollSubscription = undefined;\n }\n }\n\n /**\n * Gets active agents as an observable\n * @param conversationId Optional conversation ID to filter by\n */\n getActiveAgents(conversationId?: string): Observable<AgentWithStatus[]> {\n if (conversationId) {\n return this.activeAgents$.pipe(\n map(agents => agents.filter(a => UUIDsEqual(a.run.ConversationID, conversationId))),\n shareReplay(1)\n );\n }\n return this.activeAgents$;\n }\n\n /**\n * Gets a specific agent by ID\n * @param agentRunId The agent run ID\n */\n getAgent(agentRunId: string): AgentWithStatus | undefined {\n return this._activeAgents$.value.find(a => UUIDsEqual(a.run.ID, agentRunId));\n }\n\n /**\n * Manually refreshes active agents\n * @param conversationId Optional conversation ID to filter by\n */\n async refresh(conversationId?: string): Promise<void> {\n await this.loadActiveAgents(conversationId);\n }\n\n /**\n * Loads active agents from the database\n */\n private async loadActiveAgents(conversationId?: string): Promise<void> {\n if (!this.currentUser) {\n return;\n }\n\n this.pollCycleCount++;\n const timestamp = new Date().toISOString();\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService.loadActiveAgents - Polling for active agents (conversation: ${conversationId || 'ALL'}, cycle: ${this.pollCycleCount})`, verboseOnly: true});\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n // Valid statuses: Running, Completed, Paused, Failed, Cancelled\n let filter = `Status IN ('Running', 'Paused')`;\n\n if (conversationId) {\n filter += ` AND ConversationID='${conversationId}'`;\n }\n\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService - Executing RunView for AI Agent Runs`, verboseOnly: true});\n const result = await rv.RunView<MJAIAgentRunEntity>(\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: filter,\n OrderBy: 'StartedAt DESC',\n MaxRows: 50,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (result.Success) {\n const runs = result.Results || [];\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService - Found ${runs.length} active agent(s)`, verboseOnly: true});\n const agentsWithStatus = runs.map(run => this.mapRunToAgentWithStatus(run));\n this._activeAgents$.next(agentsWithStatus);\n\n // Stop polling if no active agents AND minimum cycles met (optimization to reduce DB load).\n // The minimum cycle guard prevents premature shutdown when fire-and-forget returns\n // before the server has created the agent run record.\n if (runs.length === 0 && this.pollSubscription && this.pollCycleCount >= this.minimumPollCycles) {\n LogStatusEx({message: `[${timestamp}] 🤖 AgentStateService - No active agents after ${this.pollCycleCount} cycles, stopping polling`, verboseOnly: true});\n this.stopPolling();\n }\n }\n } catch (error) {\n console.error('Failed to load active agents:', error);\n }\n }\n\n /**\n * Maps an agent run to include status and confidence information\n */\n private mapRunToAgentWithStatus(run: MJAIAgentRunEntity): AgentWithStatus {\n const status = this.determineAgentStatus(run);\n const confidence = this.extractConfidence(run);\n\n return {\n run,\n status,\n confidence\n };\n }\n\n /**\n * Determines the agent status based on the run entity\n */\n private determineAgentStatus(run: MJAIAgentRunEntity): AgentStatus {\n const status = run.Status?.toLowerCase() || 'running';\n\n // Check for errors\n if (status === 'error' || status === 'failed') {\n return 'error';\n }\n\n // Check for completion\n if (status === 'completed' || status === 'complete' || status === 'success') {\n return 'completed';\n }\n\n // Determine stage based on progress or elapsed time\n if (run.StartedAt) {\n const elapsed = Date.now() - new Date(run.StartedAt).getTime();\n const seconds = elapsed / 1000;\n\n // First 5 seconds: acknowledging\n if (seconds < 5) {\n return 'acknowledging';\n }\n\n // Check if nearing completion (has results or output)\n if (run.Result || run.Status === 'Completed') {\n // If there's output, likely completing\n return 'completing';\n }\n\n // Otherwise, working\n return 'working';\n }\n\n // Default to acknowledging if just started\n return 'acknowledging';\n }\n\n /**\n * Extracts confidence score from agent run if available\n */\n private extractConfidence(run: MJAIAgentRunEntity): number | null {\n // Try to parse confidence from Result or other fields\n // This is a placeholder - adjust based on actual data structure\n try {\n if (run.Result) {\n const result = typeof run.Result === 'string' ? JSON.parse(run.Result) : run.Result;\n if (result.confidence != null) {\n return parseFloat(result.confidence);\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return null;\n }\n\n /**\n * Cancels an agent run\n * @param agentRunId The agent run ID to cancel\n */\n async cancelAgent(agentRunId: string): Promise<boolean> {\n if (!this.currentUser) {\n return false;\n }\n\n try {\n const agent = this.getAgent(agentRunId);\n if (!agent) {\n return false;\n }\n\n agent.run.Status = 'Cancelled';\n const saved = await agent.run.Save();\n\n if (saved) {\n // Refresh the active agents list\n await this.refresh();\n return true;\n }\n } catch (error) {\n console.error('Failed to cancel agent:', error);\n }\n\n return false;\n }\n\n /**\n * Updates the poll interval\n * @param milliseconds The new poll interval in milliseconds\n */\n setPollInterval(milliseconds: number): void {\n this.pollInterval = milliseconds;\n\n // Restart polling if currently active\n if (this.pollSubscription && this.currentUser) {\n this.startPolling(this.currentUser);\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { UserInfo } from '@memberjunction/core';
|
|
1
|
+
import { UserInfo, IMetadataProvider } from '@memberjunction/core';
|
|
2
2
|
import { MJArtifactPermissionEntity } from '@memberjunction/core-entities';
|
|
3
3
|
import { CollectionPermissionService } from './collection-permission.service';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
@@ -25,7 +25,14 @@ export interface ArtifactPermissionSet {
|
|
|
25
25
|
}
|
|
26
26
|
export declare class ArtifactPermissionService {
|
|
27
27
|
private collectionPermissionService;
|
|
28
|
+
private _provider;
|
|
28
29
|
constructor(collectionPermissionService: CollectionPermissionService);
|
|
30
|
+
/**
|
|
31
|
+
* The metadata provider this service uses. When unset, falls back to Metadata.Provider.
|
|
32
|
+
* Setting it also propagates to the collection-permission service this depends on.
|
|
33
|
+
*/
|
|
34
|
+
get Provider(): IMetadataProvider;
|
|
35
|
+
set Provider(value: IMetadataProvider | null);
|
|
29
36
|
/**
|
|
30
37
|
* Load all explicit permissions for an artifact
|
|
31
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-permission.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-permission.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAqB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"artifact-permission.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-permission.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,14 +5,28 @@ import * as i0 from "@angular/core";
|
|
|
5
5
|
import * as i1 from "./collection-permission.service";
|
|
6
6
|
export class ArtifactPermissionService {
|
|
7
7
|
collectionPermissionService;
|
|
8
|
+
_provider = null;
|
|
8
9
|
constructor(collectionPermissionService) {
|
|
9
10
|
this.collectionPermissionService = collectionPermissionService;
|
|
10
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* The metadata provider this service uses. When unset, falls back to Metadata.Provider.
|
|
14
|
+
* Setting it also propagates to the collection-permission service this depends on.
|
|
15
|
+
*/
|
|
16
|
+
get Provider() {
|
|
17
|
+
return this._provider ?? Metadata.Provider;
|
|
18
|
+
}
|
|
19
|
+
set Provider(value) {
|
|
20
|
+
this._provider = value;
|
|
21
|
+
if (value !== null) {
|
|
22
|
+
this.collectionPermissionService.Provider = value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
11
25
|
/**
|
|
12
26
|
* Load all explicit permissions for an artifact
|
|
13
27
|
*/
|
|
14
28
|
async loadPermissions(artifactId, currentUser) {
|
|
15
|
-
const rv =
|
|
29
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
16
30
|
const result = await rv.RunView({
|
|
17
31
|
EntityName: 'MJ: Artifact Permissions',
|
|
18
32
|
ExtraFilter: `ArtifactID='${artifactId}'`,
|
|
@@ -54,7 +68,7 @@ export class ArtifactPermissionService {
|
|
|
54
68
|
* Get explicit permission record for a user on an artifact
|
|
55
69
|
*/
|
|
56
70
|
async getExplicitPermission(artifactId, userId, currentUser) {
|
|
57
|
-
const rv =
|
|
71
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
58
72
|
const result = await rv.RunView({
|
|
59
73
|
EntityName: 'MJ: Artifact Permissions',
|
|
60
74
|
ExtraFilter: `ArtifactID='${artifactId}' AND UserID='${userId}'`,
|
|
@@ -131,7 +145,7 @@ export class ArtifactPermissionService {
|
|
|
131
145
|
* Grant explicit permission to a user
|
|
132
146
|
*/
|
|
133
147
|
async grantPermission(artifactId, userId, permissions, sharedByUserId, currentUser) {
|
|
134
|
-
const md =
|
|
148
|
+
const md = this.Provider;
|
|
135
149
|
const permission = await md.GetEntityObject('MJ: Artifact Permissions', currentUser);
|
|
136
150
|
permission.ArtifactID = artifactId;
|
|
137
151
|
permission.UserID = userId;
|
|
@@ -149,7 +163,7 @@ export class ArtifactPermissionService {
|
|
|
149
163
|
* Update existing permission
|
|
150
164
|
*/
|
|
151
165
|
async updatePermission(permissionId, permissions, currentUser) {
|
|
152
|
-
const md =
|
|
166
|
+
const md = this.Provider;
|
|
153
167
|
const permission = await md.GetEntityObject('MJ: Artifact Permissions', currentUser);
|
|
154
168
|
await permission.Load(permissionId);
|
|
155
169
|
permission.CanRead = permissions.canRead;
|
|
@@ -161,7 +175,7 @@ export class ArtifactPermissionService {
|
|
|
161
175
|
* Revoke explicit permission
|
|
162
176
|
*/
|
|
163
177
|
async revokePermission(permissionId, currentUser) {
|
|
164
|
-
const md =
|
|
178
|
+
const md = this.Provider;
|
|
165
179
|
const permission = await md.GetEntityObject('MJ: Artifact Permissions', currentUser);
|
|
166
180
|
await permission.Load(permissionId);
|
|
167
181
|
return await permission.Delete();
|
|
@@ -215,7 +229,7 @@ export class ArtifactPermissionService {
|
|
|
215
229
|
* Helper: Get artifact record
|
|
216
230
|
*/
|
|
217
231
|
async getArtifact(artifactId, currentUser) {
|
|
218
|
-
const rv =
|
|
232
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
219
233
|
const result = await rv.RunView({
|
|
220
234
|
EntityName: 'MJ: Artifacts',
|
|
221
235
|
ExtraFilter: `ID='${artifactId}'`,
|
|
@@ -231,7 +245,7 @@ export class ArtifactPermissionService {
|
|
|
231
245
|
* Helper: Get all collections containing this artifact
|
|
232
246
|
*/
|
|
233
247
|
async getArtifactCollections(artifactId, currentUser) {
|
|
234
|
-
const rv =
|
|
248
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
235
249
|
const result = await rv.RunView({
|
|
236
250
|
EntityName: 'MJ: Collection Artifacts',
|
|
237
251
|
ExtraFilter: `ArtifactVersionID IN (
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-permission.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-permission.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { UserInfo, RunView, Metadata } from '@memberjunction/core';\nimport { MJArtifactPermissionEntity, MJArtifactEntity, MJCollectionArtifactEntity } from '@memberjunction/core-entities';\nimport { CollectionPermissionService } from './collection-permission.service';\nimport { UUIDsEqual } from '@memberjunction/global';\n\nexport interface ArtifactPermission {\n id: string;\n artifactId: string;\n userId: string;\n userName: string;\n canRead: boolean;\n canEdit: boolean;\n canShare: boolean;\n sharedByUserId: string | null;\n sharedByUserName: string | null;\n sharedAt: Date;\n}\n\nexport interface EffectivePermission extends ArtifactPermission {\n source: 'owner' | 'explicit' | 'collection';\n collectionName?: string; // If inherited from collection\n}\n\nexport interface ArtifactPermissionSet {\n canRead: boolean;\n canEdit: boolean;\n canShare: boolean;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ArtifactPermissionService {\n\n constructor(\n private collectionPermissionService: CollectionPermissionService\n ) {}\n\n /**\n * Load all explicit permissions for an artifact\n */\n async loadPermissions(artifactId: string, currentUser: UserInfo): Promise<ArtifactPermission[]> {\n const rv = new RunView();\n const result = await rv.RunView<MJArtifactPermissionEntity>({\n EntityName: 'MJ: Artifact Permissions',\n ExtraFilter: `ArtifactID='${artifactId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n ResultType: 'entity_object'\n }, currentUser);\n\n if (result.Success && result.Results) {\n return result.Results.map(p => this.mapToPermission(p));\n }\n return [];\n }\n\n /**\n * Check if user has specific permission for an artifact (HYBRID CHECK)\n * Checks in order: Owner > Explicit Permission > Collection Inheritance\n */\n async checkPermission(\n artifactId: string,\n userId: string,\n permission: 'read' | 'edit' | 'share',\n currentUser: UserInfo\n ): Promise<boolean> {\n // 1. Check ownership - owner has all permissions\n const artifact = await this.getArtifact(artifactId, currentUser);\n if (artifact && UUIDsEqual(artifact.UserID, userId)) {\n return true;\n }\n\n // 2. Check explicit artifact permission\n const explicit = await this.getExplicitPermission(artifactId, userId, currentUser);\n if (explicit) {\n return this.hasPermission(explicit, permission);\n }\n\n // 3. Check collection permission inheritance\n const collections = await this.getArtifactCollections(artifactId, currentUser);\n for (const collection of collections) {\n const collectionPermission = await this.collectionPermissionService.checkPermission(\n collection.CollectionID,\n userId,\n currentUser\n );\n\n if (collectionPermission && this.hasCollectionPermission(collectionPermission, permission)) {\n return true; // Inherited from collection\n }\n }\n\n // 4. No access\n return false;\n }\n\n /**\n * Get explicit permission record for a user on an artifact\n */\n async getExplicitPermission(\n artifactId: string,\n userId: string,\n currentUser: UserInfo\n ): Promise<ArtifactPermission | null> {\n const rv = new RunView();\n const result = await rv.RunView<MJArtifactPermissionEntity>({\n EntityName: 'MJ: Artifact Permissions',\n ExtraFilter: `ArtifactID='${artifactId}' AND UserID='${userId}'`,\n MaxRows: 1,\n ResultType: 'entity_object'\n }, currentUser);\n\n if (result.Success && result.Results && result.Results.length > 0) {\n return this.mapToPermission(result.Results[0]);\n }\n return null;\n }\n\n /**\n * Get all effective permissions for an artifact (owner + explicit + inherited)\n */\n async getEffectiveUsers(artifactId: string, currentUser: UserInfo): Promise<EffectivePermission[]> {\n const effectivePermissions: EffectivePermission[] = [];\n const seenUsers = new Set<string>();\n\n // 1. Add owner\n const artifact = await this.getArtifact(artifactId, currentUser);\n if (artifact && artifact.UserID) {\n effectivePermissions.push({\n id: '', // No permission record for owner\n artifactId: artifactId,\n userId: artifact.UserID,\n userName: artifact.User || 'Owner',\n canRead: true,\n canEdit: true,\n canShare: true,\n sharedByUserId: null,\n sharedByUserName: null,\n sharedAt: artifact.__mj_CreatedAt,\n source: 'owner'\n });\n seenUsers.add(artifact.UserID);\n }\n\n // 2. Add explicit permissions\n const explicitPerms = await this.loadPermissions(artifactId, currentUser);\n for (const perm of explicitPerms) {\n if (!seenUsers.has(perm.userId)) {\n effectivePermissions.push({\n ...perm,\n source: 'explicit'\n });\n seenUsers.add(perm.userId);\n }\n }\n\n // 3. Add collection-inherited permissions\n const collections = await this.getArtifactCollections(artifactId, currentUser);\n for (const collection of collections) {\n const collectionPerms = await this.collectionPermissionService.loadPermissions(\n collection.CollectionID,\n currentUser\n );\n\n for (const collPerm of collectionPerms) {\n if (!seenUsers.has(collPerm.userId)) {\n effectivePermissions.push({\n id: '',\n artifactId: artifactId,\n userId: collPerm.userId,\n userName: collPerm.userName,\n canRead: collPerm.canRead,\n canEdit: collPerm.canEdit,\n canShare: collPerm.canShare,\n sharedByUserId: collPerm.sharedByUserId,\n sharedByUserName: collPerm.sharedByUserName,\n sharedAt: collPerm.sharedAt,\n source: 'collection',\n collectionName: collection.Collection || 'Unknown Collection'\n });\n seenUsers.add(collPerm.userId);\n }\n }\n }\n\n return effectivePermissions;\n }\n\n /**\n * Grant explicit permission to a user\n */\n async grantPermission(\n artifactId: string,\n userId: string,\n permissions: ArtifactPermissionSet,\n sharedByUserId: string,\n currentUser: UserInfo\n ): Promise<MJArtifactPermissionEntity> {\n const md = new Metadata();\n const permission = await md.GetEntityObject<MJArtifactPermissionEntity>(\n 'MJ: Artifact Permissions',\n currentUser\n );\n\n permission.ArtifactID = artifactId;\n permission.UserID = userId;\n permission.CanRead = permissions.canRead;\n permission.CanEdit = permissions.canEdit;\n permission.CanShare = permissions.canShare;\n permission.SharedByUserID = sharedByUserId;\n\n const saved = await permission.Save();\n if (!saved) {\n throw new Error(permission.LatestResult?.Message || 'Failed to grant permission');\n }\n\n return permission;\n }\n\n /**\n * Update existing permission\n */\n async updatePermission(\n permissionId: string,\n permissions: ArtifactPermissionSet,\n currentUser: UserInfo\n ): Promise<boolean> {\n const md = new Metadata();\n const permission = await md.GetEntityObject<MJArtifactPermissionEntity>(\n 'MJ: Artifact Permissions',\n currentUser\n );\n\n await permission.Load(permissionId);\n permission.CanRead = permissions.canRead;\n permission.CanEdit = permissions.canEdit;\n permission.CanShare = permissions.canShare;\n\n return await permission.Save();\n }\n\n /**\n * Revoke explicit permission\n */\n async revokePermission(permissionId: string, currentUser: UserInfo): Promise<boolean> {\n const md = new Metadata();\n const permission = await md.GetEntityObject<MJArtifactPermissionEntity>(\n 'MJ: Artifact Permissions',\n currentUser\n );\n\n await permission.Load(permissionId);\n return await permission.Delete();\n }\n\n /**\n * Validate that requested permissions don't exceed granter's permissions\n */\n validatePermissions(\n requested: ArtifactPermissionSet,\n granter: ArtifactPermissionSet,\n isOwner: boolean\n ): boolean {\n if (isOwner) return true; // Owner can grant anything\n\n // Can't grant permissions you don't have\n if (requested.canEdit && !granter.canEdit) return false;\n if (requested.canShare && !granter.canShare) return false;\n\n return true;\n }\n\n /**\n * Get available permissions for a user to grant based on their own permissions\n */\n getAvailablePermissions(userPermissions: ArtifactPermissionSet, isOwner: boolean): string[] {\n if (isOwner) {\n return ['Read', 'Edit', 'Share'];\n }\n\n const available = ['Read']; // Always have read\n if (userPermissions.canEdit) available.push('Edit');\n if (userPermissions.canShare) available.push('Share');\n\n return available;\n }\n\n /**\n * Check if user is owner of artifact\n */\n async isOwner(artifactId: string, userId: string, currentUser: UserInfo): Promise<boolean> {\n const artifact = await this.getArtifact(artifactId, currentUser);\n return artifact ? UUIDsEqual(artifact.UserID, userId) : false;\n }\n\n /**\n * Get all permissions for current user on an artifact (convenience method for UI)\n */\n async getUserPermissions(artifactId: string, currentUser: UserInfo): Promise<ArtifactPermissionSet> {\n const [canRead, canEdit, canShare] = await Promise.all([\n this.checkPermission(artifactId, currentUser.ID, 'read', currentUser),\n this.checkPermission(artifactId, currentUser.ID, 'edit', currentUser),\n this.checkPermission(artifactId, currentUser.ID, 'share', currentUser)\n ]);\n\n return { canRead, canEdit, canShare };\n }\n\n /**\n * Helper: Get artifact record\n */\n private async getArtifact(artifactId: string, currentUser: UserInfo): Promise<MJArtifactEntity | null> {\n const rv = new RunView();\n const result = await rv.RunView<MJArtifactEntity>({\n EntityName: 'MJ: Artifacts',\n ExtraFilter: `ID='${artifactId}'`,\n MaxRows: 1,\n ResultType: 'entity_object'\n }, currentUser);\n\n if (result.Success && result.Results && result.Results.length > 0) {\n return result.Results[0];\n }\n return null;\n }\n\n /**\n * Helper: Get all collections containing this artifact\n */\n private async getArtifactCollections(\n artifactId: string,\n currentUser: UserInfo\n ): Promise<MJCollectionArtifactEntity[]> {\n const rv = new RunView();\n const result = await rv.RunView<MJCollectionArtifactEntity>({\n EntityName: 'MJ: Collection Artifacts',\n ExtraFilter: `ArtifactVersionID IN (\n SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${artifactId}'\n )`,\n ResultType: 'entity_object'\n }, currentUser);\n\n return result.Success && result.Results ? result.Results : [];\n }\n\n /**\n * Helper: Check if permission set has specific permission\n */\n private hasPermission(permission: ArtifactPermission, type: 'read' | 'edit' | 'share'): boolean {\n switch (type) {\n case 'read':\n return permission.canRead;\n case 'edit':\n return permission.canEdit;\n case 'share':\n return permission.canShare;\n default:\n return false;\n }\n }\n\n /**\n * Helper: Check if collection permission has specific permission\n */\n private hasCollectionPermission(\n permission: { canRead: boolean; canEdit: boolean; canShare: boolean },\n type: 'read' | 'edit' | 'share'\n ): boolean {\n switch (type) {\n case 'read':\n return permission.canRead;\n case 'edit':\n return permission.canEdit;\n case 'share':\n return permission.canShare;\n default:\n return false;\n }\n }\n\n private mapToPermission(entity: MJArtifactPermissionEntity): ArtifactPermission {\n return {\n id: entity.ID,\n artifactId: entity.ArtifactID,\n userId: entity.UserID,\n userName: entity.User || '',\n canRead: entity.CanRead,\n canEdit: entity.CanEdit,\n canShare: entity.CanShare,\n sharedByUserId: entity.SharedByUserID || null,\n sharedByUserName: entity.SharedByUser || null,\n sharedAt: entity.__mj_CreatedAt\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"artifact-permission.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-permission.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAY,OAAO,EAAE,QAAQ,EAAqB,MAAM,sBAAsB,CAAC;AAGtF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;;;AA6BpD,MAAM,OAAO,yBAAyB;IAItB;IAHJ,SAAS,GAA6B,IAAI,CAAC;IAEnD,YACY,2BAAwD;QAAxD,gCAA2B,GAA3B,2BAA2B,CAA6B;IACjE,CAAC;IAEJ;;;OAGG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAC/C,CAAC;IACD,IAAW,QAAQ,CAAC,KAA+B;QAC/C,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,2BAA2B,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtD,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,UAAkB,EAAE,WAAqB;QAC3D,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAA6B;YACxD,UAAU,EAAE,0BAA0B;YACtC,WAAW,EAAE,eAAe,UAAU,GAAG;YACzC,OAAO,EAAE,oBAAoB;YAC7B,UAAU,EAAE,eAAe;SAC9B,EAAE,WAAW,CAAC,CAAC;QAEhB,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CACjB,UAAkB,EAClB,MAAc,EACd,UAAqC,EACrC,WAAqB;QAErB,iDAAiD;QACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACjE,IAAI,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,wCAAwC;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QACnF,IAAI,QAAQ,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpD,CAAC;QAED,6CAA6C;QAC7C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC/E,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACnC,MAAM,oBAAoB,GAAG,MAAM,IAAI,CAAC,2BAA2B,CAAC,eAAe,CAC/E,UAAU,CAAC,YAAY,EACvB,MAAM,EACN,WAAW,CACd,CAAC;YAEF,IAAI,oBAAoB,IAAI,IAAI,CAAC,uBAAuB,CAAC,oBAAoB,EAAE,UAAU,CAAC,EAAE,CAAC;gBACzF,OAAO,IAAI,CAAC,CAAC,4BAA4B;YAC7C,CAAC;QACL,CAAC;QAED,eAAe;QACf,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,qBAAqB,CACvB,UAAkB,EAClB,MAAc,EACd,WAAqB;QAErB,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAA6B;YACxD,UAAU,EAAE,0BAA0B;YACtC,WAAW,EAAE,eAAe,UAAU,iBAAiB,MAAM,GAAG;YAChE,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,eAAe;SAC9B,EAAE,WAAW,CAAC,CAAC;QAEhB,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,UAAkB,EAAE,WAAqB;QAC7D,MAAM,oBAAoB,GAA0B,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;QAEpC,eAAe;QACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACjE,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC9B,oBAAoB,CAAC,IAAI,CAAC;gBACtB,EAAE,EAAE,EAAE,EAAE,iCAAiC;gBACzC,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAI,OAAO;gBAClC,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,cAAc,EAAE,IAAI;gBACpB,gBAAgB,EAAE,IAAI;gBACtB,QAAQ,EAAE,QAAQ,CAAC,cAAc;gBACjC,MAAM,EAAE,OAAO;aAClB,CAAC,CAAC;YACH,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,8BAA8B;QAC9B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC1E,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YAC/B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,oBAAoB,CAAC,IAAI,CAAC;oBACtB,GAAG,IAAI;oBACP,MAAM,EAAE,UAAU;iBACrB,CAAC,CAAC;gBACH,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/B,CAAC;QACL,CAAC;QAED,0CAA0C;QAC1C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC/E,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACnC,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,2BAA2B,CAAC,eAAe,CAC1E,UAAU,CAAC,YAAY,EACvB,WAAW,CACd,CAAC;YAEF,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;gBACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAClC,oBAAoB,CAAC,IAAI,CAAC;wBACtB,EAAE,EAAE,EAAE;wBACN,UAAU,EAAE,UAAU;wBACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;wBACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;wBACzB,OAAO,EAAE,QAAQ,CAAC,OAAO;wBACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,cAAc,EAAE,QAAQ,CAAC,cAAc;wBACvC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;wBAC3C,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,MAAM,EAAE,YAAY;wBACpB,cAAc,EAAE,UAAU,CAAC,UAAU,IAAI,oBAAoB;qBAChE,CAAC,CAAC;oBACH,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACnC,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,oBAAoB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CACjB,UAAkB,EAClB,MAAc,EACd,WAAkC,EAClC,cAAsB,EACtB,WAAqB;QAErB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACzB,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,eAAe,CACvC,0BAA0B,EAC1B,WAAW,CACd,CAAC;QAEF,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC;QACnC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC;QAC3B,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACzC,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACzC,UAAU,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;QAC3C,UAAU,CAAC,cAAc,GAAG,cAAc,CAAC;QAE3C,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,IAAI,4BAA4B,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,UAAU,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAClB,YAAoB,EACpB,WAAkC,EAClC,WAAqB;QAErB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACzB,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,eAAe,CACvC,0BAA0B,EAC1B,WAAW,CACd,CAAC;QAEF,MAAM,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACpC,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACzC,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACzC,UAAU,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;QAE3C,OAAO,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,YAAoB,EAAE,WAAqB;QAC9D,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACzB,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,eAAe,CACvC,0BAA0B,EAC1B,WAAW,CACd,CAAC;QAEF,MAAM,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACpC,OAAO,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,mBAAmB,CACf,SAAgC,EAChC,OAA8B,EAC9B,OAAgB;QAEhB,IAAI,OAAO;YAAE,OAAO,IAAI,CAAC,CAAC,2BAA2B;QAErD,yCAAyC;QACzC,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QACxD,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAE1D,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,uBAAuB,CAAC,eAAsC,EAAE,OAAgB;QAC5E,IAAI,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB;QAC/C,IAAI,eAAe,CAAC,OAAO;YAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,eAAe,CAAC,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEtD,OAAO,SAAS,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAAkB,EAAE,MAAc,EAAE,WAAqB;QACnE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACjE,OAAO,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,UAAkB,EAAE,WAAqB;QAC9D,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACnD,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC;YACrE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC;YACrE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC;SACzE,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,WAAqB;QAC/D,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAmB;YAC9C,UAAU,EAAE,eAAe;YAC3B,WAAW,EAAE,OAAO,UAAU,GAAG;YACjC,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,eAAe;SAC9B,EAAE,WAAW,CAAC,CAAC;QAEhB,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,sBAAsB,CAChC,UAAkB,EAClB,WAAqB;QAErB,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAA6B;YACxD,UAAU,EAAE,0BAA0B;YACtC,WAAW,EAAE;+EACsD,UAAU;cAC3E;YACF,UAAU,EAAE,eAAe;SAC9B,EAAE,WAAW,CAAC,CAAC;QAEhB,OAAO,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,UAA8B,EAAE,IAA+B;QACjF,QAAQ,IAAI,EAAE,CAAC;YACX,KAAK,MAAM;gBACP,OAAO,UAAU,CAAC,OAAO,CAAC;YAC9B,KAAK,MAAM;gBACP,OAAO,UAAU,CAAC,OAAO,CAAC;YAC9B,KAAK,OAAO;gBACR,OAAO,UAAU,CAAC,QAAQ,CAAC;YAC/B;gBACI,OAAO,KAAK,CAAC;QACrB,CAAC;IACL,CAAC;IAED;;OAEG;IACK,uBAAuB,CAC3B,UAAqE,EACrE,IAA+B;QAE/B,QAAQ,IAAI,EAAE,CAAC;YACX,KAAK,MAAM;gBACP,OAAO,UAAU,CAAC,OAAO,CAAC;YAC9B,KAAK,MAAM;gBACP,OAAO,UAAU,CAAC,OAAO,CAAC;YAC9B,KAAK,OAAO;gBACR,OAAO,UAAU,CAAC,QAAQ,CAAC;YAC/B;gBACI,OAAO,KAAK,CAAC;QACrB,CAAC;IACL,CAAC;IAEO,eAAe,CAAC,MAAkC;QACtD,OAAO;YACH,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,IAAI;YAC7C,gBAAgB,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;YAC7C,QAAQ,EAAE,MAAM,CAAC,cAAc;SAClC,CAAC;IACN,CAAC;mHAxXQ,yBAAyB;gEAAzB,yBAAyB,WAAzB,yBAAyB,mBAFtB,MAAM;;iFAET,yBAAyB;cAHrC,UAAU;eAAC;gBACR,UAAU,EAAE,MAAM;aACrB","sourcesContent":["import { Injectable } from '@angular/core';\nimport { UserInfo, RunView, Metadata, IMetadataProvider } from '@memberjunction/core';\nimport { MJArtifactPermissionEntity, MJArtifactEntity, MJCollectionArtifactEntity } from '@memberjunction/core-entities';\nimport { CollectionPermissionService } from './collection-permission.service';\nimport { UUIDsEqual } from '@memberjunction/global';\n\nexport interface ArtifactPermission {\n id: string;\n artifactId: string;\n userId: string;\n userName: string;\n canRead: boolean;\n canEdit: boolean;\n canShare: boolean;\n sharedByUserId: string | null;\n sharedByUserName: string | null;\n sharedAt: Date;\n}\n\nexport interface EffectivePermission extends ArtifactPermission {\n source: 'owner' | 'explicit' | 'collection';\n collectionName?: string; // If inherited from collection\n}\n\nexport interface ArtifactPermissionSet {\n canRead: boolean;\n canEdit: boolean;\n canShare: boolean;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ArtifactPermissionService {\n private _provider: IMetadataProvider | null = null;\n\n constructor(\n private collectionPermissionService: CollectionPermissionService\n ) {}\n\n /**\n * The metadata provider this service uses. When unset, falls back to Metadata.Provider.\n * Setting it also propagates to the collection-permission service this depends on.\n */\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n if (value !== null) {\n this.collectionPermissionService.Provider = value;\n }\n }\n\n /**\n * Load all explicit permissions for an artifact\n */\n async loadPermissions(artifactId: string, currentUser: UserInfo): Promise<ArtifactPermission[]> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<MJArtifactPermissionEntity>({\n EntityName: 'MJ: Artifact Permissions',\n ExtraFilter: `ArtifactID='${artifactId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n ResultType: 'entity_object'\n }, currentUser);\n\n if (result.Success && result.Results) {\n return result.Results.map(p => this.mapToPermission(p));\n }\n return [];\n }\n\n /**\n * Check if user has specific permission for an artifact (HYBRID CHECK)\n * Checks in order: Owner > Explicit Permission > Collection Inheritance\n */\n async checkPermission(\n artifactId: string,\n userId: string,\n permission: 'read' | 'edit' | 'share',\n currentUser: UserInfo\n ): Promise<boolean> {\n // 1. Check ownership - owner has all permissions\n const artifact = await this.getArtifact(artifactId, currentUser);\n if (artifact && UUIDsEqual(artifact.UserID, userId)) {\n return true;\n }\n\n // 2. Check explicit artifact permission\n const explicit = await this.getExplicitPermission(artifactId, userId, currentUser);\n if (explicit) {\n return this.hasPermission(explicit, permission);\n }\n\n // 3. Check collection permission inheritance\n const collections = await this.getArtifactCollections(artifactId, currentUser);\n for (const collection of collections) {\n const collectionPermission = await this.collectionPermissionService.checkPermission(\n collection.CollectionID,\n userId,\n currentUser\n );\n\n if (collectionPermission && this.hasCollectionPermission(collectionPermission, permission)) {\n return true; // Inherited from collection\n }\n }\n\n // 4. No access\n return false;\n }\n\n /**\n * Get explicit permission record for a user on an artifact\n */\n async getExplicitPermission(\n artifactId: string,\n userId: string,\n currentUser: UserInfo\n ): Promise<ArtifactPermission | null> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<MJArtifactPermissionEntity>({\n EntityName: 'MJ: Artifact Permissions',\n ExtraFilter: `ArtifactID='${artifactId}' AND UserID='${userId}'`,\n MaxRows: 1,\n ResultType: 'entity_object'\n }, currentUser);\n\n if (result.Success && result.Results && result.Results.length > 0) {\n return this.mapToPermission(result.Results[0]);\n }\n return null;\n }\n\n /**\n * Get all effective permissions for an artifact (owner + explicit + inherited)\n */\n async getEffectiveUsers(artifactId: string, currentUser: UserInfo): Promise<EffectivePermission[]> {\n const effectivePermissions: EffectivePermission[] = [];\n const seenUsers = new Set<string>();\n\n // 1. Add owner\n const artifact = await this.getArtifact(artifactId, currentUser);\n if (artifact && artifact.UserID) {\n effectivePermissions.push({\n id: '', // No permission record for owner\n artifactId: artifactId,\n userId: artifact.UserID,\n userName: artifact.User || 'Owner',\n canRead: true,\n canEdit: true,\n canShare: true,\n sharedByUserId: null,\n sharedByUserName: null,\n sharedAt: artifact.__mj_CreatedAt,\n source: 'owner'\n });\n seenUsers.add(artifact.UserID);\n }\n\n // 2. Add explicit permissions\n const explicitPerms = await this.loadPermissions(artifactId, currentUser);\n for (const perm of explicitPerms) {\n if (!seenUsers.has(perm.userId)) {\n effectivePermissions.push({\n ...perm,\n source: 'explicit'\n });\n seenUsers.add(perm.userId);\n }\n }\n\n // 3. Add collection-inherited permissions\n const collections = await this.getArtifactCollections(artifactId, currentUser);\n for (const collection of collections) {\n const collectionPerms = await this.collectionPermissionService.loadPermissions(\n collection.CollectionID,\n currentUser\n );\n\n for (const collPerm of collectionPerms) {\n if (!seenUsers.has(collPerm.userId)) {\n effectivePermissions.push({\n id: '',\n artifactId: artifactId,\n userId: collPerm.userId,\n userName: collPerm.userName,\n canRead: collPerm.canRead,\n canEdit: collPerm.canEdit,\n canShare: collPerm.canShare,\n sharedByUserId: collPerm.sharedByUserId,\n sharedByUserName: collPerm.sharedByUserName,\n sharedAt: collPerm.sharedAt,\n source: 'collection',\n collectionName: collection.Collection || 'Unknown Collection'\n });\n seenUsers.add(collPerm.userId);\n }\n }\n }\n\n return effectivePermissions;\n }\n\n /**\n * Grant explicit permission to a user\n */\n async grantPermission(\n artifactId: string,\n userId: string,\n permissions: ArtifactPermissionSet,\n sharedByUserId: string,\n currentUser: UserInfo\n ): Promise<MJArtifactPermissionEntity> {\n const md = this.Provider;\n const permission = await md.GetEntityObject<MJArtifactPermissionEntity>(\n 'MJ: Artifact Permissions',\n currentUser\n );\n\n permission.ArtifactID = artifactId;\n permission.UserID = userId;\n permission.CanRead = permissions.canRead;\n permission.CanEdit = permissions.canEdit;\n permission.CanShare = permissions.canShare;\n permission.SharedByUserID = sharedByUserId;\n\n const saved = await permission.Save();\n if (!saved) {\n throw new Error(permission.LatestResult?.Message || 'Failed to grant permission');\n }\n\n return permission;\n }\n\n /**\n * Update existing permission\n */\n async updatePermission(\n permissionId: string,\n permissions: ArtifactPermissionSet,\n currentUser: UserInfo\n ): Promise<boolean> {\n const md = this.Provider;\n const permission = await md.GetEntityObject<MJArtifactPermissionEntity>(\n 'MJ: Artifact Permissions',\n currentUser\n );\n\n await permission.Load(permissionId);\n permission.CanRead = permissions.canRead;\n permission.CanEdit = permissions.canEdit;\n permission.CanShare = permissions.canShare;\n\n return await permission.Save();\n }\n\n /**\n * Revoke explicit permission\n */\n async revokePermission(permissionId: string, currentUser: UserInfo): Promise<boolean> {\n const md = this.Provider;\n const permission = await md.GetEntityObject<MJArtifactPermissionEntity>(\n 'MJ: Artifact Permissions',\n currentUser\n );\n\n await permission.Load(permissionId);\n return await permission.Delete();\n }\n\n /**\n * Validate that requested permissions don't exceed granter's permissions\n */\n validatePermissions(\n requested: ArtifactPermissionSet,\n granter: ArtifactPermissionSet,\n isOwner: boolean\n ): boolean {\n if (isOwner) return true; // Owner can grant anything\n\n // Can't grant permissions you don't have\n if (requested.canEdit && !granter.canEdit) return false;\n if (requested.canShare && !granter.canShare) return false;\n\n return true;\n }\n\n /**\n * Get available permissions for a user to grant based on their own permissions\n */\n getAvailablePermissions(userPermissions: ArtifactPermissionSet, isOwner: boolean): string[] {\n if (isOwner) {\n return ['Read', 'Edit', 'Share'];\n }\n\n const available = ['Read']; // Always have read\n if (userPermissions.canEdit) available.push('Edit');\n if (userPermissions.canShare) available.push('Share');\n\n return available;\n }\n\n /**\n * Check if user is owner of artifact\n */\n async isOwner(artifactId: string, userId: string, currentUser: UserInfo): Promise<boolean> {\n const artifact = await this.getArtifact(artifactId, currentUser);\n return artifact ? UUIDsEqual(artifact.UserID, userId) : false;\n }\n\n /**\n * Get all permissions for current user on an artifact (convenience method for UI)\n */\n async getUserPermissions(artifactId: string, currentUser: UserInfo): Promise<ArtifactPermissionSet> {\n const [canRead, canEdit, canShare] = await Promise.all([\n this.checkPermission(artifactId, currentUser.ID, 'read', currentUser),\n this.checkPermission(artifactId, currentUser.ID, 'edit', currentUser),\n this.checkPermission(artifactId, currentUser.ID, 'share', currentUser)\n ]);\n\n return { canRead, canEdit, canShare };\n }\n\n /**\n * Helper: Get artifact record\n */\n private async getArtifact(artifactId: string, currentUser: UserInfo): Promise<MJArtifactEntity | null> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<MJArtifactEntity>({\n EntityName: 'MJ: Artifacts',\n ExtraFilter: `ID='${artifactId}'`,\n MaxRows: 1,\n ResultType: 'entity_object'\n }, currentUser);\n\n if (result.Success && result.Results && result.Results.length > 0) {\n return result.Results[0];\n }\n return null;\n }\n\n /**\n * Helper: Get all collections containing this artifact\n */\n private async getArtifactCollections(\n artifactId: string,\n currentUser: UserInfo\n ): Promise<MJCollectionArtifactEntity[]> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<MJCollectionArtifactEntity>({\n EntityName: 'MJ: Collection Artifacts',\n ExtraFilter: `ArtifactVersionID IN (\n SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${artifactId}'\n )`,\n ResultType: 'entity_object'\n }, currentUser);\n\n return result.Success && result.Results ? result.Results : [];\n }\n\n /**\n * Helper: Check if permission set has specific permission\n */\n private hasPermission(permission: ArtifactPermission, type: 'read' | 'edit' | 'share'): boolean {\n switch (type) {\n case 'read':\n return permission.canRead;\n case 'edit':\n return permission.canEdit;\n case 'share':\n return permission.canShare;\n default:\n return false;\n }\n }\n\n /**\n * Helper: Check if collection permission has specific permission\n */\n private hasCollectionPermission(\n permission: { canRead: boolean; canEdit: boolean; canShare: boolean },\n type: 'read' | 'edit' | 'share'\n ): boolean {\n switch (type) {\n case 'read':\n return permission.canRead;\n case 'edit':\n return permission.canEdit;\n case 'share':\n return permission.canShare;\n default:\n return false;\n }\n }\n\n private mapToPermission(entity: MJArtifactPermissionEntity): ArtifactPermission {\n return {\n id: entity.ID,\n artifactId: entity.ArtifactID,\n userId: entity.UserID,\n userName: entity.User || '',\n canRead: entity.CanRead,\n canEdit: entity.CanEdit,\n canShare: entity.CanShare,\n sharedByUserId: entity.SharedByUserID || null,\n sharedByUserName: entity.SharedByUser || null,\n sharedAt: entity.__mj_CreatedAt\n };\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { MJArtifactEntity, MJArtifactVersionEntity } from '@memberjunction/core-entities';
|
|
3
|
-
import { UserInfo } from '@memberjunction/core';
|
|
3
|
+
import { UserInfo, IMetadataProvider } from '@memberjunction/core';
|
|
4
4
|
import { ArtifactPermissionService } from './artifact-permission.service';
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
/**
|
|
@@ -19,7 +19,14 @@ export declare class ArtifactStateService {
|
|
|
19
19
|
readonly isPanelOpen$: Observable<boolean>;
|
|
20
20
|
readonly panelMode$: Observable<"view" | "edit">;
|
|
21
21
|
readonly activeArtifact$: Observable<MJArtifactEntity | null>;
|
|
22
|
+
private _provider;
|
|
22
23
|
constructor(artifactPermissionService: ArtifactPermissionService);
|
|
24
|
+
/**
|
|
25
|
+
* The metadata provider this service uses. When unset, falls back to Metadata.Provider.
|
|
26
|
+
* Setting it propagates to the dependent artifact-permission service.
|
|
27
|
+
*/
|
|
28
|
+
get Provider(): IMetadataProvider;
|
|
29
|
+
set Provider(value: IMetadataProvider | null);
|
|
23
30
|
/**
|
|
24
31
|
* Check if current user can read an artifact
|
|
25
32
|
* @param artifactId The artifact ID
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-state.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-state.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,UAAU,EAAiB,MAAM,MAAM,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC1F,OAAO,EAAqB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"artifact-state.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-state.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,9 +25,23 @@ export class ArtifactStateService {
|
|
|
25
25
|
this.activeArtifactId$,
|
|
26
26
|
this._artifacts$
|
|
27
27
|
]).pipe(map(([id, artifacts]) => id ? artifacts.get(id) || null : null), shareReplay(1));
|
|
28
|
+
_provider = null;
|
|
28
29
|
constructor(artifactPermissionService) {
|
|
29
30
|
this.artifactPermissionService = artifactPermissionService;
|
|
30
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* The metadata provider this service uses. When unset, falls back to Metadata.Provider.
|
|
34
|
+
* Setting it propagates to the dependent artifact-permission service.
|
|
35
|
+
*/
|
|
36
|
+
get Provider() {
|
|
37
|
+
return this._provider ?? Metadata.Provider;
|
|
38
|
+
}
|
|
39
|
+
set Provider(value) {
|
|
40
|
+
this._provider = value;
|
|
41
|
+
if (value !== null) {
|
|
42
|
+
this.artifactPermissionService.Provider = value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
31
45
|
/**
|
|
32
46
|
* Check if current user can read an artifact
|
|
33
47
|
* @param artifactId The artifact ID
|
|
@@ -71,7 +85,7 @@ export class ArtifactStateService {
|
|
|
71
85
|
*/
|
|
72
86
|
async openArtifactByVersionId(versionId) {
|
|
73
87
|
try {
|
|
74
|
-
const md =
|
|
88
|
+
const md = this.Provider;
|
|
75
89
|
const version = await md.GetEntityObject('MJ: Artifact Versions');
|
|
76
90
|
const loaded = await version.Load(versionId);
|
|
77
91
|
if (loaded) {
|
|
@@ -140,7 +154,7 @@ export class ArtifactStateService {
|
|
|
140
154
|
*/
|
|
141
155
|
async loadArtifactsForConversation(conversationId, currentUser) {
|
|
142
156
|
try {
|
|
143
|
-
const rv =
|
|
157
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
144
158
|
const result = await rv.RunView({
|
|
145
159
|
EntityName: 'MJ: Artifacts',
|
|
146
160
|
ExtraFilter: `ConversationID='${conversationId}'`,
|
|
@@ -168,7 +182,7 @@ export class ArtifactStateService {
|
|
|
168
182
|
*/
|
|
169
183
|
async loadArtifactsForCollection(collectionId, currentUser) {
|
|
170
184
|
try {
|
|
171
|
-
const rv =
|
|
185
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
172
186
|
// Load artifacts through the collection join - use subquery to get artifact IDs from versions
|
|
173
187
|
const artifactsResult = await rv.RunView({
|
|
174
188
|
EntityName: 'MJ: Artifacts',
|
|
@@ -201,7 +215,7 @@ export class ArtifactStateService {
|
|
|
201
215
|
*/
|
|
202
216
|
async loadArtifactVersionsForCollection(collectionId, currentUser) {
|
|
203
217
|
try {
|
|
204
|
-
const rv =
|
|
218
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
205
219
|
// Load ALL versions in collection (no DISTINCT - each version is separate)
|
|
206
220
|
const versionResult = await rv.RunView({
|
|
207
221
|
EntityName: 'MJ: Artifact Versions',
|
|
@@ -254,7 +268,7 @@ export class ArtifactStateService {
|
|
|
254
268
|
*/
|
|
255
269
|
async loadArtifact(id, currentUser) {
|
|
256
270
|
try {
|
|
257
|
-
const md =
|
|
271
|
+
const md = this.Provider;
|
|
258
272
|
const artifact = await md.GetEntityObject('MJ: Artifacts', currentUser);
|
|
259
273
|
const loaded = await artifact.Load(id);
|
|
260
274
|
if (loaded) {
|
|
@@ -275,7 +289,7 @@ export class ArtifactStateService {
|
|
|
275
289
|
* @returns The created artifact
|
|
276
290
|
*/
|
|
277
291
|
async createArtifact(data, currentUser) {
|
|
278
|
-
const md =
|
|
292
|
+
const md = this.Provider;
|
|
279
293
|
const artifact = await md.GetEntityObject('MJ: Artifacts', currentUser);
|
|
280
294
|
Object.assign(artifact, data);
|
|
281
295
|
const saved = await artifact.Save();
|
|
@@ -300,7 +314,7 @@ export class ArtifactStateService {
|
|
|
300
314
|
if (!canEdit) {
|
|
301
315
|
throw new Error('You do not have permission to edit this artifact');
|
|
302
316
|
}
|
|
303
|
-
const md =
|
|
317
|
+
const md = this.Provider;
|
|
304
318
|
const artifact = await md.GetEntityObject('MJ: Artifacts', currentUser);
|
|
305
319
|
const loaded = await artifact.Load(id);
|
|
306
320
|
if (!loaded) {
|
|
@@ -328,7 +342,7 @@ export class ArtifactStateService {
|
|
|
328
342
|
if (!canEdit) {
|
|
329
343
|
throw new Error('You do not have permission to delete this artifact');
|
|
330
344
|
}
|
|
331
|
-
const md =
|
|
345
|
+
const md = this.Provider;
|
|
332
346
|
const artifact = await md.GetEntityObject('MJ: Artifacts', currentUser);
|
|
333
347
|
const loaded = await artifact.Load(id);
|
|
334
348
|
if (!loaded) {
|
|
@@ -362,7 +376,7 @@ export class ArtifactStateService {
|
|
|
362
376
|
// Get version ID if not provided
|
|
363
377
|
let targetVersionId = versionId;
|
|
364
378
|
if (!targetVersionId) {
|
|
365
|
-
const rv =
|
|
379
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
366
380
|
const versionResult = await rv.RunView({
|
|
367
381
|
EntityName: 'MJ: Artifact Versions',
|
|
368
382
|
ExtraFilter: `ArtifactID='${artifactId}'`,
|
|
@@ -375,7 +389,7 @@ export class ArtifactStateService {
|
|
|
375
389
|
}
|
|
376
390
|
targetVersionId = versionResult.Results[0].ID;
|
|
377
391
|
}
|
|
378
|
-
const md =
|
|
392
|
+
const md = this.Provider;
|
|
379
393
|
const collectionArtifact = await md.GetEntityObject('MJ: Collection Artifacts', currentUser);
|
|
380
394
|
collectionArtifact.CollectionID = collectionId;
|
|
381
395
|
collectionArtifact.ArtifactVersionID = targetVersionId;
|
|
@@ -396,7 +410,7 @@ export class ArtifactStateService {
|
|
|
396
410
|
if (!canEdit) {
|
|
397
411
|
throw new Error('You do not have permission to remove this artifact from a collection');
|
|
398
412
|
}
|
|
399
|
-
const rv =
|
|
413
|
+
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
400
414
|
// Find all versions of this artifact in the collection
|
|
401
415
|
const result = await rv.RunView({
|
|
402
416
|
EntityName: 'MJ: Collection Artifacts',
|