@alisio/sdk 0.1.0-alpha.17 → 0.1.0-alpha.18

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.d.ts CHANGED
@@ -103,7 +103,154 @@ export type UiBlock = {
103
103
  kind: "progress";
104
104
  title?: string;
105
105
  steps: ProgressStep[];
106
+ }
107
+ /** A published, downloadable artifact (`ToolContext.artifacts`). Text surfaces show one line. */
108
+ | {
109
+ kind: "artifact";
110
+ artifact: ArtifactRef;
106
111
  };
112
+ /** Kind of a published artifact; decides the icon, the label and the renderer. */
113
+ export type ArtifactKind = "dashboard" | "document" | "spreadsheet" | "image" | "data" | "code" | "archive" | "file";
114
+ /** Public reference to a published artifact. Never carries absolute paths. */
115
+ export interface ArtifactRef {
116
+ /** `art_<ULID>`. */
117
+ id: string;
118
+ /** Root session that owns the artifact. */
119
+ sessionId: string;
120
+ title: string;
121
+ /** Download name, e.g. `report.md`, or `site.zip` for a multi-file artifact. */
122
+ fileName: string;
123
+ kind: ArtifactKind;
124
+ mimeType: string;
125
+ bytes: number;
126
+ /** More than 1 for multi-file dashboards. */
127
+ fileCount: number;
128
+ /** Decided by the host from the artifact kind and size. */
129
+ previewable: boolean;
130
+ createdAt: number;
131
+ /** Published from a failed execution (`publishOnError`). */
132
+ partial?: boolean;
133
+ status: "ready" | "deleted" | "expired";
134
+ }
135
+ /** Input of `ArtifactPublisher.publish`: files already written by the caller. */
136
+ export interface ArtifactPublishInput {
137
+ /** Absolute path of a file or a directory owned by the caller. */
138
+ source: string;
139
+ title?: string;
140
+ /** Entry file for a directory; defaults to `index.html` when present. */
141
+ entry?: string;
142
+ }
143
+ /** Publishes caller-owned files as downloadable artifacts of the current session. */
144
+ export interface ArtifactPublisher {
145
+ /** Validates, copies and registers; throws with a user-readable message on rejection. */
146
+ publish(input: ArtifactPublishInput): Promise<ArtifactRef>;
147
+ /** Creates a single-file artifact from text the tool already holds. */
148
+ publishText(input: {
149
+ fileName: string;
150
+ title?: string;
151
+ text: string;
152
+ }): Promise<ArtifactRef>;
153
+ }
154
+ /** Finer-grained permissions inside an effect (closed union; extended additively). */
155
+ export type AnalysisCapability = "analysis.run" | "analysis.install";
156
+ /**
157
+ * What an `analysis.install` approval shows (phase 4): the optional Python packages that would be
158
+ * installed, an estimate of the download and that it needs the network. Always asks, only `once`.
159
+ */
160
+ export interface InstallPreview {
161
+ extras: "analysis" | "science";
162
+ /** Top-level packages, e.g. `pandas`, `numpy`. */
163
+ packages: string[];
164
+ /** Pinned distributions in the lockfile (the packages plus their dependencies). */
165
+ packageCount: number;
166
+ /** Rough download size (wheels only); an estimate, not a measurement. */
167
+ estimatedBytes: number;
168
+ network: true;
169
+ }
170
+ /** What a tool asks the host to approve before installing packages (capability `analysis.install`). */
171
+ export type InstallApprover = (request: InstallPreview) => Promise<"once" | "deny">;
172
+ /** A persisted capability decision as exposed by the web API. */
173
+ export interface CapabilityGrantWire {
174
+ id: string;
175
+ capability: AnalysisCapability;
176
+ sessionId: string;
177
+ scope: "once" | "session";
178
+ decision: "allow" | "deny";
179
+ source: "tui" | "web" | "flag" | "headless-grant";
180
+ createdAt: number;
181
+ revokedAt?: number;
182
+ }
183
+ /** Tabular formats the data tools ingest into one SQLite file per dataset. */
184
+ export type DatasetFormat = "csv" | "tsv" | "json" | "jsonl" | "xlsx";
185
+ /** A dataset (a CSV/TSV/JSON/JSONL/XLSX file ingested into SQLite). Never carries paths. */
186
+ export interface DatasetRef {
187
+ /** `ds_<ULID>`. */
188
+ id: string;
189
+ /** Original file name. */
190
+ name: string;
191
+ format: DatasetFormat;
192
+ bytes: number;
193
+ sha256: string;
194
+ sheets: Array<{
195
+ name: string;
196
+ table: string;
197
+ rows: number;
198
+ columns: number;
199
+ }>;
200
+ }
201
+ /** Column of a dataset table with the statistics computed at ingestion. */
202
+ export interface DatasetColumnWire {
203
+ name: string;
204
+ /** Original header text. */
205
+ label: string;
206
+ /** A hint (`integer`, `real`, `date`, `boolean`, `text`); values are stored without conversion. */
207
+ type: string;
208
+ nulls: number;
209
+ distinct: number;
210
+ distinctExact: boolean;
211
+ min?: string;
212
+ max?: string;
213
+ mean?: number;
214
+ textFallbacks: number;
215
+ top: Array<{
216
+ value: string;
217
+ count: number;
218
+ }>;
219
+ }
220
+ /** `GET /api/datasets/:did`: the dataset with the schema and statistics of every sheet. */
221
+ export interface DatasetDetailWire extends DatasetRef {
222
+ ingestVersion: number;
223
+ encoding?: string;
224
+ delimiter?: string;
225
+ sheetDetails: Array<{
226
+ name: string;
227
+ table: string;
228
+ rows: number;
229
+ columns: DatasetColumnWire[];
230
+ }>;
231
+ /** Sorting and filtering are disabled above this many rows (`analysis.data.maxInteractiveRows`). */
232
+ maxInteractiveRows: number;
233
+ }
234
+ /** `GET /api/datasets/:did/rows`: one page of a sheet (keyset-paginated). */
235
+ export interface DatasetRowsPage {
236
+ columns: Array<{
237
+ name: string;
238
+ label: string;
239
+ type: string;
240
+ }>;
241
+ /** Cell values as stored: numbers stay numbers, everything else is text, empty cells are null. */
242
+ rows: Array<Array<string | number | null>>;
243
+ /** 1-based position of the first row in the (unfiltered, unsorted) sheet, per row. */
244
+ rowids: number[];
245
+ /** Opaque cursor for the next page; absent on the last page. */
246
+ next?: string;
247
+ /** Rows in the sheet. */
248
+ total: number;
249
+ /** Rows matching the filter (first page only). */
250
+ matched?: number;
251
+ /** Sorting and filtering were ignored because the sheet exceeds `maxInteractiveRows`. */
252
+ interactive: boolean;
253
+ }
107
254
  /** One case of a `{ kind: "test-results" }` UI block. */
108
255
  export interface TestCaseResult {
109
256
  name: string;
@@ -123,7 +270,7 @@ export interface ProgressStep {
123
270
  * validators). Surfaces must still render an unknown kind as text: blocks persisted by a newer
124
271
  * Alisio can be replayed by an older one.
125
272
  */
126
- export declare const UI_BLOCK_KINDS: readonly ["table", "key-value", "tree", "code", "markdown", "diff", "terminal", "mermaid", "math", "json", "test-results", "progress"];
273
+ export declare const UI_BLOCK_KINDS: readonly ["table", "key-value", "tree", "code", "markdown", "diff", "terminal", "mermaid", "math", "json", "test-results", "progress", "artifact"];
127
274
  export interface ToolResult {
128
275
  content: Array<{
129
276
  type: "text";
@@ -167,6 +314,8 @@ export type Message =
167
314
  summary?: boolean;
168
315
  display?: string;
169
316
  attachments?: Attachment[];
317
+ /** Datasets attached to this prompt (UI chips); the model sees their text summary in `text`. */
318
+ datasets?: DatasetRef[];
170
319
  } | {
171
320
  role: "assistant";
172
321
  text: string;
@@ -324,6 +473,17 @@ export interface ToolContext {
324
473
  * do not inject this fall back to the workspace-only `safePath` policy.
325
474
  */
326
475
  resolvePath?: (path: string) => Promise<string>;
476
+ /** Run and tool call that issued this execution, when run by the agent loop. */
477
+ runId?: string;
478
+ callId?: string;
479
+ /** Present when the host has an artifact store for this session (built-in tools only in v1). */
480
+ artifacts?: ArtifactPublisher;
481
+ /**
482
+ * Asks the user to approve installing the optional Python packages (capability
483
+ * `analysis.install`; built-in tools only). Resolves `deny` where nobody can be asked
484
+ * (headless, `--read-only`), because no flag grants an installation.
485
+ */
486
+ approveInstall?: InstallApprover;
327
487
  }
328
488
  export interface ToolDefinition {
329
489
  name: string;
@@ -334,6 +494,11 @@ export interface ToolDefinition {
334
494
  /** May run concurrently with other read/concurrent calls of the same turn (e.g. delegation). */
335
495
  concurrent?: boolean;
336
496
  paths?: (input: Record<string, unknown>) => string[];
497
+ /**
498
+ * Finer-grained permission inside `effect`: a broad grant of `effect` covers it, a grant of the
499
+ * capability never widens `effect`. Honored for built-in tools only (ignored for plugins in v1).
500
+ */
501
+ capability?: AnalysisCapability;
337
502
  execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolResult>;
338
503
  }
339
504
  /**
@@ -411,12 +576,29 @@ export interface RunEventDataMap {
411
576
  name: string;
412
577
  effect: "write" | "process" | "external";
413
578
  label?: string;
579
+ /** The approval is for this capability (not the whole effect). */
580
+ capability?: AnalysisCapability;
581
+ /** `analysis.install` approvals: the packages, the size estimate and the network need. */
582
+ install?: InstallPreview;
414
583
  };
415
584
  approval_resolved: {
416
585
  id: string;
417
586
  name: string;
418
587
  effect: "write" | "process" | "external";
419
588
  decision: "once" | "session" | "deny";
589
+ capability?: AnalysisCapability;
590
+ /** A `session` capability decision was stored and survives restarts. */
591
+ persisted?: boolean;
592
+ };
593
+ /**
594
+ * A tool published an artifact. `path` is the absolute local path of the file (or the entry of a
595
+ * multi-file artifact) for local consumers (TUI, JSONL); web clients ignore it.
596
+ */
597
+ artifact_published: {
598
+ artifact: ArtifactRef;
599
+ path: string;
600
+ callId?: string;
601
+ executionId?: string;
420
602
  };
421
603
  run_completed: {
422
604
  tokens: number;
@@ -1041,6 +1223,14 @@ export interface PendingApproval {
1041
1223
  /** Pretty-printed tool input, truncated to 4 KB. */
1042
1224
  input: string;
1043
1225
  expiresAt?: number;
1226
+ /** The approval is for this capability (for example running Python), not the whole effect. */
1227
+ capability?: AnalysisCapability;
1228
+ /** A short preview for capability approvals (the first 40 lines of the script). */
1229
+ preview?: string;
1230
+ /** Capability approvals: `managed` (not sandboxed) or `oci` (container). */
1231
+ runtime?: "managed" | "oci";
1232
+ /** `analysis.install` approvals: only `once` and `deny` are offered. */
1233
+ install?: InstallPreview;
1044
1234
  }
1045
1235
  /** A plugin UI request (`ui.select` / `ui.askQuestions`) waiting for a web client. */
1046
1236
  export interface PendingInteraction {
@@ -1153,6 +1343,24 @@ export type ServerFrame = {
1153
1343
  t: "resync";
1154
1344
  sessionId?: string;
1155
1345
  reason: "overflow" | "gap" | "server_restart";
1346
+ }
1347
+ /** A persisted capability grant of this root session was added or revoked. */
1348
+ | {
1349
+ t: "capabilities_changed";
1350
+ sessionId: string;
1351
+ }
1352
+ /** A dataset uploaded from the web finished ingesting (root session). */
1353
+ | {
1354
+ t: "dataset_ready";
1355
+ sessionId: string;
1356
+ dataset: DatasetRef;
1357
+ }
1358
+ /** A dataset upload could not be ingested. */
1359
+ | {
1360
+ t: "dataset_failed";
1361
+ sessionId: string;
1362
+ name: string;
1363
+ error: string;
1156
1364
  };
1157
1365
  export type ApiErrorCode = "unauthorized" | "forbidden_origin" | "forbidden_host" | "validation_failed" | "not_found" | "unknown_command" | "session_busy" | "session_locked" | "workspace_limit"
1158
1366
  /** A known workspace whose folder was deleted, moved or is no longer accessible (404). */
@@ -1168,7 +1376,19 @@ export type ApiErrorCode = "unauthorized" | "forbidden_origin" | "forbidden_host
1168
1376
  /** The server user may not read that directory (403). */
1169
1377
  | "permission_denied"
1170
1378
  /** The request was cancelled before it finished, e.g. a `/btw` side question (409). */
1171
- | "cancelled" | "internal";
1379
+ | "cancelled"
1380
+ /** The artifact does not exist or belongs to another session (404). */
1381
+ | "artifact_not_found"
1382
+ /** The artifact exceeds a size limit for this operation (413). */
1383
+ | "artifact_too_large"
1384
+ /** No usable Python runtime (503). */
1385
+ | "runtime_unavailable"
1386
+ /** The file is not a supported dataset, or needs a runtime that is missing (415/503 body code). */
1387
+ | "dataset_unsupported"
1388
+ /** A data query was rejected by the read-only guard (400). */
1389
+ | "query_rejected"
1390
+ /** A data query exceeded `analysis.data.queryTimeoutMs` (408). */
1391
+ | "query_timeout" | "internal";
1172
1392
  /** `GET /api/health` (the only unauthenticated API route). */
1173
1393
  export interface HealthInfo {
1174
1394
  name: "alisio";
@@ -1405,6 +1625,55 @@ export interface McpServerWire {
1405
1625
  };
1406
1626
  diagnostic?: string;
1407
1627
  }
1628
+ /**
1629
+ * `GET /api/analysis`: the state of the data-analysis runtime for Settings (read only). Never
1630
+ * carries a script or a repository path; interpreter paths are the user's own.
1631
+ */
1632
+ export interface AnalysisStatus {
1633
+ /** `analysis.enabled` and not `--read-only`: python_run is registered. */
1634
+ enabled: boolean;
1635
+ readOnly: boolean;
1636
+ mode: "managed" | "oci";
1637
+ /** The discovered (or `--python`) interpreter and the extras environment. */
1638
+ python: {
1639
+ found: true;
1640
+ path: string;
1641
+ version: string;
1642
+ source: string;
1643
+ extras: string[];
1644
+ runtimeVersion?: string;
1645
+ } | {
1646
+ found: false;
1647
+ reason: string;
1648
+ /** Installation guidance for this system (commands are shown, never run). */
1649
+ hints: {
1650
+ system: string;
1651
+ heading?: string;
1652
+ primary: string;
1653
+ alternatives: string[];
1654
+ notes: string[];
1655
+ };
1656
+ };
1657
+ /** Container settings; `available` is probed only when the mode is `oci` or an image is set. */
1658
+ oci: {
1659
+ engine: "docker" | "podman";
1660
+ image?: string;
1661
+ memoryMb: number;
1662
+ cpus: number;
1663
+ available?: boolean;
1664
+ version?: string;
1665
+ reason?: string;
1666
+ };
1667
+ limits: {
1668
+ timeoutMs: number;
1669
+ };
1670
+ retention: {
1671
+ jobsDays: number;
1672
+ intermediateDays: number;
1673
+ artifactsDays: number;
1674
+ lastSweep?: number;
1675
+ };
1676
+ }
1408
1677
  /** `GET /api/mcp`: the workspace's MCP runtime permission and servers. */
1409
1678
  export interface McpOverview {
1410
1679
  permission: "granted" | "not-granted" | "read-only";
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ export const UI_BLOCK_KINDS = [
16
16
  "json",
17
17
  "test-results",
18
18
  "progress",
19
+ "artifact",
19
20
  ];
20
21
  export const EPHEMERAL_RUN_EVENT_TYPES = [
21
22
  "text_delta",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alisio/sdk",
3
- "version": "0.1.0-alpha.17",
3
+ "version": "0.1.0-alpha.18",
4
4
  "description": "Typed plugin SDK for Alisio: the stable contract for tools, commands, context, compaction and session hooks, model completions and storage. Types only plus tiny helpers; zero runtime dependencies.",
5
5
  "author": "Gustavo Gutiérrez",
6
6
  "license": "MIT",