@oddington/sdk 0.1.36 → 0.1.38

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
@@ -6,11 +6,12 @@ Data and Files APIs work in browsers. Installing the package grants no authority
6
6
 
7
7
  Hosted Data and shared Files reach OS directly through `/api/data` and `/api/files`.
8
8
  Inbox owns workspace-hosted `/api/inbox/check`, `/api/inbox/publish`,
9
- `/api/inbox/resolve` and `/api/inbox/files`. Request-key recovery and captured
9
+ `/api/inbox/resolve`. Request-key recovery and captured
10
10
  publication validation are internal behavior of these operations. Retrying the
11
11
  same key and content returns the original result; changed content conflicts.
12
- Existing Inbox-retained files remain separate from shared Files, with their
13
- original identities, bytes and audience. The SDK exposes no raw-credential API.
12
+ Inbox File previews and downloads use package-root `files.read(fileId)` with
13
+ current workspace access. Item visibility does not grant File access. The SDK
14
+ exposes no raw-credential API.
14
15
 
15
16
  Hosted apps use `inbox.questions.list({ routines })` for `AnswerableQuestion[]`.
16
17
  Derive `routines` from the existing app declaration with
@@ -65,7 +66,7 @@ Each step runs at most once and returns `{ summary, data }`. Unknown or repeated
65
66
  steps fail the Run even if routine code catches the error; unreached steps are
66
67
  skipped. Omitted input normalizes to `{}`. A top-level schema can supply a validated
67
68
  immutable default with `.default(value)`, such as
68
- `schema.object({ files: schema.array(file(), { maxItems: 32 }) }).default({ files: [] })`.
69
+ `schema.object({ files: schema.array(file()) }).default({ files: [] })`.
69
70
  Nested defaults are unsupported and rejected. Omitted steps permit no step call;
70
71
  omitted result permits no returned value. `file()` declares a complete OS File descriptor.
71
72
  Its optional `storage` selects local or remote placement and its optional `path`
@@ -79,6 +80,12 @@ declared `review` handler crosses the Inbox publication seam as `review`; Inbox
79
80
  retains the canonical `invoice-import` routine identity separately, without
80
81
  deploying or executing that handler.
81
82
 
83
+ Microsoft Connection configuration has a separate, optional `access` description.
84
+ It preserves supplied strings, including existing `read` and `read-write` labels,
85
+ and does not grant or restrict Microsoft permissions. Management results omit
86
+ this metadata when absent. Setup and safe inspection are documented in the
87
+ [CLI Connections guide](../../apps/cli/README.md#connections).
88
+
82
89
  With `access: { ai: true }`, `os.ai.generateText` returns non-empty `{ text }`.
83
90
  `os.ai.generateObject` returns `{ object }` validated against the requested
84
91
  `schema`, with its inferred type. An invalid answer throws `RoutineAIError`
@@ -95,8 +102,10 @@ AI calls drain before completion. The host retains authority, isolation,
95
102
  cancellation and byte limits. Local and remote Runs use the same API.
96
103
 
97
104
  The bounded grammar supports closed objects with required properties, arrays with
98
- an explicit `maxItems` from 1 to 64, booleans, strings (at most 4096 code points),
105
+ an optional positive safe-integer `maxItems` business bound, booleans, strings (at most 4096 code points),
99
106
  finite numbers and safe integers with optional inclusive bounds, and Files.
107
+ Omitting `maxItems` imposes no item-count ceiling; the complete serialized input
108
+ still shares the Run's byte bound, including every File descriptor and other field.
100
109
  Definitions allow at most 64 steps, 64 total object properties across their schemas,
101
110
  and eight schema levels. Input, each step input, each summary, each detail value,
102
111
  and the result accept at most 256 KiB of UTF-8 serialized JSON, without truncation.
@@ -246,7 +255,7 @@ Local Data selects from the Host's exact published index; a warm selection
246
255
  neither initiates nor waits for renewal or synchronous hosted authority checks.
247
256
  Local Files returns `unsupported_context` after checking context. Neither path
248
257
  falls back to hosted services. Local app routines use the same local execution
249
- and explicit publication lifecycle as the CLI.
258
+ and live capability calls as the CLI.
250
259
 
251
260
  Apps can assess a declared routine without starting it:
252
261
 
@@ -262,19 +271,17 @@ const detail = await run.step('read'); // Inferred summary and data for this new
262
271
  const recent = await app.routines.receipts.runs.list();
263
272
  const saved = await app.routines.receipts.runs.get(recent[0].id);
264
273
  console.log(await saved.current());
265
- // await saved.publish(); // Only in response to an explicit publication action.
266
274
  ```
267
275
 
268
276
  The fixed build generates types from each routine definition; no app-authored
269
277
  contract map is needed. Descriptions combine safe structure with live readiness
270
278
  and connection availability. Starts validate the current definition and input;
271
- retained reads and publication recheck complete saved member/source/capability
272
- scope. No installation is needed. Bindings accept no endpoint, credential,
279
+ retained local reads check the established session and saved Run ownership. No installation is needed. Bindings accept no endpoint, credential,
273
280
  command, path or configuration selector. A local app uses its live Local Host;
274
281
  a hosted app uses its existing member session and workspace context to reach
275
282
  the current remote Run owner through the same bindings. Operations reject with
276
283
  `AppRoutineError.reason`: `authority_unavailable`, `execution_unavailable`, or
277
- `invalid_input`. Starts and publications are not automatically retried. A
284
+ `invalid_input`. Starts are not automatically retried. A
278
285
  disconnected watch ends and requires `current()`. History returns at most 20
279
286
  summaries without deleting older Runs. Each JSON value is bounded to 256 KiB.
280
287
  Transport envelopes allow 17 MiB per summary, 514 KiB per detail and 20 summaries
@@ -396,33 +403,28 @@ await files.enrich({ file: report.id, name: 'read.md', content: revisedMarkdown,
396
403
  await files.upload(report.id); // Move a local File and every retained enrichment to remote storage.
397
404
  ```
398
405
 
399
- Hosted Files retains remote originals and caller-produced named enrichments;
400
- `storage: 'local'` requires a managed CLI parent. Configure that parent with
401
- `OS_FILES_ROOT` pointing to an empty or already OS-managed dedicated
402
- directory outside tracked Git content. `OS_FILES_DEFAULT=local|remote`
403
- selects its default; without it, remote remains the default. Per-File `storage`
404
- overrides it. The root stays private to the parent. Local creation without a
405
- configured root fails with `unsupported_context`. Files have one durable home;
406
- `both` is invalid. Local retention establishes no hosted registration.
407
- Fresh runs recover the same creator's File by its request key, and verify
408
- retained bytes before returning a descriptor or content. A dead parent fails
409
- closed. `os routine run <name>` stages newly created Files locally for that Run,
410
- including local-placement Files, and defers promotion, enrichments and explicit
411
- uploads until `os routine publish <run>`. Legacy Inbox file capture remains
412
- additive. Existing hosted Files are read-only during local execution.
413
- `upload(id)` preserves the File descriptor, creator access and existing Source
414
- references. Local bytes remain authoritative until all remote objects verify;
415
- retrying a completed upload returns the same File. Later reads and enrichments
416
- follow remote storage; any remaining managed local bytes are disposable cache.
417
- An unreferenced local File is disclosed remotely only when explicitly uploaded
418
- or successfully published as a Source. An authorized hosted caller receives
419
- non-retryable `local_only` (409) until upload succeeds; unrelated callers receive
420
- `access_denied`.
406
+ Hosted Files retains remote originals and caller-produced named enrichments.
407
+ A managed local CLI parent stores local Files beneath the signed-in active
408
+ workspace's `~/.os/<workspace>/files` root; callers cannot configure another
409
+ root. Local Runs default new Files to local storage, hosted Runs to remote.
410
+ An existing local or remote File keeps its placement. Every completed File has
411
+ one workspace registry row, including local Files whose bytes stay on this
412
+ device. Request-key replay and reusable enrichments preserve the same identity
413
+ across member calls, Runs and restarts.
414
+
415
+ Explicit remote creation, upload and enrichment complete during their calls.
416
+ `upload(id)` verifies the original and every enrichment before changing the same
417
+ File's placement; retrying a completed upload returns that File. Later reads
418
+ and enrichments follow its pinned remote store. A Source reference leaves a
419
+ local File local. Inbox publication uploads that same File before exposing the
420
+ Ask or Digest. Completed effects survive later Run failure. A runtime without
421
+ the local bytes reports `local_only` (409).
421
422
  Unnamed inputs require a safe `name`; streams also require declared `size`.
422
423
  Blob and byte-array declarations must match their intrinsic size. Originals are
423
- bounded to 16 MiB per object, metadata to 4 KiB, and descriptor/error bodies to 16 KiB.
424
- Operations share four concurrent slots and a 30-second deadline;
425
- transport retries at most once with the same prepared bytes and request key.
424
+ bounded to 5 GiB per original and 16 MiB per enrichment. Large originals stream
425
+ through bounded multipart transfers; local writes and reads use bounded disk
426
+ buffers. Operations share four concurrent slots and idle/request deadlines;
427
+ transport retries preserve the same bytes and request key.
426
428
  Omitting a key generates one for that invocation. Supply a stable key to recover
427
429
  across processes or fresh routine runs. Caller inputs remain owned by the caller.
428
430
  Each request resolves current authority; hosted routine Files calls use the
@@ -435,24 +437,10 @@ versus received size. Streaming rejection marks partial received counts with
435
437
  failure evidence without raw names, keys, file content or provider text. Older
436
438
  errors without `detail` remain valid. Reads return the successful Web
437
439
  Response without consuming its body. Local transfer is bounded and buffered
438
- before constructing that Response. Creation grants private creator access;
439
- workspace membership alone never grants another creator's File.
440
-
441
- `await files.delete(fileId)` removes an unreferenced File's original and all
442
- retained enrichments under its current member or installed-routine creator.
443
- It returns `void` only after physical cleanup and durable completion; a completed
444
- retry succeeds. Independent retention returns `conflict` without changing the
445
- File. `access_denied` and `integrity` remain terminal; `unavailable` and
446
- `capacity` are retryable. Pending deletion denies reads, writes, new uses and
447
- creation-key replay while the same current creator retries cleanup. Deletion
448
- uses the authenticated parent for managed local Files and uploaded caches.
449
- R2 cleanup verifies the registered immutable key and native revision, removes
450
- only that object and confirms absence. Each physical writer owns a distinct
451
- candidate key, so a delayed writer cannot recreate the deleted representation.
452
- Pending admission is never success.
453
- When a completion reply is lost, retry `files.delete` with the same File ID and
454
- current creator authority. Keep stable creation keys separate from deletion
455
- recovery: a completed deleted key is denied and cannot recreate the File.
440
+ before constructing that Response. Current workspace members can use every File in that workspace. A
441
+ routine's `files: "read"` permits get/read; `files: "read-write"` also permits
442
+ create/enrich/upload. References in Sources, Runs and Inbox items grant no
443
+ additional access. Files has no public delete operation.
456
444
 
457
445
  `enrich` accepts a string encoded as UTF-8 or exact `Uint8Array` bytes, a safe
458
446
  flat filename, and an optional MIME hint. OS verifies text/Markdown/JSON or
@@ -504,6 +492,44 @@ revision and URL facts. Distinct objects and custom provider values remain.
504
492
  Helpers need no initialization and perform no I/O, choose no ref, and add no
505
493
  changes. File retention and Data validation/publication remain explicit.
506
494
 
495
+ Microsoft helpers are also exported at the package root, with the corresponding
496
+ `OutlookSourceLocation` and `SharePointSourceLocation` types:
497
+
498
+ ```ts
499
+ const messageLocation = source.location.outlook({
500
+ connection: 'outlook/invoices', message: message.id, url: message.webLink,
501
+ // attachment: attachment.id, // Include for attachment bytes; omit for message MIME.
502
+ });
503
+ const itemLocation = source.location.sharepoint({
504
+ connection: 'sharepoint/operations', site: siteId, drive: driveId, item: item.id,
505
+ version: version.id, path: lastKnownPath, url: item.webUrl,
506
+ });
507
+ ```
508
+
509
+ Construct these only after successful provider reads establish the coordinates
510
+ for the retained bytes, and save them alongside `source.location.os(file)` using
511
+ ordinary Data publication. Request `Prefer: IdType="ImmutableId"` consistently
512
+ when obtaining Outlook message and attachment IDs. These IDs are case-sensitive
513
+ and survive folder moves within the same mailbox, but not archive-mailbox moves
514
+ or export/reimport. Subjects, filenames and `internetMessageId` are not substitutes.
515
+ Omit `attachment` for an exact message MIME File; supply it for an attachment File.
516
+
517
+ For SharePoint, use the saved Graph site ID, the document library's drive ID and
518
+ the file's driveItem ID. Optional `version` is an actual driveItemVersion ID
519
+ established for those bytes, never an eTag or a guessed version. Omit it when no
520
+ such version is established. Names, paths and URLs do not establish identity.
521
+ Optional `path` is last-known context; `url` is the ordinary HTTPS message web
522
+ link or SharePoint webUrl. Never retain temporary download, upload-session or
523
+ copy-monitor URLs, authorization or credentials in Locations.
524
+
525
+ Outlook merge identity is connection/message/attachment, with whole messages
526
+ distinct from attachments. SharePoint identity is connection/site/drive/item/
527
+ version, with absent versions distinct from present ones. Matching observations
528
+ replace path/link context, including removing omitted context; distinct IDs,
529
+ versions and copies remain separate. Incomplete coordinates gain no inferred
530
+ identity. The retained OS File and hash own exact content; external edits do
531
+ not change an existing Source's bytes. These helpers perform no provider I/O.
532
+
507
533
  Read a named repository through the authenticated host context:
508
534
 
509
535
  ```ts
@@ -526,12 +552,11 @@ Binding is inert. Each operation resolves current workspace, endpoint and
526
552
  short-lived authority from the trusted app host or managed routine context.
527
553
  Customer calls cannot configure those values. Missing or expired context
528
554
  rejects; a named handle does not expand repository access. During
529
- `os routine run <name>`, the same calls use the matched checkout's committed
530
- version through a private parent transport. Dirty files are ignored. An OS
531
- cache outside the checkout reuses derived data; reads require no remote access
532
- or preparation storage. Later accepted record effects advance the run's view
533
- to their exact proposed version. Login, installed grants and provider authority
534
- retain their normal checks. A dead local parent fails without hosted fallback.
555
+ `os routine run <name>`, the same calls read current schema-governed Markdown
556
+ in the trusted checkout, including staged, modified and untracked Records. Each
557
+ operation reads the files as it begins. Later calls see completed writes and
558
+ external edits. Current local Data acquires no hosted binding or index. A dead
559
+ local parent fails without hosted fallback.
535
560
 
536
561
  Each graph selection sends one request and returns only selected canonical
537
562
  values, expanded forward links and exact opaque public versions. Cursors
@@ -662,15 +687,11 @@ projection, highlighting, embedding or historical version option.
662
687
 
663
688
  Matches have deterministic order and complete canonical Records. Empty matches
664
689
  succeed with the exact searched version. Members search latest published data;
665
- routines search their captured version, advancing only through their own
666
- publication. Hosted and app children publish immediately. During
667
- `os routine run <name>`, search uses the same committed local Index as select,
668
- ignores dirty/untracked files and advances only to that run's exact proposed
669
- version after its own Changes publication. Validation does not advance reads;
670
- another publisher does not move the captured view. Search Records can supply
671
- guards for subsequent Changes. Missing or incomplete search data, including
672
- retained versions without it, fails retryably with `unavailable` without an
673
- alternate read path.
690
+ hosted routines search their admitted hosted version. Local routines search the
691
+ schema-governed Markdown currently in the checkout, including staged, modified
692
+ and untracked Records. Each call refreshes its operation-local view; a later call
693
+ sees completed Changes writes and external edits. Search Records supply captured
694
+ versions for subsequent Changes. Explicit History keeps its hosted contract.
674
695
 
675
696
  `where` combines field conditions with AND. Alongside exact scalar/null equality
676
697
  and `$in`, declared one-valued `integer`, `number` and `date` fields accept
@@ -727,9 +748,10 @@ only after its exact index is ready. Later current reads discover that version.
727
748
  Deleted identities keep their captured versions; deletion creates no new Record
728
749
  version or tombstone. A Source deletion removes only that guarded Record, retaining
729
750
  its File, enrichments and existing durable uses.
730
- During `os routine run <name>`, publication retains the exact proposal and
731
- advances only run-local reads. `os routine publish <run>` later applies and indexes
732
- that immutable proposal; unrelated staged and unstaged work is preserved.
751
+ During a local Run, `changes.publish()` validates the complete set once before
752
+ writing individual complete files atomically. Completed paths remain after a later
753
+ filesystem failure. `validate()` grants no later permission to write; subsequent
754
+ operations read the current checkout. No later Run publication is required.
733
755
 
734
756
  `invalid_change` and known-unapplied `conflict` reject the batch.
735
757
  `publication_pending` is retryable and may report `uncertain` or `applied`;
@@ -772,42 +794,41 @@ records separately. `AirtableOperationError` reports `unapplied`, `partial` or
772
794
  work; never repeat the whole change blindly. Credentials must never be retained
773
795
  in files, publication, logs, handler input, errors or receipts.
774
796
 
775
- Managed routine launches supply workspace, scoped capability and working root.
776
- The defaults read `OS_ROUTINE_WORKSPACE`, `OS_ROUTINE_RUN` and
777
- `OS_INBOX_WORKING_ROOT` (or the current directory). Callers may supply the
778
- existing `workspace`, `capability` and `workingRoot` options. Runtime context
797
+ Managed routine launches supply workspace and scoped capability.
798
+ The defaults read `OS_ROUTINE_WORKSPACE` and `OS_ROUTINE_RUN`. Hosts may supply
799
+ `workspace`, `capability` and `request` options. Runtime context
779
800
  provides authority; callers cannot select repository remotes or expand grants.
780
801
  `os routine run <name> [--input <file|->]` executes the conventional inert
781
- definition with declared JSON input and captures OS-owned changes.
782
- `os routine publish <run>` sends those exact changes and recovers confirmed
783
- receipts without invoking business code again. Filesystem, model and installed
784
- connection effects occur immediately, including before a later failure.
785
- No-change success retains Run evidence without requiring publish. `--json`
786
- returns typed Run state/counts/result, or confirmed publish receipts/links.
802
+ definition with declared JSON input. Data writes and hosted capability calls
803
+ complete live; successful earlier work remains after a later failure. The Run
804
+ retains exact local paths, safe hosted effects and Git provenance. `--json`
805
+ returns typed Run state, result/failure and retained local activity.
787
806
  The former `prepare`, `run --local`, command/argv and authority-selection
788
807
  flags are rejected. `os routine deploy <canonical-id>` explicitly delivers the
789
808
  complete definition, including its response handlers; `--yes` provides automation
790
809
  consent. `os routine run <canonical-id> --remote` runs the current successful
791
810
  deployment with the same input/defaults, ordered steps and result validation.
792
811
  Remote handles expose `current()`, `watch()` and `step(id)`; `runs.list()` and
793
- `runs.get(id)` read retained bounded history. Remote summaries omit publication.
794
- Checkout-backed app children retain immediate publication.
795
-
796
- Retain evidence with `inbox.files.add({ path: 'evidence.txt' })`. Paths stay within
797
- the invocation's working root and uploaded bytes are verified against the retained
798
- file. Use `data.repository(name)` for Record reads and `changes()` for guarded
799
- creates, updates and deletions. Local Runs read their own successive proposals
800
- and leave ordinary uncommitted files for review. `os routine publish` sends the
801
- retained logical changes explicitly. Inbox publication has no Record methods;
812
+ `runs.get(id)` read retained bounded history. Remote summaries omit local activity.
813
+ App-started local routines use the same current-checkout and live-effects owner.
814
+
815
+ Retain evidence with shared `files.create({ file: bytes, name: 'evidence.txt' })`
816
+ and put the returned File into `fileBlock({ label, files })`. Inbox has no byte
817
+ intake API. Local publication uploads that same File before exposing the item. Use `data.repository(name)` for Record reads and `changes()` for guarded
818
+ creates, updates and deletions. Local Runs read current checkout files and leave
819
+ completed Data writes as ordinary uncommitted files for review, even after later
820
+ failure. Inbox publication has no Record methods;
802
821
  managed Response handlers retain their separately injected repository capability.
803
822
 
804
823
  Hosts publishing as a member supply the existing `request` option:
805
824
 
806
825
  ```ts
807
- const inbox = routinePublicationClient({ workspace, workingRoot, request });
826
+ const inbox = routinePublicationClient({ workspace, request });
808
827
  ```
809
828
 
810
- Here `request` is the host's authorized member transport. A member can publish an
829
+ Here `request` is the host's authorized member transport and takes precedence
830
+ over ambient Run routing. The CLI uses its active workspace and shared Files to
831
+ upload referenced local Files before sending publication. A member can publish an
811
832
  initial handlerless Ask or Digest where allowed; a member login supplies no
812
833
  routine repository-write authority. Login, session storage and refresh belong
813
834
  to `@oddington/cli`.