@sprigr/apps-app-sdk 0.8.4 → 0.8.6
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 +1 -1
- package/dist/index.d.ts +77 -3
- package/dist/index.js +54 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ Three platform tiers, and they are not substitutes for each other. Full guide: [
|
|
|
73
73
|
- `undoEnvelope({...})` throws on a blank field. The platform drops the whole envelope on a blank and mints nothing, silently.
|
|
74
74
|
- `refuseWithoutForce(name, handler, opts)` / `archiveOfferRefusal(...)`: a delete refuses once and offers the vendor's native archive unless `force: true`.
|
|
75
75
|
- `buildConfirmationPolicy({ irreversible, always, rules })` declares a dispatcher's policy beside its action registry; `checkConfirmationPolicy({ policy, registry, ungated, requiredInput })` returns every silent failure (dead rule, `(unset)` placeholder, money threshold, unclassified write) for a one-line test.
|
|
76
|
-
- `runUndoApply(args, { env, journal, specs, pin })` is the body of your `internal: true` reverse tool: load, re-pin to the journalled connection, restore, drop. `pin` may hand `restore` a different type from the env (a per-actor token state), may throw (`connection_unavailable`) or return null to refuse (`connection_mismatch`); a restore that throws is `restore_failed` and the copy is kept.
|
|
76
|
+
- `runUndoApply(args, { env, journal, specs, pin })` is the body of your `internal: true` reverse tool: load, re-pin to the journalled connection, restore, drop. `pin` may hand `restore` a different type from the env (a per-actor token state), may throw (`connection_unavailable`) or return null to refuse (`connection_mismatch`); a restore that throws is `restore_failed` and the copy is kept; a successful restore may return `newId`, `notRestored`, `extra` (spread into the payload) and `note` (appended after the fidelity sentence).
|
|
77
77
|
- `safeCapture(scope, name, id, read)` and `offerUndo({ journal, entity, id, before, connection, fidelity, resource, describe, warning })`: the capture-then-offer halves for a write that is not behind an approval card (a dispatcher `update_*` action). `requireApproval` uses the same two on its granted pass.
|
|
78
78
|
- `sprigr-check-write-protection` (bin): every destructive-by-name tool or enumerated dispatcher action must carry a policy, or a reason in `apps/<app>/write-protection.json`; ratchets on `tools/write-protection-baseline.json`.
|
|
79
79
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1153,9 +1153,11 @@ interface ApprovalGateOptions<E, P = E> {
|
|
|
1153
1153
|
/**
|
|
1154
1154
|
* Human label for a raw id, looked up THROUGH the pinned connection. Fall
|
|
1155
1155
|
* back to the id on any miss; never guess, a confidently wrong card is worse
|
|
1156
|
-
* than a terse one. Omit to always show the raw id.
|
|
1156
|
+
* than a terse one. Omit to always show the raw id. `name` is the tool, or
|
|
1157
|
+
* for a dispatcher the action, so a lookup can route by resource type when
|
|
1158
|
+
* the id alone does not say what it is (an Asana gid).
|
|
1157
1159
|
*/
|
|
1158
|
-
describeTarget?: (pinned: P, id: string) => Promise<string>;
|
|
1160
|
+
describeTarget?: (pinned: P, id: string, name: string) => Promise<string>;
|
|
1159
1161
|
/**
|
|
1160
1162
|
* Where before-images go. Required when any spec declares `undo`. The
|
|
1161
1163
|
* journal's own capture returns null rather than throwing, and this wrapper
|
|
@@ -1269,6 +1271,13 @@ interface RestoreResult {
|
|
|
1269
1271
|
error?: string;
|
|
1270
1272
|
notRestored?: string;
|
|
1271
1273
|
extra?: Record<string, unknown>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Free-form detail appended to the runner's note (the new gid, rows it
|
|
1276
|
+
* could not refile, a sticker the vendor will not remove). The runner's own
|
|
1277
|
+
* sentence on fidelity stays first so the model reads "replacement, not an
|
|
1278
|
+
* undo" before the detail.
|
|
1279
|
+
*/
|
|
1280
|
+
note?: string;
|
|
1272
1281
|
}
|
|
1273
1282
|
interface JournalRowLike<T = unknown> {
|
|
1274
1283
|
entity: string;
|
|
@@ -1415,6 +1424,71 @@ interface OfferUndoArgs {
|
|
|
1415
1424
|
*/
|
|
1416
1425
|
declare function offerUndo(args: OfferUndoArgs): Promise<AppUndoEnvelope | undefined>;
|
|
1417
1426
|
|
|
1427
|
+
/**
|
|
1428
|
+
* Apply confirmation policies to a parsed `sprigr-app.json`, for an app's
|
|
1429
|
+
* `gen:confirmation` script and its drift-guard test.
|
|
1430
|
+
*
|
|
1431
|
+
* Pure: takes the parsed manifest, mutates it in place, returns what it
|
|
1432
|
+
* touched. The script owns the two lines of file I/O around it, so this
|
|
1433
|
+
* module stays free of `node:fs` and safe to bundle into a Worker.
|
|
1434
|
+
*
|
|
1435
|
+
* Besides writing each policy, it retires the two mechanisms a policy
|
|
1436
|
+
* supersedes: the legacy `confirmation_required` flag (a bare
|
|
1437
|
+
* `{ always: true }` with no describe) and any app-declared `confirm` input
|
|
1438
|
+
* (the platform injects its own top-level `confirm` wherever a policy is
|
|
1439
|
+
* present). Both are stripped from EVERY tool, not only the gated ones,
|
|
1440
|
+
* because a stray copy on an ungated tool is how a handler ends up reading
|
|
1441
|
+
* a flag nothing enforces.
|
|
1442
|
+
*/
|
|
1443
|
+
|
|
1444
|
+
interface ManifestDispatchBlock {
|
|
1445
|
+
actionField: string;
|
|
1446
|
+
actions: string[];
|
|
1447
|
+
actionInputs?: Record<string, {
|
|
1448
|
+
accepts: string[];
|
|
1449
|
+
required?: string[];
|
|
1450
|
+
}>;
|
|
1451
|
+
}
|
|
1452
|
+
interface ManifestToolLike {
|
|
1453
|
+
name: string;
|
|
1454
|
+
input_schema?: {
|
|
1455
|
+
properties?: Record<string, unknown>;
|
|
1456
|
+
required?: string[];
|
|
1457
|
+
[k: string]: unknown;
|
|
1458
|
+
};
|
|
1459
|
+
confirmation?: unknown;
|
|
1460
|
+
confirmation_required?: boolean;
|
|
1461
|
+
dispatch?: unknown;
|
|
1462
|
+
[k: string]: unknown;
|
|
1463
|
+
}
|
|
1464
|
+
interface ManifestLike {
|
|
1465
|
+
tools?: ManifestToolLike[];
|
|
1466
|
+
[k: string]: unknown;
|
|
1467
|
+
}
|
|
1468
|
+
interface ApplyPoliciesOptions {
|
|
1469
|
+
/** Tool name -> its policy: a tool-level rule, or `{ actions }` for a dispatcher. */
|
|
1470
|
+
policies: Readonly<Record<string, ConfirmationPolicy>>;
|
|
1471
|
+
/** Tool name -> dispatch block to write alongside (dispatchers only). */
|
|
1472
|
+
dispatch?: Readonly<Record<string, ManifestDispatchBlock>>;
|
|
1473
|
+
/** Delete `confirmation_required` from every tool. Default true. */
|
|
1474
|
+
stripLegacyFlag?: boolean;
|
|
1475
|
+
/** Delete an app-declared `confirm` input (property + required entry) from every tool. Default true. */
|
|
1476
|
+
dropConfirmParam?: boolean;
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Write the policies (and dispatch blocks) onto the named tools in place.
|
|
1480
|
+
* Throws when a policy names a tool the manifest does not have, so a
|
|
1481
|
+
* renamed tool cannot silently lose its gate. Returns the tool names touched.
|
|
1482
|
+
*/
|
|
1483
|
+
declare function applyConfirmationPolicies(manifest: ManifestLike, opts: ApplyPoliciesOptions): string[];
|
|
1484
|
+
/**
|
|
1485
|
+
* True when applying the policies to a copy of the manifest changes nothing:
|
|
1486
|
+
* the committed file is a fresh generation. The drift-guard test's one call.
|
|
1487
|
+
*/
|
|
1488
|
+
declare function manifestIsFresh(manifest: ManifestLike, opts: ApplyPoliciesOptions): boolean;
|
|
1489
|
+
/** The manifest, serialised the way the repo commits it (2-space, trailing newline). */
|
|
1490
|
+
declare function serializeManifest(manifest: ManifestLike): string;
|
|
1491
|
+
|
|
1418
1492
|
/**
|
|
1419
1493
|
* @sprigr/apps-app-sdk
|
|
1420
1494
|
*
|
|
@@ -1815,4 +1889,4 @@ interface ExecutionContextLike {
|
|
|
1815
1889
|
}
|
|
1816
1890
|
type HandlerFn<TArgs, TResult> = (args: TArgs, env: Record<string, unknown>, ctx?: ExecutionContextLike) => Promise<TResult>;
|
|
1817
1891
|
|
|
1818
|
-
export { APPROVAL_GRANTED_KEY, type Actor, type AppApprovalEnvelope, type AppFileListItem, type AppFileUrlArgs, type AppFileUrlResult, type AppFilesEnv, type AppUndoEnvelope, type ApprovalGateOptions, type ApprovalSpec, type ArchiveOfferOptions, type ArchiveOfferRefusal, type CaptureJournal, type ConfirmCondition, type ConfirmRule, type ConfirmationPolicy, type D1Like, type D1PreparedStatementLike, DEFAULT_EMIT_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, DEFAULT_MONEY_FIELDS, DEFAULT_WRITE_PREFIXES, type DispatcherApprovalGate, type DispatcherApprovalOptions, type EmitMarketplaceEventOptions, type EmitResult, type EmitTransport, type EventArgs, type ExecutionContextLike, type FetchFileResult, type FetchWithRetryOptions, type GetAppFileResult, type HandlerFn, type InboxOwner, type InstallBridge, InvalidUndoEnvelopeError, type JournalRowLike, type MarketplaceEventEmitOpts, type MarketplaceEventSourceIntegration, NotConnectedError, type OAuthBouncerSignals, type OAuthState, type OfferUndoArgs, type PlatformHostEnv, type PolicyCheckInput, type PolicySource, type PutAppFileArgs, type PutAppFileResult, type PutAppFileStreamArgs, type RequireApprovalOptions, type RestoreResult, type RestoreSpec, type ScheduleArgs, type SprigrDataAggregationCell, type SprigrDataAggregationResult, type SprigrDataAggregationSpec, type SprigrDataApi, type SprigrDataIndexOpts, type SprigrDataSearchOpts, type SprigrDataSearchResult, type SprigrFilesApi, type SprigrFilesApiWithEdit, type SprigrFilesCreateInput, type SprigrFilesCreateResult, type SprigrFilesEditInput, type SprigrFilesEditResult, type SprigrFilesJobResult, type ToolArgs, type ToolHandler, type ToolResult, type ToolWrapperOptions, UNIT_SEP, type UndoApplyOptions, type UndoApplyResult, type UndoCaptureSpec, type UndoFidelity, type WebhookArgs, type WfpBridgeEnv, type WfpEmitReply, actorKey, actorTool, appFileUrl, approvalHash, archiveOfferRefusal, base64ToBytes, buildConfirmationPolicy, buildMarketplaceWebhookUrl, bytesToBase64, canEmit, checkConfirmationPolicy, constantTimeEqual, createMarketplaceEmitter, createToolWrappers, decodeState, deleteAppFile, describeMissingBridge, dispatcherApproval, emitMarketplaceEvent, encodeState, fetchFileAsBase64, fetchFileBytes, fetchWithRetry, fullWarning, getAppFile, hmacSha256Hex, installTokenPost, isNotConnectedError, isStagingHost, listAppFiles, offerUndo, overlaySprigr, ownerFromActorKey, parseActor, putAppFile, putAppFileStream, randomHex, recreatedWarning, refuseWithoutForce, requireApproval, resolveInstallBridge, resolveOAuthBouncerBase, resolveOAuthBouncerCallbackUrl, resolvePlatformWebhookBase, runUndoApply, safeCapture, seq, set, tool, undoEnvelope, withSprigrEmitFallback };
|
|
1892
|
+
export { APPROVAL_GRANTED_KEY, type Actor, type AppApprovalEnvelope, type AppFileListItem, type AppFileUrlArgs, type AppFileUrlResult, type AppFilesEnv, type AppUndoEnvelope, type ApplyPoliciesOptions, type ApprovalGateOptions, type ApprovalSpec, type ArchiveOfferOptions, type ArchiveOfferRefusal, type CaptureJournal, type ConfirmCondition, type ConfirmRule, type ConfirmationPolicy, type D1Like, type D1PreparedStatementLike, DEFAULT_EMIT_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, DEFAULT_MONEY_FIELDS, DEFAULT_WRITE_PREFIXES, type DispatcherApprovalGate, type DispatcherApprovalOptions, type EmitMarketplaceEventOptions, type EmitResult, type EmitTransport, type EventArgs, type ExecutionContextLike, type FetchFileResult, type FetchWithRetryOptions, type GetAppFileResult, type HandlerFn, type InboxOwner, type InstallBridge, InvalidUndoEnvelopeError, type JournalRowLike, type ManifestDispatchBlock, type ManifestLike, type ManifestToolLike, type MarketplaceEventEmitOpts, type MarketplaceEventSourceIntegration, NotConnectedError, type OAuthBouncerSignals, type OAuthState, type OfferUndoArgs, type PlatformHostEnv, type PolicyCheckInput, type PolicySource, type PutAppFileArgs, type PutAppFileResult, type PutAppFileStreamArgs, type RequireApprovalOptions, type RestoreResult, type RestoreSpec, type ScheduleArgs, type SprigrDataAggregationCell, type SprigrDataAggregationResult, type SprigrDataAggregationSpec, type SprigrDataApi, type SprigrDataIndexOpts, type SprigrDataSearchOpts, type SprigrDataSearchResult, type SprigrFilesApi, type SprigrFilesApiWithEdit, type SprigrFilesCreateInput, type SprigrFilesCreateResult, type SprigrFilesEditInput, type SprigrFilesEditResult, type SprigrFilesJobResult, type ToolArgs, type ToolHandler, type ToolResult, type ToolWrapperOptions, UNIT_SEP, type UndoApplyOptions, type UndoApplyResult, type UndoCaptureSpec, type UndoFidelity, type WebhookArgs, type WfpBridgeEnv, type WfpEmitReply, actorKey, actorTool, appFileUrl, applyConfirmationPolicies, approvalHash, archiveOfferRefusal, base64ToBytes, buildConfirmationPolicy, buildMarketplaceWebhookUrl, bytesToBase64, canEmit, checkConfirmationPolicy, constantTimeEqual, createMarketplaceEmitter, createToolWrappers, decodeState, deleteAppFile, describeMissingBridge, dispatcherApproval, emitMarketplaceEvent, encodeState, fetchFileAsBase64, fetchFileBytes, fetchWithRetry, fullWarning, getAppFile, hmacSha256Hex, installTokenPost, isNotConnectedError, isStagingHost, listAppFiles, manifestIsFresh, offerUndo, overlaySprigr, ownerFromActorKey, parseActor, putAppFile, putAppFileStream, randomHex, recreatedWarning, refuseWithoutForce, requireApproval, resolveInstallBridge, resolveOAuthBouncerBase, resolveOAuthBouncerCallbackUrl, resolvePlatformWebhookBase, runUndoApply, safeCapture, seq, serializeManifest, set, tool, undoEnvelope, withSprigrEmitFallback };
|
package/dist/index.js
CHANGED
|
@@ -617,9 +617,9 @@ function rawIdOf(args, keys) {
|
|
|
617
617
|
function isOk(result) {
|
|
618
618
|
return !!result && typeof result === "object" && result.ok !== false;
|
|
619
619
|
}
|
|
620
|
-
async function safeLabel(fn, pinned, id) {
|
|
620
|
+
async function safeLabel(fn, pinned, id, name) {
|
|
621
621
|
try {
|
|
622
|
-
const label = await fn(pinned, id);
|
|
622
|
+
const label = await fn(pinned, id, name);
|
|
623
623
|
return label && label.trim() ? label : id;
|
|
624
624
|
} catch {
|
|
625
625
|
return id;
|
|
@@ -629,11 +629,11 @@ async function pin(opts, env, connection) {
|
|
|
629
629
|
if (!connection || !opts.pinEnv) return env;
|
|
630
630
|
return opts.pinEnv(env, connection);
|
|
631
631
|
}
|
|
632
|
-
async function askPass(spec, params, env, opts, hashPrefix) {
|
|
632
|
+
async function askPass(name, spec, params, env, opts, hashPrefix) {
|
|
633
633
|
const connection = await opts.resolveConnection(env, params);
|
|
634
634
|
const rawId = rawIdOf(params, spec.keys);
|
|
635
635
|
const pinned = await pin(opts, env, connection);
|
|
636
|
-
const target = rawId && opts.describeTarget ? await safeLabel(opts.describeTarget, pinned, rawId) : rawId || "(unknown id)";
|
|
636
|
+
const target = rawId && opts.describeTarget ? await safeLabel(opts.describeTarget, pinned, rawId, name) : rawId || "(unknown id)";
|
|
637
637
|
const extra = spec.hash ? spec.hash(params) : [];
|
|
638
638
|
return {
|
|
639
639
|
ok: false,
|
|
@@ -688,7 +688,7 @@ function requireApproval(handlers, specs, opts) {
|
|
|
688
688
|
const { [APPROVAL_GRANTED_KEY]: _granted, ...rest } = a;
|
|
689
689
|
return grantedPass(name, spec, rest, env, opts, () => inner(rest, env, ctx));
|
|
690
690
|
}
|
|
691
|
-
return askPass(spec, a, env, opts, []);
|
|
691
|
+
return askPass(name, spec, a, env, opts, []);
|
|
692
692
|
};
|
|
693
693
|
}
|
|
694
694
|
return gated;
|
|
@@ -707,7 +707,7 @@ function dispatcherApproval(specs, opts) {
|
|
|
707
707
|
if (a[APPROVAL_GRANTED_KEY] === true) {
|
|
708
708
|
return grantedPass(action, spec, params, env, opts, write);
|
|
709
709
|
}
|
|
710
|
-
return askPass(spec, params, env, opts, [action]);
|
|
710
|
+
return askPass(action, spec, params, env, opts, [action]);
|
|
711
711
|
}
|
|
712
712
|
};
|
|
713
713
|
}
|
|
@@ -733,7 +733,7 @@ async function runUndoApply(args, opts) {
|
|
|
733
733
|
};
|
|
734
734
|
}
|
|
735
735
|
const before = row.before;
|
|
736
|
-
if (!before || typeof before !== "object") {
|
|
736
|
+
if (!before || typeof before !== "object" || Array.isArray(before)) {
|
|
737
737
|
return { ok: false, error: "before_image_unreadable", note: "The saved copy could not be read back. Nothing was changed." };
|
|
738
738
|
}
|
|
739
739
|
let pinned;
|
|
@@ -769,6 +769,7 @@ async function runUndoApply(args, opts) {
|
|
|
769
769
|
await opts.journal.dropBefore(ref);
|
|
770
770
|
const recreated = spec.fidelity === "recreated";
|
|
771
771
|
const notRestored = result.notRestored ?? spec.notRestored;
|
|
772
|
+
const suffix = result.note && result.note.trim() ? ` ${result.note.trim()}` : "";
|
|
772
773
|
return {
|
|
773
774
|
ok: true,
|
|
774
775
|
...result.extra ?? {},
|
|
@@ -778,7 +779,7 @@ async function runUndoApply(args, opts) {
|
|
|
778
779
|
new_id: result.newId ?? null,
|
|
779
780
|
fidelity: spec.fidelity,
|
|
780
781
|
...notRestored ? { not_restored: notRestored } : {},
|
|
781
|
-
note: recreated ? `Created a NEW ${spec.resource}${result.newId ? ` (${result.newId})` : ""} from the saved copy. The original ${row.original_id} is still gone and its id will never be reissued.${notRestored ? ` Not restored: ${notRestored}.` : ""} Report this as a replacement, not as an undo
|
|
782
|
+
note: recreated ? `Created a NEW ${spec.resource}${result.newId ? ` (${result.newId})` : ""} from the saved copy. The original ${row.original_id} is still gone and its id will never be reissued.${notRestored ? ` Not restored: ${notRestored}.` : ""} Report this as a replacement, not as an undo.${suffix}` : `Restored ${spec.resource} ${row.original_id} to its saved values.${notRestored ? ` Not restored: ${notRestored}.` : ""} Anything changed since the capture was overwritten.${suffix}`
|
|
782
783
|
};
|
|
783
784
|
}
|
|
784
785
|
|
|
@@ -939,6 +940,48 @@ function checkConfirmationPolicy(input) {
|
|
|
939
940
|
}
|
|
940
941
|
return out.sort();
|
|
941
942
|
}
|
|
943
|
+
|
|
944
|
+
// src/write-protection/manifest.ts
|
|
945
|
+
function applyConfirmationPolicies(manifest, opts) {
|
|
946
|
+
const tools = manifest.tools ?? [];
|
|
947
|
+
const byName = new Map(tools.map((t) => [t.name, t]));
|
|
948
|
+
const touched = [];
|
|
949
|
+
for (const [name, policy] of Object.entries(opts.policies)) {
|
|
950
|
+
const tool2 = byName.get(name);
|
|
951
|
+
if (!tool2) throw new Error(`applyConfirmationPolicies: no tool named '${name}' in the manifest`);
|
|
952
|
+
tool2.confirmation = policy;
|
|
953
|
+
touched.push(name);
|
|
954
|
+
}
|
|
955
|
+
for (const [name, block] of Object.entries(opts.dispatch ?? {})) {
|
|
956
|
+
const tool2 = byName.get(name);
|
|
957
|
+
if (!tool2) throw new Error(`applyConfirmationPolicies: no tool named '${name}' in the manifest (dispatch)`);
|
|
958
|
+
tool2.dispatch = block;
|
|
959
|
+
if (!touched.includes(name)) touched.push(name);
|
|
960
|
+
}
|
|
961
|
+
const stripLegacy = opts.stripLegacyFlag ?? true;
|
|
962
|
+
const dropConfirm = opts.dropConfirmParam ?? true;
|
|
963
|
+
for (const tool2 of tools) {
|
|
964
|
+
if (stripLegacy) delete tool2.confirmation_required;
|
|
965
|
+
if (dropConfirm) {
|
|
966
|
+
const schema = tool2.input_schema;
|
|
967
|
+
if (schema?.properties && "confirm" in schema.properties) delete schema.properties.confirm;
|
|
968
|
+
if (schema?.required?.includes("confirm")) {
|
|
969
|
+
schema.required = schema.required.filter((k) => k !== "confirm");
|
|
970
|
+
if (schema.required.length === 0) delete schema.required;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return touched;
|
|
975
|
+
}
|
|
976
|
+
function manifestIsFresh(manifest, opts) {
|
|
977
|
+
const copy = JSON.parse(JSON.stringify(manifest));
|
|
978
|
+
applyConfirmationPolicies(copy, opts);
|
|
979
|
+
return JSON.stringify(copy) === JSON.stringify(manifest);
|
|
980
|
+
}
|
|
981
|
+
function serializeManifest(manifest) {
|
|
982
|
+
return `${JSON.stringify(manifest, null, 2)}
|
|
983
|
+
`;
|
|
984
|
+
}
|
|
942
985
|
export {
|
|
943
986
|
APPROVAL_GRANTED_KEY,
|
|
944
987
|
DEFAULT_EMIT_TIMEOUT_MS,
|
|
@@ -951,6 +994,7 @@ export {
|
|
|
951
994
|
actorKey,
|
|
952
995
|
actorTool,
|
|
953
996
|
appFileUrl,
|
|
997
|
+
applyConfirmationPolicies,
|
|
954
998
|
approvalHash,
|
|
955
999
|
archiveOfferRefusal,
|
|
956
1000
|
base64ToBytes,
|
|
@@ -978,6 +1022,7 @@ export {
|
|
|
978
1022
|
isNotConnectedError,
|
|
979
1023
|
isStagingHost,
|
|
980
1024
|
listAppFiles,
|
|
1025
|
+
manifestIsFresh,
|
|
981
1026
|
offerUndo,
|
|
982
1027
|
overlaySprigr,
|
|
983
1028
|
ownerFromActorKey,
|
|
@@ -995,6 +1040,7 @@ export {
|
|
|
995
1040
|
runUndoApply,
|
|
996
1041
|
safeCapture,
|
|
997
1042
|
seq,
|
|
1043
|
+
serializeManifest,
|
|
998
1044
|
set,
|
|
999
1045
|
tool,
|
|
1000
1046
|
undoEnvelope,
|