@harnessio/ai-chat-core 0.0.20 → 0.0.22

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.
@@ -8,3 +8,6 @@ export { useContentFocus } from './useContentFocus';
8
8
  export { useCapability } from './useCapability';
9
9
  export { useCapabilityExecution } from './useCapabilityExecution';
10
10
  export { usePageContext } from './usePageContext';
11
+ export { useQuickActionScope } from './useQuickActionScope';
12
+ export { useQuickAction } from './useQuickAction';
13
+ export { useQuickActions } from './useQuickActions';
@@ -0,0 +1,26 @@
1
+ import { QuickActionConfig } from '../../types/quick-action';
2
+ /**
3
+ * Register a quick action that appears in the welcome screen.
4
+ * Automatically unregisters when the component unmounts.
5
+ *
6
+ * @param config - Quick action configuration
7
+ * @param scope - The scope to register this action in (defaults to current active scope)
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * function PipelineQuickActions() {
12
+ * useQuickActionScope('pipelines', 'merge')
13
+ *
14
+ * useQuickAction({
15
+ * id: 'list-pipelines',
16
+ * label: 'List pipelines',
17
+ * prompt: 'Show me all pipelines in this project',
18
+ * icon: 'pipeline',
19
+ * priority: 10
20
+ * }, 'pipelines')
21
+ *
22
+ * return null
23
+ * }
24
+ * ```
25
+ */
26
+ export declare function useQuickAction(config: QuickActionConfig, scope?: string): void;
@@ -0,0 +1,21 @@
1
+ import { QuickActionScopeMode } from '../../types/quick-action';
2
+ /**
3
+ * Activate a quick action scope for the duration of this component's lifecycle.
4
+ * When the component unmounts, the scope is deactivated and the previous scope is restored.
5
+ *
6
+ * Use this at the page/module level to declare "this page owns quick actions".
7
+ *
8
+ * @param scope - Unique identifier for this scope (e.g., "pipelines", "dashboards")
9
+ * @param mode - How to display actions: 'merge' (global + current), 'replace' (only current), 'append' (all scopes)
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * function PipelinePage() {
14
+ * useQuickActionScope('pipelines', 'merge')
15
+ *
16
+ * // Component automatically cleans up on unmount
17
+ * return <div>Pipeline content</div>
18
+ * }
19
+ * ```
20
+ */
21
+ export declare function useQuickActionScope(scope: string, mode?: QuickActionScopeMode): void;
@@ -0,0 +1,25 @@
1
+ import { QuickAction, QuickActionFilter } from '../../types/quick-action';
2
+ /**
3
+ * Get all visible quick actions, respecting their condition functions and the active scope.
4
+ *
5
+ * @param filter - Optional filter by scope
6
+ * @returns Array of visible quick actions, sorted by priority
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * function WelcomeScreen() {
11
+ * const quickActions = useQuickActions()
12
+ *
13
+ * return (
14
+ * <div>
15
+ * {quickActions.map(action => (
16
+ * <Button key={action.id} onClick={() => send(action.prompt)}>
17
+ * {action.label}
18
+ * </Button>
19
+ * ))}
20
+ * </div>
21
+ * )
22
+ * }
23
+ * ```
24
+ */
25
+ export declare function useQuickActions(filter?: QuickActionFilter): QuickAction[];
@@ -1,5 +1,6 @@
1
1
  import { CapabilityExecutionManager, CapabilityRegistry } from '../../core';
2
2
  import { PluginRegistry } from '../../core/PluginRegistry';
3
+ import { QuickActionRegistry } from '../../core/QuickActionRegistry';
3
4
  import { ChatPlugin } from '../../types/plugin';
4
5
  import { BaseSubscribable } from '../../utils/Subscribable';
5
6
  import { ContentFocusRuntime } from '../ContentFocusRuntime/ContentFocusRuntime';
@@ -13,6 +14,7 @@ export declare class AssistantRuntime extends BaseSubscribable {
13
14
  readonly pluginRegistry: PluginRegistry;
14
15
  readonly capabilityRegistry: CapabilityRegistry;
15
16
  readonly capabilityExecutionManager: CapabilityExecutionManager;
17
+ readonly quickActionRegistry: QuickActionRegistry;
16
18
  private _contentFocusRuntime;
17
19
  private _currentThreadUnsubscribe?;
18
20
  constructor(config: AssistantRuntimeConfig);
@@ -1,5 +1,5 @@
1
1
  import { SystemEvent } from '../../types/adapters';
2
- import { AppendMessage, Message } from '../../types/message';
2
+ import { AppendMessage, Message, MessageContent } from '../../types/message';
3
3
  import { RuntimeCapabilities, ThreadState } from '../../types/thread';
4
4
  import { BaseSubscribable, Unsubscribe } from '../../utils/Subscribable';
5
5
  import { default as ComposerRuntime } from '../ComposerRuntime/ComposerRuntime';
@@ -22,11 +22,24 @@ export declare class ThreadRuntime extends BaseSubscribable {
22
22
  getState(): ThreadState;
23
23
  append(message: AppendMessage): void;
24
24
  send(text: string): Promise<void>;
25
+ /**
26
+ * Dispatches a system event (e.g. a user click on an elicitation card).
27
+ *
28
+ * Prior to this change, this method wrapped startSystemEventRun in a
29
+ * try/catch that silently swallowed the "A run is already in progress"
30
+ * error thrown by the core when _isRunning was still true — causing
31
+ * clicks fired during the tail of the previous run to disappear.
32
+ *
33
+ * Now we await waitForIdle() before dispatching so the event is
34
+ * reliably delivered as soon as the in-flight run completes. Callers
35
+ * do not need their own queueing primitive.
36
+ */
25
37
  sendSystemEvent(systemEvent: SystemEvent): Promise<void>;
26
38
  cancelRun(): void;
27
39
  clear(): void;
28
40
  reset(messages?: Message[]): void;
29
41
  setConversationId(conversationId: string | undefined): void;
30
42
  setTitle(title: string | undefined): void;
43
+ updateMessageContent(messageId: string, updater: (content: MessageContent[]) => MessageContent[]): void;
31
44
  subscribe(callback: () => void): Unsubscribe;
32
45
  }
@@ -1,6 +1,6 @@
1
1
  import { CapabilityExecutionManager } from '../../core';
2
2
  import { StreamAdapter, SystemEvent } from '../../types/adapters';
3
- import { AppendMessage, Message } from '../../types/message';
3
+ import { AppendMessage, Message, MessageContent } from '../../types/message';
4
4
  import { RuntimeCapabilities } from '../../types/thread';
5
5
  import { BaseSubscribable } from '../../utils/Subscribable';
6
6
  export interface ThreadRuntimeCoreConfig {
@@ -19,6 +19,7 @@ export declare class ThreadRuntimeCore extends BaseSubscribable {
19
19
  private _abortController;
20
20
  private _conversationId?;
21
21
  private _title?;
22
+ private _idleWaiters;
22
23
  private _currentPart;
23
24
  constructor(config: ThreadRuntimeCoreConfig);
24
25
  get messages(): readonly Message[];
@@ -34,6 +35,16 @@ export declare class ThreadRuntimeCore extends BaseSubscribable {
34
35
  get capabilities(): RuntimeCapabilities;
35
36
  private updateMessages;
36
37
  append(message: AppendMessage): void;
38
+ /**
39
+ * Resolves when _isRunning flips to false. Use this to queue a
40
+ * follow-on dispatch (e.g. a system event from a card click that
41
+ * fires during the tail of the previous run) without racing the
42
+ * in-progress run's guard.
43
+ *
44
+ * Resolves immediately if nothing is running.
45
+ */
46
+ waitForIdle(): Promise<void>;
47
+ private drainIdleWaiters;
37
48
  startSystemEventRun(systemEvent: SystemEvent): Promise<void>;
38
49
  startRun(userMessage: AppendMessage): Promise<void>;
39
50
  private handleStreamEvent;
@@ -47,4 +58,5 @@ export declare class ThreadRuntimeCore extends BaseSubscribable {
47
58
  reset(messages?: Message[]): void;
48
59
  setConversationId(conversationId: string | undefined): void;
49
60
  setTitle(title: string | undefined): void;
61
+ updateMessageContent(messageId: string, updater: (content: MessageContent[]) => MessageContent[]): void;
50
62
  }
@@ -5,3 +5,4 @@ export type { StreamAdapter, ThreadListAdapter, StreamEvent, StreamRequest, Stre
5
5
  export type { SSEEvent } from '../utils/BaseSSEStreamAdapter';
6
6
  export type { CapabilityStatus, CapabilityExecutionContext, CapabilityExecution, CapabilityHandler, CapabilityRendererProps, CapabilityRenderer, CapabilityConfig, CapabilityContent } from './capability';
7
7
  export type { ChatContextItem, ChatContextMap, ChatContextData, ChatContextValue } from './context';
8
+ export type { QuickAction, QuickActionConfig, QuickActionScopeMode, QuickActionScopeConfig, QuickActionFilter } from './quick-action';
@@ -0,0 +1,21 @@
1
+ export interface QuickAction {
2
+ id: string;
3
+ label: string;
4
+ prompt: string;
5
+ icon?: string;
6
+ description?: string;
7
+ priority?: number;
8
+ scope?: string;
9
+ }
10
+ export interface QuickActionConfig extends QuickAction {
11
+ condition?: () => boolean | Promise<boolean>;
12
+ }
13
+ export type QuickActionScopeMode = 'replace' | 'append' | 'merge';
14
+ export interface QuickActionScopeConfig {
15
+ scope: string;
16
+ mode?: QuickActionScopeMode;
17
+ }
18
+ export interface QuickActionFilter {
19
+ scope?: string;
20
+ visible?: boolean;
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harnessio/ai-chat-core",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "private": false,
@@ -52,6 +52,7 @@
52
52
  "build": "vite build",
53
53
  "build:ci": "vite build",
54
54
  "build:watch": "vite build --watch",
55
+ "test": "jest",
55
56
  "pretty": "prettier --check ./src",
56
57
  "pre-commit": "lint-staged"
57
58
  }