@voltius/plugin-types 0.18.0 → 0.19.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.
Files changed (3) hide show
  1. package/README.md +10 -0
  2. package/index.d.ts +130 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -25,3 +25,13 @@ included automatically; you do not need to reference it.
25
25
  Generated from `src/plugins/api.ts` — see
26
26
  [developing plugins](https://docs.voltius.app/plugins/developing) and the
27
27
  [template repo](https://github.com/VoltiusApp/voltius-plugin-template).
28
+
29
+ ## Team connections
30
+
31
+ `connections:read` returns team-vault connections alongside personal ones. A team-owned entry is
32
+ marked `team: true` and can be read, listed, and used to open a session exactly like a personal
33
+ connection.
34
+
35
+ `connections.update` and `connections.delete` **reject** a team-owned connection — team objects are
36
+ managed through the team vault, not the plugin API. Check `team` before offering an edit affordance,
37
+ and expect the rejection if you do not.
package/index.d.ts CHANGED
@@ -94,7 +94,21 @@ export type PluginAuditAction =
94
94
  | "agent.session_opened"
95
95
  | "agent.session_closed"
96
96
  | "agent.command_run"
97
- | "agent.action_denied";
97
+ | "agent.action_denied"
98
+ | "agent.file_created"
99
+ | "agent.file_written"
100
+ | "agent.file_renamed"
101
+ | "agent.file_deleted"
102
+ | "agent.file_transferred"
103
+ | "agent.object_created"
104
+ | "agent.object_updated"
105
+ | "agent.object_deleted"
106
+ // A tool a plugin contributed through api.mcp, called by an external MCP
107
+ // client. Distinct from agent.command_run so the trail stays filterable by
108
+ // what actually reached the host. Must be on the server's CLIENT_WHITELIST
109
+ // before any client that emits it ships, or the team rows are 400ed and
110
+ // silently dropped.
111
+ | "agent.plugin_tool_run";
98
112
 
99
113
 
100
114
 
@@ -117,6 +131,12 @@ export interface PluginConnection {
117
131
  icon?: string;
118
132
  distro?: string;
119
133
  serial_port?: string;
134
+ /**
135
+ * True when this connection is owned by a team vault rather than the user's
136
+ * personal store. `update` and `delete` reject one; a `vault_id` does NOT
137
+ * imply it, since a personal connection can live in a local vault too.
138
+ */
139
+ team?: boolean;
120
140
  }
121
141
 
122
142
  export interface PluginConnectionInput {
@@ -248,6 +268,50 @@ export interface PluginSession {
248
268
  localShell?: string;
249
269
  }
250
270
 
271
+ // ─── Files (SFTP / FTP / local) ────────────────────────────────────────────
272
+
273
+ /**
274
+ * What a file operation acts on: a saved connection's id, or the literal
275
+ * "local" for this machine. SFTP and FTP connections are both addressed this
276
+ * way — the host opens whichever transport the connection declares.
277
+ */
278
+ export type FileTarget = string;
279
+
280
+ export interface FileEndpoint {
281
+ target: FileTarget;
282
+ path: string;
283
+ }
284
+
285
+ export interface PluginFile {
286
+ name: string;
287
+ path: string;
288
+ size: number;
289
+ isDir: boolean;
290
+ isSymlink: boolean;
291
+ /** Unix seconds, or null when the transport does not report one. */
292
+ modified: number | null;
293
+ }
294
+
295
+ /**
296
+ * Remote and local file access. Reads are gated on "sftp:read", everything that
297
+ * writes, moves or removes on "sftp:write".
298
+ */
299
+ export interface SftpAPI {
300
+ list(target: FileTarget, path: string): Promise<PluginFile[]>;
301
+ /** Null when the path does not exist — not an error. */
302
+ stat(target: FileTarget, path: string): Promise<PluginFile | null>;
303
+ readText(target: FileTarget, path: string, maxBytes?: number): Promise<string>;
304
+ writeText(target: FileTarget, path: string, content: string): Promise<void>;
305
+ mkdir(target: FileTarget, path: string): Promise<void>;
306
+ rename(target: FileTarget, from: string, to: string): Promise<void>;
307
+ delete(target: FileTarget, path: string): Promise<void>;
308
+ /** Copy one path between any two targets, in any direction, files or
309
+ * directories. Host→host streams directly and never lands on this machine. */
310
+ transfer(src: FileEndpoint, dst: FileEndpoint): Promise<void>;
311
+ /** Release the handle held for `target`, if any. */
312
+ disconnect(target: FileTarget): Promise<void>;
313
+ }
314
+
251
315
  export type PluginTheme = AppTheme;
252
316
 
253
317
  // ─── Notification types ────────────────────────────────────────────────────
@@ -480,6 +544,51 @@ export interface DockerAPI {
480
544
  };
481
545
  }
482
546
 
547
+ /** A local audit row, projected. Drops the internal id, actor id, team/vault
548
+ * ids and IP — none of which a plugin or an external client has any use for. */
549
+ export interface PluginAuditRow {
550
+ action: string;
551
+ actor_name: string;
552
+ source: "server" | "client";
553
+ target_type: string | null;
554
+ target_id: string | null;
555
+ target_name: string | null;
556
+ metadata: Record<string, unknown> | null;
557
+ created_at: string;
558
+ }
559
+
560
+ export interface PluginAuditQuery {
561
+ actions?: string[];
562
+ /** ISO 8601. */
563
+ from?: string;
564
+ to?: string;
565
+ page?: number;
566
+ /** Clamped to 100. */
567
+ perPage?: number;
568
+ }
569
+
570
+ /** One MCP tool a plugin contributes. The host namespaces the name, validates
571
+ * everything here at registration, and audits calls unless `mutating` is false. */
572
+ export interface McpToolContribution {
573
+ /** Unqualified, matching /^[a-z0-9_]+$/. The host adds the namespace prefix. */
574
+ name: string;
575
+ description: string;
576
+ /** Plain JSON Schema. Converted host-side with the host's own zod, so no zod
577
+ * instance crosses the bundle boundary. */
578
+ inputSchema: Record<string, unknown>;
579
+ /** Whether a call changes state. Defaults to true: forgetting the field
580
+ * audits rather than silently not auditing. */
581
+ mutating?: boolean;
582
+ execute(args: Record<string, unknown>): Promise<unknown>;
583
+ }
584
+
585
+ /** Contribute tools to the Voltius MCP server. GATED (mcp:contribute). */
586
+ export interface McpAPI {
587
+ /** Register this plugin's whole tool set. Throws on any invalid tool and
588
+ * registers none of them. Returns a teardown that removes the whole set. */
589
+ registerTools(tools: McpToolContribution[]): () => void;
590
+ }
591
+
483
592
  // ─── API principale ────────────────────────────────────────────────────────
484
593
 
485
594
  export interface PluginAPI {
@@ -504,10 +613,17 @@ export interface PluginAPI {
504
613
 
505
614
  // Connections (requires connections:*)
506
615
  connections: {
616
+ /**
617
+ * Every connection the user can reach, personal and team-vault alike. A
618
+ * team-owned entry carries `team: true`; it is addressable exactly like a
619
+ * personal connection for reads and for opening a session.
620
+ */
507
621
  list(): Promise<PluginConnection[]>;
508
622
  get(id: string): Promise<PluginConnection | null>;
509
623
  create(data: PluginConnectionInput): Promise<PluginConnection>;
624
+ /** Rejects a team-vault connection: team objects are not editable through this API. */
510
625
  update(id: string, data: Partial<PluginConnectionInput>): Promise<void>;
626
+ /** Rejects a team-vault connection: team objects are not deletable through this API. */
511
627
  delete(id: string): Promise<void>;
512
628
  bulkImport(items: PluginConnectionInput[]): Promise<PluginConnection[]>;
513
629
  subscribe(cb: (connections: PluginConnection[]) => void): () => void;
@@ -520,7 +636,8 @@ export interface PluginAPI {
520
636
  delete(key: string): Promise<void>;
521
637
  };
522
638
 
523
- // Audit — record what this plugin did (requires "audit")
639
+ // Audit — record what this plugin did (requires "audit"); read this device's
640
+ // log (requires the gated "audit:read")
524
641
  audit: {
525
642
  /**
526
643
  * Record an action against the connection it targets. A team-vault
@@ -536,6 +653,9 @@ export interface PluginAPI {
536
653
  metadata?: Record<string, unknown>,
537
654
  localMetadata?: Record<string, unknown>,
538
655
  ): void;
656
+ /** This device's local rows only. Team-vault rows are server-backed and
657
+ * are not returned here. */
658
+ query(filters: PluginAuditQuery): Promise<{ logs: PluginAuditRow[]; total: number }>;
539
659
  };
540
660
 
541
661
  // Themes (requires "themes")
@@ -685,6 +805,10 @@ export interface PluginAPI {
685
805
 
686
806
  // Proxmox VE LXC management — GATED, split
687
807
  // proxmox:read (list/snapshots.list) / proxmox:manage (everything else).
808
+ // Files over SFTP/FTP and the local disk — GATED, split
809
+ // sftp:read (list/stat/readText) / sftp:write (everything that mutates).
810
+ sftp: SftpAPI;
811
+
688
812
  proxmox: ProxmoxAPI;
689
813
 
690
814
  // Docker container/image/volume/network/stack management — GATED, split
@@ -742,6 +866,10 @@ export interface PluginAPI {
742
866
  /** Get another plugin's exposed API. Returns null if not loaded or not exposed. */
743
867
  getApi(pluginId: string): unknown | null;
744
868
  };
869
+
870
+ // MCP tool contributions — GATED (mcp:contribute). Tools run with THIS
871
+ // plugin's permissions, called by whatever external agent the user connected.
872
+ mcp: McpAPI;
745
873
  }
746
874
 
747
875
  export type PluginRegisterFn = (api: PluginAPI) => (() => void) | void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltius/plugin-types",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "TypeScript definitions for the Voltius plugin API",
5
5
  "types": "index.d.ts",
6
6
  "files": [