@canonmsg/core 0.15.4 → 0.16.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.
@@ -1,6 +1,5 @@
1
1
  import type { AgentRuntime, AgentSessionSnapshot, SessionConfig, SessionState } from './types.js';
2
2
  import type { TurnState } from './turn-protocol.js';
3
- import { type CanonWorkSessionContext } from './work-session.js';
4
3
  export interface BuildAgentSessionSnapshotInput {
5
4
  conversationId: string;
6
5
  agentId: string;
@@ -8,8 +7,6 @@ export interface BuildAgentSessionSnapshotInput {
8
7
  sessionConfig?: SessionConfig | null;
9
8
  sessionState?: SessionState | null;
10
9
  turnState?: TurnState | null;
11
- workSession?: CanonWorkSessionContext | null;
12
- workSessions?: CanonWorkSessionContext[] | null;
13
10
  lastHeartbeatAt?: number | null;
14
11
  updatedAt?: number | null;
15
12
  }
@@ -1,4 +1,3 @@
1
- import { mergeWorkSessionContexts, } from './work-session.js';
2
1
  function listDescriptorControls(runtime) {
3
2
  const descriptor = runtime?.runtimeDescriptor;
4
3
  return [
@@ -16,20 +15,6 @@ function descriptorDefaultValue(runtime, controlId) {
16
15
  .find((candidate) => candidate.id === controlId);
17
16
  return control?.defaultValue ?? undefined;
18
17
  }
19
- function buildWorkSessionSummary(workSession, workSessions) {
20
- const merged = mergeWorkSessionContexts(workSession, workSessions);
21
- const primary = merged[0];
22
- if (!primary?.id) {
23
- return null;
24
- }
25
- return {
26
- count: merged.length,
27
- id: primary.id,
28
- title: primary.title ?? null,
29
- objective: primary.objective ?? null,
30
- status: primary.status ?? null,
31
- };
32
- }
33
18
  function setControlState(controlState, id, value, source, appliedAt) {
34
19
  if (value === undefined)
35
20
  return;
@@ -147,6 +132,7 @@ export function buildAgentSessionSnapshot(input) {
147
132
  executionFallbackReason: input.sessionState?.executionFallbackReason,
148
133
  turnState: input.turnState?.state,
149
134
  supportsQueue: input.turnState?.capabilities?.supportsQueue,
135
+ supportsInputInterrupt: input.turnState?.capabilities?.supportsInterrupt,
150
136
  queueDepth: input.turnState?.queueDepth ?? 0,
151
137
  waitingForInput: input.turnState?.state === 'waiting_input',
152
138
  contextUsage: input.sessionState?.contextUsage,
@@ -154,7 +140,6 @@ export function buildAgentSessionSnapshot(input) {
154
140
  lastHeartbeatAt: input.lastHeartbeatAt
155
141
  ?? input.runtime?.updatedAt
156
142
  ?? input.sessionState?.updatedAt,
157
- workSession: buildWorkSessionSummary(input.workSession, input.workSessions),
158
143
  updatedAt: input.updatedAt
159
144
  ?? input.turnState?.updatedAt
160
145
  ?? input.sessionState?.updatedAt
package/dist/browser.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
2
2
  export { resolveCanonBaseUrl } from './base-url.js';
3
3
  export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
4
- export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentSessionWorkSessionSummary, AgentRuntime, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonStreamEvent, CreateContactRequestResult, MediaAttachment, MediaAttachmentKind, ModelOption, PermissionModeOption, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
4
+ export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentRuntime, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonStreamEvent, CreateContactRequestResult, MediaAttachment, MediaAttachmentKind, ModelOption, PermissionModeOption, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
5
5
  export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
6
6
  export type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
7
- export type { CanonResolvedWorkSession, CanonWorkSession, CanonWorkSessionContext, CanonWorkSessionConversationRole, CanonWorkSessionDisclosureMode, CanonWorkSessionParticipant, CanonWorkSessionStatus, CreateWorkSessionOptions, SendLinkedMessageOptions, SendLinkedMessageResult, UpdateWorkSessionConversationOptions, WorkSessionPromptRenderOptions, } from './work-session.js';
8
- export { buildWorkSessionPromptLines, buildWorkSessionsPromptLines, mergeWorkSessionContexts, } from './work-session.js';
7
+ export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
8
+ export { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
9
9
  export { buildAgentSessionSnapshot } from './agent-session.js';
10
- export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
10
+ export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
11
11
  export type { AgentBehaviorSettings, ParticipationHistoryMessage, ParticipationHistorySnapshot, ParticipationStyle, ResolvedAgentBehaviorPolicy, } from './policy.js';
12
12
  export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots, buildBehaviorPolicyLines, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, evaluateParticipationPolicy, getDefaultParticipationPolicy, resolveAgentBehaviorPolicy, } from './policy.js';
13
13
  export { DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, isTurnOpen, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
package/dist/browser.js CHANGED
@@ -2,9 +2,9 @@ export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js'
2
2
  export { resolveCanonBaseUrl } from './base-url.js';
3
3
  export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
4
4
  export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
5
- export { buildWorkSessionPromptLines, buildWorkSessionsPromptLines, mergeWorkSessionContexts, } from './work-session.js';
5
+ export { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
6
6
  export { buildAgentSessionSnapshot } from './agent-session.js';
7
- export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
7
+ export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
8
8
  export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots, buildBehaviorPolicyLines, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, evaluateParticipationPolicy, getDefaultParticipationPolicy, resolveAgentBehaviorPolicy, } from './policy.js';
9
9
  export { DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, isTurnOpen, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
10
10
  export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type CanonMessage, type CanonConversation, type CanonContact, type CanonContactRequest, type CanonMessagesPage, type CanonResolveAdmissionResult, type AgentContext, type AddMemberResult, type CreateContactRequestResult, type MediaAttachment, type SendMessageOptions, type CreateConversationOptions, type RegistrationStatus, type SetStreamingOptions } from './types.js';
2
- import type { CanonResolvedWorkSession, CreateWorkSessionOptions, SendLinkedMessageOptions, SendLinkedMessageResult, UpdateWorkSessionConversationOptions } from './work-session.js';
2
+ import type { SendContextualMessageOptions, SendContextualMessageResult } from './self-context.js';
3
3
  import type { InboundDisposition } from './turn-protocol.js';
4
4
  /**
5
5
  * Thin REST client for Canon's agent API.
@@ -25,10 +25,7 @@ export declare class CanonClient {
25
25
  sendMessage(conversationId: string, text: string, options?: SendMessageOptions): Promise<{
26
26
  messageId: string;
27
27
  }>;
28
- createWorkSession(options: CreateWorkSessionOptions): Promise<CanonResolvedWorkSession>;
29
- getWorkSession(workSessionId: string, conversationId: string): Promise<CanonResolvedWorkSession>;
30
- upsertWorkSessionConversation(workSessionId: string, conversationId: string, options?: UpdateWorkSessionConversationOptions): Promise<CanonResolvedWorkSession>;
31
- sendLinkedMessage(options: SendLinkedMessageOptions): Promise<SendLinkedMessageResult>;
28
+ sendContextualMessage(options: SendContextualMessageOptions): Promise<SendContextualMessageResult>;
32
29
  createConversation(options: CreateConversationOptions): Promise<{
33
30
  conversationId: string;
34
31
  }>;
package/dist/client.js CHANGED
@@ -82,8 +82,8 @@ export class CanonClient {
82
82
  throw new CanonApiError(res.status, await res.text());
83
83
  return res.json();
84
84
  }
85
- async createWorkSession(options) {
86
- const res = await fetch(`${this.baseUrl}/work-sessions`, {
85
+ async sendContextualMessage(options) {
86
+ const res = await fetch(`${this.baseUrl}/messages/send-contextual`, {
87
87
  method: 'POST',
88
88
  headers: this.authHeaders(),
89
89
  body: JSON.stringify(options),
@@ -92,44 +92,6 @@ export class CanonClient {
92
92
  throw new CanonApiError(res.status, await res.text());
93
93
  return res.json();
94
94
  }
95
- async getWorkSession(workSessionId, conversationId) {
96
- const params = new URLSearchParams({ conversationId });
97
- const res = await fetch(`${this.baseUrl}/work-sessions/${workSessionId}?${params}`, { headers: this.authHeaders() });
98
- if (!res.ok)
99
- throw new CanonApiError(res.status, await res.text());
100
- return res.json();
101
- }
102
- async upsertWorkSessionConversation(workSessionId, conversationId, options) {
103
- const res = await fetch(`${this.baseUrl}/work-sessions/${workSessionId}/conversations/${conversationId}`, {
104
- method: 'PUT',
105
- headers: this.authHeaders(),
106
- body: JSON.stringify(options ?? {}),
107
- });
108
- if (!res.ok)
109
- throw new CanonApiError(res.status, await res.text());
110
- return res.json();
111
- }
112
- async sendLinkedMessage(options) {
113
- const res = await fetch(`${this.baseUrl}/messages/send-linked`, {
114
- method: 'POST',
115
- headers: this.authHeaders(),
116
- body: JSON.stringify({
117
- sourceConversationId: options.sourceConversationId,
118
- targetConversationId: options.targetConversationId,
119
- text: options.text,
120
- ...(options.workSessionId ? { workSessionId: options.workSessionId } : {}),
121
- ...(options.createWorkSession
122
- ? { createWorkSession: options.createWorkSession }
123
- : {}),
124
- ...(options.sourceContext ? { sourceContext: options.sourceContext } : {}),
125
- ...(options.targetContext ? { targetContext: options.targetContext } : {}),
126
- ...(options.messageOptions ? { messageOptions: options.messageOptions } : {}),
127
- }),
128
- });
129
- if (!res.ok)
130
- throw new CanonApiError(res.status, await res.text());
131
- return res.json();
132
- }
133
95
  async createConversation(options) {
134
96
  const res = await fetch(`${this.baseUrl}/conversations/create`, {
135
97
  method: 'POST',
@@ -33,8 +33,7 @@ export declare function buildCanonHostPrompt(input: {
33
33
  conversationId: string;
34
34
  participantContext: HostInboundParticipantContext;
35
35
  behavior?: ResolvedAgentBehaviorPolicy | null;
36
- workSession?: MessageCreatedPayload['message']['workSession'];
37
- workSessions?: MessageCreatedPayload['workSessions'];
36
+ selfContexts?: MessageCreatedPayload['selfContexts'];
38
37
  buildInboundContextLines: (context: HostInboundParticipantContext) => string[];
39
38
  sessionContextLines?: string[];
40
39
  }): string;
@@ -68,7 +67,7 @@ export declare function buildHydratedInboundContext(input: {
68
67
  }): {
69
68
  participantContext: HostInboundParticipantContext;
70
69
  behavior?: ResolvedAgentBehaviorPolicy | null;
71
- workSessions: NonNullable<MessageCreatedPayload['workSessions']>;
70
+ selfContexts: NonNullable<MessageCreatedPayload['selfContexts']>;
72
71
  hydratedFromPage: boolean;
73
72
  };
74
73
  export declare function publishHostAgentRuntime(agentId: string, clientType: AgentClientType, runtime: AgentRuntime): Promise<void>;
@@ -1,7 +1,7 @@
1
1
  import { buildAgentSessionSnapshot } from './agent-session.js';
2
2
  import { buildConversationWorktreeSpec, normalizeOptionalString, readSessionWorkspaceConfig, resolveConfiguredWorkspaceCwd, } from './execution-environment.js';
3
3
  import { buildBehaviorPolicyLines, buildParticipationHistorySnapshot, } from './policy.js';
4
- import { buildWorkSessionsPromptLines, mergeWorkSessionContexts, } from './work-session.js';
4
+ import { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
5
5
  import { rtdbRead } from './rtdb-rest.js';
6
6
  import { createRuntimeStatePublisher } from './runtime-state-publisher.js';
7
7
  const HOST_INBOUND_CONTACT_CARD_ACTION_CAPABILITIES = Object.freeze({
@@ -11,18 +11,18 @@ const HOST_INBOUND_CONTACT_CARD_ACTION_CAPABILITIES = Object.freeze({
11
11
  canRejectPendingContactRequests: false,
12
12
  });
13
13
  export function buildCanonHostPrompt(input) {
14
- const resolvedWorkSessions = mergeWorkSessionContexts(input.workSession, input.workSessions);
14
+ const resolvedSelfContexts = normalizeSelfContexts(input.selfContexts);
15
15
  return [
16
16
  `You are connected to Canon messaging through a ${input.hostLabel} host wrapper.`,
17
17
  'Only the last assistant message from this turn will be delivered as the permanent Canon reply.',
18
18
  'Short intermediate assistant messages may be shown as ephemeral status while you work.',
19
19
  ...input.buildInboundContextLines(input.participantContext),
20
20
  ...buildBehaviorPolicyLines(input.behavior),
21
- ...buildWorkSessionsPromptLines(resolvedWorkSessions),
21
+ ...buildSelfContextPromptLines(resolvedSelfContexts),
22
22
  'Canon participants may be humans or AI agents.',
23
23
  'Honor the Canon behavior policy above when deciding how proactively to participate.',
24
- ...(resolvedWorkSessions.length > 0
25
- ? ['Honor the Canon work-session context above within its stated disclosure limits.']
24
+ ...(resolvedSelfContexts.length > 0
25
+ ? ['Honor the Canon self-context above when continuing your own cross-session action.']
26
26
  : []),
27
27
  ...(input.sessionContextLines?.length
28
28
  ? ['Canon session state:', ...input.sessionContextLines]
@@ -117,7 +117,7 @@ export function buildHydratedInboundContext(input) {
117
117
  currentAgentStreakStartedByHuman: history.currentAgentStreakStartedByHuman,
118
118
  },
119
119
  behavior: input.page?.behavior ?? input.conversation?.behavior,
120
- workSessions: input.page?.workSessions ?? [],
120
+ selfContexts: input.page?.selfContexts ?? [],
121
121
  hydratedFromPage: input.page != null,
122
122
  };
123
123
  }
package/dist/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
2
- export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, AgentSessionWorkSessionSummary, ResolvedAdmission, MediaAttachment, MediaAttachmentKind, MessageCreatedPayload, TypingPayload, PresencePayload, RuntimeUpdatedPayload, TurnUpdatedPayload, SendMessageOptions, CreateConversationOptions, RegistrationInput, RegistrationResult, RegistrationStatus, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
3
- export type { CanonResolvedWorkSession, CanonWorkSession, CanonWorkSessionContext, CanonWorkSessionConversationRole, CreateWorkSessionOptions, CanonWorkSessionDisclosureMode, CanonWorkSessionParticipant, CanonWorkSessionStatus, SendLinkedMessageOptions, SendLinkedMessageResult, UpdateWorkSessionConversationOptions, WorkSessionPromptRenderOptions, } from './work-session.js';
4
- export { buildWorkSessionPromptLines, buildWorkSessionsPromptLines, mergeWorkSessionContexts, } from './work-session.js';
2
+ export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, ResolvedAdmission, MediaAttachment, MediaAttachmentKind, MessageCreatedPayload, TypingPayload, PresencePayload, RuntimeUpdatedPayload, TurnUpdatedPayload, SendMessageOptions, CreateConversationOptions, RegistrationInput, RegistrationResult, RegistrationStatus, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
3
+ export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
4
+ export { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
5
5
  export { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildWorkspaceRootId, discoverWorkspaceProjects, } from './workspace-discovery.js';
6
6
  export type { ConfiguredWorkspaceRoot, WorkspaceDiscoveryResult, } from './workspace-discovery.js';
7
7
  export { CanonClient, CanonApiError } from './client.js';
8
8
  export { buildAgentSessionSnapshot } from './agent-session.js';
9
- export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
9
+ export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
10
10
  export { CanonStream } from './stream.js';
11
11
  export type { StreamHandler } from './stream.js';
12
- export type { PolicyRole, ParticipationStyle, RepresentationMode, PermissionLevel, ConversationScope, AgentBehaviorSettings, Participant, Relationship, ContextOverlay, BehaviorProfile, AdmissionPolicy, RuntimeControlPolicy, ActionApprovalPolicy, ParticipationPolicy, WorkSession, ResolvedPolicy, ResolvedTurnEligibility, ResolvedAgentBehaviorPolicy, ParticipationHistoryMessage, ParticipationHistorySnapshot, ParticipationDecisionInput, ParticipationDecision, } from './policy.js';
12
+ export type { PolicyRole, ParticipationStyle, RepresentationMode, PermissionLevel, ConversationScope, AgentBehaviorSettings, Participant, Relationship, ContextOverlay, BehaviorProfile, AdmissionPolicy, RuntimeControlPolicy, ActionApprovalPolicy, ParticipationPolicy, ResolvedPolicy, ResolvedTurnEligibility, ResolvedAgentBehaviorPolicy, ParticipationHistoryMessage, ParticipationHistorySnapshot, ParticipationDecisionInput, ParticipationDecision, } from './policy.js';
13
13
  export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots, buildBehaviorPolicyLines, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, evaluateParticipationPolicy, getDefaultParticipationPolicy, resolveAgentBehaviorPolicy, } from './policy.js';
14
14
  export { DEFAULT_RUNTIME_CAPABILITIES, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, FINAL_MESSAGE_HANDOFF_MS, isTurnOpen, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
15
15
  export type { DeliveryIntent, TurnMessageSemantics, InboundDisposition, TurnLifecycleState, RuntimeCapabilities, HostAdmissionActionCapabilities, TurnState, TurnMetadata, TriggerDecision, } from './turn-protocol.js';
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // Types
2
2
  export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
3
- export { buildWorkSessionPromptLines, buildWorkSessionsPromptLines, mergeWorkSessionContexts, } from './work-session.js';
3
+ export { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
4
4
  export { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildWorkspaceRootId, discoverWorkspaceProjects, } from './workspace-discovery.js';
5
5
  // Client
6
6
  export { CanonClient, CanonApiError } from './client.js';
7
7
  export { buildAgentSessionSnapshot } from './agent-session.js';
8
- export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
8
+ export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildFirstPartyCodingRuntimeDescriptor, buildRuntimeEffortControl, buildRuntimeExecutionModeControl, buildRuntimeExecutionModeOptions, buildRuntimeModelControl, buildRuntimePermissionModeControl, buildRuntimeWorkspaceControl, buildRuntimeWorkspaceControlOptions, } from './runtime-descriptor.js';
9
9
  // Stream
10
10
  export { CanonStream } from './stream.js';
11
11
  export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots, buildBehaviorPolicyLines, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, evaluateParticipationPolicy, getDefaultParticipationPolicy, resolveAgentBehaviorPolicy, } from './policy.js';
package/dist/policy.d.ts CHANGED
@@ -67,16 +67,6 @@ export interface ParticipationPolicy {
67
67
  requireMentionForGroupReplies: boolean;
68
68
  maxConsecutiveAgentTurns?: number | null;
69
69
  }
70
- export interface WorkSession {
71
- id: string;
72
- conversationId?: string | null;
73
- label?: string | null;
74
- objective?: string | null;
75
- participationStyle?: ParticipationStyle;
76
- activeParticipantIds: string[];
77
- overlayIds?: string[];
78
- status: "active" | "paused" | "completed";
79
- }
80
70
  export interface ResolvedPolicy {
81
71
  admission: AdmissionPolicy;
82
72
  runtime: RuntimeControlPolicy;
@@ -90,7 +80,6 @@ export interface ResolvedPolicy {
90
80
  globalDefault?: string;
91
81
  agentDefault?: string;
92
82
  relationship?: string;
93
- workSession?: string;
94
83
  messageDirective?: string;
95
84
  };
96
85
  }
@@ -80,6 +80,7 @@ export interface AgentSessionSnapshotPatch {
80
80
  state?: null;
81
81
  turnState?: TurnLifecycleState | null;
82
82
  supportsQueue?: boolean | null;
83
+ supportsInputInterrupt?: boolean | null;
83
84
  queueDepth?: number;
84
85
  waitingForInput?: boolean;
85
86
  contextUsage?: {
@@ -91,13 +92,6 @@ export interface AgentSessionSnapshotPatch {
91
92
  lastHeartbeatAt?: number | {
92
93
  '.sv': 'timestamp';
93
94
  };
94
- workSession?: {
95
- count: number;
96
- id: string;
97
- title?: string | null;
98
- objective?: string | null;
99
- status?: string | null;
100
- } | null;
101
95
  updatedAt?: {
102
96
  '.sv': 'timestamp';
103
97
  };
package/dist/rtdb-rest.js CHANGED
@@ -198,6 +198,9 @@ function createRTDBClientHandle(client, options) {
198
198
  ...(state.capabilities?.supportsQueue !== undefined
199
199
  ? { supportsQueue: state.capabilities.supportsQueue }
200
200
  : {}),
201
+ ...(state.capabilities?.supportsInterrupt !== undefined
202
+ ? { supportsInputInterrupt: state.capabilities.supportsInterrupt }
203
+ : {}),
201
204
  queueDepth: state.queueDepth,
202
205
  waitingForInput: state.state === 'waiting_input',
203
206
  lastHeartbeatAt: { '.sv': 'timestamp' },
@@ -36,6 +36,9 @@ export declare function buildRuntimePermissionModeControl(input: {
36
36
  defaultValue?: string | null;
37
37
  }): CanonControlDescriptor;
38
38
  export declare function buildRuntimeEffortControl(): CanonControlDescriptor;
39
+ export declare const RUNTIME_STOP_ACTION: CanonRuntimeActionDescriptor;
40
+ export declare const RUNTIME_STOP_AND_DROP_ACTION: CanonRuntimeActionDescriptor;
41
+ export declare const RUNTIME_NEW_SESSION_ACTION: CanonRuntimeActionDescriptor;
39
42
  export declare function buildFirstPartyCodingRuntimeDescriptor(input: {
40
43
  clientType: Extract<AgentClientType, 'claude-code' | 'codex'>;
41
44
  models: ReadonlyArray<ModelOption>;
@@ -93,6 +93,36 @@ export function buildRuntimeEffortControl() {
93
93
  selectionPolicy: 'inherit',
94
94
  };
95
95
  }
96
+ export const RUNTIME_STOP_ACTION = {
97
+ id: 'stop',
98
+ label: 'Stop',
99
+ description: 'Interrupt the current turn.',
100
+ aliases: ['stop'],
101
+ category: 'turn',
102
+ placements: ['composer_slash', 'command_palette'],
103
+ availability: ['busy'],
104
+ dispatch: { kind: 'signal', signal: 'interrupt' },
105
+ };
106
+ export const RUNTIME_STOP_AND_DROP_ACTION = {
107
+ id: 'stop-and-clear-queue',
108
+ label: 'Stop & clear queue',
109
+ description: 'Interrupt the current turn and drop queued Canon messages.',
110
+ aliases: ['stop-clear', 'clear-queue'],
111
+ category: 'turn',
112
+ placements: ['composer_slash', 'command_palette', 'session_strip'],
113
+ availability: ['busy_with_queue'],
114
+ dispatch: { kind: 'signal', signal: 'stop_and_drop' },
115
+ };
116
+ export const RUNTIME_NEW_SESSION_ACTION = {
117
+ id: 'new-session',
118
+ label: 'New session',
119
+ description: 'Reset this runtime session inside the current Canon chat.',
120
+ aliases: ['new'],
121
+ category: 'session',
122
+ placements: ['composer_slash', 'command_palette', 'session_strip'],
123
+ availability: ['always'],
124
+ dispatch: { kind: 'signal', signal: 'new_session' },
125
+ };
96
126
  export function buildFirstPartyCodingRuntimeDescriptor(input) {
97
127
  const permissionModes = input.permissionModes
98
128
  ?? (input.clientType === 'claude-code' ? CLAUDE_PERMISSION_MODE_OPTIONS : []);
@@ -122,6 +152,7 @@ export function buildFirstPartyCodingRuntimeDescriptor(input) {
122
152
  actions: input.actions,
123
153
  workspaceRoots: input.workspaceRoots,
124
154
  supportsInterrupt: true,
155
+ supportsInputInterrupt: true,
125
156
  streamingTextMode: input.streamingTextMode,
126
157
  admissionActions: input.admissionActions,
127
158
  };
@@ -0,0 +1,39 @@
1
+ export type CanonSelfContextType = 'cross_session';
2
+ export interface CanonSelfContext {
3
+ id: string;
4
+ type: CanonSelfContextType;
5
+ context: string;
6
+ createdAt?: string | null;
7
+ updatedAt?: string | null;
8
+ }
9
+ export interface SendContextualSelfContextInput {
10
+ type: CanonSelfContextType;
11
+ context: string;
12
+ }
13
+ export interface SendContextualMessageOptions {
14
+ sourceConversationId: string;
15
+ targetConversationId?: string;
16
+ targetUserId?: string;
17
+ text: string;
18
+ selfContext: SendContextualSelfContextInput;
19
+ sessionConfig?: import('./types.js').SessionConfig | null;
20
+ requestMessage?: string | null;
21
+ messageOptions?: Omit<import('./types.js').SendMessageOptions, 'selfContextId' | 'selfContext'>;
22
+ }
23
+ export type SendContextualMessageResult = {
24
+ status: 'messaged';
25
+ messageId: string;
26
+ conversationId: string;
27
+ selfContextId: string;
28
+ } | {
29
+ status: 'requested' | 'pending';
30
+ requestId: string | null;
31
+ } | {
32
+ status: 'setup_required' | 'blocked' | 'unavailable';
33
+ reason: string;
34
+ };
35
+ export interface SelfContextPromptRenderOptions {
36
+ maxSelfContexts?: number;
37
+ }
38
+ export declare function normalizeSelfContexts(selfContexts?: CanonSelfContext[] | null, options?: SelfContextPromptRenderOptions): CanonSelfContext[];
39
+ export declare function buildSelfContextPromptLines(selfContexts?: CanonSelfContext[] | null, options?: SelfContextPromptRenderOptions): string[];
@@ -0,0 +1,66 @@
1
+ const DEFAULT_SELF_CONTEXT_PROMPT_OPTIONS = {
2
+ maxSelfContexts: 3,
3
+ };
4
+ function normalizeString(value) {
5
+ if (typeof value !== 'string')
6
+ return null;
7
+ const trimmed = value.trim();
8
+ return trimmed.length > 0 ? trimmed : null;
9
+ }
10
+ function resolvePromptOptions(options) {
11
+ return {
12
+ maxSelfContexts: Math.max(1, options?.maxSelfContexts ?? DEFAULT_SELF_CONTEXT_PROMPT_OPTIONS.maxSelfContexts),
13
+ };
14
+ }
15
+ function contextSortTime(context) {
16
+ const updatedAt = normalizeString(context.updatedAt);
17
+ if (updatedAt) {
18
+ const parsed = new Date(updatedAt).getTime();
19
+ if (Number.isFinite(parsed))
20
+ return parsed;
21
+ }
22
+ const createdAt = normalizeString(context.createdAt);
23
+ if (createdAt) {
24
+ const parsed = new Date(createdAt).getTime();
25
+ if (Number.isFinite(parsed))
26
+ return parsed;
27
+ }
28
+ return 0;
29
+ }
30
+ export function normalizeSelfContexts(selfContexts, options) {
31
+ if (!Array.isArray(selfContexts))
32
+ return [];
33
+ const promptOptions = resolvePromptOptions(options);
34
+ const byId = new Map();
35
+ for (const selfContext of selfContexts) {
36
+ const id = normalizeString(selfContext?.id);
37
+ const context = normalizeString(selfContext?.context);
38
+ if (!id || !context || selfContext.type !== 'cross_session')
39
+ continue;
40
+ byId.set(id, {
41
+ id,
42
+ type: 'cross_session',
43
+ context,
44
+ createdAt: normalizeString(selfContext.createdAt),
45
+ updatedAt: normalizeString(selfContext.updatedAt),
46
+ });
47
+ }
48
+ return [...byId.values()]
49
+ .sort((left, right) => contextSortTime(right) - contextSortTime(left))
50
+ .slice(0, promptOptions.maxSelfContexts);
51
+ }
52
+ export function buildSelfContextPromptLines(selfContexts, options) {
53
+ const resolved = normalizeSelfContexts(selfContexts, options);
54
+ if (resolved.length === 0)
55
+ return [];
56
+ const lines = ['Canon cross-session self-context for you:'];
57
+ resolved.forEach((selfContext, index) => {
58
+ if (resolved.length > 1) {
59
+ lines.push(`Self-context ${index + 1}:`);
60
+ }
61
+ lines.push(`Context type: ${selfContext.type}.`);
62
+ lines.push(`Why you are speaking in this conversation: ${selfContext.context}`);
63
+ });
64
+ lines.push('Canon rule: this self-context explains your own prior cross-session action; it does not grant access to the source transcript. Keep Canon sessions separate.');
65
+ return lines;
66
+ }
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
2
2
  import type { ResolvedAgentBehaviorPolicy } from './policy.js';
3
3
  import type { TurnLifecycleState } from './turn-protocol.js';
4
- import type { CanonWorkSessionContext } from './work-session.js';
4
+ import type { CanonSelfContext } from './self-context.js';
5
5
  export type { ExecutionEnvironmentMode };
6
6
  export type MediaAttachmentKind = 'image' | 'audio' | 'file';
7
7
  export interface MediaAttachment {
@@ -51,7 +51,6 @@ export interface CanonMessage {
51
51
  replyToPosition: number | null;
52
52
  forwarded?: boolean;
53
53
  forwardedFrom?: ForwardedFrom;
54
- workSession?: CanonWorkSessionContext | null;
55
54
  metadata?: Record<string, unknown>;
56
55
  contactCard?: ContactCardPayload;
57
56
  status: 'sent' | 'read';
@@ -78,7 +77,7 @@ export interface CanonConversation {
78
77
  export interface CanonMessagesPage {
79
78
  messages: CanonMessage[];
80
79
  behavior?: ResolvedAgentBehaviorPolicy;
81
- workSessions?: CanonWorkSessionContext[];
80
+ selfContexts?: CanonSelfContext[];
82
81
  }
83
82
  export type CanonContactRequestStatus = 'pending' | 'approved' | 'rejected' | 'expired';
84
83
  export interface CanonContactRequest {
@@ -236,7 +235,7 @@ export type CanonRuntimeActionDispatch = {
236
235
  value: CanonControlValue;
237
236
  } | {
238
237
  kind: 'signal';
239
- signal: 'interrupt' | 'stop_and_drop';
238
+ signal: 'interrupt' | 'stop_and_drop' | 'new_session';
240
239
  } | {
241
240
  kind: 'compose';
242
241
  text: string;
@@ -279,6 +278,7 @@ export interface CanonRuntimeDescriptor {
279
278
  workspaceRoots?: ReadonlyArray<CanonWorkspaceRootMetadata>;
280
279
  writableRoots?: ReadonlyArray<CanonWorkspaceRootMetadata>;
281
280
  supportsInterrupt?: boolean;
281
+ supportsInputInterrupt?: boolean;
282
282
  /**
283
283
  * Fidelity of live text exposed through Canon's streaming bubble path.
284
284
  * `delta` means token/content deltas, `block` means chunked live previews,
@@ -355,7 +355,7 @@ export interface AgentContext {
355
355
  export interface MessageCreatedPayload {
356
356
  conversationId: string;
357
357
  behavior?: ResolvedAgentBehaviorPolicy;
358
- workSessions?: CanonWorkSessionContext[];
358
+ selfContexts?: CanonSelfContext[];
359
359
  message: {
360
360
  id: string;
361
361
  senderId: string;
@@ -372,7 +372,6 @@ export interface MessageCreatedPayload {
372
372
  forwardedFrom?: ForwardedFrom;
373
373
  mentions?: string[];
374
374
  createdAt?: string;
375
- workSession?: CanonWorkSessionContext | null;
376
375
  /** Structured metadata for rich UI (approval cards, etc.) */
377
376
  metadata?: Record<string, unknown>;
378
377
  /** Populated when `contentType === 'contact_card'`. */
@@ -453,7 +452,7 @@ export interface SendMessageOptions {
453
452
  attachments?: MediaAttachment[];
454
453
  contactCardUserId?: string;
455
454
  mentions?: string[];
456
- workSessionId?: string;
455
+ selfContextId?: string;
457
456
  /** Structured metadata for rich UI (approval cards, etc.) */
458
457
  metadata?: Record<string, unknown>;
459
458
  }
@@ -577,13 +576,6 @@ export interface AgentRuntime {
577
576
  availableWorkspaces?: WorkspaceOption[];
578
577
  updatedAt?: number;
579
578
  }
580
- export interface AgentSessionWorkSessionSummary {
581
- count: number;
582
- id: string;
583
- title?: string | null;
584
- objective?: string | null;
585
- status?: CanonWorkSessionContext['status'] | null;
586
- }
587
579
  export interface AgentSessionSnapshot {
588
580
  conversationId: string;
589
581
  agentId: string;
@@ -610,12 +602,12 @@ export interface AgentSessionSnapshot {
610
602
  executionFallbackReason?: string | null;
611
603
  turnState?: TurnLifecycleState;
612
604
  supportsQueue?: boolean;
605
+ supportsInputInterrupt?: boolean;
613
606
  queueDepth: number;
614
607
  waitingForInput: boolean;
615
608
  contextUsage?: SessionState['contextUsage'];
616
609
  lastError?: string;
617
610
  lastHeartbeatAt?: number;
618
- workSession?: AgentSessionWorkSessionSummary | null;
619
611
  updatedAt?: number;
620
612
  }
621
613
  export interface RegistrationInput {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/core",
3
- "version": "0.15.4",
3
+ "version": "0.16.0",
4
4
  "description": "Canon core — shared types, REST client, SSE stream, and registration for Canon messaging",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,88 +0,0 @@
1
- import type { RepresentationMode } from './policy.js';
2
- import type { SendMessageOptions } from './types.js';
3
- export type CanonWorkSessionStatus = 'active' | 'paused' | 'completed';
4
- export type CanonWorkSessionConversationRole = 'requester' | 'coordinator' | 'participant' | 'delegate' | 'observer';
5
- export type CanonWorkSessionDisclosureMode = 'none' | 'summary' | 'full';
6
- export interface CanonWorkSessionParticipant {
7
- conversationId?: string | null;
8
- participantId?: string | null;
9
- label?: string | null;
10
- role?: CanonWorkSessionConversationRole | null;
11
- }
12
- export interface CanonWorkSessionContext {
13
- id: string;
14
- title?: string | null;
15
- objective?: string | null;
16
- status?: CanonWorkSessionStatus | null;
17
- summary?: string | null;
18
- representation?: RepresentationMode | null;
19
- currentConversationRole?: CanonWorkSessionConversationRole | null;
20
- sourceConversationId?: string | null;
21
- sourceConversationLabel?: string | null;
22
- sourceParticipantId?: string | null;
23
- sourceParticipantLabel?: string | null;
24
- disclosure?: CanonWorkSessionDisclosureMode | null;
25
- disclosureNotes?: string[];
26
- visibleFacts?: string[];
27
- pendingQuestions?: string[];
28
- participants?: CanonWorkSessionParticipant[];
29
- updatedAt?: string | null;
30
- }
31
- export interface CanonWorkSession {
32
- id: string;
33
- title?: string | null;
34
- objective?: string | null;
35
- status: CanonWorkSessionStatus;
36
- createdAt?: string | null;
37
- updatedAt?: string | null;
38
- }
39
- export interface UpdateWorkSessionConversationOptions {
40
- summary?: string | null;
41
- representation?: RepresentationMode | null;
42
- currentConversationRole?: CanonWorkSessionConversationRole | null;
43
- sourceConversationId?: string | null;
44
- sourceConversationLabel?: string | null;
45
- sourceParticipantId?: string | null;
46
- sourceParticipantLabel?: string | null;
47
- disclosure?: CanonWorkSessionDisclosureMode | null;
48
- disclosureNotes?: string[];
49
- visibleFacts?: string[];
50
- pendingQuestions?: string[];
51
- participants?: CanonWorkSessionParticipant[];
52
- }
53
- export interface CreateWorkSessionOptions extends UpdateWorkSessionConversationOptions {
54
- conversationId: string;
55
- title?: string | null;
56
- objective?: string | null;
57
- status?: CanonWorkSessionStatus | null;
58
- }
59
- export interface CanonResolvedWorkSession {
60
- workSession: CanonWorkSession;
61
- context: CanonWorkSessionContext;
62
- }
63
- export interface SendLinkedMessageOptions {
64
- sourceConversationId: string;
65
- targetConversationId: string;
66
- text: string;
67
- workSessionId?: string;
68
- createWorkSession?: Omit<CreateWorkSessionOptions, 'conversationId'>;
69
- sourceContext?: UpdateWorkSessionConversationOptions;
70
- targetContext?: UpdateWorkSessionConversationOptions;
71
- messageOptions?: Omit<SendMessageOptions, 'workSessionId'>;
72
- }
73
- export interface SendLinkedMessageResult {
74
- messageId: string;
75
- workSessionId: string;
76
- workSessionCreated: boolean;
77
- }
78
- export interface WorkSessionPromptRenderOptions {
79
- maxVisibleFacts?: number;
80
- maxPendingQuestions?: number;
81
- maxDisclosureNotes?: number;
82
- maxParticipants?: number;
83
- maxDetailedWorkSessions?: number;
84
- maxOtherWorkSessions?: number;
85
- }
86
- export declare function mergeWorkSessionContexts(explicitWorkSession?: CanonWorkSessionContext | null, activeWorkSessions?: CanonWorkSessionContext[] | null): CanonWorkSessionContext[];
87
- export declare function buildWorkSessionPromptLines(workSession?: CanonWorkSessionContext | null, options?: WorkSessionPromptRenderOptions): string[];
88
- export declare function buildWorkSessionsPromptLines(workSessions?: CanonWorkSessionContext[] | null, options?: WorkSessionPromptRenderOptions): string[];
@@ -1,238 +0,0 @@
1
- const DEFAULT_WORK_SESSION_PROMPT_OPTIONS = {
2
- maxVisibleFacts: 3,
3
- maxPendingQuestions: 2,
4
- maxDisclosureNotes: 1,
5
- maxParticipants: 3,
6
- maxDetailedWorkSessions: 1,
7
- maxOtherWorkSessions: 3,
8
- };
9
- function normalizeString(value) {
10
- if (typeof value !== 'string')
11
- return null;
12
- const trimmed = value.trim();
13
- return trimmed.length > 0 ? trimmed : null;
14
- }
15
- function normalizeStringList(value) {
16
- if (!Array.isArray(value))
17
- return [];
18
- return value
19
- .map((entry) => normalizeString(entry))
20
- .filter((entry) => entry != null);
21
- }
22
- function mergeStringLists(primary, secondary) {
23
- const merged = [...normalizeStringList(primary), ...normalizeStringList(secondary)];
24
- const unique = Array.from(new Set(merged));
25
- return unique.length > 0 ? unique : undefined;
26
- }
27
- function mergeParticipants(primary, secondary) {
28
- const result = [];
29
- const seen = new Set();
30
- const pushParticipant = (participant) => {
31
- if (!participant)
32
- return;
33
- const key = [
34
- normalizeString(participant.conversationId),
35
- normalizeString(participant.participantId),
36
- normalizeString(participant.label),
37
- normalizeString(participant.role),
38
- ].join('::');
39
- if (seen.has(key))
40
- return;
41
- seen.add(key);
42
- result.push(participant);
43
- };
44
- for (const participant of primary ?? [])
45
- pushParticipant(participant);
46
- for (const participant of secondary ?? [])
47
- pushParticipant(participant);
48
- return result.length > 0 ? result : undefined;
49
- }
50
- function mergeTwoWorkSessions(primary, secondary) {
51
- const disclosureNotes = mergeStringLists(primary.disclosureNotes, secondary.disclosureNotes);
52
- const visibleFacts = mergeStringLists(primary.visibleFacts, secondary.visibleFacts);
53
- const pendingQuestions = mergeStringLists(primary.pendingQuestions, secondary.pendingQuestions);
54
- const participants = mergeParticipants(primary.participants, secondary.participants);
55
- return {
56
- id: primary.id,
57
- title: primary.title ?? secondary.title ?? null,
58
- objective: primary.objective ?? secondary.objective ?? null,
59
- status: primary.status ?? secondary.status ?? null,
60
- summary: primary.summary ?? secondary.summary ?? null,
61
- representation: primary.representation ?? secondary.representation ?? null,
62
- currentConversationRole: primary.currentConversationRole ?? secondary.currentConversationRole ?? null,
63
- sourceConversationId: primary.sourceConversationId ?? secondary.sourceConversationId ?? null,
64
- sourceConversationLabel: primary.sourceConversationLabel ?? secondary.sourceConversationLabel ?? null,
65
- sourceParticipantId: primary.sourceParticipantId ?? secondary.sourceParticipantId ?? null,
66
- sourceParticipantLabel: primary.sourceParticipantLabel ?? secondary.sourceParticipantLabel ?? null,
67
- disclosure: primary.disclosure ?? secondary.disclosure ?? null,
68
- ...(disclosureNotes ? { disclosureNotes } : {}),
69
- ...(visibleFacts ? { visibleFacts } : {}),
70
- ...(pendingQuestions ? { pendingQuestions } : {}),
71
- ...(participants ? { participants } : {}),
72
- updatedAt: primary.updatedAt ?? secondary.updatedAt ?? null,
73
- };
74
- }
75
- export function mergeWorkSessionContexts(explicitWorkSession, activeWorkSessions) {
76
- const merged = new Map();
77
- const add = (workSession) => {
78
- if (!workSession?.id)
79
- return;
80
- const existing = merged.get(workSession.id);
81
- merged.set(workSession.id, existing ? mergeTwoWorkSessions(existing, workSession) : workSession);
82
- };
83
- add(explicitWorkSession);
84
- for (const workSession of activeWorkSessions ?? []) {
85
- add(workSession);
86
- }
87
- return Array.from(merged.values());
88
- }
89
- function formatParticipantLabel(participant) {
90
- const label = normalizeString(participant.label);
91
- if (label)
92
- return label;
93
- const participantId = normalizeString(participant.participantId);
94
- if (participantId)
95
- return participantId;
96
- return normalizeString(participant.conversationId);
97
- }
98
- function resolvePromptOptions(options) {
99
- return {
100
- maxVisibleFacts: Math.max(0, options?.maxVisibleFacts
101
- ?? DEFAULT_WORK_SESSION_PROMPT_OPTIONS.maxVisibleFacts),
102
- maxPendingQuestions: Math.max(0, options?.maxPendingQuestions
103
- ?? DEFAULT_WORK_SESSION_PROMPT_OPTIONS.maxPendingQuestions),
104
- maxDisclosureNotes: Math.max(0, options?.maxDisclosureNotes
105
- ?? DEFAULT_WORK_SESSION_PROMPT_OPTIONS.maxDisclosureNotes),
106
- maxParticipants: Math.max(0, options?.maxParticipants ?? DEFAULT_WORK_SESSION_PROMPT_OPTIONS.maxParticipants),
107
- maxDetailedWorkSessions: Math.max(1, options?.maxDetailedWorkSessions
108
- ?? DEFAULT_WORK_SESSION_PROMPT_OPTIONS.maxDetailedWorkSessions),
109
- maxOtherWorkSessions: Math.max(0, options?.maxOtherWorkSessions
110
- ?? DEFAULT_WORK_SESSION_PROMPT_OPTIONS.maxOtherWorkSessions),
111
- };
112
- }
113
- function takeWithHiddenCount(values, maxCount) {
114
- if (maxCount <= 0) {
115
- return { visible: [], hiddenCount: values.length };
116
- }
117
- return {
118
- visible: values.slice(0, maxCount),
119
- hiddenCount: Math.max(0, values.length - maxCount),
120
- };
121
- }
122
- function buildOriginLabel(workSession) {
123
- const sourceConversation = normalizeString(workSession.sourceConversationLabel)
124
- ?? normalizeString(workSession.sourceConversationId);
125
- const sourceParticipant = normalizeString(workSession.sourceParticipantLabel)
126
- ?? normalizeString(workSession.sourceParticipantId);
127
- if (sourceConversation && sourceParticipant) {
128
- return `${sourceParticipant} in ${sourceConversation}`;
129
- }
130
- return sourceParticipant ?? sourceConversation;
131
- }
132
- function formatWorkSessionReference(workSession) {
133
- const title = normalizeString(workSession.title);
134
- const objective = normalizeString(workSession.objective);
135
- if (title)
136
- return `${title} (${workSession.id})`;
137
- if (objective)
138
- return `${objective} (${workSession.id})`;
139
- return workSession.id;
140
- }
141
- export function buildWorkSessionPromptLines(workSession, options) {
142
- if (!workSession)
143
- return [];
144
- const promptOptions = resolvePromptOptions(options);
145
- const title = normalizeString(workSession.title);
146
- const objective = normalizeString(workSession.objective);
147
- const summary = normalizeString(workSession.summary);
148
- const origin = buildOriginLabel(workSession);
149
- const visibleFacts = takeWithHiddenCount(normalizeStringList(workSession.visibleFacts), promptOptions.maxVisibleFacts);
150
- const pendingQuestions = takeWithHiddenCount(normalizeStringList(workSession.pendingQuestions), promptOptions.maxPendingQuestions);
151
- const disclosureNotes = takeWithHiddenCount(normalizeStringList(workSession.disclosureNotes), promptOptions.maxDisclosureNotes);
152
- const participants = takeWithHiddenCount(Array.isArray(workSession.participants) ? workSession.participants : [], promptOptions.maxParticipants);
153
- return [
154
- `Canon work session ID: ${workSession.id}`,
155
- ...(title ? [`Canon work session title: ${title}`] : []),
156
- ...(objective ? [`Canon work session objective: ${objective}`] : []),
157
- ...(workSession.status
158
- ? [`Canon work session status: ${workSession.status}`]
159
- : []),
160
- ...(workSession.currentConversationRole
161
- ? [
162
- `This conversation's role in the work session: ${workSession.currentConversationRole}`,
163
- ]
164
- : []),
165
- ...(workSession.representation
166
- ? [`Participate in this conversation as: ${workSession.representation}`]
167
- : []),
168
- ...(origin ? [`Work session origin: ${origin}`] : []),
169
- ...(workSession.disclosure
170
- ? [`Allowed disclosure level in this conversation: ${workSession.disclosure}`]
171
- : []),
172
- ...(summary ? [`Shared work session summary: ${summary}`] : []),
173
- ...visibleFacts.visible.map((fact, index) => `Shared fact ${index + 1}: ${fact}`),
174
- ...(visibleFacts.hiddenCount > 0
175
- ? [`Additional shared facts omitted for brevity: ${visibleFacts.hiddenCount}`]
176
- : []),
177
- ...pendingQuestions.visible.map((question, index) => `Open question ${index + 1}: ${question}`),
178
- ...(pendingQuestions.hiddenCount > 0
179
- ? [
180
- `Additional open questions omitted for brevity: ${pendingQuestions.hiddenCount}`,
181
- ]
182
- : []),
183
- ...disclosureNotes.visible.map((note, index) => `Disclosure note ${index + 1}: ${note}`),
184
- ...(disclosureNotes.hiddenCount > 0
185
- ? [
186
- `Additional disclosure notes omitted for brevity: ${disclosureNotes.hiddenCount}`,
187
- ]
188
- : []),
189
- ...participants.visible.flatMap((participant, index) => {
190
- const label = formatParticipantLabel(participant);
191
- if (!label)
192
- return [];
193
- const role = normalizeString(participant.role);
194
- return [
195
- `Related participant ${index + 1}: ${label}${role ? ` (${role})` : ''}`,
196
- ];
197
- }),
198
- ...(participants.hiddenCount > 0
199
- ? [
200
- `Additional related participants omitted for brevity: ${participants.hiddenCount}`,
201
- ]
202
- : []),
203
- 'Canon rule: this shared work-session context is scoped to this conversation only and does not grant access to other conversation transcripts.',
204
- ];
205
- }
206
- export function buildWorkSessionsPromptLines(workSessions, options) {
207
- const promptOptions = resolvePromptOptions(options);
208
- if (!Array.isArray(workSessions) || workSessions.length === 0)
209
- return [];
210
- if (workSessions.length === 1) {
211
- return [
212
- 'Canon active work session for this conversation:',
213
- ...buildWorkSessionPromptLines(workSessions[0], promptOptions),
214
- ];
215
- }
216
- const detailedWorkSessions = workSessions.slice(0, promptOptions.maxDetailedWorkSessions);
217
- const hiddenWorkSessions = workSessions.slice(promptOptions.maxDetailedWorkSessions);
218
- const lines = ['Canon active work sessions for this conversation:'];
219
- detailedWorkSessions.forEach((workSession, index) => {
220
- lines.push(detailedWorkSessions.length === 1
221
- ? 'Primary active work session:'
222
- : `Detailed work session ${index + 1}:`);
223
- lines.push(...buildWorkSessionPromptLines(workSession, promptOptions));
224
- });
225
- if (hiddenWorkSessions.length > 0) {
226
- lines.push('Other active work sessions linked here:');
227
- hiddenWorkSessions
228
- .slice(0, promptOptions.maxOtherWorkSessions)
229
- .forEach((workSession, index) => {
230
- lines.push(`Other work session ${index + 1}: ${formatWorkSessionReference(workSession)}`);
231
- });
232
- if (hiddenWorkSessions.length > promptOptions.maxOtherWorkSessions) {
233
- lines.push(`Additional active work sessions omitted for brevity: ${hiddenWorkSessions.length - promptOptions.maxOtherWorkSessions}`);
234
- }
235
- lines.push('Canon rule: do not assume the current message refers to another linked work session unless the conversation clearly points to it.');
236
- }
237
- return lines;
238
- }