@oddington/sdk 0.1.19 → 0.1.20
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
|
@@ -12,9 +12,16 @@ same key and content returns the original result; changed content conflicts.
|
|
|
12
12
|
Existing Inbox-retained files remain separate from shared Files, with their
|
|
13
13
|
original identities, bytes and audience. The SDK exposes no raw-credential API.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
Hosted apps use `inbox.questions.list({ routines })` for `AnswerableQuestion[]`.
|
|
16
|
+
Derive `routines` from the existing app declaration with
|
|
17
|
+
`[...new Set(Object.values(appDeclaration.routines).map(binding => binding.routine))]`.
|
|
18
|
+
These inner canonical names narrow relevance only; they grant no answer or
|
|
19
|
+
Record-search authority. The ordinary authenticated Inbox context needs no app
|
|
20
|
+
identity or declaration provisioning. The filter is required; `[]` returns no
|
|
21
|
+
Questions after authentication. The SDK validates and privately snapshots the
|
|
22
|
+
filter across pagination. Local apps use `inbox.questions.list()` instead, bound
|
|
23
|
+
to their trusted host's declaration; any supplied filter is invalid locally.
|
|
24
|
+
Both use the same answer and Record-search methods, without a filter or prior list.
|
|
18
25
|
`InboxItem` remains the complete first-party Inbox value. Record refs are placement
|
|
19
26
|
hints only: match them against independently authorized Data, and omit ambiguous
|
|
20
27
|
detail placement. Keep drafts on failed or uncertain acceptance, prevent duplicate
|
package/dist/browser.js
CHANGED
|
@@ -475,7 +475,11 @@ var AppRoutineContractError = class extends Error {
|
|
|
475
475
|
this.code = code;
|
|
476
476
|
}
|
|
477
477
|
code;
|
|
478
|
-
}, propertyName = /^[a-z][A-Za-z0-9]*(?![\s\S])/, stepId = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, routineName = /^[a-z0-9][a-z0-9-]{0,62}(?![\s\S])
|
|
478
|
+
}, propertyName = /^[a-z][A-Za-z0-9]*(?![\s\S])/, stepId = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, routineName = /^[a-z0-9][a-z0-9-]{0,62}(?![\s\S])/;
|
|
479
|
+
function isAppRoutineName(value) {
|
|
480
|
+
return typeof value == "string" && routineName.test(value);
|
|
481
|
+
}
|
|
482
|
+
var owns = (value, key) => Object.hasOwn(value, key), invalidContract = () => {
|
|
479
483
|
throw new AppRoutineContractError("invalid_contract");
|
|
480
484
|
}, invalidValue = () => {
|
|
481
485
|
throw new AppRoutineContractError("invalid_value");
|
|
@@ -530,7 +534,7 @@ function parseAppRoutineContract(value) {
|
|
|
530
534
|
return invalidContract();
|
|
531
535
|
}
|
|
532
536
|
}
|
|
533
|
-
if (!record(value) || !fields2(value, ["routine", "input", "steps"], ["result"]) ||
|
|
537
|
+
if (!record(value) || !fields2(value, ["routine", "input", "steps"], ["result"]) || !isAppRoutineName(value.routine) || !denseArray(value.steps) || value.steps.length < 1 || value.steps.length > 64) return invalidContract();
|
|
534
538
|
let input = schema2(value.input), result2 = owns(value, "result") ? schema2(value.result) : void 0, ids = /* @__PURE__ */ new Set(), steps = value.steps.map((step) => !record(step) || !fields2(step, ["id"], ["summary"]) || typeof step.id != "string" || !stepId.test(step.id) || ids.has(step.id) ? invalidContract() : (ids.add(step.id), { id: step.id, ...owns(step, "summary") ? { summary: schema2(step.summary) } : {} }));
|
|
535
539
|
return { routine: value.routine, input, steps, ...result2 === void 0 ? {} : { result: result2 } };
|
|
536
540
|
}
|
|
@@ -1937,14 +1941,14 @@ function response(value) {
|
|
|
1937
1941
|
let answer = object3(value);
|
|
1938
1942
|
return assert(Object.keys(answer).every((key) => ["selection", "note"].includes(key))), typeof answer.selection == "string" ? assert(text3(answer.selection) && answer.selection === answer.selection.trim()) : recordReference(answer.selection), Object.hasOwn(answer, "note") && assert(text3(answer.note)), answer;
|
|
1939
1943
|
}
|
|
1940
|
-
function parseInboxRequest(value) {
|
|
1944
|
+
function parseInboxRequest(value, questionListContext = "local") {
|
|
1941
1945
|
try {
|
|
1942
1946
|
let envelope = object3(value);
|
|
1943
1947
|
assert(Object.keys(envelope).sort().join(",") === "input,operation"), assert(typeof envelope.operation == "string" && Object.hasOwn(operations, envelope.operation));
|
|
1944
|
-
let operation2 = envelope.operation, input = object3(envelope.input), required = operations[operation2];
|
|
1945
|
-
assert(required.every((key) => Object.hasOwn(input, key)) && Object.keys(input).every((key) => required.includes(key) || operation2 === "questions.searchRecords" && key === "selected" || (operation2 === "items.list" || operation2 === "questions.list") && key === "beforeNumber"));
|
|
1948
|
+
let operation2 = envelope.operation, input = { ...object3(envelope.input) }, required = operations[operation2];
|
|
1949
|
+
assert(required.every((key) => Object.hasOwn(input, key)) && Object.keys(input).every((key) => required.includes(key) || operation2 === "questions.searchRecords" && key === "selected" || (operation2 === "items.list" || operation2 === "questions.list") && key === "beforeNumber" || operation2 === "questions.list" && questionListContext === "hosted" && key === "routines")), operation2 === "questions.list" && questionListContext === "hosted" && (assert(Object.hasOwn(input, "routines")), assert(array2(input.routines).every(isAppRoutineName)));
|
|
1946
1950
|
for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
|
|
1947
|
-
return "revision" in input && assert(integer(input.revision)), "beforeNumber" in input && assert(integer(input.beforeNumber)), "questionId" in input && assert(text3(input.questionId) && input.questionId === input.questionId.trim()), "title" in input && assert(text3(input.title)), "lifecycle" in input && assert(input.lifecycle === "open" || input.lifecycle === "closed"), "query" in input && assert(text3(input.query, !0) && input.query.length <= 256), "selected" in input && recordReference(input.selected), "response" in input && response(input.response), assert(new TextEncoder().encode(JSON.stringify(envelope)).byteLength <= INBOX_INPUT_BYTES), { operation: operation2, input };
|
|
1951
|
+
return "revision" in input && assert(integer(input.revision)), "beforeNumber" in input && assert(integer(input.beforeNumber)), "questionId" in input && assert(text3(input.questionId) && input.questionId === input.questionId.trim()), "title" in input && assert(text3(input.title)), "lifecycle" in input && assert(input.lifecycle === "open" || input.lifecycle === "closed"), "query" in input && assert(text3(input.query, !0) && input.query.length <= 256), "selected" in input && recordReference(input.selected), "response" in input && response(input.response), assert(new TextEncoder().encode(JSON.stringify(envelope)).byteLength <= INBOX_INPUT_BYTES), "routines" in input && (input.routines = [...new Set(input.routines)]), { operation: operation2, input };
|
|
1948
1952
|
} catch {
|
|
1949
1953
|
throw new InboxOperationError(400, "invalid_input");
|
|
1950
1954
|
}
|
|
@@ -2493,13 +2497,13 @@ function hostFailure(error, context2) {
|
|
|
2493
2497
|
return !context2.isCurrent() || context2.expiresAt <= Date.now() || error instanceof InboxContextError && error.status === 401 ? stale() : error instanceof InboxContextError && error.status === 403 ? new InboxOperationError(403, "access_denied") : unavailable2();
|
|
2494
2498
|
}
|
|
2495
2499
|
async function send2(operation2, input) {
|
|
2496
|
-
let envelope = parseInboxRequest({ operation: operation2, input }), context2;
|
|
2500
|
+
let envelope = operation2 === "questions.list" ? void 0 : parseInboxRequest({ operation: operation2, input }), context2;
|
|
2497
2501
|
try {
|
|
2498
2502
|
context2 = await resolveAppContext();
|
|
2499
2503
|
} catch {
|
|
2500
2504
|
throw stale();
|
|
2501
2505
|
}
|
|
2502
|
-
if (context2.kind === "local") {
|
|
2506
|
+
if (envelope ??= parseInboxRequest({ operation: operation2, input }, context2.kind === "local" ? "local" : "hosted"), context2.kind === "local") {
|
|
2503
2507
|
if (!isAppQuestionOperation(operation2)) throw new InboxOperationError(403, "access_denied");
|
|
2504
2508
|
let check2 = () => {
|
|
2505
2509
|
if (!context2.isCurrent() || context2.signal.aborted || context2.expiresAt <= Date.now()) throw stale();
|
|
@@ -2636,13 +2640,17 @@ var inbox = {
|
|
|
2636
2640
|
addRecipient: async (input) => await send2("items.addRecipient", input)
|
|
2637
2641
|
},
|
|
2638
2642
|
questions: {
|
|
2639
|
-
async list() {
|
|
2640
|
-
let
|
|
2643
|
+
async list(input) {
|
|
2644
|
+
let supplied = input === void 0 ? void 0 : parseInboxRequest({ operation: "questions.list", input }, "hosted").input;
|
|
2645
|
+
if (supplied && Object.hasOwn(supplied, "beforeNumber")) throw new InboxOperationError(400, "invalid_input");
|
|
2646
|
+
let routines = supplied ? Object.freeze(supplied.routines) : void 0, questions = [], beforeNumber, initial;
|
|
2641
2647
|
try {
|
|
2642
2648
|
initial = await resolveAppContext();
|
|
2643
2649
|
} catch {
|
|
2644
2650
|
throw stale();
|
|
2645
2651
|
}
|
|
2652
|
+
if (initial.kind === "local" ? input !== void 0 : routines === void 0)
|
|
2653
|
+
throw new InboxOperationError(400, "invalid_input");
|
|
2646
2654
|
let host;
|
|
2647
2655
|
try {
|
|
2648
2656
|
host = initial.kind !== "local" && await resolveHostedInboxContext(initial);
|
|
@@ -2655,8 +2663,11 @@ var inbox = {
|
|
|
2655
2663
|
};
|
|
2656
2664
|
do {
|
|
2657
2665
|
check();
|
|
2658
|
-
let page = await send2("questions.list",
|
|
2659
|
-
|
|
2666
|
+
let page = await send2("questions.list", {
|
|
2667
|
+
...routines === void 0 ? {} : { routines },
|
|
2668
|
+
...beforeNumber === void 0 ? {} : { beforeNumber }
|
|
2669
|
+
});
|
|
2670
|
+
if (check(), page.questions.some((question2) => question2.item.href !== `https://${initial.workspace}.oddington.ai/inbox/${question2.item.id}` || routines !== void 0 && !routines.includes(question2.origin.routine)) || beforeNumber !== void 0 && (page.questions.some((question2) => question2.item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable2();
|
|
2660
2671
|
if (questions.push(...page.questions), page.nextBeforeNumber === null) return questions;
|
|
2661
2672
|
beforeNumber = page.nextBeforeNumber;
|
|
2662
2673
|
} while (!0);
|