@oddington/sdk 0.1.37 → 0.1.39

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.
@@ -1,22 +1,20 @@
1
- import type { AskInput, DigestInput, InboxFile, PublicationRequest, PublishedAsk, PublishedDigest, ResolutionInput } from '../../../shared/inbox-contract.js';
2
- import type { FileAddOptions } from '../../../shared/inbox-files.js';
1
+ import type { AskInput, DigestInput, PublicationRequest, PublishedAsk, PublishedDigest, ResolutionInput } from '../../../shared/inbox-contract.js';
3
2
  export type { RoutineSchema, RoutineSchemaValue, RoutineDefinition, RoutineInput, RoutineRuntime, RoutineAccess, RoutineCapabilities, RoutineStep, RoutineSteps, RoutineStepInput, RoutineStepResult, RoutineStepOutput, RoutineArtifactInput, RoutineArtifact, RoutineAI } from './routine-definition-types.js';
4
3
  export declare const defineRoutine: import('./routine-definition-types.js').DefineRoutine;
5
4
  export declare const schema: import('./routine-definition-types.js').RoutineSchemaBuilders;
6
5
  export declare const file: import('./routine-definition-types.js').RoutineFileSchema;
7
- export { RoutineAIError } from '../../../shared/routine-ai-contract.js';
6
+ export { AIError, RoutineAIError } from '../../../shared/routine-ai-contract.js';
8
7
  export type { RoutineAIOutputIssue } from '../../../shared/routine-ai-output-detail.js';
9
8
  export { InboxContractError, asksBlock, continueAsk, defineHandler, fileBlock, question, recordBlock, recordsBlock, resolveAsk, respond, richTextBlock, selection, } from '../../../shared/inbox-contract.js';
10
9
  export type { AskInput, AuthoredSource, CapturedRecords, DigestInput, Handler, HandlerReference, HandlerRuntime, HandlerTransition, InboxBlock, InboxFile, JsonObject, JsonValue, PresentedField, PresentedRecord, PresentedRecordSummary, PublishedAsk, PublishedDigest, PublishedView, PublicationRequest, Question, QuestionInput, QuestionResponse, RecordCreate, RecordDelete, RecordReference, RecordSource, RecordUpdate, RepositoryCapabilities, RepositoryReceipt, Resolution, ResolutionInput, ResponseDefinition, } from '../../../shared/inbox-contract.js';
11
10
  export type { CapturedRecordTableInput, RecordField, RecordTableInput, RecordValue, RecordViewInput, TableColumn, ViewRecord, } from '../../../shared/inbox-views.js';
12
- export type { FileAddOptions } from '../../../shared/inbox-files.js';
13
11
  export { AirtableOperationError } from '../../../shared/airtable-contract.js';
14
12
  export type { AirtableField, AirtableTable, AirtableRecord, AirtableListInput, AirtableGetInput, AirtableCreateInput, AirtableUpdateInput, AirtableDeleteInput, AirtableReceipt, AirtableWriteResult, AirtableClient } from '../../../shared/airtable-contract.js';
15
13
  export type { GmailRuntimeConnection, AirtableRuntimeConnection, DropboxRuntimeConnection, OutlookRuntimeConnection, SharePointRuntimeConnection, RuntimeConnection, RuntimeConnectionFor } from '../../../shared/connection-runtime.js';
16
14
  export type { Connections } from '../../../shared/airtable-contract.js';
17
15
  export declare const connections: import('../../../shared/airtable-contract.js').Connections;
18
16
  export { DataOperationError } from '../../../shared/data-contract.js';
19
- export type { DataRepository, DataErrorCode, PublicValueDefinition, PublicField, CollectionSummary, CollectionSchema, QueryScalar, SelectionOptions, RecordSelection, RecordsQuery, DataValue, SelectedRecord, SelectionMetadata, RecordsResult, RecordsReadInput, RecordsReadResult, RecordsSearchOptions, RecordsSearchResult, HistoryListOptions, HistoryEntry, HistoryChangesOptions, HistoryChange, HistoryChangesResult, RecordIdentity, RecordCreation, RecordUpdateSet, DataPublication, DataChangeSet, DataEffect } from '../../../shared/data-contract.js';
17
+ export type { DataRepository, DataErrorCode, DataValidationDetail, DataFieldExpectation, PublicValueDefinition, PublicField, CollectionSummary, CollectionSchema, QueryScalar, SelectionOptions, RecordSelection, RecordsQuery, DataValue, SelectedRecord, SelectionMetadata, RecordsResult, RecordsReadInput, RecordsReadResult, RecordsSearchOptions, RecordsSearchResult, HistoryListOptions, HistoryEntry, HistoryChangesOptions, HistoryChange, HistoryChangesResult, RecordIdentity, RecordCreation, RecordUpdateSet, AppliedChanges, DataChangeSet, DataEffect, DataFailureDetail, DataFailureCauseCode, LocalDataFileAction } from '../../../shared/data-contract.js';
20
18
  declare global {
21
19
  namespace __OddingtonOS {
22
20
  /** Import-free OS-generated metadata; no runtime namespace is created. */
@@ -41,7 +39,6 @@ export type { File, FileInput, FileStorage, FileCreateInput, FileCreateOptions,
41
39
  export declare const files: {
42
40
  create(input: import('../../../shared/files-contract.js').FileCreateInput, options?: import('../../../shared/files-contract.js').FileCreateOptions): Promise<import('../../../shared/files-contract.js').File>;
43
41
  get(id: string): Promise<import('../../../shared/files-contract.js').File>;
44
- delete(id: string): Promise<void>;
45
42
  upload(id: string): Promise<import('../../../shared/files-contract.js').File>;
46
43
  enrich(input: import('../../../shared/files-contract.js').FileEnrichOptions): Promise<import('../../../shared/files-contract.js').FileEnrichResult>;
47
44
  read(id: string): Promise<Response>;
@@ -125,15 +122,28 @@ export type AppRoutineHandle<Result, Steps> = {
125
122
  summary?: unknown;
126
123
  data?: unknown;
127
124
  })>;
128
- publish(): Promise<Omit<RunSummary, 'result'> & {
129
- result?: Result;
130
- }>;
131
125
  };
132
- export type LocalPublication = {
133
- state: 'not_needed' | 'ready' | 'published';
134
- } | {
135
- state: 'failed';
136
- message: string;
126
+ export type LocalRunActivity = {
127
+ data: Array<{
128
+ repository: string;
129
+ created: string[];
130
+ updated: string[];
131
+ deleted: string[];
132
+ failures?: string[];
133
+ failure?: import('../../../shared/data-contract.js').DataFailureDetail;
134
+ }>;
135
+ effects: Array<{
136
+ capability: 'files' | 'inbox' | 'ai';
137
+ operation: string;
138
+ status: 'completed' | 'failed';
139
+ reference?: string;
140
+ summary?: unknown;
141
+ }>;
142
+ git?: {
143
+ branch?: string;
144
+ commit?: string;
145
+ dirty: boolean;
146
+ };
137
147
  };
138
148
  export type StepDetail = {
139
149
  id: string;
@@ -159,13 +169,12 @@ export type RunSummary = {
159
169
  failure?: {
160
170
  message: string;
161
171
  };
162
- publication?: LocalPublication;
172
+ local?: LocalRunActivity;
163
173
  };
164
174
  export type RunHandle = {
165
175
  current(): Promise<RunSummary>;
166
176
  watch(): AsyncIterable<RunSummary>;
167
177
  step(id: string): Promise<StepDetail>;
168
- publish(): Promise<RunSummary>;
169
178
  };
170
179
  export type RoutineReadiness = {
171
180
  state: 'ready';
@@ -209,7 +218,6 @@ export type RoutinePublicationClientOptions = {
209
218
  workspace?: string;
210
219
  capability?: string;
211
220
  request?: InboxRequester;
212
- workingRoot?: string;
213
221
  };
214
222
  export type RoutinePublicationClient = {
215
223
  publishAsk(value: AskInput, options: {
@@ -219,9 +227,6 @@ export type RoutinePublicationClient = {
219
227
  requestKey: string;
220
228
  }): Promise<PublishedDigest>;
221
229
  publishResolution(askId: string, value: ResolutionInput): Promise<void>;
222
- files: {
223
- add(value: FileAddOptions): Promise<InboxFile>;
224
- };
225
230
  check(body: PublicationRequest): Promise<void>;
226
231
  };
227
232
  export declare function routinePublicationClient(options?: RoutinePublicationClientOptions): RoutinePublicationClient;
@@ -110,8 +110,8 @@ export type RoutineSchemaBuilders = {
110
110
  object<const Properties extends Record<string, RoutineSchema<unknown>>>(properties: Properties): RoutineSchema<{
111
111
  [Key in keyof Properties]: RoutineSchemaValue<Properties[Key]>;
112
112
  }, false>;
113
- array<Item extends RoutineSchema<unknown>>(items: Item, options: {
114
- maxItems: number;
113
+ array<Item extends RoutineSchema<unknown>>(items: Item, options?: {
114
+ maxItems?: number;
115
115
  }): RoutineSchema<RoutineSchemaValue<Item>[], false>;
116
116
  string(options?: {
117
117
  maxLength?: number;
@@ -17,7 +17,7 @@ export type AppValueSchema = {
17
17
  } | {
18
18
  type: 'array';
19
19
  items: AppValueSchema;
20
- maxItems: number;
20
+ maxItems?: number;
21
21
  } | {
22
22
  type: 'boolean';
23
23
  } | {
@@ -138,15 +138,18 @@ export type RecordsSearchResult = {
138
138
  record: SelectedRecord;
139
139
  }>;
140
140
  };
141
- export type RecordUpdateSet = Record<string, DataValue>;
141
+ export type RecordUpdateSet = Record<string, DataValue> & {
142
+ $body?: string;
143
+ };
142
144
  export type RecordCreation = {
143
145
  $ref: string;
144
146
  $filing?: Record<string, string>;
147
+ $body?: string;
145
148
  $version?: never;
146
149
  $path?: never;
147
150
  [field: string]: DataValue | undefined;
148
151
  };
149
- export type DataPublication = {
152
+ export type AppliedChanges = {
150
153
  version: string;
151
154
  created: RecordIdentity[];
152
155
  updated: RecordIdentity[];
@@ -200,7 +203,7 @@ export interface DataChangeSet {
200
203
  update(record: RecordIdentity, set: RecordUpdateSet): void;
201
204
  delete(record: RecordIdentity): void;
202
205
  validate(): Promise<void>;
203
- publish(): Promise<DataPublication>;
206
+ apply(): Promise<AppliedChanges>;
204
207
  }
205
208
  export interface DataRepository {
206
209
  collections: {
@@ -213,9 +216,27 @@ export interface DataRepository {
213
216
  all<Query extends RecordsQuery>(query: Query, options: {
214
217
  maxRecords: number;
215
218
  }): Promise<RecordsResult<Query>>;
216
- read(ref: string): Promise<SelectedRecord | null>;
217
- read(refs: readonly string[]): Promise<RecordsReadResult>;
218
- read(input: RecordsReadInput): Promise<SelectedRecord | null | RecordsReadResult>;
219
+ read(ref: string, options: {
220
+ body: true;
221
+ }): Promise<(SelectedRecord & {
222
+ $body: string;
223
+ }) | null>;
224
+ read(refs: readonly string[], options: {
225
+ body: true;
226
+ }): Promise<Omit<RecordsReadResult, 'records'> & {
227
+ records: Array<(SelectedRecord & {
228
+ $body: string;
229
+ }) | null>;
230
+ }>;
231
+ read(ref: string, options?: {
232
+ body?: boolean;
233
+ }): Promise<SelectedRecord | null>;
234
+ read(refs: readonly string[], options?: {
235
+ body?: boolean;
236
+ }): Promise<RecordsReadResult>;
237
+ read(input: RecordsReadInput, options?: {
238
+ body?: boolean;
239
+ }): Promise<SelectedRecord | null | RecordsReadResult>;
219
240
  search(query: string, options?: RecordsSearchOptions): Promise<RecordsSearchResult>;
220
241
  };
221
242
  history: {
@@ -225,13 +246,64 @@ export interface DataRepository {
225
246
  };
226
247
  changes(): DataChangeSet;
227
248
  }
228
- export type DataErrorCode = 'context_unavailable' | 'unauthenticated' | 'access_denied' | 'invalid_query' | 'request_too_large' | 'capacity' | 'unavailable' | 'invalid_change' | 'conflict' | 'publication_pending';
249
+ export type DataErrorCode = 'context_unavailable' | 'unauthenticated' | 'access_denied' | 'invalid_query' | 'request_too_large' | 'capacity' | 'unavailable' | 'invalid_change' | 'conflict' | 'apply_pending';
229
250
  export type DataEffect = 'unapplied' | 'uncertain' | 'applied';
251
+ export type DataFieldExpectation = {
252
+ type: DataValueDefinition['kind'];
253
+ many: boolean;
254
+ nullable: boolean;
255
+ decimalPlaces?: number;
256
+ format?: 'month';
257
+ };
258
+ export type DataValidationDetail = {
259
+ record: string;
260
+ field: string;
261
+ reason: 'unknown_field' | 'missing_field' | 'invalid_value' | 'source_schema_mismatch';
262
+ schemaFile?: string;
263
+ expected?: DataFieldExpectation;
264
+ };
265
+ export type LocalDataFileAction = 'created' | 'updated' | 'deleted';
266
+ export type DataFailureCauseCode = 'schema_validation_failed' | 'invalid_record' | 'unsafe_record' | 'stale_record' | 'path_conflict' | 'filesystem_unavailable';
267
+ export type DataFailurePath = {
268
+ action: LocalDataFileAction;
269
+ path: string;
270
+ };
271
+ export type DataFailureDetail = {
272
+ code: 'local_data_read_failed' | 'local_data_write_failed' | 'local_data_write_partial';
273
+ operation: 'read' | 'write';
274
+ repository: string;
275
+ cause: {
276
+ code: DataFailureCauseCode;
277
+ message: string;
278
+ path?: string;
279
+ };
280
+ files: {
281
+ state: 'none' | 'partial';
282
+ saved: DataFailurePath[];
283
+ failed?: DataFailurePath;
284
+ notAttempted: DataFailurePath[];
285
+ savedOmitted?: number;
286
+ notAttemptedOmitted?: number;
287
+ };
288
+ nextAction: 'fix_failed_file_then_rerun' | 'review_resolve_then_rerun';
289
+ };
290
+ export type DataRecordLimitDetail = {
291
+ code: 'record_limit_exceeded';
292
+ maxRecords: number;
293
+ collections: string[];
294
+ };
295
+ export type DataOperationDetail = DataFailureDetail | DataRecordLimitDetail | DataValidationDetail;
296
+ /** Parse the only local checkout detail allowed to cross the private SDK and
297
+ * retained-Run boundary. It contains no values, raw exceptions or host paths. */
298
+ export declare function parseDataFailureDetail(value: unknown): DataFailureDetail;
299
+ export declare function parseDataOperationDetail(value: unknown): DataOperationDetail;
300
+ export declare function dataRecordLimitMessage(detail: DataRecordLimitDetail): string;
230
301
  export declare class DataOperationError extends Error {
231
302
  readonly code: DataErrorCode;
232
303
  readonly retryable: boolean;
233
304
  readonly effect?: DataEffect | undefined;
234
305
  readonly component?: string | undefined;
235
- constructor(code: DataErrorCode, retryable?: boolean, effect?: DataEffect | undefined, component?: string | undefined);
306
+ readonly detail?: DataOperationDetail | undefined;
307
+ constructor(code: DataErrorCode, retryable?: boolean, effect?: DataEffect | undefined, component?: string | undefined, detail?: DataOperationDetail | undefined);
236
308
  }
237
309
  export {};
@@ -0,0 +1,23 @@
1
+ import type { DataFieldExpectation, DataValidationDetail } from './data-contract.js';
2
+ type FieldProblem = 'unknown' | 'missing' | 'invalid' | 'source_schema';
3
+ export type FieldExpectation = DataFieldExpectation;
4
+ /** Detach and validate only the approved bounded facts at every trust boundary. */
5
+ export declare function parseDataValidationDetail(value: unknown): DataValidationDetail | undefined;
6
+ export declare function recordFieldDetail(record: string, field: string, problem: FieldProblem, schemaFile?: string, expectation?: FieldExpectation): DataValidationDetail | undefined;
7
+ /** Only bounded identifiers, relative schema locations and fixed advice enter
8
+ * public messages. Values and arbitrary upstream prose stay private. */
9
+ export declare function recordFieldMessage(record: string, field: string, problem: FieldProblem, schemaPath?: string, expected?: FieldExpectation): string | undefined;
10
+ export declare function safeRecordFieldMessage(value: unknown): string | undefined;
11
+ export declare function dataValidationMessageFacts(error: {
12
+ code: string;
13
+ message: string;
14
+ detail?: unknown;
15
+ }): {
16
+ message?: string;
17
+ detail?: DataValidationDetail;
18
+ };
19
+ export declare function explainDataValidation<T extends {
20
+ code: string;
21
+ message: string;
22
+ }>(error: T, message: unknown, detail?: unknown): T;
23
+ export {};
@@ -48,6 +48,7 @@ declare const fileValidationReasons: {
48
48
  invalid_enrichment_name: string;
49
49
  invalid_replacement: string;
50
50
  invalid_bytes: string;
51
+ original_changed: string;
51
52
  };
52
53
  export type FileErrorDetail = {
53
54
  reason: keyof typeof fileValidationReasons | 'size_mismatch' | 'size_limit';
@@ -59,6 +60,8 @@ export type FileErrorDetail = {
59
60
  /** Only inert, bounded facts cross Files and Run error boundaries. */
60
61
  export declare function parseFileErrorDetail(value: unknown): FileErrorDetail | undefined;
61
62
  export declare function fileErrorExplanation(detail: FileErrorDetail): string;
63
+ export declare const FILE_CAPACITY_MESSAGE: string;
64
+ export declare const FILE_INTEGRITY_MESSAGE: string;
62
65
  export declare class FileOperationError extends Error {
63
66
  readonly code: FileErrorCode;
64
67
  readonly status: number;
@@ -208,11 +208,13 @@ export type RecordUpdate = {
208
208
  ref: string;
209
209
  expectedVersion: string;
210
210
  set: JsonObject;
211
+ body?: string;
211
212
  };
212
213
  export type RecordCreate = {
213
214
  ref: string;
214
215
  path: string;
215
216
  fields: JsonObject;
217
+ body?: string;
216
218
  };
217
219
  export type RecordDelete = {
218
220
  ref: string;
@@ -269,6 +271,15 @@ export type Handler<Input extends JsonValue = JsonValue> = {
269
271
  export declare class InboxContractError extends Error {
270
272
  constructor(message: string);
271
273
  }
274
+ export declare const INBOX_PUBLICATION_ITEM_BYTES: number;
275
+ export declare const INBOX_PUBLICATION_REQUEST_BYTES: number;
276
+ export declare const INBOX_PUBLICATION_TOO_LARGE = "Your Inbox item failed to publish. Its content exceeds the 1 MB limit. Trim the content, or attach long reports, data, and supporting materials as files instead. Then try again.";
277
+ export declare class InboxPublicationSizeError extends InboxContractError {
278
+ readonly kind: Publication['kind'];
279
+ readonly bytes: number;
280
+ constructor(kind: Publication['kind'], bytes: number);
281
+ }
282
+ export declare function enforcePublicationSize(value: Publication): Publication;
272
283
  /** Copy only lossless JSON. In particular, JSON.stringify must not silently
273
284
  * erase undefined/functions or convert dates, sparse arrays, or nonfinite numbers. */
274
285
  export declare function serializable(value: unknown, ancestors?: Set<object>): JsonValue;
@@ -9,7 +9,7 @@ export declare const INBOX_INPUT_BYTES = 8192;
9
9
  /** Includes the exact declaration only on the private CLI-authenticated ingress. */
10
10
  export declare const INBOX_LOCAL_INPUT_BYTES: number;
11
11
  export declare const INBOX_UUID: RegExp;
12
- export type InboxOperation = 'current' | 'items.list' | 'items.read' | 'items.see' | 'items.markDigestRead' | 'items.rename' | 'items.setLifecycle' | 'items.listRecipientCandidates' | 'items.addRecipient' | 'questions.list' | 'questions.answer' | 'questions.searchRecords' | 'files.read';
12
+ export type InboxOperation = 'current' | 'items.list' | 'items.read' | 'items.see' | 'items.markDigestRead' | 'items.rename' | 'items.setLifecycle' | 'items.listRecipientCandidates' | 'items.addRecipient' | 'questions.list' | 'questions.answer' | 'questions.searchRecords';
13
13
  export declare function isAppQuestionOperation(operation: InboxOperation): boolean;
14
14
  /** Closed wire vocabulary; both placements require an explicit relevance filter. */
15
15
  export declare function parseInboxRequest(value: unknown): {
@@ -201,11 +201,5 @@ export interface InboxMember {
201
201
  answer(input: InboxAnswerInput): Promise<ResponseAcceptance>;
202
202
  searchRecords(input: InboxSearchInput): Promise<RecordSelectionResult>;
203
203
  };
204
- files: {
205
- read(input: {
206
- itemId: string;
207
- fileId: string;
208
- }): Promise<Response>;
209
- };
210
204
  }
211
205
  export {};
@@ -12,7 +12,7 @@ export declare const ROUTINE_AI_OPERATION_MS = 120000;
12
12
  export declare const ROUTINE_AI_ERROR_CODES: readonly ['access_denied', 'capability_unavailable', 'invalid_input', 'unsupported_file', 'file_unavailable', 'input_too_large', 'output_too_large', 'provider_failure', 'invalid_output', 'cancelled'];
13
13
  export type RoutineAIErrorCode = typeof ROUTINE_AI_ERROR_CODES[number];
14
14
  /** The original answer is explicit recovery data, never part of the message or JSON logging. */
15
- export declare class RoutineAIError extends Error {
15
+ export declare class AIError extends Error {
16
16
  readonly code: RoutineAIErrorCode;
17
17
  readonly detail?: RoutineAIOutputIssue;
18
18
  readonly text?: string;
@@ -21,13 +21,15 @@ export declare class RoutineAIError extends Error {
21
21
  text?: string;
22
22
  });
23
23
  }
24
+ /** Compatibility alias: both names identify the same error constructor. */
25
+ export { AIError as RoutineAIError };
24
26
  /** Explicit private transport projection; ordinary error logging excludes answer text. */
25
- export declare function routineAIErrorFacts(error: RoutineAIError): {
27
+ export declare function routineAIErrorFacts(error: AIError): {
26
28
  code: "access_denied" | "cancelled" | "capability_unavailable" | "file_unavailable" | "input_too_large" | "invalid_input" | "invalid_output" | "output_too_large" | "provider_failure" | "unsupported_file";
27
29
  detail?: RoutineAIOutputIssue | undefined;
28
30
  text?: string | undefined;
29
31
  };
30
- export declare function parseRoutineAIError(value: unknown): RoutineAIError;
32
+ export declare function parseRoutineAIError(value: unknown): AIError;
31
33
  export type RoutineAIInput = string | File;
32
34
  export type RoutineAIRequest = {
33
35
  kind: 'generateText';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oddington/sdk",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "description": "OS routine and response-handler SDK",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -1,2 +0,0 @@
1
- export declare function parseDelimitedText(value: string, declaredDelimiter?: string): string[][];
2
- export declare function delimitedDataRowCount(rows: string[][], headerRow?: number): number;
@@ -1,12 +0,0 @@
1
- import { type InboxFile } from './inbox-contract.js';
2
- export type FileAddOptions = {
3
- path: string;
4
- name?: string;
5
- };
6
- export declare function validateFileAddOptions(value: unknown): FileAddOptions;
7
- /** Consumer interpretation only: no parsing facts become File metadata. */
8
- export declare function previewCsvRows(bytes: Uint8Array): string[][];
9
- export declare function deriveInboxFile(bytes: Uint8Array, name: string): Promise<Omit<InboxFile, 'id'>>;
10
- /** Original integrity is independent of consumer format interpretation. */
11
- export declare function verifyInboxFile(bytes: Uint8Array, value: unknown): Promise<InboxFile>;
12
- export declare function publicationFiles(body?: import('./inbox-contract.js').InboxBlock[]): InboxFile[];