@standardagents/code-plugin-sdk 1.0.0-alpha.5-usage.0 → 1.0.0-alpha.7-theme.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/README.md CHANGED
@@ -11,8 +11,8 @@ Its `package.json` includes a static `standardPlugin` manifest.
11
11
  {
12
12
  "name": "example-status",
13
13
  "type": "module",
14
- "peerDependencies": { "@standardagents/code-plugin-sdk": "^1.0.0-alpha.5-usage.0" },
15
- "devDependencies": { "@standardagents/code-plugin-sdk": "^1.0.0-alpha.5-usage.0" },
14
+ "peerDependencies": { "@standardagents/code-plugin-sdk": "^1.0.0-alpha.7-theme.0" },
15
+ "devDependencies": { "@standardagents/code-plugin-sdk": "^1.0.0-alpha.7-theme.0" },
16
16
  "standardPlugin": {
17
17
  "apiVersion": 1,
18
18
  "id": "example-status",
package/REFERENCE.md CHANGED
@@ -31,7 +31,14 @@ Contribution declarations contain a stable ID, surface kind, anchor, title,
31
31
  merge mode, width, menu position, palette group, chord, URL pattern, and
32
32
  action ID as appropriate.
33
33
 
34
- A `card` declaration draws a boxed card in the sidebar. `validateManifest`
34
+ A `card` declaration draws a sidebar card. Its optional `border` boolean
35
+ defaults to `true`. Set `border: false` for a borderless group: the host
36
+ retains the author title, content padding, focus indication, and activation
37
+ behavior, and removes the outline and bottom border row. This preference
38
+ is declared by each plugin on its own cards; other surface kinds reject it.
39
+ The nested view node named `card` is a separate content element.
40
+
41
+ `validateManifest`
35
42
  refuses a card whose anchor is not `plugins`. Two optional fields control
36
43
  panels:
37
44
 
@@ -234,6 +241,11 @@ add node types.
234
241
 
235
242
  ### Card views
236
243
 
244
+ Titles come from the contribution's `title`. The host adds no status dot,
245
+ health text, or machine label to a card title or panel. Authors can include
246
+ indicators in their own title or content. Runtime health remains available in
247
+ plugin management through `ctx.health.set()`.
248
+
237
249
  A card shows a short summary. Its view can contain `stack`, `row`, `text`,
238
250
  `badge`, `dot`, `progress`, `segments`, `stat`, and `divider` nodes, and it
239
251
  is at most 6 lines tall. A `stack` is as tall as its children plus `gap`
@@ -346,8 +358,8 @@ contributions when their target disappears or changes generation.
346
358
 
347
359
  Sections, plugin cards, machine slots, stacked pane header/footer slots, canvas surfaces, host-rendered views,
348
360
  global command palette entries, and the three
349
- panel presentations are implemented. A popover is content-sized within the
350
- modal area. A column attaches to the sidebar and resizes the workspace. A
361
+ panel presentations are implemented. A popover follows the content width and height within the
362
+ modal area. Its title is the contribution title and its body starts beneath it. A column attaches to the sidebar and resizes the workspace. A
351
363
  plugin pane has a tab and focus, drag, close, and reveal behavior; its width
352
364
  follows content and it does not create a tmux pane or resize a terminal.
353
365
 
@@ -504,3 +516,21 @@ It records traces, surface replacement, subscriptions, and resources without
504
516
  starting subprocesses. `harness.surface(id, entity?)` returns the current
505
517
  content of a published contribution, including view and canvas content, or
506
518
  `undefined` after the contribution clears.
519
+
520
+ ### Canvas theme colors
521
+
522
+ `CanvasSpec.themeColors` maps up to 32 canvas-local ANSI indexes (0–255) to
523
+ recipes. Each recipe has `source` (optional ANSI index 0–15, omitted for the
524
+ default foreground), `mix` (optional second ANSI index mixed equally), and
525
+ `opacity` (0–1, blended against the viewer background). Both foreground and
526
+ background SGR references to that index resolve through the same recipe.
527
+ For example, `{ 16: { source: 4, opacity: 0.72 }, 20: { opacity: 0.4 } }`
528
+ provides muted terminal blue at index 16 and a subtle foreground at index 20.
529
+
530
+ Resolution occurs in the viewer for sidebar, pane, slot, column, and popover
531
+ canvases. Remote producers do not read or bake another machine's colors.
532
+ Recipes remain unchanged across terminal theme updates. Unavailable source
533
+ colors fall back to the named ANSI index or default foreground; unavailable
534
+ background colors leave opacity unapplied. OSC queries remain unsupported
535
+ in plugin canvas streams. This capability is public and identical for all
536
+ plugins.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standardagents/code-plugin-sdk",
3
- "version": "1.0.0-alpha.5-usage.0",
3
+ "version": "1.0.0-alpha.7-theme.0",
4
4
  "type": "module",
5
5
  "description": "Standard Code plugin authoring SDK",
6
6
  "license": "MIT",
package/src/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type Json = null | boolean | number | string | Json[] | { [key: string]: Json };
2
2
  export type Capability = 'surfaces' | 'events' | 'hooks' | 'panes' | 'projects' |
3
3
  'notifications' | 'url' | 'fetch' | 'secrets' | 'webhook';
4
- /** `card` draws a boxed card in the sidebar under the `plugins` anchor. */
4
+ /** `card` draws a sidebar card under the `plugins` anchor, with an optional border. */
5
5
  export type SurfaceKind = 'section' | 'card' | 'slot' | 'badge' | 'panel' | 'overlay' |
6
6
  'menu' | 'command' | 'key' | 'link';
7
7
  /** How a panel opens. Absent means `popover`. */
@@ -14,6 +14,8 @@ export interface ContributionDeclaration {
14
14
  id: string;
15
15
  kind: SurfaceKind;
16
16
  anchor: Anchor;
17
+ /** Sidebar card border. Defaults to true; false retains the title and content padding. */
18
+ border?: boolean;
17
19
  title?: string;
18
20
  merge?: 'by-machine' | 'by-identity';
19
21
  width?: 'full' | 'half';
@@ -84,7 +86,17 @@ export type TextContent = { kind: 'text'; lines: TextSpan[][] };
84
86
  export type BadgeContent = { kind: 'badge'; spans: TextSpan[]; actionId?: string };
85
87
  export type NativeContent = RowsContent | TextContent | BadgeContent;
86
88
  /** `columns` is also the intrinsic width of a card, column, or plugin pane that shows the canvas. */
89
+ export interface CanvasThemeColor {
90
+ /** ANSI palette index 0..15; omitted uses the viewer's default foreground. */
91
+ source?: number;
92
+ /** Optional second ANSI palette index, mixed equally with source. */
93
+ mix?: number;
94
+ /** Blend against the viewer background, from 0 to 1. */
95
+ opacity: number;
96
+ }
87
97
  export interface CanvasSpec {
98
+ /** Up to 32 canvas-local indexed color recipes. Keys are ANSI indexes 0..255. */
99
+ themeColors?: Record<number, CanvasThemeColor>;
88
100
  columns: number;
89
101
  rows: number;
90
102
  transparent?: boolean;
package/src/manifest.mjs CHANGED
@@ -76,6 +76,8 @@ export function validateManifest(value) {
76
76
  ensure(object(declaration) && identifier(declaration.id) && !ids.has(declaration.id) &&
77
77
  SURFACE_KINDS.includes(declaration.kind) && ANCHORS.includes(declaration.anchor), 'invalid_manifest', 'Invalid contribution declaration')
78
78
  ids.add(declaration.id)
79
+ ensure(declaration.border === undefined || (typeof declaration.border === 'boolean' && declaration.kind === 'card'),
80
+ 'invalid_manifest', 'Only sidebar cards declare a boolean border preference')
79
81
  for (const [key, choices] of Object.entries({ merge: ['by-machine', 'by-identity'], width: ['full', 'half'],
80
82
  position: ['top', 'after-open', 'before-danger', 'bottom'], presentation: PRESENTATIONS })) {
81
83
  ensure(declaration[key] === undefined || choices.includes(declaration[key]), 'invalid_manifest', `Invalid contribution ${key}`)
package/src/runtime.mjs CHANGED
@@ -94,10 +94,20 @@ function validateContent(content, declaration, manifest) {
94
94
  if (content.kind === 'view') validateView(content.root, { kind: declaration.kind, manifest })
95
95
  jsonBytes(content)
96
96
  if (content.kind === 'canvas') {
97
- const { columns, rows, shade = 0, hover } = content.canvas ?? {}
97
+ const { columns, rows, shade = 0, hover, themeColors } = content.canvas ?? {}
98
98
  ensure(Number.isSafeInteger(columns) && columns > 0 && columns <= LIMITS.canvasColumns &&
99
99
  Number.isSafeInteger(rows) && rows > 0 && rows <= LIMITS.canvasRows &&
100
100
  Number.isFinite(shade) && shade >= 0 && shade <= 1, 'invalid_payload', 'Invalid canvas dimensions or shade')
101
+ if (themeColors !== undefined) {
102
+ ensure(object(themeColors) && Object.keys(themeColors).length <= 32, 'invalid_payload', 'Invalid canvas theme colors')
103
+ for (const [index, recipe] of Object.entries(themeColors)) {
104
+ ensure(/^(0|[1-9][0-9]{0,2})$/.test(index) && Number(index) <= 255 && object(recipe) &&
105
+ Object.keys(recipe).every(key=>['source','mix','opacity'].includes(key)) &&
106
+ ['source','mix'].every(key=>recipe[key] === undefined || (Number.isInteger(recipe[key]) && recipe[key]>=0 && recipe[key]<16)) &&
107
+ Number.isFinite(recipe.opacity) && recipe.opacity>=0 && recipe.opacity<=1,
108
+ 'invalid_payload', 'Invalid canvas theme color recipe')
109
+ }
110
+ }
101
111
  if (hover !== undefined) validateCanvasHover(hover)
102
112
  }
103
113
  }