@openchamber/sdk 2.5.3 → 2.6.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/index.js CHANGED
@@ -6,11 +6,12 @@ export { GUEST_SHELL_END_STATUSES, GUEST_SHELL_ID_MAX, GUEST_SHELLS_MAX, GUEST_S
6
6
  export { GUEST_STATUS_CONTROLS_MAX, GUEST_STATUS_CONTROL_ID, GUEST_STATUS_CONTROL_LABEL_MAX, GUEST_STATUS_CONTROL_OPTIONS_MAX, GUEST_STATUS_CONTROL_VALUE_MAX } from './status-controls.js';
7
7
  export { GUEST_STATUS_SOURCE_INTERVAL_DEFAULT, GUEST_STATUS_SOURCE_INTERVAL_MAX, GUEST_STATUS_SOURCE_INTERVAL_MIN, GUEST_STATUS_VIEW_ACTIONS_MAX, GUEST_STATUS_VIEW_CHART_POINTS_MAX, GUEST_STATUS_VIEW_CHIPS_MAX, GUEST_STATUS_VIEW_ICON, GUEST_STATUS_VIEW_NOTE_MAX, GUEST_STATUS_VIEW_ROWS_MAX, GUEST_STATUS_VIEW_SEGMENTS_MAX, GUEST_STATUS_VIEW_SEGMENTS_MIN, GUEST_STATUS_VIEW_TEXT_MAX, } from './status-view.js';
8
8
  export { compareOpenChamberVersions, hostMeetsOpenChamberEngine, openChamberEngineMinimum, OPENCHAMBER_ENGINE_PATTERN, parseOpenChamberVersion, } from './host-version.js';
9
- export { DECLARED_GUEST_CAPABILITIES, GUEST_ACTIONS_MAX, GUEST_ACTION_LABEL_MAX, GUEST_CAPABILITIES, GUEST_COMMANDS_MAX, GUEST_COMMAND_DESCRIPTION_MAX, GUEST_COMMAND_NAME, GUEST_TOOLS_MAX, GUEST_TOOL_COLUMNS_MAX, GUEST_TOOL_COLUMN_MAX, GUEST_TOOL_LANGUAGE_MAX, GUEST_TOOL_MATCH, GUEST_TOOL_MATCH_MAX, GUEST_TOOL_NAME_MAX, GUEST_TOOL_OUTPUTS, GUEST_TOOL_TEMPLATE_MAX, GUEST_TOOL_TEMPLATE_VALUE_MAX, guestActionsNeedConversation, GUEST_FILESYSTEM_PATTERN_MAX, GUEST_FILESYSTEM_PATTERNS_MAX, GUEST_ORIGINS_MAX, GUEST_SERVICE_PROVIDES, GUEST_SURFACE_DOCKS, GUEST_SURFACE_DOCK_DEFAULT, GUEST_SURFACE_DOCK_SIZE_DEFAULT, GUEST_SURFACE_DOCK_SIZE_MAX, GUEST_SURFACE_DOCK_SIZE_MIN, GUEST_STATUS_SECTION_HEIGHT_DEFAULT, GUEST_STATUS_SECTION_HEIGHT_MAX, GUEST_STATUS_SECTION_HEIGHT_MIN, GUEST_STATUS_SECTION_TITLE_MAX, clampStatusSectionHeight, HOST_LINEAR_API_ORIGIN, isGuestFilesystemPattern, hasGuestCapability, hasGuestPage, isGuestApproved, isGuestPackageSvgIcon, requestedGuestCapabilities, resolveAttachEntry, resolvePageEntry, resolveStatusSectionEntry, resolveStatusSectionSource, resolveAttachMode, resolveIntegrationApi, resolveIntegrationAuth, serviceProvides, SOURCE_CONTROL_DEFAULT_INSTANCES_MAX, SOURCE_CONTROL_GUEST_ID_MAX, SOURCE_CONTROL_URL_TEMPLATES_MAX, SOURCE_CONTROL_URL_TEMPLATE_MAX, SOURCE_CONTROL_URL_TOKENS, sourceControlProviderIdOf, toPublicService, toPublicSourceControl, toPublicIntegration, } from './manifest.js';
9
+ export { DECLARED_GUEST_CAPABILITIES, GUEST_ACTIONS_MAX, GUEST_ACTION_LABEL_MAX, GUEST_CAPABILITIES, GUEST_COMMANDS_MAX, GUEST_COMMAND_DESCRIPTION_MAX, GUEST_COMMAND_NAME, GUEST_TOOLS_MAX, GUEST_TOOL_COLUMNS_MAX, GUEST_TOOL_COLUMN_MAX, GUEST_TOOL_LANGUAGE_MAX, GUEST_TOOL_MATCH, GUEST_TOOL_MATCH_MAX, GUEST_TOOL_NAME_MAX, GUEST_TOOL_OUTPUTS, GUEST_TOOL_TEMPLATE_MAX, GUEST_TOOL_TEMPLATE_VALUE_MAX, guestActionsNeedConversation, GUEST_FILESYSTEM_PATTERN_MAX, GUEST_FILESYSTEM_PATTERNS_MAX, GUEST_ORIGINS_MAX, GUEST_SERVICE_PROVIDES, GUEST_SURFACE_DOCKS, GUEST_SURFACE_DOCK_DEFAULT, GUEST_SURFACE_DOCK_SIZE_DEFAULT, GUEST_SURFACE_DOCK_SIZE_MAX, GUEST_SURFACE_DOCK_SIZE_MIN, GUEST_STATUS_SECTION_HEIGHT_DEFAULT, GUEST_STATUS_SECTION_HEIGHT_MAX, GUEST_STATUS_SECTION_HEIGHT_MIN, GUEST_STATUS_SECTION_TITLE_MAX, clampStatusSectionHeight, HOST_LINEAR_API_ORIGIN, isGuestFilesystemPattern, hasGuestCapability, hasGuestPage, isGuestApproved, isGuestPackageSvgIcon, NOTIFICATIONS_GUEST_ID_MAX, notificationProviderIdOf, requestedGuestCapabilities, resolveAttachEntry, resolvePageEntry, resolveStatusSectionEntry, resolveStatusSectionSource, resolveAttachMode, resolveIntegrationApi, resolveIntegrationAuth, serviceProvides, SOURCE_CONTROL_DEFAULT_INSTANCES_MAX, SOURCE_CONTROL_GUEST_ID_MAX, SOURCE_CONTROL_URL_TEMPLATES_MAX, SOURCE_CONTROL_URL_TEMPLATE_MAX, SOURCE_CONTROL_URL_TOKENS, sourceControlProviderIdOf, toPublicNotifications, toPublicService, toPublicSessionEvents, toPublicSourceControl, toPublicIntegration, toPublicTracker, TRACKER_BASE_STATE_FILTERS, TRACKER_GUEST_ID_MAX, TRACKER_IDENTIFIER_KINDS, TRACKER_STATE_FILTERS_MAX, TRACKER_URL_TEMPLATES_MAX, TRACKER_URL_TEMPLATE_MAX, TRACKER_URL_TOKENS, isTrackerUrlTemplate, trackerProviderIdOf, } from './manifest.js';
10
+ export { GUEST_SESSION_EVENT_TYPES, SESSION_EVENT_ERROR_MAX, SESSION_EVENT_PENDING_MAX, SESSION_EVENT_REPLY_MAX, SESSION_EVENT_TIMEOUT_MS, SESSION_EVENTS_IDLE_MS, SESSION_EVENTS_PATH, SESSION_EVENTS_WIRE_VERSION, isGuestSessionEventType, readSessionEventRequest, } from './session-events.js';
10
11
  export { GUEST_FILE_EDITORS_MAX, GUEST_FILE_EDITOR_CONTENT_MAX, GUEST_FILE_EDITOR_PATTERNS_MAX, GUEST_FILE_EDITOR_PATTERN_MAX, GUEST_FILE_EDITOR_TITLE_MAX, GUEST_FILE_EDITOR_VERSION_MAX, createFileSaveTracker, fileEditorPayloadSize, isFileEditorPattern, matchesFileEditorPattern, } from './file-editor.js';
11
12
  export { connectHost, HostRequestError } from './host.js';
12
13
  export { GUEST_POPOVER_COORDINATE_MAX, GUEST_POPOVER_DATA_DEPTH_MAX, GUEST_POPOVER_DATA_MAX, GUEST_POPOVER_HEIGHT_MAX, GUEST_POPOVER_HEIGHT_MIN, GUEST_POPOVER_ID, GUEST_POPOVER_SIDES, GUEST_POPOVER_WIDTH_MAX, GUEST_POPOVER_WIDTH_MIN, GUEST_POPOVER_CLOSE_REASONS, isGuestPopoverRequest, } from './popover.js';
13
14
  export { clampAttachRequest, clampBadgeCount, clampFrameHeight, isGuestCommitSha, GUEST_COMMIT_SHA, clampPromptRequest, clampStartSessionRequest, guestFileScope, isAttachData, isJsonValue, isFileListResult, isFileReadResult, isFileStatResult, isGenerateResult, isFileWriteResult, isGuestFilePath, isGuestAttachItem, isGuestMessageItem, isGuestSessionItem, isServiceStatusResult, isGuestRequestPath, isGuestRequestResult, isHostRequestErrorCode, isPromptResult, isStartSessionResult, readHostMessage, resolveHostRequestErrorCode, } from './contract.js';
14
15
  export { EMPTY_GUEST_CONNECTION, GUEST_BADGE_MAX, GUEST_FRAME_HEIGHT_MAX, GUEST_ITEM_MESSAGE_TEXT_MAX, GUEST_ITEM_SESSION_MAX, GUEST_RESOLVE_ERROR_MAX, GUEST_FILE_CONTENT_MAX, GUEST_FILE_ENTRY_KINDS, GUEST_FILE_LIST_MAX, GUEST_FILE_PATH_MAX, GUEST_GENERATE_OUTPUT_TOKENS_MAX, GUEST_GENERATE_PROMPT_MAX, GUEST_GENERATE_SYSTEM_MAX, GUEST_GENERATE_TEXT_MAX, GUEST_GENERATE_TIMEOUT_MS, GUEST_GENERATE_LATE_KEEP_MS, GUEST_GENERATE_LATE_MAX, GUEST_FILE_STAT_KINDS, SERVICE_STATUS_VALUES, HOST_REQUEST_ERROR_CODES, SESSION_LIFECYCLE_PHASES, START_SESSION_SENT, GUEST_ACCOUNT_MAX, GUEST_SESSION_AGENT_MAX, GUEST_SESSION_MODEL_MAX, GUEST_ATTACH_AUTHOR_MAX, GUEST_ATTACH_BRANCH_MAX, GUEST_ATTACH_DATA_MAX, GUEST_ATTACH_ID_MAX, GUEST_ATTACH_TEXT_MAX, GUEST_ATTACH_TITLE_MAX, GUEST_ATTACH_URL_MAX, GUEST_CLIPBOARD_TEXT_MAX, GUEST_TOAST_MAX, GUEST_COMPOSE_TEXT_MAX, GUEST_REQUEST_BODY_MAX, GUEST_REQUEST_PATH_MAX, GUEST_REQUEST_RESPONSE_MAX, GUEST_REQUEST_TIMEOUT_MS, GUEST_SETTING_VALUE_MAX, } from './contract.js';
15
- export { BROWSER_CONTROL_ACTIONS, BROWSER_PROVIDER_ACTION_TIMEOUT_MS, BROWSER_PROVIDER_IDLE_MS, BROWSER_PROVIDER_OPEN_TIMEOUT_MS, BROWSER_PROVIDER_PATH, BROWSER_PROVIDER_RESPONSE_MAX, BROWSER_SCROLL_DIRECTIONS, BROWSER_VIEWPORT_MODES, isBrowserControlAction, readBrowserProviderRequest, OPENCHAMBER_HOST_CALLBACK_URL, SOURCE_CONTROL_OUTBOUND_BODY_MAX, SOURCE_CONTROL_OUTBOUND_METHODS, SOURCE_CONTROL_OUTBOUND_PATH, SOURCE_CONTROL_OUTBOUND_REQUEST_HEADERS, SOURCE_CONTROL_OUTBOUND_RESPONSE_HEADERS, SOURCE_CONTROL_OUTBOUND_RESPONSE_HEADER_PREFIX, SOURCE_CONTROL_OUTBOUND_RESPONSE_MAX, SOURCE_CONTROL_OUTBOUND_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_AUTH_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_ERROR_MESSAGE_MAX, SOURCE_CONTROL_PROVIDER_IDLE_MS, SOURCE_CONTROL_PROVIDER_METHODS, SOURCE_CONTROL_PROVIDER_MUTATION_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_PATH, SOURCE_CONTROL_PROVIDER_READ_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_RESPONSE_MAX, SOURCE_CONTROL_PROVIDER_STATUS_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_TARGET_MAX, SOURCE_CONTROL_PROVIDER_WIRE_VERSION, SourceControlForgeError, createSourceControlForge, isSourceControlProviderMethod, readSourceControlProviderRequest, sourceControlProviderTimeoutMs, } from './service-providers.js';
16
+ export { BROWSER_CONTROL_ACTIONS, BROWSER_PROVIDER_ACTION_TIMEOUT_MS, BROWSER_PROVIDER_IDLE_MS, BROWSER_PROVIDER_OPEN_TIMEOUT_MS, BROWSER_PROVIDER_PATH, BROWSER_PROVIDER_RESPONSE_MAX, BROWSER_SCROLL_DIRECTIONS, BROWSER_VIEWPORT_MODES, isBrowserControlAction, readBrowserProviderRequest, OPENCHAMBER_HOST_CALLBACK_URL, SOURCE_CONTROL_OUTBOUND_BODY_MAX, SOURCE_CONTROL_OUTBOUND_METHODS, SOURCE_CONTROL_OUTBOUND_PATH, SOURCE_CONTROL_OUTBOUND_REQUEST_HEADERS, SOURCE_CONTROL_OUTBOUND_RESPONSE_HEADERS, SOURCE_CONTROL_OUTBOUND_RESPONSE_HEADER_PREFIX, SOURCE_CONTROL_OUTBOUND_RESPONSE_MAX, SOURCE_CONTROL_OUTBOUND_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_AUTH_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_ERROR_MESSAGE_MAX, SOURCE_CONTROL_PROVIDER_IDLE_MS, SOURCE_CONTROL_PROVIDER_METHODS, SOURCE_CONTROL_PROVIDER_MUTATION_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_PATH, SOURCE_CONTROL_PROVIDER_READ_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_RESPONSE_MAX, SOURCE_CONTROL_PROVIDER_STATUS_TIMEOUT_MS, SOURCE_CONTROL_PROVIDER_TARGET_MAX, SOURCE_CONTROL_PROVIDER_WIRE_VERSION, SourceControlForgeError, createSourceControlForge, isSourceControlProviderMethod, readSourceControlProviderRequest, sourceControlProviderTimeoutMs, GUEST_NOTIFICATION_KINDS, NOTIFICATIONS_OUTBOUND_PATH, NOTIFICATIONS_OUTBOUND_TIMEOUT_MS, NOTIFICATIONS_PROVIDER_AUTH_TIMEOUT_MS, NOTIFICATIONS_PROVIDER_ERROR_MESSAGE_MAX, NOTIFICATIONS_PROVIDER_IDLE_MS, NOTIFICATIONS_PROVIDER_METHODS, NOTIFICATIONS_PROVIDER_NOTIFY_TIMEOUT_MS, NOTIFICATIONS_PROVIDER_PATH, NOTIFICATIONS_PROVIDER_RESPONSE_MAX, NOTIFICATIONS_PROVIDER_WIRE_VERSION, NotificationsOutboundError, createNotificationsOutbound, isNotificationsProviderMethod, notificationsProviderTimeoutMs, readNotificationsProviderRequest, TRACKER_OUTBOUND_PATH, TRACKER_OUTBOUND_TIMEOUT_MS, TRACKER_PROVIDER_AUTH_TIMEOUT_MS, TRACKER_PROVIDER_CONTAINERS_MAX, TRACKER_PROVIDER_ERROR_MESSAGE_MAX, TRACKER_PROVIDER_IDLE_MS, TRACKER_PROVIDER_LIST_MAX, TRACKER_PROVIDER_LIVE_SUMMARIES_MAX, TRACKER_PROVIDER_METHODS, TRACKER_PROVIDER_PATH, TRACKER_PROVIDER_READ_TIMEOUT_MS, TRACKER_PROVIDER_RESPONSE_MAX, TRACKER_PROVIDER_WIRE_VERSION, TRACKER_PROVIDER_WRITE_METHODS, TRACKER_PROVIDER_WRITE_TIMEOUT_MS, TrackerOutboundError, createTrackerOutbound, isTrackerProviderMethod, isTrackerProviderWriteMethod, readTrackerProviderRequest, trackerProviderTimeoutMs, } from './service-providers.js';
16
17
  export { SURFACE_AGENT_ACTIVE_HEADER, SURFACE_AGENT_HOLD_MS, SURFACE_CLIPBOARD_PATH, SURFACE_CONTROL_PATH, SURFACE_CONTROLLERS, SURFACE_DIMENSION_MAX, SURFACE_FRAME_MAX_BYTES, SURFACE_FRAME_MIMES, SURFACE_FRAME_PATH, SURFACE_FRAME_SEQ_HEADER, SURFACE_FRAME_WAIT_MS, SURFACE_HEIGHT_HEADER, SURFACE_INPUT_BATCH_MAX, SURFACE_INPUT_PATH, SURFACE_RESIZE_PATH, SURFACE_SEQ_HEADER, SURFACE_TEXT_MAX, SURFACE_TITLE_HEADER, SURFACE_TITLE_MAX, SURFACE_VIEWER_CONTROLS_HEADER, SURFACE_VIEWER_HEADER, SURFACE_WIDTH_HEADER, readSurfaceControlNotice, readSurfaceInputBatch, readSurfaceResizeRequest, } from './service-surface.js';
@@ -1,6 +1,7 @@
1
1
  import type { OpenChamberManifestApiVersion } from './api-version.ts';
2
2
  import type { FileEditorContribution } from './file-editor.ts';
3
3
  import { type StatusSectionSource } from './status-view.ts';
4
+ import type { PublicSessionEvents, SessionEventsContribution } from './session-events.ts';
4
5
  export declare const PANEL_ID: RegExp;
5
6
  /**
6
7
  * The extension's identity on the rail, the Extensions card, and the approval
@@ -250,11 +251,15 @@ export type PublicSocketBinding = {
250
251
  * Host roles a service can stand in for. `browser` answers the agent's
251
252
  * `browser.*` actions in place of the in-app browser view. `source-control`
252
253
  * makes the extension a Git host next to GitHub, GitLab and Gitea, described
253
- * by `contributes.sourceControl`. Both contracts are in `service-providers.ts`.
254
+ * by `contributes.sourceControl`. `notifications` makes it a delivery channel
255
+ * for the user's notifications next to the desktop and the phone, described
256
+ * by `contributes.notifications`. `tracker` makes it a work item tracker next
257
+ * to Linear, described by `contributes.tracker`; an extension is a Git host
258
+ * or a tracker, never both. The contracts are in `service-providers.ts`.
254
259
  * A service that provides a role needs no panel or background entry: the host
255
260
  * starts it on the first call.
256
261
  */
257
- export declare const GUEST_SERVICE_PROVIDES: readonly ['browser', 'source-control'];
262
+ export declare const GUEST_SERVICE_PROVIDES: readonly ['browser', 'source-control', 'notifications', 'tracker'];
258
263
  export type GuestServiceProvides = (typeof GUEST_SERVICE_PROVIDES)[number];
259
264
  /**
260
265
  * The host names an extension's Git host `ext-<panel.id>`, and provider ids
@@ -264,6 +269,217 @@ export type GuestServiceProvides = (typeof GUEST_SERVICE_PROVIDES)[number];
264
269
  export declare const SOURCE_CONTROL_GUEST_ID_MAX = 28;
265
270
  /** The provider id OpenChamber gives the Git host an extension provides. */
266
271
  export declare const sourceControlProviderIdOf: (guestId: string) => string;
272
+ /** The notification channel is named `ext-<panel.id>` the same way, within the same 32 characters. */
273
+ export declare const NOTIFICATIONS_GUEST_ID_MAX = 28;
274
+ /** The provider id OpenChamber gives the notification channel an extension provides. */
275
+ export declare const notificationProviderIdOf: (guestId: string) => string;
276
+ /**
277
+ * `contributes.notifications`: the delivery channel an extension with
278
+ * `service.provides: ["notifications"]` adds, declared in the manifest so
279
+ * OpenChamber can draw its account card and route to it without starting the
280
+ * service. The account is OpenChamber's: the user connects it in Settings →
281
+ * Integrations, the token stays in OpenChamber, and the service reaches the
282
+ * channel's server through OpenChamber's outbound proxy with a per-call handle.
283
+ */
284
+ export type NotificationsContribution = {
285
+ /** The channel's name on its account card, shown untranslated. 1 to 64 characters. */
286
+ label: string;
287
+ /**
288
+ * Where every account lives: one `fixed` https origin (Slack's API), or an
289
+ * origin the `user` types when connecting (a Matrix homeserver), with the
290
+ * field's label and an optional example.
291
+ */
292
+ instances: {
293
+ kind: 'fixed';
294
+ origin: string;
295
+ } | {
296
+ kind: 'user';
297
+ label: string;
298
+ placeholder?: string;
299
+ };
300
+ /** How OpenChamber sends the token: which header, with which prefix. Same rules as `contributes.sourceControl.token`. */
301
+ token: {
302
+ header: 'authorization' | 'private-token';
303
+ scheme: 'bearer' | 'token' | 'basic' | 'none';
304
+ /** Settings asks for the account's username beside the token. Required with, and only with, `basic`. */
305
+ username?: boolean;
306
+ /** Scopes the Settings card asks the user to grant. */
307
+ scopes?: string[];
308
+ /** Path on the instance where tokens are created, linked from Settings. */
309
+ createPath?: string;
310
+ };
311
+ };
312
+ /** What the extension catalog and approval dialog show of the channel; never a token. */
313
+ export type PublicNotifications = {
314
+ label: string;
315
+ instances: {
316
+ kind: 'fixed';
317
+ origin: string;
318
+ } | {
319
+ kind: 'user';
320
+ label: string;
321
+ placeholder?: string;
322
+ };
323
+ token: {
324
+ scheme: 'bearer' | 'token' | 'basic' | 'none';
325
+ username: boolean;
326
+ scopes: string[];
327
+ createPath?: string;
328
+ };
329
+ };
330
+ export declare const toPublicNotifications: (contribution: NotificationsContribution) => PublicNotifications;
331
+ /** The tracker is named `ext-<panel.id>` the same way, within the same 32 characters. */
332
+ export declare const TRACKER_GUEST_ID_MAX = 28;
333
+ /** The provider id OpenChamber gives the tracker an extension provides. */
334
+ export declare const trackerProviderIdOf: (guestId: string) => string;
335
+ /** Link templates per tracker (`contributes.tracker.urls.item`). */
336
+ export declare const TRACKER_URL_TEMPLATES_MAX = 8;
337
+ /** Characters in one link template. */
338
+ export declare const TRACKER_URL_TEMPLATE_MAX = 256;
339
+ /**
340
+ * The placeholders a link template may use. `{id}` is the item's identifier,
341
+ * exactly once, in the path or as a query value (`?selectedIssue={id}`);
342
+ * `{segment}` is any one path segment; `{segments+}` one or more (a
343
+ * self-hosted server's prefix), at most once per template.
344
+ */
345
+ export declare const TRACKER_URL_TOKENS: readonly ['{id}', '{segment}', '{segments+}'];
346
+ /**
347
+ * A link template of a tracker item: `/`, segments that are each a literal or
348
+ * one of `TRACKER_URL_TOKENS`, and optionally `?name={id}`. `{id}` appears
349
+ * exactly once, in the path or as the query value; `{segments+}` at most once.
350
+ * The host compiles it into the pattern that recognises a pasted link; an
351
+ * extension never supplies a regular expression.
352
+ */
353
+ export declare const isTrackerUrlTemplate: (value: string) => boolean;
354
+ /** State filters every tracker offers, first in the menu; the rest are the tracker's own. */
355
+ export declare const TRACKER_BASE_STATE_FILTERS: readonly ['open', 'all'];
356
+ /** Filters a tracker may add past the base ones: the six neutral categories, then its own ids. */
357
+ export declare const TRACKER_STATE_FILTERS_MAX = 16;
358
+ /**
359
+ * The shape of an item's identifier, which OpenChamber compares
360
+ * case-insensitively everywhere (links, tracked items, session links):
361
+ * `key-number` is `PROJ-42` (Jira, YouTrack, Linear), `number` a bare number
362
+ * (Azure DevOps, Redmine), `short-code` letters and digits (Trello, ClickUp).
363
+ */
364
+ export declare const TRACKER_IDENTIFIER_KINDS: readonly ['key-number', 'number', 'short-code'];
365
+ export type TrackerIdentifierKind = (typeof TRACKER_IDENTIFIER_KINDS)[number];
366
+ /** The token block of a tracker, the Git host's rules. */
367
+ export type TrackerTokenAuth = {
368
+ header: 'authorization' | 'private-token';
369
+ scheme: 'bearer' | 'token' | 'basic' | 'none';
370
+ /** Settings asks for the account's username beside the token. Required with, and only with, `basic`. */
371
+ username?: boolean;
372
+ /** Scopes the Settings card asks the user to grant. */
373
+ scopes?: string[];
374
+ /** Path on the instance where tokens are created, linked from Settings. */
375
+ createPath?: string;
376
+ };
377
+ /**
378
+ * OAuth with PKCE, run by OpenChamber: the user enters the client id (and a
379
+ * secret, when the tracker issues one) on the card, signs in in the browser,
380
+ * and OpenChamber keeps the tokens. `authorizeUrl` and `tokenUrl` are https
381
+ * URLs, or paths on the instance (`/hub/api/rest/oauth2/auth`) for a tracker
382
+ * whose server the user names.
383
+ */
384
+ export type TrackerOAuth = {
385
+ authorizeUrl: string;
386
+ tokenUrl: string;
387
+ scopes?: string[];
388
+ };
389
+ /**
390
+ * What the tracker can do. A capability left out is off. Host access (an SDK
391
+ * guest borrowing the token) is not declared: the host keeps it off for every
392
+ * extension, because the service itself never sees a token.
393
+ */
394
+ export type TrackerCapabilities = {
395
+ multipleAccounts: boolean;
396
+ /** `items.updateState` and `states.list` are called. */
397
+ stateUpdate: boolean;
398
+ children: boolean;
399
+ labels: boolean;
400
+ priority: boolean;
401
+ filters: {
402
+ people: boolean;
403
+ priority: boolean;
404
+ };
405
+ /** `containers.list` is called, and Settings maps containers to projects. */
406
+ projectMapping: boolean;
407
+ /** `comments.create` is called with "session started / completed / failed" and a link. */
408
+ sessionComments: boolean;
409
+ };
410
+ /**
411
+ * `contributes.tracker`: the work item tracker an extension with
412
+ * `service.provides: ["tracker"]` adds next to Linear, declared in the manifest
413
+ * so OpenChamber can list it, draw its account card and recognise its links
414
+ * without starting the service. The provider id is not declared: OpenChamber
415
+ * names it `ext-<panel.id>`. Accounts and tokens are OpenChamber's; the
416
+ * service reaches the tracker's server through OpenChamber's outbound proxy
417
+ * with a per-call handle.
418
+ */
419
+ export type TrackerContribution = {
420
+ /** Wire version of the role's service contract; `1`. */
421
+ wire: 1;
422
+ /** The product name, shown untranslated. 1 to 64 characters. */
423
+ label: string;
424
+ /**
425
+ * Where the accounts live: one `fixed` https origin (a cloud tracker with
426
+ * one address), or an origin the `user` types when connecting (a self-hosted
427
+ * server, a per-company site), with the field's label and an optional example.
428
+ */
429
+ instances: {
430
+ kind: 'fixed';
431
+ origin: string;
432
+ } | {
433
+ kind: 'user';
434
+ label: string;
435
+ placeholder?: string;
436
+ };
437
+ /** How the user signs in: a pasted token, OAuth, or either. At least one. */
438
+ auth: {
439
+ token?: TrackerTokenAuth;
440
+ oauth?: TrackerOAuth;
441
+ };
442
+ capabilities: TrackerCapabilities;
443
+ /**
444
+ * In menu order: `open` and `all` first, then the neutral categories the
445
+ * tracker offers (`triage`, `backlog`, `todo`, `in-progress`, `done`,
446
+ * `canceled`) and its own filter ids (`inReview`). What `items.list` is asked for.
447
+ */
448
+ stateFilters: string[];
449
+ identifier: TrackerIdentifierKind;
450
+ /**
451
+ * Link templates of one item on the instance, made of literal segments and
452
+ * the `TRACKER_URL_TOKENS` placeholders, such as `/browse/{id}` or
453
+ * `/{segments+}?selectedIssue={id}`. OpenChamber compiles them; an extension
454
+ * never supplies a regular expression.
455
+ */
456
+ urls: {
457
+ item: string[];
458
+ };
459
+ };
460
+ /** What the extension catalog, the approval dialog and the account card show of the tracker; never a token. */
461
+ export type PublicTracker = {
462
+ label: string;
463
+ instances: {
464
+ kind: 'fixed';
465
+ origin: string;
466
+ } | {
467
+ kind: 'user';
468
+ label: string;
469
+ placeholder?: string;
470
+ };
471
+ authMethods: Array<'oauth' | 'token'>;
472
+ token?: {
473
+ scheme: 'bearer' | 'token' | 'basic' | 'none';
474
+ username: boolean;
475
+ scopes: string[];
476
+ createPath?: string;
477
+ };
478
+ oauth?: {
479
+ scopes: string[];
480
+ };
481
+ };
482
+ export declare const toPublicTracker: (contribution: TrackerContribution) => PublicTracker;
267
483
  /** Default instances a Git host extension may name. */
268
484
  export declare const SOURCE_CONTROL_DEFAULT_INSTANCES_MAX = 4;
269
485
  /** URL templates per kind (`presentation.urls.changeRequest` / `.issue`). */
@@ -456,9 +672,11 @@ export declare const serviceProvides: (service: Pick<ServiceContribution, 'provi
456
672
  * `shells` are declared under `contributes.capabilities`; `service`, `network`,
457
673
  * `filesystem` and `origins` follow from `contributes.service`,
458
674
  * `contributes.integration`, `contributes.filesystem` and `contributes.origins`. `model` is one-off text generation with the
459
- * user's Small Model (`host.generate`), outside any session.
675
+ * user's Small Model (`host.generate`), outside any session. `transcript`
676
+ * follows from `contributes.sessionEvents.content`: the service receives what
677
+ * the agent said or asked, not only that it did.
460
678
  */
461
- export declare const GUEST_CAPABILITIES: readonly ['prompt', 'sessions', 'files', 'model', 'shells', 'conversation', 'service', 'network', 'filesystem', 'origins'];
679
+ export declare const GUEST_CAPABILITIES: readonly ['prompt', 'sessions', 'files', 'model', 'shells', 'conversation', 'service', 'network', 'filesystem', 'origins', 'transcript'];
462
680
  export type GuestCapability = (typeof GUEST_CAPABILITIES)[number];
463
681
  export declare const DECLARED_GUEST_CAPABILITIES: readonly ['prompt', 'sessions', 'files', 'model', 'shells'];
464
682
  /** The capabilities a manifest may ask for directly. */
@@ -502,6 +720,12 @@ export type OpenChamberContributes = {
502
720
  fileEditors?: FileEditorContribution[];
503
721
  /** The Git host a `source-control` service provides; present exactly when it does. */
504
722
  sourceControl?: SourceControlContribution;
723
+ /** Session events OpenChamber posts to the service (`session-events.ts`). Needs `service`. */
724
+ sessionEvents?: SessionEventsContribution;
725
+ /** The notification channel a `notifications` service provides; present exactly when it does. */
726
+ notifications?: NotificationsContribution;
727
+ /** The work item tracker a `tracker` service provides; present exactly when it does. */
728
+ tracker?: TrackerContribution;
505
729
  };
506
730
  /** Whether any declared action asks for a session's messages, which needs `conversation`. */
507
731
  export declare const guestActionsNeedConversation: (actions: readonly GuestActionContribution[] | undefined) => boolean;
@@ -510,7 +734,9 @@ export type PublicGuestCapabilities = {
510
734
  requested: GuestCapability[];
511
735
  granted: GuestCapability[];
512
736
  };
513
- export declare const requestedGuestCapabilities: (contributes: Pick<OpenChamberContributes, 'capabilities' | 'integration' | 'service' | 'filesystem' | 'actions' | 'origins'>) => GuestCapability[];
737
+ export declare const requestedGuestCapabilities: (contributes: Pick<OpenChamberContributes, 'capabilities' | 'integration' | 'service' | 'filesystem' | 'actions' | 'origins' | 'sessionEvents'>) => GuestCapability[];
738
+ /** What the catalog and the approval dialog show of `contributes.sessionEvents`. */
739
+ export declare const toPublicSessionEvents: (contribution: SessionEventsContribution) => PublicSessionEvents;
514
740
  /**
515
741
  * Whether the package ships a visible panel. Background-only extensions can
516
742
  * execute code but have no rail surface, attach picker, or full-screen page.
@@ -543,7 +769,7 @@ export type OpenChamberManifest = {
543
769
  engines?: OpenChamberEngines;
544
770
  contributes: OpenChamberContributes;
545
771
  };
546
- export type ParseManifestErrorCode = 'not-object' | 'missing-openchamber' | 'unsupported-api-version' | 'invalid-engines' | 'invalid-version' | 'missing-panel' | 'invalid-panel' | 'invalid-panel-id' | 'invalid-panel-name' | 'invalid-panel-icon' | 'invalid-panel-entry' | 'invalid-background' | 'invalid-attach' | 'invalid-page' | 'invalid-status-section' | 'invalid-capabilities' | 'invalid-integration' | 'invalid-service' | 'invalid-filesystem' | 'invalid-origins' | 'invalid-actions' | 'invalid-commands' | 'invalid-tools' | 'invalid-file-editors';
772
+ export type ParseManifestErrorCode = 'not-object' | 'missing-openchamber' | 'unsupported-api-version' | 'invalid-engines' | 'invalid-version' | 'missing-panel' | 'invalid-panel' | 'invalid-panel-id' | 'invalid-panel-name' | 'invalid-panel-icon' | 'invalid-panel-entry' | 'invalid-background' | 'invalid-attach' | 'invalid-page' | 'invalid-status-section' | 'invalid-session-events' | 'invalid-capabilities' | 'invalid-integration' | 'invalid-service' | 'invalid-filesystem' | 'invalid-origins' | 'invalid-actions' | 'invalid-commands' | 'invalid-tools' | 'invalid-file-editors';
547
773
  export type ParseManifestFailure = {
548
774
  ok: false;
549
775
  code: ParseManifestErrorCode;
package/dist/manifest.js CHANGED
@@ -90,11 +90,15 @@ export const resolveIntegrationApi = (integration) => {
90
90
  * Host roles a service can stand in for. `browser` answers the agent's
91
91
  * `browser.*` actions in place of the in-app browser view. `source-control`
92
92
  * makes the extension a Git host next to GitHub, GitLab and Gitea, described
93
- * by `contributes.sourceControl`. Both contracts are in `service-providers.ts`.
93
+ * by `contributes.sourceControl`. `notifications` makes it a delivery channel
94
+ * for the user's notifications next to the desktop and the phone, described
95
+ * by `contributes.notifications`. `tracker` makes it a work item tracker next
96
+ * to Linear, described by `contributes.tracker`; an extension is a Git host
97
+ * or a tracker, never both. The contracts are in `service-providers.ts`.
94
98
  * A service that provides a role needs no panel or background entry: the host
95
99
  * starts it on the first call.
96
100
  */
97
- export const GUEST_SERVICE_PROVIDES = ['browser', 'source-control'];
101
+ export const GUEST_SERVICE_PROVIDES = ['browser', 'source-control', 'notifications', 'tracker'];
98
102
  /**
99
103
  * The host names an extension's Git host `ext-<panel.id>`, and provider ids
100
104
  * are at most 32 characters, so a guest taking the role has an id of at most
@@ -103,6 +107,99 @@ export const GUEST_SERVICE_PROVIDES = ['browser', 'source-control'];
103
107
  export const SOURCE_CONTROL_GUEST_ID_MAX = 28;
104
108
  /** The provider id OpenChamber gives the Git host an extension provides. */
105
109
  export const sourceControlProviderIdOf = (guestId) => `ext-${guestId}`;
110
+ /** The notification channel is named `ext-<panel.id>` the same way, within the same 32 characters. */
111
+ export const NOTIFICATIONS_GUEST_ID_MAX = 28;
112
+ /** The provider id OpenChamber gives the notification channel an extension provides. */
113
+ export const notificationProviderIdOf = (guestId) => `ext-${guestId}`;
114
+ export const toPublicNotifications = (contribution) => {
115
+ const token = {
116
+ scheme: contribution.token.scheme,
117
+ username: contribution.token.username === true,
118
+ scopes: [...(contribution.token.scopes ?? [])],
119
+ };
120
+ if (contribution.token.createPath)
121
+ token.createPath = contribution.token.createPath;
122
+ return { label: contribution.label, instances: { ...contribution.instances }, token };
123
+ };
124
+ /** The tracker is named `ext-<panel.id>` the same way, within the same 32 characters. */
125
+ export const TRACKER_GUEST_ID_MAX = 28;
126
+ /** The provider id OpenChamber gives the tracker an extension provides. */
127
+ export const trackerProviderIdOf = (guestId) => `ext-${guestId}`;
128
+ /** Link templates per tracker (`contributes.tracker.urls.item`). */
129
+ export const TRACKER_URL_TEMPLATES_MAX = 8;
130
+ /** Characters in one link template. */
131
+ export const TRACKER_URL_TEMPLATE_MAX = 256;
132
+ /**
133
+ * The placeholders a link template may use. `{id}` is the item's identifier,
134
+ * exactly once, in the path or as a query value (`?selectedIssue={id}`);
135
+ * `{segment}` is any one path segment; `{segments+}` one or more (a
136
+ * self-hosted server's prefix), at most once per template.
137
+ */
138
+ export const TRACKER_URL_TOKENS = ['{id}', '{segment}', '{segments+}'];
139
+ // A literal template segment: no placeholder braces, no regex syntax.
140
+ const TRACKER_URL_TEMPLATE_LITERAL = /^[A-Za-z0-9._~-]+$/;
141
+ const TRACKER_URL_TOKEN_SET = new Set(TRACKER_URL_TOKENS);
142
+ // `?name={id}`: the query parameter that carries the identifier.
143
+ const TRACKER_QUERY_TEMPLATE = /^([A-Za-z0-9_.-]{1,64})=\{id\}$/;
144
+ /**
145
+ * A link template of a tracker item: `/`, segments that are each a literal or
146
+ * one of `TRACKER_URL_TOKENS`, and optionally `?name={id}`. `{id}` appears
147
+ * exactly once, in the path or as the query value; `{segments+}` at most once.
148
+ * The host compiles it into the pattern that recognises a pasted link; an
149
+ * extension never supplies a regular expression.
150
+ */
151
+ export const isTrackerUrlTemplate = (value) => {
152
+ if (!value.startsWith('/') || value.length > TRACKER_URL_TEMPLATE_MAX)
153
+ return false;
154
+ const queryAt = value.indexOf('?');
155
+ const pathPart = queryAt === -1 ? value : value.slice(0, queryAt);
156
+ const queryPart = queryAt === -1 ? null : value.slice(queryAt + 1);
157
+ const segments = pathPart === '/' ? [] : pathPart.slice(1).split('/');
158
+ if (segments.some((segment) => segment === '.' || segment === '..'))
159
+ return false;
160
+ if (segments.some((segment) => !TRACKER_URL_TOKEN_SET.has(segment) && !TRACKER_URL_TEMPLATE_LITERAL.test(segment)))
161
+ return false;
162
+ const count = (token) => segments.filter((segment) => segment === token).length;
163
+ if (count('{segments+}') > 1)
164
+ return false;
165
+ if (queryPart === null)
166
+ return count('{id}') === 1;
167
+ return TRACKER_QUERY_TEMPLATE.test(queryPart) && count('{id}') === 0;
168
+ };
169
+ /** State filters every tracker offers, first in the menu; the rest are the tracker's own. */
170
+ export const TRACKER_BASE_STATE_FILTERS = ['open', 'all'];
171
+ /** Filters a tracker may add past the base ones: the six neutral categories, then its own ids. */
172
+ export const TRACKER_STATE_FILTERS_MAX = 16;
173
+ /**
174
+ * The shape of an item's identifier, which OpenChamber compares
175
+ * case-insensitively everywhere (links, tracked items, session links):
176
+ * `key-number` is `PROJ-42` (Jira, YouTrack, Linear), `number` a bare number
177
+ * (Azure DevOps, Redmine), `short-code` letters and digits (Trello, ClickUp).
178
+ */
179
+ export const TRACKER_IDENTIFIER_KINDS = ['key-number', 'number', 'short-code'];
180
+ export const toPublicTracker = (contribution) => {
181
+ const view = {
182
+ label: contribution.label,
183
+ instances: { ...contribution.instances },
184
+ // Browser sign-in first where both exist: it needs no token to be made by hand.
185
+ authMethods: [
186
+ ...(contribution.auth.oauth ? ['oauth'] : []),
187
+ ...(contribution.auth.token ? ['token'] : []),
188
+ ],
189
+ };
190
+ if (contribution.auth.token) {
191
+ view.token = {
192
+ scheme: contribution.auth.token.scheme,
193
+ username: contribution.auth.token.username === true,
194
+ scopes: [...(contribution.auth.token.scopes ?? [])],
195
+ };
196
+ if (contribution.auth.token.createPath)
197
+ view.token.createPath = contribution.auth.token.createPath;
198
+ }
199
+ if (contribution.auth.oauth)
200
+ view.oauth = { scopes: [...(contribution.auth.oauth.scopes ?? [])] };
201
+ return view;
202
+ };
106
203
  /** Default instances a Git host extension may name. */
107
204
  export const SOURCE_CONTROL_DEFAULT_INSTANCES_MAX = 4;
108
205
  /** URL templates per kind (`presentation.urls.changeRequest` / `.issue`). */
@@ -127,9 +224,11 @@ export const serviceProvides = (service, role) => Boolean(service?.provides?.inc
127
224
  * `shells` are declared under `contributes.capabilities`; `service`, `network`,
128
225
  * `filesystem` and `origins` follow from `contributes.service`,
129
226
  * `contributes.integration`, `contributes.filesystem` and `contributes.origins`. `model` is one-off text generation with the
130
- * user's Small Model (`host.generate`), outside any session.
227
+ * user's Small Model (`host.generate`), outside any session. `transcript`
228
+ * follows from `contributes.sessionEvents.content`: the service receives what
229
+ * the agent said or asked, not only that it did.
131
230
  */
132
- export const GUEST_CAPABILITIES = ['prompt', 'sessions', 'files', 'model', 'shells', 'conversation', 'service', 'network', 'filesystem', 'origins'];
231
+ export const GUEST_CAPABILITIES = ['prompt', 'sessions', 'files', 'model', 'shells', 'conversation', 'service', 'network', 'filesystem', 'origins', 'transcript'];
133
232
  export const DECLARED_GUEST_CAPABILITIES = ['prompt', 'sessions', 'files', 'model', 'shells'];
134
233
  /** How many `contributes.origins` a package may declare. */
135
234
  export const GUEST_ORIGINS_MAX = 8;
@@ -169,8 +268,15 @@ export const requestedGuestCapabilities = (contributes) => {
169
268
  declared.add('filesystem');
170
269
  if (contributes.origins && contributes.origins.length > 0)
171
270
  declared.add('origins');
271
+ if (contributes.sessionEvents?.content)
272
+ declared.add('transcript');
172
273
  return GUEST_CAPABILITIES.filter((capability) => declared.has(capability));
173
274
  };
275
+ /** What the catalog and the approval dialog show of `contributes.sessionEvents`. */
276
+ export const toPublicSessionEvents = (contribution) => ({
277
+ events: [...contribution.events],
278
+ content: contribution.content === true,
279
+ });
174
280
  /**
175
281
  * Whether the package ships a visible panel. Background-only extensions can
176
282
  * execute code but have no rail surface, attach picker, or full-screen page.